ref: c8e83c81d910049123621d766bc837abc9103145
parent: dc095bf883919052348b9f8ba907bb3807e2283d
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Jun 25 11:15:45 EDT 2024
move verbatim C code from gen.rkt to otf.[ch].in
--- a/gen.rkt
+++ b/gen.rkt
@@ -21,7 +21,7 @@
(define/contract (indent lst)
(-> (listof any/c) (listof string?))
- (map (λ (str) (string-append "\t" str)) (flatten lst)))
+ (map (λ (str) (string-append " " str)) (flatten lst)))
(define/contract (c-typedef? s)
(-> string? boolean?)
@@ -142,7 +142,7 @@
[count
#:when (type-string? t)
(list (~a "if((b = otfreadn(o, " count ")) == nil)")
- (~a "\tgoto err;")
+ (~a " goto err;")
(if (equal? t String-UTF16)
(list (~a ref " = malloc(" count "/2+1);")
(~a "utf16to8((u8int*)" ref ", " count "/2+1, b, " count ");"))
@@ -153,7 +153,7 @@
empty
(list (if (number? count) empty (~a ref " = malloc(" count "*sizeof(*" ref "));"))
(~a "for(int i = 0; i < " count "; i++)")
- (~a "\t"
+ (~a " "
ref
"[i] = "
((type-parse (field-type f)) b index (~a "i*" (size (field-type f))))
@@ -180,31 +180,30 @@
(if (not at)
lst
(list (~a "if(" (fmt-expr at) " != 0){")
- (~a "\tif(otfpushrange(o, " (fmt-expr at) ", -1) < 0)")
- (~a "\t\tgoto err;")
+ (~a " if(otfpushrange(o, " (fmt-expr at) ", -1) < 0)")
+ (~a " goto err;")
(indent lst)
- (~a "\tif(otfpoprange(o) < 0)")
- (~a "\t\tgoto err;")
+ (~a " if(otfpoprange(o) < 0)")
+ (~a " goto err;")
(~a "}"))))
- (at (list* (parse-if-error #t)
- (if index
- empty
- (list (~a "\twerrstr(\"%s: %r\", \"" (field-name f) "\");")
- (~a "\tgoto err;")
- (~a "}")))
- (match (test-cond (field-test f))
- [(list) empty]
- [(list a ...)
- (list (~a "if(" (string-join a " || ") "){")
- (~a "\twerrstr(\"%s: invalid value: %d (0x%ux)\", \""
- (field-name f)
- "\", "
- ref
- ", "
- ref
- ");")
- (~a "\tgoto err;")
- (~a "}"))]))))])
+ (at (list*
+ (parse-if-error #t)
+ (if index
+ empty
+ (list (~a " werrstr(\"%s: %r\", \"" (field-name f) "\");") (~a " goto err;") (~a "}")))
+ (match (test-cond (field-test f))
+ [(list) empty]
+ [(list a ...)
+ (list (~a "if(" (string-join a " || ") "){")
+ (~a " werrstr(\"%s: invalid value: %d (0x%ux)\", \""
+ (field-name f)
+ "\", "
+ ref
+ ", "
+ ref
+ ");")
+ (~a " goto err;")
+ (~a "}"))]))))])
(define/contract (field-attr f a)
(-> field? symbol? any)
@@ -291,7 +290,7 @@
");")
(list (if cnt empty (~a "Bprint(f, \"%*s%s:\\n\", indent, \"\", \"" (field-name f) "\");"))
(if is-ptr (~a "if(v->" (field-name f) " != nil)") empty)
- (~a (if is-ptr "\t" "")
+ (~a (if is-ptr " " "")
"print_"
(cmplx-name t)
"(f, indent+indentΔ, o, "
@@ -387,7 +386,7 @@
[lst (flatten (list (if (field-offset (car fields))
empty
(list (~a "if((b = otfreadn(o, " sum ")) == nil)")
- (~a "\tgoto err;")
+ (~a " goto err;")
(if unused "USED(b);" empty)))
(parse-group fields)))])
lst))))
@@ -397,13 +396,13 @@
(~a "int")
(~a "read_" (cmplx-name c) "(Otf *o, " (cmplx-name c) " *v)")
(~a "{")
- (~a "\tu8int *b;"))
+ (~a " u8int *b;"))
(indent (map gen-group-c (group-fields (cmplx-fields c))))
(indent (filter-extra (cmplx-extra c) 'read))
- (list (~a "\treturn 0;")
+ (list (~a " return 0;")
(~a "err:")
- (~a "\twerrstr(\"%s: %r\", \"" (cmplx-name c) "\");")
- (~a "\treturn -1;")
+ (~a " werrstr(\"%s: %r\", \"" (cmplx-name c) "\");")
+ (~a " return -1;")
(~a "}"))
(list (~a "")
(~a "void")
@@ -411,7 +410,7 @@
(~a "{")
(indent (map field-print-c (cmplx-fields c)))
(indent (filter-extra (cmplx-extra c) 'print))
- (~a "\tUSED(o);")
+ (~a " USED(o);")
(~a "}")))))
(define (c-type c)
(cmplx-name c))])
@@ -561,80 +560,10 @@
(out "otf.h"
(λ ()
- (printf #<<EOF
-/* this file is generated. do not modify. */
-typedef struct Otf Otf;
-#pragma incomplete Otf
+ (printf (port->string (open-input-file "otf.h.in") #:close? #t))
+ (printf "\n")
+ (printf (format gen-h))))
-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,
- CGLYPH_FL_SCALE_XY = 1<<6,
- CGLYPH_FL_2X2_TRANSFORM = 1<<7,
- CGLYPH_FL_INSTRUCTIONS = 1<<8,
- CGLYPH_FL_METRICS = 1<<9,
- CGLYPH_FL_OVERLAP_COMPOUND = 1<<10,
- CGLYPH_FL_SCALED_COMPONENT_OFFSET = 1<<11,
- CGLYPH_FL_UNSCALED_COMPONENT_OFFSET = 1<<12,
-};
-
-struct ComponentGlyph {
- u16int flags;
- u16int glyphIndex;
- union {
- u8int u8;
- s8int s8;
- u16int u16;
- s16int s16;
- }arg1, arg2;
- float scale, scaleX, scale01, scale10, scaleY;
- u16int numInstr;
- u8int *instr;
- ComponentGlyph *next;
-};
-
-typedef struct Point Point;
-
-struct Point {
- int x;
- int y;
- int onCurve;
-};
-
-typedef struct SimpleGlyph SimpleGlyph;
-
-struct SimpleGlyph {
- u16int *endPtsOfContours;
- u16int instructionLength;
- u8int *instructions;
-
- int numPoints;
- Point *points;
-};
-
-EOF
- )
- (printf (format gen-h))
- (printf #<<EOF
-
-extern int indentΔ;
-
-#pragma varargck type "T" s64int
-#pragma varargck type "t" u32int
-#pragma varargck type "V" u32int
-
-void otfinit(void);
-Otf *otfopen(char *path);
-void otfclose(Otf *o);
-
-EOF
- )))
-
(define (extra-context-fields c)
(if (cmplx? c)
(filter-map (λ (f) (and (field-context? f) (indent (gen-h f)))) (cmplx-fields c))
@@ -642,31 +571,8 @@
(out "otf.c"
(λ ()
- (printf #<<EOF
-/* this file is generated. do not modify. */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include "otf.h"
-
-typedef struct Range Range;
-
-struct Otf {
- Biobuf *f;
- Range *r;
- u8int *buf;
- int bufsz;
- int off;
- /* extra fields to simplify parsing */
-
-EOF
- )
- (printf (format extra-context-fields #:on-all remove-duplicates))
- (printf #<<EOF
-};
-
-#include "otfpriv.h"
-
-EOF
- )
+ (printf (string-replace (port->string (open-input-file "otf.c.in") #:close? #t)
+ "OTF_EXTRA_FIELDS\n"
+ (format extra-context-fields #:on-all remove-duplicates)))
+ (printf "\n")
(printf (format (λ (c) (gen-c c #f #f))))))
--- a/mkfile
+++ b/mkfile
@@ -9,7 +9,6 @@
HFILES=\
otf.h\
- otfpriv.h\
default:V: all
--- a/otf.c
+++ b/otf.c
@@ -30,7 +30,453 @@
u16int axisValueCount;
};
-#include "otfpriv.h"
+struct Range {
+ int start;
+ int len;
+ int prevoff;
+ Range *par;
+};
+
+#define rchr(s) (be ? ((s)[0]<<8 | (s)[1]) : ((s)[1]<<8 | (s)[0]))
+
+static u8int mark[] = {0x00, 0x00, 0xc0, 0xe0, 0xf0};
+
+static int
+utf16to8(u8int *o, int osz, u8int *s, int sz)
+{
+ u32int c, c2;
+ int i, wr, j, be;
+
+ i = 0;
+ be = 1;
+ if(s[0] == 0xfe && s[1] == 0xff)
+ i += 2;
+ else if(s[0] == 0xff && s[1] == 0xfe){
+ be = 0;
+ i += 2;
+ }
+
+ for(; i < sz-1 && osz > 1;){
+ c = rchr(&s[i]);
+ i += 2;
+ if(c >= 0xd800 && c <= 0xdbff && i < sz-1){
+ c2 = rchr(&s[i]);
+ if(c2 >= 0xdc00 && c2 <= 0xdfff){
+ c = 0x10000 | (c - 0xd800)<<10 | (c2 - 0xdc00);
+ i += 2;
+ }else
+ return -1;
+ }else if(c >= 0xdc00 && c <= 0xdfff)
+ return -1;
+
+ if(c < 0x80)
+ wr = 1;
+ else if(c < 0x800)
+ wr = 2;
+ else if(c < 0x10000)
+ wr = 3;
+ else
+ wr = 4;
+
+ osz -= wr;
+ if(osz < 1)
+ break;
+
+ o += wr;
+ for(j = wr; j > 1; j--){
+ *(--o) = (c & 0xbf) | 0x80;
+ c >>= 6;
+ }
+ *(--o) = (u8int)c | mark[wr];
+ o += wr;
+ }
+
+ *o = 0;
+ return i;
+}
+
+static char *
+strtoutf8(Otf *o, u8int *in, int sz)
+{
+ char *s;
+
+ // FIXME this is not sufficient, obviously - need more platform/encoding handling
+ if(o->platformID == 0 || (o->platformID == 3 && o->encodingID == 1)){
+ s = malloc(sz/2+1);
+ utf16to8((u8int*)s, sz/2+1, in, sz);
+ }else{
+ s = malloc(sz+1);
+ memcpy(s, in, sz);
+ s[sz] = 0;
+ }
+ return s;
+}
+
+Otf *
+otfopen(char *path)
+{
+ Otf *o;
+ Biobuf *f;
+
+ if((f = Bopen(path, OREAD)) == nil)
+ return nil;
+ if((o = calloc(1, sizeof(*o))) == nil){
+ werrstr("no memory");
+ Bterm(f);
+ }else{
+ o->f = f;
+ }
+ return o;
+}
+
+void
+otfclose(Otf *o)
+{
+ if(o == nil)
+ return;
+ // FIXME traverse and free everything
+ free(o);
+}
+
+static int
+otfpushrange(Otf *o, int off, int len)
+{
+ Range *r;
+ int x;
+
+ r = nil;
+ if(o->r != nil){
+ if(len < 0)
+ len = o->r->len - off;
+ if(len < 0 || off+len > o->r->len){
+ werrstr("range overflow (len %d) by %d bytes", len, off+len - o->r->len);
+ goto err;
+ }
+ off += o->r->start;
+ }else if(len < 0){
+ len = 0x7fffffff;
+ }
+ if((r = malloc(sizeof(*r))) == nil){
+ werrstr("no memory");
+ goto err;
+ }
+ r->par = o->r;
+ r->start = off;
+ r->len = len;
+ r->prevoff = o->off;
+ if((x = Bseek(o->f, off, 0)) != off){
+ werrstr("seek offset: need %d, got %d", off, x);
+ goto err;
+ }
+ o->off = off;
+ o->r = r;
+ return 0;
+err:
+ free(r);
+ return -1;
+}
+
+static int
+otfpoprange(Otf *o)
+{
+ Range *r;
+ int x;
+
+ r = o->r;
+ if(r == nil){
+ werrstr("pop without push");
+ goto err;
+ }
+ if((x = Bseek(o->f, r->prevoff, 0)) != r->prevoff){
+ werrstr("seek offset: need %d, got %d", r->prevoff, x);
+ goto err;
+ }
+ o->off = r->prevoff;
+ o->r = r->par;
+ free(r);
+ return 0;
+err:
+ return -1;
+}
+
+static u8int *
+otfreadn(Otf *o, int n)
+{
+ Range *r;
+ u8int *b;
+ int x;
+
+ r = o->r;
+ if(r != nil && o->off+n > r->start+r->len){
+ werrstr("need %d at %d, have %d at %d", n, o->off, r->len, r->start);
+ goto err;
+ }
+ if(n > o->bufsz){
+ if((b = realloc(o->buf, n)) == nil){
+ werrstr("no memory");
+ goto err;
+ }
+ o->buf = b;
+ o->bufsz = n;
+ }
+ if((x = Bread(o->f, o->buf, n)) != n){
+ werrstr("need %d, got %d; off %d", n, x, o->off);
+ goto err;
+ }
+ o->off += n;
+
+ return o->buf;
+err:
+ return nil;
+}
+
+static int
+otfarray(Otf *o, void **arr_, void *fun_, int elsz, int num)
+{
+ int i;
+ int (*fun)(Otf*, void*);
+ u8int *arr;
+
+ if((arr = calloc(num, elsz)) == nil){
+ werrstr("no memory");
+ goto err;
+ }
+ fun = fun_;
+ for(i = 0; i < num; i++){
+ if(fun(o, arr + i*elsz) < 0)
+ goto err;
+ }
+ *arr_ = arr;
+ return 0;
+err:
+ free(arr);
+ return -1;
+}
+
+static int
+read_ComponentGlyph(Otf *o, ComponentGlyph **out, int instr)
+{
+ ComponentGlyph *v;
+ u8int *b;
+
+ if((v = calloc(1, sizeof(*v))) == nil){
+nomem:
+ werrstr("no memory");
+ goto err;
+ }
+
+ if((b = otfreadn(o, 2*2)) == nil)
+ goto err;
+ v->flags = b[0]<<8 | b[1];
+ v->glyphIndex = b[2]<<8 | b[3];
+ 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];
+ }else if((b = otfreadn(o, 2)) != nil){
+ v->arg1.u8 = b[0];
+ v->arg2.u8 = b[1];
+ }
+ if(b == nil)
+ goto err;
+ if((v->flags & CGLYPH_FL_SCALE) != 0 && (b = otfreadn(o, 2)) != nil){
+ v->scale = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
+ }else if((v->flags & CGLYPH_FL_SCALE_XY) != 0 && (b = otfreadn(o, 2*2)) != nil){
+ v->scaleX = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
+ v->scaleY = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
+ }else if((v->flags & CGLYPH_FL_2X2_TRANSFORM) != 0 && (b = otfreadn(o, 2*2*2)) != nil){
+ v->scaleX = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
+ v->scale01 = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
+ v->scale10 = (b[4]<<8 | b[5]>>14)+(b[4]<<8 | b[5]&((1<<14)-1))/16384.0;
+ v->scaleY = (b[6]<<8 | b[7]>>14)+(b[6]<<8 | b[7]&((1<<14)-1))/16384.0;
+ }
+ if(b == nil)
+ goto err;
+ if((v->flags & CGLYPH_FL_MORE_COMPONENTS) != 0){
+ if(read_ComponentGlyph(o, &v->next, instr) != 0){
+ free(v);
+ return -1;
+ }
+ }else if(instr != 0){
+ if((b = otfreadn(o, 2)) == nil)
+ goto err;
+ v->numInstr = b[0]<<8 | b[1];
+ if((v->instr = malloc(v->numInstr)) == nil)
+ goto nomem;
+ if(v->numInstr > 0 && (b = otfreadn(o, v->numInstr)) == nil)
+ goto err;
+ memcpy(v->instr, b, v->numInstr);
+ }
+ *out = v;
+ return 0;
+err:
+ if(v != nil)
+ free(v->instr);
+ free(v);
+ werrstr("ComponentGlyph: %r");
+ return -1;
+}
+
+enum {
+ GLYPH_FL_ON_CURVE_POINT = 1<<0,
+ GLYPH_FL_X_SHORT_VECTOR = 1<<1,
+ GLYPH_FL_Y_SHORT_VECTOR = 1<<2,
+ GLYPH_FL_REPEAT = 1<<3,
+ GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1<<4,
+ GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1<<5,
+ GLYPH_FL_OVERLAP_SIMPLE = 1<<6,
+};
+
+static int
+read_SimpleGlyph(Otf *o, SimpleGlyph **out)
+{
+ SimpleGlyph *v;
+ u8int *b, *flags;
+ int i, n, nflags, c;
+
+ flags = nil;
+ if((v = calloc(1, sizeof(*v))) == nil){
+nomem:
+ werrstr("no memory");
+ goto err;
+ }
+
+ n = o->numberOfContours;
+ if((b = otfreadn(o, 2*n+2)) == nil)
+ goto err;
+ if((v->endPtsOfContours = malloc(2*n)) == nil)
+ goto nomem;
+ for(int i = 0; i < n; i++)
+ v->endPtsOfContours[i] = b[2*i+0]<<8 | b[2*i+1];
+
+ v->instructionLength = b[2*n+0]<<8 | b[2*n+1];
+ n = v->instructionLength;
+ if((b = otfreadn(o, n)) == nil)
+ goto err;
+ if((v->instructions = malloc(n)) == nil)
+ goto nomem;
+ memcpy(v->instructions, b, n);
+
+ if((flags = malloc(v->numPoints)) == nil) /* not supposed to be more than that, 64Kb max */
+ goto nomem;
+ 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((b = otfreadn(o, 1)) == nil)
+ goto err;
+ if(nflags + 1 + *b > v->numPoints){
+ werrstr("repeat overflow");
+ goto err;
+ }
+ memset(flags+nflags+1, flags[nflags], *b);
+ nflags += 1 + *b;
+ }else{
+ nflags++;
+ }
+ }
+
+ v->numPoints = v->endPtsOfContours[o->numberOfContours-1];
+ if((v->points = calloc(v->numPoints, sizeof(*v->points))) == nil)
+ goto nomem;
+
+ /* flags first */
+ for(i = n = 0; i < nflags && n < v->numPoints; i++, n++)
+ v->points[n].onCurve = (flags[i] & GLYPH_FL_ON_CURVE_POINT) != 0;
+
+ /* read packed x coordinates */
+ c = 0;
+ for(i = n = 0; i < nflags && n < v->numPoints; i++){
+ if((flags[i] & GLYPH_FL_X_SHORT_VECTOR) != 0){
+ if((b = otfreadn(o, 1)) == nil)
+ goto err;
+ c = *b;
+ if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) == 0)
+ c = -c;
+ v->points[n++].x = c;
+ }else if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) != 0){
+ v->points[n++].x = c;
+ }else{
+ if((b = otfreadn(o, 2)) == nil)
+ goto err;
+ c += (s16int)(b[0]<<8 | b[1]);
+ v->points[n++].x = c;
+ }
+ }
+
+ /* read packed y coordinates */
+ c = 0;
+ for(i = n = 0; i < nflags && n < v->numPoints; i++){
+ if((flags[i] & GLYPH_FL_Y_SHORT_VECTOR) != 0){
+ if((b = otfreadn(o, 1)) == nil)
+ goto err;
+ c = *b;
+ if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) == 0)
+ c = -c;
+ v->points[n++].y = c;
+ }else if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) != 0){
+ v->points[n++].y = c;
+ }else{
+ if((b = otfreadn(o, 2)) == nil)
+ goto err;
+ c += (s16int)(b[0]<<8 | b[1]);
+ v->points[n++].y = c;
+ }
+ }
+
+ free(flags);
+ *out = v;
+ return 0;
+err:
+ free(flags);
+ if(v != nil){
+ free(v->endPtsOfContours);
+ free(v->instructions);
+ free(v->points);
+ }
+ free(v);
+ werrstr("SimpleGlyph: %r");
+ return -1;
+}
+
+int indentΔ = 2;
+
+static int
+Tfmt(Fmt *f)
+{
+ Tm t;
+ s64int v = va_arg(f->args, s64int);
+ return fmtprint(f, "%τ", tmfmt(tmtime(&t, v, nil), nil));
+}
+
+static int
+Vfmt(Fmt *f)
+{
+ u32int v = va_arg(f->args, u32int);
+ return fmtprint(f, "%d.%d", v>>16, v&0xffff);
+}
+
+static int
+tfmt(Fmt *f)
+{
+ u32int v = va_arg(f->args, u32int);
+ if(v == 0)
+ return fmtprint(f, "<nil>");
+ return fmtprint(f, "%c%c%c%c", v>>24, v>>16, v>>8, v>>0);
+}
+
+void
+otfinit(void)
+{
+ tmfmtinstall();
+ fmtinstall('V', Vfmt);
+ fmtinstall('T', Tfmt);
+ fmtinstall('t', tfmt);
+}
+
int
read_SubHeader(Otf *o, SubHeader *v)
--- /dev/null
+++ b/otf.c.in
@@ -1,0 +1,464 @@
+/* this file is generated. do not modify. */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "otf.h"
+
+typedef struct Range Range;
+
+struct Otf {
+ Biobuf *f;
+ Range *r;
+ u8int *buf;
+ int bufsz;
+ int off;
+ /* extra fields to simplify parsing */
+OTF_EXTRA_FIELDS
+};
+
+struct Range {
+ int start;
+ int len;
+ int prevoff;
+ Range *par;
+};
+
+#define rchr(s) (be ? ((s)[0]<<8 | (s)[1]) : ((s)[1]<<8 | (s)[0]))
+
+static u8int mark[] = {0x00, 0x00, 0xc0, 0xe0, 0xf0};
+
+static int
+utf16to8(u8int *o, int osz, u8int *s, int sz)
+{
+ u32int c, c2;
+ int i, wr, j, be;
+
+ i = 0;
+ be = 1;
+ if(s[0] == 0xfe && s[1] == 0xff)
+ i += 2;
+ else if(s[0] == 0xff && s[1] == 0xfe){
+ be = 0;
+ i += 2;
+ }
+
+ for(; i < sz-1 && osz > 1;){
+ c = rchr(&s[i]);
+ i += 2;
+ if(c >= 0xd800 && c <= 0xdbff && i < sz-1){
+ c2 = rchr(&s[i]);
+ if(c2 >= 0xdc00 && c2 <= 0xdfff){
+ c = 0x10000 | (c - 0xd800)<<10 | (c2 - 0xdc00);
+ i += 2;
+ }else
+ return -1;
+ }else if(c >= 0xdc00 && c <= 0xdfff)
+ return -1;
+
+ if(c < 0x80)
+ wr = 1;
+ else if(c < 0x800)
+ wr = 2;
+ else if(c < 0x10000)
+ wr = 3;
+ else
+ wr = 4;
+
+ osz -= wr;
+ if(osz < 1)
+ break;
+
+ o += wr;
+ for(j = wr; j > 1; j--){
+ *(--o) = (c & 0xbf) | 0x80;
+ c >>= 6;
+ }
+ *(--o) = (u8int)c | mark[wr];
+ o += wr;
+ }
+
+ *o = 0;
+ return i;
+}
+
+static char *
+strtoutf8(Otf *o, u8int *in, int sz)
+{
+ char *s;
+
+ // FIXME this is not sufficient, obviously - need more platform/encoding handling
+ if(o->platformID == 0 || (o->platformID == 3 && o->encodingID == 1)){
+ s = malloc(sz/2+1);
+ utf16to8((u8int*)s, sz/2+1, in, sz);
+ }else{
+ s = malloc(sz+1);
+ memcpy(s, in, sz);
+ s[sz] = 0;
+ }
+ return s;
+}
+
+Otf *
+otfopen(char *path)
+{
+ Otf *o;
+ Biobuf *f;
+
+ if((f = Bopen(path, OREAD)) == nil)
+ return nil;
+ if((o = calloc(1, sizeof(*o))) == nil){
+ werrstr("no memory");
+ Bterm(f);
+ }else{
+ o->f = f;
+ }
+ return o;
+}
+
+void
+otfclose(Otf *o)
+{
+ if(o == nil)
+ return;
+ // FIXME traverse and free everything
+ free(o);
+}
+
+static int
+otfpushrange(Otf *o, int off, int len)
+{
+ Range *r;
+ int x;
+
+ r = nil;
+ if(o->r != nil){
+ if(len < 0)
+ len = o->r->len - off;
+ if(len < 0 || off+len > o->r->len){
+ werrstr("range overflow (len %d) by %d bytes", len, off+len - o->r->len);
+ goto err;
+ }
+ off += o->r->start;
+ }else if(len < 0){
+ len = 0x7fffffff;
+ }
+ if((r = malloc(sizeof(*r))) == nil){
+ werrstr("no memory");
+ goto err;
+ }
+ r->par = o->r;
+ r->start = off;
+ r->len = len;
+ r->prevoff = o->off;
+ if((x = Bseek(o->f, off, 0)) != off){
+ werrstr("seek offset: need %d, got %d", off, x);
+ goto err;
+ }
+ o->off = off;
+ o->r = r;
+ return 0;
+err:
+ free(r);
+ return -1;
+}
+
+static int
+otfpoprange(Otf *o)
+{
+ Range *r;
+ int x;
+
+ r = o->r;
+ if(r == nil){
+ werrstr("pop without push");
+ goto err;
+ }
+ if((x = Bseek(o->f, r->prevoff, 0)) != r->prevoff){
+ werrstr("seek offset: need %d, got %d", r->prevoff, x);
+ goto err;
+ }
+ o->off = r->prevoff;
+ o->r = r->par;
+ free(r);
+ return 0;
+err:
+ return -1;
+}
+
+static u8int *
+otfreadn(Otf *o, int n)
+{
+ Range *r;
+ u8int *b;
+ int x;
+
+ r = o->r;
+ if(r != nil && o->off+n > r->start+r->len){
+ werrstr("need %d at %d, have %d at %d", n, o->off, r->len, r->start);
+ goto err;
+ }
+ if(n > o->bufsz){
+ if((b = realloc(o->buf, n)) == nil){
+ werrstr("no memory");
+ goto err;
+ }
+ o->buf = b;
+ o->bufsz = n;
+ }
+ if((x = Bread(o->f, o->buf, n)) != n){
+ werrstr("need %d, got %d; off %d", n, x, o->off);
+ goto err;
+ }
+ o->off += n;
+
+ return o->buf;
+err:
+ return nil;
+}
+
+static int
+otfarray(Otf *o, void **arr_, void *fun_, int elsz, int num)
+{
+ int i;
+ int (*fun)(Otf*, void*);
+ u8int *arr;
+
+ if((arr = calloc(num, elsz)) == nil){
+ werrstr("no memory");
+ goto err;
+ }
+ fun = fun_;
+ for(i = 0; i < num; i++){
+ if(fun(o, arr + i*elsz) < 0)
+ goto err;
+ }
+ *arr_ = arr;
+ return 0;
+err:
+ free(arr);
+ return -1;
+}
+
+static int
+read_ComponentGlyph(Otf *o, ComponentGlyph **out, int instr)
+{
+ ComponentGlyph *v;
+ u8int *b;
+
+ if((v = calloc(1, sizeof(*v))) == nil){
+nomem:
+ werrstr("no memory");
+ goto err;
+ }
+
+ if((b = otfreadn(o, 2*2)) == nil)
+ goto err;
+ v->flags = b[0]<<8 | b[1];
+ v->glyphIndex = b[2]<<8 | b[3];
+ 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];
+ }else if((b = otfreadn(o, 2)) != nil){
+ v->arg1.u8 = b[0];
+ v->arg2.u8 = b[1];
+ }
+ if(b == nil)
+ goto err;
+ if((v->flags & CGLYPH_FL_SCALE) != 0 && (b = otfreadn(o, 2)) != nil){
+ v->scale = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
+ }else if((v->flags & CGLYPH_FL_SCALE_XY) != 0 && (b = otfreadn(o, 2*2)) != nil){
+ v->scaleX = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
+ v->scaleY = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
+ }else if((v->flags & CGLYPH_FL_2X2_TRANSFORM) != 0 && (b = otfreadn(o, 2*2*2)) != nil){
+ v->scaleX = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
+ v->scale01 = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
+ v->scale10 = (b[4]<<8 | b[5]>>14)+(b[4]<<8 | b[5]&((1<<14)-1))/16384.0;
+ v->scaleY = (b[6]<<8 | b[7]>>14)+(b[6]<<8 | b[7]&((1<<14)-1))/16384.0;
+ }
+ if(b == nil)
+ goto err;
+ if((v->flags & CGLYPH_FL_MORE_COMPONENTS) != 0){
+ if(read_ComponentGlyph(o, &v->next, instr) != 0){
+ free(v);
+ return -1;
+ }
+ }else if(instr != 0){
+ if((b = otfreadn(o, 2)) == nil)
+ goto err;
+ v->numInstr = b[0]<<8 | b[1];
+ if((v->instr = malloc(v->numInstr)) == nil)
+ goto nomem;
+ if(v->numInstr > 0 && (b = otfreadn(o, v->numInstr)) == nil)
+ goto err;
+ memcpy(v->instr, b, v->numInstr);
+ }
+ *out = v;
+ return 0;
+err:
+ if(v != nil)
+ free(v->instr);
+ free(v);
+ werrstr("ComponentGlyph: %r");
+ return -1;
+}
+
+enum {
+ GLYPH_FL_ON_CURVE_POINT = 1<<0,
+ GLYPH_FL_X_SHORT_VECTOR = 1<<1,
+ GLYPH_FL_Y_SHORT_VECTOR = 1<<2,
+ GLYPH_FL_REPEAT = 1<<3,
+ GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1<<4,
+ GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1<<5,
+ GLYPH_FL_OVERLAP_SIMPLE = 1<<6,
+};
+
+static int
+read_SimpleGlyph(Otf *o, SimpleGlyph **out)
+{
+ SimpleGlyph *v;
+ u8int *b, *flags;
+ int i, n, nflags, c;
+
+ flags = nil;
+ if((v = calloc(1, sizeof(*v))) == nil){
+nomem:
+ werrstr("no memory");
+ goto err;
+ }
+
+ n = o->numberOfContours;
+ if((b = otfreadn(o, 2*n+2)) == nil)
+ goto err;
+ if((v->endPtsOfContours = malloc(2*n)) == nil)
+ goto nomem;
+ for(int i = 0; i < n; i++)
+ v->endPtsOfContours[i] = b[2*i+0]<<8 | b[2*i+1];
+
+ v->instructionLength = b[2*n+0]<<8 | b[2*n+1];
+ n = v->instructionLength;
+ if((b = otfreadn(o, n)) == nil)
+ goto err;
+ if((v->instructions = malloc(n)) == nil)
+ goto nomem;
+ memcpy(v->instructions, b, n);
+
+ if((flags = malloc(v->numPoints)) == nil) /* not supposed to be more than that, 64Kb max */
+ goto nomem;
+ 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((b = otfreadn(o, 1)) == nil)
+ goto err;
+ if(nflags + 1 + *b > v->numPoints){
+ werrstr("repeat overflow");
+ goto err;
+ }
+ memset(flags+nflags+1, flags[nflags], *b);
+ nflags += 1 + *b;
+ }else{
+ nflags++;
+ }
+ }
+
+ v->numPoints = v->endPtsOfContours[o->numberOfContours-1];
+ if((v->points = calloc(v->numPoints, sizeof(*v->points))) == nil)
+ goto nomem;
+
+ /* flags first */
+ for(i = n = 0; i < nflags && n < v->numPoints; i++, n++)
+ v->points[n].onCurve = (flags[i] & GLYPH_FL_ON_CURVE_POINT) != 0;
+
+ /* read packed x coordinates */
+ c = 0;
+ for(i = n = 0; i < nflags && n < v->numPoints; i++){
+ if((flags[i] & GLYPH_FL_X_SHORT_VECTOR) != 0){
+ if((b = otfreadn(o, 1)) == nil)
+ goto err;
+ c = *b;
+ if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) == 0)
+ c = -c;
+ v->points[n++].x = c;
+ }else if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) != 0){
+ v->points[n++].x = c;
+ }else{
+ if((b = otfreadn(o, 2)) == nil)
+ goto err;
+ c += (s16int)(b[0]<<8 | b[1]);
+ v->points[n++].x = c;
+ }
+ }
+
+ /* read packed y coordinates */
+ c = 0;
+ for(i = n = 0; i < nflags && n < v->numPoints; i++){
+ if((flags[i] & GLYPH_FL_Y_SHORT_VECTOR) != 0){
+ if((b = otfreadn(o, 1)) == nil)
+ goto err;
+ c = *b;
+ if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) == 0)
+ c = -c;
+ v->points[n++].y = c;
+ }else if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) != 0){
+ v->points[n++].y = c;
+ }else{
+ if((b = otfreadn(o, 2)) == nil)
+ goto err;
+ c += (s16int)(b[0]<<8 | b[1]);
+ v->points[n++].y = c;
+ }
+ }
+
+ free(flags);
+ *out = v;
+ return 0;
+err:
+ free(flags);
+ if(v != nil){
+ free(v->endPtsOfContours);
+ free(v->instructions);
+ free(v->points);
+ }
+ free(v);
+ werrstr("SimpleGlyph: %r");
+ return -1;
+}
+
+int indentΔ = 2;
+
+static int
+Tfmt(Fmt *f)
+{
+ Tm t;
+ s64int v = va_arg(f->args, s64int);
+ return fmtprint(f, "%τ", tmfmt(tmtime(&t, v, nil), nil));
+}
+
+static int
+Vfmt(Fmt *f)
+{
+ u32int v = va_arg(f->args, u32int);
+ return fmtprint(f, "%d.%d", v>>16, v&0xffff);
+}
+
+static int
+tfmt(Fmt *f)
+{
+ u32int v = va_arg(f->args, u32int);
+ if(v == 0)
+ return fmtprint(f, "<nil>");
+ return fmtprint(f, "%c%c%c%c", v>>24, v>>16, v>>8, v>>0);
+}
+
+void
+otfinit(void)
+{
+ tmfmtinstall();
+ fmtinstall('V', Vfmt);
+ fmtinstall('T', Tfmt);
+ fmtinstall('t', tfmt);
+}
--- a/otf.h
+++ b/otf.h
@@ -52,6 +52,17 @@
int numPoints;
Point *points;
};
+
+extern int indentΔ;
+
+#pragma varargck type "T" s64int
+#pragma varargck type "t" u32int
+#pragma varargck type "V" u32int
+
+void otfinit(void);
+Otf *otfopen(char *path);
+void otfclose(Otf *o);
+
typedef struct SubHeader SubHeader;
typedef struct MapGroup MapGroup;
typedef struct SubtableCmap0 SubtableCmap0;
@@ -1559,13 +1570,3 @@
int read_TableDirectory(Otf *o, TableDirectory *v);
void print_TableDirectory(Biobuf *f, int indent, Otf *o, TableDirectory *v);
-
-extern int indentΔ;
-
-#pragma varargck type "T" s64int
-#pragma varargck type "t" u32int
-#pragma varargck type "V" u32int
-
-void otfinit(void);
-Otf *otfopen(char *path);
-void otfclose(Otf *o);
--- /dev/null
+++ b/otf.h.in
@@ -1,0 +1,64 @@
+/* this file is generated. do not modify. */
+typedef struct Otf Otf;
+#pragma incomplete Otf
+
+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,
+ CGLYPH_FL_SCALE_XY = 1<<6,
+ CGLYPH_FL_2X2_TRANSFORM = 1<<7,
+ CGLYPH_FL_INSTRUCTIONS = 1<<8,
+ CGLYPH_FL_METRICS = 1<<9,
+ CGLYPH_FL_OVERLAP_COMPOUND = 1<<10,
+ CGLYPH_FL_SCALED_COMPONENT_OFFSET = 1<<11,
+ CGLYPH_FL_UNSCALED_COMPONENT_OFFSET = 1<<12,
+};
+
+struct ComponentGlyph {
+ u16int flags;
+ u16int glyphIndex;
+ union {
+ u8int u8;
+ s8int s8;
+ u16int u16;
+ s16int s16;
+ }arg1, arg2;
+ float scale, scaleX, scale01, scale10, scaleY;
+ u16int numInstr;
+ u8int *instr;
+ ComponentGlyph *next;
+};
+
+typedef struct Point Point;
+
+struct Point {
+ int x;
+ int y;
+ int onCurve;
+};
+
+typedef struct SimpleGlyph SimpleGlyph;
+
+struct SimpleGlyph {
+ u16int *endPtsOfContours;
+ u16int instructionLength;
+ u8int *instructions;
+
+ int numPoints;
+ Point *points;
+};
+
+extern int indentΔ;
+
+#pragma varargck type "T" s64int
+#pragma varargck type "t" u32int
+#pragma varargck type "V" u32int
+
+void otfinit(void);
+Otf *otfopen(char *path);
+void otfclose(Otf *o);
--- a/otf.rkt
+++ b/otf.rkt
@@ -178,7 +178,7 @@
{int16 yMax}
{uint16 macStyle}
{uint16 lowestRecPPEM}
- {int16 fontDirectionHint unused (>= -2) (<= 2)}
+ {int16 fontDirectionHint (>= -2) (<= 2) unused}
{int16 indexToLocFormat ->o (<= 1)}
{int16 glyphDataFormat unused (== 0)}
#:tag "head")
@@ -212,9 +212,9 @@
(list (cons 'field (list (~a "ComponentGlyph *component;") (~a "SimpleGlyph *simple;")))
(cons 'read
(list (~a "if(v->numberOfContours < 0 && read_ComponentGlyph(o, &v->component, 0) < 0)")
- (~a "\tgoto err;")
+ (~a " goto err;")
(~a "if(v->numberOfContours > 0 && read_SimpleGlyph(o, &v->simple) < 0)")
- (~a "\tgoto err;")))))
+ (~a " goto err;")))))
(mkcmplx LongHorMetric {UFWORD advanceWidth} {FWORD lsb})
--- a/otfpriv.h
+++ /dev/null
@@ -1,446 +1,0 @@
-struct Range {
- int start;
- int len;
- int prevoff;
- Range *par;
-};
-
-#define rchr(s) (be ? ((s)[0]<<8 | (s)[1]) : ((s)[1]<<8 | (s)[0]))
-
-static u8int mark[] = {0x00, 0x00, 0xc0, 0xe0, 0xf0};
-
-static int
-utf16to8(u8int *o, int osz, u8int *s, int sz)
-{
- u32int c, c2;
- int i, wr, j, be;
-
- i = 0;
- be = 1;
- if(s[0] == 0xfe && s[1] == 0xff)
- i += 2;
- else if(s[0] == 0xff && s[1] == 0xfe){
- be = 0;
- i += 2;
- }
-
- for(; i < sz-1 && osz > 1;){
- c = rchr(&s[i]);
- i += 2;
- if(c >= 0xd800 && c <= 0xdbff && i < sz-1){
- c2 = rchr(&s[i]);
- if(c2 >= 0xdc00 && c2 <= 0xdfff){
- c = 0x10000 | (c - 0xd800)<<10 | (c2 - 0xdc00);
- i += 2;
- }else
- return -1;
- }else if(c >= 0xdc00 && c <= 0xdfff)
- return -1;
-
- if(c < 0x80)
- wr = 1;
- else if(c < 0x800)
- wr = 2;
- else if(c < 0x10000)
- wr = 3;
- else
- wr = 4;
-
- osz -= wr;
- if(osz < 1)
- break;
-
- o += wr;
- for(j = wr; j > 1; j--){
- *(--o) = (c & 0xbf) | 0x80;
- c >>= 6;
- }
- *(--o) = (u8int)c | mark[wr];
- o += wr;
- }
-
- *o = 0;
- return i;
-}
-
-static char *
-strtoutf8(Otf *o, u8int *in, int sz)
-{
- char *s;
-
- // FIXME this is not sufficient, obviously - need more platform/encoding handling
- if(o->platformID == 0 || (o->platformID == 3 && o->encodingID == 1)){
- s = malloc(sz/2+1);
- utf16to8((u8int*)s, sz/2+1, in, sz);
- }else{
- s = malloc(sz+1);
- memcpy(s, in, sz);
- s[sz] = 0;
- }
- return s;
-}
-
-Otf *
-otfopen(char *path)
-{
- Otf *o;
- Biobuf *f;
-
- if((f = Bopen(path, OREAD)) == nil)
- return nil;
- if((o = calloc(1, sizeof(*o))) == nil){
- werrstr("no memory");
- Bterm(f);
- }else{
- o->f = f;
- }
- return o;
-}
-
-void
-otfclose(Otf *o)
-{
- if(o == nil)
- return;
- // FIXME traverse and free everything
- free(o);
-}
-
-static int
-otfpushrange(Otf *o, int off, int len)
-{
- Range *r;
- int x;
-
- r = nil;
- if(o->r != nil){
- if(len < 0)
- len = o->r->len - off;
- if(len < 0 || off+len > o->r->len){
- werrstr("range overflow (len %d) by %d bytes", len, off+len - o->r->len);
- goto err;
- }
- off += o->r->start;
- }else if(len < 0){
- len = 0x7fffffff;
- }
- if((r = malloc(sizeof(*r))) == nil){
- werrstr("no memory");
- goto err;
- }
- r->par = o->r;
- r->start = off;
- r->len = len;
- r->prevoff = o->off;
- if((x = Bseek(o->f, off, 0)) != off){
- werrstr("seek offset: need %d, got %d", off, x);
- goto err;
- }
- o->off = off;
- o->r = r;
- return 0;
-err:
- free(r);
- return -1;
-}
-
-static int
-otfpoprange(Otf *o)
-{
- Range *r;
- int x;
-
- r = o->r;
- if(r == nil){
- werrstr("pop without push");
- goto err;
- }
- if((x = Bseek(o->f, r->prevoff, 0)) != r->prevoff){
- werrstr("seek offset: need %d, got %d", r->prevoff, x);
- goto err;
- }
- o->off = r->prevoff;
- o->r = r->par;
- free(r);
- return 0;
-err:
- return -1;
-}
-
-static u8int *
-otfreadn(Otf *o, int n)
-{
- Range *r;
- u8int *b;
- int x;
-
- r = o->r;
- if(r != nil && o->off+n > r->start+r->len){
- werrstr("need %d at %d, have %d at %d", n, o->off, r->len, r->start);
- goto err;
- }
- if(n > o->bufsz){
- if((b = realloc(o->buf, n)) == nil){
- werrstr("no memory");
- goto err;
- }
- o->buf = b;
- o->bufsz = n;
- }
- if((x = Bread(o->f, o->buf, n)) != n){
- werrstr("need %d, got %d; off %d", n, x, o->off);
- goto err;
- }
- o->off += n;
-
- return o->buf;
-err:
- return nil;
-}
-
-static int
-otfarray(Otf *o, void **arr_, void *fun_, int elsz, int num)
-{
- int i;
- int (*fun)(Otf*, void*);
- u8int *arr;
-
- if((arr = calloc(num, elsz)) == nil){
- werrstr("no memory");
- goto err;
- }
- fun = fun_;
- for(i = 0; i < num; i++){
- if(fun(o, arr + i*elsz) < 0)
- goto err;
- }
- *arr_ = arr;
- return 0;
-err:
- free(arr);
- return -1;
-}
-
-static int
-read_ComponentGlyph(Otf *o, ComponentGlyph **out, int instr)
-{
- ComponentGlyph *v;
- u8int *b;
-
- if((v = calloc(1, sizeof(*v))) == nil){
-nomem:
- werrstr("no memory");
- goto err;
- }
-
- if((b = otfreadn(o, 2*2)) == nil)
- goto err;
- v->flags = b[0]<<8 | b[1];
- v->glyphIndex = b[2]<<8 | b[3];
- 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];
- }else if((b = otfreadn(o, 2)) != nil){
- v->arg1.u8 = b[0];
- v->arg2.u8 = b[1];
- }
- if(b == nil)
- goto err;
- if((v->flags & CGLYPH_FL_SCALE) != 0 && (b = otfreadn(o, 2)) != nil){
- v->scale = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
- }else if((v->flags & CGLYPH_FL_SCALE_XY) != 0 && (b = otfreadn(o, 2*2)) != nil){
- v->scaleX = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
- v->scaleY = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
- }else if((v->flags & CGLYPH_FL_2X2_TRANSFORM) != 0 && (b = otfreadn(o, 2*2*2)) != nil){
- v->scaleX = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
- v->scale01 = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
- v->scale10 = (b[4]<<8 | b[5]>>14)+(b[4]<<8 | b[5]&((1<<14)-1))/16384.0;
- v->scaleY = (b[6]<<8 | b[7]>>14)+(b[6]<<8 | b[7]&((1<<14)-1))/16384.0;
- }
- if(b == nil)
- goto err;
- if((v->flags & CGLYPH_FL_MORE_COMPONENTS) != 0){
- if(read_ComponentGlyph(o, &v->next, instr) != 0){
- free(v);
- return -1;
- }
- }else if(instr != 0){
- if((b = otfreadn(o, 2)) == nil)
- goto err;
- v->numInstr = b[0]<<8 | b[1];
- if((v->instr = malloc(v->numInstr)) == nil)
- goto nomem;
- if(v->numInstr > 0 && (b = otfreadn(o, v->numInstr)) == nil)
- goto err;
- memcpy(v->instr, b, v->numInstr);
- }
- *out = v;
- return 0;
-err:
- if(v != nil)
- free(v->instr);
- free(v);
- werrstr("ComponentGlyph: %r");
- return -1;
-}
-
-enum {
- GLYPH_FL_ON_CURVE_POINT = 1<<0,
- GLYPH_FL_X_SHORT_VECTOR = 1<<1,
- GLYPH_FL_Y_SHORT_VECTOR = 1<<2,
- GLYPH_FL_REPEAT = 1<<3,
- GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1<<4,
- GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1<<5,
- GLYPH_FL_OVERLAP_SIMPLE = 1<<6,
-};
-
-static int
-read_SimpleGlyph(Otf *o, SimpleGlyph **out)
-{
- SimpleGlyph *v;
- u8int *b, *flags;
- int i, n, nflags, c;
-
- flags = nil;
- if((v = calloc(1, sizeof(*v))) == nil){
-nomem:
- werrstr("no memory");
- goto err;
- }
-
- n = o->numberOfContours;
- if((b = otfreadn(o, 2*n+2)) == nil)
- goto err;
- if((v->endPtsOfContours = malloc(2*n)) == nil)
- goto nomem;
- for(int i = 0; i < n; i++)
- v->endPtsOfContours[i] = b[2*i+0]<<8 | b[2*i+1];
-
- v->instructionLength = b[2*n+0]<<8 | b[2*n+1];
- n = v->instructionLength;
- if((b = otfreadn(o, n)) == nil)
- goto err;
- if((v->instructions = malloc(n)) == nil)
- goto nomem;
- memcpy(v->instructions, b, n);
-
- if((flags = malloc(v->numPoints)) == nil) /* not supposed to be more than that, 64Kb max */
- goto nomem;
- 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((b = otfreadn(o, 1)) == nil)
- goto err;
- if(nflags + 1 + *b > v->numPoints){
- werrstr("repeat overflow");
- goto err;
- }
- memset(flags+nflags+1, flags[nflags], *b);
- nflags += 1 + *b;
- }else{
- nflags++;
- }
- }
-
- v->numPoints = v->endPtsOfContours[o->numberOfContours-1];
- if((v->points = calloc(v->numPoints, sizeof(*v->points))) == nil)
- goto nomem;
-
- /* flags first */
- for(i = n = 0; i < nflags && n < v->numPoints; i++, n++)
- v->points[n].onCurve = (flags[i] & GLYPH_FL_ON_CURVE_POINT) != 0;
-
- /* read packed x coordinates */
- c = 0;
- for(i = n = 0; i < nflags && n < v->numPoints; i++){
- if((flags[i] & GLYPH_FL_X_SHORT_VECTOR) != 0){
- if((b = otfreadn(o, 1)) == nil)
- goto err;
- c = *b;
- if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) == 0)
- c = -c;
- v->points[n++].x = c;
- }else if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) != 0){
- v->points[n++].x = c;
- }else{
- if((b = otfreadn(o, 2)) == nil)
- goto err;
- c += (s16int)(b[0]<<8 | b[1]);
- v->points[n++].x = c;
- }
- }
-
- /* read packed y coordinates */
- c = 0;
- for(i = n = 0; i < nflags && n < v->numPoints; i++){
- if((flags[i] & GLYPH_FL_Y_SHORT_VECTOR) != 0){
- if((b = otfreadn(o, 1)) == nil)
- goto err;
- c = *b;
- if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) == 0)
- c = -c;
- v->points[n++].y = c;
- }else if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) != 0){
- v->points[n++].y = c;
- }else{
- if((b = otfreadn(o, 2)) == nil)
- goto err;
- c += (s16int)(b[0]<<8 | b[1]);
- v->points[n++].y = c;
- }
- }
-
- free(flags);
- *out = v;
- return 0;
-err:
- free(flags);
- if(v != nil){
- free(v->endPtsOfContours);
- free(v->instructions);
- free(v->points);
- }
- free(v);
- werrstr("SimpleGlyph: %r");
- return -1;
-}
-
-int indentΔ = 2;
-
-static int
-Tfmt(Fmt *f)
-{
- Tm t;
- s64int v = va_arg(f->args, s64int);
- return fmtprint(f, "%τ", tmfmt(tmtime(&t, v, nil), nil));
-}
-
-static int
-Vfmt(Fmt *f)
-{
- u32int v = va_arg(f->args, u32int);
- return fmtprint(f, "%d.%d", v>>16, v&0xffff);
-}
-
-static int
-tfmt(Fmt *f)
-{
- u32int v = va_arg(f->args, u32int);
- if(v == 0)
- return fmtprint(f, "<nil>");
- return fmtprint(f, "%c%c%c%c", v>>24, v>>16, v>>8, v>>0);
-}
-
-void
-otfinit(void)
-{
- tmfmtinstall();
- fmtinstall('V', Vfmt);
- fmtinstall('T', Tfmt);
- fmtinstall('t', tfmt);
-}
--
⑨