Rendering text on screen (bitmap font)

Advanced game related topics
mahan
Posts: 19
Joined: Sun Nov 15, 2015 9:44 pm

Rendering text on screen (bitmap font)

Post by mahan »

I've created a small lib for SpiderBasic to render text based on bitmap fonts on the active "Screen".

The project (with a small demo) is available here: https://github.com/mahan/bitmapfont

Since SpiderBasic does not support the command ScreenOutput() like in PureBasic for drawing operations, the only things that are drawable on a Screen (OpenScreen/OpenWindowedScreen) are sprites (DisplaySprite/DisplayTransparentSprite).

The lib basically adds the function DisplayText() to your program, which you can use during the Screen rendering to write out any text(s) you like on the screen in real time.
User avatar
MrTAToad
Posts: 291
Joined: Sun Apr 20, 2014 11:43 am
Location: Chichester, England
Contact:

Re: Rendering text on screen (bitmap font)

Post by MrTAToad »

What would be the best way to do this for variable width characters, where the character layout is stored in a separate file ?
User avatar
MrTAToad
Posts: 291
Joined: Sun Apr 20, 2014 11:43 am
Location: Chichester, England
Contact:

Re: Rendering text on screen (bitmap font)

Post by MrTAToad »

I've got the base system going for proportional bitmap font system, and as such it works well.

The main problem is how everything is loaded - it can either from a file (and get the user to select the correct file for dimensions), or either convert the bitmap to raw data, and put it, along with the dimension data into a datasection or load the graphic and then process the dimension data from a datasection.
mahan
Posts: 19
Joined: Sun Nov 15, 2015 9:44 pm

Re: Rendering text on screen (bitmap font)

Post by mahan »

MrTAToad wrote:I've got the base system going for proportional bitmap font system, and as such it works well.
Sounds useful. Is this something you'd care to share?
User avatar
MrTAToad
Posts: 291
Joined: Sun Apr 20, 2014 11:43 am
Location: Chichester, England
Contact:

Re: Rendering text on screen (bitmap font)

Post by MrTAToad »

The TTF to PNG program will be on my website soon (its just a modified version of Microsoft's routine), and the source can be here soon.

The good thing about this is that it should be able to handle up to 65535 characters.
User avatar
MrTAToad
Posts: 291
Joined: Sun Apr 20, 2014 11:43 am
Location: Chichester, England
Contact:

Re: Rendering text on screen (bitmap font)

Post by MrTAToad »

This is an example of the data produced from my TTF to PNG program :

Code: Select all

; Upgraded the TTF2BMP Microsoft project to allow proportional fonts to be used with SpiderBasic
; Modified by Nicholas Kingsley
DeclareModule hiscoreFont
  Declare.s OnInitialise()
EndDeclareModule

Module hiscoreFont
  Procedure.s OnInitialise()
    Restore hiscoreFont_Data
  EndProcedure

  DataSection
  hiscoreFont_Data:

  ; This is the filename of the graphics file
    Data.s "1,HiscoreText.png"
  ; Minimum character, maximum character, number of characters
    Data.s "2,32,127,95"
  ; Character, xpos, ypos, width, height
    Data.s "3,32,8,8,6,22"
    Data.s "3,33,22,8,5,22"
    Data.s "3,34,35,8,7,22"
    Data.s "3,35,50,8,14,22"
    Data.s "3,36,72,8,12,22"
    Data.s "3,37,92,8,17,22"
    Data.s "3,38,117,8,15,22"
    Data.s "3,39,140,8,5,22"
    Data.s "3,40,153,8,7,22"
    Data.s "3,41,168,8,7,22"
    Data.s "3,42,183,8,11,22"
    Data.s "3,43,202,8,13,22"
    Data.s "3,44,223,8,5,22"
    Data.s "3,45,236,8,8,22"
    Data.s "3,46,252,8,5,22"
    Data.s "3,47,265,8,9,22"
    Data.s "3,48,8,38,12,22"
    Data.s "3,49,28,38,8,22"
    Data.s "3,50,44,38,12,22"
    Data.s "3,51,64,38,12,22"
    Data.s "3,52,84,38,14,22"
    Data.s "3,53,106,38,12,22"
    Data.s "3,54,126,38,12,22"
    Data.s "3,55,146,38,12,22"
    Data.s "3,56,166,38,12,22"
    Data.s "3,57,186,38,12,22"
    Data.s "3,58,206,38,5,22"
    Data.s "3,59,219,38,5,22"
    Data.s "3,60,232,38,13,22"
    Data.s "3,61,253,38,13,22"
    Data.s "3,62,274,38,13,22"
    Data.s "3,63,295,38,11,22"
    Data.s "3,64,8,68,18,22"
    Data.s "3,65,34,68,14,22"
    Data.s "3,66,56,68,13,22"
    Data.s "3,67,77,68,13,22"
    Data.s "3,68,98,68,13,22"
    Data.s "3,69,119,68,12,22"
    Data.s "3,70,139,68,11,22"
    Data.s "3,71,158,68,13,22"
    Data.s "3,72,179,68,13,22"
    Data.s "3,73,200,68,5,22"
    Data.s "3,74,213,68,12,22"
    Data.s "3,75,233,68,13,22"
    Data.s "3,76,254,68,12,22"
    Data.s "3,77,274,68,16,22"
    Data.s "3,78,298,68,13,22"
    Data.s "3,79,319,68,13,22"
    Data.s "3,80,8,98,12,22"
    Data.s "3,81,28,98,13,22"
    Data.s "3,82,49,98,13,22"
    Data.s "3,83,70,98,14,22"
    Data.s "3,84,92,98,13,22"
    Data.s "3,85,113,98,13,22"
    Data.s "3,86,134,98,14,22"
    Data.s "3,87,156,98,19,22"
    Data.s "3,88,183,98,15,22"
    Data.s "3,89,206,98,15,22"
    Data.s "3,90,229,98,12,22"
    Data.s "3,91,249,98,7,22"
    Data.s "3,92,264,98,9,22"
    Data.s "3,93,281,98,7,22"
    Data.s "3,94,296,98,13,22"
    Data.s "3,95,317,98,11,22"
    Data.s "3,96,8,128,6,22"
    Data.s "3,97,22,128,10,22"
    Data.s "3,98,40,128,11,22"
    Data.s "3,99,59,128,11,22"
    Data.s "3,100,78,128,10,22"
    Data.s "3,101,96,128,11,22"
    Data.s "3,102,115,128,9,22"
    Data.s "3,103,132,128,10,22"
    Data.s "3,104,150,128,10,22"
    Data.s "3,105,168,128,5,22"
    Data.s "3,106,181,128,6,22"
    Data.s "3,107,195,128,10,22"
    Data.s "3,108,213,128,5,22"
    Data.s "3,109,226,128,15,22"
    Data.s "3,110,249,128,10,22"
    Data.s "3,111,267,128,11,22"
    Data.s "3,112,8,158,11,22"
    Data.s "3,113,27,158,10,22"
    Data.s "3,114,45,158,10,22"
    Data.s "3,115,63,158,11,22"
    Data.s "3,116,82,158,10,22"
    Data.s "3,117,100,158,10,22"
    Data.s "3,118,118,158,11,22"
    Data.s "3,119,137,158,15,22"
    Data.s "3,120,160,158,11,22"
    Data.s "3,121,179,158,11,22"
    Data.s "3,122,198,158,10,22"
    Data.s "3,123,216,158,9,22"
    Data.s "3,124,233,158,5,22"
    Data.s "3,125,246,158,9,22"
    Data.s "3,126,263,158,14,22"
    Data.s ""
  EndDataSection
EndModule
The actual bitmap printing is :

Code: Select all

  Procedure.b ProcessBitmapFonts(*loadingManager._LOADINGMANAGER)
    Define line.s
    Define code.s
    Define char.i
    Define mapName.s  = ""
    ;Define minCode.i,maxCode.i,char.i
    
    If *loadingManager<>#Null
    	If *loadingManager\bitmapFontInit<>#Null
        mapName=*loadingManager\bitmapFontInit()
        If Len(mapName)>0        
		      Read.s line
		      While Len(line)>0
		        If Left(line,1)<>";"
		          ; Ignore comments
		          code=StringField(line,1,",")
		          Select code
		            Case  "1" ; Graphic filename
		                        bitmapFonts(mapName)\spriteID=loadingManager()\index
		              
		            Case  "2" ; Range of characters
		                        bitmapFonts(mapName)\minChar=Val(StringField(line,2,","))
		                        bitmapFonts(mapName)\maxChar=Val(StringField(line,3,","))
		                        bitmapFonts(mapName)\numChars=bitmapFonts(mapName)\maxChar-bitmapFonts(mapName)\minChar
		                        Dim bitmapFonts(mapName)\chars(bitmapFonts(mapName)\numChars)
		                        
		            Case  "3" ; Data
		                        char=Val(StringField(line,2,","))-bitmapFonts(mapName)\minChar
		                        Debug "Char : "+Str(char)+" "+line
		                        If char>=0 And char<ArraySize(bitmapFonts(mapName)\chars())
		                          bitmapFonts(mapName)\chars(char)\x=Val(StringField(line,3,","))
		                          bitmapFonts(mapName)\chars(char)\y=Val(StringField(line,4,","))
		                          bitmapFonts(mapName)\chars(char)\w=Val(StringField(line,5,","))
		                          bitmapFonts(mapName)\chars(char)\h=Val(StringField(line,6,","))
		                        EndIf
		            EndSelect
		        EndIf
		        Read.s line
		      Wend
    
		      ProcedureReturn #True
		    EndIf
	    EndIf
    EndIf
    
    ProcedureReturn #False
  EndProcedure
  
  Procedure.i ProTextHeight(mapName.s,text.s,*callBack.bitmapFontCallBack=#Null)
    Define loop.i,one.i
    Define height.i
    Define bitmapInfo._BITMAPINFO
    
    height=0
    If Len(mapName)>0 And FindMapElement(bitmapFonts(),mapName)
      For loop=1 To Len(text)
        one=Asc(Mid(text,loop,1))-bitmapFonts(mapName)\minChar
        CopyStructure(bitmapFonts(mapName)\chars(one),@bitmapInfo\clip,RECT)
        
        bitmapInfo\scaleX=1.0
        bitmapInfo\scaleY=1.0
        
        If *callBack<>#Null
          callBack(one,#Null,@bitmapInfo)
        EndIf
        
        height=Routines::Max(bitmapInfo\clip\h*bitmapInfo\scaleY,height)
      Next
    EndIf
    
    ProcedureReturn height
  EndProcedure      
  
  Procedure.i ProTextWidth(mapName.s,text.s,*callBack.bitmapFontCallBack=#Null)
    Define loop.i,one.i
    Define width.i
    Define bitmapInfo._BITMAPINFO
    
    width=0
    If Len(mapName)>0 And FindMapElement(bitmapFonts(),mapName)
      For loop=1 To Len(text)
        one=Asc(Mid(text,loop,1))-bitmapFonts(mapName)\minChar
        CopyStructure(bitmapFonts(mapName)\chars(one),@bitmapInfo\clip,RECT)
        
        bitmapInfo\scaleX=1.0
        bitmapInfo\scaleY=1.0
        
        If *callBack<>#Null
          callBack(one,#Null,@bitmapInfo)
        EndIf
        
        width+Int(bitmapInfo\clip\w*bitmapInfo\scaleX)
      Next
    EndIf
    
    ProcedureReturn width
  EndProcedure  
    
  Procedure.b DrawBitmapFontString(mapName.s,text.s,x.i,y.i,colour.i,scaleX.f=1.0,scaleY.f=1.0,intensity.i=255,*callBack.bitmapFontCallBack=#Null)
    Define loop.i,size.i
    Define one.i
    
    If Len(mapName)>0
      size=Len(text)
      If size>0
        For loop=1 To size
          x+DrawBitmapFontChar(mapName,Asc(Mid(text,loop,1)),x,y,colour,scaleX,scaleY,intensity,*callBack)
        Next
      EndIf
    
      ProcedureReturn #True
    EndIf
    
    ProcedureReturn #False
  EndProcedure
  
  Procedure.i DrawBitmapFontChar(mapName.s,one.i,x.i,y.i,colour.i,scaleX.f=1.0,scaleY.f=1.0,intensity.i=255,*callBack.bitmapFontCallBack=#Null)
    Define index.i
    Define bitmapInfo._BITMAPINFO
    Define point.POINT
    ;Define clip.RECT
    ;Define tempColour
    ;Define tempScaleX.f,tempScaleY.f
    ;Define tempX.i,tempY.i
    
    If FindMapElement(bitmapFonts(),mapName)
      point\x=x
      point\y=y
    
      index=one-bitmapFonts(mapName)\minChar
      If index>=0 And index<ArraySize(bitmapFonts(mapName)\chars())
        CopyStructure(bitmapFonts(mapName)\chars(index),@bitmapInfo\clip,RECT)
        bitmapInfo\colour=colour
        bitmapInfo\scaleX=scaleX
        bitmapInfo\scaleY=scaleY
        bitmapInfo\intensity=intensity
        
        If *callBack<>#Null
          callBack(one,@point,@bitmapInfo)
        EndIf
        
        ClipSprite(bitmapFonts(mapName)\spriteID,bitmapInfo\clip\x,bitmapInfo\clip\y,bitmapInfo\clip\w,bitmapInfo\clip\h)
        DisplayTransparentSprite(bitmapFonts(mapName)\spriteID,point\x,point\y,bitmapInfo\intensity,bitmapInfo\colour)
        ProcedureReturn (bitmapInfo\clip\w*bitmapInfo\scaleX)
     EndIf
   EndIf
   
   ProcedureReturn 0
  EndProcedure
It will need upgrading so that other sprites can be used in place of certain characters - but that can come later.
poshu
Posts: 96
Joined: Mon Feb 24, 2014 11:46 pm

Re: Rendering text on screen (bitmap font)

Post by poshu »

I did my own, I'll post it here as soon as I can find some time to clean the code :
Image
User avatar
MrTAToad
Posts: 291
Joined: Sun Apr 20, 2014 11:43 am
Location: Chichester, England
Contact:

Re: Rendering text on screen (bitmap font)

Post by MrTAToad »

Will be interesting to see the code...
quartexNOR
Posts: 1
Joined: Wed Aug 21, 2019 1:34 am

Re: Rendering text on screen (bitmap font)

Post by quartexNOR »

You posted back in 2014 so the code should be immaculate by now or?
Post Reply