shithub: fnt

Download patch

ref: b8442cf99bf3c724441a5abca9f6497eb6407add
parent: 03431f292ab32bee57e01d9dc93670c55a4411e9
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Jun 23 20:26:26 EDT 2024

define flags as bits and generate enums; allow bitflags comparisons

--- a/gen.rkt
+++ b/gen.rkt
@@ -31,6 +31,10 @@
   (-> symbol? boolean?)
   (string-prefix? (symbol->string ref) "o->"))
 
+(define/contract (enum? e)
+  (-> symbol? boolean?)
+  (regexp-match? #rx"^[A-Z][A-Z0-9_]+$" (symbol->string e)))
+
 (define/contract (format f)
   (-> procedure? string?)
   (define-values (a b) (partition c-typedef? (flatten (map f cmplxs))))
@@ -45,7 +49,7 @@
       [(list? e)
        (match e
          [(list op x y) (~a "(" (fmt x) op (fmt y) ")")])]
-      [(and (symbol? e) (extra-context-ref? e)) (~a e)]
+      [(and (symbol? e) (or (enum? e) (extra-context-ref? e))) (~a e)]
       [(symbol? e) (~a "v->" e)]))
   (and e (fmt e)))
 
@@ -74,9 +78,8 @@
 (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 (fmt-ref ref)
+  (if (symbol? ref) (~a (if (extra-context-ref? ref) "" "v->") ref) (fmt-expr ref)))
 
 (define (wrap-cond-c cond lst)
   (match cond
@@ -227,6 +230,9 @@
 (define (field-context? f)
   (field-attr f '->o))
 
+(define (field-bits f)
+  (field-attr f 'bits))
+
 (define/contract (field-count f)
   (-> field? (or/c false/c number? string?))
   (fmt-expr (field-attr f 'count)))
@@ -241,15 +247,28 @@
   (define fixed-array (and basic-array (number? cnt)))
   (define array-index (if cnt "[i]" ""))
   (define verb (if (type? t) (or (field-verb f) (type-verb t)) ""))
+  (define bits (field-bits f))
+  (define bits-verbs (or (and bits (string-join (make-list (hash-count bits) "%s") "")) ""))
+  (define bits-args
+    (or (and bits
+             (string-join
+              (hash-map (field-bits f)
+                        (λ (bit enum)
+                          (~a "(v->" (field-name f) array-index "&" enum ")?\" " enum "\":\"\"")))
+              ", "
+              #:before-first ", "))
+        ""))
   (define print-index
     (if basic-array
         (~a "Bprint(f, \"%*s%s[%d]: "
             verb
+            bits-verbs
             "\\n\", indent, \"\", \""
             (field-name f)
             "\", i, v->"
             (field-name f)
             array-index
+            bits-args
             ");")
         (~a "Bprint(f, \"%*s%s[%d]:\\n\", indent, \"\", \"" (field-name f) "\", i);")))
   (define array-loop
@@ -265,11 +284,13 @@
       (if (type? t)
           (~a "Bprint(f, \"%*s%s: "
               verb
+              bits-verbs
               "\\n\", indent, \"\", \""
               (field-name f)
               "\", v->"
               (field-name f)
               array-index
+              bits-args
               ");")
           (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)
@@ -293,8 +314,20 @@
   [(define/generic super-gen-h gen-h)
    (define/generic super-gen-c gen-c)
    (define (gen-h c)
+     (define allbits
+       (filter-map (λ (f)
+                     (define bits (field-bits f))
+                     (and bits
+                          (list (~a "// " (field-name f))
+                                (hash-map bits (λ (bit enum) (~a enum " = 1<<" bit ","))))))
+                   (cmplx-fields c)))
+     (define enums
+       (if (empty? allbits)
+           empty
+           (list (~a "enum { // " (cmplx-name c)) (indent allbits) (~a "};") (~a ""))))
      (flatten (append (list (~a "typedef struct " (cmplx-name c) " " (cmplx-name c) ";")
                             (~a "")
+                            enums
                             (~a "struct " (cmplx-name c) " {"))
                       (indent (map super-gen-h (cmplx-fields c)))
                       (indent (filter-extra (cmplx-extra c) 'field))
@@ -479,6 +512,10 @@
           p
           oref
           e)]
+    [(_ _ _ (p:compop e:expr ...+)) ; FIXME - check fields and ops/numbers
+     #''(cond
+          p
+          e ...)]
     [(_ _ _ {~literal unused}) #''(unused #t)]
     [(_ _ _ (oref:oref)) #''(count oref)]
     [(_ _ _ (ref:ref))
@@ -485,6 +522,7 @@
      #:fail-when (not (type-index? (syntax-e #'ref.type))) "can't be used as index to an array"
      #''(count ref)]
     [(_ _ _ (n:number)) #''(count n)]
+    [(_ _ _ ({~literal bits} ht:expr)) #'(list 'bits ht)]
     [(_ _ _ (p:arithop e:expr ...+)) #''(count (p e ...))])) ; FIXME - check fields and ops/numbers
 
 (define-syntax (mkfield stx)
--- a/otf.c
+++ b/otf.c
@@ -746,7 +746,7 @@
 void
 print_TableHead(Biobuf *f, int indent, Otf *o, TableHead *v)
 {
-	Bprint(f, "%*s%s: %ud\n", indent, "", "flags", v->flags);
+	Bprint(f, "%*s%s: %#ux%s%s%s%s%s%s%s%s%s\n", indent, "", "flags", v->flags, (v->flags&HEAD_FL_BASELINE_Y_0)?" HEAD_FL_BASELINE_Y_0":"", (v->flags&HEAD_FL_LEFT_SIDEBEARING_X_0)?" HEAD_FL_LEFT_SIDEBEARING_X_0":"", (v->flags&HEAD_FL_INSTR_DEP_POINT_SZ)?" HEAD_FL_INSTR_DEP_POINT_SZ":"", (v->flags&HEAD_FL_FORCE_PPEM_INT)?" HEAD_FL_FORCE_PPEM_INT":"", (v->flags&HEAD_FL_INSTR_ALT_ADVANCE_WIDTH)?" HEAD_FL_INSTR_ALT_ADVANCE_WIDTH":"", (v->flags&HEAD_FL_LOSSLESS)?" HEAD_FL_LOSSLESS":"", (v->flags&HEAD_FL_CONVERTED)?" HEAD_FL_CONVERTED":"", (v->flags&HEAD_FL_CLEARTYPE)?" HEAD_FL_CLEARTYPE":"", (v->flags&HEAD_FL_LAST_RESORT)?" HEAD_FL_LAST_RESORT":"");
 	Bprint(f, "%*s%s: %ud\n", indent, "", "unitsPerEm", v->unitsPerEm);
 	Bprint(f, "%*s%s: %T\n", indent, "", "created", v->created);
 	Bprint(f, "%*s%s: %T\n", indent, "", "modified", v->modified);
@@ -1493,7 +1493,7 @@
 	Bprint(f, "%*s%s: %ud\n", indent, "", "ppemX", v->ppemX);
 	Bprint(f, "%*s%s: %ud\n", indent, "", "ppemY", v->ppemY);
 	Bprint(f, "%*s%s: %ud\n", indent, "", "bitDepth", v->bitDepth);
-	Bprint(f, "%*s%s: %d\n", indent, "", "flags", v->flags);
+	Bprint(f, "%*s%s: %#ux%s%s\n", indent, "", "flags", v->flags, (v->flags&BITMAPSIZE_FL_HORIZONTAL_METRICS)?" BITMAPSIZE_FL_HORIZONTAL_METRICS":"", (v->flags&BITMAPSIZE_FL_VERTICAL_METRICS)?" BITMAPSIZE_FL_VERTICAL_METRICS":"");
 	for(int i = 0; i < v->numberOfIndexSubtables; i++){
 		Bprint(f, "%*s%s[%d]:\n", indent, "", "indexSubtableList", i);
 		print_IndexSubtableRecord(f, indent+indentΔ, o, &v->indexSubtableList[i]);
@@ -3613,7 +3613,7 @@
 	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: %#ux\n", indent, "", "flags", v->flags);
+	Bprint(f, "%*s%s: %#ux%s\n", indent, "", "flags", v->flags, (v->flags&VARIATIONAXISRECORD_FL_HIDDEN_AXIS)?" VARIATIONAXISRECORD_FL_HIDDEN_AXIS":"");
 	Bprint(f, "%*s%s: %ud\n", indent, "", "axisNameID", v->axisNameID);
 	USED(o);
 }
@@ -3648,7 +3648,6 @@
 	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;
@@ -3668,7 +3667,6 @@
 print_InstanceRecord(Biobuf *f, int indent, Otf *o, InstanceRecord *v)
 {
 	Bprint(f, "%*s%s: %ud\n", indent, "", "subfamilyNameID", v->subfamilyNameID);
-	Bprint(f, "%*s%s: %#ux\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)))
@@ -4174,7 +4172,7 @@
 print_TableDSIG(Biobuf *f, int indent, Otf *o, TableDSIG *v)
 {
 	Bprint(f, "%*s%s: %ud\n", indent, "", "numSignatures", v->numSignatures);
-	Bprint(f, "%*s%s: %#ux\n", indent, "", "flags", v->flags);
+	Bprint(f, "%*s%s: %#ux%s\n", indent, "", "flags", v->flags, (v->flags&DSIG_CANNOT_BE_RESIGNED)?" DSIG_CANNOT_BE_RESIGNED":"");
 	for(int i = 0; i < v->numSignatures; i++){
 		Bprint(f, "%*s%s[%d]:\n", indent, "", "signatureRecords", i);
 		print_SignatureRecord(f, indent+indentΔ, o, &v->signatureRecords[i]);
@@ -4381,6 +4379,20 @@
 	v->glyphCount = b[12]<<8 | b[13];
 	v->flags = b[14]<<8 | b[15];
 	v->glyphVariationDataArrayOffset = b[16]<<24 | b[17]<<16 | b[18]<<8 | b[19];
+	if((v->flags&GVAR_FL_LONG_OFFSETS) == 0){
+		if((b = otfreadn(o, (v->glyphCount+1)*2)) == nil)
+			goto err;
+		v->glyphVariationDataOffsetsShort = malloc((v->glyphCount+1)*sizeof(*v->glyphVariationDataOffsetsShort));
+		for(int i = 0; i < (v->glyphCount+1); i++)
+			v->glyphVariationDataOffsetsShort[i] = b[0+i*2]<<8 | b[1+i*2];
+	}
+	if((v->flags&GVAR_FL_LONG_OFFSETS) != 0){
+		if((b = otfreadn(o, (v->glyphCount+1)*4)) == nil)
+			goto err;
+		v->glyphVariationDataOffsetsLong = malloc((v->glyphCount+1)*sizeof(*v->glyphVariationDataOffsetsLong));
+		for(int i = 0; i < (v->glyphCount+1); i++)
+			v->glyphVariationDataOffsetsLong[i] = b[0+i*4]<<24 | b[1+i*4]<<16 | b[2+i*4]<<8 | b[3+i*4];
+	}
 	return 0;
 err:
 	werrstr("%s: %r", "TableGvar");
@@ -4394,8 +4406,16 @@
 	Bprint(f, "%*s%s: %ud\n", indent, "", "sharedTupleCount", v->sharedTupleCount);
 	Bprint(f, "%*s%s: %ud\n", indent, "", "sharedTuplesOffset", v->sharedTuplesOffset);
 	Bprint(f, "%*s%s: %ud\n", indent, "", "glyphCount", v->glyphCount);
-	Bprint(f, "%*s%s: %#ux\n", indent, "", "flags", v->flags);
+	Bprint(f, "%*s%s: %#ux%s\n", indent, "", "flags", v->flags, (v->flags&GVAR_FL_LONG_OFFSETS)?" GVAR_FL_LONG_OFFSETS":"");
 	Bprint(f, "%*s%s: %ud\n", indent, "", "glyphVariationDataArrayOffset", v->glyphVariationDataArrayOffset);
+	if((v->flags&GVAR_FL_LONG_OFFSETS) == 0){
+		for(int i = 0; i < (v->glyphCount+1); i++)
+			Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "glyphVariationDataOffsetsShort", i, v->glyphVariationDataOffsetsShort[i]);
+	}
+	if((v->flags&GVAR_FL_LONG_OFFSETS) != 0){
+		for(int i = 0; i < (v->glyphCount+1); i++)
+			Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "glyphVariationDataOffsetsLong", i, v->glyphVariationDataOffsetsLong[i]);
+	}
 	USED(o);
 }
 
--- a/otf.h
+++ b/otf.h
@@ -300,6 +300,19 @@
 int read_TableCmap(Otf *o, TableCmap *v);
 void print_TableCmap(Biobuf *f, int indent, Otf *o, TableCmap *v);
 
+enum { // TableHead
+	// flags
+	HEAD_FL_BASELINE_Y_0 = 1<<0,
+	HEAD_FL_LEFT_SIDEBEARING_X_0 = 1<<1,
+	HEAD_FL_INSTR_DEP_POINT_SZ = 1<<2,
+	HEAD_FL_FORCE_PPEM_INT = 1<<3,
+	HEAD_FL_INSTR_ALT_ADVANCE_WIDTH = 1<<4,
+	HEAD_FL_LOSSLESS = 1<<11,
+	HEAD_FL_CONVERTED = 1<<12,
+	HEAD_FL_CLEARTYPE = 1<<13,
+	HEAD_FL_LAST_RESORT = 1<<14,
+};
+
 struct TableHead {
 	// u16int majorVersion;
 	// u16int minorVersion;
@@ -528,6 +541,12 @@
 int read_IndexSubtableRecord(Otf *o, IndexSubtableRecord *v);
 void print_IndexSubtableRecord(Biobuf *f, int indent, Otf *o, IndexSubtableRecord *v);
 
+enum { // BitmapSize
+	// flags
+	BITMAPSIZE_FL_HORIZONTAL_METRICS = 1<<0,
+	BITMAPSIZE_FL_VERTICAL_METRICS = 1<<1,
+};
+
 struct BitmapSize {
 	u32int indexSubtableListOffset;
 	u32int indexSubtableListSize;
@@ -1068,6 +1087,11 @@
 int read_TableLoca(Otf *o, TableLoca *v);
 void print_TableLoca(Biobuf *f, int indent, Otf *o, TableLoca *v);
 
+enum { // VariationAxisRecord
+	// flags
+	VARIATIONAXISRECORD_FL_HIDDEN_AXIS = 1<<0,
+};
+
 struct VariationAxisRecord {
 	u32int axisTag;
 	float minValue;
@@ -1089,7 +1113,7 @@
 
 struct InstanceRecord {
 	u16int subfamilyNameID;
-	u16int flags;
+	// u16int flags;
 	UserTuple coordinates;
 	u16int postScriptNameID;
 };
@@ -1222,6 +1246,11 @@
 int read_SignatureRecord(Otf *o, SignatureRecord *v);
 void print_SignatureRecord(Biobuf *f, int indent, Otf *o, SignatureRecord *v);
 
+enum { // TableDSIG
+	// flags
+	DSIG_CANNOT_BE_RESIGNED = 1<<0,
+};
+
 struct TableDSIG {
 	// u32int version;
 	u16int numSignatures;
@@ -1282,6 +1311,11 @@
 int read_TableGasp(Otf *o, TableGasp *v);
 void print_TableGasp(Biobuf *f, int indent, Otf *o, TableGasp *v);
 
+enum { // TableGvar
+	// flags
+	GVAR_FL_LONG_OFFSETS = 1<<0,
+};
+
 struct TableGvar {
 	// u16int majorVersion;
 	// u16int minorVersion;
@@ -1291,6 +1325,8 @@
 	u16int glyphCount;
 	u16int flags;
 	u32int glyphVariationDataArrayOffset;
+	u16int *glyphVariationDataOffsetsShort;
+	u32int *glyphVariationDataOffsetsLong;
 };
 
 int read_TableGvar(Otf *o, TableGvar *v);
--- a/otf.rkt
+++ b/otf.rkt
@@ -151,6 +151,17 @@
          {EncodingRecord encodingRecords [numTables]}
          #:tag "cmap")
 
+(define headFlags
+  #hash((0 . HEAD_FL_BASELINE_Y_0)
+        (1 . HEAD_FL_LEFT_SIDEBEARING_X_0)
+        (2 . HEAD_FL_INSTR_DEP_POINT_SZ)
+        (3 . HEAD_FL_FORCE_PPEM_INT)
+        (4 . HEAD_FL_INSTR_ALT_ADVANCE_WIDTH)
+        (11 . HEAD_FL_LOSSLESS)
+        (12 . HEAD_FL_CONVERTED)
+        (13 . HEAD_FL_CLEARTYPE)
+        (14 . HEAD_FL_LAST_RESORT)))
+
 (mkcmplx TableHead
          {uint16 majorVersion unused (== 1)}
          {uint16 minorVersion unused (== 0)}
@@ -157,7 +168,7 @@
          {Fixed fontRevision unused}
          {uint32 checksumAdjustment unused}
          {uint32 magicNumber unused (== #x5f0f3cf5)}
-         {uint16 flags}
+         {uint16 flags hex (bits headFlags)}
          {uint16 unitsPerEm (>= 16) (<= 16384)}
          {LONGDATETIME created}
          {LONGDATETIME modified}
@@ -298,6 +309,9 @@
          {Offset32 indexSubtableOffset}
          {IndexSubtable indexSubtable (at indexSubtableOffset)})
 
+(define bitmapSizeFlags
+  #hash((0 . BITMAPSIZE_FL_HORIZONTAL_METRICS) (1 . BITMAPSIZE_FL_VERTICAL_METRICS)))
+
 (mkcmplx
  BitmapSize
  {Offset32 indexSubtableListOffset}
@@ -311,7 +325,7 @@
  {uint8 ppemX}
  {uint8 ppemY}
  {uint8 bitDepth}
- {int8 flags}
+ {int8 flags hex (bits bitmapSizeFlags)}
  {IndexSubtableRecord indexSubtableList [numberOfIndexSubtables] (at indexSubtableListOffset)})
 
 (mkcmplx TableEBDT {uint16 majorVersion (== 2)} {uint16 minorVersion (== 0) unused} #:tag "EBDT")
@@ -617,12 +631,14 @@
          #:tag "loca"
          #:after (list TableHead))
 
+(define variationAxisRecordFlags #hash((0 . VARIATIONAXISRECORD_FL_HIDDEN_AXIS)))
+
 (mkcmplx VariationAxisRecord
          {Tag axisTag}
          {Fixed minValue}
          {Fixed defaultValue}
          {Fixed maxValue}
-         {uint16 flags hex}
+         {uint16 flags hex (bits variationAxisRecordFlags)}
          {uint16 axisNameID})
 
 (mkcmplx UserTuple {Fixed coordinates [o->axisCount]})
@@ -629,7 +645,7 @@
 
 (mkcmplx InstanceRecord
          {uint16 subfamilyNameID}
-         {uint16 flags hex}
+         {uint16 flags hex unused}
          {UserTuple coordinates}
          {uint16 postScriptNameID (== o->instanceSize (+ (* o->axisCount 4) 6))})
 
@@ -718,10 +734,12 @@
          {Offset32 signatureBlockOffset}
          {SignatureBlock1 signatureBlock1 (at signatureBlockOffset) (== format 1)})
 
+(define dsigFlags #hash((0 . DSIG_CANNOT_BE_RESIGNED)))
+
 (mkcmplx TableDSIG
          {uint32 version (== 1) unused}
          {uint16 numSignatures}
-         {uint16 flags hex}
+         {uint16 flags hex (bits dsigFlags)}
          {SignatureRecord signatureRecords [numSignatures]}
          #:tag "DSIG")
 
@@ -755,17 +773,21 @@
          {GaspRange gaspRanges [numRanges]}
          #:tag "gasp")
 
-(mkcmplx TableGvar
-         {uint16 majorVersion (== 1) unused}
-         {uint16 minorVersion (== 0) unused}
-         {uint16 axisCount #;(== o->axisCount)} ; FIXME
-         {uint16 sharedTupleCount}
-         {Offset32 sharedTuplesOffset}
-         {uint16 glyphCount #;(== o->glyphCount)} ; FIXME
-         {uint16 flags hex}
-         {Offset32 glyphVariationDataArrayOffset}
-         #;{Offset16/Offset32 glyphVariationDataOffsets [+ glyphCount 1]} ; FIXME
-         #:tag "gvar")
+(define gvarFlags #hash((0 . GVAR_FL_LONG_OFFSETS)))
+
+(mkcmplx
+ TableGvar
+ {uint16 majorVersion (== 1) unused}
+ {uint16 minorVersion (== 0) unused}
+ {uint16 axisCount #;(== o->axisCount)} ; FIXME
+ {uint16 sharedTupleCount}
+ {Offset32 sharedTuplesOffset}
+ {uint16 glyphCount #;(== o->glyphCount)} ; FIXME
+ {uint16 flags hex (bits gvarFlags)}
+ {Offset32 glyphVariationDataArrayOffset}
+ {Offset16 glyphVariationDataOffsetsShort [+ glyphCount 1] (== (& flags GVAR_FL_LONG_OFFSETS) 0)}
+ {Offset32 glyphVariationDataOffsetsLong [+ glyphCount 1] (!= (& flags GVAR_FL_LONG_OFFSETS) 0)}
+ #:tag "gvar")
 
 (mkcmplx AxisValueMap {F2DOT14 fromCoordinate} {F2DOT14 toCoordinate})