ref: 360b4c5effb93584b29179241df67b725c54d7b2
parent: 094b3e1d61c9c7cd85c3dfba8a6b40185004eed3
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Jul 24 19:56:24 EDT 2024
more bitmap font functionality; split ppem into ppemX and ppemY
--- a/gen.rkt
+++ b/gen.rkt
@@ -292,37 +292,38 @@
identity))
(define is-ptr (and (cmplx? t) (field-offset f) (not cnt)))
(define lst
- (flatten (list (if (type? t)
- (~a "f->print(f->aux, \"%*s%s: "
- verb
- bits-verbs
- "\\n\", indent, \"\", \""
- (field-name f)
- "\", "
- (fmtarg (~a "v->" (field-name f) array-index))
- bits-args
- ");")
- (list (if cnt
- empty
- (~a "f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \""
- (field-name f)
- "\");"))
- (if is-ptr (~a "if(v->" (field-name f) " != nil)") empty)
- (~a (if is-ptr " " "")
- "print_"
- (cmplx-name t)
- "(f, indent+indentΔ, o, "
- (if is-ptr "" "&")
- "v->"
- (field-name f)
- array-index
- ");"))))))
+ (flatten
+ (list
+ (if (type? t)
+ (list (~a "f->print(f->aux, \"%*s%s: "
+ verb
+ bits-verbs
+ "\\n\", indent, \"\", \""
+ (field-name f)
+ "\", "
+ (fmtarg (~a "v->" (field-name f) array-index))
+ bits-args
+ ");")
+ (if (field-context? f) (~a "o->" (field-name f) " = v->" (field-name f) ";") empty))
+ (list (if cnt
+ empty
+ (~a "f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"" (field-name f) "\");"))
+ (if is-ptr (~a "if(v->" (field-name f) " != nil)") empty)
+ (~a (if is-ptr " " "")
+ "print_"
+ (cmplx-name t)
+ "(f, indent+indentΔ, o, "
+ (if is-ptr "" "&")
+ "v->"
+ (field-name f)
+ array-index
+ ");"))))))
(if (field-unused? f) empty (wrap-cond-c (field-cond f) (array-loop lst))))
(define (filter-extra extra key)
(flatten (filter-map (λ (e) (and (eq? (car e) key) (cdr e))) extra)))
-(define-struct cmplx (name fields tag extra after)
+(define-struct cmplx (name fields tag extra after optional)
#:transparent
#:methods gen:code
[(define/generic super-gen-h gen-h)
@@ -476,7 +477,8 @@
fields:expr ...+
(~optional (~seq #:tag tag))
(~optional (~seq #:extra extra:expr))
- (~optional (~seq #:after after)))
+ (~optional (~seq #:after after))
+ (~optional (~seq #:optional optional)))
#:declare tag (expr/c #'tag/c #:name "table tag")
(begin
(set! typenames (cons (syntax-e #`typ) typenames))
@@ -487,7 +489,8 @@
(mkfields [~@ fields] ...)
tag-
(~? (~@ extra) empty)
- (~? (~@ after) empty)))
+ (~? (~@ after) empty)
+ (~? (~@ optional) #f)))
(set! cmplxs (append cmplxs (list typ)))
(when tag-
(set! tagged (append tagged (list typ))))))]))
--- a/otf.c.in
+++ b/otf.c.in
@@ -248,6 +248,7 @@
f->print(a, "%*s%s: %d\n", indent, "", "format", v->format);
f->print(a, "%*s%s: %d\n", indent, "", "offset", v->offset);
if(v->size > 0){
+ f->print(a, "%*s%s: %d\n", indent, "", "pitchBits", v->pitchBits);
f->print(a, "%*s%s: %d\n", indent, "", "size", v->size);
f->print(a, "%*s%s: ", indent, "", "image");
for(i = 0; i < v->size; i++)
@@ -254,8 +255,10 @@
f->print(a, "%02"PRIx8, v->image[i]);
f->print(a, "\n");
}
+ f->print(a, "%*s%s: %d\n", indent, "", "ppemX", v->ppemX);
+ f->print(a, "%*s%s: %d\n", indent, "", "ppemY", v->ppemY);
if(v->numComponents > 0){
- f->print(a, "%*s%s: %d\n", indent, "", "numComponents");
+ f->print(a, "%*s%s: %d\n", indent, "", "numComponents", v->numComponents);
f->print(a, "%*s%s:\n", indent, "", "components");
for(i = 0; i < v->numComponents; i++){
f->print(a, "%*s%d:\n", indent+indentΔ, "", i);
@@ -551,7 +554,7 @@
bitebdt(Otf *o, Glyf *g, BitmapGlyph *bg)
{
u8int *b;
- int i;
+ int i, n;
if(o->ebdt == nil){
for(i = 0; i < o->td.numTables; i++){
@@ -579,7 +582,6 @@
g->yMin = sm.bearingY - sm.height;
g->xMax = sm.bearingX + sm.width;
g->yMax = sm.bearingY;
- bg->size -= 6;
}else if(bg->format == 6 || bg->format == 7 || bg->format == 9){
BigGlyphMetrics bm;
if(read_BigGlyphMetrics(o, &bm) < 0)
@@ -591,24 +593,34 @@
g->yMin = -(int)bm.horiBearingY;
g->xMax += g->xMin;
g->yMax += g->yMin;
- bg->size -= 8;
}
bg->numComponents = 0;
+ if(bg->format == 2 || bg->format == 5 || bg->format == 7){
+ /* bit-aligned - last row is padded to a full byte */
+ bg->pitchBits = g->xMax - g->xMin;
+ bg->size = (bg->pitchBits*(g->yMax-g->yMin)*bg->bitDepth + 7)/8;
+ }else{
+ /* byte-aligned - every row is byte-aligned */
+ n = ((g->xMax-g->xMin)*bg->bitDepth + 7)/8;
+ bg->size = n * (g->yMax-g->yMin);
+ bg->pitchBits = n * 8;
+ }
+
switch(bg->format){
case 8:
if(otfreadn(o, 1) == nil) /* skip uint8 pad */
goto err;
- bg->size -= 1;
/* fallthrough */
case 9:
if((b = otfreadn(o, 2)) == nil)
goto err;
bg->numComponents = b[0]<<8 | b[1];
- bg->size -= 2;
if(otfarray(o, &bg->components, read_EbdtComponent, sizeof(EbdtComponent), bg->numComponents) < 0)
goto err;
- bg->size -= 4*bg->numComponents;
+ /* no image, both 8 and 9 are component */
+ bg->pitchBits = 0;
+ bg->size = 0;
/* fallthrough */
case 1:
case 2:
@@ -615,11 +627,14 @@
case 5:
case 6:
case 7:
- if((b = otfreadn(o, bg->size)) == nil)
- goto err;
g->bitmap = malloc(sizeof(*bg) + bg->size);
memcpy(g->bitmap, bg, sizeof(*bg));
- memcpy(g->bitmap->image, b, bg->size);
+ if(bg->size > 0){
+ if((b = otfreadn(o, bg->size)) == nil)
+ goto err;
+ memcpy(g->bitmap->image, b, bg->size);
+ }
+ break;
}
otfpoprange(o);
otfpoprange(o);
@@ -646,8 +661,10 @@
for(i = 0; i < (int)o->td.eblc->numSizes; i++, bs++){
if(g->index >= bs->startGlyphIndex && g->index <= bs->endGlyphIndex){
b.bitDepth = bs->bitDepth;
+ b.ppemX = bs->ppemX;
+ b.ppemY = bs->ppemY;
isr = bs->indexSubtableList;
- for(j = 0; j < (int)bs->numberOfIndexSubtables; j++){
+ for(j = 0; j < (int)bs->numberOfIndexSubtables; j++, isr++){
if(g->index >= isr->firstGlyphIndex && g->index <= isr->lastGlyphIndex){
is = isr->indexSubtable;
if(is == nil)
@@ -780,7 +797,6 @@
}
otfpoprange(o);
otfpoprange(o);
- g->type = g->numberOfContours < 0 ? GLYPH_COMPONENT : GLYPH_SIMPLE;
return g;
err:
--- a/otf.h.in
+++ b/otf.h.in
@@ -51,6 +51,9 @@
int format;
int offset;
int size;
+ int pitchBits;
+ int ppemX;
+ int ppemY;
int numComponents;
EbdtComponent *components;
u8int image[];
@@ -129,4 +132,4 @@
Rune otfglyph2rune(Otf *o, int g);
Glyf *otfglyf(Otf *o, int index);
-GlyfImage *otfdrawglyf(Otf *o, Glyf *g, double ppem, double scaleX, double scaleY);
+GlyfImage *otfdrawglyf(Otf *o, Glyf *g, double ppemX, double ppemY);
--- a/otf.rkt
+++ b/otf.rkt
@@ -201,48 +201,47 @@
{uint16 numberOfHMetrics ->o}
#:tag "hhea")
-(mkcmplx EbdtComponent
- {uint16 glyphID}
- {int8 xOffset}
- {int8 yOffset})
+(mkcmplx EbdtComponent {uint16 glyphID} {int8 xOffset} {int8 yOffset})
-(mkcmplx
- Glyf
- {int16 numberOfContours ->o}
- {int16 xMin}
- {int16 yMin}
- {int16 xMax}
- {int16 yMax}
- #:extra
- (list (cons 'field (list (~a "int index;")
- (~a "int type;")
- (~a "union {");
- (~a " ComponentGlyph *component;")
- (~a " SimpleGlyph *simple;")
- (~a " BitmapGlyph *bitmap;")
- (~a "};")))
- (cons 'read
- (list (~a "if(v->numberOfContours < 0){")
- (~a " if(read_ComponentGlyph(o, &v->component, 0) < 0)")
- (~a " goto err;")
- (~a " v->type = GLYPH_COMPONENT;")
- (~a "}else if(v->numberOfContours > 0){")
- (~a " if(read_SimpleGlyph(o, &v->simple) < 0)")
- (~a " goto err;")
- (~a " v->type = GLYPH_SIMPLE;")
- (~a "}else if(o->td.eblc != nil && o->td.ebdt != nil)")
- (~a " v->type = GLYPH_BITMAP;")))
- (cons 'print
- (list (~a "if(v->type == GLYPH_BITMAP){")
- (~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"bitmap\");")
- (~a " print_BitmapGlyph(f, indent+indentΔ, o, v->bitmap);")
- (~a "}else if(v->type == GLYPH_COMPONENT){")
- (~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"component\");")
- (~a " print_ComponentGlyph(f, indent+indentΔ, o, v->component);")
- (~a "}else if(v->type == GLYPH_SIMPLE){")
- (~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"simple\");")
- (~a " print_SimpleGlyph(f, indent+indentΔ, o, v->simple);")
- (~a "}")))))
+(mkcmplx Glyf
+ {int16 numberOfContours ->o}
+ {int16 xMin}
+ {int16 yMin}
+ {int16 xMax}
+ {int16 yMax}
+ #:extra
+ (list (cons 'field
+ (list (~a "int index;")
+ (~a "int type;")
+ (~a "union {") ;
+ (~a " ComponentGlyph *component;")
+ (~a " SimpleGlyph *simple;")
+ (~a " BitmapGlyph *bitmap;")
+ (~a "};")))
+ (cons 'read
+ (list (~a "if(v->numberOfContours < 0){")
+ (~a " if(read_ComponentGlyph(o, &v->component, 0) < 0)")
+ (~a " goto err;")
+ (~a " v->type = GLYPH_COMPONENT;")
+ (~a "}else if(v->numberOfContours > 0){")
+ (~a " if(read_SimpleGlyph(o, &v->simple) < 0)")
+ (~a " goto err;")
+ (~a " v->type = GLYPH_SIMPLE;")
+ (~a "}else if(o->td.eblc != nil && o->td.ebdt != nil)")
+ (~a " v->type = GLYPH_BITMAP;")
+ (~a "else")
+ (~a " v->type = GLYPH_EMPTY;")))
+ (cons 'print
+ (list (~a "if(v->type == GLYPH_BITMAP){")
+ (~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"bitmap\");")
+ (~a " print_BitmapGlyph(f, indent+indentΔ, o, v->bitmap);")
+ (~a "}else if(v->type == GLYPH_COMPONENT){")
+ (~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"component\");")
+ (~a " print_ComponentGlyph(f, indent+indentΔ, o, v->component);")
+ (~a "}else if(v->type == GLYPH_SIMPLE){")
+ (~a " f->print(f->aux, \"%*s%s:\\n\", indent, \"\", \"simple\");")
+ (~a " print_SimpleGlyph(f, indent+indentΔ, o, v->simple);")
+ (~a "}")))))
(mkcmplx LongHorMetric {UFWORD advanceWidth} {FWORD lsb})
@@ -672,7 +671,8 @@
{Offset16 shortOffsets [+ o->numGlyphs 1] (== o->indexToLocFormat 0)}
{Offset32 longOffsets [+ o->numGlyphs 1] (== o->indexToLocFormat 1)}
#:tag "loca"
- #:after (list TableHead TableMaxp))
+ #:after (list TableHead TableMaxp)
+ #:optional #t)
(define variationAxisRecordFlags #hash((0 . VARIATIONAXISRECORD_FL_HIDDEN_AXIS)))
@@ -954,7 +954,8 @@
(~a " v->" (ptr c) " = calloc(1, sizeof(" (cmplx-name c) "));")
(~a " if(read_" (cmplx-name c) "(o, v->" (ptr c) ") < 0){")
(~a " free(v->" (ptr c) ");")
- (~a " goto err;")
+ (~a " v->" (ptr c) " = nil;")
+ (~a " " (if (cmplx-optional c) "break;" "goto err;"))
(~a " }")
(~a " rec->parsed = v->" (ptr c) ";")
(~a " rec->print = (void*)print_" (cmplx-name c) ";")
--- a/plan9/otf.c
+++ b/plan9/otf.c
@@ -249,6 +249,7 @@
f->print(a, "%*s%s: %d\n", indent, "", "format", v->format);
f->print(a, "%*s%s: %d\n", indent, "", "offset", v->offset);
if(v->size > 0){
+ f->print(a, "%*s%s: %d\n", indent, "", "pitchBits", v->pitchBits);
f->print(a, "%*s%s: %d\n", indent, "", "size", v->size);
f->print(a, "%*s%s: ", indent, "", "image");
for(i = 0; i < v->size; i++)
@@ -255,8 +256,10 @@
f->print(a, "%02"PRIx8, v->image[i]);
f->print(a, "\n");
}
+ f->print(a, "%*s%s: %d\n", indent, "", "ppemX", v->ppemX);
+ f->print(a, "%*s%s: %d\n", indent, "", "ppemY", v->ppemY);
if(v->numComponents > 0){
- f->print(a, "%*s%s: %d\n", indent, "", "numComponents");
+ f->print(a, "%*s%s: %d\n", indent, "", "numComponents", v->numComponents);
f->print(a, "%*s%s:\n", indent, "", "components");
for(i = 0; i < v->numComponents; i++){
f->print(a, "%*s%d:\n", indent+indentΔ, "", i);
@@ -552,7 +555,7 @@
bitebdt(Otf *o, Glyf *g, BitmapGlyph *bg)
{
u8int *b;
- int i;
+ int i, n;
if(o->ebdt == nil){
for(i = 0; i < o->td.numTables; i++){
@@ -580,7 +583,6 @@
g->yMin = sm.bearingY - sm.height;
g->xMax = sm.bearingX + sm.width;
g->yMax = sm.bearingY;
- bg->size -= 6;
}else if(bg->format == 6 || bg->format == 7 || bg->format == 9){
BigGlyphMetrics bm;
if(read_BigGlyphMetrics(o, &bm) < 0)
@@ -592,24 +594,34 @@
g->yMin = -(int)bm.horiBearingY;
g->xMax += g->xMin;
g->yMax += g->yMin;
- bg->size -= 8;
}
bg->numComponents = 0;
+ if(bg->format == 2 || bg->format == 5 || bg->format == 7){
+ /* bit-aligned - last row is padded to a full byte */
+ bg->pitchBits = g->xMax - g->xMin;
+ bg->size = (bg->pitchBits*(g->yMax-g->yMin)*bg->bitDepth + 7)/8;
+ }else{
+ /* byte-aligned - every row is byte-aligned */
+ n = ((g->xMax-g->xMin)*bg->bitDepth + 7)/8;
+ bg->size = n * (g->yMax-g->yMin);
+ bg->pitchBits = n * 8;
+ }
+
switch(bg->format){
case 8:
if(otfreadn(o, 1) == nil) /* skip uint8 pad */
goto err;
- bg->size -= 1;
/* fallthrough */
case 9:
if((b = otfreadn(o, 2)) == nil)
goto err;
bg->numComponents = b[0]<<8 | b[1];
- bg->size -= 2;
if(otfarray(o, &bg->components, read_EbdtComponent, sizeof(EbdtComponent), bg->numComponents) < 0)
goto err;
- bg->size -= 4*bg->numComponents;
+ /* no image, both 8 and 9 are component */
+ bg->pitchBits = 0;
+ bg->size = 0;
/* fallthrough */
case 1:
case 2:
@@ -616,11 +628,14 @@
case 5:
case 6:
case 7:
- if((b = otfreadn(o, bg->size)) == nil)
- goto err;
g->bitmap = malloc(sizeof(*bg) + bg->size);
memcpy(g->bitmap, bg, sizeof(*bg));
- memcpy(g->bitmap->image, b, bg->size);
+ if(bg->size > 0){
+ if((b = otfreadn(o, bg->size)) == nil)
+ goto err;
+ memcpy(g->bitmap->image, b, bg->size);
+ }
+ break;
}
otfpoprange(o);
otfpoprange(o);
@@ -647,8 +662,10 @@
for(i = 0; i < (int)o->td.eblc->numSizes; i++, bs++){
if(g->index >= bs->startGlyphIndex && g->index <= bs->endGlyphIndex){
b.bitDepth = bs->bitDepth;
+ b.ppemX = bs->ppemX;
+ b.ppemY = bs->ppemY;
isr = bs->indexSubtableList;
- for(j = 0; j < (int)bs->numberOfIndexSubtables; j++){
+ for(j = 0; j < (int)bs->numberOfIndexSubtables; j++, isr++){
if(g->index >= isr->firstGlyphIndex && g->index <= isr->lastGlyphIndex){
is = isr->indexSubtable;
if(is == nil)
@@ -781,7 +798,6 @@
}
otfpoprange(o);
otfpoprange(o);
- g->type = g->numberOfContours < 0 ? GLYPH_COMPONENT : GLYPH_SIMPLE;
return g;
err:
@@ -1958,6 +1974,7 @@
f->print(f->aux, "%*s%s: %ud\n", indent, "", "macStyle", v->macStyle);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lowestRecPPEM", v->lowestRecPPEM);
f->print(f->aux, "%*s%s: %d\n", indent, "", "indexToLocFormat", v->indexToLocFormat);
+ o->indexToLocFormat = v->indexToLocFormat;
USED(o);
}
@@ -2017,6 +2034,7 @@
f->print(f->aux, "%*s%s: %d\n", indent, "", "caretOffset", v->caretOffset);
f->print(f->aux, "%*s%s: %d\n", indent, "", "metricDataFormat", v->metricDataFormat);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numberOfHMetrics", v->numberOfHMetrics);
+ o->numberOfHMetrics = v->numberOfHMetrics;
USED(o);
}
@@ -2066,6 +2084,8 @@
v->type = GLYPH_SIMPLE;
}else if(o->td.eblc != nil && o->td.ebdt != nil)
v->type = GLYPH_BITMAP;
+ else
+ v->type = GLYPH_EMPTY;
return 0;
err:
werrstr("%s: %r", "Glyf");
@@ -2076,6 +2096,7 @@
print_Glyf(Otfile *f, int indent, Otf *o, Glyf *v)
{
f->print(f->aux, "%*s%s: %d\n", indent, "", "numberOfContours", v->numberOfContours);
+ o->numberOfContours = v->numberOfContours;
f->print(f->aux, "%*s%s: %d\n", indent, "", "xMin", v->xMin);
f->print(f->aux, "%*s%s: %d\n", indent, "", "yMin", v->yMin);
f->print(f->aux, "%*s%s: %d\n", indent, "", "xMax", v->xMax);
@@ -2138,6 +2159,7 @@
print_TableMaxp(Otfile *f, int indent, Otf *o, TableMaxp *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "numGlyphs", v->numGlyphs);
+ o->numGlyphs = v->numGlyphs;
USED(o);
}
@@ -2236,7 +2258,9 @@
print_NameRecord(Otfile *f, int indent, Otf *o, NameRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "platformID", v->platformID);
+ o->platformID = v->platformID;
f->print(f->aux, "%*s%s: %ud\n", indent, "", "encodingID", v->encodingID);
+ o->encodingID = v->encodingID;
f->print(f->aux, "%*s%s: %ud\n", indent, "", "languageID", v->languageID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "nameID", v->nameID);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "stringLength", v->stringLength);
@@ -2319,6 +2343,7 @@
f->print(f->aux, "%*s%s: %ud\n", indent, "", "version", v->version);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "count", v->count);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "storageOffset", v->storageOffset);
+ o->storageOffset = v->storageOffset;
for(int i = 0; i < v->count; i++){
f->print(f->aux, "%*s%s[%d]:\n", indent, "", "nameRecord", i);
print_NameRecord(f, indent+indentΔ, o, &v->nameRecord[i]);
@@ -2703,7 +2728,9 @@
print_IndexSubtableRecord(Otfile *f, int indent, Otf *o, IndexSubtableRecord *v)
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "firstGlyphIndex", v->firstGlyphIndex);
+ o->firstGlyphIndex = v->firstGlyphIndex;
f->print(f->aux, "%*s%s: %ud\n", indent, "", "lastGlyphIndex", v->lastGlyphIndex);
+ o->lastGlyphIndex = v->lastGlyphIndex;
f->print(f->aux, "%*s%s: %ud\n", indent, "", "indexSubtableOffset", v->indexSubtableOffset);
f->print(f->aux, "%*s%s:\n", indent, "", "indexSubtable");
if(v->indexSubtable != nil)
@@ -5034,8 +5061,11 @@
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axesArrayOffset", v->axesArrayOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisCount", v->axisCount);
+ o->axisCount = v->axisCount;
f->print(f->aux, "%*s%s: %ud\n", indent, "", "instanceCount", v->instanceCount);
+ o->instanceCount = v->instanceCount;
f->print(f->aux, "%*s%s: %ud\n", indent, "", "instanceSize", v->instanceSize);
+ o->instanceSize = v->instanceSize;
f->print(f->aux, "%*s%s:\n", indent, "", "axisInstances");
if(v->axisInstances != nil)
print_AxisInstances(f, indent+indentΔ, o, v->axisInstances);
@@ -5567,9 +5597,12 @@
{
f->print(f->aux, "%*s%s: %ud\n", indent, "", "minorVersion", v->minorVersion);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "designAxisSize", v->designAxisSize);
+ o->designAxisSize = v->designAxisSize;
f->print(f->aux, "%*s%s: %ud\n", indent, "", "designAxisCount", v->designAxisCount);
+ o->designAxisCount = v->designAxisCount;
f->print(f->aux, "%*s%s: %ud\n", indent, "", "designAxesOffset", v->designAxesOffset);
f->print(f->aux, "%*s%s: %ud\n", indent, "", "axisValueCount", v->axisValueCount);
+ o->axisValueCount = v->axisValueCount;
f->print(f->aux, "%*s%s: %ud\n", indent, "", "offsetToAxisValueOffsets", v->offsetToAxisValueOffsets);
if(v->minorVersion > 0)
f->print(f->aux, "%*s%s: %ud\n", indent, "", "elidedFallbackNameID", v->elidedFallbackNameID);
@@ -6075,6 +6108,7 @@
v->cmap = calloc(1, sizeof(TableCmap));
if(read_TableCmap(o, v->cmap) < 0){
free(v->cmap);
+ v->cmap = nil;
goto err;
}
rec->parsed = v->cmap;
@@ -6086,6 +6120,7 @@
v->head = calloc(1, sizeof(TableHead));
if(read_TableHead(o, v->head) < 0){
free(v->head);
+ v->head = nil;
goto err;
}
rec->parsed = v->head;
@@ -6097,6 +6132,7 @@
v->hhea = calloc(1, sizeof(TableHhea));
if(read_TableHhea(o, v->hhea) < 0){
free(v->hhea);
+ v->hhea = nil;
goto err;
}
rec->parsed = v->hhea;
@@ -6108,6 +6144,7 @@
v->maxp = calloc(1, sizeof(TableMaxp));
if(read_TableMaxp(o, v->maxp) < 0){
free(v->maxp);
+ v->maxp = nil;
goto err;
}
rec->parsed = v->maxp;
@@ -6133,6 +6170,7 @@
v->hmtx = calloc(1, sizeof(TableHmtx));
if(read_TableHmtx(o, v->hmtx) < 0){
free(v->hmtx);
+ v->hmtx = nil;
goto err;
}
rec->parsed = v->hmtx;
@@ -6144,6 +6182,7 @@
v->post = calloc(1, sizeof(TablePost));
if(read_TablePost(o, v->post) < 0){
free(v->post);
+ v->post = nil;
goto err;
}
rec->parsed = v->post;
@@ -6155,6 +6194,7 @@
v->name = calloc(1, sizeof(TableName));
if(read_TableName(o, v->name) < 0){
free(v->name);
+ v->name = nil;
goto err;
}
rec->parsed = v->name;
@@ -6166,6 +6206,7 @@
v->ebdt = calloc(1, sizeof(TableEBDT));
if(read_TableEBDT(o, v->ebdt) < 0){
free(v->ebdt);
+ v->ebdt = nil;
goto err;
}
rec->parsed = v->ebdt;
@@ -6177,6 +6218,7 @@
v->eblc = calloc(1, sizeof(TableEBLC));
if(read_TableEBLC(o, v->eblc) < 0){
free(v->eblc);
+ v->eblc = nil;
goto err;
}
rec->parsed = v->eblc;
@@ -6188,6 +6230,7 @@
v->gdef = calloc(1, sizeof(TableGDEF));
if(read_TableGDEF(o, v->gdef) < 0){
free(v->gdef);
+ v->gdef = nil;
goto err;
}
rec->parsed = v->gdef;
@@ -6199,6 +6242,7 @@
v->gpos = calloc(1, sizeof(TableGPOS));
if(read_TableGPOS(o, v->gpos) < 0){
free(v->gpos);
+ v->gpos = nil;
goto err;
}
rec->parsed = v->gpos;
@@ -6210,6 +6254,7 @@
v->gsub = calloc(1, sizeof(TableGSUB));
if(read_TableGSUB(o, v->gsub) < 0){
free(v->gsub);
+ v->gsub = nil;
goto err;
}
rec->parsed = v->gsub;
@@ -6221,6 +6266,7 @@
v->math = calloc(1, sizeof(TableMATH));
if(read_TableMATH(o, v->math) < 0){
free(v->math);
+ v->math = nil;
goto err;
}
rec->parsed = v->math;
@@ -6232,6 +6278,7 @@
v->kern = calloc(1, sizeof(TableKern));
if(read_TableKern(o, v->kern) < 0){
free(v->kern);
+ v->kern = nil;
goto err;
}
rec->parsed = v->kern;
@@ -6257,7 +6304,8 @@
v->loca = calloc(1, sizeof(TableLoca));
if(read_TableLoca(o, v->loca) < 0){
free(v->loca);
- goto err;
+ v->loca = nil;
+ break;
}
rec->parsed = v->loca;
rec->print = (void*)print_TableLoca;
@@ -6268,6 +6316,7 @@
v->fvar = calloc(1, sizeof(TableFvar));
if(read_TableFvar(o, v->fvar) < 0){
free(v->fvar);
+ v->fvar = nil;
goto err;
}
rec->parsed = v->fvar;
@@ -6293,6 +6342,7 @@
v->hvar = calloc(1, sizeof(TableHVAR));
if(read_TableHVAR(o, v->hvar) < 0){
free(v->hvar);
+ v->hvar = nil;
goto err;
}
rec->parsed = v->hvar;
@@ -6304,6 +6354,7 @@
v->fftm = calloc(1, sizeof(TableFFTM));
if(read_TableFFTM(o, v->fftm) < 0){
free(v->fftm);
+ v->fftm = nil;
goto err;
}
rec->parsed = v->fftm;
@@ -6315,6 +6366,7 @@
v->dsig = calloc(1, sizeof(TableDSIG));
if(read_TableDSIG(o, v->dsig) < 0){
free(v->dsig);
+ v->dsig = nil;
goto err;
}
rec->parsed = v->dsig;
@@ -6326,6 +6378,7 @@
v->stat = calloc(1, sizeof(TableSTAT));
if(read_TableSTAT(o, v->stat) < 0){
free(v->stat);
+ v->stat = nil;
goto err;
}
rec->parsed = v->stat;
@@ -6337,6 +6390,7 @@
v->gasp = calloc(1, sizeof(TableGasp));
if(read_TableGasp(o, v->gasp) < 0){
free(v->gasp);
+ v->gasp = nil;
goto err;
}
rec->parsed = v->gasp;
@@ -6362,6 +6416,7 @@
v->gvar = calloc(1, sizeof(TableGvar));
if(read_TableGvar(o, v->gvar) < 0){
free(v->gvar);
+ v->gvar = nil;
goto err;
}
rec->parsed = v->gvar;
@@ -6373,6 +6428,7 @@
v->avar = calloc(1, sizeof(TableAvar));
if(read_TableAvar(o, v->avar) < 0){
free(v->avar);
+ v->avar = nil;
goto err;
}
rec->parsed = v->avar;
@@ -6384,6 +6440,7 @@
v->os∕2 = calloc(1, sizeof(TableOS∕2));
if(read_TableOS∕2(o, v->os∕2) < 0){
free(v->os∕2);
+ v->os∕2 = nil;
goto err;
}
rec->parsed = v->os∕2;
--- a/plan9/otf.h
+++ b/plan9/otf.h
@@ -52,6 +52,9 @@
int format;
int offset;
int size;
+ int pitchBits;
+ int ppemX;
+ int ppemY;
int numComponents;
EbdtComponent *components;
u8int image[];
@@ -130,7 +133,7 @@
Rune otfglyph2rune(Otf *o, int g);
Glyf *otfglyf(Otf *o, int index);
-GlyfImage *otfdrawglyf(Otf *o, Glyf *g, double ppem, double scaleX, double scaleY);
+GlyfImage *otfdrawglyf(Otf *o, Glyf *g, double ppemX, double ppemY);
typedef struct SubHeader SubHeader;
typedef struct MapGroup MapGroup;
--- a/rast.c
+++ b/rast.c
@@ -548,15 +548,14 @@
}
static GlyfImage *
-outlineglyf(Otf *o, Glyf *g, double ppem, double scaleX, double scaleY)
+outlineglyf(Otf *o, Glyf *g, double ppemX, double ppemY)
{
int i, j, maxptstotal, maxpts, ngs, w, h, npx, baseline;
+ Sval bb[4], offY, scaleX, scaleY;
Glyf *gs[MAXCOMPONENTS] = {nil};
ComponentGlyph *cg;
SegQ *s₀, *s, *p;
GlyfImage *im;
- Sval bb[4];
- Sval offY;
Spt *pts;
ngs = 0;
@@ -563,7 +562,7 @@
pts = nil;
im = nil;
- if(g->simple != nil){
+ if(g->type == GLYPH_SIMPLE){
gs[ngs++] = g;
}else{
for(cg = g->component; cg != nil && ngs < nelem(gs); cg = cg->next, ngs++){
@@ -589,14 +588,14 @@
*/
pts = calloc(1, maxpts*sizeof(*pts) + maxptstotal/2*sizeof(*s));
- scaleX *= ppem / o->td.head->unitsPerEm;
- scaleY *= ppem / o->td.head->unitsPerEm;
+ scaleX = ppemX / o->td.head->unitsPerEm;
+ scaleY = ppemY / o->td.head->unitsPerEm;
bb[0] = g->xMin*scaleX;
bb[1] = g->yMin*scaleY;
bb[2] = g->xMax*scaleX;
bb[3] = g->yMax*scaleY;
s = s₀ = (SegQ*)(pts + maxpts);
- cg = g->component;
+ cg = g->type == GLYPH_COMPONENT ? g->component : nil;
for(i = 0; i < ngs; i++){
Sval dx = 0, dy = 0, gscaleX = scaleX, gscaleY = scaleY;
if(cg != nil){
@@ -681,67 +680,129 @@
return im;
}
+static u8int
+bitpixel(BitmapGlyph *bg, int x, int y)
+{
+ int i;
+
+ if(bg->bitDepth == 1){
+ if(bg->format == 2 || bg->format == 5){
+ i = y*bg->pitchBits + x;
+ x = i - (i & ~7);
+ return (bg->image[i>>3] & (0x80>>x)) ? 255 : 0;
+ }
+ i = y*bg->pitchBits+x;
+ x &= 7;
+ return (bg->image[i>>3] & (0x80>>x)) ? 255 : 0;
+ }
+ return 0;
+}
+
+static void
+bitblit(Glyf *g, GlyfImage *im, int zoomX, int zoomY, int *bb)
+{
+ int i, x, y, w, h, tmp;
+ BitmapGlyph *bg;
+ u8int *b, *p, v;
+
+ bg = g->bitmap;
+ w = g->xMax - g->xMin;
+ h = g->yMax - g->yMin;
+ b = im->b + (g->yMin - bb[1])*im->w + (g->xMin - bb[0]);
+
+ for(y = 0; y < h; y++){
+ p = b;
+ for(x = 0; x < w; x++){
+ v = bitpixel(bg, x, y);
+#define blend(a,b) (tmp = a+b, tmp > 255 ? 255 : tmp)
+ *b = blend(*b, v);
+ b++;
+ for(i = 1; i < zoomX; i++, b++)
+ *b = blend(b[0], b[-1]);
+#undef blend
+ }
+ for(i = 1; i < zoomY; i++, b += im->w)
+ memcpy(b, p, w*zoomX);
+ }
+}
+
GlyfImage *
-bitmapglyf(Otf *o, Glyf *g, double ppem, double scaleX, double scaleY)
+bitmapglyf(Otf *o, Glyf *g, double ppemX, double ppemY)
{
- int zoomX, zoomY, w, h, x, y, i;
+ int zoomX, zoomY, n, w, h, x, y, i, bb[4], ngs;
+ Glyf *gs[MAXCOMPONENTS], *cg;
+ EbdtComponent *c;
BitmapGlyph *bg;
GlyfImage *im;
- u8int *b, *p;
USED(o);
+ im = nil;
bg = g->bitmap;
- if(bg->numComponents > 0){
- /* FIXME implement this. components may also be outlines */
- werrstr("components not implemented");
- return nil;
- }
-
- if((zoomX = scaleX * ppem / 72) < 1)
+ if((zoomX = ppemX/bg->ppemX) < 1)
zoomX = 1;
- if((zoomY = scaleY * ppem / 72) < 1)
+ if((zoomY = ppemY/bg->ppemY) < 1)
zoomY = 1;
- w = g->xMax - g->xMin;
- h = g->yMax - g->yMin;
+ bb[0] = g->xMin;
+ bb[1] = g->yMin;
+ bb[2] = g->xMax;
+ bb[3] = g->yMax;
+ for(ngs = 0; ngs < nelem(gs) && ngs < bg->numComponents;){
+ c = bg->components + ngs;
+ if((cg = gs[ngs] = otfglyf(o, c->glyphID)) == nil)
+ goto err;
+ ngs++;
+ if(cg->type != GLYPH_BITMAP){
+ /* FIXME spec allows outlines here, oh well */
+ werrstr("component glyph not a bitmap");
+ goto err;
+ }
+ if(bb[0] > (x = cg->xMin+c->xOffset))
+ bb[0] = x;
+ if(bb[1] > (y = cg->yMin+c->yOffset))
+ bb[1] = y;
+ if(bb[2] > (x = cg->xMax+c->xOffset))
+ bb[2] = x;
+ if(bb[3] > (y = cg->yMax+c->yOffset))
+ bb[3] = y;
+ }
+
+ w = bb[2] - bb[0];
+ h = bb[3] - bb[1];
im = calloc(1, sizeof(*im) + w*zoomX*h*zoomY);
im->w = w*zoomX;
im->h = h*zoomY;
- im->baseline = g->yMin * zoomY;
- b = im->b;
- if(bg->bitDepth == 1){
- for(y = 0; y < h; y++){
- p = b;
- for(x = w-1; x >= 0; x--){
- *b++ = (bg->image[(y*w+x)/8] & (1<<(x&7))) ? 0 : 255;
- for(i = 1; i < zoomX; i++, b++)
- *b = b[-1];
- }
- for(i = 1; i < zoomY; i++, b += im->w)
- memcpy(b, p, im->w);
- }
- }else if(bg->bitDepth == 4){
- /* FIXME */
- werrstr("bitDepth 4 not implemented");
- free(im);
- im = nil;
- }else if(bg->bitDepth == 8){
- /* FIXME */
- werrstr("bitDepth 8 not implemented");
- free(im);
- im = nil;
+ im->baseline = bb[1] * zoomY;
+
+ bitblit(g, im, zoomX, zoomY, bb);
+ for(i = 0; i < ngs; i++)
+ bitblit(gs[i], im, zoomX, zoomY, bb);
+ n = im->w*im->h;
+ for(i = 0; i < n; i++)
+ im->b[i] = 255 - im->b[i];
+
+ for(i = 0; i < ngs; i++){
+ free(gs[i]->bitmap);
+ free(gs[i]);
}
return im;
+err:
+ for(i = 0; i < ngs; i++){
+ free(gs[i]->bitmap);
+ free(gs[i]);
+ }
+ free(im);
+ return nil;
}
GlyfImage *
-otfdrawglyf(Otf *o, Glyf *g, double ppem, double scaleX, double scaleY)
+otfdrawglyf(Otf *o, Glyf *g, double ppemX, double ppemY)
{
if(g->type == GLYPH_SIMPLE || g->type == GLYPH_COMPONENT)
- return outlineglyf(o, g, ppem, scaleX, scaleY);
+ return outlineglyf(o, g, ppemX, ppemY);
if(g->type == GLYPH_BITMAP)
- return bitmapglyf(o, g, ppem, scaleX, scaleY);
+ return bitmapglyf(o, g, ppemX, ppemY);
werrstr("empty glyph");
return nil;
}
--- a/test.h
+++ b/test.h
@@ -10,14 +10,14 @@
f->print(f->aux, " -m: print out glyph ids or render them all as a map (with -p)\n");
f->print(f->aux, " -R: ignore glyphs that do not represent valid runes\n");
f->print(f->aux, " -H: highlight a specific glyph in the map by its ID\n");
- f->print(f->aux, " -x: horizontal scale factor\n");
- f->print(f->aux, " -y: vertical scale factor\n");
+ f->print(f->aux, " -x: horizontal ppem\n");
+ f->print(f->aux, " -y: vertical ppem\n");
f->print(f->aux, "Specifying -m more than once adds guide lines\n");
f->print(f->aux, "Specifying -m more than twice makes empty pixels filled out\n");
}
static int gind = -1, map, highlight = -1, runesonly;
-static double ppem, scaleX = 1, scaleY = 1;
+static double ppemX, ppemY;
static Rune rune = NoRune;
static char *gtypes[] = {
[GLYPH_EMPTY] = "empty",
@@ -147,7 +147,7 @@
goto glypherr;
}
if(map && gind < 0){
- im = ppem > 0 ? calloc(n, sizeof(*im)) : nil;
+ im = ppemX > 0 ? calloc(n, sizeof(*im)) : nil;
for(i = 0; i < n; i++){
if(runesonly && otfglyph2rune(o, i) == NoRune)
continue;
@@ -157,16 +157,18 @@
werrstr("glyph %d: %r", gind);
return -1;
}
- if(ppem > 0 && g->type != GLYPH_EMPTY){
- if((im[i] = otfdrawglyf(o, g, ppem, scaleX, scaleY)) == nil)
+ if(ppemX > 0 && g->type != GLYPH_EMPTY){
+ if((im[i] = otfdrawglyf(o, g, ppemX, ppemY)) == nil){
+ gind = i;
goto glypherr;
- }else if(ppem <= 0){
+ }
+ }else if(ppemX <= 0){
out->print(out->aux, "%d (%s):\n", i, gtypes[g->type]);
print_Glyf(out, indentΔ, o, g);
}
free(g);
}
- if(ppem > 0){
+ if(ppemX > 0){
if(out->write != otfdiscard && dumpmap(out, im, n) != 0)
return -1;
for(i = 0; i < n; i++)
@@ -178,9 +180,9 @@
}else{
if((g = otfglyf(o, gind)) == nil){
goto glypherr;
- }else if(ppem > 0){
+ }else if(ppemX > 0){
GlyfImage *im;
- if((im = otfdrawglyf(o, g, ppem, scaleX, scaleY)) == nil)
+ if((im = otfdrawglyf(o, g, ppemX, ppemY)) == nil)
goto glypherr;
if(out->write != otfdiscard && dumpmap(out, &im, 1) != 0)
return -1;
@@ -211,7 +213,7 @@
map++; \
break; \
case 'p': \
- ppem = strtod(EARGF(usage(&out)), nil); \
+ ppemX = ppemY = strtod(EARGF(usage(&out)), nil); \
break; \
case 'r': { \
char *s = EARGF(usage(&out)); \
@@ -228,13 +230,17 @@
runesonly++; \
break; \
case 'x': \
- scaleX = strtod(EARGF(usage(&out)), nil); \
+ ppemX = strtod(EARGF(usage(&out)), nil); \
break; \
case 'y': \
- scaleY = strtod(EARGF(usage(&out)), nil); \
+ ppemY = strtod(EARGF(usage(&out)), nil); \
break; \
default: \
usage(&out); \
}ARGEND \
if(argc != 1) \
- usage(&out);
+ usage(&out); \
+ if(ppemX == 0 && ppemY != 0) \
+ ppemX = ppemY; \
+ if(ppemY == 0 && ppemX != 0) \
+ ppemY = ppemX;