Custom Fonts With Foreground/Background Colors

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
Destructosoft
Posts: 88
Joined: Apr 03, 2011 3:44
Location: Inside the bomb
Contact:

Custom Fonts With Foreground/Background Colors

Postby Destructosoft » Feb 09, 2012 9:15

A tutorial by Destructosoft
---------------------------
Last modified 20120209

Any Draw String type font, in PNG/BMP/TGA format, can be changed to a PNG which will allow it to be drawn with
any foreground and background color just like with the built-in FB font. Here's how to make it
happen:

-Have FBPNG.BI included as usual. If you don't know how to include it, there are tutorials
elsewhere that explain this, but there is a simple way to make it work:
--Copy the FBPNG folder into the project folder
--Find LIBFBPNG.A in the FBPNG folder and put a copy of it into the project folder
--Add the line in your main program:

Code: Select all

#Include "fbpng/inc/fbpng.bi"


-Load the font file in the normal way (using BLOAD, PNG_LOAD or TGA_LOAD or whatever you use).
Assume the ANY PTR or UBYTE PTR is named FONT.

-Add some lines to define a type and dimension some variables:

Code: Select all

Union pixel
  c As UInteger
  Type
    r As UByte
    g As UByte
    b As UByte
    a As UByte
  End Type
End Union

Dim as pixel px
dim as short t,x,xx,y,yy


-Make sure the program knows the height and width of the font graphic. Set XX=width and YY=height.

-Add the following code:

Code: Select all

For y=1 To yy-1
  'Y starts at 1 so as not to disturb the character width data
  For x=0 To xx-1
    px.c=Point(x,y,font)
    t=(px.r+px.g+px.b)\3 'guarantees correct alpha value
    px.r=255:px.g=255:px.b=255 'sets all pixels to white
    px.a=t
    Pset font,(x,y),px.c
  Next
Next


-After this code, add the following code which saves the data as a new file. Avoid overwriting
the old font data until you are sure it works. Also remember to follow these lines with an
IMAGEDESTROY or PNG_DESTROY() or whatever you need to prevent memory leaks.

Code: Select all

t=png_save("newfont.png",font)
if t<>0 then print"Cannot save file"
sleep


-If it saved correctly, NEWFONT.PNG will be the old font with a transparency. Every single pixel
will be white, which is important. If any transparent pixel isn't white it will mess up the
background color.

-Now we can use the font. Here is my code I use.
--I am using two fonts (UBYTE PTR images), FONT16 and FONT32. Both are variable width, and I have
stored two BYTE arrays, F16(32 to 127) and F32(32 to 127) which contain the widths of each
character in the two fonts.
--I also use an ANY PTR called TEXTAREA which is an image 32 pixels tall and the same width as the
display screen. TEXTAREA is used as a workspace for the text generation.
--The TEXT() subroutine is what you call to draw text on the screen.
---Notice the size and colors have defaults. Based on the order of the elements, if you need to
specify the size, you must specify both colors. This can be fixed by changing the order of
the elements.
--The TLEN() function determines the width of the string when using a certain font.

Code: Select all

Declare Sub text(As String,As Short,As Short,As UInteger=Rgb(255,255,255),As UInteger=Rgb(0,0,0),As Byte=16)
Declare Function tlen(As String,As Byte=16)As Short

Sub text(a0 As String,x As Short,y As Short,c0 As UInteger=Rgb(255,255,255),c1 As UInteger=Rgb(0,0,0),t As Byte=16)
'a0=text x,y=coordinate c0=foreground c1=background t=size u=length
Dim As Short u=tlen(a0,t)
  Line textarea,(0,0)-(u-1,t-1),c0,bf
  Select Case t
  Case 16:Draw String textarea,(0,0),a0,,font16,And
  Case 32:Draw String textarea,(0,0),a0,,font32,And
  End Select
  Screenlock
    Line(x,y)-(x+u-1,y+t-1),c1,bf
    Put(x,y),textarea,(0,0)-(x+u-1,y+t-1),alpha
  Screenunlock
End Sub

Function tlen(a0 As String,b As Byte=16)As Short
Dim As Short t,u=0
  If a0=""Then Return 0
  For t=0 To Len(a0)-1
    If b=16 Then u+=f16(a0[t]) Else u+=f32(a0[t])
  Next
  Return u
End Function


-And here is an example of the use of TEXT() in a 1024x768 screen:

Code: Select all

Cls
For t=0 To 736 Step 32
  c(0)=Rgb(Int(Rnd*256),Int(Rnd*256),Int(Rnd*256))
  c(1)=Rgb(Int(Rnd*256),Int(Rnd*256),Int(Rnd*256))
  text("Jackdaws love my big sphinx of quartz.",0,t,c(0),c(1),32)
Next
Sleep


-Again, remember to use PNG_DESTROY().

-One final optional step: I like running all my PNG files through an optimizer such as PNGOUT so
they will take the least drive space. Any changes made to an optimized PNG, such as was done in
this tutorial, make it need to be reoptimized. With my FONT16 and FONT32 I used when writing
this, I only saved 3020 bytes, so it isn't always necessary.

-To make TEXT() work more like PRINT and have screen scrolling and word wrapping, you need another
subroutine, which I call TPRINT(). It moves a text array's data up line by line and adds new
lines on the bottom. This is excellent for games. I leave it to the reader to explore the
possibilities.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest