#rem header:This module contains the BitmapFont class. This class is the most important class in the FontMachine library as this class is, itself, a font. All FontMachine bitmap fonts are instances od a BitmapFont class. #end Import mojo.graphics Import mojo.app 'Import mojo.input Import fontmachine.fontmachine Import fontmachine.bitmapchar Import fontmachine.drawingrectangle Import fontinterface Import fontmachine.edrawalign private Import fontmachine.edrawmode public #rem summary:This class represents a BitmapFont. A BitmapFont is a font used to draw text on the graphics canvas. Usually, to load a FontMachine font in your game or application, all you have to do is: [code] Global myFont:BitmapFont = BitmapFont.Load("myfont.txt") myFont.DrawText("Hello world!",10,10) [/code][i](Obviously, you better see the complete source code samples)[/i] #end Class BitmapFont implements fmFont #rem summary:This function creates an instance of a BitmapFont class. The fontName parameter indicates the name of the txt file containing the font description (generated by the FontMachine editor). The second parameter indicates if the font should be loaded dynamically (only valid for non packed fonts). #end Function Load:BitmapFont(fontName:String, dynamicLoad:bool) Local font:= new BitmapFont(fontName, dynamicLoad) Return font End #rem summary:This is a BitmapFont class constructor. The fontDescriptionFilePath parameter indicates the name of the txt file containing the font description (generated by the FontMachine editor). The second parameter (dynamicLoad) indicates if the font should be loaded dynamically (only valid for non packed fonts). #end Method New(fontDescriptionFilePath:String, dynamicLoad:bool) local text:String = LoadString(fontDescriptionFilePath) if text = "" Then Print "FONT " + fontDescriptionFilePath + " WAS NOT FOUND!!!" LoadFontData(text, fontDescriptionFilePath, dynamicLoad ) End #rem summary:This is a BitmapFont class constructor. The fontDescriptionFilePath parameter indicates the name of the txt file containing the font description (generated by the FontMachine editor). #end Method New(fontDescriptionFilePath:String) local text:String = LoadString(fontDescriptionFilePath) if text = "" Then Print "FONT " + fontDescriptionFilePath + " WAS NOT FOUND!!!" LoadFontData(text, fontDescriptionFilePath, True ) End method #rem summary:Set this property to True or False to enable the font shadow. If the font has been rendered without a shadow, this property has no effect. [a ../sample programs/sample02.monkey]Load an example in Jungle Ide.[/a] #end Method DrawShadow:Bool() property Return _drawShadow End Method DrawShadow(value:Bool) property _drawShadow = value End #rem summary:Set this property to True or False to enable the font border. If the font has been rendered without a border, this property has no effect. [a ../sample programs/sample02.monkey]Load an example in Jungle Ide.[/a] #end Method DrawBorder:Bool() property Return _drawBorder End Method DrawBorder(value:Bool) property _drawBorder = value End #rem summary:this method will return the image associated to a given char on dynamic fonts. If the character image has not been loaded yet, this function will load it. #end Method GetFaceImage:Image(char:Int) if char>=0 And char0 Then Return packedImages[faceChars[char].packedFontIndex] if faceChars[char].CharImageLoaded() = false then faceChars[char].LoadCharImage() Return faceChars[char].image endif End Method #rem summary:this method will return the image associated to a given char border on dynamic fonts. If the character border image has not been loaded yet, this function will load it. #end Method GetBorderImage:Image(char:Int) if char>=0 And char0 Then Return packedImages[borderChars[char].packedFontIndex] if borderChars[char].CharImageLoaded() = false Then borderChars[char].LoadCharImage() Return borderChars[char].image endif End Method #rem summary:this method will return the image associated to a given char shadow on dynamic fonts. If the character shadow image has not been loaded yet, this function will load it. #end Method GetShadowImage:Image(char:Int) if char>=0 And char0 Then Return packedImages[shadowChars[char].packedFontIndex] If shadowChars[char].CharImageLoaded() = false Then shadowChars[char].LoadCharImage() Return shadowChars[char].image endif End Method #Rem summary: This function return the number of chars that have been created in the given bitmapfont. [b]Important:[/b]Notice that some chars can have null characters due them being just part of scape sequences, so be sure to check for <> null before accesing any character info by index. #End Method CharCount:Int() Return Self.faceChars.Length End #rem summary:This method allows you to draw a string on the graphics canvas. The first parameter is the string to be drawn The second and third parameters are the X and Y coordinates. The third parameter is a member of eDrawAlign and determines the aligment of the text to be drawn on the graphics canvas. This is a detailed example: [code] 'We import the required modules: Import mojo Import fontmachine 'Start the program: Function Main() New Tutorial End Class Tutorial extends App 'We create a BitmapFont variable called font. Our font will be loaded here: Field font:BitmapFont Method OnCreate() SetUpdateRate(60) 'We load the sample font (called bluesky) into our variable called font. 'The first parameter is the name (and path) of the font description file (txt file generated on the FontMachine editor) 'The second parameter indicates if the font glipths will be loaded dynamically (true) or statically (false). 'If the font characters are loaded dynamically, the application will load (and download on HTML5) only required characters. 'Otherwise, the full font will be required. For more information about dynamic or static fonts, see the documentation. font = New BitmapFont("bluesky/bluesky.txt", False) Print "Font loaded!" End Method OnRender() Cls(255,255,255) 'We just draw some text: font.DrawText("Hello world",210,10, eDrawAlign.CENTER) End Method OnUpdate() If KeyDown(KEY_A) Then font.Kerning.x-=.4 If KeyDown(KEY_D) Then font.Kerning.x+=.4 If KeyDown(KEY_W) Then font.Kerning.y-=.4 If KeyDown(KEY_S) Then font.Kerning.y+=.4 End End [/code][a ../sample programs/firstsample.monkey]Load this example in Jungle Ide.[/a] #end Method DrawText(text:String, x#, y#, align:Int) if DrawShadow Then DrawCharsText (text,x,y,eDrawMode.SHADOW, align ) if DrawBorder Then DrawCharsText (text,x,y,eDrawMode.BORDER, align ) DrawCharsText (text,x,y,eDrawMode.FACE ,align) End #rem summary:This method allows you to draw a string on the graphics canvas. This method is a simplified version of the DrawText command that asumes left aligment of text. #end Method DrawText(text:String, x#, y#) Self.DrawText(text,x,y,eDrawAlign.LEFT ) End #rem summary:This method returns the width in graphic units of the given string. You can see [a ../sample programs/sample03.monkey]a sample application that uses the GetTxtWidth function here.[/a] #end Method GetTxtWidth:Float(text:String) Return GetTxtWidth(text, 1, text.Length) End #rem summary:This method returns the width in graphic units of the given substring. This function will take fromChar and toChar parameters to calculate the substring metrics #end Method GetTxtWidth:Float(text:String, fromChar:Int, toChar:Int) Local twidth:Float Local MaxWidth:Float = 0 Local char:Int Local lastchar:Int = 0 For Local i:Int = fromChar To toChar char = text[i-1] If char >= 0 And char < faceChars.Length() and char<> 10 And char<>13 Then If faceChars[char] <> Null Then lastchar = char twidth = twidth + faceChars[char].drawingMetrics.drawingWidth + Kerning.x End If ElseIf char = 10 If Abs(MaxWidth)= 0 And lastchar < faceChars.Length() Then if lastchar = 32 then 'Do nothing. We let the spacing at the end of the string. ElseIf faceChars[lastchar] <> Null Then twidth = twidth - faceChars[lastchar].drawingMetrics.drawingWidth twidth = twidth + faceChars[lastchar].drawingMetrics.drawingSize.x End If End If If Abs(MaxWidth)=0 And char null Then Return faceChars[char].drawingMetrics Else Return null End End #rem summary:This method returns the drawing char info of the given border character. #end Method GetBorderInfo:BitMapCharMetrics(char:Int) if char>=0 And char null Then Return borderChars[char].drawingMetrics Else Return null End End #rem summary:This method returns the drawing char info of the given shadow character. #end Method GetShadowInfo:BitMapCharMetrics(char:Int) if char>=0 And char null Then Return shadowChars[char].drawingMetrics Else Return null End End #rem summary:This method returns the rectangle coordinates of the given char into the packed texture. This method returns phisical coordinates in the texture, in pixels. #end Method GetPackedFaceRectangle:DrawingRectangle(char:Int) if char>=0 And char=0 And char=0 And char0 then For local ch:BitMapChar = EachIn faceChars if ch<>null then ch.LoadCharImage() Next endif if borderChars.Length >0 then For local ch:BitMapChar = EachIn borderChars if ch<>null then ch.LoadCharImage() Next endif if shadowChars.Length >0 then For local ch:BitMapChar = EachIn shadowChars if ch<>null then ch.LoadCharImage() Next endif End #rem summary:This method will force a dynamic font to unload all its characters. #end Method UnloadFullFont() if faceChars.Length >0 then For local ch:BitMapChar = EachIn faceChars if ch<>null then ch.UnloadCharImage() Next endif if borderChars.Length >0 then For local ch:BitMapChar = EachIn borderChars if ch<>null then ch.UnloadCharImage() Next endif if shadowChars.Length >0 then For local ch:BitMapChar = EachIn shadowChars if ch<>null then ch.UnloadCharImage() Next endif End #rem summary:This method will force a dynamic font to load all the characters required to draw the given string on the graphics canvas. #end Method LoadCharsForText(text:String) For Local i:Int = 1 to text.Length Local char:Int = text[i-1] if char>=0 And char<=faceChars.Length Then If faceChars[char] <> null Then faceChars[char].LoadCharImage() EndIf if char>=0 And char<=borderChars.Length Then If borderChars[char] <> null Then borderChars[char].LoadCharImage() EndIf if char>=0 And char<=shadowChars.Length Then If shadowChars[char] <> null Then shadowChars[char].LoadCharImage() EndIf Next End #rem summary:This method will force a dynamic font to unload all the characters in the given string. #end Method UnloadCharsForText(text:String) For Local i:Int = 1 to text.Length Local char:Int = text[i-1] if char>=0 And char<=faceChars.Length Then If faceChars[char] <> null Then faceChars[char].UnloadCharImage() EndIf if char>=0 And char<=borderChars.Length Then If borderChars[char] <> null Then borderChars[char].UnloadCharImage() EndIf if char>=0 And char<=shadowChars.Length Then If shadowChars[char] <> null Then shadowChars[char].UnloadCharImage() EndIf Next End Private Field _drawShadow:Bool = true Field _drawBorder:Bool = true Field borderChars:BitMapChar[] Field faceChars:BitMapChar[] Field shadowChars:BitMapChar[] Method LoadFontData(Info:String, fontName:String, dynamicLoad:bool ) if Info.StartsWith("P1") Then LoadPacked(Info,fontName,dynamicLoad) return EndIf Local tokenStream:String[] = Info.Split(",") local index:Int = 0 borderChars = New BitMapChar[65536] faceChars = New BitMapChar[65536] shadowChars = New BitMapChar[65536] Local prefixName:String = fontName if prefixName.ToLower().EndsWith(".txt") Then prefixName = prefixName[..-4] Local char:Int = 0 while index text.Length Then endPos = text.Length end If align<>eDrawAlign.LEFT then Local lineSepPos:Int = text.Find(lineSep, startPos) if lineSepPos < 0 Then lineSepPos = text.Length Select align Case eDrawAlign.CENTER ; xOffset = Self.GetTxtWidth(text, startPos, lineSepPos) / 2 'Forcing an INT is a good idea to prevent drawing rounding artifacts... �? Case eDrawAlign.RIGHT ; xOffset = Self.GetTxtWidth(text, startPos, lineSepPos) End Select EndIf For Local i:Int = startPos to endPos 'text.Length Local char:Int = text[i-1] if char>=0 And char<=target.Length Then if char = 10 Then dry += Int(faceChars[32].drawingMetrics.drawingSize.y) + Kerning.y Self.DrawCharsText(text, oldX, dry, target, align, i + 1, endPos) return ElseIf target[char] <> null Then if target[char].CharImageLoaded() = false Then target[char].LoadCharImage() End if target[char].image <> null Then DrawImage(target[char].image,drx-xOffset,dry) ElseIf target[char].packedFontIndex > 0 Then DrawImageRect(packedImages[target[char].packedFontIndex],-xOffset+drx+target[char].drawingMetrics.drawingOffset.x,dry+target[char].drawingMetrics.drawingOffset.y,target[char].packedPosition.x,target[char].packedPosition.y,target[char].packedSize.x,target[char].packedSize.y) Endif drx+=faceChars[char].drawingMetrics.drawingWidth + Kerning.x endif Else ' Print "Char " + char + " out of scope." EndIf Next End Private Field _kerning:drawingpoint.DrawingPoint Public #rem summary: This property allows you to define additional kerning on a given bitmap font. By using this property, you set the horizonal and vertical kerning that has to be added on any draw operation. This information will be expressed in the form of a DrawingPoint instance. #end Method Kerning:drawingpoint.DrawingPoint() property if _kerning = null Then _kerning = New drawingpoint.DrawingPoint Return _kerning End Method Kerning:void(value:drawingpoint.DrawingPoint) property _kerning = value End End #rem footer:This FontMachine library is released under the MIT license: [quote]Copyright (c) 2011 Manel Ibanez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [/quote] #end