Fontext for free - Merry Christmas blitzers

Miscellaneous Forums/Content Creation Tools/Fontext for free - Merry Christmas blitzers

Fontext is now free for all users. Thank you to all those that purchased it over the years. Enjoy.

What is Fontext?
Fontext is an application for creating great looking packed bitmap fonts for 2D & 3D games. It also comes with some excellent code libraries to use bitmap fonts in your games (Blitz3D & BlitzPlus - BlitzMax library in a post below).

The Blitz3D library has some extended features including:
Save Fontext text mesh
Create clickable GUI objects
Create curved text

Fontext application and codelibs:
http://www.mediafire.com/?24ng952x3dm

Plugin to create Fontext mesh directly in gile[s] (v1.36 only I think?):
http://www.mediafire.com/?5y31ol6zvbl

If you make any changes to the libraries that others might enjoy then please share them.

Wow thanks, very generous (shame I've got it already) ;-)

I'll be using this for my next game for sure.

That is very generous. A great application and library I have used for a couple of years now.

Thanks :)

Yep Fontext is good. Used it for a couple years now. Was pretty easy to get some basic Fontext functionality up and running in Blitzmax, too.

Awesome, thanks so much!

thanks,

.

Thanks, it's a great product I'vs ued til now :)

I have always wanted this! Beaker is d best!

Very generous. I thank you!

Many thanks,

IPete2.

Very generous, thank you, and have a great christmas! :)

Dabz

Many thanks Beaker and Happy Christamas to you too !

Free font tool? You b*****d!!!

j/k :)

Most generous, Beaks! ;)

Nice, thanks Beaker!

Many thanks!
Merry Christmas!

Its not just for blitz3d, i used it last week to make the fonts for my bmax game.

Thanks Beaker!

sa-weet!

Very nice! Thank you so much.

Just found this thread - much thanks to Beaker! Fontext is awesome, I'll be sure to use this.

I wonder which is better for rendering text in Blitz 3D, the Fontext library or the SwiftGUI library.

Purchased it years ago and enjoyed it very much.

Very generous of Beaker to let all Blitzers have it. :-)

Barney

The links end up at a dead page. Any Bmax source to use the fonts?

no they work. just tried em.

no they work. just tried em.


Even this one : http://www.tomspeed.com/fontext/ ?

Dead. At least the ones pointing to the BlitzMax framework to use the fonts is.

tomspeed.com has expired ;(

is it christmas in july or was the topic bumped?

Does anyone have these files still since all the links are dead?

Sorry for the delay. The files are now available again from the first post.

Does anyone have the BMax files? The link is dead.

The problem is that the one that was originally written used some low level stuff and no longer works in the current version of Bmax. I'm sure there are others out there.

I can post the old one if someone wants to have a go at updating it.

Beaker, I *think* it was pretty straightforward. Do you just mean the DX references in FontTextType.bmx? If so, I believe I have it working for DX.
Can I post it?

Of course.

OK, any problems let me know :
Strict
Framework BRL.Basic

?win32
Import BRL.D3D7Max2D
?
Import BRL.GLMax2D
Import BRL.Retro
Import BRL.TGALoader
Import BRL.PNGLoader


'Local DX_Driver = D3D7Max2DDriver()
'Local GL_Driver:TGLMax2DDriver = GLMax2DDriver()
SetGraphicsDriver GLMax2DDriver()
	
Graphics 1024,768,0

'Create a FonText Type
'The function will expect to find the accompanying .ini that was created when you
'made your bitmap font in FonText. It should reside in the same folder as the bitmap
Local myFT:FonText = FonText.Create("f.png", FILTEREDIMAGE)


Local rot# = 0
Local i:Int
Local cen:Byte = False
Local scale:Float = 1.0
Local time:Int
Local text:String
Local angle:Float = 0
Local lbToggle:Byte = False


text = "Justified Text!"+Chr(13)+Chr(13)
text:+ "This text is drawn using DrawJustified(), the text is automatically wrapped at a user "
text:+ "specified pixel width. Spaces are not drawn if they're at the beginning of a line, and words are "
text:+ "wrapped properly so they don't get split!"+Chr(13)+Chr(13)
text:+ "The line break width can be optionally scaled (press RETURN to see it in action)"+Chr(13)
text:+ "Also..."+Chr(13)
text:+ "Line breaks..."+Chr(13)
text:+ "Are..."+Chr(13)
text:+ "Supported!"


SeedRnd(MilliSecs())
While Not KeyHit(KEY_ESCAPE)
	Cls
	If 0

	For i=1 To 100
		SetColor Rand(50,100),Rand(50,100),Rand(50,100)
		DrawRect Rand(600),Rand(400),200,200
	Next
	SetColor 255,255,255
	End If
	
	SetRotation rot
	SetScale scale,scale
	
	If KeyHit(KEY_T) 'create an animated fontext routine
		Local mx=MouseX()
		Local my=MouseY()
		Local cr#=Cos(rot+90)
		Local cs#=Sin(rot+90)
		afonText.Create("Wouldn't it be nice...",					myFT, mx, my, 0,    2000, 4000, 2000, 2, 1,0)
		afonText.Create("To be able to automate..",				myFT, mx+cr*40, my+cs*40*scale, 1000, 2000, 3000, 2000, 2, 1,-1)
		afonText.Create("Text fading onto the screen..",	myFT, mx+cr*80, my+cs*80*scale, 2000, 2000, 2000, 2000, 2, 1,1)
		afonText.Create("?",																	myFT, mx+cr*150, my+cs*150*scale, 4000, 2000, 2000, 2000, 0, 1,0)
		afontext.Create("..Well now you can!",							myFT, mx+cr*200, my+cs*200*scale, 5000, 2000, 2000, 2000, 2, 1,0)
	End If
	
	SetRotation 0
	SetScale scale*.5,scale*.5
	myFT.DrawJustified(text,60,60,False,2,800,lbToggle)

	SetBlend ALPHABLEND
	SetScale scale,scale
	
	Local x#=MouseX()
	Local y#=MouseY()
	
	time = MilliSecs()
	
	SetRotation 0
	'SetScale 1,1
	myFT.Draw("FonText Rocks!",GraphicsWidth()/2,0,True,4)

	myFT.DrawVertical("Vertical Text",0,0,cen,-20)


	SetScale scale,scale
	SetRotation rot
	'myFT.DrawVertical("Draw Vertical",0,0,cen,-25) '* working
	myFT.DrawWave("Drawn with DrawWave()",x,y,angle,45,8,cen,8) '* working
	myFT.DrawWiggle("Drawn with DrawWiggle()",x,y+60,angle,45,8,cen,8) '* working
	myFT.DrawBouncy("Drawn with DrawBouncy()",x,y+120,angle,15,24,cen,6) '* working
	myFT.DrawWobble("Drawn with DrawWobble()",x,y+180,-angle,-45,10,cen,6) '* working
	myFT.DrawSineSize("Drawn with DrawSineSize()",x,y+240,-angle,-45,30,cen,6) '* working	
	myFT.DrawSwing("Drawn with DrawSwing()",x,y+300,-angle,5,20,cen,6) '* working

	aFonText.Update()
		
	time = MilliSecs() - time
	angle:- 5
	SetScale 1,1
	SetRotation 0
	
	If KeyHit(KEY_RETURN) lbToggle = Not lbToggle
	If KeyDown(KEY_LEFT) scale:- .01
	If KeyDown(KEY_RIGHT) scale:+ .01	
	If KeyHit(KEY_SPACE) cen=Not cen
	If MouseDown(1) rot:- 1
	If MouseDown(2) rot:+ 1
	
	SetScale .3,.3
	myFT.Draw("FonText draw time: "+time+"ms",0,728,False,2)
	myFT.Draw("LMB/RMB rotate, cursor LEFT/RIGHT adjust scale, SPACE toggle center, 't' for a special FX",0,748,False,2)
	'DrawText MemAlloced(),0,0
	Flip
Wend
EndGraphics()




Type FonText
	Field image:TImage
	Field blockHeight:Int
	Field char:Byte[255]	'Boolean for each ASCII character, True if the FonText includes it, False if not
	Field maskColor:Int
	Field packed:Int

	Field pX:Float[255]		'Position X
	Field pY:Float[255]		'Position Y
	Field cW:Int[255]			'Width

	Field sinL:Float[360]	'not used yet
	Field cosL:Float[360]	' ""

	Field iwM:Float			'Image width & height multipliers used in
	Field ihM:Float			'functions to optimise UV calculation speed
	
	Field u0:Float[255]
	Field v0:Float[255]
	
	Field u1:Float[255]
	Field v1:Float[255]
	
	Function Create:FonText(file:String,flags:Int = -1)
		Local img:TImage = LoadImage(file,flags)
		If Not img RuntimeError "Could not load Image "+file
		SetImageHandle(img,0,0)

		Local ini:TStream = OpenFile(Left$(file,file.length - 3)+"ini")
		If Not ini RuntimeError "Could not find "+Left$(file,file.length - 3)+"ini"

		Local f:FonText = New FonText
		f.image = img
		
		f.iwM = 1.0 / img.width
		f.ihM = 1.0 / img.height
	
		'Get BlockSize (height)
		Local r:String

		'Ignore first 3 lines
		ReadLine(ini)
		ReadLine(ini)
		ReadLine(ini)

		'Get MaskColor (needed?)
		r = ReadLine(ini)
		f.maskColor = Int(Right$(r,r.length-10))

		'Packed Font?
		r = ReadLine(ini)
		f.packed = Int(Right$(r,1))

		'Find [text] line
		r = ReadLine(ini)
		While r<>"[text]"
			r = ReadLine(ini)
		Wend

		'Block Height
		r = ReadLine(ini)
		f.blockHeight = Int(Right$(r,r.length - 10))

		'Count Characters
		r = ReadLine(ini)
		While r<>"[charset]"
			r = ReadLine(ini)
		Wend

		'Store this location
		Local location:Int = StreamPos(ini)

		'do the count
		Local count:Int = 0
		While Not Eof(ini)
			r = ReadLine(ini)
			count:+ 1
		Wend

		'Back to the Characters...
		SeekStream(ini,location)

		Local i:Int,j:Int,s:String,t:String
		Local cur:Byte

		'Parse each characters position & width
		For i = 0 Until count
			r = ReadLine(ini)
			cur = Asc(Left$(r,1))
			f.char[cur] = True

			'Position X
			j = 3
			s = ""
			t = Mid$(r,j,1)
			While t<>","
				s:+ t
				j:+1
				t = Mid$(r,j,1)
			Wend
			f.pX[cur] = Float(s)

			'Position Y
			j:+1
			s = ""
			t = Mid$(r,j,1)
			While t<>","
				s:+ t
				j:+1
				t = Mid$(r,j,1)
			Wend
			f.pY[cur] = Float(s)

			'Character Width
			j:+ 1
			s = ""
			t = Mid$(r,j,1)
			While t<>","
				s:+ t
				j:+1
				If j>r.length Exit
				t = Mid$(r,j,1)
			Wend
			f.cW[cur] = Int(s)

			'Adjust packing if the font isn't packed (trim space either side of character)
			If Not f.packed
				f.pX[cur]:+ (f.blockheight - f.cW[cur]) * .5
			End If
			
			f.u0[cur] = f.pX[cur] * f.iwM
			f.v0[cur] = f.pY[cur] * f.ihM
			f.u1[cur] = (f.pX[cur]+f.cW[cur]) * f.iwM
			f.v1[cur] = (f.pY[cur]+f.blockHeight) * f.ihM
		Next
		
		CloseStream ini
		Return f
	End Function
	
	Method DrawJustified(s:String, x:Float, y:Float, centered:Byte, spacing:Float, lineBreak:Float, scaleLB:Byte)
		Local i:Int,t:String

		Local scaleX#,scaleY#
		Local oX#,oY#
		Local rot#
		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#

		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		Local frame:Int = 0
		Local xDrawn:Float = 0
		
		GetOrigin oX,oY
		GetScale scaleX,scaleY
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot+90)
		cosP90 = Cos(rot+90)

		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe 	= TGLImageFrame(image.frame(frame))
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(image.frame(frame))
		End If
		
		If scaleLB Then lineBreak:* scaleX
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			x:- cosR * lineBreak * .5
			y:- sinR * lineBreak * .5
		End If

		Local newWord:Int = 0
		Local wordLen:Float
		Local tw:Int
		Local lastLen:Int = 0
		
		Local vSpacing = blockHeight * .8

		'Draw each letter in the string...
		For i = 0 Until s.length
			'Check for whole word, we don't want to break them up
			If lastLen <= 0 And s[i]<>32 And lineBreak>0
				lastLen = 0
				For newWord = i Until s.length
					lastLen:+ 1
					If s[newWord]=32 Or s[newWord]=13 Exit
				Next
				
				wordLen = 0
				'Was there a word?
				If newWord>0
					For tw = i Until newWord
						wordLen:+ (cW[s[tw]] + spacing)*scaleX
					Next
				End If
				
				'Check the length doesn't go over the lineBreak limit
				If xDrawn + wordLen > lineBreak
					'goto next line
				
					'move back to beginning
					x:- cosR * xDrawn
					y:- sinR * xDrawn

					'move down
					x:+ cosP90 * vSpacing * scaleX
					y:+ sinP90 * vSpacing * scaleY
					lastLen = 0
					xDrawn = 0
				End If
			End If
			
			
			'Space character?
			'blockHeight/3 *seems* to be an ok value for spaces
			If s[i] = 32' And xDrawn>2
				x:+ cosR * blockHeight*.3 * scaleX
				y:+ sinR * blockHeight*.3 * scaleY
				xDrawn:+ blockHeight*.3 * scaleX
			End If
			
			'Linebreak?
			If s[i] = 13

				'goto next line
				
				'move back to beginning
				x:- cosR * xDrawn
				y:- sinR * xDrawn
									
				'move down
				x:+ cosP90 * vSpacing * scaleX
				y:+ sinP90 * vSpacing * scaleY
				lastLen = 0
				xDrawn = 0
				
			End If

			'If our loaded bitmap font has this character...
			If char[s[i]]' And s[i]<>32
				curChar = s[i]

				lastLen:- 1

				areaW = cW[curChar]
				areaH = blockHeight

				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw 0, 0, areaW, areaH, x+oX, y+oY
					
				Else 'Same as above, but using DX variation
					DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw 0, 0, areaW, areaH, x+oX, y+oY
				End If
				
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ cosR * (cW[curChar]+spacing) * scaleX
				y:+ sinR * (cW[curChar]+spacing) * scaleY
				xDrawn:+ (cW[curChar]+spacing) * scaleX
			End If
		Next

				
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV (0,0,1,1)
		End If	
	End Method


	Method Draw(s:String, x:Float, y:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int,t:String

		Local scaleX#,scaleY#
		Local oX#,oY#				'Current Max2D Origin
		Local rot#						'Current Max2D Rotation
		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		Local frame:Int = 0
		
		GetOrigin oX,oY
		GetScale scaleX,scaleY
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot+90)
		cosP90 = Cos(rot+90)
		
	
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe 	= TGLImageFrame(image.frame(frame))
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(image.frame(frame))
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					ln:+ blockHeight*.3
				Else If char[s[i]]
					ln:+ cW[s[i]]+spacing
				End If
			Next
			ln:- spacing 'remove last unwanted space

			ln = ln*scaleX *.5
			x:- cosR*ln
			y:- sinR*ln
		End If
		
		Local spaceValX# = cosR * blockHeight * .3 * scaleX
		Local spaceValY# = sinR * blockHeight * .3 * scaleY
				
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				x:+ spaceValX
				y:+ spaceValY
			End If

			'If our loaded bitmap font has this character...
			If char[s[i]] And s[i]<>32
				curChar = s[i]

				areaW = cW[curChar]
				areaH = blockHeight

				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw 0, 0, areaW, areaH, x+oX, y+oY
					
				Else 'Same as above, but using DX variation
					DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw 0, 0, areaW, areaH, x+oX, y+oY
				End If
				
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ CosR * (cW[curChar]+spacing) * scaleX
				y:+ SinR * (cW[curChar]+spacing) * scaleY
			
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV (0,0,1,1)
		End If	
	End Method


	Method DrawWave(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
		Local i:Int,t:String

		Local scaleX#,scaleY#
		Local oX#,oY#				'Current Max2D Origin
		Local rot#						'Current Max2D Rotation
		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		Local frame:Int = 0
		
		GetOrigin oX,oY
		GetScale scaleX,scaleY
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot+90)
		cosP90 = Cos(rot+90)
		
	
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe 	= TGLImageFrame(image.frame(frame))
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(image.frame(frame))
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					ln:+ blockHeight*.3
				Else If char[s[i]]
					ln:+ cW[s[i]]+spacing
				End If
			Next
			ln:- spacing 'remove last unwanted space

			ln = ln*scaleX *.5
			x:- cosR*ln
			y:- sinR*ln
		End If
		
		Local spaceValX# = cosR * blockHeight * .3 * scaleX
		Local spaceValY# = sinR * blockHeight * .3 * scaleY
		
		Local bx#,by#,bMag#
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				x:+ spaceValX
				y:+ spaceValY
			End If

			'If our loaded bitmap font has this character...
			If char[s[i]] And s[i]<>32
				curChar = s[i]

				bMag = Sin(angle) * mag * scaleY
				bx = x - cosP90 * bMag
				by = y - sinP90 * bMag

				areaW = cW[curChar]
				areaH = blockHeight

				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
					
				Else 'Same as above, but using DX variation
					DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
				End If
				
				angle:+ angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ CosR * (cW[curChar]+spacing) * scaleX
				y:+ SinR * (cW[curChar]+spacing) * scaleY
			
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV (0,0,1,1)
		End If	
	End Method

	Method DrawWiggle(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
		Local i:Int,t:String

		Local scaleX#,scaleY#
		Local oX#,oY#				'Current Max2D Origin
		Local rot#						'Current Max2D Rotation
		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		Local frame:Int = 0
		
		GetOrigin oX,oY
		GetScale scaleX,scaleY
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot+90)
		cosP90 = Cos(rot+90)
		
	
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe 	= TGLImageFrame(image.frame(frame))
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(image.frame(frame))
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					ln:+ blockHeight*.3
				Else If char[s[i]]
					ln:+ cW[s[i]]+spacing
				End If
			Next
			ln:- spacing 'remove last unwanted space

			ln = ln*scaleX *.5
			x:- cosR*ln
			y:- sinR*ln
		End If
		
		Local spaceValX# = cosR * blockHeight * .3 * scaleX
		Local spaceValY# = sinR * blockHeight * .3 * scaleY
		
		Local bx#,by#,bMag#
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				x:+ spaceValX
				y:+ spaceValY
			End If

			'If our loaded bitmap font has this character...
			If char[s[i]] And s[i]<>32
				curChar = s[i]

				bMag = Sin(angle) * mag * scaleX
				bx = x - cosR * bMag
				by = y - sinR * bMag

				areaW = cW[curChar]
				areaH = blockHeight

				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
					
				Else 'Same as above, but using DX variation
					DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
				End If
				
				angle:+ angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ CosR * (cW[curChar]+spacing) * scaleX
				y:+ SinR * (cW[curChar]+spacing) * scaleY
			
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV (0,0,1,1)
		End If	
	End Method

	Method DrawBouncy(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
		Local i:Int,t:String

		Local scaleX#,scaleY#
		Local oX#,oY#				'Current Max2D Origin
		Local rot#						'Current Max2D Rotation
		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		Local frame:Int = 0
		
		GetOrigin oX,oY
		GetScale scaleX,scaleY
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot+90)
		cosP90 = Cos(rot+90)
		
	
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe 	= TGLImageFrame(image.frame(frame))
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(image.frame(frame))
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					ln:+ blockHeight*.3
				Else If char[s[i]]
					ln:+ cW[s[i]]+spacing
				End If
			Next
			ln:- spacing 'remove last unwanted space

			ln = ln*scaleX *.5
			x:- cosR*ln
			y:- sinR*ln
		End If
		
		Local spaceValX# = cosR * blockHeight * .3 * scaleX
		Local spaceValY# = sinR * blockHeight * .3 * scaleY
		
		Local bx#,by#,bMag#
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				x:+ spaceValX
				y:+ spaceValY
			End If

			'If our loaded bitmap font has this character...
			If char[s[i]] And s[i]<>32
				curChar = s[i]

				bMag = Abs(Sin(angle)) * mag * scaleY
				bx = x - cosP90 * bMag
				by = y - sinP90 * bMag

				areaW = cW[curChar]
				areaH = blockHeight

				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
					
				Else 'Same as above, but using DX variation
					DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
				End If
				
				angle:+ angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ CosR * (cW[curChar]+spacing) * scaleX
				y:+ SinR * (cW[curChar]+spacing) * scaleY
			
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV (0,0,1,1)
		End If	
	End Method


	Method DrawVertical(s:String, x:Float, y:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int,t:String
		Local scaleX#,scaleY#
		Local oX#,oY#				'Current Max2D Origin
		Local rot#						'Current Max2D Rotation
		
		'Look UPs
		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		Local frame:Int = 0
		
		GetOrigin oX,oY
		GetScale scaleX,scaleY
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90# = Sin(rot+90)
		cosP90# = Cos(rot+90)
		
		
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe 	= TGLImageFrame(image.frame(frame))
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(image.frame(frame))
		End If
		
		'Center the Vertical text so it appears
		'nicely centered
		
		'Find widest character
		Local bc:Float = 0
		For i = 0 Until s.length
			If cW[s[i]] > bc Then bc = cW[s[i]]
		Next

		'build an offset array based of widest char
		Local ofs:Float[255]
		For i = 0 Until s.length
			ofs[s[i]] = (bc - cW[s[i]]) * .5
		Next


			'ln = bc*scaleX *.5
		If centered
			x:- cosR*(bc*.5) * scaleX
			y:- sinR*(bc*.5) * scaleY
		End If

		Local spaceX# = cosP90 * (blockHeight+spacing) * scaleX
		Local spaceY# = sinP90 * (blockHeight+spacing) * scaleY
		
		Local bx#,by#
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight/3 *seems* to be an ok value for spaces
			'for Vertical text, move the position down
			If s[i] = 32
				x:+ spaceX
				y:+ spaceY
			End If
			
			If char[s[i]] And s[i]<>32
				curChar = s[i]
		
				areaW = cW[curChar]
				areaH = blockHeight

				bx = x
				by = y
					
				bx:+ cosR* ofs[curChar] * scaleX
				by:+ sinR* ofs[curChar] * scaleY
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw 0, 0, areaW, areaH, x+oX, y+oY
					
				Else 'Same as above, but using DX variation
					DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
				End If
				
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ spaceX
				y:+ spaceY
						
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV (0,0,1,1)
		End If	
	End Method

	Method DrawWobble(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
		Local i:Int,t:String

		Local scaleX#,scaleY#
		Local oX#,oY#				'Current Max2D Origin
		Local rot#						'Current Max2D Rotation
		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		Local frame:Int = 0
		
		GetOrigin oX,oY
		GetScale scaleX,scaleY
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot+90)
		cosP90 = Cos(rot+90)
		
	
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe 	= TGLImageFrame(image.frame(frame))
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(image.frame(frame))
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					ln:+ blockHeight*.3
				Else If char[s[i]]
					ln:+ cW[s[i]]+spacing
				End If
			Next
			ln:- spacing 'remove last unwanted space

			ln = ln*scaleX *.5
			x:- cosR*ln
			y:- sinR*ln
		End If
		
		Local spaceValX# = cosR * blockHeight * .3 * scaleX
		Local spaceValY# = sinR * blockHeight * .3 * scaleY
		
		Local bx#,by#
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				x:+ spaceValX
				y:+ spaceValY
			End If

			'If our loaded bitmap font has this character...
			If char[s[i]] And s[i]<>32
				curChar = s[i]

				bx = x + Cos(angle) * mag * scaleX
				by = y + Sin(angle) * mag * scaleY

				areaW = cW[curChar]
				areaH = blockHeight

				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					GLframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
					
				Else 'Same as above, but using DX variation
					DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
				End If
				
				angle:+ angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ CosR * (cW[curChar]+spacing) * scaleX
				y:+ SinR * (cW[curChar]+spacing) * scaleY
			
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV (0,0,1,1)
		End If	
	End Method

	
	Method DrawSineSize(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
		Local i:Int,t:String

		Local scaleX#,scaleY#
		Local oX#,oY#				'Current Max2D Origin
		Local rot#						'Current Max2D Rotation
		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		Local frame:Int = 0
		
		GetOrigin oX,oY
		GetScale scaleX,scaleY
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot+90)
		cosP90 = Cos(rot+90)
		
	
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe 	= TGLImageFrame(image.frame(frame))
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(image.frame(frame))
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					ln:+ blockHeight*.3
				Else If char[s[i]]
					ln:+ cW[s[i]]+spacing
				End If
			Next
			ln:- spacing 'remove last unwanted space

			ln = ln*scaleX *.5
			x:- cosR*ln
			y:- sinR*ln
		End If
		
		Local spaceValX# = cosR * blockHeight * .3 * scaleX
		Local spaceValY# = sinR * blockHeight * .3 * scaleY
		
		Local bx#,by#
		Local sizeX#,sizeY#
		mag:* .01
		Local ah#,aw#
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				x:+ spaceValX
				y:+ spaceValY
			End If

			'If our loaded bitmap font has this character...
			If char[s[i]] And s[i]<>32
				curChar = s[i]

				areaW = cW[curChar]' + 
				areaH = blockHeight' + 
				aw = areaW + (Sin(angle)*cW[curChar]*mag)
				ah = areaH + (Sin(angle)*blockHeight * mag)
				
				bx=x
				by=y

				bx:+ cosR* (areaW - aw) * .5 * scaleX
				by:+ sinR* (areaW - aw) * .5 * scaleX

				bx:+ cosP90* (areaH - ah) * .5 * scaleY
				by:+ sinP90* (areaH - ah) * .5 * scaleY

							
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = pX[curChar] * iwM
					GLframe.v0 = pY[curChar] * ihM
					GLframe.u1 = (pX[curChar]+areaW) * iwM
					GLframe.v1 = (pY[curChar]+areaH) * ihM
					
					GLframe.Draw 0, 0, aw, ah, bx+oX, by+oY
					
				Else 'Same as above, but using DX variation
					DXframe.setUV(pX[curChar]*iwM, pY[curChar]*ihM, (pX[curChar]+areaW)*iwM, (pY[curChar]+areaH)*ihM)
					DXframe.Draw 0, 0, aw, ah, bx+oX, by+oY
				End If
				
				angle:+ angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ CosR * (cW[s[i]]+spacing) * scaleX
				y:+ SinR * (cW[s[i]]+spacing) * scaleY
			
			End If
		Next
		
		SetScale scaleX,scaleY
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV (0,0,1,1)
		End If	
	End Method

	Method DrawSwing(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
		Local i:Int,t:String

		Local scaleX#,scaleY#
		Local oX#,oY#				'Current Max2D Origin
		Local rot#						'Current Max2D Rotation
		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#
		
		Local curchar:Byte		
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		Local frame:Int = 0
		Local hX#,hY#
		
		GetOrigin oX,oY
		GetScale scaleX,scaleY
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot+90)
		cosP90 = Cos(rot+90)
		
	
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe 	= TGLImageFrame(image.frame(frame))
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(image.frame(frame))
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					ln:+ blockHeight*.3
				Else If char[s[i]]
					ln:+ cW[s[i]]+spacing
				End If
			Next
			ln:- spacing 'remove last unwanted space

			ln:* scaleX *.5
			x:- cosR*ln
			y:- sinR*ln
		End If
		
		Local spaceValX# = cosR * blockHeight * .3 * scaleX
		Local spaceValY# = sinR * blockHeight * .3 * scaleY
		Local bx#,by#

		'Draw each letter in the string...
		For i = 0 Until s.length
		
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				x:+ spaceValX
				y:+ spaceValY
			End If

			SetRotation rot+Sin(angle)*mag
			'If our loaded bitmap font has this character...
			If char[s[i]] And s[i]<>32
				curChar = s[i]	

				hX = -cW[curChar]*.5
				hY = 0

				bx = x - cosR*hX*scaleX '- cosR * bMag
				by = y - sinR*hX*scaleY'- sinR * bMag
				
				areaW = cW[curChar]
				areaH = blockHeight

				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw hX, hY, areaW+hX, areaH, bx+oX, by+oY
					
				Else 'Same as above, but using DX variation
					DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw hX, hY, areaW+hX, areaH, bx+oX, by+oY
				End If
				
				angle:+ angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ cosR * (cW[curChar]+spacing) * scaleX
				y:+ sinR * (cW[curChar]+spacing) * scaleY
			
			End If
		Next
		
		SetRotation rot
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV (0,0,1,1)
		End If	
	End Method
End Type

Type aFonText
	Global list:TList
	
	Field link:TLink
	
	Field sX#,sY#
	Field sT%
	Field aT%
	Field dT%
	Field rT%
	Field str$
	
	Field srcX:Float[],srcY:Float[]
	Field dstX:Float[],dstY:Float[]
	Field vX:Float[],vY:Float[]
	
	Field f:FonText

	Field thisScaleX#,thisScaleY#
	Field thisOriginX#,thisOriginY#
	Field thisRotation#
	Field textCenter#
	Field textLength#
		
	Method New()
		If Not list Then list = CreateList()
		link = ListAddLast(list,Self)
	End Method
	
	Method Destroy()
		RemoveLink link
	End Method
	
	Function Create(text$, ft:FonText, pX#, pY#, start%, attack%,..
		 duration%, _release%, spacing#, centered:Byte,dir:Int)
		
		Local a:aFonText = New aFonText
		Local time% = MilliSecs()
		a.str = text
		a.f = ft
		a.sX = pX
		a.sY = pY
		a.sT = time + start
		a.aT = time + start + attack
		a.dT = time + start + attack + duration
		a.rT = time + start + attack + duration + _release

		a.thisRotation = GetRotation()
		GetOrigin a.thisOriginX,a.thisOriginY
		GetScale a.thisScaleX,a.thisScaleY
			
		Local sLen% = text.length
		a.srcX = New Float[sLen]
		a.srcY = New Float[sLen]
		
		a.dstX = New Float[sLen]
		a.dstY = New Float[sLen]
		
		a.vX = New Float[sLen]
		a.vY = New Float[sLen]
		
		
		
		Local i:Int,t:String

		Local sinR#,cosR#,sinP90#,cosP90#
		Local areaW#,areaH#
		
		Local curChar:Byte

		sinR = Sin(a.thisRotation)
		cosR = Cos(a.thisRotation)
		sinP90 = Sin(a.thisRotation+90)
		cosP90 = Cos(a.thisRotation+90)
		
	
		'Center text horizontally?
		Local ln:Float = 0
		'If centered
			'Get string length
			For i = 0 Until text.length
				If text[i] = 32
					ln:+ a.f.blockHeight*.3
				Else If a.f.char[text[i]]
					ln:+ a.f.cW[text[i]]+spacing
				End If
			Next
			
			ln:- spacing 'remove last unwanted space

			a.textLength = ln
			'ln = ln * a.thisScaleX *.5
			ln:* .5
		If centered
			pX:- cosR*ln * a.thisScaleX
			pY:- sinR*ln * a.thisScaleY
		End If
		
		Local spaceValX# = cosR * a.f.blockHeight * .3 * a.thisScaleX
		Local spaceValY# = sinR * a.f.blockHeight * .3 * a.thisScaleY
				
		'Calc each characters destination, and store it
		For i = 0 Until text.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If text[i] = 32
				pX:+ spaceValX
				pY:+ spaceValY
			End If

			'If our loaded bitmap font has this character...
			If a.f.char[text[i]] And text[i]<>32
				curChar = text[i]

				areaW = a.f.cW[curChar]
				areaH = a.f.blockHeight

				a.dstX[i] = pX+a.thisOriginX
				a.dstY[i] = pY+a.thisOriginY
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				pX:+ CosR * (a.f.cW[curChar]+spacing) * a.thisScaleX
				pY:+ SinR * (a.f.cW[curChar]+spacing) * a.thisScaleY
			
			End If
		Next
	

		'setup src & velocity vectors
		For i = 0 Until text.length
			Select dir
				Case 0
					Local ix:Int = Int(a.str.length*.5-.5)
					If ix < 0 ix = 0
					a.srcX[i] = a.dstX[ix]'a.sX + cosR * a.textCenter
					a.srcY[i] = a.dstY[ix]'sY + sinR * a.textCenter	
				Case -1
					a.srcX[i] = a.dstX[0] 
					a.srcY[i] = a.dstY[0] 
				Case 1
					a.srcX[i] = a.dstX[a.str.length-1]
					a.srcY[i] = a.dstY[a.str.length-1]
			End Select
				
			a.vX[i] = a.srcX[i]-a.dstX[i]
			a.vY[i] = a.srcY[i]-a.dstY[i]
			
		Next
	End Function



	Function Update()
		If Not list Then Return
		
		Local time%
		Local a:aFonText
		Local oldRot#,oldScaleX#,oldScaleY#,oldOriginX#,oldOriginY#
		Local oldAlpha# = GetAlpha()
		Local oldBlend% = GetBlend()
		
		oldRot = GetRotation()
		GetScale oldScaleX,oldScaleY
		GetOrigin oldOriginX,oldOriginY

		Local i:Int		
		Local isGL:Byte
		
		Local tx#,ty#,areaw#,areah#
		Local curChar:Byte
		Local GLframe:TGLImageFrame
		Local DXframe:TD3D7ImageFrame
		
		SetBlend ALPHABLEND
		For a = EachIn aFonText.list
			SetRotation a.thisRotation
			SetScale a.thisScaleX,a.thisScaleY
			SetOrigin a.thisOriginX,a.thisOriginY
			
			If TGLImageFrame(a.f.image.frame(0))
				isGL = True
				GLframe 	= TGLImageFrame(a.f.image.frame(0))
			Else
				isGL = False
				DXframe = TD3D7ImageFrame(a.f.image.frame(0))
			End If
		
			If time > a.rT
				a.Destroy()
				a = Null
			End If

			time = MilliSecs()			
			If a And time >= a.sT And time <= a.rT
				Local elap#
				Local al#

				For i = 0 Until a.str.length
					If time >= a.sT And time < a.aT
						elap = (Float((time - a.sT)) / (a.aT-a.sT))
						al = elap
						elap = 1.0 - elap
						elap = 1.0 - Cos(elap*90)
						
						tx = a.dstX[i] + a.vX[i]*elap
						tY = a.dstY[i] + a.vY[i]*elap'srcY[i]*elap'dstY[i] - a.srcY[i]*elap '+ a.vY[i]*elap
						
						SetAlpha  1.0 - elap
						'DrawText "Attack",0,0
					Else If time >=a.aT And time <= a.dT
						SetAlpha 1
						'pause
						tx = a.dstX[i]
						ty = a.dstY[i]
						'DrawText "Duration",0,0
					Else If time > a.dT And time <= a.rT
						tx = a.dstX[i]
						ty = a.dstY[i]' + (Abs(time - a.dT) * .05)
						
						elap = 1.0 - (Float(time - a.dT)) / (a.rT-a.dT)
						SetAlpha elap
						'DrawText "Release",0,0
					
					End If
			
					curChar = a.str[i]

					areaW = a.f.cW[curChar]
					areaH = a.f.blockHeight
					If isGL
						'Point UVs to character in FonText Bitmap..
						GLframe.u0 = a.f.u0[curChar]
						GLframe.v0 = a.f.v0[curChar]
						GLframe.u1 = a.f.u1[curChar]
						GLframe.v1 = a.f.v1[curChar]
					
						GLframe.Draw 0, 0, areaW, areaH, tx, ty
					
					Else 'Same as above, but using DX variation
						DXframe.setUV(a.f.u0[curchar], a.f.v0[curChar], a.f.u1[curChar], a.f.v1[curChar])
						DXframe.Draw 0, 0, areaW, areaH, tx, ty
					End If
				Next
			End If
		Next
		
		SetBlend oldBlend
		SetAlpha oldAlpha
		SetRotation oldRot
		SetScale oldScaleX,oldScaleY
		SetOrigin oldOriginX,oldOriginY
	End Function
	
End Type




It's that time of year once again, so *bump*. :)

thanks, ill be able to use it on christmas day

oo I should try using FONText in BlitzMax. I've been using it for years with Blitz3D and it worked excellent; meanwhile in BlitzMax the Max2D text commands are great for my needs so far, but I will probably want snazzier text eventually.

Merry Christmas again!

Wow! This is going to be very useful! Thank you.

I missed this 2 years ago ;) so thanks 2 years later

kev

That
Plugin to create Fontext mesh directly in gile[s]
has a shiny new appeal this Christmas, so that deserves a thankyou too.

Nice one, Mr Beaker. :o)

PS: This is gonna sound scroungy in this context, but whatever happened to that fancy schmancy "dissolve" code (based on greyscale gradients, IIRC) you were playing with waaaay back in the 2D days? Did you ever end up using it something like you were planning to?

LineOf7s - I did use it for a presentation display thing a few years back. But not really had much use for it otherwise. The problem with it for games is that you have to set your screen res in stone beforehand and then never change it, which could be a problem for distributed fullscreen games etc. There are several ways to make it more flexible but I never bothered. You are welcome to it if you want it.

Please note that the gile[s] plugin probably only works in v1.36. I've never tried it in the newer 2.0 beta version, if anyone wants to give it a go.

Thankyou for the offer, but apart from noting that it was an especially cool effect, I haven't yet been able to think what I'd use it for. :o) I'm just glad you did actually use it at some stage, because you were quite chuffed with it at the time and it was, after all, especially cool.

Did I miss a working link to the BlitzMax module?

The source is listed earlier.

Thanks, I'll turn the code into a SuperStrict module and repost..

SuperStrict module (note the changes from FonText to TFonText and aFonText to TAnimFonText):
SuperStrict

?win32
	Import brl.D3D7Max2D
?
Import brl.GLMax2D

Rem
bbdoc: FonText
End Rem
Module beaker.FonText

ModuleInfo "Version: 1.00"
ModuleInfo "Author: Beaker (converted to standard SuperStrict module by Plash)"

ModuleInfo "History: Changed FonText to TFonText, and aFonText to TAnimFonText"
ModuleInfo "History: Removed dependency on BRL.Retro by using slicing, changed all variable type definitions to full-length."

Type TFonText
	Field image:TImage
	Field blockHeight:Int
	Field char:Byte[255]	'Boolean for each ASCII character, True if the FonText includes it, False if not
	Field maskColor:Int
	Field packed:Int
	
	Field pX:Float[255]		'Position X
	Field pY:Float[255]		'Position Y
	Field cW:Int[255]		'Width
	
	Field sinL:Float[360]	'not used yet
	Field cosL:Float[360]	'""
	
	Field iwM:Float			'Image width & height multipliers used in
	Field ihM:Float			'functions to optimise UV calculation speed
	
	Field u0:Float[255]
	Field v0:Float[255]
	
	Field u1:Float[255]
	Field v1:Float[255]
	
	Function Create:TFonText(file:String, Flags:Int = -1)
		Local img:TImage = LoadImage(file, Flags)
		If Not img RuntimeError("Could not load Image " + file)
		SetImageHandle(img, 0, 0)
		
		Local ini:TStream = OpenFile(file[..file.Length - 3] + "ini")
		If Not ini RuntimeError("Could not find " + file[..file.Length - 3] + "ini")
		
		Local f:TFonText = New(TFonText)
		f.Image = img
		
		f.iwM = 1.0 / img.width
		f.ihM = 1.0 / img.height
		
		'Get BlockSize (height)
		Local r:String
		
		'Ignore first 3 lines
		ini.ReadLine()
		ini.ReadLine()
		ini.ReadLine()
		
		'Get MaskColor (needed?)
		r = ini.ReadLine()
		f.maskColor = Int(r[10..])
		
		'Packed Font?
		r = ini.ReadLine()
		f.packed = Int(r[r.Length - 1..])
		
		'Find [text] line
		r = ReadLine(ini)
		While r <> "[text]"
			r = ini.ReadLine()
		Wend
		
		'Block Height
		r = ini.ReadLine()
		f.blockHeight = Int(r[10..])
		
		'Count Characters
		r = ini.ReadLine()
		While r<>"[charset]"
			r = ini.ReadLine()
		Wend
		
		'Store this location
		Local location:Int = ini.Pos() 'StreamPos(ini)
		
		'do the count
		Local count:Int = 0
		While Not Eof(ini)
			r = ini.ReadLine()
			count:+1
		Wend
		
		'Back to the Characters...
		'SeekStream(ini, location)
		ini.seek(location)
		
		Local i:Int,j:Int,s:String,t:String
		Local cur:Byte
		
		'Parse each characters position & width
		For i = 0 Until count
			r = ini.ReadLine()
			cur = r[0]
			f.char[cur] = True
			
			'Position X
			j = 3
			s = ""
			t = r[j - 1..j]
			While t<>","
				s:+ t
				j:+1
				t = r[j - 1..j]
			Wend
			f.pX[cur] = Float(s)
			
			'Position Y
			j:+1
			s = ""
			t = r[j - 1..j]
			While t<>","
				s:+t
				j:+1
				t = r[j - 1..j]
			Wend
			f.pY[cur] = Float(s)
			
			'Character Width
			j:+1
			s = ""
			t = r[j - 1..j]
			While t <> ","
				s:+t
				j:+1
				If j > r.Length Exit
				t = r[j - 1..j]
			Wend
			f.cW[cur] = Int(s)
			
			'Adjust packing if the font isn't packed (trim space either side of character)
			If Not f.packed
				f.pX[cur]:+(f.blockheight - f.cW[cur]) *.5
			End If
			
			f.u0[cur] = f.pX[cur] * f.iwM
			f.v0[cur] = f.pY[cur] * f.ihM
			f.u1[cur] = (f.pX[cur] + f.cW[cur]) * f.iwM
			f.v1[cur] = (f.pY[cur] + f.blockHeight) * f.ihM
		Next
		
		ini.Close()
		
		Return(f)
		
	End Function
	
	Method DrawJustified(s:String, X:Float, Y:Float, centered:Byte, spacing:Float, lineBreak:Float, scaleLB:Byte)
		Local i:Int, t:String
		
		Local ScaleX:Float, ScaleY:Float
		Local oX:Float, oY:Float
		Local rot:Float
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		Local frame:Int = 0
		Local xDrawn:Float = 0
		
		GetOrigin(oX, oY)
		GetScale(ScaleX, ScaleY)
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot + 90)
		cosP90 = Cos(rot + 90)
		
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe = TGLImageFrame(Image.Frame(Frame))
		?win32
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(Image.Frame(Frame))
		?
		End If
		
		If scaleLB Then lineBreak:*ScaleX
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			X:-cosR * lineBreak *.5
			Y:-sinR * lineBreak *.5
		End If
		
		Local newWord:Int = 0
		Local wordLen:Float
		Local tw:Int
		Local lastLen:Int = 0
		
		Local vSpacing:Int = blockHeight *.8
		
		'Draw each letter in the string...
		For i = 0 Until s.Length
			'Check for whole word, we don't want to break them up
			If lastLen <= 0 And s[i] <> 32 And lineBreak > 0
				lastLen = 0
				For newWord = i Until s.Length
					lastLen:+1
					If s[newWord] = 32 Or s[newWord] = 13 Exit
				Next
				
				wordLen = 0
				'Was there a word?
				If newWord > 0
					For tw = i Until newWord
						wordLen:+(cW[s[tw] ] + spacing) * ScaleX
					Next
				End If
				
				'Check the length doesn't go over the lineBreak limit
				If xDrawn + wordLen > lineBreak
					'goto next line
					
					'move back to beginning
					X:-cosR * xDrawn
					Y:-sinR * xDrawn
					
					'move down
					X:+cosP90 * vSpacing * ScaleX
					Y:+sinP90 * vSpacing * ScaleY
					lastLen = 0
					xDrawn = 0
				End If
			End If
			
			'Space character?
			'blockHeight/3 *seems* to be an ok value for spaces
			If s[i] = 32 ' And xDrawn>2
				X:+cosR * blockHeight *.3 * ScaleX
				Y:+sinR * blockHeight *.3 * ScaleY
				xDrawn:+blockHeight *.3 * ScaleX
			End If
			
			'Linebreak?
			If s[i] = 13
				
				'goto next line
				
				'move back to beginning
				X:-cosR * xDrawn
				Y:-sinR * xDrawn
									
				'move down
				X:+cosP90 * vSpacing * ScaleX
				Y:+sinP90 * vSpacing * ScaleY
				lastLen = 0
				xDrawn = 0
				
			End If
			
			'If our loaded bitmap font has this character...
			If char[s[i] ] ' And s[i]<>32
				curChar = s[i]
				
				lastLen:-1
				
				areaW = cW[curChar]
				areaH = blockHeight
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)
					
				?win32
				Else 'Same as above, but using DX variation
					DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)
				?
				End If
				
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ cosR * (cW[curChar]+spacing) * scaleX
				y:+ sinR * (cW[curChar]+spacing) * scaleY
				xDrawn:+ (cW[curChar]+spacing) * scaleX
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1	= 1
		Else
			DXframe.SetUV(0, 0, 1, 1)
		End If	
	End Method
	
	Method Draw(s:String, X:Float, Y:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int, t:String
		
		Local ScaleX:Float, ScaleY:Float
		Local oX:Float, oY:Float		'Current Max2D Origin
		Local rot:Float					'Current Max2D Rotation
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		Local frame:Int = 0
		
		GetOrigin(oX, oY)
		GetScale(ScaleX, ScaleY)
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot + 90)
		cosP90 = Cos(rot + 90)
		
		If TGLImageFrame(Image.Frame(Frame))
			isGL = True
			GLframe = TGLImageFrame(Image.Frame(Frame))
		?win32
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(Image.Frame(Frame))
		?
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					ln:+ blockHeight*.3
				Else If char[s[i]]
					ln:+ cW[s[i]]+spacing
				End If
			Next
			Ln:-spacing 'remove last unwanted space
			
			Ln = Ln * ScaleX *.5
			X:-cosR * Ln
			Y:-sinR * Ln
		End If
		
		Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
		Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY
				
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				X:+spaceValX
				Y:+spaceValY
			End If
			
			'If our loaded bitmap font has this character...
			If char[s[i] ] And s[i] <> 32
				curChar = s[i]
				
				areaW = cW[curChar]
				areaH = blockHeight
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)
					
				?win32
				Else 'Same as above, but using DX variation
					DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)
				?
				End If
				
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				X:+CosR * (cW[curChar] + spacing) * ScaleX
				Y:+SinR * (cW[curChar] + spacing) * ScaleY
			
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0 = 0
			GLframe.v0 = 0
			GLframe.u1 = 1
			GLframe.v1 = 1
		?win32
		Else
			DXframe.SetUV(0, 0, 1, 1)
		?
		End If
	End Method
	
	Method DrawWave(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int, t:String

		Local ScaleX:Float, ScaleY:Float
		Local oX:Float, oY:Float	'Current Max2D Origin
		Local rot:Float				'Current Max2D Rotation
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		Local frame:Int = 0
		
		GetOrigin(oX, oY)
		GetScale(ScaleX, ScaleY)
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot + 90)
		cosP90 = Cos(rot + 90)
		
		If TGLImageFrame(Image.Frame(Frame))
			isGL = True
			GLframe = TGLImageFrame(Image.Frame(Frame))
		?win32
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(Image.Frame(Frame))
		?
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					Ln:+blockHeight *.3
				Else If char[s[i] ]
					Ln:+cW[s[i] ] + spacing
				End If
			Next
			ln:- spacing 'remove last unwanted space
			
			Ln = Ln * ScaleX *.5
			X:-cosR * Ln
			Y:-sinR * Ln
		End If
		
		Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
		Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY
		
		Local bx:Float, by:Float, bMag:Float
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				X:+spaceValX
				Y:+spaceValY
			End If
			
			'If our loaded bitmap font has this character...
			If char[s[i] ] And s[i] <> 32
				curChar = s[i]
				
				bMag = Sin(angle) * mag * ScaleY
				bx = X - cosP90 * bMag
				by = Y - sinP90 * bMag
				
				areaW = cW[curChar]
				areaH = blockHeight
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
					
				?win32
				Else 'Same as above, but using DX variation
					DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
				?
				End If
				
				angle:+angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				X:+CosR * (cW[curChar] + spacing) * ScaleX
				Y:+SinR * (cW[curChar] + spacing) * ScaleY
			
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0 = 0
			GLframe.v0 = 0
			GLframe.u1 = 1
			GLframe.v1 = 1
		?win32
		Else
			DXframe.SetUV(0, 0, 1, 1)
		?
		End If	
	End Method
	
	Method DrawWiggle(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int, t:String
		
		Local ScaleX:Float, ScaleY:Float
		Local oX:Float, oY:Float	'Current Max2D Origin
		Local rot:Float				'Current Max2D Rotation
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		Local frame:Int = 0
		
		GetOrigin(oX, oY)
		GetScale(ScaleX, ScaleY)
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot + 90)
		cosP90 = Cos(rot + 90)
		
		If TGLImageFrame(Image.Frame(Frame))
			isGL = True
			GLframe = TGLImageFrame(Image.Frame(Frame))
		?win32
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(Image.Frame(Frame))
		?
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.Length
				If s[i] = 32
					Ln:+blockHeight *.3
				Else If char[s[i] ]
					Ln:+cW[s[i] ] + spacing
				End If
			Next
			Ln:-spacing 'remove last unwanted space
			
			Ln = Ln * ScaleX *.5
			X:-cosR * Ln
			Y:-sinR * Ln
		End If
		
		Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
		Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY
		
		Local bx:Float, by:Float, bMag:Float
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				X:+spaceValX
				Y:+spaceValY
			End If
			
			'If our loaded bitmap font has this character...
			If char[s[i] ] And s[i] <> 32
				curChar = s[i]
				
				bMag = Sin(angle) * mag * ScaleX
				bx = X - cosR * bMag
				by = Y - sinR * bMag
				
				areaW = cW[curChar]
				areaH = blockHeight
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
					
				?win32
				Else 'Same as above, but using DX variation
					DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
				?
				End If
				
				angle:+ angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				X:+CosR * (cW[curChar] + spacing) * ScaleX
				Y:+SinR * (cW[curChar] + spacing) * ScaleY
			
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0 = 0
			GLframe.v0 = 0
			GLframe.u1 = 1
			GLframe.v1 = 1
		?win32
		Else
			DXframe.SetUV(0, 0, 1, 1)
		?
		End If	
	End Method

	Method DrawBouncy(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int, t:String
		
		Local ScaleX:Float, ScaleY:Float
		Local oX:Float, oY:Float	'Current Max2D Origin
		Local rot:Float				'Current Max2D Rotation
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		Local frame:Int = 0
		
		GetOrigin(oX, oY)
		GetScale(ScaleX, ScaleY)
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot + 90)
		cosP90 = Cos(rot + 90)
		
		If TGLImageFrame(Image.Frame(Frame))
			isGL = True
			GLframe = TGLImageFrame(Image.Frame(Frame))
		?win32
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(Image.Frame(Frame))
		?
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					Ln:+blockHeight *.3
				Else If char[s[i] ]
					Ln:+cW[s[i] ] + spacing
				End If
			Next
			ln:- spacing 'remove last unwanted space
			
			Ln = Ln * ScaleX *.5
			X:-cosR * Ln
			Y:-sinR * Ln
		End If
		
		Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
		Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY
		
		Local bx:Float, by:Float, bMag:Float
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				X:+spaceValX
				Y:+spaceValY
			End If
			
			'If our loaded bitmap font has this character...
			If char[s[i] ] And s[i] <> 32
				curChar = s[i]
				
				bMag = Abs(Sin(angle)) * mag * ScaleY
				bx = X - cosP90 * bMag
				by = Y - sinP90 * bMag
				
				areaW = cW[curChar]
				areaH = blockHeight
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
					
				?win32
				Else 'Same as above, but using DX variation
					DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
				?
				End If
				
				angle:+ angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				X:+CosR * (cW[curChar] + spacing) * ScaleX
				Y:+SinR * (cW[curChar] + spacing) * ScaleY
				
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0 = 0
			GLframe.v0 = 0
			GLframe.u1 = 1
			GLframe.v1 = 1
		?win32
		Else
			DXframe.SetUV(0, 0, 1, 1)
		?
		End If	
	End Method
	
	Method DrawVertical(s:String, X:Float, Y:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int, t:String
		Local ScaleX:Float, ScaleY:Float
		Local oX:Float, oY:Float	'Current Max2D Origin
		Local rot:Float				'Current Max2D Rotation
		
		'Look UPs
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		
		Local frame:Int = 0
		
		GetOrigin(oX, oY)
		GetScale(ScaleX, ScaleY)
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90:Float = Sin(rot + 90)
		cosP90:Float = Cos(rot + 90)
		
		If TGLImageFrame(Image.Frame(Frame))
			isGL = True
			GLframe = TGLImageFrame(Image.Frame(Frame))
		?win32
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(Image.Frame(Frame))
		?
		End If
		
		'Center the Vertical text so it appears
		'nicely centered
		
		'Find widest character
		Local bc:Float = 0
		For i = 0 Until s.length
			If cW[s[i] ] > bc Then bc = cW[s[i] ]
		Next
		
		'build an offset array based of widest char
		Local ofs:Float[255]
		For i = 0 Until s.Length
			ofs[s[i] ] = (bc - cW[s[i] ]) *.5
		Next
		
			'ln = bc*scaleX *.5
		If centered
			X:-cosR * (bc *.5) * ScaleX
			Y:-sinR * (bc *.5) * ScaleY
		End If
		
		Local spaceX:Float = cosP90 * (blockHeight + spacing) * ScaleX
		Local spaceY:Float = sinP90 * (blockHeight + spacing) * ScaleY
		
		Local bx:Float, by:Float
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight/3 *seems* to be an ok value for spaces
			'for Vertical text, move the position down
			If s[i] = 32
				X:+spaceX
				Y:+spaceY
			End If
			
			If char[s[i] ] And s[i] <> 32
				curChar = s[i]
				
				areaW = cW[curChar]
				areaH = blockHeight
				
				bx = X
				by = y
					
				bx:+cosR * ofs[curChar] * ScaleX
				by:+sinR * ofs[curChar] * ScaleY
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)
					
				?win32
				Else 'Same as above, but using DX variation
					DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
				?
				End If
				
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				x:+ spaceX
				y:+ spaceY
						
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0 = 0
			GLframe.v0 = 0
			GLframe.u1 = 1
			GLframe.v1 = 1
		?win32
		Else
			DXframe.SetUV(0, 0, 1, 1)
		?
		End If	
	End Method
	
	Method DrawWobble(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int,t:String
		
		Local ScaleX:Float, ScaleY:Float
		Local oX:Float, oY:Float			'Current Max2D Origin
		Local rot:Float						'Current Max2D Rotation
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		Local frame:Int = 0
		
		GetOrigin(oX, oY)
		GetScale(ScaleX, ScaleY)
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot + 90)
		cosP90 = Cos(rot + 90)
		
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe = TGLImageFrame(Image.Frame(Frame))
		?win32
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(Image.Frame(Frame))
		?
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.Length
				If s[i] = 32
					Ln:+blockHeight *.3
				Else If char[s[i] ]
					Ln:+cW[s[i] ] + spacing
				End If
			Next
			Ln:-spacing 'remove last unwanted space
			
			Ln = Ln * ScaleX *.5
			X:-cosR * Ln
			Y:-sinR * Ln
		End If
		
		Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
		Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY
		
		Local bx:Float, by:Float
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				X:+spaceValX
				Y:+spaceValY
			End If
			
			'If our loaded bitmap font has this character...
			If char[s[i] ] And s[i] <> 32
				curChar = s[i]
				
				bx = X + Cos(angle) * mag * ScaleX
				by = Y + Sin(angle) * mag * ScaleY
				
				areaW = cW[curChar]
				areaH = blockHeight
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					GLframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
					
				?win32
				Else 'Same as above, but using DX variation
					DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
				?
				End If
				
				angle:+angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				X:+CosR * (cW[curChar] + spacing) * ScaleX
				Y:+SinR * (cW[curChar] + spacing) * ScaleY
			
			End If
		Next
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0
			GLframe.v0	= 0
			GLframe.u1	= 1
			GLframe.v1 = 1
		?win32
		Else
			DXframe.SetUV(0, 0, 1, 1)
		?
		End If	
	End Method
	
	Method DrawSineSize(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int, t:String
		
		Local ScaleX:Float, ScaleY:Float
		Local oX:Float, oY:Float		'Current Max2D Origin
		Local rot:Float					'Current Max2D Rotation
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curChar:Byte
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		Local frame:Int = 0
		
		GetOrigin(oX, oY)
		GetScale(ScaleX, ScaleY)
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot + 90)
		cosP90 = Cos(rot + 90)
		
		If TGLImageFrame(image.frame(frame))
			isGL = True
			GLframe = TGLImageFrame(Image.Frame(Frame))
		?win32
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(Image.Frame(Frame))
		?
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.Length
				If s[i] = 32
					Ln:+blockHeight *.3
				Else If char[s[i] ]
					Ln:+cW[s[i] ] + spacing
				End If
			Next
			Ln:-spacing 'remove last unwanted space
			
			Ln = Ln * ScaleX *.5
			X:-cosR * Ln
			Y:-sinR * Ln
		End If
		
		Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
		Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY
		
		Local bx:Float, by:Float
		Local sizeX:Float, sizeY:Float
		mag:*.01
		Local ah:Float, aw:Float
		
		'Draw each letter in the string...
		For i = 0 Until s.Length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				X:+spaceValX
				Y:+spaceValY
			End If
			
			'If our loaded bitmap font has this character...
			If char[s[i] ] And s[i] <> 32
				curChar = s[i]
				
				areaW = cW[curChar] ' + 
				areaH = blockHeight ' + 
				aw = areaW + (Sin(angle) * cW[curChar] * mag)
				ah = areaH + (Sin(angle) * blockHeight * mag)
				
				bx = X
				by = Y
				
				bx:+cosR * (areaW - aw) *.5 * ScaleX
				by:+sinR * (areaW - aw) *.5 * ScaleX
				
				bx:+cosP90 * (areaH - ah) *.5 * ScaleY
				by:+sinP90 * (areaH - ah) *.5 * ScaleY
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = pX[curChar] * iwM
					GLframe.v0 = pY[curChar] * ihM
					GLframe.u1 = (pX[curChar] + areaW) * iwM
					GLframe.v1 = (pY[curChar] + areaH) * ihM
					
					GLframe.Draw(0, 0, aw, ah, bx + oX, by + oY)
					
				?win32
				Else 'Same as above, but using DX variation
					DXframe.SetUV(pX[curChar] * iwM, pY[curChar] * ihM, (pX[curChar] + areaW) * iwM, (pY[curChar] + areaH) * ihM)
					DXframe.Draw(0, 0, aw, ah, bx + oX, by + oY)
				?
				End If
				
				angle:+angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				X:+CosR * (cW[s[i] ] + spacing) * ScaleX
				Y:+SinR * (cW[s[i] ] + spacing) * ScaleY
			
			End If
		Next
		
		SetScale(ScaleX, ScaleY)
		
		'Restore UVs
		If isGL
			GLframe.u0	= 0 
			GLframe.v0 = 0
			GLframe.u1 = 1
			GLframe.v1 = 1
		?win32
		Else
			DXframe.SetUV(0, 0, 1, 1)
		?
		End If	
	End Method
	
	Method DrawSwing(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
		Local i:Int, t:String
		
		Local ScaleX:Float, ScaleY:Float
		Local oX:Float, oY:Float 				'Current Max2D Origin
		Local rot:Float 						'Current Max2D Rotation
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curchar:Byte		
		Local isGL:Byte			'Boolean
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		
		Local frame:Int = 0
		Local hX:Float, hY:Float
		
		GetOrigin(oX, oY)
		GetScale(ScaleX, ScaleY)
		
		rot = GetRotation()
		sinR = Sin(rot)
		cosR = Cos(rot)
		sinP90 = Sin(rot+90)
		cosP90 = Cos(rot+90)
		
		If TGLImageFrame(Image.Frame(Frame))
			isGL = True
			GLframe = TGLImageFrame(Image.Frame(Frame))
		?win32
		Else
			isGL = False
			DXframe = TD3D7ImageFrame(Image.Frame(Frame))
		?
		End If
		
		'Center text horizontally?
		Local ln:Float = 0
		If centered
			'Get string length
			For i = 0 Until s.length
				If s[i] = 32
					Ln:+blockHeight *.3
				Else If char[s[i] ]
					Ln:+cW[s[i] ] + spacing
				End If
			Next
			Ln:-spacing 'remove last unwanted space
			
			Ln:*ScaleX *.5
			X:-cosR * Ln
			Y:-sinR * Ln
		End If
		
		Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
		Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY
		Local bx:Float, by:Float
		
		'Draw each letter in the string...
		For i = 0 Until s.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If s[i] = 32
				X:+spaceValX
				Y:+spaceValY
			End If
			
			SetRotation(rot + Sin(angle) * mag)
			'If our loaded bitmap font has this character...
			If char[s[i] ] And s[i] <> 32
				curChar = s[i]
				
				hX = -cW[curChar] *.5
				hY = 0
				
				bx = X - cosR * hX * ScaleX '- cosR * bMag
				by = Y - sinR * hX * ScaleY '- sinR * bMag
				
				areaW = cW[curChar]
				areaH = blockHeight
				
				'Draw this character
				If isGL
					'Point UVs to character in FonText Bitmap..
					GLframe.u0 = u0[curChar]
					GLframe.v0 = v0[curChar]
					GLframe.u1 = u1[curChar]
					GLframe.v1 = v1[curChar]
					
					GLframe.Draw(hX, hY, areaW + hX, areaH, bx + oX, by + oY)
					
				?win32
				Else 'Same as above, but using DX variation
					DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
					DXframe.Draw(hX, hY, areaW + hX, areaH, bx + oX, by + oY)
				?
				End If
				
				angle:+ angleStep
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				X:+cosR * (cW[curChar] + spacing) * ScaleX
				Y:+sinR * (cW[curChar] + spacing) * ScaleY
			
			End If
		Next
		
		SetRotation(rot)
		'Restore UVs
		If isGL
			GLframe.u0 = 0
			GLframe.v0 = 0
			GLframe.u1 = 1
			GLframe.v1 = 1
		?win32
		Else
			DXframe.SetUV(0, 0, 1, 1)
		?
		End If	
	End Method
End Type

Type TAnimFonText
	Global list:TList = New(TList)
	
	Field link:TLink
	
	Field sX:Float, sY:Float
	Field sT:Int
	Field aT:Int
	Field dT:Int
	Field rT:Int
	Field str:String
	
	Field srcX:Float[],srcY:Float[]
	Field dstX:Float[],dstY:Float[]
	Field vX:Float[],vY:Float[]
	
	Field f:TFonText
	
	Field thisScaleX:Float, thisScaleY:Float
	Field thisOriginX:Float, thisOriginY:Float
	Field thisRotation:Float
	Field textCenter:Float
	Field textLength:Float
		
	Method New()
		
		Link = list.AddLast(Self)
		
	End Method
	
	Method Destroy()
		
		Link.Remove()
		
	End Method
	
	Function Create(Text:String, ft:TFonText, pX:Float, pY:Float, start:Int, attack:Int,  ..
		duration:Int, _release:Int, spacing:Float, centered:Byte, dir:Int)
		
		Local a:TAnimFonText = New(TAnimFonText)
		Local Time:Int = MilliSecs()
		a.str = text
		a.f = ft
		a.sX = pX
		a.sY = pY
		a.sT = time + start
		a.aT = time + start + attack
		a.dT = time + start + attack + duration
		a.rT = time + start + attack + duration + _release
		
		a.thisRotation = GetRotation()
		GetOrigin(a.thisOriginX, a.thisOriginY)
		GetScale(a.thisScaleX, a.thisScaleY)
			
		Local sLen:Int = Text.Length
		a.srcX = New Float[sLen]
		a.srcY = New Float[sLen]
		
		a.dstX = New Float[sLen]
		a.dstY = New Float[sLen]
		
		a.vX = New Float[sLen]
		a.vY = New Float[sLen]
		
		Local i:Int, t:String
		
		Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
		Local areaW:Float, areaH:Float
		
		Local curChar:Byte
		
		sinR = Sin(a.thisRotation)
		cosR = Cos(a.thisRotation)
		sinP90 = Sin(a.thisRotation + 90)
		cosP90 = Cos(a.thisRotation + 90)
		
		'Center text horizontally?
		Local ln:Float = 0
		'If centered
			'Get string length
			For i = 0 Until text.length
				If Text[i] = 32
					Ln:+a.f.blockHeight *.3
				Else If a.f.char[Text[i] ]
					Ln:+a.f.cW[Text[i] ] + spacing
				End If
			Next
			
			Ln:-spacing 'remove last unwanted space
			
			a.textLength = Ln
			'ln = ln * a.thisScaleX *.5
			Ln:*.5
		If centered
			pX:-cosR * Ln * a.thisScaleX
			pY:-sinR * Ln * a.thisScaleY
		End If
		
		Local spaceValX:Float = cosR * a.f.blockHeight *.3 * a.thisScaleX
		Local spaceValY:Float = sinR * a.f.blockHeight *.3 * a.thisScaleY
				
		'Calc each characters destination, and store it
		For i = 0 Until text.length
			
			'Space character?
			'blockHeight*.3 *seems* to be an ok value for spaces
			If text[i] = 32
				pX:+spaceValX
				pY:+spaceValY
			End If
				
			'If our loaded bitmap font has this character...
			If a.f.char[text[i]] And text[i]<>32
				curChar = Text[i]
				
				areaW = a.f.cW[curChar]
				areaH = a.f.blockHeight
				
				a.dstX[i] = pX + a.thisOriginX
				a.dstY[i] = pY + a.thisOriginY
				'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
				pX:+CosR * (a.f.cW[curChar] + spacing) * a.thisScaleX
				pY:+SinR * (a.f.cW[curChar] + spacing) * a.thisScaleY
				
			End If
		Next
		
		
		'setup src & velocity vectors
		For i = 0 Until text.length
			Select dir
				Case 0
					Local ix:Int = Int(a.str.Length *.5 -.5)
					If ix < 0 ix = 0
					a.srcX[i] = a.dstX[ix] 'a.sX + cosR * a.textCenter
					a.srcY[i] = a.dstY[ix] 'sY + sinR * a.textCenter	 
				Case - 1
					a.srcX[i] = a.dstX[0]
					a.srcY[i] = a.dstY[0]
				Case 1
					a.srcX[i] = a.dstX[a.str.Length - 1]
					a.srcY[i] = a.dstY[a.str.Length - 1]
			End Select
			
			a.vX[i] = a.srcX[i] - a.dstX[i]
			a.vY[i] = a.srcY[i] - a.dstY[i]
			
		Next
		
	End Function
	
	Function Update()
		If Not list Then Return
		
		Local Time:Int
		Local a:TAnimFonText
		Local oldRot:Float, oldScaleX:Float, oldScaleY:Float, oldOriginX:Float, oldOriginY:Float
		Local oldAlpha:Float = GetAlpha()
		Local oldBlend:Int = GetBlend()
		
		oldRot = GetRotation()
		GetScale(oldScaleX, oldScaleY)
		GetOrigin(oldOriginX, oldOriginY)
		
		Local i:Int		
		Local isGL:Byte
		
		Local tx:Float, ty:Float, areaw:Float, areah:Float
		Local curChar:Byte
		Local GLframe:TGLImageFrame
		?win32
		Local DXframe:TD3D7ImageFrame
		?
		
		SetBlend(ALPHABLEND)
		For a = EachIn TAnimFonText.list
			SetRotation(a.thisRotation)
			SetScale(a.thisScaleX, a.thisScaleY)
			SetOrigin(a.thisOriginX, a.thisOriginY)
			
			If TGLImageFrame(a.f.Image.Frame(0))
				isGL = True
				GLframe = TGLImageFrame(a.f.Image.Frame(0))
			?win32
			Else
				isGL = False
				DXframe = TD3D7ImageFrame(a.f.Image.Frame(0))
			?
			End If
			
			If Time > a.rT
				a.Destroy()
				a = Null
			End If
			
			time = MilliSecs()			
			If a And Time >= a.sT And Time <= a.rT
				Local elap:Float
				Local al:Float
				
				For i = 0 Until a.str.Length
					If Time >= a.sT And Time < a.aT
						elap = (Float((Time - a.sT)) / (a.aT - a.sT))
						al = elap
						elap = 1.0 - elap
						elap = 1.0 - Cos(elap * 90)
						
						tx = a.dstX[i] + a.vX[i] * elap
						tY = a.dstY[i] + a.vY[i] * elap 'srcY[i]*elap'dstY[i] - a.srcY[i]*elap '+ a.vY[i]*elap
						
						SetAlpha(1.0 - elap)
						'DrawText "Attack",0,0 
					Else If Time >= a.aT And Time <= a.dT
						SetAlpha(1)
						'pause
						tx = a.dstX[i]
						ty = a.dstY[i]
						'DrawText "Duration",0,0
					Else If Time > a.dT And Time <= a.rT
						tx = a.dstX[i]
						ty = a.dstY[i] ' + (Abs(time - a.dT) * .05)
						
						elap = 1.0 - (Float(Time - a.dT)) / (a.rT - a.dT)
						SetAlpha(elap)
						'DrawText "Release",0,0
					
					End If
					
					curChar = a.str[i]
					
					areaW = a.f.cW[curChar]
					areaH = a.f.blockHeight
					If isGL
						'Point UVs to character in FonText Bitmap..
						GLframe.u0 = a.f.u0[curChar]
						GLframe.v0 = a.f.v0[curChar]
						GLframe.u1 = a.f.u1[curChar]
						GLframe.v1 = a.f.v1[curChar]
						
						GLframe.Draw(0, 0, areaW, areaH, tx, ty)
					
					?win32
					Else 'Same as above, but using DX variation
						DXframe.setUV(a.f.u0[curchar], a.f.v0[curChar], a.f.u1[curChar], a.f.v1[curChar])
						DXframe.Draw(0, 0, areaW, areaH, tx, ty)
					?
					End If
				Next
			End If
		Next
		
		SetBlend(oldBlend)
		SetAlpha(oldAlpha)
		SetRotation(oldRot)
		SetScale(oldScaleX, oldScaleY)
		SetOrigin(oldOriginX, oldOriginY)
	End Function
	
End Type


It should work cross-platform (but I haven't tested it).
I plan on integrating it with my duct modules, and loading FonText data by using a script (quake/c-style) instead of an ini.

wow, this looks awesome.

uhm, Plash, you sure that works cross platform?
Did anyone test?