1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2025-04-12 06:39:51 +00:00

Two font formats for bitmaps and pixmaps

This commit is contained in:
David Schmenk 2025-01-12 19:23:03 -08:00
parent b7a7d60019
commit ea39e71ed9
6 changed files with 329 additions and 190 deletions

@ -1,10 +1,11 @@
import dhgrutils
const FONT_WIDE = 0
const FONT_THIN = 1
byte fontDefWide
byte fontDefThin
predef dhgrAllocBl7Mem(w, h)#2
predef dcgrStr(x, y, strptr)#0
predef dcgrBoldStr(clr, x, y, strptr)#0
predef dcgrStr(x, y, strptr)#2
predef dcgrBoldStr(clr, x, y, strptr)#2
predef dcgrFont(font)#0
predef fontRead(filename)#1
predef dcgrRect(x, y, w, h)#0
predef dcgrGetPixMap(x, y, w, h)#1
predef dcgrEncPixMap(w, h, pixmap, rlemap)#1

@ -1,13 +1,44 @@
include "inc/cmdsys.plh"
include "inc/fileio.plh"
include "dhgr.tk/inc/dhgrlib.plh"
include "dhgr.tk/inc/dhgrutils.plh"
const page1m = $C054
const page1x = $C055
//
// Font type bits
//
const FONT_MONO = $00
const FONT_PROP = $80
const FONT_BITMAP = $00
const FONT_PIXMAP = $40
//
// Font header
//
struc t_font
byte[] fnt_typelen
char fnt_name[16]
byte fnt_first
byte fnt_last
byte fnt_width
byte fnt_height
var fnt_glyptrs[]
end
//
// Variable pitch glyphs
//
struc t_glyph
var gly_left
var gly_top
byte gly_width
byte gly_height
byte gly_adv
byte gly_strike[]
end
//
// Apple //e hires character font
//
byte fontWide[]
byte[] Apple2Glyphs
byte = $00,$00,$00,$00,$00,$00,$00,$00,$08,$08,$08,$08,$08,$00,$08,$00
byte = $14,$14,$14,$00,$00,$00,$00,$00,$14,$14,$3E,$14,$3E,$14,$14,$00
byte = $08,$3C,$0A,$1C,$28,$1E,$08,$00,$06,$26,$10,$08,$04,$32,$30,$00
@ -56,9 +87,32 @@ byte = $00,$00,$22,$14,$08,$14,$22,$00,$00,$00,$22,$22,$22,$3C,$20,$1C
byte = $00,$00,$3E,$10,$08,$04,$3E,$00,$38,$0C,$0C,$06,$0C,$0C,$38,$00
byte = $08,$08,$08,$08,$08,$08,$08,$08,$0E,$18,$18,$30,$18,$18,$0E,$00
byte = $00,$2C,$1A,$00,$00,$00,$00,$00,$00,$2A,$14,$2A,$14,$2A,$00,$00
var fontThin = NULL
var fontPtr = @fontWide
var fontWidth = 7
//
// Default wide font header
//
export byte[] fontDefWide
char[16] = "Default Wide"
byte = 32, 127 // first, last
byte = 7, 8 // width, height
var = @Apple2Glyphs
//
// Default narrow font header (unallocated)
//
export byte[] fontDefThin
char[16] = "Default Thin"
byte = 32, 127 // first, last
byte = 4, 8 // width, height
var = NULL
//
// Current font
//
var fontPtr = @fontDefWide
//
// Function pointers
//
export asm dcgrStr(x, y, strptr)#2
JMP $2000
end
//
// Utility functions
//
@ -69,15 +123,101 @@ export def dhgrAllocBl7Mem(w, h)#2
memblk = heapalloc(span * h)
return memblk, span
end
export def dcgrStr(x, y, strptr)#0
byte i
def bitMonoGlyphStr(x, y, strptr)#2
byte first, last, width, height, size, i, ch
var strikes
first = fontPtr->fnt_first
last = fontPtr->fnt_last
width = fontPtr->fnt_width
height = fontPtr->fnt_height
strikes = fontPtr=>fnt_glyptrs
size = (width + 7) / 8 * height
for i = 1 to ^strptr
dcgrBitmap(x, y, fontWidth, 8, fontPtr + (^(strptr + i) - 32) * 8)
x = x + fontWidth
ch = ^(strptr + i)
if ch >= first and ch <= last
dcgrBitmap(x, y, width, height, strikes + (^(strptr + i) - first) * size)
x = x + width
else
when ch
is '\n'
x = 0
y = y + fontPtr->fnt_height
break
is '\t'
x = x + (fontPtr->fnt_width * 8)
break
wend
fin
next
return x, y
end
export def dcgrBoldStr(clr, x, y, strptr)#0
def pixPropGlyphStr(x, y, strptr)#2
var glyptrs, glyph, left, top
byte first, last, i, ch, width, height
dhgrOp(OP_XOR)
first = fontPtr->fnt_first
last = fontPtr->fnt_last
glyptrs = fontPtr + fnt_glyptrs
for i = 1 to ^strptr
ch = ^(strptr + i)
if ch >= first and ch <= last
glyph = glyptrs=>[ch - first]
left = glyph=>gly_left
top = glyph=>gly_top
width = glyph->gly_width
height = glyph->gly_height
dcgrPixmap((x + left) / 4, y + top, width, height, glyph + gly_strike)
x = x + glyph->gly_adv
else
when ch
is '\n'
x = 0
y = y + fontPtr->fnt_height
break
is '\t'
x = x + (fontPtr->fnt_width * 8)
break
wend
fin
next
return x, y
end
def bitPropGlyphStr(x, y, strptr)#2
var glyptrs, glyph, left, top
byte first, last, i, ch, width, height
dhgrOp(OP_SRC)
first = fontPtr->fnt_first
last = fontPtr->fnt_last
glyptrs = fontPtr + fnt_glyptrs
for i = 1 to ^strptr
ch = ^(strptr + i)
if ch >= first and ch <= last
glyph = glyptrs=>[ch - first]
left = glyph=>gly_left
top = glyph=>gly_top
width = glyph->gly_width
height = glyph->gly_height
dcgrBitmap(x + left, y + top, width, height, glyph + gly_strike)
x = x + glyph->gly_adv
else
when ch
is '\n'
x = 0
y = y + fontPtr->fnt_height
break
is '\t'
x = x + (fontPtr->fnt_width * 4)
break
wend
fin
next
return x, y
end
export def dcgrBoldStr(clr, x, y, strptr)#2
byte h, v
for v = y - 1 to y + 1
@ -86,32 +226,94 @@ export def dcgrBoldStr(clr, x, y, strptr)#0
next
next
dcgrColor(clr)
dcgrStr(x, y, strptr)
return dcgrStr(x, y, strptr)
end
export def dcgrFont(font)#0
var rows, pWide, pThin
byte bits
if font
if not fontThin
fontThin = heapalloc(96*8)
pThin = fontThin
pWide = @fontWide
for rows = 0 to 96*8
bits = (^pWide ) & $02
bits = bits | (^pWide | ^pWide >> 1 | ^pWide >> 2) & $04
bits = bits | ( ^pWide >> 2) & $08
^pThin = bits
pThin++
pWide++
next
if font == @fontDefThin
if not fontDefThin:fnt_glyptrs
pWide = @Apple2Glyphs
pThin = heapalloc(96*8)
fontDefThin:fnt_glyptrs = pThin
for rows = 0 to 96*8
bits = (^pWide ) & $02
bits = bits | (^pWide | ^pWide >> 1 | ^pWide >> 2) & $04
bits = bits | ( ^pWide >> 2) & $08
^pThin = bits
pThin++
pWide++
next
fin
fin
fontPtr = font
if fontPtr->fnt_typelen & FONT_PROP
if fontPtr->fnt_typelen & FONT_PIXMAP
dcgrStr:1 = @pixPropGlyphStr
else
dcgrStr:1 = @bitPropGlyphStr
fin
else // FONT_MONO
dcgrStr:1 = @bitMonoGlyphStr
fin
fontPtr = fontThin
fontWidth = 4
else
fontPtr = @fontWide
fontWidth = 7
fin
end
export def fontRead(filename)#1
var glyph, strksize, left, top
byte refnum, num, i, width, height, adv
byte roundup, pixbyte
var font_header, gly_ptr
font_header = NULL
if filename and ^filename
refnum = fileio:open(filename)
if refnum
font_header = heapalloc(t_font)
fileio:read(refnum, font_header, t_font)
num = font_header->fnt_last - font_header->fnt_first
if font_header->fnt_typelen & FONT_PROP
gly_ptr = heapalloc(num * 2) // Allocate glyph ptrs right after
if font_header->fnt_typelen & FONT_PIXMAP
roundup = 1
pixbyte = 2
else
roundup = 7
pixbyte = 8
fin
for i = 1 to num
fileio:read(refnum, @left, 1); left = sext(left)
fileio:read(refnum, @top, 1); top = sext(top)
fileio:read(refnum, @width, 1)
fileio:read(refnum, @height, 1)
fileio:read(refnum, @adv, 1)
strksize = (width + roundup) / pixbyte * height
if strksize
*gly_ptr = heapalloc(strksize + t_glyph)
glyph = *gly_ptr
if glyph and fileio:read(refnum, glyph + gly_strike, strksize) == strksize
glyph=>gly_left = left
glyph=>gly_top = top
glyph->gly_width = width
glyph->gly_height = height
glyph->gly_adv = adv
else
heaprelease(font_header)
font_header = NULL
break
fin
else
*gly_ptr = NULL
fin
gly_ptr = gly_ptr + 2
next
fin
fileio:close(refnum)
fin
fin
return font_header
end
export def dcgrRect(x, y, w, h)#0
byte x2, y2, v
@ -249,3 +451,9 @@ export def screenWrite(filestr)#1
fin
return result
end
//
// Fixups
//
dcgrStr:1 = @bitMonoGlyphStr
done

@ -229,7 +229,7 @@ def dcgrTest#0
dcgrVLin(29,29+133,(21/7)*7+(100/7)*7)
dcgrColor(CLR_BLACK) // Outline color
dcgrBoldStr(CLR_WHITE,48,10,"Hello!")
dcgrFont(FONT_THIN)
dcgrFont(@fontDefThin)
dcgrColor(CLR_WHITE) // Outline color
dcgrBoldStr(CLR_BLACK,42,20,"from DCGRTEST")
i = 64; j = 64; k = 86

@ -7,162 +7,21 @@ include "dhgr.tk/inc/dhgrutils.plh"
sysflags resxtxt1|reshgr1|resxhgr1
//
// Glyph sprites
//
struc t_glyph
var gly_left
var gly_top
byte gly_width
byte gly_height
byte gly_adv
byte gly_pixmap[]
end
byte firstGlyph, numGlyphs, widthGlyph, heightGlyph, baselineGlyph
var fontGlyphs
var arg
var xPen = 0
var yPen = 16
byte clrRot = $00,$08,$01,$09,$02,$0A,$03,$0B
byte = $04,$0C,$05,$0D,$06,$0E,$07,$0F
def fontRead(filename)#5
var base, glyph, pixsize, left, top
byte refnum, first, num, avewidth, aveheight, i, width, height, adv
num = 0
base = NULL
if filename and ^filename
refnum = fileio:open(filename)
if refnum
fileio:read(refnum, @first, 1)
fileio:read(refnum, @num, 1)
fileio:read(refnum, @avewidth, 1)
fileio:read(refnum, @aveheight, 1)
for i = 1 to num
fileio:read(refnum, @left, 1); left = sext(left)
fileio:read(refnum, @top, 1); top = sext(top)
fileio:read(refnum, @width, 1)
fileio:read(refnum, @height, 1)
fileio:read(refnum, @adv, 1)
pixsize = (width + 1) / 2 * height
glyph = heapalloc(pixsize + t_glyph)
if glyph and fileio:read(refnum, glyph + gly_pixmap, pixsize) == pixsize
glyph=>gly_left = left
glyph=>gly_top = top
glyph->gly_width = width
glyph->gly_height = height
glyph->gly_adv = adv
if not base; base = glyph; fin
else
if base; heaprelease(base); fin
base = NULL
num = 0
break
fin
next
fileio:close(refnum)
fin
fin
return first, num, avewidth, aveheight, base
end
def fontLoad(filename)#1
var fontSprites, glyphs
byte i, width, height
firstGlyph, numGlyphs, widthGlyph, heightGlyph, glyphs = fontRead(filename)
if numGlyphs
fontGlyphs = heapalloc(numGlyphs * 2)
for i = 1 to numGlyphs
fontGlyphs=>[i-1] = glyphs
width = glyphs->gly_width
height = glyphs->gly_height
glyphs = glyphs + t_glyph + (width + 1) / 2 * height
next
fin
return numGlyphs
end
def pixGlyphStr(x, y, strptr)#2
var glyph, left, top, fixX
byte i, ch, width, height
fixX = x * 4
for i = 1 to ^strptr
ch = ^(strptr + i)
if ch < 32 or ch > 127
when ch
is '\n'
x = 0
y = y + heightGlyph
break
is '\t'
x = x + (widthGlyph * 8)
break
wend
elsif (ch >= firstGlyph and ch < (firstGlyph + numGlyphs))
glyph = fontGlyphs=>[ch - firstGlyph]
left = glyph=>gly_left
top = glyph=>gly_top
width = glyph->gly_width
height = glyph->gly_height
dcgrPixmap((x + left) / 4, y + top, width, height, glyph + gly_pixmap)
x = x + glyph->gly_adv
else
x = x + widthGlyph
fin
next
return x, y
end
def bitGlyphStr(x, y, strptr)#2
var glyph, left, top
byte i, ch, width, height
for i = 1 to ^strptr
ch = ^(strptr + i)
if ch < 32 or ch > 127
when ch
is '\n'
x = 0
y = y + heightGlyph
break
is '\t'
x = x + (widthGlyph * 4)
break
wend
elsif (ch >= firstGlyph and ch < (firstGlyph + numGlyphs))
glyph = fontGlyphs=>[ch - firstGlyph]
left = glyph=>gly_left
top = glyph=>gly_top
width = glyph->gly_width * 4
height = glyph->gly_height
dcgrBitmap(x + left, y + top, width, height, glyph + gly_pixmap)
x = x + glyph->gly_adv
else
x = x + widthGlyph
fin
next
return x, y
end
arg = argNext(argFirst)
dhgrMode(DHGR_COLOR_MODE)
dcgrColor(CLR_WHITE)
dhgrClearBl7(0, 0, SCR_WIDTH7, SCR_HEIGHT)
dcgrColor(CLR_BLACK)
dcgrStr(0, 0, "Wide Default Font Test")
dcgrFont(FONT_THIN)
dcgrFont(@fontDefThin)
dcgrStr(0, 8, "Thin Default Font Test")
dhgrOp(OP_XOR)
while arg and ^arg
fontLoad(arg)
xPen, yPen = pixGlyphStr(xPen, yPen, "\nHello, world")
//xPen, yPen = bitGlyphStr(xPen, yPen, "\nHello, world")
dcgrFont(fontRead(arg))
xPen, yPen = dcgrStr(xPen, yPen, "\nHello, world")
arg = argNext(arg)
loop
getc

@ -57,6 +57,13 @@ void write_glyph(FILE *fp, int c)
int pixOffset, pixWidth, byteWidth, byteOffset, bitShift, bitWidth, glyphSpan, i;
int left, top, width, height;
if (c < macf->firstChar || c > macf->lastChar)
{
memset(glyphdef, 0, 5);
fwrite(&glyphdef, 1, 5, fp);
return;
}
c -= macf->firstChar;
glyphBits = (uint8_t *)&(macf->bitImage),
glyphSpan = macf->rowWords * 2;
height = macf->rectHeight;
@ -66,18 +73,22 @@ void write_glyph(FILE *fp, int c)
glyphdef[0] = left;
glyphdef[1] = -top;
#if PIXFONT
glyphdef[2] = (width + 3) / 4;
#else
glyphdef[2] = width;
#endif
glyphdef[3] = height;
glyphdef[4] = width + left;
fwrite(&glyphdef, 1, 5, fp);
pixOffset = locTable[c];
pixWidth = locTable[c+1] - locTable[c];
byteOffset = pixOffset / 8;
bitShift = pixOffset & 7;
bitWidth = bitShift + pixWidth;
byteWidth = (width + 7) / 8;
rowbits = 0;
pixOffset = locTable[c];
pixWidth = locTable[c+1] - locTable[c];
byteOffset = pixOffset / 8;
bitShift = pixOffset & 7;
bitWidth = bitShift + pixWidth;
byteWidth = (width + 7) / 8;
rowbits = 0;
while (height--)
{
if (pixWidth > 0)
@ -96,29 +107,66 @@ void write_glyph(FILE *fp, int c)
rowbits >>= bitShift;
rowbits &= 0xFFFFFFFF >> (32 - pixWidth);
}
#if PIXFONT
glyphdef[0] = clrSwap[rowbits & 0xFF];
glyphdef[1] = clrSwap[(rowbits >> 8) & 0xFF];
glyphdef[2] = clrSwap[(rowbits >> 16) & 0xFF];
glyphdef[3] = clrSwap[(rowbits >> 24) & 0xFF];
#else
glyphdef[0] = rowbits;
glyphdef[1] = rowbits >> 8;
glyphdef[2] = rowbits >> 16;
glyphdef[3] = rowbits >> 24;
#endif
fwrite(&glyphdef, 1, byteWidth, fp);
glyphBits += glyphSpan;
}
}
void write_font_file(char *filename)
void write_font_file(char *filename, char *fontfile)
{
FILE *fp;
unsigned char ch;
char *fontname, *scanname, font_header[16];
int glyph_width, glyph_height, c;
if ((fp = fopen(filename, "wb")))
{
fontname = scanname = fontfile;
while (*scanname) // Strip leading directory names
{
if (*scanname == '/')
fontname = scanname + 1;
scanname++;
}
while (scanname > fontfile)
{
if (*scanname == '.')
{
*scanname = '\0';
}
scanname--;
}
memset(font_header, 0, 16);
strncpy(&font_header[1], fontname, 15);
ch = strlen(fontname);
font_header[0] = ch < 16 ? ch : 15;
#if PIXFONT
font_header[0] |= 0x80 | 0x40; // FONT_PROP | FONT_PIXMAP
#else
font_header[0] |= 0x80; // FONT_PROP
#endif
fwrite(font_header, 1, 16, fp);
glyph_width = macf->rectWidth;
glyph_height = macf->rectHeight;
ch = GLYPH_FIRST;
fwrite(&ch, 1, 1, fp);
ch = GLYPH_COUNT;
ch = GLYPH_LAST;
fwrite(&ch, 1, 1, fp);
#if PIXFONT
ch = (glyph_width + 3) / 4;
#else
ch = glyph_width;
#endif
fwrite(&ch, 1, 1, fp);
ch = glyph_height;
fwrite(&ch, 1, 1, fp);
@ -250,7 +298,7 @@ int main(int argc, char **argv)
* Load IIGS font file header.
*/
load_iigs_file(iigs_file);
write_font_file(font_file);
write_font_file(font_file, iigs_file);
return 0;
}

@ -7,8 +7,9 @@
#include <string.h>
#include <freetype2/ft2build.h>
#include <freetype/freetype.h>
//#include FT_FREETYPE2_H
#include <freetype2/freetype/freetype.h>
#define FONT_WIDTH 32
#define FONT_HEIGHT 12
#define GLYPH_FIRST 32
@ -42,17 +43,39 @@ void write_glyph(FILE *fp, int left, int top, int width, int height, int advance
}
free(swapbuf);
}
void write_font_file(char *filename, FT_Face face, int glyph_width, int glyph_height)
void write_font_file(char *filename, char *fontfile, FT_Face face, int glyph_width, int glyph_height)
{
FILE *fp;
unsigned char ch;
char *fontname, *scanname, font_header[16];
int c;
if ((fp = fopen(filename, "wb")))
{
fontname = scanname = fontfile;
while (*scanname) // Strip leading directory names
{
if (*scanname == '/')
fontname = scanname + 1;
scanname++;
}
while (scanname > fontfile)
{
if (*scanname == '.')
{
*scanname = '\0';
}
scanname--;
}
memset(font_header, 0, 16);
strncpy(&font_header[1], fontname, 15);
ch = strlen(fontname);
font_header[0] = ch < 16 ? ch : 15;
font_header[0] |= 0x80 | 0x40; // FONT_PROP | FONT_PIXMAP
fwrite(font_header, 1, 16, fp);
ch = GLYPH_FIRST;
fwrite(&ch, 1, 1, fp);
ch = GLYPH_COUNT;
ch = GLYPH_LAST;
fwrite(&ch, 1, 1, fp);
ch = (glyph_width + 3) / 4;
fwrite(&ch, 1, 1, fp);
@ -203,7 +226,7 @@ int main(int argc, char **argv)
//if (glyph_height < 8) glyph_height = 8;
FT_Set_Pixel_Sizes(face, glyph_width, glyph_height);
//write_bitmap_file(font_file, face, glyph_width, glyph_height);
write_font_file(font_file, face, glyph_width, glyph_height);
write_font_file(font_file, ttf_file, face, glyph_width, glyph_height);
return 0;
}