shithub: fnt

Download patch

ref: f711b4426695620ce7646d3036f69275be73e59f
parent: 19827008dbe2ae5253cb63df13c4d207ccecbf02
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Mon Sep 2 19:25:31 EDT 2024

define COLR and CPAL

--- a/otf.rkt
+++ b/otf.rkt
@@ -1130,6 +1130,32 @@
          {uint16 usUpperOpticalPointSize (>= version 5)}
          #:tag "OS/2")
 
+(mkcmplx BaseGlyph {uint16 glyphID} {uint16 firstLayerIndex} {uint16 numLayers})
+
+(mkcmplx Layer {uint16 glyphID} {uint16 paletteIndex})
+
+(mkcmplx TableCOLR
+         {uint16 version (== 0)} ; FIXME v1 has more stuff
+         {uint16 numBaseGlyphRecords}
+         {Offset32 baseGlyphRecordsOffset}
+         {Offset32 layerRecordsOffset}
+         {uint16 numLayerRecords}
+         {BaseGlyph baseGlyphs [numBaseGlyphRecords] (at baseGlyphRecordsOffset)}
+         {Layer layers [numLayerRecords] (at layerRecordsOffset)}
+         #:tag "COLR")
+
+(mkcmplx ColorRecord {uint8 blue} {uint8 greed} {uint8 red} {uint8 alpha})
+
+(mkcmplx TableCPAL
+         {uint16 version (== 0)} ; FIXME v1 has more stuff
+         {uint16 numPaletteEntries}
+         {uint16 numPalettes}
+         {uint16 numColorRecords}
+         {Offset32 colorRecordsArrayOffset}
+         {uint16 colorRecordIndices [numPalettes]}
+         {ColorRecord colorRecords [numColorRecords] (at colorRecordsArrayOffset)}
+         #:tag "CPAL")
+
 (mkcmplx TableRecord
          {Tag tableTag}
          {uint32 checksum unused hex}
--- a/plan9/otf.c
+++ b/plan9/otf.c
@@ -7376,6 +7376,191 @@
 }
 
 int
+read_BaseGlyph(Otf *o, BaseGlyph *v)
+{
+	u8int *b = nil; USED(b);
+	if((b = otfreadn(o, 6)) == nil)
+		goto err;
+	v->glyphID = b[0]<<8 | b[1];
+	v->firstLayerIndex = b[2]<<8 | b[3];
+	v->numLayers = b[4]<<8 | b[5];
+	return 0;
+err:
+	werrstr("%s: %r", "BaseGlyph");
+	return -1;
+}
+
+void
+print_BaseGlyph(Otfile *f, int indent, Otf *o, BaseGlyph *v)
+{
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "firstLayerIndex", v->firstLayerIndex);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "numLayers", v->numLayers);
+	USED(o);
+}
+
+int
+read_Layer(Otf *o, Layer *v)
+{
+	u8int *b = nil; USED(b);
+	if((b = otfreadn(o, 4)) == nil)
+		goto err;
+	v->glyphID = b[0]<<8 | b[1];
+	v->paletteIndex = b[2]<<8 | b[3];
+	return 0;
+err:
+	werrstr("%s: %r", "Layer");
+	return -1;
+}
+
+void
+print_Layer(Otfile *f, int indent, Otf *o, Layer *v)
+{
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "glyphID", v->glyphID);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "paletteIndex", v->paletteIndex);
+	USED(o);
+}
+
+int
+read_TableCOLR(Otf *o, TableCOLR *v)
+{
+	u8int *b = nil; USED(b);
+	if((b = otfreadn(o, 14)) == nil)
+		goto err;
+	v->version = b[0]<<8 | b[1];
+	if(v->version != 0){
+		werrstr("%s: invalid value: %d (%#ux)", "version", v->version, v->version);
+		goto err;
+	}
+	v->numBaseGlyphRecords = b[2]<<8 | b[3];
+	v->baseGlyphRecordsOffset = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
+	v->layerRecordsOffset = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11];
+	v->numLayerRecords = b[12]<<8 | b[13];
+	if(v->baseGlyphRecordsOffset != 0){
+		if(otfpushrange(o, v->baseGlyphRecordsOffset, -1) < 0)
+			goto err;
+		if(otfarray(o, &v->baseGlyphs, read_BaseGlyph, sizeof(BaseGlyph), v->numBaseGlyphRecords) < 0){
+			werrstr("%s: %r", "baseGlyphs");
+			goto err;
+		}
+		if(otfpoprange(o) < 0)
+			goto err;
+	}
+	if(v->layerRecordsOffset != 0){
+		if(otfpushrange(o, v->layerRecordsOffset, -1) < 0)
+			goto err;
+		if(otfarray(o, &v->layers, read_Layer, sizeof(Layer), v->numLayerRecords) < 0){
+			werrstr("%s: %r", "layers");
+			goto err;
+		}
+		if(otfpoprange(o) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	werrstr("%s: %r", "TableCOLR");
+	return -1;
+}
+
+void
+print_TableCOLR(Otfile *f, int indent, Otf *o, TableCOLR *v)
+{
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "version", v->version);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "numBaseGlyphRecords", v->numBaseGlyphRecords);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "baseGlyphRecordsOffset", v->baseGlyphRecordsOffset);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "layerRecordsOffset", v->layerRecordsOffset);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "numLayerRecords", v->numLayerRecords);
+	for(int i = 0; i < v->numBaseGlyphRecords; i++){
+		f->print(f->aux, "%*s%s[%d]:\n", indent, "", "baseGlyphs", i);
+		print_BaseGlyph(f, indent+indentΔ, o, &v->baseGlyphs[i]);
+	}
+	for(int i = 0; i < v->numLayerRecords; i++){
+		f->print(f->aux, "%*s%s[%d]:\n", indent, "", "layers", i);
+		print_Layer(f, indent+indentΔ, o, &v->layers[i]);
+	}
+	USED(o);
+}
+
+int
+read_ColorRecord(Otf *o, ColorRecord *v)
+{
+	u8int *b = nil; USED(b);
+	if((b = otfreadn(o, 4)) == nil)
+		goto err;
+	v->blue = b[0];
+	v->greed = b[1];
+	v->red = b[2];
+	v->alpha = b[3];
+	return 0;
+err:
+	werrstr("%s: %r", "ColorRecord");
+	return -1;
+}
+
+void
+print_ColorRecord(Otfile *f, int indent, Otf *o, ColorRecord *v)
+{
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "blue", v->blue);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "greed", v->greed);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "red", v->red);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "alpha", v->alpha);
+	USED(o);
+}
+
+int
+read_TableCPAL(Otf *o, TableCPAL *v)
+{
+	u8int *b = nil; USED(b);
+	if((b = otfreadn(o, 12)) == nil)
+		goto err;
+	v->version = b[0]<<8 | b[1];
+	if(v->version != 0){
+		werrstr("%s: invalid value: %d (%#ux)", "version", v->version, v->version);
+		goto err;
+	}
+	v->numPaletteEntries = b[2]<<8 | b[3];
+	v->numPalettes = b[4]<<8 | b[5];
+	v->numColorRecords = b[6]<<8 | b[7];
+	v->colorRecordsArrayOffset = b[8]<<24 | b[9]<<16 | b[10]<<8 | b[11];
+	if((b = otfreadn(o, v->numPalettes*2)) == nil)
+		goto err;
+	v->colorRecordIndices = malloc(v->numPalettes*sizeof(*v->colorRecordIndices));
+	for(int i = 0; i < v->numPalettes; i++)
+		v->colorRecordIndices[i] = b[0+i*2]<<8 | b[1+i*2];
+	if(v->colorRecordsArrayOffset != 0){
+		if(otfpushrange(o, v->colorRecordsArrayOffset, -1) < 0)
+			goto err;
+		if(otfarray(o, &v->colorRecords, read_ColorRecord, sizeof(ColorRecord), v->numColorRecords) < 0){
+			werrstr("%s: %r", "colorRecords");
+			goto err;
+		}
+		if(otfpoprange(o) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	werrstr("%s: %r", "TableCPAL");
+	return -1;
+}
+
+void
+print_TableCPAL(Otfile *f, int indent, Otf *o, TableCPAL *v)
+{
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "version", v->version);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "numPaletteEntries", v->numPaletteEntries);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "numPalettes", v->numPalettes);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "numColorRecords", v->numColorRecords);
+	f->print(f->aux, "%*s%s: %ud\n", indent, "", "colorRecordsArrayOffset", v->colorRecordsArrayOffset);
+	for(int i = 0; i < v->numPalettes; i++)
+		f->print(f->aux, "%*s%s[%d]: %ud\n", indent, "", "colorRecordIndices", i, v->colorRecordIndices[i]);
+	for(int i = 0; i < v->numColorRecords; i++){
+		f->print(f->aux, "%*s%s[%d]:\n", indent, "", "colorRecords", i);
+		print_ColorRecord(f, indent+indentΔ, o, &v->colorRecords[i]);
+	}
+	USED(o);
+}
+
+int
 read_TableRecord(Otf *o, TableRecord *v)
 {
 	u8int *b = nil; USED(b);
@@ -7784,6 +7969,30 @@
 				}
 				rec->parsed = v->os∕2;
 				rec->print = (void*)print_TableOS∕2;
+				break;
+			case (u32int)('C'<<24|'O'<<16|'L'<<8|'R'):
+				if(v->colr != nil)
+					break;
+				v->colr = calloc(1, sizeof(TableCOLR));
+				if(read_TableCOLR(o, v->colr) < 0){
+					free(v->colr);
+					v->colr = nil;
+					goto err;
+				}
+				rec->parsed = v->colr;
+				rec->print = (void*)print_TableCOLR;
+				break;
+			case (u32int)('C'<<24|'P'<<16|'A'<<8|'L'):
+				if(v->cpal != nil)
+					break;
+				v->cpal = calloc(1, sizeof(TableCPAL));
+				if(read_TableCPAL(o, v->cpal) < 0){
+					free(v->cpal);
+					v->cpal = nil;
+					goto err;
+				}
+				rec->parsed = v->cpal;
+				rec->print = (void*)print_TableCPAL;
 				break;
 			default:
 				// FIXME fprint(2, "no parser for \"%t\"\n", rec->tableTag);
--- a/plan9/otf.h
+++ b/plan9/otf.h
@@ -311,6 +311,11 @@
 typedef struct SegmentMaps SegmentMaps;
 typedef struct TableAvar TableAvar;
 typedef struct TableOS∕2 TableOS∕2;
+typedef struct BaseGlyph BaseGlyph;
+typedef struct Layer Layer;
+typedef struct TableCOLR TableCOLR;
+typedef struct ColorRecord ColorRecord;
+typedef struct TableCPAL TableCPAL;
 typedef struct TableRecord TableRecord;
 typedef struct TableDirectory TableDirectory;
 
@@ -1985,6 +1990,59 @@
 int read_TableOS∕2(Otf *o, TableOS∕2 *v);
 void print_TableOS∕2(Otfile *f, int indent, Otf *o, TableOS∕2 *v);
 
+struct BaseGlyph {
+	u16int glyphID;
+	u16int firstLayerIndex;
+	u16int numLayers;
+};
+
+int read_BaseGlyph(Otf *o, BaseGlyph *v);
+void print_BaseGlyph(Otfile *f, int indent, Otf *o, BaseGlyph *v);
+
+struct Layer {
+	u16int glyphID;
+	u16int paletteIndex;
+};
+
+int read_Layer(Otf *o, Layer *v);
+void print_Layer(Otfile *f, int indent, Otf *o, Layer *v);
+
+struct TableCOLR {
+	u16int version;
+	u16int numBaseGlyphRecords;
+	u32int baseGlyphRecordsOffset;
+	u32int layerRecordsOffset;
+	u16int numLayerRecords;
+	BaseGlyph *baseGlyphs;
+	Layer *layers;
+};
+
+int read_TableCOLR(Otf *o, TableCOLR *v);
+void print_TableCOLR(Otfile *f, int indent, Otf *o, TableCOLR *v);
+
+struct ColorRecord {
+	u8int blue;
+	u8int greed;
+	u8int red;
+	u8int alpha;
+};
+
+int read_ColorRecord(Otf *o, ColorRecord *v);
+void print_ColorRecord(Otfile *f, int indent, Otf *o, ColorRecord *v);
+
+struct TableCPAL {
+	u16int version;
+	u16int numPaletteEntries;
+	u16int numPalettes;
+	u16int numColorRecords;
+	u32int colorRecordsArrayOffset;
+	u16int *colorRecordIndices;
+	ColorRecord *colorRecords;
+};
+
+int read_TableCPAL(Otf *o, TableCPAL *v);
+void print_TableCPAL(Otfile *f, int indent, Otf *o, TableCPAL *v);
+
 struct TableRecord {
 	u32int tableTag;
 	// u32int checksum;
@@ -2029,6 +2087,8 @@
 	TableGvar *gvar;
 	TableAvar *avar;
 	TableOS∕2 *os∕2;
+	TableCOLR *colr;
+	TableCPAL *cpal;
 };
 
 int read_TableDirectory(Otf *o, TableDirectory *v);