ref: a65e44617ba1d08e011f3cee56470a0a7351ea47
parent: c8e83c81d910049123621d766bc837abc9103145
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Jun 25 19:11:38 EDT 2024
fix glyf parsing, add pretty-printing too
--- a/otf.c
+++ b/otf.c
@@ -4,6 +4,8 @@
#include <bio.h>
#include "otf.h"
+int indentΔ = 2;
+
typedef struct Range Range;
struct Otf {
@@ -12,7 +14,10 @@
u8int *buf;
int bufsz;
int off;
+
/* extra fields to simplify parsing */
+ TableDirectory td;
+ TableRecord glyf;
s16int indexToLocFormat;
u16int numberOfHMetrics;
s16int numberOfContours;
@@ -125,11 +130,22 @@
Bterm(f);
}else{
o->f = f;
+ if(read_TableDirectory(o, &o->td) != 0){
+ Bterm(f);
+ free(o);
+ o = nil;
+ }
}
return o;
}
void
+otfprint(Otf *o, Biobuf *out, int indent)
+{
+ print_TableDirectory(out, indent, o, &o->td);
+}
+
+void
otfclose(Otf *o)
{
if(o == nil)
@@ -199,6 +215,13 @@
return -1;
}
+static void
+otfpopranges(Otf *o)
+{
+ while(o->r != nil)
+ otfpoprange(o);
+}
+
static u8int *
otfreadn(Otf *o, int n)
{
@@ -253,6 +276,11 @@
return -1;
}
+enum {
+ CGLYPH_FL_WORD_ARGS = 1<<0,
+ CGLYPH_FL_SIGNED_XY = 1<<1,
+};
+
static int
read_ComponentGlyph(Otf *o, ComponentGlyph **out, int instr)
{
@@ -272,11 +300,21 @@
instr |= v->flags & CGLYPH_FL_INSTRUCTIONS;
if((v->flags & CGLYPH_FL_WORD_ARGS) != 0 && (b = otfreadn(o, 2*2)) != nil){
- v->arg1.u16 = b[0]<<8 | b[1];
- v->arg2.u16 = b[2]<<8 | b[3];
+ if(v->flags & CGLYPH_FL_SIGNED_XY){
+ v->arg1 = (s16int)(b[0]<<8 | b[1]);
+ v->arg2 = (s16int)(b[2]<<8 | b[3]);
+ }else{
+ v->arg1 = b[0]<<8 | b[1];
+ v->arg1 = b[2]<<8 | b[3];
+ }
}else if((b = otfreadn(o, 2)) != nil){
- v->arg1.u8 = b[0];
- v->arg2.u8 = b[1];
+ if(v->flags & CGLYPH_FL_SIGNED_XY){
+ v->arg1 = (s8int)b[0];
+ v->arg2 = (s8int)b[1];
+ }else{
+ v->arg1 = b[0];
+ v->arg2 = b[1];
+ }
}
if(b == nil)
goto err;
@@ -318,6 +356,50 @@
return -1;
}
+void
+print_ComponentGlyph(Biobuf *f, int indent, Otf *o, ComponentGlyph *v)
+{
+ Bprint(f, "%*s%s: %#ux%s%s%s%s%s%s%s%s%s%s\n", indent, "", "flags", v->flags,
+ (v->flags&CGLYPH_FL_ROUND_TO_GRID_XY)?" CGLYPH_FL_ROUND_TO_GRID_XY":"",
+ (v->flags&CGLYPH_FL_SCALE)?" CGLYPH_FL_SCALE":"",
+ (v->flags&CGLYPH_FL_MORE_COMPONENTS)?" CGLYPH_FL_MORE_COMPONENTS":"",
+ (v->flags&CGLYPH_FL_SCALE_XY)?" CGLYPH_FL_SCALE_XY":"",
+ (v->flags&CGLYPH_FL_2X2_TRANSFORM)?" CGLYPH_FL_2X2_TRANSFORM":"",
+ (v->flags&CGLYPH_FL_INSTRUCTIONS)?" CGLYPH_FL_INSTRUCTIONS":"",
+ (v->flags&CGLYPH_FL_METRICS)?" CGLYPH_FL_METRICS":"",
+ (v->flags&CGLYPH_FL_OVERLAP_COMPOUND)?" CGLYPH_FL_OVERLAP_COMPOUND":"",
+ (v->flags&CGLYPH_FL_SCALED_COMPONENT_OFFSET)?" CGLYPH_FL_SCALED_COMPONENT_OFFSET":"",
+ (v->flags&CGLYPH_FL_UNSCALED_COMPONENT_OFFSET)?" CGLYPH_FL_UNSCALED_COMPONENT_OFFSET":""
+ );
+ Bprint(f, "%*s%s: %ud\n", indent, "", "glyphIndex", v->glyphIndex);
+ if(v->arg1 != 0 || v->arg2 != 0){
+ Bprint(f, "%*s%s: %d\n", indent, "", "arg1", v->arg1);
+ Bprint(f, "%*s%s: %d\n", indent, "", "arg2", v->arg2);
+ }
+ if(v->flags & CGLYPH_FL_SCALE){
+ Bprint(f, "%*s%s: %g\n", indent, "", "scale", v->scale);
+ }else if(v->flags & CGLYPH_FL_SCALE_XY){
+ Bprint(f, "%*s%s: %g\n", indent, "", "scaleX", v->scaleX);
+ Bprint(f, "%*s%s: %g\n", indent, "", "scaleY", v->scaleY);
+ }else if(v->flags & CGLYPH_FL_2X2_TRANSFORM){
+ Bprint(f, "%*s%s: %g\n", indent, "", "scaleX", v->scaleX);
+ Bprint(f, "%*s%s: %g\n", indent, "", "scale01", v->scale01);
+ Bprint(f, "%*s%s: %g\n", indent, "", "scale10", v->scale10);
+ Bprint(f, "%*s%s: %g\n", indent, "", "scaleY", v->scaleY);
+ }
+ if(v->numInstr > 0 && v->instr != nil){
+ Bprint(f, "%*s%s: %ud\n", indent, "", "numInstr", v->numInstr);
+ Bprint(f, "%*s%s:", indent, "", "instr");
+ for(int i = 0; i < v->numInstr; i++)
+ Bprint(f, " %02ux", v->instr[i]);
+ Bprint(f, "\n");
+ }
+ if(v->next != nil){
+ Bprint(f, "%*s%s:\n", indent, "", "next");
+ print_ComponentGlyph(f, indent+indentΔ, o, v->next);
+ }
+}
+
enum {
GLYPH_FL_ON_CURVE_POINT = 1<<0,
GLYPH_FL_X_SHORT_VECTOR = 1<<1,
@@ -333,7 +415,7 @@
{
SimpleGlyph *v;
u8int *b, *flags;
- int i, n, nflags, c;
+ int i, n, nflags, c, nc;
flags = nil;
if((v = calloc(1, sizeof(*v))) == nil){
@@ -342,6 +424,7 @@
goto err;
}
+ v->numEndPtsOfContours = o->numberOfContours;
n = o->numberOfContours;
if((b = otfreadn(o, 2*n+2)) == nil)
goto err;
@@ -349,6 +432,7 @@
goto nomem;
for(int i = 0; i < n; i++)
v->endPtsOfContours[i] = b[2*i+0]<<8 | b[2*i+1];
+ v->numPoints = 1 + v->endPtsOfContours[o->numberOfContours-1];
v->instructionLength = b[2*n+0]<<8 | b[2*n+1];
n = v->instructionLength;
@@ -363,23 +447,19 @@
for(nflags = 0; nflags < v->numPoints;){
if((b = otfreadn(o, 1)) == nil)
goto err;
- flags[nflags] = *b;
- if((flags[nflags] & GLYPH_FL_REPEAT) != 0){
- flags[nflags] ^= GLYPH_FL_REPEAT;
+ if((flags[nflags++] = *b) & GLYPH_FL_REPEAT){
+ flags[nflags-1] ^= GLYPH_FL_REPEAT;
if((b = otfreadn(o, 1)) == nil)
goto err;
- if(nflags + 1 + *b > v->numPoints){
- werrstr("repeat overflow");
+ if(nflags + *b > v->numPoints){
+ werrstr("repeat overflow (%d+%d > %d)", nflags, *b, v->numPoints);
goto err;
}
- memset(flags+nflags+1, flags[nflags], *b);
- nflags += 1 + *b;
- }else{
- nflags++;
+ memset(flags+nflags, flags[nflags-1], *b);
+ nflags += *b;
}
}
- v->numPoints = v->endPtsOfContours[o->numberOfContours-1];
if((v->points = calloc(v->numPoints, sizeof(*v->points))) == nil)
goto nomem;
@@ -393,10 +473,10 @@
if((flags[i] & GLYPH_FL_X_SHORT_VECTOR) != 0){
if((b = otfreadn(o, 1)) == nil)
goto err;
- c = *b;
+ nc = *b;
if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) == 0)
- c = -c;
- v->points[n++].x = c;
+ nc = -nc;
+ c = v->points[n++].x = c + nc;
}else if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) != 0){
v->points[n++].x = c;
}else{
@@ -413,10 +493,10 @@
if((flags[i] & GLYPH_FL_Y_SHORT_VECTOR) != 0){
if((b = otfreadn(o, 1)) == nil)
goto err;
- c = *b;
+ nc = *b;
if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) == 0)
- c = -c;
- v->points[n++].y = c;
+ nc = -nc;
+ c = v->points[n++].y = c + nc;
}else if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) != 0){
v->points[n++].y = c;
}else{
@@ -442,7 +522,31 @@
return -1;
}
-int indentΔ = 2;
+void
+print_SimpleGlyph(Biobuf *f, int indent, Otf *o, SimpleGlyph *v)
+{
+ USED(o);
+ if(v->numEndPtsOfContours > 0){
+ Bprint(f, "%*s%s:", indent, "", "endPtsOfContours");
+ for(int i = 0; i < v->numEndPtsOfContours; i++)
+ Bprint(f, " %ud", v->endPtsOfContours[i]);
+ Bprint(f, "\n");
+ }
+ if(v->instructionLength > 0){
+ Bprint(f, "%*s%s: %ud\n", indent, "", "instructionLength", v->instructionLength);
+ Bprint(f, "%*s%s:", indent, "", "instructions");
+ for(int i = 0; i < v->instructionLength; i++)
+ Bprint(f, " %02ux", v->instructions[i]);
+ Bprint(f, "\n");
+ }
+ if(v->numPoints > 0){
+ Bprint(f, "%*s%s: %d\n", indent, "", "numPoints", v->numPoints);
+ Bprint(f, "%*s%s:", indent, "", "points");
+ for(int i = 0; i < v->numPoints; i++)
+ Bprint(f, " (%d,%d,%d)", v->points[i].x, v->points[i].y, v->points[i].onCurve);
+ Bprint(f, "\n");
+ }
+}
static int
Tfmt(Fmt *f)
@@ -477,8 +581,73 @@
fmtinstall('t', tfmt);
}
+Glyf *
+otfglyf(Otf *o, int index)
+{
+ Glyf *g;
+ int off, len, i;
+ if((g = calloc(1, sizeof(*g))) == nil){
+ werrstr("no memory");
+ goto err;
+ }
+ if(o->td.loca == nil){
+ werrstr("no loca table");
+ goto err;
+ }
+ if(o->glyf.offset == 0){
+ for(i = 0; i < o->td.numTables; i++){
+ TableRecord *rec = o->td.tableRecords+i;
+ if(rec->tableTag == (u32int)('g'<<24|'l'<<16|'y'<<8|'f')){
+ o->glyf = *rec;
+ break;
+ }
+ }
+ if(o->glyf.offset == 0){
+ werrstr("no glyf table");
+ goto err;
+ }
+ }
+ if(index < 0 || index >= o->numGlyphs){
+ werrstr("index out of range");
+ goto err;
+ }
+ if(o->indexToLocFormat == 0){
+ off = (int)o->td.loca->shortOffsets[index]*2;
+ len = (int)o->td.loca->shortOffsets[index+1]*2 - off;
+ }else{
+ off = o->td.loca->longOffsets[index];
+ len = o->td.loca->longOffsets[index+1] - off;
+ }
+ if(len < 1) /* no outlines */
+ return g;
+
+ if(otfpushrange(o, o->glyf.offset, o->glyf.length) < 0)
+ return nil;
+ if(otfpushrange(o, off, len) < 0)
+ goto err;
+ if(read_Glyf(o, g) < 0){
+ free(g);
+ g = nil;
+ }
+ otfpoprange(o);
+ otfpoprange(o);
+
+ return g;
+err:
+ free(g);
+ otfpopranges(o);
+ return nil;
+}
+
int
+otfglyfnum(Otf *o)
+{
+ return o->numGlyphs;
+}
+
+
+int
read_SubHeader(Otf *o, SubHeader *v)
{
u8int *b;
@@ -1296,6 +1465,13 @@
Bprint(f, "%*s%s: %d\n", indent, "", "yMin", v->yMin);
Bprint(f, "%*s%s: %d\n", indent, "", "xMax", v->xMax);
Bprint(f, "%*s%s: %d\n", indent, "", "yMax", v->yMax);
+ if(v->component != nil){
+ Bprint(f, "%*s%s:\n", indent, "", "component");
+ print_ComponentGlyph(f, indent+indentΔ, o, v->component);
+ }else if(v->simple != nil){
+ Bprint(f, "%*s%s:\n", indent, "", "simple");
+ print_SimpleGlyph(f, indent+indentΔ, o, v->simple);
+ }
USED(o);
}
--- a/otf.c.in
+++ b/otf.c.in
@@ -4,6 +4,8 @@
#include <bio.h>
#include "otf.h"
+int indentΔ = 2;
+
typedef struct Range Range;
struct Otf {
@@ -12,7 +14,10 @@
u8int *buf;
int bufsz;
int off;
+
/* extra fields to simplify parsing */
+ TableDirectory td;
+ TableRecord glyf;
OTF_EXTRA_FIELDS
};
@@ -111,11 +116,22 @@
Bterm(f);
}else{
o->f = f;
+ if(read_TableDirectory(o, &o->td) != 0){
+ Bterm(f);
+ free(o);
+ o = nil;
+ }
}
return o;
}
void
+otfprint(Otf *o, Biobuf *out, int indent)
+{
+ print_TableDirectory(out, indent, o, &o->td);
+}
+
+void
otfclose(Otf *o)
{
if(o == nil)
@@ -185,6 +201,13 @@
return -1;
}
+static void
+otfpopranges(Otf *o)
+{
+ while(o->r != nil)
+ otfpoprange(o);
+}
+
static u8int *
otfreadn(Otf *o, int n)
{
@@ -239,6 +262,11 @@
return -1;
}
+enum {
+ CGLYPH_FL_WORD_ARGS = 1<<0,
+ CGLYPH_FL_SIGNED_XY = 1<<1,
+};
+
static int
read_ComponentGlyph(Otf *o, ComponentGlyph **out, int instr)
{
@@ -258,11 +286,21 @@
instr |= v->flags & CGLYPH_FL_INSTRUCTIONS;
if((v->flags & CGLYPH_FL_WORD_ARGS) != 0 && (b = otfreadn(o, 2*2)) != nil){
- v->arg1.u16 = b[0]<<8 | b[1];
- v->arg2.u16 = b[2]<<8 | b[3];
+ if(v->flags & CGLYPH_FL_SIGNED_XY){
+ v->arg1 = (s16int)(b[0]<<8 | b[1]);
+ v->arg2 = (s16int)(b[2]<<8 | b[3]);
+ }else{
+ v->arg1 = b[0]<<8 | b[1];
+ v->arg1 = b[2]<<8 | b[3];
+ }
}else if((b = otfreadn(o, 2)) != nil){
- v->arg1.u8 = b[0];
- v->arg2.u8 = b[1];
+ if(v->flags & CGLYPH_FL_SIGNED_XY){
+ v->arg1 = (s8int)b[0];
+ v->arg2 = (s8int)b[1];
+ }else{
+ v->arg1 = b[0];
+ v->arg2 = b[1];
+ }
}
if(b == nil)
goto err;
@@ -304,6 +342,50 @@
return -1;
}
+void
+print_ComponentGlyph(Biobuf *f, int indent, Otf *o, ComponentGlyph *v)
+{
+ Bprint(f, "%*s%s: %#ux%s%s%s%s%s%s%s%s%s%s\n", indent, "", "flags", v->flags,
+ (v->flags&CGLYPH_FL_ROUND_TO_GRID_XY)?" CGLYPH_FL_ROUND_TO_GRID_XY":"",
+ (v->flags&CGLYPH_FL_SCALE)?" CGLYPH_FL_SCALE":"",
+ (v->flags&CGLYPH_FL_MORE_COMPONENTS)?" CGLYPH_FL_MORE_COMPONENTS":"",
+ (v->flags&CGLYPH_FL_SCALE_XY)?" CGLYPH_FL_SCALE_XY":"",
+ (v->flags&CGLYPH_FL_2X2_TRANSFORM)?" CGLYPH_FL_2X2_TRANSFORM":"",
+ (v->flags&CGLYPH_FL_INSTRUCTIONS)?" CGLYPH_FL_INSTRUCTIONS":"",
+ (v->flags&CGLYPH_FL_METRICS)?" CGLYPH_FL_METRICS":"",
+ (v->flags&CGLYPH_FL_OVERLAP_COMPOUND)?" CGLYPH_FL_OVERLAP_COMPOUND":"",
+ (v->flags&CGLYPH_FL_SCALED_COMPONENT_OFFSET)?" CGLYPH_FL_SCALED_COMPONENT_OFFSET":"",
+ (v->flags&CGLYPH_FL_UNSCALED_COMPONENT_OFFSET)?" CGLYPH_FL_UNSCALED_COMPONENT_OFFSET":""
+ );
+ Bprint(f, "%*s%s: %ud\n", indent, "", "glyphIndex", v->glyphIndex);
+ if(v->arg1 != 0 || v->arg2 != 0){
+ Bprint(f, "%*s%s: %d\n", indent, "", "arg1", v->arg1);
+ Bprint(f, "%*s%s: %d\n", indent, "", "arg2", v->arg2);
+ }
+ if(v->flags & CGLYPH_FL_SCALE){
+ Bprint(f, "%*s%s: %g\n", indent, "", "scale", v->scale);
+ }else if(v->flags & CGLYPH_FL_SCALE_XY){
+ Bprint(f, "%*s%s: %g\n", indent, "", "scaleX", v->scaleX);
+ Bprint(f, "%*s%s: %g\n", indent, "", "scaleY", v->scaleY);
+ }else if(v->flags & CGLYPH_FL_2X2_TRANSFORM){
+ Bprint(f, "%*s%s: %g\n", indent, "", "scaleX", v->scaleX);
+ Bprint(f, "%*s%s: %g\n", indent, "", "scale01", v->scale01);
+ Bprint(f, "%*s%s: %g\n", indent, "", "scale10", v->scale10);
+ Bprint(f, "%*s%s: %g\n", indent, "", "scaleY", v->scaleY);
+ }
+ if(v->numInstr > 0 && v->instr != nil){
+ Bprint(f, "%*s%s: %ud\n", indent, "", "numInstr", v->numInstr);
+ Bprint(f, "%*s%s:", indent, "", "instr");
+ for(int i = 0; i < v->numInstr; i++)
+ Bprint(f, " %02ux", v->instr[i]);
+ Bprint(f, "\n");
+ }
+ if(v->next != nil){
+ Bprint(f, "%*s%s:\n", indent, "", "next");
+ print_ComponentGlyph(f, indent+indentΔ, o, v->next);
+ }
+}
+
enum {
GLYPH_FL_ON_CURVE_POINT = 1<<0,
GLYPH_FL_X_SHORT_VECTOR = 1<<1,
@@ -319,7 +401,7 @@
{
SimpleGlyph *v;
u8int *b, *flags;
- int i, n, nflags, c;
+ int i, n, nflags, c, nc;
flags = nil;
if((v = calloc(1, sizeof(*v))) == nil){
@@ -328,6 +410,7 @@
goto err;
}
+ v->numEndPtsOfContours = o->numberOfContours;
n = o->numberOfContours;
if((b = otfreadn(o, 2*n+2)) == nil)
goto err;
@@ -335,6 +418,7 @@
goto nomem;
for(int i = 0; i < n; i++)
v->endPtsOfContours[i] = b[2*i+0]<<8 | b[2*i+1];
+ v->numPoints = 1 + v->endPtsOfContours[o->numberOfContours-1];
v->instructionLength = b[2*n+0]<<8 | b[2*n+1];
n = v->instructionLength;
@@ -349,23 +433,19 @@
for(nflags = 0; nflags < v->numPoints;){
if((b = otfreadn(o, 1)) == nil)
goto err;
- flags[nflags] = *b;
- if((flags[nflags] & GLYPH_FL_REPEAT) != 0){
- flags[nflags] ^= GLYPH_FL_REPEAT;
+ if((flags[nflags++] = *b) & GLYPH_FL_REPEAT){
+ flags[nflags-1] ^= GLYPH_FL_REPEAT;
if((b = otfreadn(o, 1)) == nil)
goto err;
- if(nflags + 1 + *b > v->numPoints){
- werrstr("repeat overflow");
+ if(nflags + *b > v->numPoints){
+ werrstr("repeat overflow (%d+%d > %d)", nflags, *b, v->numPoints);
goto err;
}
- memset(flags+nflags+1, flags[nflags], *b);
- nflags += 1 + *b;
- }else{
- nflags++;
+ memset(flags+nflags, flags[nflags-1], *b);
+ nflags += *b;
}
}
- v->numPoints = v->endPtsOfContours[o->numberOfContours-1];
if((v->points = calloc(v->numPoints, sizeof(*v->points))) == nil)
goto nomem;
@@ -379,10 +459,10 @@
if((flags[i] & GLYPH_FL_X_SHORT_VECTOR) != 0){
if((b = otfreadn(o, 1)) == nil)
goto err;
- c = *b;
+ nc = *b;
if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) == 0)
- c = -c;
- v->points[n++].x = c;
+ nc = -nc;
+ c = v->points[n++].x = c + nc;
}else if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) != 0){
v->points[n++].x = c;
}else{
@@ -399,10 +479,10 @@
if((flags[i] & GLYPH_FL_Y_SHORT_VECTOR) != 0){
if((b = otfreadn(o, 1)) == nil)
goto err;
- c = *b;
+ nc = *b;
if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) == 0)
- c = -c;
- v->points[n++].y = c;
+ nc = -nc;
+ c = v->points[n++].y = c + nc;
}else if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) != 0){
v->points[n++].y = c;
}else{
@@ -428,7 +508,31 @@
return -1;
}
-int indentΔ = 2;
+void
+print_SimpleGlyph(Biobuf *f, int indent, Otf *o, SimpleGlyph *v)
+{
+ USED(o);
+ if(v->numEndPtsOfContours > 0){
+ Bprint(f, "%*s%s:", indent, "", "endPtsOfContours");
+ for(int i = 0; i < v->numEndPtsOfContours; i++)
+ Bprint(f, " %ud", v->endPtsOfContours[i]);
+ Bprint(f, "\n");
+ }
+ if(v->instructionLength > 0){
+ Bprint(f, "%*s%s: %ud\n", indent, "", "instructionLength", v->instructionLength);
+ Bprint(f, "%*s%s:", indent, "", "instructions");
+ for(int i = 0; i < v->instructionLength; i++)
+ Bprint(f, " %02ux", v->instructions[i]);
+ Bprint(f, "\n");
+ }
+ if(v->numPoints > 0){
+ Bprint(f, "%*s%s: %d\n", indent, "", "numPoints", v->numPoints);
+ Bprint(f, "%*s%s:", indent, "", "points");
+ for(int i = 0; i < v->numPoints; i++)
+ Bprint(f, " (%d,%d,%d)", v->points[i].x, v->points[i].y, v->points[i].onCurve);
+ Bprint(f, "\n");
+ }
+}
static int
Tfmt(Fmt *f)
@@ -461,4 +565,69 @@
fmtinstall('V', Vfmt);
fmtinstall('T', Tfmt);
fmtinstall('t', tfmt);
+}
+
+Glyf *
+otfglyf(Otf *o, int index)
+{
+ Glyf *g;
+ int off, len, i;
+
+ if((g = calloc(1, sizeof(*g))) == nil){
+ werrstr("no memory");
+ goto err;
+ }
+ if(o->td.loca == nil){
+ werrstr("no loca table");
+ goto err;
+ }
+ if(o->glyf.offset == 0){
+ for(i = 0; i < o->td.numTables; i++){
+ TableRecord *rec = o->td.tableRecords+i;
+ if(rec->tableTag == (u32int)('g'<<24|'l'<<16|'y'<<8|'f')){
+ o->glyf = *rec;
+ break;
+ }
+ }
+ if(o->glyf.offset == 0){
+ werrstr("no glyf table");
+ goto err;
+ }
+ }
+ if(index < 0 || index >= o->numGlyphs){
+ werrstr("index out of range");
+ goto err;
+ }
+ if(o->indexToLocFormat == 0){
+ off = (int)o->td.loca->shortOffsets[index]*2;
+ len = (int)o->td.loca->shortOffsets[index+1]*2 - off;
+ }else{
+ off = o->td.loca->longOffsets[index];
+ len = o->td.loca->longOffsets[index+1] - off;
+ }
+ if(len < 1) /* no outlines */
+ return g;
+
+ if(otfpushrange(o, o->glyf.offset, o->glyf.length) < 0)
+ return nil;
+ if(otfpushrange(o, off, len) < 0)
+ goto err;
+ if(read_Glyf(o, g) < 0){
+ free(g);
+ g = nil;
+ }
+ otfpoprange(o);
+ otfpoprange(o);
+
+ return g;
+err:
+ free(g);
+ otfpopranges(o);
+ return nil;
+}
+
+int
+otfglyfnum(Otf *o)
+{
+ return o->numGlyphs;
}
--- a/otf.h
+++ b/otf.h
@@ -5,8 +5,6 @@
typedef struct ComponentGlyph ComponentGlyph;
enum {
- CGLYPH_FL_WORD_ARGS = 1<<0,
- CGLYPH_FL_SIGNED_XY = 1<<1,
CGLYPH_FL_ROUND_TO_GRID_XY = 1<<2,
CGLYPH_FL_SCALE = 1<<3,
CGLYPH_FL_MORE_COMPONENTS = 1<<5,
@@ -22,12 +20,8 @@
struct ComponentGlyph {
u16int flags;
u16int glyphIndex;
- union {
- u8int u8;
- s8int s8;
- u16int u16;
- s16int s16;
- }arg1, arg2;
+ int arg1;
+ int arg2;
float scale, scaleX, scale01, scale10, scaleY;
u16int numInstr;
u8int *instr;
@@ -45,6 +39,7 @@
typedef struct SimpleGlyph SimpleGlyph;
struct SimpleGlyph {
+ int numEndPtsOfContours;
u16int *endPtsOfContours;
u16int instructionLength;
u8int *instructions;
@@ -61,7 +56,13 @@
void otfinit(void);
Otf *otfopen(char *path);
+void otfprint(Otf *o, Biobuf *out, int indent);
void otfclose(Otf *o);
+
+/* FIXME these will go, this is for debugging and designing the drawing logic */
+typedef struct Glyf Glyf;
+Glyf *otfglyf(Otf *o, int index);
+int otfglyfnum(Otf *o);
typedef struct SubHeader SubHeader;
typedef struct MapGroup MapGroup;
--- a/otf.h.in
+++ b/otf.h.in
@@ -5,8 +5,6 @@
typedef struct ComponentGlyph ComponentGlyph;
enum {
- CGLYPH_FL_WORD_ARGS = 1<<0,
- CGLYPH_FL_SIGNED_XY = 1<<1,
CGLYPH_FL_ROUND_TO_GRID_XY = 1<<2,
CGLYPH_FL_SCALE = 1<<3,
CGLYPH_FL_MORE_COMPONENTS = 1<<5,
@@ -22,12 +20,8 @@
struct ComponentGlyph {
u16int flags;
u16int glyphIndex;
- union {
- u8int u8;
- s8int s8;
- u16int u16;
- s16int s16;
- }arg1, arg2;
+ int arg1;
+ int arg2;
float scale, scaleX, scale01, scale10, scaleY;
u16int numInstr;
u8int *instr;
@@ -45,6 +39,7 @@
typedef struct SimpleGlyph SimpleGlyph;
struct SimpleGlyph {
+ int numEndPtsOfContours;
u16int *endPtsOfContours;
u16int instructionLength;
u8int *instructions;
@@ -61,4 +56,10 @@
void otfinit(void);
Otf *otfopen(char *path);
+void otfprint(Otf *o, Biobuf *out, int indent);
void otfclose(Otf *o);
+
+/* FIXME these will go, this is for debugging and designing the drawing logic */
+typedef struct Glyf Glyf;
+Glyf *otfglyf(Otf *o, int index);
+int otfglyfnum(Otf *o);
--- a/otf.rkt
+++ b/otf.rkt
@@ -214,7 +214,15 @@
(list (~a "if(v->numberOfContours < 0 && read_ComponentGlyph(o, &v->component, 0) < 0)")
(~a " goto err;")
(~a "if(v->numberOfContours > 0 && read_SimpleGlyph(o, &v->simple) < 0)")
- (~a " goto err;")))))
+ (~a " goto err;")))
+ (cons 'print
+ (list (~a "if(v->component != nil){")
+ (~a " Bprint(f, \"%*s%s:\\n\", indent, \"\", \"component\");")
+ (~a " print_ComponentGlyph(f, indent+indentΔ, o, v->component);")
+ (~a "}else if(v->simple != nil){")
+ (~a " Bprint(f, \"%*s%s:\\n\", indent, \"\", \"simple\");")
+ (~a " print_SimpleGlyph(f, indent+indentΔ, o, v->simple);")
+ (~a "}")))))
(mkcmplx LongHorMetric {UFWORD advanceWidth} {FWORD lsb})
--- a/test.c
+++ b/test.c
@@ -6,7 +6,6 @@
void
main(int argc, char **argv)
{
- TableDirectory td;
Biobuf *out;
Otf *o;
int i;
@@ -17,10 +16,18 @@
Bprint(out, "%s\n", argv[i]);
if((o = otfopen(argv[i])) == nil){
fprint(2, "%r\n");
- }else if(read_TableDirectory(o, &td) != 0){
- fprint(2, "%s: %r\n", argv[i]);
- } else {
- print_TableDirectory(out, indentΔ, o, &td);
+ }else{
+ int n = otfglyfnum(o);
+ for(int i = 0; i < n; i++){
+ Glyf *g = otfglyf(o, i);
+ if(g == nil)
+ fprint(2, "%d: %r\n", i);
+ else{
+ Bprint(out, "\n%d:\n", i);
+ print_Glyf(out, indentΔ, o, g);
+ }
+ }
+ //otfprint(o, out, indentΔ);
}
otfclose(o);
}