shithub: fnt

Download patch

ref: d5219f723f7511b56d9811d19da617c4bb3b3fd0
parent: b8442cf99bf3c724441a5abca9f6497eb6407add
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Jun 23 21:50:56 EDT 2024

a bit more of gvar

--- a/gen.rkt
+++ b/gen.rkt
@@ -476,7 +476,7 @@
   (define-syntax-class arithop
     #:description "arithmetical operator"
     (pattern op:id
-      #:when (member (syntax-e #'op) '(+ - / *))))
+      #:when (member (syntax-e #'op) '(+ - / * &))))
 
   (define-syntax-class oref
     #:description "extra context field reference"
--- a/otf.c
+++ b/otf.c
@@ -4358,6 +4358,99 @@
 }
 
 int
+read_Tuple(Otf *o, Tuple *v)
+{
+	u8int *b;
+	if((b = otfreadn(o, o->axisCount*2)) == 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*2]<<8 | b[1+i*2]>>14)+(b[0+i*2]<<8 | b[1+i*2]&((1<<14)-1))/16384.0;
+	return 0;
+err:
+	werrstr("%s: %r", "Tuple");
+	return -1;
+}
+
+void
+print_Tuple(Biobuf *f, int indent, Otf *o, Tuple *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_TupleVariationHeader(Otf *o, TupleVariationHeader *v)
+{
+	u8int *b;
+	if((b = otfreadn(o, 4)) == nil)
+		goto err;
+	v->variationDataSize = b[0]<<8 | b[1];
+	v->tupleIndex = b[2]<<8 | b[3];
+	if(read_Tuple(o, &v->peakTuple) < 0){
+		werrstr("%s: %r", "peakTuple");
+		goto err;
+	}
+	if(read_Tuple(o, &v->intermediateStartTuple) < 0){
+		werrstr("%s: %r", "intermediateStartTuple");
+		goto err;
+	}
+	if(read_Tuple(o, &v->intermediateEndTuple) < 0){
+		werrstr("%s: %r", "intermediateEndTuple");
+		goto err;
+	}
+	return 0;
+err:
+	werrstr("%s: %r", "TupleVariationHeader");
+	return -1;
+}
+
+void
+print_TupleVariationHeader(Biobuf *f, int indent, Otf *o, TupleVariationHeader *v)
+{
+	Bprint(f, "%*s%s: %ud\n", indent, "", "variationDataSize", v->variationDataSize);
+	Bprint(f, "%*s%s: %ud%s%s%s\n", indent, "", "tupleIndex", v->tupleIndex, (v->tupleIndex&TUPLEINDEX_FL_PRIVATE_POINT_NUMBERS)?" TUPLEINDEX_FL_PRIVATE_POINT_NUMBERS":"", (v->tupleIndex&TUPLEINDEX_FL_INTERMEDIATE_REGION)?" TUPLEINDEX_FL_INTERMEDIATE_REGION":"", (v->tupleIndex&TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE)?" TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE":"");
+	Bprint(f, "%*s%s:\n", indent, "", "peakTuple");
+	print_Tuple(f, indent+indentΔ, o, &v->peakTuple);
+	Bprint(f, "%*s%s:\n", indent, "", "intermediateStartTuple");
+	print_Tuple(f, indent+indentΔ, o, &v->intermediateStartTuple);
+	Bprint(f, "%*s%s:\n", indent, "", "intermediateEndTuple");
+	print_Tuple(f, indent+indentΔ, o, &v->intermediateEndTuple);
+	USED(o);
+}
+
+int
+read_GlyphVariationData(Otf *o, GlyphVariationData *v)
+{
+	u8int *b;
+	if((b = otfreadn(o, 4)) == nil)
+		goto err;
+	v->tupleVariationCount = b[0]<<8 | b[1];
+	v->dataOffset = b[2]<<8 | b[3];
+	if(otfarray(o, &v->tupleVariationHeaders, read_TupleVariationHeader, sizeof(TupleVariationHeader), (v->tupleVariationCount&4095)) < 0){
+		werrstr("%s: %r", "tupleVariationHeaders");
+		goto err;
+	}
+	return 0;
+err:
+	werrstr("%s: %r", "GlyphVariationData");
+	return -1;
+}
+
+void
+print_GlyphVariationData(Biobuf *f, int indent, Otf *o, GlyphVariationData *v)
+{
+	Bprint(f, "%*s%s: %ud%s\n", indent, "", "tupleVariationCount", v->tupleVariationCount, (v->tupleVariationCount&COUNT_FL_SHARED_POINT_NUMBERS)?" COUNT_FL_SHARED_POINT_NUMBERS":"");
+	Bprint(f, "%*s%s: %ud\n", indent, "", "dataOffset", v->dataOffset);
+	for(int i = 0; i < (v->tupleVariationCount&4095); i++){
+		Bprint(f, "%*s%s[%d]:\n", indent, "", "tupleVariationHeaders", i);
+		print_TupleVariationHeader(f, indent+indentΔ, o, &v->tupleVariationHeaders[i]);
+	}
+	USED(o);
+}
+
+int
 read_TableGvar(Otf *o, TableGvar *v)
 {
 	u8int *b;
@@ -4393,6 +4486,16 @@
 		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];
 	}
+	if(v->sharedTuplesOffset != 0){
+		if(otfpushrange(o, v->sharedTuplesOffset, -1) < 0)
+			goto err;
+		if(otfarray(o, &v->sharedTuples, read_Tuple, sizeof(Tuple), v->sharedTupleCount) < 0){
+			werrstr("%s: %r", "sharedTuples");
+			goto err;
+		}
+		if(otfpoprange(o) < 0)
+			goto err;
+	}
 	return 0;
 err:
 	werrstr("%s: %r", "TableGvar");
@@ -4416,6 +4519,10 @@
 		for(int i = 0; i < (v->glyphCount+1); i++)
 			Bprint(f, "%*s%s[%d]: %ud\n", indent, "", "glyphVariationDataOffsetsLong", i, v->glyphVariationDataOffsetsLong[i]);
 	}
+	for(int i = 0; i < v->sharedTupleCount; i++){
+		Bprint(f, "%*s%s[%d]:\n", indent, "", "sharedTuples", i);
+		print_Tuple(f, indent+indentΔ, o, &v->sharedTuples[i]);
+	}
 	USED(o);
 }
 
@@ -4958,6 +5065,20 @@
 				rec->print = (void*)print_TableGasp;
 				break;
 			case (u32int)('g'<<24|'v'<<16|'a'<<8|'r'):
+				{
+					static int retried = 0;
+					if(v->fvar == nil){
+						if(retried){
+							werrstr("%s: deps missing", "TableGvar");
+							goto err;
+						}
+						retried = 1;
+						retry++;
+						break;
+					}
+					if(retried)
+						retry--;
+				}
 				if(v->gvar != nil)
 					break;
 				v->gvar = calloc(1, sizeof(TableGvar));
--- a/otf.h
+++ b/otf.h
@@ -108,6 +108,9 @@
 typedef struct TableSTAT TableSTAT;
 typedef struct GaspRange GaspRange;
 typedef struct TableGasp TableGasp;
+typedef struct Tuple Tuple;
+typedef struct TupleVariationHeader TupleVariationHeader;
+typedef struct GlyphVariationData GlyphVariationData;
 typedef struct TableGvar TableGvar;
 typedef struct AxisValueMap AxisValueMap;
 typedef struct SegmentMaps SegmentMaps;
@@ -1311,6 +1314,45 @@
 int read_TableGasp(Otf *o, TableGasp *v);
 void print_TableGasp(Biobuf *f, int indent, Otf *o, TableGasp *v);
 
+struct Tuple {
+	float *coordinates;
+};
+
+int read_Tuple(Otf *o, Tuple *v);
+void print_Tuple(Biobuf *f, int indent, Otf *o, Tuple *v);
+
+enum { // TupleVariationHeader
+	// tupleIndex
+	TUPLEINDEX_FL_PRIVATE_POINT_NUMBERS = 1<<13,
+	TUPLEINDEX_FL_INTERMEDIATE_REGION = 1<<14,
+	TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE = 1<<15,
+};
+
+struct TupleVariationHeader {
+	u16int variationDataSize;
+	u16int tupleIndex;
+	Tuple peakTuple;
+	Tuple intermediateStartTuple;
+	Tuple intermediateEndTuple;
+};
+
+int read_TupleVariationHeader(Otf *o, TupleVariationHeader *v);
+void print_TupleVariationHeader(Biobuf *f, int indent, Otf *o, TupleVariationHeader *v);
+
+enum { // GlyphVariationData
+	// tupleVariationCount
+	COUNT_FL_SHARED_POINT_NUMBERS = 1<<15,
+};
+
+struct GlyphVariationData {
+	u16int tupleVariationCount;
+	u16int dataOffset;
+	TupleVariationHeader *tupleVariationHeaders;
+};
+
+int read_GlyphVariationData(Otf *o, GlyphVariationData *v);
+void print_GlyphVariationData(Biobuf *f, int indent, Otf *o, GlyphVariationData *v);
+
 enum { // TableGvar
 	// flags
 	GVAR_FL_LONG_OFFSETS = 1<<0,
@@ -1327,6 +1369,7 @@
 	u32int glyphVariationDataArrayOffset;
 	u16int *glyphVariationDataOffsetsShort;
 	u32int *glyphVariationDataOffsetsLong;
+	Tuple *sharedTuples;
 };
 
 int read_TableGvar(Otf *o, TableGvar *v);
--- a/otf.rkt
+++ b/otf.rkt
@@ -773,6 +773,27 @@
          {GaspRange gaspRanges [numRanges]}
          #:tag "gasp")
 
+(mkcmplx Tuple {F2DOT14 coordinates [o->axisCount]})
+
+(define tupleIndexFlags
+  #hash((13 . TUPLEINDEX_FL_PRIVATE_POINT_NUMBERS)
+        (14 . TUPLEINDEX_FL_INTERMEDIATE_REGION)
+        (15 . TUPLEINDEX_FL_EMBEDDED_PEAK_TUPLE)))
+
+(mkcmplx TupleVariationHeader
+         {uint16 variationDataSize}
+         {uint16 tupleIndex (bits tupleIndexFlags)} ; FIXME 0xfff is TUPLE_INDEX_MASK
+         {Tuple peakTuple}
+         {Tuple intermediateStartTuple}
+         {Tuple intermediateEndTuple})
+
+(define glyphVariationDataCountFlags #hash((15 . COUNT_FL_SHARED_POINT_NUMBERS)))
+
+(mkcmplx GlyphVariationData
+         {uint16 tupleVariationCount (bits glyphVariationDataCountFlags)}
+         {Offset16 dataOffset}
+         {TupleVariationHeader tupleVariationHeaders [& tupleVariationCount #xfff]})
+
 (define gvarFlags #hash((0 . GVAR_FL_LONG_OFFSETS)))
 
 (mkcmplx
@@ -787,7 +808,9 @@
  {Offset32 glyphVariationDataArrayOffset}
  {Offset16 glyphVariationDataOffsetsShort [+ glyphCount 1] (== (& flags GVAR_FL_LONG_OFFSETS) 0)}
  {Offset32 glyphVariationDataOffsetsLong [+ glyphCount 1] (!= (& flags GVAR_FL_LONG_OFFSETS) 0)}
- #:tag "gvar")
+ {Tuple sharedTuples [sharedTupleCount] (at sharedTuplesOffset)}
+ #:tag "gvar"
+ #:after (list TableFvar))
 
 (mkcmplx AxisValueMap {F2DOT14 fromCoordinate} {F2DOT14 toCoordinate})