Draw String Custom Font

Forum for discussion about the documentation project.
Post Reply
sancho2
Posts: 547
Joined: May 17, 2015 6:41

Draw String Custom Font

Post by sancho2 »

One thing not talked about in the help for Draw String is the fact that the color magenta rgb(255, 0, 255) is not drawn.
For example the following source image is used to make a font:
Image
This is the code used to make the font. Note that I am using PSET as the drawing method parameter for the put command. So in theory the magenta areas in the zero and the 1 should show up magenta.

Code: Select all

Const As UByte FIRSTCHAR = &H30, LASTCHAR = &H39
Const As UByte NUMCHARS = (LASTCHAR - FIRSTCHAR) + 1

Dim As UByte Ptr p, myFont
Dim As Integer i
Dim As Any Ptr charImg, sourceimg
ScreenRes 800, 600, 32
Color , RGB(255,0,0)
cls

sourceimg = ImageCreate(360, 46)
charImg = ImageCreate(360, 47)
BLoad "..\snlnumbers.bmp", sourceimg

ImageInfo( charImg, , , , , p )

p[0] = 0
p[1] = FIRSTCHAR
p[2] = LASTCHAR
Put charImg, (0, 1), sourceimg, (0,0) - (359, 45),PSet
For i = FIRSTCHAR To LASTCHAR
'    '' Here we could define a custom width for each letter, 
    p[3 + i - FIRSTCHAR] = 36
Next i

Draw String (10, 10), "0172", , charImg 'myFont

BSave "font.bmp", charImg

ImageDestroy charImg
Sleep
The result shows that the magenta colored areas are transparent.
Image
I am not %100 sure this is a documentation issue. It may be incorrect behavior for the Draw String function (a bug?), since this virtually eliminates a color from being used.

I double checked that it is not my code that is causing this issue. I modified the sample code in the documentation for Draw String. I changed it so the custom font was created using the color magenta instead of multi-colors. None of the chars printed. But Draw String prints magenta colors just fine using the default font.
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: Draw String Custom Font

Post by dkl »

This form of transparency is a feature of some FB Screen modes (there is a default transparent color) and also of FB.Images created with ImageCreate() (which even has an optional parameter to change the transparent color). By default it's indeed the rgb(255,0,255) pink.

So it's not specific to Draw String, but applies to all the drawing functions, especially (or maybe only?!) when Put'ing an image to screen, which is basically what the custom Draw String function does. I only found few notes on this though: Internal graphics formats - Notes on transparency, Put (Graphics), Mask color, Trans (Put mode)
sancho2
Posts: 547
Joined: May 17, 2015 6:41

Re: Draw String Custom Font

Post by sancho2 »

Yes but it says magenta is always a transparent color for the Put modes that support transparency
PSET as is used by my code, does not support transparency and should have drawn the magenta pixels.
You can replicate this by simply using Put with an image of all magenta pixels and if you use the PSET option it wil show a magenta square.

Code: Select all

ScreenRes 800, 600, 32

Dim As Any Ptr img = ImageCreate(100,100, RGB(255,0,255))

Put (0,0), img, PSet
Sleep
Cls
Put (0,0), img, Trans

Sleep
So if I am drawing to the buffer used by draw string and using the PSET drawing method, those pixels should be there. There is no transparent operation occuring, unless there is some default transparency happening that is specifically draw string related.

I added the following line to my font creation code in the first post and it shows that the magenta pixels are in the font (image buffer)

Code: Select all

Put (0,0), charImg, PSet
It seems that Draw String uses some sort of default transparency in drawing the font to the screen. This is how the sample code can write text to the image buffer using a black background but the text background is transparent against any background color.
So maybe the draw string buffer is filled with magenta by default and then pixels of the font are added to it.

In the end, if this is desired behavior then a note in the documentation to warn against using magenta as a custom font color, or that Draw String uses this transparency operation in drawing custom fonts, would be wise.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Draw String Custom Font

Post by dodicat »

I created some basic fonts a few years back.
I cheated a bit in the pointer allocations (I have p as ubyte pointer in a 32 bit screen) --sub createfont.
I found the help files a bit vague back then, and there were hardly any forum examples for a tip or two.
However, although it draws a font pretty quickly, it is difficult to beautify the dos fonts.
Exampe (use font colours other than rgb(255,0,255)):

Code: Select all


'  FONTS
Function Filter(Byref tim As Ulong Pointer,_
    Byval rad As Single,_
    Byval destroy As Long=1,_
    Byval fade As Long=0) As Ulong Pointer
    #define map(a,b,_x_,c,d) ((d)-(c))*((_x_)-(a))/((b)-(a))+(c)
    If fade<0 Then fade=0:If fade>100 Then fade=100
    Type p2
        As Long x,y
        As Ulong col
    End Type
    #macro ppoint(_x,_y,colour)
    pixel=row+pitch*(_y)+(_x)*4
    (colour)=*pixel
    #endmacro
    #macro ppset(_x,_y,colour)
    pixel=row+pitch*(_y)+(_x)*4
    *pixel=(colour)
    #endmacro
    #macro average()
    ar=0:ag=0:ab=0:inc=0
    xmin=x:If xmin>rad Then xmin=rad
    xmax=rad:If x>=(_x-1-rad) Then xmax=_x-1-x
    ymin=y:If ymin>rad Then ymin=rad
    ymax=rad:If y>=(_y-1-rad) Then ymax=_y-1-y
    For y1 As Long=-ymin To ymax
        For x1 As Long=-xmin To xmax
            inc=inc+1 
            ar=ar+(NewPoints(x+x1,y+y1).col Shr 16 And 255)
            ag=ag+(NewPoints(x+x1,y+y1).col Shr 8 And 255)
            ab=ab+(NewPoints(x+x1,y+y1).col And 255)
        Next x1
    Next y1
    If fade=0 Then
        averagecolour=Rgb(ar/(inc),ag/(inc),ab/(inc))
    Else
        averagecolour=Rgb(fd*ar/(inc),fd*ag/(inc),fd*ab/(inc))
    End If
    #endmacro
    Dim As Single fd=map(0,100,fade,1,0)
    Dim As Integer _x,_y
    Imageinfo tim,_x,_y
    Dim  As Ulong Pointer im=Imagecreate(_x,_y)
    Dim As Integer pitch
    Dim  As Any Pointer row
    Dim As Ulong Pointer pixel
    Dim As Ulong col
    Imageinfo tim,,,,pitch,row
    Dim As p2 NewPoints(_x-1,_y-1)
    For y As Long=0 To (_y)-1
        For x As Long=0 To (_x)-1
            ppoint(x,y,col)
            NewPoints(x,y)=Type<p2>(x,y,col)
        Next x
    Next y
    Dim As Ulong averagecolour
    Dim As Long ar,ag,ab
    Dim As Long xmin,xmax,ymin,ymax,inc
    Imageinfo im,,,,pitch,row
    For y As Long=0 To _y-1
        For x As Long=0 To _x-1  
            average()
            ppset((NewPoints(x,y).x),(NewPoints(x,y).y),averagecolour) 
        Next x
    Next y
    If destroy Then Imagedestroy tim: tim = 0
    Function= im
End Function
Sub drawstring(Byval xpos As Long,Byval ypos As Long,Byref text As String,Byval colour As Ulong,Byval size As Single,Byref im As Any Pointer=0)
    Type D2
        As Double x,y
        As Ulong col
    End Type
    size=Abs(size)
    Static As d2 XY()
    Static As Long runflag
    If runflag=0 Then   
        Redim  XY(128,32 to 127)
        Screen 8
        Width 640\8,200\16 
        Dim As Ulong Pointer img
        Dim count As Long
        For ch As Long=32 To 127
            img=Imagecreate(9,17)
            Draw String img,(1,1),Chr(ch)
            For x As Long=1 To 8  
                For y As Long=1 To 16
                    If Point(x,y,img)<>0 Then
                        count=count+1
                        XY(count,ch)=Type<D2>(x,y)
                    End If 
                Next y
            Next x
            count=0
            Imagedestroy img
        Next ch
        runflag=1 
    End If
    If size=0 Then Exit Sub
    Dim As D2 np,t
    #macro Scale(p1,p2,d)
    np.col=p2.col
    np.x=d*(p2.x-p1.x)+p1.x
    np.y=d*(p2.y-p1.y)+p1.y
    #endmacro
    Dim As D2 c=Type<D2>(xpos,ypos)
    Dim As Long dx=xpos,dy=ypos,f
    If Abs(size)=1.5 Then f=3 Else f=2
    For z6 As Long=1 To Len(text)
        Var asci=text[z6-1]
        For _x1 As Long=1 To 64*2
            t=Type<D2>(XY(_x1,asci).x+dx,XY(_x1,asci).y+dy,colour)         
            Scale(c,t,size)
            If XY(_x1,asci).x<>0 Then 
                If size>1 Then 
                    Line im,(np.x-size/f,np.y-size/f)-(np.x+size/f,np.y+size/f),np.col,bf
                Else
                    Pset im,(np.x,np.y),np.col
                End If
            End If
        Next _x1
        dx=dx+8
    Next z6 
End Sub
Sub init Constructor 
    drawstring(0,0,"",0,0)
    Screen 0
End Sub
Function Colour(Byref im As Any Pointer,Byval newcol As Ulong,Byval tweak As Long,Byval fontsize As Single) As Any Pointer
    #macro ppset2(_x,_y,colour)
    pixel2=row2+pitch2*(_y)+(_x)*dpp2 
    *pixel2=(colour)
    #endmacro
    #macro ppoint(_x,_y,colour)
    pixel=row+pitch*(_y)+(_x)*dpp
    (colour)=*pixel
    #endmacro
    Dim As Long grade
    Select Case  fontsize
    Case 1 To 1.5:grade=205
    Case 2 :grade=225
    Case 2.5:grade=222
    Case 3 To 3.5:grade=200
    Case 4 To 4.5:grade=190
    Case 5 To 5.5:grade=165
    Case Else: grade=160
    End Select
    Dim As Integer w,h
    Dim As Integer pitch,pitch2,dpp,dpp2
    Dim  As Any Pointer row,row2
    Dim As Ulong Pointer pixel,pixel2
    Dim As Ulong col
    Imageinfo im,w,h,dpp,pitch,row
    Dim As Any Pointer temp=Imagecreate(w,h)
    Imageinfo temp,,,dpp2,pitch2,row2
    For y As Long=0 To h-1
        For x As Long=0 To w-1
            ppoint(x,y,col)
            Var v=.299*((col Shr 16)And 255)+.587*((col Shr 8)And 255)+.114*(col And 255)
            If v>(grade+tweak) Then 
                ppset2(x,y,newcol)
            Else
                ppset2(x,y,Rgb(255,0,255))
            End If
        Next x
    Next y
    Return temp
End Function

Sub CreateFont(Byref myfont As Any Pointer,Byval fontsize As Single,Byval col As Ulong,Byval tweak As Long=0)
    fontsize=Int(2*Abs(fontsize))/2
    If fontsize=0 Then fontsize=.5
    Dim As Ubyte Ptr p
    Dim As Any Pointer temp
    Dim As Integer i
    temp = Imagecreate(FontSize*768,FontSize*16)
    myfont=Imagecreate(FontSize*768,FontSize*16)
    For i = 32 To 127
        drawstring ((i-32)*FontSize*8,1,Chr(i),Rgb(255,255,255),FontSize,temp)
    Next i
    If fontsize>1.5 Then
        For n As Single=0 To fontsize-2:temp=filter(temp,1,1,0):Next
        End If
        temp=Colour(temp,col,tweak,fontsize)
        Put myfont,(0,0),temp,trans
        Imageinfo( myfont,i,,,, p )
        p[0]=0:p[1]=32:p[2]=127
        For i = 32 To 127
            p[3+i-32]=FontSize*8
        Next i
        Imagedestroy(temp)
    End Sub 
   
    
    Screen 20,32
    Dim As Any Ptr font,framerate,chars
    
    createfont font,2.5,Rgb(0,200,55),10
    createfont framerate,3,Rgb(255,0,0),5
    createfont chars,2,Rgb(255,255,255)
    
    function dos(s as long, e as long) as string
        dim as string g
        for n as long=s to e
            g+=chr(n)
        next n
        return g
    end function
    
    Function framecounter() As Integer
    dim as double t2=timer
    Static As Double t3,frames,answer
    frames=frames+1
    If (t2-t3)>=1 Then
        t3=t2
        answer=frames
        frames=0
    End If
    Return answer
End Function
dim as any ptr i=imagecreate(1024,768)
for n as long=0 to 768
    line i,(0,n)-(1024,n),rgb(n\4,0,255-n\4)
    next
    
    do
        screenlock
        cls
        put(0,0),i,pset
        draw string(5,50),"Chars 32 to 127:",,chars
        draw string(5,120),dos(32,64),,font
        draw string(5,160),dos(65,97),,font
        draw string(5,200),dos(98,127),,font
        draw string(5,300),"F.P.S. = " &(framecounter),,framerate
        draw string(5,400),"Any key to exit",,chars
        screenunlock
        sleep 1,1
        loop until len(inkey)
        
    sleep
    imagedestroy i
    
    
     
sancho2
Posts: 547
Joined: May 17, 2015 6:41

Re: Draw String Custom Font

Post by sancho2 »

sancho2 wrote:This is how the sample code can write text to the image buffer using a black background but the text background is transparent against any background color.
This statement of mine is not accurate. ImageCreate() without a color parameter creates buffer with the transparency color as fill. That is how the sample code implements transaparency.

@Dodicat:
I agree that there is not a lot of sample code for font creation and it took me actually sitting down and making one to get an idea of what was going on.
I don't understand exactly what you are showing me. Your code creates two enlarged font sets but there must be more to the story.

This is how I made my font:
I used a graphics editor to make my font. Its just MS Sans Serif font enlarged.

I decided on the size of font I needed and created an image of the size that would be large enough to hold the widest number with some added space to get separation.

I added a new layer to the image for each character and centered the char. Putting each char on its own layer allows you to show a single image at a time by turning off all the other layers.

Then I created another image the size I needed for ten numbers. I added some background lines to help me align the numbers I was pasting into the image.

I copied each char from the source image and pasted them into big image. Then saved the image as a bmp.

The only thing you have to do to that bmp to make it a font is to add the header (as stated in the docs for Draw String), and to add a char width for each char.
This means loading the bmp file into an image buffer enlarged by 1 in height. Load the image offset by 1 row of pixels. So the font buffer needs to be the size of the image + 1 row in height.

Add the three bytes required for the header as shown in the sample code. For my font they are all the same width so I just add the 10 bytes of width values right after the header. 1 byte for width per character. So I guess the largest size font you could have would be 255.

Its seems possible to write a program to eliminate much of the graphics work I did in creating a font.
I have thought about creating a font creation tool that would take a ttf and create a custom font for use with freebasic's Draw String command. It would be a big undertaking so not right now.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Draw String Custom Font

Post by dodicat »

Hi sancho2.
No more to story really.
Just experimenting with draw string.

Some windows fonts are too chunky for use in draw string (especially capitals), but others seem OK.
I have tried three types, Win10 has "source code pro", which seems apt, although in my case, the pro is redundant.
edit: some unused code removed.

Code: Select all



#include "windows.bi"
#include "fbgfx.bi"
Const FS_BOLD = 2
Const FS_ITALIC = 4 
'drawstring -- a deviation of code by Mysoft
Sub Drawstring(Byref BUFFER As Any Ptr=0,Byval POSX As Long, Byval POSY As Long, _
    Byref FTEXT As String, Byref FNAME As String,Byval FSIZE As Long, _
    Byval FCOLOR As Ulong=Rgb(255,255,255),Byval FSTYLE As Long=0,Byval CHARSET As Long=DEFAULT_CHARSET )
    
    Static FINIT As Long
    Static As hdc THEDC
    Static As hbitmap THEBMP
    Static As Any Ptr THEPTR
    Static As fb.image Ptr FBBLK
    Static As Long TXTSZ,RESU,RESUU
    Static As hfont THEFONT
    Static As Long FW,FI,TXYY
    Static DSKWND As hwnd, DSKDC As hdc
    Static MYBMPINFO As BITMAPINFO
    Static As TEXTMETRIC MYTXINFO
    Static As SIZE TXTSIZE
    Static As RECT RCT
    Static As Ubyte Ptr ubp
    ubp=Cptr(Ubyte Ptr,@FCOLOR)
    Swap ubp[0],ubp[2]
    Dim As Ubyte alphaval =ubp[3]
    ubp[3]=0
    #define FontSize(PointSize) -MulDiv(PointSize, GetDeviceCaps(THEDC, LOGPIXELSY), 72) 
    
    If FINIT = 0 Then   
        FINIT = 1   
        With MYBMPINFO.bmiheader
            .biSize = Sizeof(BITMAPINFOHEADER)
            .biWidth = 2048
            .biHeight = -513
            .biPlanes = 1
            .biBitCount = 32
            .biCompression = BI_RGB
        End With   
        DSKWND = GetDesktopWindow()
        DSKDC = GetDC(DSKWND)
        THEDC = CreateCompatibleDC(DSKDC)
        THEBMP = CreateDIBSection(THEDC,@MYBMPINFO,DIB_RGB_COLORS,@THEPTR,null,null)  
        ReleaseDC(DSKWND,DSKDC)   
    End If
    If (FSTYLE And FS_BOLD) Then FW = FW_BOLD Else FW = FW_NORMAL   
    If (FSTYLE And FS_ITALIC) Then FI = True Else FI = False   
    THEFONT = CreateFont(FontSize(FSIZE),0,0,0,FW,FI,0,0,CHARSET,0,0,0,0,Cast(Any Ptr,Strptr(FNAME)))   
    SelectObject(THEDC,THEBMP)
    SelectObject(THEDC,THEFONT)
    GetTextMetrics(THEDC,@MYTXINFO)
    GetTextExtentPoint32(THEDC,Strptr(FTEXT),Len(FTEXT),@TXTSIZE) 
    TXTSZ = TXTSIZE.CX
    TXYY = TXTSIZE.CY
    If (FSTYLE And FS_ITALIC) Then
        If MYTXINFO.tmOverhang Then
            TXTSZ += MYTXINFO.tmOverhang
        Else
            TXTSZ += 1+(FSIZE/2)
        End If
        TXYY += 1+(FSIZE/8)
    End If
    RCT.LEFT = 0
    RCT.TOP = 1
    RCT.RIGHT = TXTSZ
    RCT.BOTTOM = TXYY+1
    TXTSZ -= 1
    TXYY -= 1
    SetBkColor(THEDC,Rgba(255,0,255,0))
    SetTextColor(THEDC,FCOLOR)
    SystemParametersInfo(SPI_GETFONTSMOOTHING,null,@RESU,null)
    If RESU Then SystemParametersInfo(SPI_SETFONTSMOOTHING,False,@RESUU,null)
    ExtTextOut(THEDC,0,1,ETO_CLIPPED Or ETO_OPAQUE,@RCT,Strptr(FTEXT),Len(FTEXT),null)
    If RESU Then SystemParametersInfo(SPI_SETFONTSMOOTHING,True,@RESUU,null)
    FBBLK = THEPTR+(2048*4)-Sizeof(fb.image)
    FBBLK->Type = 7
    FBBLK->bpp = 4
    FBBLK->Width = 2048
    FBBLK->height = 512
    FBBLK->pitch = 2048*4
    Put BUFFER,(POSX,POSY),FBBLK,(0,0)-(TXTSZ-1,TXYY),Alpha,alphaval
    DeleteObject(THEFONT)
End Sub


Sub CreateFonts(Byref myfont As Any Pointer,fontsize As Long=8,col As Ulong,fnt As String="roman",style As Long=0)
    Dim As Ubyte Ptr p
    Dim As Integer i
    myfont=Imagecreate(FontSize*(127-31),FontSize*2)
    For i = 32 To 127
        drawstring (myfont,(i-32)*FontSize,1,Chr(i),fnt,fontsize,col,style)
    Next i
    Imageinfo( myfont,i,,,, p )
    p[0]=0:p[1]=32:p[2]=127
    For i = 32 To 127
        p[3+i-32]=fontsize
    Next i
End Sub 


Function dos(s As Long=32, e As Long=127) As String
    Dim As String g
    For n As Long=s To e
        g+=Chr(n)
    Next n
    Return g
End Function

Function framecounter() As Integer
    Dim As Double t2=Timer
    Static As Double t3,frames,answer
    frames=frames+1
    If (t2-t3)>=1 Then
        t3=t2
        answer=frames
        frames=0
    End If
    Return answer
End Function

Screen 20,32
Color ,Rgb(0,100,255)
Cls
Dim As Any Ptr f,f2,f3
createfonts f,30,Rgb(150,50,0),"source code pro",FS_BOLD
createfonts f2,45,Rgb(0,200,0),,FS_BOLD
createfonts f3,30,Rgb(0,0,0),"Courier New"
Do
    Screenlock
    Cls
    Draw String(10,50),dos(32,64),,f
    Draw String(10,100),dos(65,97),,f
    Draw String(10,150),dos(98,127),,f
    Draw String(10,300),"Fps = " &framecounter,,f2
    Draw String(10,500),"Any key to exit",,f3
    Screenunlock
    Sleep 1,1
Loop Until Len(Inkey)
Sleep
Boromir
Posts: 463
Joined: Apr 30, 2015 19:28
Location: Oklahoma,U.S., Earth,Solar System
Contact:

Re: Draw String Custom Font

Post by Boromir »

sancho2 wrote:
sancho2 wrote: Its seems possible to write a program to eliminate much of the graphics work I did in creating a font.
I have thought about creating a font creation tool that would take a ttf and create a custom font for use with freebasic's Draw String command. It would be a big undertaking so not right now.
There is a tool for that made.
The links are dead but the thread contains the code.
http://www.freebasic.net/forum/viewtopic.php?f=8&t=4805
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Draw String Custom Font

Post by dodicat »

Trial of loading font via bitmap.
1) create a temp folder and pop the two files into it.
2) Run the create bitmap code to produce a bitmap
3) Run the createfont code to use the bitmap for custom draw string.

EDIT faster createfonts.bas

createbitmap.bas

Code: Select all


#include "windows.bi"
#include "fbgfx.bi"
Const FS_BOLD = 2
Const FS_ITALIC = 4 
'drawstring -- a deviation of code by Mysoft
Sub Drawstring(Byref BUFFER As Any Ptr=0,Byval POSX As Long, Byval POSY As Long, _
    Byref FTEXT As String, Byref FNAME As String,Byval FSIZE As Long, _
    Byval FCOLOR As Ulong=Rgb(255,255,255),Byval FSTYLE As Long=0,Byval CHARSET As Long=DEFAULT_CHARSET )
    
    Static FINIT As Long
    Static As hdc THEDC
    Static As hbitmap THEBMP
    Static As Any Ptr THEPTR
    Static As fb.image Ptr FBBLK
    Static As Long TXTSZ,RESU,RESUU
    Static As hfont THEFONT
    Static As Long FW,FI,TXYY
    Static DSKWND As hwnd, DSKDC As hdc
    Static MYBMPINFO As BITMAPINFO
    Static As TEXTMETRIC MYTXINFO
    Static As SIZE TXTSIZE
    Static As RECT RCT
    Static As Ubyte Ptr ubp
    ubp=Cptr(Ubyte Ptr,@FCOLOR)
    Swap ubp[0],ubp[2]
    Dim As Ubyte alphaval =ubp[3]
    ubp[3]=0
    #define FontSize(PointSize) -MulDiv(PointSize, GetDeviceCaps(THEDC, LOGPIXELSY), 72) 
    
    If FINIT = 0 Then   
        FINIT = 1   
        With MYBMPINFO.bmiheader
            .biSize = Sizeof(BITMAPINFOHEADER)
            .biWidth = 2048
            .biHeight = -513
            .biPlanes = 1
            .biBitCount = 32
            .biCompression = BI_RGB
        End With   
        DSKWND = GetDesktopWindow()
        DSKDC = GetDC(DSKWND)
        THEDC = CreateCompatibleDC(DSKDC)
        THEBMP = CreateDIBSection(THEDC,@MYBMPINFO,DIB_RGB_COLORS,@THEPTR,null,null)  
        ReleaseDC(DSKWND,DSKDC)   
    End If
    If (FSTYLE And FS_BOLD) Then FW = FW_BOLD Else FW = FW_NORMAL   
    If (FSTYLE And FS_ITALIC) Then FI = True Else FI = False   
    THEFONT = CreateFont(FontSize(FSIZE),0,0,0,FW,FI,0,0,CHARSET,0,0,0,0,Cast(Any Ptr,Strptr(FNAME)))   
    SelectObject(THEDC,THEBMP)
    SelectObject(THEDC,THEFONT)
    GetTextMetrics(THEDC,@MYTXINFO)
    GetTextExtentPoint32(THEDC,Strptr(FTEXT),Len(FTEXT),@TXTSIZE) 
    TXTSZ = TXTSIZE.CX
    TXYY = TXTSIZE.CY
    If (FSTYLE And FS_ITALIC) Then
        If MYTXINFO.tmOverhang Then
            TXTSZ += MYTXINFO.tmOverhang
        Else
            TXTSZ += 1+(FSIZE/2)
        End If
        TXYY += 1+(FSIZE/8)
    End If
    RCT.LEFT = 0
    RCT.TOP = 1
    RCT.RIGHT = TXTSZ
    RCT.BOTTOM = TXYY+1
    TXTSZ -= 1
    TXYY -= 1
    SetBkColor(THEDC,Rgba(255,0,255,0))
    SetTextColor(THEDC,FCOLOR)
    SystemParametersInfo(SPI_GETFONTSMOOTHING,null,@RESU,null)
    If RESU Then SystemParametersInfo(SPI_SETFONTSMOOTHING,False,@RESUU,null)
    ExtTextOut(THEDC,0,1,ETO_CLIPPED Or ETO_OPAQUE,@RCT,Strptr(FTEXT),Len(FTEXT),null)
    If RESU Then SystemParametersInfo(SPI_SETFONTSMOOTHING,True,@RESUU,null)
    FBBLK = THEPTR+(2048*4)-Sizeof(fb.image)
    FBBLK->Type = 7
    FBBLK->bpp = 4
    FBBLK->Width = 2048
    FBBLK->height = 512
    FBBLK->pitch = 2048*4
    Put BUFFER,(POSX,POSY),FBBLK,(0,0)-(TXTSZ-1,TXYY),Alpha,alphaval
    DeleteObject(THEFONT)
End Sub


Screen 19,32

Const fixedfontsize=80 ' can make a little bigger - optional
Dim fnt As String="Courier New" 'can use a different font -- optional
Var style=0     'FS_BOLD  'FS_ITALIC

Dim As Ulong col=Rgb(255,255,255)
Dim As Any Ptr myfont=Imagecreate(fixedfontsize*(127-31),fixedfontsize*2)
For i As Long = 32 To 127
    drawstring (myfont,(i-32)*fixedfontsize,1,Chr(i),fnt,fixedfontsize,col,style)
Next i
Bsave("Normal "+fnt+".bmp",myfont)
print "done, press a key"
sleep 
createfont.bas

Code: Select all


#include "file.bi"

Sub CreateFonts(Byref myfont As Any Pointer,fontsize As Long=8,col As Ulong,fnt As String=".bmp")
    if fileexists(fnt)=0 then print fnt + " not found":sleep: end
    
    #macro ppoint(_x,_y,colour)
    pixel=row+pitch*(_y)+(_x)*4
    (colour)=*pixel
    #endmacro
    
    #macro ppset(_x,_y,colour)
    pixel=row+pitch*(_y)+(_x)*4
    *pixel=(colour)
    #endmacro 
    
  #macro Size(bmp,h)
    Open bmp For Binary access read As #1
    Get #1, 23, b
    Close #1
    h=b
  #endmacro

  #macro dil(pivotx,pivoty,px,py,scale)
  rx=scale*((px-pivotx))+pivotx
  ry=scale*((py-pivoty))+pivoty
  #endmacro
  
    Dim As Integer pitch
    Dim  As Any Pointer row
    Dim As Ulong Pointer pixel
    
dim as long sz,b
size(fnt,sz)
 sz=sz/2
    Dim As Ubyte Ptr p
    Dim As Integer i,rx,ry
    Dim As Single f=fontsize/sz
    dim as any ptr  myfont2=Imagecreate(sz*(127-31),sz*2)
    Imageinfo myfont2,,,,pitch,row
    myfont=Imagecreate(fontsize*(127-31),fontsize*2)
    Bload fnt,myfont2
    Dim As Ulong clr,white=Rgba(255,255,255,0)
    For y As Long=0 To sz*2-1
        For x As Long=0 To sz*(127-31)-1
            ppoint(x,y,clr)
           ' clr=Point(x,y,myfont2)
            If clr=white Then: ppset(x,y,col):end if'Pset myfont2,(x,y),col
            dil(0,0,x,y,f)
            ppoint(x,y,clr)
           ' ppset2(cint(rx),cint(ry),clr)
            Pset myfont,(rx,ry),clr'Point(x,y,myfont2)
        Next x
    Next y
    Imageinfo( myfont,i,,,, p )
    p[0]=0:p[1]=32:p[2]=127
    For i = 32 To 127
        p[3+i-32]=fontsize
    Next i
    Imagedestroy myfont2
End Sub 


'example, using the created bitmap
screenres 900,500,32
Dim As Any Ptr f,g
createfonts f,40,Rgb(0,200,0),"Normal Courier New.bmp"
createfonts g,50,Rgb(200,0,0),"Normal Courier New.bmp"

do
    screenlock
    cls
Draw String(20,200),"Hello World!",,g
Draw String(20,400),Str(Timer),,f
screenunlock
sleep 1,1
loop until len(inkey)

Sleep
 
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Draw String Custom Font

Post by MrSwiss »

@dodicat,

tried your new code. With "normal" everything is OK.
With either "italic" or "bold" the "W" is partially overwritten, by the "X".
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Draw String Custom Font

Post by dodicat »

Thanks for the test Mr Swiss.
You are correct, only some of the many win 10 types of font are suitable for draw string.
Some bold uppercase actually take up two spaces -- looks like anyway.
- and Italics have a serious lean over their neighbours.

Writing "Hello World! is a good test.
If the W is written fully then the font should be suitable.
Maybe fiddling with the bmp header might fix this, but a ubyte pointer leaves little room for a workaround.

Thanks again.
sancho2
Posts: 547
Joined: May 17, 2015 6:41

Re: Draw String Custom Font

Post by sancho2 »

Boromir wrote:There is a tool for that made.
The links are dead but the thread contains the code.
http://www.freebasic.net/forum/viewtopic.php?f=8&t=4805
That tool works well. Thanks.
I made it into an exe and use it in FBEdit as another tool.
Post Reply