ref: d44ae07e343d91452f7cd0bc8f78024f2ab3883a
parent: 48e1da1dd908852cb62e931b46c92f8d3e987ab4
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Fri Jun 21 12:41:18 EDT 2024
fix custom parsing with offset; handle full blown expressions with references as conditionals
--- a/gen.rkt
+++ b/gen.rkt
@@ -37,6 +37,18 @@
(define ps (list a b (map f types) ""))
(string-join (flatten ps) "\n"))
+(define (fmt-expr e)
+ (define (fmt e)
+ (cond
+ [#f #f]
+ [(number? e) e]
+ [(list? e)
+ (match e
+ [(list op x y) (~a "(" (fmt x) op (fmt y) ")")])]
+ [(and (symbol? e) (extra-context-ref? e)) (~a e)]
+ [(symbol? e) (~a "v->" e)]))
+ (and e (fmt e)))
+
(define-generics code
(gen-h code) ; generates code for the C header
(gen-c code b index) ; generates code for the C source file
@@ -59,14 +71,20 @@
(define (block stmt lst)
(if (= (length lst) 1) (list* stmt lst) (list (string-append stmt "{") lst "}")))
+(define/contract (fmt-ref ref)
+ (-> symbol? string?)
+ (~a (if (extra-context-ref? ref) "" "v->") ref))
+
(define (wrap-cond-c cond lst)
- (define (fmt-ref ref)
- (if (extra-context-ref? ref) ref (~a "v->" ref)))
(match cond
[#f lst]
[(list op ref n ...)
+ #:when ((listof number?) n)
(block (~a "if(" (string-join (map (λ (n) (~a (fmt-ref ref) " " op " " n)) n) " || ") ")")
- (indent lst))]))
+ (indent lst))]
+ [(list op ref e)
+ #:when (list? e)
+ (block (~a "if(" (fmt-expr cond) ")") (indent lst))]))
(define (invert-c op)
(match op
@@ -199,16 +217,7 @@
(define/contract (field-count f)
(-> field? (or/c false/c number? string?))
- (define (fmt-expr e)
- (cond
- [(number? e) e]
- [(list? e)
- (match e
- [(list op x y) (~a "(" (fmt-expr x) op (fmt-expr y) ")")])]
- [(and (symbol? e) (extra-context-ref? e)) (~a e)]
- [(symbol? e) (~a "v->" e)]))
- (define e (field-attr f 'count))
- (and e (fmt-expr e)))
+ (fmt-expr (field-attr f 'count)))
(define (field-test f)
(filter (λ (t) (eq? (car t) 'test)) (field-attrs f)))
@@ -442,17 +451,18 @@
[(_ type _ (p:compop vs:number ...+))
#:fail-when (not (type-comparable? (syntax-e #'type))) "type can't be used in a comparison"
#''(test p vs ...)]
- [(_ _ _ (p:compop oref:oref vs:number ...+))
- #''(cond
- p
- oref
- vs ...)]
[(_ _ _ (p:compop ref:ref vs:number ...+))
#''(cond
p
ref
vs ...)]
+ [(_ _ _ (p:compop oref:oref e:expr))
+ #''(cond
+ p
+ oref
+ e)]
[(_ _ _ {~literal unused}) #''(unused #t)]
+ [(_ _ _ (oref:oref)) #''(count oref)]
[(_ _ _ (ref:ref))
#:fail-when (not (type-index? (syntax-e #'ref.type))) "can't be used as index to an array"
#''(count ref)]
--- a/otf.c
+++ b/otf.c
@@ -18,6 +18,9 @@
u16int numGlyphs;
u16int firstGlyphIndex;
u16int lastGlyphIndex;
+ u16int axisCount;
+ u16int instanceCount;
+ u16int instanceSize;
};
struct Range {
@@ -1008,7 +1011,7 @@
read_TableHmtx(Otf *o, TableHmtx *v)
{
u8int *b;
- if(otfarray(o, &v->hMetrics, read_LongHorMetric, sizeof(LongHorMetric), (o->numberOfHMetrics+0)) < 0){
+ if(otfarray(o, &v->hMetrics, read_LongHorMetric, sizeof(LongHorMetric), o->numberOfHMetrics) < 0){
werrstr("%s: %r", "hMetrics");
goto err;
}
@@ -1026,7 +1029,7 @@
void
print_TableHmtx(Biobuf *f, int indent, Otf *o, TableHmtx *v)
{
- for(int i = 0; i < (o->numberOfHMetrics+0); i++){
+ for(int i = 0; i < o->numberOfHMetrics; i++){
Bprint(f, "%*s%s[%d]:\n", indent, "", "hMetrics", i);
print_LongHorMetric(f, indent+indentΔ, o, &v->hMetrics[i]);
}
@@ -3702,6 +3705,184 @@
}
int
+read_VariationAxisRecord(Otf *o, VariationAxisRecord *v)
+{
+ u8int *b;
+ if((b = otfreadn(o, 20)) == nil)
+ goto err;
+ v->axisTag = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
+ v->minValue = (b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7])/65536.0f;
+ v->defaultValue = (b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11])/65536.0f;
+ v->maxValue = (b[12]<<24 | b[13]<<16 | b[14]<<8 | b[15])/65536.0f;
+ v->flags = b[16]<<8 | b[17];
+ v->axisNameID = b[18]<<8 | b[19];
+ return 0;
+err:
+ werrstr("%s: %r", "VariationAxisRecord");
+ return -1;
+}
+
+void
+print_VariationAxisRecord(Biobuf *f, int indent, Otf *o, VariationAxisRecord *v)
+{
+ Bprint(f, "%*s%s: %t\n", indent, "", "axisTag", v->axisTag);
+ Bprint(f, "%*s%s: %g\n", indent, "", "minValue", v->minValue);
+ Bprint(f, "%*s%s: %g\n", indent, "", "defaultValue", v->defaultValue);
+ Bprint(f, "%*s%s: %g\n", indent, "", "maxValue", v->maxValue);
+ Bprint(f, "%*s%s: %ud\n", indent, "", "flags", v->flags);
+ Bprint(f, "%*s%s: %ud\n", indent, "", "axisNameID", v->axisNameID);
+ USED(o);
+}
+
+int
+read_UserTuple(Otf *o, UserTuple *v)
+{
+ u8int *b;
+ if((b = otfreadn(o, o->axisCount*4)) == nil)
+ goto err;
+ v->coordinates = malloc(o->axisCount*sizeof(*v->coordinates));
+ for(int i = 0; i < o->axisCount; i++)
+ v->coordinates[i] = (b[0+i*4]<<24 | b[1+i*4]<<16 | b[2+i*4]<<8 | b[3+i*4])/65536.0f;
+ return 0;
+err:
+ werrstr("%s: %r", "UserTuple");
+ return -1;
+}
+
+void
+print_UserTuple(Biobuf *f, int indent, Otf *o, UserTuple *v)
+{
+ for(int i = 0; i < o->axisCount; i++)
+ Bprint(f, "%*s%s[%d]: %g\n", indent, "", "coordinates", i, v->coordinates[i]);
+ USED(o);
+}
+
+int
+read_InstanceRecord(Otf *o, InstanceRecord *v)
+{
+ u8int *b;
+ if((b = otfreadn(o, 4)) == nil)
+ goto err;
+ v->subfamilyNameID = b[0]<<8 | b[1];
+ v->flags = b[2]<<8 | b[3];
+ if(read_UserTuple(o, &v->coordinates) < 0){
+ werrstr("%s: %r", "coordinates");
+ goto err;
+ }
+ if((o->instanceSize==((o->axisCount*4)+6))){
+ if((b = otfreadn(o, 2)) == nil)
+ goto err;
+ v->postScriptNameID = b[0]<<8 | b[1];
+ }
+ return 0;
+err:
+ werrstr("%s: %r", "InstanceRecord");
+ return -1;
+}
+
+void
+print_InstanceRecord(Biobuf *f, int indent, Otf *o, InstanceRecord *v)
+{
+ Bprint(f, "%*s%s: %ud\n", indent, "", "subfamilyNameID", v->subfamilyNameID);
+ Bprint(f, "%*s%s: %ud\n", indent, "", "flags", v->flags);
+ Bprint(f, "%*s%s:\n", indent, "", "coordinates");
+ print_UserTuple(f, indent+indentΔ, o, &v->coordinates);
+ if((o->instanceSize==((o->axisCount*4)+6)))
+ Bprint(f, "%*s%s: %ud\n", indent, "", "postScriptNameID", v->postScriptNameID);
+ USED(o);
+}
+
+int
+read_AxisInstances(Otf *o, AxisInstances *v)
+{
+ u8int *b;
+ if(otfarray(o, &v->axes, read_VariationAxisRecord, sizeof(VariationAxisRecord), o->axisCount) < 0){
+ werrstr("%s: %r", "axes");
+ goto err;
+ }
+ if(otfarray(o, &v->instaces, read_InstanceRecord, sizeof(InstanceRecord), o->instanceCount) < 0){
+ werrstr("%s: %r", "instaces");
+ goto err;
+ }
+ return 0;
+err:
+ werrstr("%s: %r", "AxisInstances");
+ return -1;
+}
+
+void
+print_AxisInstances(Biobuf *f, int indent, Otf *o, AxisInstances *v)
+{
+ for(int i = 0; i < o->axisCount; i++){
+ Bprint(f, "%*s%s[%d]:\n", indent, "", "axes", i);
+ print_VariationAxisRecord(f, indent+indentΔ, o, &v->axes[i]);
+ }
+ for(int i = 0; i < o->instanceCount; i++){
+ Bprint(f, "%*s%s[%d]:\n", indent, "", "instaces", i);
+ print_InstanceRecord(f, indent+indentΔ, o, &v->instaces[i]);
+ }
+ USED(o);
+}
+
+int
+read_TableFvar(Otf *o, TableFvar *v)
+{
+ u8int *b;
+ if((b = otfreadn(o, 16)) == nil)
+ goto err;
+ u16int majorVersion = b[0]<<8 | b[1];
+ if(majorVersion != 1){
+ werrstr("%s: invalid value: %d (0x%ux)", "majorVersion", majorVersion, majorVersion);
+ goto err;
+ }
+ u16int minorVersion = b[2]<<8 | b[3];
+ if(minorVersion != 0){
+ werrstr("%s: invalid value: %d (0x%ux)", "minorVersion", minorVersion, minorVersion);
+ goto err;
+ }
+ v->axesArrayOffset = b[4]<<8 | b[5];
+ v->axisCount = b[8]<<8 | b[9];
+ o->axisCount = v->axisCount;
+ u16int axisSize = b[10]<<8 | b[11];
+ if(axisSize != 20){
+ werrstr("%s: invalid value: %d (0x%ux)", "axisSize", axisSize, axisSize);
+ goto err;
+ }
+ v->instanceCount = b[12]<<8 | b[13];
+ o->instanceCount = v->instanceCount;
+ v->instanceSize = b[14]<<8 | b[15];
+ o->instanceSize = v->instanceSize;
+ if(v->axesArrayOffset != 0){
+ if(otfpushrange(o, v->axesArrayOffset, -1) < 0)
+ goto err;
+ v->axisInstances = calloc(1, sizeof(*v->axisInstances));
+ if(read_AxisInstances(o, v->axisInstances) < 0){
+ werrstr("%s: %r", "axisInstances");
+ goto err;
+ }
+ if(otfpoprange(o) < 0)
+ goto err;
+ }
+ return 0;
+err:
+ werrstr("%s: %r", "TableFvar");
+ return -1;
+}
+
+void
+print_TableFvar(Biobuf *f, int indent, Otf *o, TableFvar *v)
+{
+ Bprint(f, "%*s%s: %ud\n", indent, "", "axesArrayOffset", v->axesArrayOffset);
+ Bprint(f, "%*s%s: %ud\n", indent, "", "axisCount", v->axisCount);
+ Bprint(f, "%*s%s: %ud\n", indent, "", "instanceCount", v->instanceCount);
+ Bprint(f, "%*s%s: %ud\n", indent, "", "instanceSize", v->instanceSize);
+ Bprint(f, "%*s%s:\n", indent, "", "axisInstances");
+ if(v->axisInstances != nil)
+ print_AxisInstances(f, indent+indentΔ, o, v->axisInstances);
+ USED(o);
+}
+
+int
read_TableFFTM(Otf *o, TableFFTM *v)
{
u8int *b;
@@ -4207,6 +4388,17 @@
}
rec->parsed = v->loca;
rec->print = (void*)print_TableLoca;
+ break;
+ case (u32int)('f'<<24|'v'<<16|'a'<<8|'r'):
+ if(v->fvar != nil)
+ break;
+ v->fvar = calloc(1, sizeof(TableFvar));
+ if(read_TableFvar(o, v->fvar) < 0){
+ free(v->fvar);
+ goto err;
+ }
+ rec->parsed = v->fvar;
+ rec->print = (void*)print_TableFvar;
break;
case (u32int)('F'<<24|'F'<<16|'T'<<8|'M'):
if(v->fftm != nil)
--- a/otf.h
+++ b/otf.h
@@ -87,6 +87,11 @@
typedef struct KernSubtable KernSubtable;
typedef struct TableKern TableKern;
typedef struct TableLoca TableLoca;
+typedef struct VariationAxisRecord VariationAxisRecord;
+typedef struct UserTuple UserTuple;
+typedef struct InstanceRecord InstanceRecord;
+typedef struct AxisInstances AxisInstances;
+typedef struct TableFvar TableFvar;
typedef struct TableFFTM TableFFTM;
typedef struct SignatureBlock1 SignatureBlock1;
typedef struct SignatureRecord SignatureRecord;
@@ -1045,6 +1050,58 @@
int read_TableLoca(Otf *o, TableLoca *v);
void print_TableLoca(Biobuf *f, int indent, Otf *o, TableLoca *v);
+struct VariationAxisRecord {
+ u32int axisTag;
+ float minValue;
+ float defaultValue;
+ float maxValue;
+ u16int flags;
+ u16int axisNameID;
+};
+
+int read_VariationAxisRecord(Otf *o, VariationAxisRecord *v);
+void print_VariationAxisRecord(Biobuf *f, int indent, Otf *o, VariationAxisRecord *v);
+
+struct UserTuple {
+ float *coordinates;
+};
+
+int read_UserTuple(Otf *o, UserTuple *v);
+void print_UserTuple(Biobuf *f, int indent, Otf *o, UserTuple *v);
+
+struct InstanceRecord {
+ u16int subfamilyNameID;
+ u16int flags;
+ UserTuple coordinates;
+ u16int postScriptNameID;
+};
+
+int read_InstanceRecord(Otf *o, InstanceRecord *v);
+void print_InstanceRecord(Biobuf *f, int indent, Otf *o, InstanceRecord *v);
+
+struct AxisInstances {
+ VariationAxisRecord *axes;
+ InstanceRecord *instaces;
+};
+
+int read_AxisInstances(Otf *o, AxisInstances *v);
+void print_AxisInstances(Biobuf *f, int indent, Otf *o, AxisInstances *v);
+
+struct TableFvar {
+ // u16int majorVersion;
+ // u16int minorVersion;
+ u16int axesArrayOffset;
+ // u16int reserved;
+ u16int axisCount;
+ // u16int axisSize;
+ u16int instanceCount;
+ u16int instanceSize;
+ AxisInstances *axisInstances;
+};
+
+int read_TableFvar(Otf *o, TableFvar *v);
+void print_TableFvar(Biobuf *f, int indent, Otf *o, TableFvar *v);
+
struct TableFFTM {
u32int version;
s64int fontforge;
@@ -1164,6 +1221,7 @@
TableMATH *math;
TableKern *kern;
TableLoca *loca;
+ TableFvar *fvar;
TableFFTM *fftm;
TableDSIG *dsig;
TableOS∕2 *os∕2;
--- a/otf.rkt
+++ b/otf.rkt
@@ -26,19 +26,23 @@
64
s64int
"%T"
- (λ (b index) (~a "(" ((autoparse 64 's64int) b index) ") - 2082844800LL")))
+ (λ (b index [offset #f]) (~a "(" ((autoparse 64 's64int) b index offset) ") - 2082844800LL")))
(mktype Tag 32 u32int "%t")
(mktype Offset16 16 u16int "%ud")
(mktype Offset24 24 u32int "%ud")
(mktype Offset32 32 u32int "%ud")
(mktype Version16Dot16 32 u32int "%V")
-(mktype Fixed 32 float "%g" (λ (b index) (~a "(" ((type-parse int32) b index) ")/65536.0f")))
+(mktype Fixed
+ 32
+ float
+ "%g"
+ (λ (b index [offset #f]) (~a "(" ((type-parse int32) b index offset) ")/65536.0f")))
(mktype F2DOT14
16
float
"%g"
- (λ (b index)
- (define x (~a ((type-parse int16) b index)))
+ (λ (b index [offset #f])
+ (define x (~a ((type-parse int16) b index offset)))
(~a "(" x ">>14)+(" x "&((1<<14)-1))/16384.0")))
(mkcmplx SubHeader {uint16 firstCode} {uint16 entryCode} {int16 idDelta} {uint16 idRangeOffset})
@@ -190,7 +194,7 @@
#:tag "maxp")
(mkcmplx TableHmtx
- {LongHorMetric hMetrics [+ o->numberOfHMetrics 0]}
+ {LongHorMetric hMetrics [o->numberOfHMetrics]}
{FWORD leftSideBearings [- o->numGlyphs o->numberOfHMetrics]}
#:tag "hmtx"
#:after (list TableHhea TableMaxp))
@@ -603,6 +607,38 @@
{Offset32 longOffsets [+ o->numGlyphs 1] (== o->indexToLocFormat 1)}
#:tag "loca"
#:after (list TableHead))
+
+(mkcmplx VariationAxisRecord
+ {Tag axisTag}
+ {Fixed minValue}
+ {Fixed defaultValue}
+ {Fixed maxValue}
+ {uint16 flags}
+ {uint16 axisNameID})
+
+(mkcmplx UserTuple {Fixed coordinates [o->axisCount]})
+
+(mkcmplx InstanceRecord
+ {uint16 subfamilyNameID}
+ {uint16 flags}
+ {UserTuple coordinates}
+ {uint16 postScriptNameID (== o->instanceSize (+ (* o->axisCount 4) 6))})
+
+(mkcmplx AxisInstances
+ {VariationAxisRecord axes [o->axisCount]}
+ {InstanceRecord instaces [o->instanceCount]})
+
+(mkcmplx TableFvar
+ {uint16 majorVersion (== 1) unused}
+ {uint16 minorVersion (== 0) unused}
+ {Offset16 axesArrayOffset}
+ {uint16 reserved unused}
+ {uint16 axisCount ->o}
+ {uint16 axisSize (== 20) unused}
+ {uint16 instanceCount ->o}
+ {uint16 instanceSize ->o}
+ {AxisInstances axisInstances (at axesArrayOffset)}
+ #:tag "fvar")
(mkcmplx TableFFTM
{uint32 version}