auto kerning fonts (variable width)

Previous topic - Next topic

loganite

AutoKern() //only needs to be called once

PRINT "Normal Unkerned Hello World",0,0
PrintKerned("Auto Kerned Hello World",0,40)
PRINT "This is a test sentence without kerning.",0,80
PrintKerned("This is a test sentence with kerning.",0,120)
PrintKerned("Use your own smallfont.bmp to see the difference.",0,200)


SHOWSCREEN
MOUSEWAIT

END


FUNCTION PrintKerned: txt$,x,y
 LOCAL w,h,i,t$,e
 GETFONTSIZE w,h
 e=0
 FOR i=0 TO LEN(txt$)-1
  t$=MID$(txt$,i,1)
  index=INSTR(fontkern$,t$)
  PRINT t$,x+e,y
  e=e+kern[index]-kernS[index] + INTEGER(w*.3)
 NEXT
ENDFUNCTION

FUNCTION AutoKern:
 LOCAL w,h,i
 fontkern$="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz .0123456789!£$%_'()*+,-/:;<=>?@{}|~#"+CHR$(34)
 DIM kern[LEN(fontkern$)]
 DIM kernS[LEN(fontkern$)]
 
 GETFONTSIZE w,h
 
 FOR i=0 TO LEN(fontkern$)-1
  DRAWRECT 0,0,50,50,RGB(0,0,0)
  PRINT MID$(fontkern$,i,1),0,0
 
  //find end
  x=w-1;y=0
  WHILE x>0 AND GETPIXEL(x,y)=RGB(0,0,0)
   INC y,1
   IF y=h
    y=0
    DEC x,1
   ENDIF
  WEND
  IF x=0 THEN x=w*.7
  kern=x
  //findstart
  x=0;y=0
  WHILE x   INC y,1
   IF y=h
    y=0
    INC x,1
   ENDIF
  WEND
  IF x=w THEN x=w*.7
  kernS=x
 
 NEXT
ENDFUNCTION

Moru

Nice, I was planning on writing something like that but was too lazy so far. I wrote one for STOS basic ages ago but lost all sources and didn't feel like doing it again :-)

Kitty Hello

oh. Why are you using a fontkern$ string, and do not store 256 characters, and get their width using PRINT CHR$(index)?
That way you wouldn't have to do INSTR for each character when printing.
Very nice sample, though. Please update it.

PeeJay

Funnily enough, you're using a similar technique to the one I have adopted to use in my upcoming compo game, but there I am using bitmapped fonts. At some point I will build a library of loads of font utilities, and post it up for people to play with.
www.peejays-remakes.co.uk
For games, remakes, and GL Basic Tutorials
Artificial Intelligence is no match for Natural Stupidity

loganite

Quote from: GernotFrischoh. Why are you using a fontkern$ string, and do not store 256 characters, and get their width using PRINT CHR$(index)?
That way you wouldn't have to do INSTR for each character when printing.
Very nice sample, though. Please update it.
Updated taking into account Gernot's suggestions

Code (glbasic) Select
AutoKern() //only needs to be called once

PRINT "Normal Unkerned Hello World",0,0
PrintKerned("Auto Kerned Hello World",0,40)
PRINT "This is a test sentence without kerning.",0,80
PrintKerned("This is a test sentence with kerning.",0,120)
PrintKerned("Use your own smallfont.bmp to see the difference.",0,200)


SHOWSCREEN
MOUSEWAIT

END


FUNCTION PrintKerned: txt$,x,y
 LOCAL w,h,i,t$,e
 GETFONTSIZE w,h
 e=0
 FOR i=0 TO LEN(txt$)-1
  t$=MID$(txt$,i,1)
  index=ASC(t$)
  PRINT t$,x+e,y
  e=e+kern[index]-kernS[index] + INTEGER(w*.25)
 NEXT
ENDFUNCTION

FUNCTION AutoKern:
 LOCAL w,h,i
 
 DIM kern[256]
 DIM kernS[256]

 GETFONTSIZE w,h

 FOR i=0 TO 255
  DRAWRECT 0,0,50,50,RGB(0,0,0)
  PRINT CHR$(i),0,0

  //find end
  x=w-1;y=0
  WHILE x>0 AND GETPIXEL(x,y)=RGB(0,0,0)
   INC y,1
   IF y=h
    y=0
    DEC x,1
   ENDIF
  WEND
  IF x=0 THEN x=INTEGER(w*.7)
  kern[i]=x
  //findstart
  x=0;y=0
  WHILE x   INC y,1
   IF y=h
    y=0
    INC x,1
   ENDIF
  WEND
  IF x=w THEN x=INTEGER(w*.7)
  kernS[i]=x
 
 NEXT
 BLACKSCREEN //clean up
ENDFUNCTION