3 text heights without #include

New to FreeBASIC? Post your questions here.
Post Reply
nosfera2
Posts: 6
Joined: Oct 05, 2019 21:44

3 text heights without #include

Post by nosfera2 »

Hi all. I'm not a raw beginner but there's still loads I don't know. This is 122 lines of code that gets text in 3 different heights (8, 14 and 16) on the screen at the same time, without any #include statements. I don't suppose anyone needs it, but maybe there's some use I haven't thought of. I just figured it out because I had dependency fatigue, after spending two weeks failing to get C++ to work.

Code: Select all

Declare Function MakeImageOfASCIIchars (charHeight as uinteger, r as uinteger, g as uinteger, b as uinteger) As Any Ptr
Declare Function MakeImageOfString (charHeight as uinteger, r as uinteger, g as uinteger, b as uinteger, tx as string) As Any Ptr
Declare Sub TextH8(x as uinteger, y as uinteger, tx as string)
Declare Sub TextH14(x as uinteger, y as uinteger, tx as string)

Const screenW = 800  ' Must be divisible by 8.
' Must be divisible by 16 for characters 16 pixels high; by 14 for characters 16 pixels high; by 112 to have both.
Const screenD = 448

ScreenRes screenW, screenD, 32, 1  ' Just 1 screen, to keep it simple.
'Usually you'd set "32, 2" for 2 screens, then something like "screenset 1, 0" (for screen 1 'work', screen 0 visible).

Dim shared as uinteger numChrs, charWidth = 8
Dim shared as uinteger codeF1, codeT1  ' Codes for first and last non-blank ASCII characters.
Dim as uinteger i
Dim as integer p, q, r
Dim as string t

codeF1 = 1  ' Code of first non-blank ASCII character.
codeT1 = 254  ' Code of last non-blank ASCII character.
numChrs = codeT1 - codeF1 + 1

' MAKE THE IMAGES (make all of them before using any of them).

'Make an image with every non-blank ASCII symbol, 8 pixels high.
Dim shared As Any Ptr imChars8
imChars8 = MakeImageOfASCIIchars(8, 0, 32, 0)

'Make an image with every non-blank ASCII symbol, 14 pixels high.
Dim shared As Any Ptr imChars14
imChars14 = MakeImageOfASCIIchars(14, 0, 0, 112)  ' Args: character height (8 or 14), r,g,b (color).

' Put a string into an image, while set for character height 8.
Dim shared As Any Ptr imString8
' Args: character height, r,g,b, string
imString8 = MakeImageOfString (8, 0, 0, 176, "This string was put into an image while character height was 8.")

' Put a string into an image, while set for character height 14.
Dim shared As Any Ptr imString14_1
imString14_1 = MakeImageOfString (14, 192, 96, 0, "This string was put into an image while character height was 14.")

' and another string ...
Dim shared As Any Ptr imString14_2
imString14_2 = MakeImageOfString (14, 192, 96, 0, "Just displaying a whole image is probably faster than fishing a series of characters out of it.")

' The images must be set up (as above) before the last width instruction, which sets the character height to 16.

color RGB(0, 0, 0), RGB(247, 255, 192)  ' The following "width" will wipe the screen, with the background color.
width screenW/8, screenD/16  ' To make normal text 16 pixels high.

draw string (10, 20), "This text is 16 pixels high (it's all 8 pixels wide).", RGB(0, 128, 0)
draw string (10, 40), "It's shown using the standard Freebasic 'draw string'.", RGB(0, 128, 0)

TextH8 (10, 70, "This text is 8 pixels high (and 8 pixels wide), shown using 'TextH8'.")

TextH14 (10, 100, "This text is 14 pixels high (and 8 pixels wide), shown using TextH14.")

draw string (10, 140), "TextH8 and TextH14 lookup a little image for each character,", RGB(128, 64, 0)
draw string (10, 160), "which might be too slow somethimes.", RGB(128, 64, 0)

put (10, 210), imString8, Alpha  ' "This string was put ... height was 8."
put (10, 240), imString14_1, Alpha  ' "This string was put ... height was 14."
put (10, 270), imString14_2, Alpha  ' "Just displaying the whole image is ... "
draw string (10, 300), "No need to put height-16 text into an image.", RGB(0, 92, 128)

circle (240, 400), 15  ' Just to show you can get standard graphics on the screen.

draw string (40, 340), "ASCII characters, height 14, in reverse order ==>", RGB(220, 0, 10)

for p = 7 to 0 step -1
    t = ""
    for q as integer = 31 to 0 step -1
        r = p * 32 + q
        if r > 0 then t += chr(r)
    next
    TextH14 (480, 300 + (7 - p) * 16, t)
next

sleep

' Making images of text.

Function MakeImageOfASCIIchars (charHeight as uinteger, r as uinteger, g as uinteger, b as uinteger) As Any Ptr
    Dim As Any Ptr imChars
    Dim as uinteger i
    width screenW/charWidth, screenD/charHeight  ' A strange instruction that sets char width and height.
    imChars = ImageCreate( charWidth*numChrs + 1, charHeight, RGBA(255, 0, 255, 0) ) ' Magenta for mask.
    for i = codeF1 to codeT1  ' Loop to slot image of each character into the wide image.
        ' I don't know why the "+ 1" is needed (and also in Sub TextH8), but without it there are unwanted pixels.
        draw string imChars, ((i-codeF1)*charWidth + 1, 0), chr(i), RGB(r, g, b)
    next
    return imChars  ' Returns a pointer to the image of the 8-high ASCII characters.
End Function

Function MakeImageOfString (charHeight as uinteger, r as uinteger, g as uinteger, b as uinteger, tx as string) As Any Ptr
    Dim As Any Ptr imString
    width screenW/charWidth, screenD/charHeight  ' A strange instruction that sets char width and height.
    imString = ImageCreate( charWidth*len(tx), charHeight, RGBA(255, 0, 255, 0) ) ' Magenta for mask.
    draw string imString, (0, 0), tx, RGB(r, g, b)
    return imString  ' Returns a pointer to the image of the 8-high ASCII characters.
End Function

'Using the images to show text.

Sub TextH8(x as uinteger, y as uinteger, tx as string)  ' Height 8 pixels.
    Dim as uinteger c, i, len_tx
    len_tx = len(tx)
    for i = 1 to len_tx
        c = asc(mid(tx, i, 1))
        Put (x + (i-1)*8, y), imChars8, ((c-1)*8 + 1, 0)-(c*8, 7), Alpha
        ' "Alpha" is to not print the background (also needs "Magenta for mask" (find above).
    next
End Sub

Sub TextH14(x as uinteger, y as uinteger, tx as string)  ' Height 14 pixels.
    Dim as uinteger c, i, len_tx
    len_tx = len(tx)
    for i = 1 to len_tx
        c = asc(mid(tx, i, 1))
        Put (x + (i-1)*8, y), imChars14, ((c-1)*8 + 1, 0)-(c*8, 13), Alpha
    next
End Sub
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: 3 text heights without #include

Post by D.J.Peters »

"All roads lead to Rome" but some are shorter as the others :-)

Sorry if this code does not meets your needs !
It's only for fun.

Joshy

Code: Select all

type FBFont
  as long      w,h
  as ubyte ptr b
end type
extern GFXFonts(2) alias "__fb_font" as FBFont

enum : FONT_8, FONT_14, FONT_16 : end enum

sub InitFonts(ImgFonts() as any ptr)
  if screenptr()=0 then 
    open err for output as #99
    print #99,"fatal error: no active gfx screen !"
    close #99
    beep : sleep :end 1
  end if
  dim as integer bytes
  dim as ulong FC,BC ' colors
  screeninfo ,,,bytes
  select case as const bytes
  case 1 : FC=&H00000F : BC=&H000000
  case 2 : FC=&H00FFFF : BC=&H00F81F
  case 4 : FC=&HFFFFFF : BC=&HFF00FF
  end select
  for f as integer = 0 to 2
    ImgFonts(f) = ImageCreate(GFXFonts(f).w*256,GFXFonts(f).h+1)
    dim as integer ImgPitch
    dim as ubyte ptr ImgRow,ImgPixels
    dim as ubyte FntBits,FntMask
    ImageInfo(ImgFonts(f),,,,ImgPitch,ImgPixels)
    ImgPixels[0] =  0 ' version of custom font's
    ImgPixels[1] =  0 ' first char in font image
    ImgPixels[2] =255 ' last  char in font image
    ImgRow = ImgPixels : ImgRow+=ImgPitch
    for iChar as integer = 0 to 255 
      ImgPixels[3+iChar] = GFXFonts(f).w
      for iRow as integer = 0 to GFXFonts(f).h-1
        FntBits = GFXFonts(f).b[iChar*GFXFonts(f).h+iRow]
        FntMask = 1
        for iBit as integer = 0 to 7
          PSet ImgFonts(f),(iChar*GFXFonts(f).w+iBit,1+iRow),iif(FntBits and FntMask,FC,BC)
          FntMask shl=1
        next  
      next
    next
  next
end sub  
'
' main
'
ScreenRes 640,480
dim as any ptr Fonts(FONT_16)
InitFonts(Fonts())
draw string (10,10),"Font  8",,Fonts(FONT_8)
draw string (10,18),"Font 14",,Fonts(FONT_14)
draw string (10,32),"Font 16",,Fonts(FONT_16)
sleep
nosfera2
Posts: 6
Joined: Oct 05, 2019 21:44

Re: 3 text heights without #include

Post by nosfera2 »

Thanks for that. There isn't much of it I understand, so I might be more of a raw beginner than I thought. I managed to change the color to yellow on blue (just to know I could change the color). I hadn't come across "iif" before, and it will be useful for keeping the line-count down a bit.
nosfera2
Posts: 6
Joined: Oct 05, 2019 21:44

Re: 3 text heights without #include

Post by nosfera2 »

I got my code down to 52 lines, with the same output as yours. But it's not worth posting, because I can think of three reasons why your code is better.

1) It doesn't clear the screen.
2) It doesn't restrict the width of the screen to multiples of 14 and 16 (i.e. of 112).
3) 'Draw string' should be very well tested by now, e.g. for strings that go off the screen (and it's probably faster than my loops).

So thanks again for your code.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: 3 text heights without #include

Post by dodicat »

Another method for fun.
Using your ascii blocks, re spaced a bit

Code: Select all

 Type D2
    As Long x,y
    As Ulong col
End Type
Sub drawstring(xpos As Long,ypos As Long,text As String,colour As Ulong,xy() As D2,n As Long=0,im As Any Pointer=0)
    Static As Long loading
    If loading<3 Then
        If Screenptr=0 Then Screen 8,,,-1
        Width 640\8,200\n
        Dim count As Long
        For ch As Long=1 To 256
            Cls
            Draw String (1,1),Chr(ch)
            For x As Long=1 To 8
                For y As Long=1 To n
                    If Point(x,y)<>0 Then count+=1: XY(count,ch)=Type(x,y)
                Next y
            Next x
            count=0
        Next ch
        loading+=1
    End If
    Dim As D2 c=(xpos,ypos),t,cpt(1 To ubound(xy,1))
    For n As Long=1 To Len(text)
        Var asci=text[n-1]
        For _x1 As Long=1 To ubound(xy,1)
            t=Type(XY(_x1,asci).x+xpos,XY(_x1,asci).y+ypos,colour)
            cpt(_x1)= Type((t.x-c.x)+c.x,(t.y-c.y)+c.y,t.col)
            If XY(_x1,asci).x<>0 Then Pset im,(cpt(_x1).x,cpt(_x1).y),cpt(_x1).col
        Next _x1
        xpos+=8
    Next n
End Sub
Redim As d2 size8(64,256),size14(112,256),size16(128,256)
drawstring(0,0,"",0,size8(),8)
drawstring(0,0,"",0,size14(),14)
drawstring(0,0,"",0,size16(),16)
'=========== done  ==============

' main
Screen 20
color ,15
cls

for z as long=1 to 3
for p as long= 7 to 0 step -1
   var t = ""
    for q as long = 31 to 0 step -1
       var r = p * 32 + q
        if r > 0 then t += chr(255-r)
    next
   if z=1 then drawstring(100, 200 + (7 - p) * (8+2), t,0,size8())
   if z=2 then drawstring(400, 200 + (7 - p) * (14+2), t,4,size14())
   if z=3 then drawstring(700, 200 + (7 - p) * (16+2), t,2,size16())
next
next z
drawstring(100,150,"Eight",0,size8())
drawstring(400,150,"Fourteen",4,size14())
drawstring(700,150,"Sixteen",2,size16())


drawstring(20,700,"Press a key to end  . . .",8,size16())

Sleep
 
nosfera2
Posts: 6
Joined: Oct 05, 2019 21:44

Re: 3 text heights without #include

Post by nosfera2 »

I hope 161 lines of daftness are allowed. It isn't tested much, I just fine tuned things to get what you see.

Code: Select all

' The Type makes it easier to set params for Candle14.
' There isn't much logic about what's in the type, in the other params, and set in the Sub.
Type candle
    as uinteger cellW, cellD  ' Cell width & depth are the separation between cells.
    as uinteger bOffsetX, bOffsetY, bWidth, bDepth  ' For drawing a tall white box, for the candle.
    as uinteger fcOffsetX, fcOffsetY, fcRad  ' For drawing 'circle' (ellipse) for flame.
    as single fcAsp  ' Aspect ratio of 'circle'.
    as uinteger wOffsetX, wOffsetY, wWidth, wDepth  ' Wick.
    as uinteger rand  ' Pixels of random variation in height of candle. Other variation is derived from it.
End type

Declare Function MakeImageOfASCIIchars (charHeight as uinteger, r as uinteger, g as uinteger, b as uinteger) As Any Ptr
Declare Sub Candle14 (ca as candle, x as uinteger, y as uinteger, skew as integer, tx as string)
Declare Sub SpaceOut14(x as uinteger, y as uinteger, sepX as uinteger, sepY as uinteger, _
    r as uinteger, g as uinteger, b as uinteger, tx as string)

Randomize

Const screenW = 600  ' Must be divisible by 8.
Const screenD = 462  ' Must be divisible by 14.

ScreenRes screenW, screenD, 32, 2  ' 2 screens.
ScreenSet (1, 0)  ' 1 work, 0 visible.

Dim shared as uinteger charWidth = 8

'Make an image with every non-blank ASCII symbol, 14 pixels high.
Dim shared As Any Ptr imChars14
imChars14 = MakeImageOfASCIIchars(14, 0, 0, 112)  ' Args: character height (8 or 14), r,g,b (color).

' Set values for a candle. There will be one candle for each pixel in a character.
Dim as candle can
can.cellW = 30  ' Cell (space the other stuff is in)
can.cellD = 28
can.bOffsetX = 6  ' Box (drawn for the candle body)
can.bOffsetY = 14
can.bWidth = 4
can.bDepth = 20
can.fcOffsetX = 9  ' Circle (ellipse) for flame. Offset apply to center.
can.fcOffsetY = 5
can.fcRad = 5
can.fcAsp = 2.0
can.wOffsetX = 8  ' Wick.
can.wOffsetY = 7
can.wWidth = 1
can.wDepth = 4
can.rand = 6

Candle14 (can, 20, 0, 7, "21")  ' "can" as just set, then: x, y, skew, text.

SpaceOut14 (150, 340, 7, 7, 224, 224, 255, "again")  ' x, y, x-separation, y-sep, r, g, b, text.

screencopy (1, 0)

sleep

' Making images of text.

Function MakeImageOfASCIIchars (charHeight as uinteger, r as uinteger, g as uinteger, b as uinteger) As Any Ptr
    Dim As Any Ptr imChars
    Dim as uinteger i
    Dim as string tx = ""
    width screenW/charWidth, screenD/charHeight  ' Sets char width and height.
    imChars = ImageCreate( charWidth*254 + 1, charHeight, RGBA(255, 0, 255, 0) ) ' Magenta for mask.
    for i = 1 to 254
        tx += chr(i)
    next
    draw string imChars, (1, 0), tx, RGB(r, g, b)
    return imChars  ' Returns a pointer to the image of the ASCII characters.
End Function

'Using the images to show text (in strange ways).

Sub SpaceOut14(x as uinteger, y as uinteger, sepX as uinteger, sepY as uinteger, _
    r as uinteger, g as uinteger, b as uinteger, tx as string)
    Dim as uinteger c, cd, ch, i, len_tx, p, ro, x2, y2
    len_tx = len(tx)
    for i = 1 to len_tx
        cd = asc(mid(tx, i, 1))
        x2 = x + (i-1)*8 * sepX
        for ro = 0 to 13
            y2 = y + ro * sepY
            for c = 0 to 7
                p = point ((cd-1)*8 + 1 + c, ro, imChars14)
                if p <> 16711935 then pset (x2 + c*sepX, y2), RGB(r, g, b)
            next
        next
    next
End Sub

Sub Candle14 (ca as candle, x as uinteger, y as uinteger, skew as integer, tx as string)
    Dim as uinteger c, cd, ch, cw, i, len_tx, p, r,xb, xc, xw, yb, yc, yw, charX, rowY, drop
    Dim as uinteger rs, xb2, xc2, xw2  ' Includes skew for box, circle & wick.
    Dim as uinteger w, d, bX, bY, bw, bd  ' Width & depth of cells, then info for white-ish box in each cell.
    Dim as uinteger fX, fY, fR  ' For drawing 'circle' (ellipse) for flame.
    Dim as uinteger wX, wY, wW, wD  ' For drawing wick.
    Dim as single fA, randAsp
    Dim as uinteger rand, randH, randC, randHor, randVert, randX, randY ' Random candle height and color, and position.
    w = ca.cellW
    d = ca.cellD
    bX = ca.bOffsetX  ' box x-offset from box left (box drawn for waxy part)
    bY = ca.bOffsetY  ' box y-offset from box top
    bw = ca.bWidth  ' box width
    bd = ca.bDepth  ' box depth
    fX = ca.fcOffsetX  ' flame-circle (ellipse) x-offset
    fY = ca.fcOffsetY  ' flame-circle y-offset
    fR = ca.fcRad  ' flame-circle radius
    fA = ca.fcAsp  ' flame-circle aspect ratio
    wX = ca.wOffsetX  ' wick x-offset
    wY = ca.wOffsetY  ' wick y-offset
    wW = ca.wWidth - 1  ' Wick width. -1 so can use "+ wW" instead of "+ wW -1" in "line" statement.
    wD = ca.wDepth  ' wick depth
    rand = ca.rand
    randHor = 1 + rand/2
    randVert = 1 + rand/3
    randAsp = fA / 2.0
    len_tx = len(tx)
    for i = 1 to len_tx
        cd = asc(mid(tx, i, 1))
        charX = x + (i-1)*8 * w
        xb = bX + charX
        xc = fX + charX
        xw = wX + charX
        for r = 0 to 13
            rowY = y + r * d
            yb = rowY + bY
            yc = rowY + fY
            yw = rowY + wY
            rs = r * skew
            xb2 = xb + rs
            xc2 = xc + rs
            xw2 = xw + rs
            for c = 0 to 7
                p = point ((cd-1)*8 + 1 + c, r, imChars14)
                if p <> 16711935 then
                    randH = int(1 + Rnd * rand)  ' Random variation in height of candles (randH reduces height).
                    randC = int(1 + Rnd * 10)  ' Random color
                    randX = int(Rnd * randHor)  ' Random move right
                    randY = int(Rnd * randVert)  ' Random move down
                    drop = randH + randY
                    cw = c * w + randX
                    circle (xc2 + cw + int(Rnd * 2.25 - 1.125), yc + drop + int(Rnd * 2.25 - 1.125)), fR, RGB(255, 255, 32), , , fA + randAsp * (rnd - 0.5), F ' flame
                    line (xw2 + cw, yw + drop)-(xw2 + cw + wW, yw + wD + drop), RGB(128, 128, 0), BF  ' wick
                    select case as const randC
                    case 1
                        Color RGB(255, 0, 255)  ' magenta
                    case 2
                        Color RGB(0, 224, 0)  ' green
                    case 3
                        Color RGB(255, 64, 96)  ' pink
                    case 4
                        Color RGB(96, 80, 255)  ' light blue
                    case else
                        Color RGB(255, 245, 235), RGB(0, 0, 0)  ' White, red tinge
                    End select
                    line (xb2 + cw, yb + drop)-(xb2 + cw + bw, yb + bd + randY),, BF  ' body
                end if
            next
        next
    next
End Sub
Post Reply