From eff663502098cb6d657e23577997bea7cef00a3e Mon Sep 17 00:00:00 2001 From: glenda Date: Sun, 23 Nov 2025 16:28:16 +0000 Subject: [PATCH] use memdraw properly, checkmapfile --- ufx2font.c | 413 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 273 insertions(+), 140 deletions(-) diff --git a/ufx2font.c b/ufx2font.c index ca48a87f190d9071c1cecd9998123cba3ce8d561..72ba980afbba42013389e4a2cfee84363a4aa521 100644 --- a/ufx2font.c +++ b/ufx2font.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include /* entry has 1 byte in widtab + 8 bytes per tile */ @@ -18,6 +20,8 @@ enum{ struct MapRule{ struct MapRule *next; + uint linum; + uchar ty; uint start, end; }; @@ -43,10 +47,9 @@ struct GlyphInfo{ uchar top, bottom, left, width; }; - -struct RawImage{ - char chan[12], minx[12], miny[12], maxx[12], maxy[12]; - uchar data[]; +struct RawSubfont{ + char n[12], height[12], ascent[12]; + uchar entries[][6]; }; @@ -58,7 +61,7 @@ struct MapFile *mapfiles, *lastmf; uchar wasmferr, wasreaderr; struct GlyphInfo *glyphs; -struct RawImage *glyphbuf; +Memimage *glyphimg; void @@ -73,6 +76,12 @@ readtoken(Biobuf *b, char **line, uint *linum) { char *ret, *p; + if(b->aux != nil){ + ret = b->aux; + b->aux = nil; + return ret; + } + while(*line != nil){ p = *line; while(p[0] != '\0' && strchr("\t\r ", p[0]) != nil) @@ -98,6 +107,11 @@ readtoken(Biobuf *b, char **line, uint *linum) return nil; } +void +unreadtoken(Biobuf *b, char *tok) +{ + b->aux = tok; +} #pragma varargck argpos mferr 3 void mferr(char *file, uint linum, char *fmt, ...) @@ -115,13 +129,150 @@ mferr(char *file, uint linum, char *fmt, ...) wasmferr = 1; } +struct MapRule * +parsemaprule(char *file, Biobuf *b, char **line, uint *linum) +{ + struct MapRule *ret; + char *tok, *p; + + tok = readtoken(b, line, linum); + if(tok == nil) + return nil; + + ret = malloc(sizeof(struct MapRule)); + ret->next = nil; + ret->linum = *linum; + + if(strcmp(tok, "blank") == 0){ + ret->ty = MR_BLANK; + return ret; + }else if(tok[0] == '-'){ /* e.g. -0x4f */ + tok++; + ret->ty = MR_RANGE; + ret->start = 0; + ret->end = strtoul(tok, &p, 0); + if(tok == p || p[0] != '\0'){ + mferr(file, *linum, "bad upper glyph bound"); + free(ret); + return nil; + } + return ret; + } + + + ret->start = strtoul(tok, &p, 0); + if(tok == p){ + unreadtoken(b, tok); + free(ret); + return nil; + }else if(p[0] == '\0'){ + ret->ty = MR_SINGLE; + return ret; + }else if(p[0] != '-'){ + mferr(file, *linum, "bad lower glyph bound"); + free(ret); + return nil; + } + + + ret->ty = MR_RANGE; + + tok = p+1; + if(tok[0] == '\0'){ /* e.g. 0x80- */ + ret->end = nglyphs - 1; + return ret; + } + ret->end = strtoul(tok, &p, 0); + if(tok == p || p[0] != '\0'){ + mferr(file, *linum, "bad upper glyph bound"); + free(ret); + return nil; + } + + return ret; +} +struct Mapping * +parsemapping(char *file, Biobuf *b, char **line, uint *linum) +{ + struct Mapping *ret; + struct MapRule *rlast = nil, *r; + char *tok, *p; + + tok = readtoken(b, line, linum); + if(tok == nil){ + mferr(file, *linum, "unexpected eof"); + return nil; + } + + ret = malloc(sizeof(struct Mapping)); + ret->linum = *linum; + ret->rules = nil; + ret->next = nil; + + ret->start = strtoul(tok, &p, 0); + if(tok == p){ + mferr(file, *linum, "empty lower rune bound"); + free(ret); + return nil; + } + tok = p; + + if(tok[0] == '\0'){ /* 1:1 mapping */ + tok = readtoken(b, line, linum); + if(tok == nil){ + mferr(file, *linum, "unexpected eof"); + free(ret); + return nil; + } + ret->idx = strtoul(tok, &p, 0); + + if(tok == p || p[0] != '\0'){ + mferr(file, *linum, "bad glyph index"); + free(ret); + return nil; + } + + return ret; + }else if(tok[0] != '-'){ + mferr(file, *linum, "bad rune range"); + free(ret); + return nil; + } + tok++; + + /* many:many mapping */ + ret->end = strtoul(tok, &p, 0); + if(tok == p){ + mferr(file, *linum, "empty upper rune bound"); + free(ret); + return nil; + }else if(p[0] != '\0'){ + mferr(file, *linum, "bad upper rune bound"); + free(ret); + return nil; + } + + while((r = parsemaprule(file, b, line, linum)) != nil){ + if(rlast == nil) + ret->rules = rlast = r; + else + rlast = rlast->next = r; + } + + if(rlast == nil){ + mferr(file, *linum, "unexpected eof"); + free(ret); + return nil; + } + + return ret; +} void _parsemapfile(Biobuf *b, struct MapFile *mf) { - char *line, *tok, *p; + char *line, *tok; uint linum = 1; - struct Mapping *mlast = nil; - struct MapRule *rlast; + struct Mapping *mlast = nil, *m; wasreaderr = 0; line = Brdline(b, '\n'); @@ -131,120 +282,21 @@ _parsemapfile(Biobuf *b, struct MapFile *mf) return; } - tok = readtoken(b, &line, &linum); - while(tok != nil){ + while((tok = readtoken(b, &line, &linum)) != nil){ if(strcmp(tok, "mapping") == 0){ - if(mlast == nil) - mf->mappings = mlast = malloc(sizeof(struct Mapping)); - else - mlast = mlast->next = malloc(sizeof(struct Mapping)); - - mlast->linum = linum; - mlast->rules = nil; - mlast->next = nil; - - tok = readtoken(b, &line, &linum); - if(tok == nil){ - mferr(mf->file, linum, "unexpected eof"); - return; - } - - mlast->start = strtoul(tok, &p, 0); - if(tok == p){ - mferr(mf->file, linum, "empty lower rune bound"); - return; - } - tok = p; - - if(tok[0] == '\0'){ /* 1:1 mapping */ - tok = readtoken(b, &line, &linum); - if(tok == nil){ - mferr(mf->file, linum, "unexpected eof"); - return; - } - mlast->idx = strtoul(tok, &p, 0); - - if(tok == p || p[0] != '\0'){ - mferr(mf->file, linum, "bad glyph index"); - return; - } - - tok = readtoken(b, &line, &linum); + m = parsemapping(mf->file, b, &line, &linum); + if(m == nil) continue; - }else if(tok[0] != '-'){ - mferr(mf->file, linum, "bad rune range"); - return; - } - tok++; - - /* many:many mapping */ - mlast->end = strtoul(tok, &p, 0); - if(tok == p){ - mferr(mf->file, linum, "empty upper rune bound"); - return; - }else if(p[0] != '\0'){ - mferr(mf->file, linum, "bad upper rune bound"); - return; - } - - rlast = nil; - while((tok = readtoken(b, &line, &linum)) != nil){ - if(rlast == nil) - mlast->rules = rlast = malloc(sizeof(struct MapRule)); - else - rlast = rlast->next = malloc(sizeof(struct MapRule)); - - rlast->next = nil; - - if(strcmp(tok, "blank") == 0){ - rlast->ty = MR_BLANK; - continue; - }else if(tok[0] == '-'){ /* e.g. -0x4f */ - tok++; - rlast->ty = MR_RANGE; - rlast->start = 0; - rlast->end = strtoul(tok, &p, 0); - if(tok == p || p[0] != '\0'){ - mferr(mf->file, linum, "bad upper glyph bound"); - return; - } - continue; - } - - rlast->start = strtoul(tok, &p, 0); - if(tok == p) - break; /* return to toplevel parser */ - else if(p[0] == '\0'){ - rlast->ty = MR_SINGLE; - continue; - }else if(p[0] != '-'){ - mferr(mf->file, linum, "bad lower glyph bound"); - return; - } - - rlast->ty = MR_RANGE; - tok = p+1; - if(tok[0] == '\0'){ /* e.g. 0x80- */ - rlast->end = nglyphs - 1; - continue; - } - rlast->end = strtoul(tok, &p, 0); - if(tok == p || p[0] != '\0'){ - mferr(mf->file, linum, "bad upper glyph bound"); - return; - } - } /* end while */ - - if(rlast == nil){ - mferr(mf->file, linum, "unexpected eof"); - return; - } + if(mlast == nil) + mf->mappings = mlast = m; + else + mlast = mlast->next = m; }else{ mferr(mf->file, linum, "unknown verb %s", tok); return; } - } /* end while */ + } } void parsemapfile(struct MapFile *mf) @@ -306,8 +358,77 @@ addmapfile(char *file) parsemapfile(lastmf); } void +testmappingoverlap(char *file, struct Mapping *a, struct Mapping *b) +{ + uchar res = 0; + struct Mapping *tmp; + + if(a->rules == nil){ + tmp = a; a = b; b = tmp; + } + + if(a->rules == nil){ + if(a->start == b->start) + res = 1; + }else if(b->rules == nil){ + if(a->start <= b->start && b->start <= a->end) + res = 1; + }else{ + if(a->start > b->start){ + tmp = a; a = b; b = tmp; + } + if(a->end >= b->start) + res = 1; + } + + if(res) + mferr(file, a->linum, "overlaps mapping on line %ud", b->linum); +} +void +testmappingrange(char *file, struct Mapping *m) +{ + struct MapRule *r; + int nrunes, n = 0; + + for(r = m->rules; r != nil; r = r->next){ + if((r->ty != MR_BLANK && r->start >= nglyphs) || + (r->ty == MR_RANGE && r->end >= nglyphs)) + mferr(file, r->linum, "glyphs out of range"); + + if(r->ty == MR_RANGE) + n += r->end - r->start; + n++; + } + + nrunes = (m->end-m->start+1); + + if(nrunes != n) + mferr(file, m->linum, "# runes != # glyphs (%d != %d)", nrunes, n); +} +void checkmapfiles(void) { + struct MapFile *mf; + struct Mapping *p1, *p2; + + if(wasmferr) + exits("mapfile"); + + for(mf = mapfiles; mf != nil; mf = mf->next){ + for(p1 = mf->mappings; p1 != nil; p1 = p1->next){ + if(p1->rules != nil && p1->start > p1->end) + mferr(mf->file, p1->linum, "rune start > rune end"); + + if(p1->rules != nil) + testmappingrange(mf->file, p1); + else if(p1->idx >= nglyphs) + mferr(mf->file, p1->linum, "glyph out of range"); + + for(p2 = p1->next; p2 != nil; p2 = p2->next) + testmappingoverlap(mf->file, p1, p2); + } + } + if(wasmferr) exits("mapfile"); } @@ -379,25 +500,13 @@ loadwidths(Biobuf *b, char *file) } void -allocrawimage(void) +allocglyphimg(void) { - char buf[13]; - uint imglen; - - /* cols * rows */ - imglen = glyphedge * nglyphs*fwidth; - glyphbuf = malloc(sizeof(struct RawImage) + imglen); - - memcpy(glyphbuf->chan, " k1 ", 12); - memcpy(glyphbuf->minx, " 0 ", 12); - memcpy(glyphbuf->miny, " 0 ", 12); + Rectangle dims = Rect(0,0, nglyphs*fwidth*8,glyphedge); - snprint(buf, 12, "%11d ", nglyphs*fwidth*8); - memcpy(glyphbuf->maxx, buf, 11); - snprint(buf, 12, "%11d ", glyphedge); - memcpy(glyphbuf->maxy, buf, 11); - - memset(glyphbuf->data, 0, imglen); + glyphimg = allocmemimage(dims, strtochan("k1")); + if(glyphimg == nil) + sysfatal("%r"); } uchar @@ -434,12 +543,14 @@ void storeglyph(uint i, uchar *bitmap) { uint y, x; - ulong dstidx, srcidx; + ulong srcidx; + Point dst; + for(x = 0; x < fwidth; x++){ for(y = 0; y < glyphedge; y++){ - dstidx = (i*fwidth)+x+(y*fwidth*nglyphs); srcidx = y+(x*glyphedge); - glyphbuf->data[dstidx] = bitmap[srcidx]; + dst = Pt((i*fwidth+x)*8, y); + *byteaddr(glyphimg, dst) = bitmap[srcidx]; } } } @@ -493,7 +604,7 @@ loadufx(char *infile) glyphs = malloc(nglyphs * sizeof(struct GlyphInfo)); b = Bopen(infile, OREAD); - allocrawimage(); + allocglyphimg(); loadwidths(b, infile); loadglyphs(b); @@ -502,6 +613,14 @@ loadufx(char *infile) } +void +makenaive(void) +{ + int fd; + struct RawSubfont s; +} + + void usage(void) { @@ -516,6 +635,7 @@ void main(int argc, char **argv) { char *infile, *outdir; + int fd; ARGBEGIN{ case 'l': @@ -546,8 +666,6 @@ main(int argc, char **argv) default: usage(); }ARGEND; - - checkmapfiles(); if(argv0 == nil) @@ -563,9 +681,24 @@ main(int argc, char **argv) if(baseline >= glyphedge) sysfatal("-b: baseline must be in range 1-width*8"); + checkmapfiles(); + loadufx(infile); - int fd = create(outdir, OWRITE, 0644); - write(fd, glyphbuf, sizeof(struct RawImage) + (glyphedge*nglyphs*fwidth)); + + fd = create(outdir, OWRITE, 0777|DMDIR); + if(fd < 0) + sysfatal("%r"); close(fd); + chdir(outdir); + + fd = create("test", OWRITE, 0777); + writememimage(fd, glyphimg); + close(fd); + + if(!setconv || donaive) + makenaive(); +/* if(!setconv || doholes) + makeholes(); + makemapped();*/ }