TBitmapFont

BlitzMax Forums/BlitzMax Programming/TBitmapFont

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

You might need to change some stuff to work on the latest version of BMAX but here is my module that you are more than welcome to include in your framework as long as you make reference to me. Oh and it works on all platforms.

Compiled example : http://www.pjio.com/temp/bmaptext.zip

Module:
Strict

Rem
bbdoc: BitMap Text Lib - Single Surface
End Rem
Module Indiepath.bmaptext

ModuleInfo "Version: 1.0"
ModuleInfo "Author: Tim Fisher"
ModuleInfo "License: Indiepath License for non warranted software"
ModuleInfo "Modserver:indiepath"
?Win32
Import BRL.D3D7Max2D
?
Import BRL.GLMax2D
Import BRL.PNGLoader
Import BRL.Retro


Type bMapText
	Field Image		:TImage
	Field Texturesize	:Double
	Field ScaleFactor	:Double
	Field NumChars	:Short
	Field ID			:Byte[96]
	Field xPos		:Double[96]
	Field yPos		:Double[96]
	Field width		:Double[96]
	Field height		:Double[96]
	Field xOffset		:Double[96]
	Field yOffset		:Double[96]
	Field xAdvance	:Double[96]
Rem
bbdoc: Free the Object
End Rem		
		Function Destroy(b:bMapText)
				b = Null
        	End Function

		'-----------------------------------------------------------------
Rem
bbdoc: Create a New bitMapped Text object by loading info from file
returns: Handle to new Bit Map Text Object
about: Use this command exactly as you would the Standard BLitz Command
End Rem			
		Function Create:bMapText(url:Object,flags:Int=-1)
				Local b:bMapText
				b:bMapText = New bMapText
				b.Image = LoadImage(String(url)+".png",flags)
				b.NumChars = 0
				Local myfile:TStream = ReadStream("littleendian::" + String(url)+".fnt")
				Local temp:String = ReadLine(myfile)
				Local pos1:Byte = temp.Find("scaleF=")
				b.ScaleFactor = Double(Mid(temp,pos1+8,4))
				temp:String = ReadLine(myfile)
				pos1:Byte = temp.Find("scaleW=")
				b.TextureSize = Double(Mid(temp,pos1+8,4))
				While Not Eof(myfile)
					temp:String = ReadLine(myfile)
					pos1:Byte = temp.Find("id=")
					b.ID[b.NumChars] = Byte(Mid(temp,pos1+4,3))
					pos1:Byte = temp.find("x=")
					b.xPos[b.NumChars] = Double(Mid(temp,pos1+3,3)) / b.TextureSize
					pos1:Byte = temp.find("y=")
					b.yPos[b.NumChars] = Double(Mid(temp,pos1+3,3)) / b.TextureSize
					pos1:Byte = temp.find("width=")
					b.Width[b.NumChars] = Double(Mid(temp,pos1+7,3)) / b.TextureSize
					pos1:Byte = temp.find("height=")
					b.Height[b.NumChars] = Double(Mid(temp,pos1+8,3)) / b.TextureSize
					pos1:Byte = temp.find("xoffset=")
					b.xOffset[b.NumChars] = Double(Mid(temp,pos1+9,3))
					pos1:Byte = temp.find("yoffset=")
					b.yOffset[b.NumChars] = Double(Mid(temp,pos1+9,3))
					pos1:Byte = temp.find("xadvance=")
					b.xadvance[b.NumChars] = Double(Mid(temp,pos1+10,3))
					b.Numchars:+1	
				Wend
				CloseStream(myfile)
				Return b		
		End Function
		
		'----------------------------------------------------------------
Rem
bbdoc: Get width of a string 
returns: Width of String as Double
End Rem			
		Method StringWidth:Double(text:String)
				Local a:Int
				Local char:Byte
				Local width1:Double
				For a = 0 To Len(text) -1
					char = FindChar(Mid(text,a+1,1))
					width1:+ self.xAdvance[char]
				Next
				Return width1
		End Method
		
			
		'----------------------------------------------------------------
Rem
bbdoc:Get height of a string
returns: Returns height of string as Double
End Rem		
		Method StringHeight:Double(text:String)
				Local a:Int
				Local char:Byte
				Local Height1:Double
				For a = 0 To Len(text) -1
					char = FindChar(Mid(text,a+1,1))
					Height1:+ self.height[char] * self.TextureSize
				Next
				Return (height1 / Double (Len(text)-1)) 
		End Method
		
		'----------------------------------------------------------------
Rem
bbdoc: Draw string to Screen using BmapText object
about: Pass text, positon and justification.
End Rem			
		Method Draw(text:String,x:Double,y:Double,center:Byte=False,rght:Byte=False)
			'	SetBlend(SOLIDBLEND)
				Local char:Int
				Local scale_x:Float
				Local scale_y:Float
				GetScale(scale_x,scale_y)
				
			 	scale_x :* self.ScaleFactor
			 	scale_y :* self.ScaleFactor
								
				If center 	Then x = x - (Self.StringWidth(text) / 2 * scale_x)
				If Rght 	Then x = x - (Self.StringWidth(text) * scale_x)
				
				If Len(text) < 1 Then Return
					
				Local a:Byte
				For a = 0 To Len(text) -1
			
					char = FindChar(Mid(text,a+1,1))
	
					If char >= 0 Then
						Local xpos		:Double = self.xPos[char]
						Local ypos		:Double = self.yPos[char]
						Local width		:Double = self.width[char]
						Local height	:Double = self.height[char]
?Win32
						Local DXFrame:TD3D7ImageFrame = TD3D7ImageFrame (self.Image.frame(0))
						If DXFrame
                			  	 DXFrame.setUV(xpos,ypos,xpos + width,ypos + height)
            				Else
?
                   			 	Local GLFrame:TGLImageFrame = TGLImageFrame(self.Image.frame(0))
                  					GLFrame.u0 = xpos
                    				GLFrame.v0 = ypos
                    				GLFrame.u1 = xpos + width
                    				GLFrame.v1 = ypos + height
?Win32
                			EndIf
?
						Local x1:Double = x +  self.xOffset[char] * scale_x
						Local y1:Double = y +  self.yOffset[char] * scale_y
					'	SetBlend(ALPHABLEND)
						DrawImageRect(self.Image,x1,y1,width * self.TextureSize * self.scalefactor,height * self.TextureSize * self.scalefactor)
						x :+ (self.xAdvance[char] * scale_x)
					EndIf
				Next
		End Method
		
		'----------------------------------------------------------------
		
		Method FindChar(digit:String)
			Local b:Int
			For b = 0 To self.NumChars
				If Asc(digit) = self.ID[b] Then Return b
			Next
		EndMethod
	
End Type


This is how you would use it:
Strict
Import Indiepath.bMapText

Graphics 640,480,0
SetClsColor(80,80,80)
Cls
SetBlend(alphablend)
Local text1:bMapText = bMapText.Create("fatbot",FILTEREDIMAGE|MIPMAPPEDIMAGE)
SetScale(0.4,0.4)
text1.Draw("Indiepath Ltd",320,280,True,False)
SetScale(0.35,0.35)
SetColor(255,255,155)
text1.Draw("Hit ESC to Exit",320,330,True,False)
Flip
WaitKey() 


And here is some stuff you really do need to read:
Generate Fonts using the BitMap Font Editor from www.AngelCode.com

You Must do the following to the generated .fnt file!

1) Replace the very first line with a Scale Factor, this is the scale factor that the module will reference

The First line will look something like :-
info face="Arial" size=32 bold=0 italic=0 charset="ANSI" stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1

Replace it with :-
scaleF=1.3

It will now look something like :-
scaleF=1.3
common lineHeight=64 base=57 scaleW=512 scaleH=512 pages=1
char id=32   x=0     y=0     width=1     height=0     xoffset=0     yoffset=64    xadvance=14    page=0 

2) Delete All references to Kerning, they appear after char id=255 ( we don't need these)


Finally *********************************************

***THE FONT IMAGE FILE MUST BE A .PNG**********	

That's all folks.