True Type Font to Image Font

BlitzMax Forums/BlitzMax Programming/True Type Font to Image Font

zoqfotpik(Posted 2013) [#1]
This program takes the name of a font at the specified path and spits out a .png of that font in the same directory you're running this program in.

Graphics 640, 480, 0
Local fontname$="8BITWONDER"  
Local pathstring$="C:/windows/fonts/"

Local NewFont:TImageFont = LoadImageFont(pathstring+fontname+".ttf", 18) ' The 18 here is the size 
'of the ttf that you want to use.  Play with that and the various globals 
'until you get a spritesheet to your liking.

Global ROWS:Int = 10  ' characteristics you want in finished bitmap
Global COLUMNS:Int = 7
Global CHARWIDTH:Int = 18
Global CHARHEIGHT:Int = 20
Global SCALEFACTOR:Int = 1

SetImageFont NewFont
SetScale SCALEFACTOR,SCALEFACTOR
fontstring$ = "1234567890!@..."

thischar:Int = 0
For i = 0 To ROWS
	For j = 0 To COLUMNS
		DrawText fontstring[thischar..thischar+1], j*CHARWIDTH,i*CHARHEIGHT
		thischar = thischar + 1
	Next
Next

tempimage:TImage = CreateImage((j+1)*18,(i+1)*20)
GrabImage(tempimage, 0,0)
temppixmap = GrabPixmap(0,0,(j+1)*18,(i+1)*20)
SavePixmapPNG temppixmap,fontname+".png"

Flip
WaitKey()
End



GfK(Posted 2013) [#2]
It's actually a little pointless - TTFs are internally converted to bitmap fonts anyway. Plus, using the above code will change the font to fixed width of 18 pixels, whereas just using a TTF the font characters are drawn at their true width and won't leave horrible spaces between narrow letters like i, l, etc. So in short, your code is taking a TTF, and making it worse.

That aside, you should try FONText or FontMachine - both of which do what the above does, plus they handle character width/spacing, and loads of font effects such as gradients, outlines and drop-shadows.

Oh, and out of the two, FontMachine is much more advanced and gives better results.


Polan(Posted 2013) [#3]
As GfK said, Bmax does ttf-to-bitmap conversion, you can access those images with TImageFont._glyphs
Example, that will draw all chars from font:
FontFun()


Function FontFun()
	Global gw%=768,gh%=512
	Graphics(gw,gh)
	Global chars%=65536,size%=15
	Global font:TImageFont = LoadImageFont("C:/windows/fonts/consola.ttf",size,SMOOTHFONT)
	SetBlend(ALPHABLEND) 'nice alpha blending!
	SetImageFont(font)
		For Local x% = 0 To chars-1 'force bmax to load glyphs for chars
			DrawText(chr(x),0,0)
		next
	While Not KeyHit(KEY_ESCAPE)
		Cls
			Local ofx%,ofy%=0
			if(MouseDown(1))
				chars :+ 1
				DrawText(chr(chars),0,0)
			endif
			For Local x% = 0 to len(font._glyphs)-1
				if(font._glyphs[x]) 'if glyph exists, draw it!
					Local img:TImage = font._glyphs[x].Pixels()
					if(img)
						if(ofx+img.width > gw)
							ofx = 0
							ofy :+ size+2
						endif
						DrawImage(img,ofx,ofy)
						ofx :+ img.width
					endif
				endif
			next
		Flip
	wend
EndFunction



jkrankie(Posted 2013) [#4]
Blitzmax does render them as images, but not in a very efficient way as i recall. Anyway, this'd be much more useful if it also spat out a file with texture coords for each of the characters.

Cheers
Charlie


zoqfotpik(Posted 2013) [#5]
The reason I made this is because I wanted a little more control on the display end over what the truetype functionality offers, things like slicing and stretching of letters as well as rainbow cycling, etc. Kerning isn't a problem since I use only monospace fonts. There are probably numerous other ways to do what I want but it only took an hour or so to write.

Maybe someone will get some use out of it.

jkrankie: The way my display function works is based on the dimensions of the text spritesheet, the dimensions of the characters and the same string you use to generate the sheet. From that it just derives the x and y position of the rectangle of the character it wants.

If you really wanted to maximize display speed you could have it memoize a list of recently used strings into pixmaps-- if it had already displayed a string it would just blit the pixmap rather than displaying individual characters.