Custom typeface (font)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
badidea
Posts: 2594
Joined: May 24, 2007 22:10
Location: The Netherlands

Custom typeface (font)

Post by badidea »

Just for fun I was trying to design a typeface. The plan is to convert the characters into 3d-objects, but in 2d this might also be useful.
Only "A...Z" and "0..9" created, "a..z" is more challenging.
Code:

Code: Select all

#include "fbgfx.bi"

const SW = 800, SH = 600 'screen size

'https://www.freebasic.net/forum/viewtopic.php?p=281975
'bresenham line + circle
sub thick_line_circle(x0 As Long, y0 As Long, x1 As Long, y1 As Long, _
	thickness as Long, _color as ULong, pImage as FB.Image ptr)
	'
	Dim As Long dx = Abs(x1 - x0), dy = Abs(y1 - y0)
	Dim As Long sx = IIf(x0 < x1, 1, -1)
	Dim As Long sy = IIf(y0 < y1, 1, -1)
	Dim As Long er = IIf(dx > dy, dx, -dy) \ 2, e2
	dim as Long radius
	radius = thickness \ 2
	if thickness <= 0 then exit sub
	if radius > 0 then
		Do
			circle pImage, (x0, y0), radius, _color,, , ,F
			If (x0 = x1) And (y0 = y1) Then Exit Do
			e2 = er
			If e2 > -dx Then Er -= dy : x0 += sx
			If e2 <  dy Then Er += dx : y0 += sy
		Loop
	else
		line(x0, y0)-(x1, y1), _color
	end if
End Sub

'-------------------------------------------------------------------------------

#define isz integer
#define i32 long
#define u32 ulong
#define f32 single
#define f64 double

'-------------------------------------------------------------------------------

function isDigitChar(charval as isz) as boolean
	if charval < asc("0") then return false
	if charval > asc("9") then return false
	return true
end function

function isLetterChar(charval as isz) as boolean
	if charval >= asc("A") and charval <= asc("Z") then return true
	if charval >= asc("a") and charval <= asc("z") then return true
	if charval >= asc("_") then return true
	return false
end function

'startPos: 0+
function getIntvalInstr(text as string, searchPos as isz) as isz
	dim as isz strLen = len(text)
	if searchPos < 0 then return -1 'not good
	if searchPos > strLen - 1 then return -2 'not good
	'search value start
	dim as isz startPos = -1
	for i as isz = searchPos to strLen - 1 
		if isDigitChar(text[i]) = true then startPos = i : exit for
	next
	if startPos = -1 then return -3 'not good
	'search for first non-value char
	dim as isz endPos = strLen
	for i as isz = startPos to strLen - 1 
		if isDigitChar(text[i]) = false then endPos = i : exit for
	next
	'print endPos, startPos, endPos - startPos
	return valint(mid(text, startPos + 1, endPos - startPos))
end function

'value as string, set searchPos for next call
'add -/+/. formats
function getValInstr(text as string, byref valStr as string, byref searchPos as isz) as isz
	dim as isz strLen = len(text)
	if searchPos < 0 then return -1 'not good
	if searchPos > strLen - 1 then return -1 'not good
	'search value start
	dim as isz startPos = -1
	for i as isz = searchPos to strLen - 1 
		if isDigitChar(text[i]) = true then startPos = i : exit for
	next
	if startPos = -1 then return -1 'not good
	'search for first non-value char
	dim as isz endPos = strLen
	for i as isz = startPos to strLen - 1 
		if isDigitChar(text[i]) = false then endPos = i : exit for
	next
	'print endPos, startPos, endPos - startPos
	valStr = mid(text, startPos + 1, endPos - startPos)
	searchPos = endPos
	return 0 'ok
end function

'-------------------------------------------------------------------------------

type config_file_type
	dim as string fileName = ""
	dim as string fileData(any)
	dim as isz lastLine = -1, lastCol = -1
	'dim as string labelStr
	'functions
	declare function loadFile(fileName_ as string) as isz
	declare sub printContents()
	declare function getIntValueForLabel(varLabel as string, byref retVal as i32) as isz
	declare function findLabel(varLabel as string) as isz
	declare function getIntValue(byref retVal as i32) as isz
end type

'read contents line by line into data buffer
function config_file_type.loadFile(fileName_ as string) as isz
	dim as i32 fileNum = freefile()
	dim as string text
	if open(fileName_ for input as #1) <> 0 then
		print "Error opening: " & fileName_
		return -1
	else
		fileName = fileName_
		while not eof(fileNum)
			line input #fileNum, text
			dim as isz ub = ubound(fileData)
			redim preserve fileData(ub + 1)
			fileData(ub + 1) = text
		wend
		close fileNum
	end if
	return 0 'ok
end function

sub config_file_type.printContents()
	for i as isz = 0 to ubound(fileData)
		print fileData(i)
	next
end sub

'todo: add negative numbers
'no white space alowed before label
'cal again for next line
'case sensitive !
function config_file_type.getIntValueForLabel(varLabel as string, byref retVal as i32) as isz
	lastLine += 1
	for i as isz = lastLine to ubound(fileData)
		dim as isz searchPos = instr(fileData(i), varLabel)
		if searchPos = 1 then 'at start of line
			'check next char is a non-letter
			if isLetterChar(asc(mid(fileData(i), 1 + len(varLabel), 1))) = false then
				'label found, get value
				retVal = getIntvalInstr(fileData(i), searchPos)
				lastLine = i 'for next search
				return 0 'ok
			end if
		end if
	next
	'lastLine = -1 'reset search
	return -1
end function

'find label, set row & col position
function config_file_type.findLabel(varLabel as string) as isz
	lastLine += 1
	for i as isz = lastLine to ubound(fileData)
		dim as isz searchPos = instr(fileData(i), varLabel)
		if searchPos = 1 then 'at start of line
			'check next char is a non-letter
			if isLetterChar(asc(mid(fileData(i), 1 + len(varLabel), 1))) = false then
				'label found, save line pos
				lastLine = i 'for next search
				'go to first non-letter and save col pos
				dim as integer col = 1 + len(varLabel)
				while isLetterChar(fileData(i)[col])
					col += 1
				wend
				lastCol = col
				return 0 'ok
			end if
		end if
	next
	'lastLine = 0 'reset search
	return -1
end function

'call after findLabel() or previous getIntValue()
function config_file_type.getIntValue(byref retVal as i32) as isz
	dim as string retStr
	if getValInstr(fileData(lastLine), retStr, lastCol) = 0 then
		retVal = valInt(retStr)
		return 0
	end if
	return -1 'not found
end function

'-------------------------------------------------------------------------------

type i32_xy
	dim as i32 x, y
end type

type segment_type 'line 
	dim as i32_xy p(0 to 1)
end type

type char_type
	dim as i32 charCode
	dim as i32_xy charSize
	dim as i32 numSegment
	dim as segment_type segment(any)
	declare sub printInfo()
	declare sub addSegment(segment_ as segment_type)
	declare sub draw_(x as i32, y as i32, scale as f64, c as u32)
end type

sub char_type.printInfo()
	print "charCode: " & charCode
	print "charSize: " & charSize.x & ", " & charSize.y
	print "numSegment: " & numSegment
	for i as isz = 0 to ubound(segment)
		with segment(i)
			print "line: " & .p(0).x & ", " & .p(0).y & " - " & .p(1).x & ", " & .p(1).y
		end with
	next
end sub

sub char_type.addSegment(segment_ as segment_type)
	dim as isz ub = ubound(segment)
	redim preserve segment(ub + 1)
	segment(ub + 1) = segment_
end sub

sub char_type.draw_(x as i32, y as i32, scale as f64, c as u32)
	for i as isz = 0 to ubound(segment)
		dim as isz x0 = segment(i).p(0).x * scale + x
		dim as isz y0 = segment(i).p(0).y * scale + y
		dim as isz x1 = segment(i).p(1).x * scale + x
		dim as isz y1 = segment(i).p(1).y * scale + y
		'line(x0, SH - y0)-(x1, SH - y1), c
		thick_line_circle(x0, SH - y0, x1, SH - y1, 6, c, 0)
	next
end sub

'-------------------------------------------------------------------------------

function readChar(cfgFile as config_file_type, tface as char_type) as isz
	if cfgFile.findLabel("charcode") <> 0 then return -1
	if cfgFile.getIntValue(tface.charCode) <> 0 then return -1
	if cfgFile.findLabel("charsize") <> 0 then return -1
	if cfgFile.getIntValue(tface.charSize.x) <> 0 then return -1
	if cfgFile.getIntValue(tface.charSize.y) <> 0 then return -1
	if cfgFile.findLabel("numline") <> 0 then return -1
	if cfgFile.getIntValue(tface.numSegment) <> 0 then return -1
	for i as isz = 0 to tface.numSegment - 1
		dim as segment_type segment
		if cfgFile.findLabel("line") <> 0 then return -1
		'read first point
		dim as i32 x0, y0, x1, y1
		if cfgFile.getIntValue(x0) <> 0 then return -1
		if cfgFile.getIntValue(y0) <> 0 then return -1
		'read next
		while true
			if cfgFile.getIntValue(x1) <> 0 then exit while
			if cfgFile.getIntValue(y1) <> 0 then exit while
			segment.p(0) = type(x0, y0)
			segment.p(1) = type(x1, y1)
			tface.addSegment(segment)
			x0 = x1
			y0 = y1
		wend
		'if cfgFile.getIntValue(segment.p(0).x) <> 0 then return -1
		'if cfgFile.getIntValue(segment.p(0).y) <> 0 then return -1
		'if cfgFile.getIntValue(segment.p(1).x) <> 0 then return -1
		'if cfgFile.getIntValue(segment.p(1).y) <> 0 then return -1
		'tface.addSegment(segment)
	next
	return 0 'ok
end function

'-------------------------------------------------------------------------------

'const N_CHAR = 2
const W_CHAR = 5, H_CHAR = 7

type tf_type 'type face
	dim as char_type char(any)
	dim as i32 charmap(0 to 255)
	dim as i32 numChar
	declare function init(cfgFile as config_file_type) as isz
	declare sub print_(x as i32, y as i32, text as string, scale as f64)
end type

function tf_type.init(cfgFile as config_file_type) as isz
	if cfgFile.findLabel("numchar") <> 0 then return -1
	if cfgFile.getIntValue(numChar) <> 0 then return -1
	redim char(numChar - 1)
	for i as isz = 0 to ubound(char)
		if readChar(cfgFile, char(i)) <> 0 then return -1
		char(i).printInfo()
		charmap(char(i).charCode) = i 'tf.charmap(asc("A")) = 0
	next
	return 0
end function

sub tf_type.print_(x as i32, y as i32, text as string, scale as f64)
	for i as isz = 0 to len(text) - 1
		dim as isz charIdx = charmap(text[i])
		char(charIdx).draw_(x + i * (W_CHAR + 1) * scale, y, scale, &hff00ff00)
	next
end sub

dim as config_file_type cfgFile
if cfgFile.loadFile("2dfont.cfg") <> 0 then _
	print "Error cfgFile.loadFile" : end
print "--------------------"
cfgFile.printContents()
print "--------------------"

dim as tf_type tf
if tf.init(cfgFile) <> 0 then _
	print "Error tf.init" : end
print "tf.numChar: "& tf.numChar

screenres SW, SH, 32
width SW\8, SH\16
tf.print_(50, 450, "ABCDEFGHI", 12)
tf.print_(50, 350, "JKLMNOPQR", 12)
tf.print_(50, 250, "STUVWXYZ0", 12)
tf.print_(50, 150, "123456789", 12)

'for i as isz = 0 to ubound(tf.char)
	'print i
	'tf.char(i).draw_(50+i*50, 50, 10, &hff00ff00)
	'tf.char(i).printInfo()
'next

getkey()

'TODO
'~ Font editor
'~ Strip spaces
'~ Rendering
'~ Conversion to triangles + line thickness
Which needs this saved as "2dfont.cfg":

Code: Select all

numchar: 36

----------------------------------------

charcode: 65 'A
charsize: 5,7
numline: 2
line: 0,3-4,3
line: 0,0-0,4-2,6-4,4-4,0

charcode: 66 'B
charsize: 5,7
numline: 2
line: 0,0-0,6-3,6-4,5-4,4-3,3-0,3
line: 3,3-4,2-4,1-3,0-0,0

charcode: 67 'C
charsize: 5,7
numline: 1
line: 4,1-3,0-1,0-0,1-0,5-1,6-3,6-4,5

charcode: 68 'D
charsize: 5,7
numline: 1
line: 0,0-3,0-4,1-4,5-3,6-0,6-0,0

charcode: 69 'E
charsize: 5,7
numline: 2
line: 4,0-0,0-0,6-4,6
line: 0,3-3,3

charcode: 70 'F
charsize: 5,7
numline: 2
line: 0,0-0,6-4,6
line: 0,3-3,3

charcode: 71 'G
charsize: 5,7
numline: 1
line: 2,3-4,3-4,1-3,0-1,0-0,1-0,5-1,6-3,6-4-5

charcode: 72 'H
charsize: 5,7
numline: 3
line: 0,3-4,3
line: 0,0-0,6
line: 4,0-4-6

charcode: 73 'I
charsize: 5,7
numline: 3
line: 0,0-4,0
line: 0,6-4,6
line: 2,0-2,6

charcode: 74 'J
charsize: 5,7
numline: 1
line: 0,1-1,0-3,0-4,1-4,6-0,6

charcode: 75 'K
charsize: 5,7
numline: 3
line: 0,0-0,6
line: 0,3-1,3-4,6
line: 1,3-4,0

charcode: 76 'L
charsize: 5,7
numline: 1
line: 0,6-0,0-4,0

charcode: 77 'M
charsize: 5,7
numline: 1
line: 0,0-0,6-2,4-4,6-4,0

charcode: 78 'N
charsize: 5,7
numline: 2
line: 0,0-0,6-4,2
line: 4,0-4,6

charcode: 79 'O
charsize: 5,7
numline: 1
line: 0,1-0,5-1,6-3,6-4,5-4,1-3,0-1,0-0,1

charcode: 80 'P
charsize: 5,7
numline: 1
line: 0,0-0,6-3,6-4,5-4,4-3,3-0,3

charcode: 81 'Q
charsize: 5,7
numline: 2
line: 0,1-0,5-1,6-3,6-4,5-4,2-2,0-1,0-0,1
line: 2,2-4,0

charcode: 82 'R
charsize: 5,7
numline: 2
line: 0,0-0,6-3,6-4,5-4,4-3,3-0,3
line: 3,3-4,2-4,0

charcode: 83 'S
charsize: 5,7
numline: 1
line: 0,1-1,0-3,0-4,1-4,2-3,3-1,3-0,4-0,5-1,6-3,6-4,5

charcode: 84 'T
charsize: 5,7
numline: 2
line: 0,6-4,6
line: 2,0-2,6

charcode: 85 'U
charsize: 5,7
numline: 1
line: 0,6-0,1-1,0-3,0-4,1-4,6

charcode: 86 'V
charsize: 5,7
numline: 1
line: 0,6-0,2-2,0-4,2-4,6

charcode: 87 'W
charsize: 5,7
numline: 2
line: 0,6-0,1-1,0-2,1-3,0-4,1-4,6
line: 2,1-2,3

charcode: 88 'X
charsize: 5,7
numline: 2
line: 0,6-0,5-4,1-4,0
line: 0,0-0,1-4,5-4,6

charcode: 89 'Y
charsize: 5,7
numline: 2
line: 0,6-0,4-2,2-4,4-4-6
line: 2,2-2,0

charcode: 90 'Z
charsize: 5,7
numline: 1
line: 0,6-4,6-4,5-0,1-0,0-4,0

----------------------------------------

charcode: 48 '0
charsize: 5,7
numline: 2
line: 0,1-0,5-1,6-3,6-4,5-4,1-3,0-1,0-0,1
line: 0,1-4,5

charcode: 49 '1
charsize: 5,7
numline: 2
line: 0,4-2,6-2,0
line: 0,0-4,0

charcode: 50 '2
charsize: 5,7
numline: 1
line: 0,5-1,6-3,6-4,5-4,4-0,0-4,0

charcode: 51 '3
charsize: 5,7
numline: 2
line: 0,5-1,6-3,6-4,5-4,4-3,3-4,2-4,1-3,0-1,0-0,1
line: 1,3-3,3

charcode: 52 '4
charsize: 5,7
numline: 2
line: 0,6-0,3-4,3
line: 3,0-3,6

charcode: 53 '5
charsize: 5,7
numline: 1
line: 0,1-1,0-3,0-4,1-4,3-3,4-0,4-0,6-4,6

charcode: 54 '6
charsize: 5,7
numline: 1
line: 4,5-3,6-1,6-0,5-0,1-1,0-3,0-4,1-4,3-3,4-1,4-0,3

charcode: 55 '7
charsize: 5,7
numline: 1
line: 0,6-4,6-4,5-0,1-0,0

charcode: 56 '8
charsize: 5,7
numline: 1
line: 3,3-4,4-4,5-3,6-1,6-0,5-0,4-1,3-3,3-4,2-4,1-3,0-1,0-0,1-0,2-1,3

charcode: 57 '9
charsize: 5,7
numline: 1
line: 0,1-1,0-3,0-4,1-4,5-3,6-1,6-0,5-0,3-1,2-3,2-4,3
dodicat
Posts: 7986
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Custom typeface (font)

Post by dodicat »

Nice fonts Badidea.
Many years ago I painfully made up the keyboard characters ,British, including chr(163) the £ sign.
I don't know how £ will show over there!.

Code: Select all


Namespace show
Sub rotate(Byval pivot_x As Double,_   'turns about this point
    Byval pivot_y As Double,_
    Byval first_x As Double,_    'centre for circles
    Byval first_y As Double,_
    Byval second_x As Double, _   'radius for circles
    Byval second_y As Double, _   'aspect
    Byval arc_1 As Double,_       'arcs only for circle, 0 for lines
    Byval arc_2 As Double,_
    Byval angle As Double, _      
    Byval Scale As Double,_
    Byval colour As Ulong,_
    Byval th As Double,_           'thickness
    Byref shape As String,_
    image As Any Pointer=0)
    'rotated line is  (np(1),np(2))-(np(3),np(4))
    'rotated circle centre is np(3),np(4)
    'arcs from horizontal positive x axis in DEGREES
    'arc1<arc2 always e.g from 330 to 430
    shape=Lcase(shape) 
    Const prime=Rgb(255,255,255)
    Const p As Double = 4*Atn(1)  '(pi)
    Dim radians As Double=(2*p/360)*angle  'change from degrees to radians
    #define sx second_x
    angle=angle Mod 360
    #Macro thickline(t)
    Var h=Sqr(((np(1))-(np(3)))^2+((np(2))-(np(4)))^2)
    Var s=((np(4))-np(2))/h
    Var c=(np(1)-(np(3)))/h
    Line image, (np(3)+s*t/2,np(4)+c*t/2)-(np(1)+s*t/2,np(2)+c*t/2),prime
    Line image, (np(3)-s*t/2,np(4)-c*t/2)-(np(1)-s*t/2,np(2)-c*t/2),prime
    Line image, (np(3)+s*t/2,np(4)+c*t/2)-(np(3)-s*t/2,np(4)-c*t/2),prime
    Line image, (np(1)+s*t/2,np(2)+c*t/2)-(np(1)-s*t/2,np(2)-c*t/2),prime
    Paint image,((np(3)+np(1))/2, (np(4)+np(2))/2),prime,prime
    
    Line image, (np(3)+s*t/2,np(4)+c*t/2)-(np(1)+s*t/2,np(2)+c*t/2),colour
    Line image, (np(3)-s*t/2,np(4)-c*t/2)-(np(1)-s*t/2,np(2)-c*t/2),colour
    Line image, (np(3)+s*t/2,np(4)+c*t/2)-(np(3)-s*t/2,np(4)-c*t/2),colour
    Line image, (np(1)+s*t/2,np(2)+c*t/2)-(np(1)-s*t/2,np(2)-c*t/2),colour
    Paint image,((np(3)+np(1))/2, (np(4)+np(2))/2), colour, colour
    #EndMacro
    
    #macro thickcircle(t)
    Dim As Double xp1,xp2,yp1,yp2
    Dim arc1 As Double=arc_1*p/180
    Dim arc2 As Double=arc_2*p/180
    arc1=2*p+(arc1-(radians))
    arc2=2*p+(arc2-(radians))
    sx=sx*Scale
    If arc1=arc2 Then
        Circle image,(np(3),np(4)),sx+t/2,prime,,,second_y
        Circle image,(np(3),np(4)),sx-t/2,prime,,,second_y
        Paint image,(np(3),np(4)+sx),prime,prime
        Paint image,(np(3)+sx,np(4)),prime,prime
        Circle image,(np(3),np(4)),sx+t/2,colour,,,second_y
        Circle image,(np(3),np(4)),sx-t/2,colour,,,second_y
        Paint image,(np(3),np(4)+sx),colour,colour
        Paint image,(np(3)+sx,np(4)),colour,colour
    End If
    If arc1<>arc2 Then
        xp1=np(3)+(sx)*Cos(.5*(arc2+arc1))
        yp1=np(4)-(sx)*Sin(.5*(arc2+arc1))
        Circle image,(np(3),np(4)),sx+t/2,prime,arc1,arc2,second_y
        Circle image,(np(3),np(4)),sx-t/2,prime,arc1,arc2,second_y
        Line image,(np(3)+(sx+t/2)*Cos(arc1),np(4)-(sx+t/2)*Sin(arc1))-(np(3)+(sx-t/2)*Cos(arc1),np(4)-(sx-t/2)*Sin(arc1)),prime
        Line image,(np(3)+(sx+t/2)*Cos(arc2),np(4)-(sx+t/2)*Sin(arc2))-(np(3)+(sx-t/2)*Cos(arc2),np(4)-(sx-t/2)*Sin(arc2)),prime
        
        Paint image,(xp1,yp1),prime,prime
        
        Circle image,(np(3),np(4)),sx+t/2,colour,arc1,arc2,second_y
        Circle image,(np(3),np(4)),sx-t/2,colour,arc1,arc2,second_y
        Line image,(np(3)+(sx+t/2)*Cos(arc1),np(4)-(sx+t/2)*Sin(arc1))-(np(3)+(sx-t/2)*Cos(arc1),np(4)-(sx-t/2)*Sin(arc1)),colour
        Line image,(np(3)+(sx+t/2)*Cos(arc2),np(4)-(sx+t/2)*Sin(arc2))-(np(3)+(sx-t/2)*Cos(arc2),np(4)-(sx-t/2)*Sin(arc2)),colour
        
        Paint image,(xp1,yp1),colour,colour
        
    End If
    #endmacro
   
    Dim Turn(1 To 2,1 To 2) As Double={{Cos(radians),-Sin(radians)}, _
                                        {Sin(radians),Cos(radians)}}
    
    Var T1=Turn(1,1)*Scale*(first_x-pivot_x)+Turn(1,2)*Scale*(first_y-pivot_y) +pivot_x
    Var T2=Turn(2,1)*Scale*(first_x-pivot_x)+Turn(2,2)*Scale*(first_y-pivot_y) +pivot_y
    
    Var N1=Turn(1,1)*Scale*(second_x-first_x)+Turn(1,2)*Scale*(second_y-first_y) +first_x
    Var N2=Turn(2,1)*Scale*(second_x-first_x)+Turn(2,2)*Scale*(second_y-first_y) +first_y
    'translation
    Dim  np(1 To 4) As Double ={N1-(first_x-T1),N2-(first_y-T2),T1,T2} 
    
    Select Case shape
    Case "line"
        If th<2 Then
            Line image,(np(3),np(4))-(np(1),np(2)),colour 
        Else
            thickline(th)   
        End If
    Case "circle"
        Dim arc1 As Double=arc_1*p/180
        Dim arc2 As Double=arc_2*p/180
        If arc1=arc2 Then
            If th<=3 Then
                For n As Double=Scale*sx-1 To Scale*sx+1 Step .5
                    Circle image,(np(3),np(4)),n,colour,,,second_y       
                    'circle image,(np(3),np(4)),Scale*sx,colour,,,second_y
                Next n
            Else
                thickcircle(th)
            End If
            endif
            If arc1<>arc2 Then
                If th<=3 Then
                    arc1=2*p+(arc1-(radians))'new
                    arc2=2*p+(arc2-(radians))'new
                    For n As Double=Scale*sx-1 To Scale*sx+1 Step .5
                        Circle image,(np(3),np(4)),n,colour,arc1,arc2,second_y   
                        ' circle image,(np(3),np(4)),Scale*sx,colour,arc1,arc2,second_y
                    Next n
                Else
                    thickcircle(th)
                End If
            End If
            
        End Select 
    End Sub
    
    
    Sub text(x As Double,_
        y As Double,_
        s As String,_
        size As Double,_
        c As Ulong,_
        line_angle As Double=0,_
        char_angle As Double=0,_
        thickness_tweak As Double=1,_
        image As Any Pointer=0)
        
        Dim As Double next_x,next_y
        Dim l As Integer=Len(s)
        Dim px As Double=16*size+x
        y=y+16*size
        Dim py As Double=y'16*size+y
        Dim z As Integer=0
        Dim th As Double'=4
        th=((.5-size)/4.5+5)*thickness_tweak
        Dim sp As Double=6
        Dim sp2 As Double=6
        Const pi As Double=4*Atn(1)
        Dim la As Double=(line_angle *.5) 
        Dim ca As Double=(char_angle*.5) 
        sp2=sp2+30*Abs(Sin(ca*pi/180-la*pi/180))
        
        #macro set(x1,y1,x2,y2,sarc,earc,shape,im)
        rotate(px,py,x1,y1,x2,y2,sarc,earc,-char_angle,size,c,th*size,shape,im)
        #endmacro
        
        #macro spaces(xpixels,ypixels)
        px=px+(xpixels*size+sp2*size)*Cos(line_angle*pi/180)
        py=py-(ypixels*size+sp2*size)*Sin(line_angle*pi/180)
        next_x=px-16*size
        next_y=py-16*size
        #endmacro
        
        For n As Integer=1 To l
            
            Select Case Mid(s,n,1)
            Case " "
                spaces(30,30)
            Case "|"
                set(px-8,py-18,px-8,py+16,.0,.0,"line",image)'vert   
                spaces(12,12)  
            Case Chr(10)
                z=z+1
                px=(x+16*size+z*16*Sin(line_angle*pi/180))+1.3*z*(24*size+size*sp*size)*Sin(line_angle*pi/180)
                py=(y+z*16*Cos(line_angle*pi/180))+1.3*z*(24*size+size*sp*size)*Cos(line_angle*pi/180)
                next_x=px-16*size
                next_y=py-16*size
            Case "1"
                set(px-8,py-18,px-8,py+16,.0,.0,"line",image)'vert
                set(px-8,py-16,px-12,py-8,.0,.0,"line",image)
                spaces(12,12)
            Case "2"
                set(px-2,py-8,9,1,310,530,"circle",image)'curve
                set(px-15,py+14,px+5,py-2,.0,.0,"line",image)
                set(px-16,py+14,px+10,py+14,.0,.0,"line",image)'base
                spaces(28,28)
            Case "3"
                set(px-2,py-7,9,1,300,530,"circle",image)'curve top
                set(px-2,py+6,9,1,190,395,"circle",image)'curve
                set(px-3,py,px+5,py,.0,.0,"line",image)
                spaces(28,28)
            Case "4"
                set(px-16,py+4,px+12,py+4,.0,.0,"line",image)'horiz 
                set(px-14,py+4,px+4,py-16,.0,.0,"line",image)'slope
                set(px+4,py-18,px+4,py+16,.0,.0,"line",image)
                spaces(28,28)
            Case "5"
                set(px-14,py-16,px+6,py-16,.0,.0,"line",image)'top
                set(px-12,py-16,px-12,py+1,.0,.0,"line",image)'vert
                set(px-4,py+6,9,1,210,500,"circle",image)'curve
                spaces(28,28)
            Case "6"
                set(px-2,py+6,9,1,360,360,"circle",image)'curve base
                set(px+16,py+4,27,1,130,180,"circle",image)'curve edge
                spaces(28,28)
            Case "7"
                set(px-14,py-16,px+6,py-16,.0,.0,"line",image)'top
                set(px+5,py-16,px-12,py+16,.0,.0,"line",image)'slope
                spaces(26,26)
            Case "8"
                set(px-2,py-7,9,1,320,575,"circle",image)'curve top
                set(px-2,py+6,9,1,130,415,"circle",image)'curve
                set(px-9,py-1,px+6,py-1,.0,.0,"line",image)
                spaces(28,28)
                
            Case "9"
                set(px-2,py-6,9,1,360,360,"circle",image)'top 
                set(px-20,py-4,27,1,310,360,"circle",image)
                spaces(28,28)
            Case "0"
                set(px,py-1,15,1,360,360,"circle",image)
                spaces(36,36)
            Case "."
                set(px-12,py+12,1,1,360,360,"circle",image)
                spaces(10,10)
            Case "A"
                set(px,py-16,px-12,py+16,.0,.0,"line",image)
                set(px,py-16,px+12,py+16,.0,.0,"line",image)
                set(px-8,py+3,px+8,py+3,.0,.0,"line",image)
                spaces(30,30)'36
            Case "a"
                set(px-4,py+4,10,1,360,360,"circle",image)
                set(px+6,py-8,px+6,py+16,.0,.0,"line",image)
                spaces(26,26)
            Case "B"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px-12,py-14,px-5,py-14,.0,.0,"line",image)'top
                set(px-12,py+14,px-5,py+14,.0,.0,"line",image)'base
                set(px-5,py-6,8,1,290,450,"circle",image)'top loop
                set(px-5,py+6,8,1,270,430,"circle",image)'base loop
                set(px-12,py,px-2,py,.0,.0,"line",image)'middle
                spaces(24,24)
            Case "b"
                set(px-2,py+4,10,1,360,360,"circle",image)
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)
                spaces(28,28)
            Case "C"
                set(px,py,14,1,60,300,"circle",image)
                spaces(25,25)
            Case "c"
                set(px-4,py+4,10,1,60,300,"circle",image)
                spaces(20,20)
            Case "D"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)
                set(px-5,py,14,1,270,450,"circle",image)
                set(px-12,py-14,px-5,py-14,.0,.0,"line",image)
                set(px-12,py+14,px-5,py+14,.0,.0,"line",image)
                
                'rotate(px,py,px-24,py+20,px-24,py-20,0,0,-line_angle,1,size,rgb(255,0,0),1,"line",image)
                spaces(30,30)
            Case "d"
                set(px-4,py+4,10,1,360,360,"circle",image)
                set(px+6,py-16,px+6,py+16,.0,.0,"line",image)
                spaces(26,26)
            Case "E"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px-12,py-14,px+6,py-14,.0,.0,"line",image)'top
                set(px-12,py+14,px+6,py+14,.0,.0,"line",image)'base
                set(px-12,py,px-2,py,.0,.0,"line",image)'middle
                spaces(25,25)
            Case "e"
                set(px-4,py+4,10,1,0,320,"circle",image)
                set(px-12,py+3,px+8,py+3,.0,.0,"line",image)
                spaces(26,26)
            Case "F"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px-12,py-14,px+6,py-14,.0,.0,"line",image)'top
                set(px-12,py,px-2,py,.0,.0,"line",image)'middle
                spaces(24,24)
            Case "f"
                set(px-2,py-8,10,1,0,170,"circle",image)'curve
                set(px-12,py-10,px-12,py+16,.0,.0,"line",image)'vert
                set(px-10,py,px-2,py,.0,.0,"line",image)'middle
                spaces(28,28) 
            Case "G"
                set(px,py,14,1,50,350,"circle",image)
                set(px,py,px+16,py,.0,.0,"line",image)
                spaces(35,35)
            Case "g"
                set(px-4,py+4,10,1,360,360,"circle",image)
                set(px+6,py-6,px+6,py+20,.0,.0,"line",image)
                set(px-4,py+17,10,1,230,345,"circle",image)
                
                spaces(26,26)
            Case "H"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px+12,py-16,px+12,py+16,.0,.0,"line",image)'vert
                set(px-12,py,px+12,py,.0,.0,"line",image)'middle
                spaces(32,32)
            Case "h"
                'set(px-6,py+4,10,1,0,150,"circle",image)
                set(px-4,py+2,8,1,0,170,"circle",image)'curve right
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)
                set(px+4,py,px+4,py+16,.0,.0,"line",image)
                spaces(25,25)
            Case "I"
                set(px,py+16,px,py-16,.0,.0,"line",image)'vert
                set(px-12,py+14,px+12,py+14,.0,.0,"line",image)
                set(px-12,py-14,px+12,py-14,.0,.0,"line",image)
                spaces(30,30)
            Case "i"
                set(px-12,py-6,px-12,py+16,.0,.0,"line",image)
                set(px-12,py-14,1,1,360,360,"circle",image)
                spaces(10,10)
            Case "J"
                'set(px-2,py+4,12,1,200,270,"circle",image)
                set(px-7,py+8,7,1,220,355,"circle",image)
                set(px,py-16,px,py+9,.0,.0,"line",image)'vert
                set(px-12,py-14,px+12,py-14,.0,.0,"line",image)'top
                spaces(30,30)
            Case "j"
                set(px,py-6,px,py+20,.0,.0,"line",image)
                set(px-7,py+20,7,1,220,360,"circle",image)
                set(px,py-14,1,1,360,360,"circle",image)
                spaces(22,22)
            Case "K"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px+6,py-16,px-12,py,.0,.0,"line",image)'upper
                set(px+6,py+16,px-6,py-3,.0,.0,"line",image)
                spaces(25,25)
            Case "k"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px+3,py-6,px-12,py,.0,.0,"line",image)'upper
                set(px,py+16,px-8,py-3,.0,.0,"line",image)'lower
                spaces(20,20)
            Case "L"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px-12,py+14,px+6,py+14,.0,.0,"line",image)'base
                spaces(25,25)
            Case "l"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                spaces(10,10)
            Case "M"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px+12,py-16,px+12,py+16,.0,.0,"line",image)'vert
                set(px-12,py-16,px,py,.0,.0,"line",image)'left arm
                set(px+12,py-16,px,py,.0,.0,"line",image)'right arm
                
                spaces(32,32)
            Case "m"
                set(px-6,py+2,6,1,0,170,"circle",image)'curve left
                set(px+6,py+2,6,1,0,170,"circle",image)'curve right
                set(px-12,py-5,px-12,py+16,.0,.0,"line",image)'vert left
                set(px+12,py,px+12,py+16,.0,.0,"line",image)'vert right
                set(px,py+16,px,py,.0,.0,"line",image)'mid arm
                spaces(32,32)
            Case "N"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px+12,py-16,px+12,py+16,.0,.0,"line",image)'vert
                set(px-12,py-16,px+12,py+16,.0,.0,"line",image)'middle
                spaces(32,32)
            Case "n"
                set(px-4,py+2,8,1,0,170,"circle",image)'curve right
                set(px-12,py-5,px-12,py+16,.0,.0,"line",image)'vert left
                set(px+4,py+16,px+4,py,.0,.0,"line",image)'mid arm
                spaces(24,24)
            Case "O"
                set(px,py,14,1,360,360,"circle",image)
                spaces(36,36)
            Case "o"
                set(px-4,py+4,10,1,360,360,"circle",image)
                'set(px+6,py-16,px+6,py+16,.0,.0,"line",image)
                spaces(26,26)
            Case "P"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px-12,py-14,px-5,py-14,.0,.0,"line",image)'top
                'set(px-12,py+14,px-5,py+14,.0,.0,"line",image)'base
                set(px-5,py-6,8,1,280,450,"circle",image)'top loop
                'set(px-5,py+6,10,1,270,430,"circle",image)'base loop
                set(px-12,py+2,px-2,py+2,.0,.0,"line",image)'middle
                spaces(24,24)
            Case "p"
                set(px-5,py+4,10,1,270,435,"circle",image)' loop
                set(px-14,py-5,px-2,py-5,.0,.0,"line",image)'top
                set(px-12,py+14,px-5,py+14,.0,.0,"line",image)'base
                set(px-12,py-6,px-12,py+26,.0,.0,"line",image)'vert
                spaces(24,24) 
            Case "Q"
                set(px,py,14,1,360,360,"circle",image)
                set(px+5,py+20,16,1,400,460,"circle",image)
                spaces(36,36)
            Case "q"
                set(px-5,py+6,10,1,110,270,"circle",image)' loop
                set(px-9,py-3,px+2,py-3,.0,.0,"line",image)'top
                set(px-8,py+16,px,py+16,.0,.0,"line",image)'base
                set(px,py-3,px,py+26,.0,.0,"line",image)'vert
                spaces(20,20)
            Case "R"
                set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
                set(px-12,py-14,px-5,py-14,.0,.0,"line",image)'top
                'set(px-12,py+14,px-5,py+14,.0,.0,"line",image)'base
                set(px-5,py-6,8,1,290,450,"circle",image)'top loop
                'set(px-5,py+6,10,1,270,430,"circle",image)'base loop
                set(px-12,py+2,px-2,py+2,.0,.0,"line",image)'middle
                set(px-8-1+3,py+1,px+12-8-1,py+16+1-2,.0,.0,"line",image)'slope
                spaces(24,24)
            Case "r"
                set(px-4,py+4,10,1,30,130,"circle",image)
                set(px-12,py-8,px-12,py+16,.0,.0,"line",image)
                spaces(24,24)
            Case "S"
                set(px-2,py-7,8,1,20,240,"circle",image)'curve top
                set(px-2,py+6,8,1,200,500,"circle",image)'curve
                'set(px-9,py-1,px+6,py-1,.0,.0,"line",image)
                spaces(26,26)
            Case "s"
                set(px-4,py+4,10,1,40,140,"circle",image)'top
                set(px-1,py-4,10,1,180,240,"circle",image)'topslant
                set(px-6,py+14,10,1,20,100,"circle",image)'baseslant
                set(px-4,py+4,10,1,220,325,"circle",image)'base
                'set(px-12,py-4,px+2,py+12,.0,.0,"line",image)
                'set(px+6,py-8,px+6,py+16,.0,.0,"line",image)
                spaces(26,26)
            Case "T"
                set(px,py-12,px,py+16,.0,.0,"line",image)'vert
                set(px-16,py-12,px+16,py-12,.0,.0,"line",image)
                spaces(34,34)
            Case "t"
                set(px-12,py-16,px-12,py+10,.0,.0,"line",image)'edge
                set(px-12,py-4,px-2,py-4,.0,.0,"line",image)
                set(px-4,py+4,10,1,210,320,"circle",image)
                spaces (24,24)
            Case "U"
                set(px-12,py-16,px-12,py+8,.0,.0,"line",image)'vert
                set(px+12,py-16,px+12,py+8,.0,.0,"line",image)'vert
                set(px,py,14,1,205,335,"circle",image)
                'set(px-12,py,px+12,py,.0,.0,"line",image)'middle
                spaces(33,33)
            Case "u"
                set(px-4,py+4,10,1,210,360,"circle",image)
                set(px+6,py-6,px+6,py+16,.0,.0,"line",image)
                set(px-12,py-6,px-12,py+10,.0,.0,"line",image)'left edge
                spaces(26,26)
            Case "V"
                set(px,py+16,px-12,py-16,.0,.0,"line",image)
                set(px,py+16,px+12,py-16,.0,.0,"line",image)
                'set(px-8,py+3,px+8,py+3,.0,.0,"line",image)
                spaces(32,32)'36
            Case "v"
                set(px-12,py-6,px-4,py+16,.0,.0,"line",image)'left 
                set(px-4,py+16,px+4,py-6,.0,.0,"line",image)
                spaces(24,24) 
            Case "W"
                set(px-12,py-16,px-8,py+16,.0,.0,"line",image)'vert left
                set(px+12,py-16,px+8,py+16,.0,.0,"line",image)'vert
                set(px-8,py+16,px,py,.0,.0,"line",image)'left arm
                set(px+8,py+16,px,py,.0,.0,"line",image)'right arm
                spaces(32,32)
            Case "w"
                set(px-14,py-6,px-8,py+16,.0,.0,"line",image)'vert left
                set(px+8,py+16,px+12,py-6,.0,.0,"line",image)'vert right
                set(px-8,py+16,px,py,.0,.0,"line",image)'left arm
                set(px+8,py+16,px,py,.0,.0,"line",image)'right arm
                spaces(33,33)
            Case "X"
                set(px-12,py-16,px+12,py+16,.0,.0,"line",image)
                set(px+12,py-16,px-12,py+16,.0,.0,"line",image)
                spaces(32,32)
            Case "x"
                set(px-12,py-6,px+2,py+16,.0,.0,"line",image)
                set(px+2,py-6,px-12,py+16,.0,.0,"line",image)
                spaces(22,22)
            Case "Y"
                set(px-12,py-16,px,py,.0,.0,"line",image)
                set(px+12,py-16,px,py,.0,.0,"line",image)
                set(px,py,px,py+16,.0,.0,"line",image)
                spaces(32,32)
            Case "y"
                set(px-4,py+4,8,1,180,380,"circle",image)'top
                set(px+4,py-6,px+4,py+20,.0,.0,"line",image)'right
                set(px-6,py+17,10,1,230,345,"circle",image)'base
                set(px-12,py-6,px-12,py+4,.0,.0,"line",image)'left
                spaces(24,24)
            Case "Z"
                set(px-12,py-14,px+12,py-14,.0,.0,"line",image)'top
                set(px-12,py+14,px+12,py+14,.0,.0,"line",image)
                set(px+10,py-14,px-10,py+14,.0,.0,"line",image)'slope
                spaces(30,30)
            Case "z"
                set(px-16,py-4,px+2,py-4,.0,.0,"line",image)'top
                set(px-16,py+14,px+2,py+14,.0,.0,"line",image)'base
                set(px+1,py-5,px-14,py+14,.0,.0,"line",image)'slope
                spaces(20,20)
                
                '************************************************ 		
            Case ","
                set(px-12,py+12,px-18,py+20,.0,.0,"line",image)
                set(px-12,py+12,1,1,360,360,"circle",image)
                spaces(10,10)
                
                Case"£"
                set(px-5,py-5,8,1,40,220,"circle",image)'top
                set(px-19-5-5,py+10-5,18,1,320,390,"circle",image)
                set(px-16,py+16,px+8,py+16,.0,.0,"line",image)'base
                set(px-16,py+2,px,py+2,.0,.0,"line",image)
                spaces(28,28)
            Case "$"
                set(px-2,py-7,8,1,20,240,"circle",image)'curve top
                set(px-2,py+6,8,1,200,495,"circle",image)'curve
                set(px-2,py-17,px-2,py+17,.0,.0,"line",image)
                'set(px-9,py-1,px+6,py-1,.0,.0,"line",image)
                spaces(26,26)
            Case "%"
                set(px-10,py-10,6,1,360,360,"circle",image)
                set(px+10,py+10,6,1,360,360,"circle",image)
                set(px+8,py-8,px-8,py+8,.0,.0,"line",image)
                spaces(33,33)
            Case "^"
                set(px-14,py,px-7,py-16,.0,.0,"line",image)
                set(px-7,py-16,px,py,.0,.0,"line",image)
                spaces(20,20)
                Case"&"
                set(px-2,py-7,8,1,70,220,"circle",image)'curve top
                set(px-2,py+6,8,1,110,415,"circle",image)'curve
                set(px-4-4-2,py-8,px+12-4,py+16,.0,.0,"line",image)
                'set(px-9,py-1,px+6,py-1,.0,.0,"line",image)
                spaces(28,28)
            Case "*"
                set(px-12,py-6-8,px+2,py+16-8,.0,.0,"line",image)
                set(px+2,py-6-8,px-12,py+16-8,.0,.0,"line",image)
                set(px-16,py-3,px+6,py-3,.0,.0,"line",image)
                spaces(24,24)
            Case "("
                set(px+22,py,38,1,150,210,"circle",image)
                spaces(12,12)
            Case ")"
                set(px-22-16-6,py,38,1,330,390,"circle",image)
                spaces(12,12)
            Case "-"
                set(px-16,py,px+8,py,.0,.0,"line",image)
                spaces(26,26)
            Case "_"
                set(px-16,py+16,px+16,py+16,.0,.0,"line",image)
                spaces(34,34)
            Case "+"
                set(px-16,py,px+8,py,.0,.0,"line",image)
                set(px-4,py+12,px-4,py-12,.0,.0,"line",image)
                spaces(26,26)
            Case "="
                set(px-16,py-4,px+8,py-4,.0,.0,"line",image)
                set(px-16,py+4,px+8,py+4,.0,.0,"line",image)
                spaces(26,26)
            Case "!"
                set(px-12,py-16,px-12,py+6,.0,.0,"line",image)
                set(px-12,py+12,1,1,360,360,"circle",image)
                spaces(10,10)
            Case "¬"
                set(px-16,py+4,px+8,py+4,.0,.0,"line",image)
                set(px+6,py+4,px+6,py+12,.0,.0,"line",image)
                spaces(26,26)
            Case "`"
                set(px-16,py-16,px-12,py-12,.0,.0,"line",image)
                spaces(8,8)
            Case ";"
                set(px-12,py-4,1,1,360,360,"circle",image)'top
                set(px-12,py+12,px-18,py+20,.0,.0,"line",image)
                set(px-12,py+12,1,1,360,360,"circle",image)
                spaces(10,10) 
            Case ":"
            set(px-12,py-4,1,1,360,360,"circle",image)'top
            'set(px-12,py+12,px-18,py+20,.0,.0,"line",image)
            set(px-12,py+12,1,1,360,360,"circle",image)
            spaces(10,10)
        Case "@"
            set(px,py,14,1,0,290,"circle",image)
            set(px+6,py,7,1,100,365,"circle",image)
            spaces(36,36)
        Case "'"
            set(px-12,py-12,px-18,py-4,.0,.0,"line",image)
            set(px-12,py-12,1,1,360,360,"circle",image)
            spaces(10,10)
        Case "#"
            set(px-16,py-4,px+8,py-4,.0,.0,"line",image)
            set(px-16,py+4,px+8,py+4,.0,.0,"line",image)
            set(px-8,py-12,px-8,py+12,.0,.0,"line",image)
            set(px,py-12,px,py+12,.0,.0,"line",image)
            spaces(26,26)
        Case "~"
            set(px-8,py+16,14,1,60,120,"circle",image)
            set(px+4,py-8,14,1,240,300,"circle",image)
            spaces(30,30)
        Case "/"
            set(px+14,py-16,px-14,py+16,.0,.0,"line",image)
            spaces(34,34)
        Case "\"
            set(px-14,py-16,px+14,py+16,.0,.0,"line",image)
            spaces(34,34)
        Case "["
            set(px-12,py-16,px-12,py+16,.0,.0,"line",image)'vert
            set(px-12,py-14,px-4,py-14,.0,.0,"line",image)'top
            set(px-12,py+14,px-4,py+14,.0,.0,"line",image)
            spaces(14,14)
        Case "]"
            set(px-4,py-16,px-4,py+16,.0,.0,"line",image)'vert
            set(px-4,py-14,px-12,py-14,.0,.0,"line",image)'top
            set(px-12,py+14,px-4,py+14,.0,.0,"line",image)
            spaces(16,16)
        Case "{"
            set(px+12,py-8,28,1,160,200,"circle",image)
            set(px+12,py+8,28,1,160,200,"circle",image)
            spaces(8,8)
        Case "}"
            set(px-12-16-6,py-8,28,1,340,380,"circle",image)
            set(px-12-16-6,py+8,28,1,340,380,"circle",image)
            spaces(14,14)
        Case "<"
            set(px-16,py,px+4,py-12,.0,.0,"line",image)
            set(px-16,py,px+4,py+12,.0,.0,"line",image)
            spaces(24,24)
        Case ">"
            set(px+4,py,px-16,py-12,.0,.0,"line",image)
            set(px+4,py,px-16,py+12,.0,.0,"line",image)
            spaces(24,24)
        Case "?"
            set(px-5,py-6,8,1,280,490,"circle",image)'top loop
            set(px-4,py,px-4,py+8,.0,.0,"line",image)
            set(px-4,py+15,1,1,360,360,"circle",image)
            spaces(24,24)
        Case """"
            set(px-12,py-16,px-18,py-8,.0,.0,"line",image)
            set(px-12,py-16,1,1,360,360,"circle",image)
            
            set(px-4,py-16,px-10,py-8,.0,.0,"line",image)
            set(px-4,py-16,1,1,360,360,"circle",image)
            spaces(16,16)  
        Case Else
            Draw String(px,py),"?",c
            spaces(24,24)
        End Select
    Next n
End Sub
End Namespace 'show
'************************* END OF FONTS ******************************

Function framecounter As Long Static
    Dim As Long c,framerate
    Dim As Double t
    c += 1
	If Timer - t > 1 Then
		framerate = c
		c = 0
		t = Timer
	End If
    Return framerate
End Function

Const SW = 1024, SH = 768 
Screenres SW,SH
Dim As String x
Dim As Long C
For n As Long=33 To 126
    C+=1
    x+=Chr(n)
    If C Mod 13=0 Then x+=Chr(10)
Next
dim as single a
Do
    a+=.5
    Screenlock
    Cls
show.text(20,20,x,1,7)
show.text(720,250,!"turning\nspace",1.5,6,a,a)
show.text(10,460,!"framerate\n" & framecounter,2,3)
show.text(0,660,"The British pound sign: "+chr(163),1,2)
Screenunlock
Sleep 1,1
Loop Until Len(Inkey)

Sleep
 
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: Custom typeface (font)

Post by neil »

Really nice fonts, badidea and dodicat.
A while ago, I tried a custom large font test using only one letter.
This was using the line function. Your fonts are so much nicer.

Code: Select all

' custom large font test by neil

ScreenRes 800, 600, 32
Dim As Integer x, y, i, j, sz, num

sz = 7 ' size of large font

Dim As String font(sz) ' custom font data

font(0) = "  ##  "
font(1) = " #  # "
font(2) = "#    #"
font(3) = "######"
font(4) = "#    #"
font(5) = "#    #"
font(6) = "#    #"

x = 10
y = 10

for num = 1 to 8

For i = 0 To 6
  For j = 1 To Len(font(i))
     If Mid(font(i), j, 1) = "#" Then
       Line (x + j * sz, y + i * sz)-Step(sz, sz), RGB(0, 255, 0), BF
     End If
    Next
Next
sz += 1
x = x + 86
Next
Sleep
badidea
Posts: 2594
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Custom typeface (font)

Post by badidea »

dodicat wrote: Apr 10, 2024 1:19 Many years ago I painfully made up the keyboard characters ,British, including chr(163) the £ sign.
I don't know how £ will show over there!.
Looks like a lot of work indeed. The £ only shows if set set the file encoding to e.g. ISO-8859-1 instead of UTF8.
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Custom typeface (font)

Post by marcov »

Fonts consisting only out of lines are called stroked fonts, and basically level zero of scalable (non bitmapped(*)) fonts. Turbo Pascal had stroked fonts file (.chr) and the format is available on the net.

IIRC Freetype has a function to make stroked fonts for opengl consumption from TTFs, so you might avoiding doing that all by hand, and with more modern stuff than Turbo Pascal.

(*) well, signed distance fields made bitmapped fields also scalable
badidea
Posts: 2594
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Custom typeface (font)

Post by badidea »

Thanks, I will look into that. Sometimes you have to try the ugly work yourself to better appreciate what others have already done, I guess.
Gunslinger
Posts: 106
Joined: Mar 08, 2016 19:10
Location: The Netherlands

Re: Custom typeface (font)

Post by Gunslinger »

Checkout Sebastian Lague on youtube
https://www.youtube.com/watch?v=SO83KQuuZvg
He going mad with the truetype font in 3D, very interesting to watch him struggle with al little bugs.
Roland Chastain
Posts: 1007
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Re: Custom typeface (font)

Post by Roland Chastain »

Hello everybody! Maybe you could be interested in SMFONTS. It's a collection of fonts in Pascal. I imagine it would be easy to adapt them for FreeBASIC.
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: Custom typeface (font)

Post by neil »

Here are a couple of Cairo fonts.

Code: Select all

#include once "cairo/cairo.bi"

const W as integer = 1024
const H as integer = 768

screenres W, H, 32
dim as any ptr image = imagecreate(W, H)
dim as any ptr pixels

imageinfo(image, W, H,,, pixels)

dim as long stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, W)
dim as cairo_surface_t ptr cs = cairo_image_surface_create_for_data(pixels, CAIRO_FORMAT_ARGB32, W, H, stride)
dim as cairo_t ptr cr = cairo_create(cs)

cairo_set_source_rgb(cr, 0.0, 0.0, 0.0)
cairo_paint(cr)

cairo_set_source_rgb(cr, 0.0, 1.0, 0.0)

cairo_select_font_face (cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL)
cairo_set_font_size (cr, 44.0)
cairo_move_to(cr, 15.0, 100)
cairo_show_text(cr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
cairo_move_to(cr, 15.0, 150)
cairo_show_text(cr, "abcdefghijklmnopqrstuvwxyz")

cairo_select_font_face (cr, "courier", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL)
cairo_set_font_size (cr, 44.0)
cairo_move_to(cr, 15.0, 250)
cairo_show_text(cr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
cairo_move_to(cr, 15.0, 300)
cairo_show_text(cr, "abcdefghijklmnopqrstuvwxyz")

put (0, 0), image, pset

sleep

cairo_destroy(cr)
cairo_surface_destroy(cs)
imagedestroy image
Post Reply