From 49b360a928a9b1da39095af85356a4a42f9c6750 Mon Sep 17 00:00:00 2001 From: Rohit Kumbhar Date: Tue, 16 Jun 2026 15:29:45 -0700 Subject: [PATCH 1/6] Add stub support for variable font tables (fvar, avar, gvar, STAT, HVAR, MVAR) Registers parsers, tags, and typed accessors for the OpenType font variations tables without implementing full decoding of their internal structures. Co-Authored-By: Claude Sonnet 4 --- sfnt/font.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++ sfnt/table.go | 6 +++++ sfnt/table_avar.go | 20 ++++++++++++++++ sfnt/table_fvar.go | 20 ++++++++++++++++ sfnt/table_gvar.go | 20 ++++++++++++++++ sfnt/table_hvar.go | 20 ++++++++++++++++ sfnt/table_mvar.go | 20 ++++++++++++++++ sfnt/table_stat.go | 21 ++++++++++++++++ sfnt/tag.go | 13 ++++++++++ 9 files changed, 200 insertions(+) create mode 100644 sfnt/table_avar.go create mode 100644 sfnt/table_fvar.go create mode 100644 sfnt/table_gvar.go create mode 100644 sfnt/table_hvar.go create mode 100644 sfnt/table_mvar.go create mode 100644 sfnt/table_stat.go diff --git a/sfnt/font.go b/sfnt/font.go index 619608d..4540a27 100644 --- a/sfnt/font.go +++ b/sfnt/font.go @@ -167,6 +167,66 @@ func (font *Font) GsubTable() (*TableLayout, error) { return font.TableLayout(TagGsub) } +// FvarTable returns the font variations table identified with the 'fvar' tag. +func (font *Font) FvarTable() (*TableFvar, error) { + t, err := font.Table(TagFvar) + if err != nil { + return nil, err + } + return t.(*TableFvar), nil +} + +// AvarTable returns the axis variations table identified with the 'avar' tag. +func (font *Font) AvarTable() (*TableAvar, error) { + t, err := font.Table(TagAvar) + if err != nil { + return nil, err + } + return t.(*TableAvar), nil +} + +// GvarTable returns the glyph variations table identified with the 'gvar' tag. +func (font *Font) GvarTable() (*TableGvar, error) { + t, err := font.Table(TagGvar) + if err != nil { + return nil, err + } + return t.(*TableGvar), nil +} + +// StatTable returns the style attributes table identified with the 'STAT' tag. +func (font *Font) StatTable() (*TableStat, error) { + t, err := font.Table(TagStat) + if err != nil { + return nil, err + } + return t.(*TableStat), nil +} + +// HvarTable returns the horizontal metrics variations table identified with the 'HVAR' tag. +func (font *Font) HvarTable() (*TableHvar, error) { + t, err := font.Table(TagHvar) + if err != nil { + return nil, err + } + return t.(*TableHvar), nil +} + +// MvarTable returns the metrics variations table identified with the 'MVAR' tag. +func (font *Font) MvarTable() (*TableMvar, error) { + t, err := font.Table(TagMvar) + if err != nil { + return nil, err + } + return t.(*TableMvar), nil +} + +// IsVariable returns true if this font contains an 'fvar' table, +// indicating it is a variable font. +func (font *Font) IsVariable() bool { + return font.HasTable(TagFvar) +} + func (font *Font) Table(tag Tag) (Table, error) { s, found := font.tables[tag] if !found { diff --git a/sfnt/table.go b/sfnt/table.go index 366fb41..f595d97 100644 --- a/sfnt/table.go +++ b/sfnt/table.go @@ -12,6 +12,12 @@ var parsers = map[Tag]tableParser{ TagOS2: parseTableOS2, TagGpos: parseTableLayout, TagGsub: parseTableLayout, + TagFvar: parseTableFvar, + TagAvar: parseTableAvar, + TagGvar: parseTableGvar, + TagStat: parseTableStat, + TagHvar: parseTableHvar, + TagMvar: parseTableMvar, } // Table is an interface for each section of the font file. diff --git a/sfnt/table_avar.go b/sfnt/table_avar.go new file mode 100644 index 0000000..a169a6d --- /dev/null +++ b/sfnt/table_avar.go @@ -0,0 +1,20 @@ +package sfnt + +// TableAvar contains the axis variations table, which provides +// optional fine-tuning of the variation space by remapping axis values. +// See https://learn.microsoft.com/en-us/typography/opentype/spec/avar +type TableAvar struct { + baseTable + bytes []byte +} + +func parseTableAvar(tag Tag, buf []byte) (Table, error) { + return &TableAvar{ + baseTable: baseTable(tag), + bytes: buf, + }, nil +} + +func (t *TableAvar) Bytes() []byte { + return t.bytes +} diff --git a/sfnt/table_fvar.go b/sfnt/table_fvar.go new file mode 100644 index 0000000..da802b9 --- /dev/null +++ b/sfnt/table_fvar.go @@ -0,0 +1,20 @@ +package sfnt + +// TableFvar contains the font variations table, which defines the +// variation axes and named instances for a variable font. +// See https://learn.microsoft.com/en-us/typography/opentype/spec/fvar +type TableFvar struct { + baseTable + bytes []byte +} + +func parseTableFvar(tag Tag, buf []byte) (Table, error) { + return &TableFvar{ + baseTable: baseTable(tag), + bytes: buf, + }, nil +} + +func (t *TableFvar) Bytes() []byte { + return t.bytes +} diff --git a/sfnt/table_gvar.go b/sfnt/table_gvar.go new file mode 100644 index 0000000..695167b --- /dev/null +++ b/sfnt/table_gvar.go @@ -0,0 +1,20 @@ +package sfnt + +// TableGvar contains the glyph variations table, which defines +// how TrueType glyph outlines vary across the font's variation axes. +// See https://learn.microsoft.com/en-us/typography/opentype/spec/gvar +type TableGvar struct { + baseTable + bytes []byte +} + +func parseTableGvar(tag Tag, buf []byte) (Table, error) { + return &TableGvar{ + baseTable: baseTable(tag), + bytes: buf, + }, nil +} + +func (t *TableGvar) Bytes() []byte { + return t.bytes +} diff --git a/sfnt/table_hvar.go b/sfnt/table_hvar.go new file mode 100644 index 0000000..b0dadea --- /dev/null +++ b/sfnt/table_hvar.go @@ -0,0 +1,20 @@ +package sfnt + +// TableHvar contains the horizontal metrics variations table, which +// describes how horizontal glyph metrics vary across variation axes. +// See https://learn.microsoft.com/en-us/typography/opentype/spec/hvar +type TableHvar struct { + baseTable + bytes []byte +} + +func parseTableHvar(tag Tag, buf []byte) (Table, error) { + return &TableHvar{ + baseTable: baseTable(tag), + bytes: buf, + }, nil +} + +func (t *TableHvar) Bytes() []byte { + return t.bytes +} diff --git a/sfnt/table_mvar.go b/sfnt/table_mvar.go new file mode 100644 index 0000000..1fb712c --- /dev/null +++ b/sfnt/table_mvar.go @@ -0,0 +1,20 @@ +package sfnt + +// TableMvar contains the metrics variations table, which describes +// how font-wide metrics vary across the font's variation axes. +// See https://learn.microsoft.com/en-us/typography/opentype/spec/mvar +type TableMvar struct { + baseTable + bytes []byte +} + +func parseTableMvar(tag Tag, buf []byte) (Table, error) { + return &TableMvar{ + baseTable: baseTable(tag), + bytes: buf, + }, nil +} + +func (t *TableMvar) Bytes() []byte { + return t.bytes +} diff --git a/sfnt/table_stat.go b/sfnt/table_stat.go new file mode 100644 index 0000000..8ac1903 --- /dev/null +++ b/sfnt/table_stat.go @@ -0,0 +1,21 @@ +package sfnt + +// TableStat contains the style attributes table, which describes +// design axes and their values for variable and non-variable fonts. +// Required for variable fonts. +// See https://learn.microsoft.com/en-us/typography/opentype/spec/stat +type TableStat struct { + baseTable + bytes []byte +} + +func parseTableStat(tag Tag, buf []byte) (Table, error) { + return &TableStat{ + baseTable: baseTable(tag), + bytes: buf, + }, nil +} + +func (t *TableStat) Bytes() []byte { + return t.bytes +} diff --git a/sfnt/tag.go b/sfnt/tag.go index 1dcfaa1..38a6870 100644 --- a/sfnt/tag.go +++ b/sfnt/tag.go @@ -25,6 +25,19 @@ var ( // TagGsub represents the 'GSUB' table, which contains Glyph Substitution features TagGsub = MustNamedTag("GSUB") + // TagFvar represents the 'fvar' table, which contains font variation axis definitions + TagFvar = MustNamedTag("fvar") + // TagAvar represents the 'avar' table, which contains axis variation remapping + TagAvar = MustNamedTag("avar") + // TagGvar represents the 'gvar' table, which contains glyph variation data + TagGvar = MustNamedTag("gvar") + // TagStat represents the 'STAT' table, which contains style attributes + TagStat = MustNamedTag("STAT") + // TagHvar represents the 'HVAR' table, which contains horizontal metrics variations + TagHvar = MustNamedTag("HVAR") + // TagMvar represents the 'MVAR' table, which contains metrics variations + TagMvar = MustNamedTag("MVAR") + // TypeTrueType is the first four bytes of an OpenType file containing a TrueType font TypeTrueType = Tag{0x00010000} // TypeAppleTrueType is the first four bytes of an OpenType file containing a TrueType font From d8039a178889d3d87bb739ea8ce9740a99927185 Mon Sep 17 00:00:00 2001 From: Rohit Kumbhar Date: Tue, 16 Jun 2026 19:30:07 -0700 Subject: [PATCH 2/6] updated readme for test --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ea1f050..6922ebb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ font ==== -[![Build Status](https://travis-ci.org/ConradIrwin/font.svg?branch=master)](https://travis-ci.org/ConradIrwin/font) [![GoDoc](https://godoc.org/github.com/ConradIrwin/font?status.svg)](https://godoc.org/github.com/ConradIrwin/font) A collection of Go packages for parsing and encoding OpenType fonts. From b8b26c805dce6c7a855aed4629e69e34f8638a2f Mon Sep 17 00:00:00 2001 From: Rohit Kumbhar Date: Tue, 16 Jun 2026 19:52:10 -0700 Subject: [PATCH 3/6] Revert "updated readme for test" This reverts commit d8039a178889d3d87bb739ea8ce9740a99927185. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6922ebb..ea1f050 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ font ==== +[![Build Status](https://travis-ci.org/ConradIrwin/font.svg?branch=master)](https://travis-ci.org/ConradIrwin/font) [![GoDoc](https://godoc.org/github.com/ConradIrwin/font?status.svg)](https://godoc.org/github.com/ConradIrwin/font) A collection of Go packages for parsing and encoding OpenType fonts. From 57565113751aff12eef2ff236211666f67e2448c Mon Sep 17 00:00:00 2001 From: Rohit Kumbhar Date: Tue, 16 Jun 2026 19:55:44 -0700 Subject: [PATCH 4/6] Reapply "updated readme for test" This reverts commit b8b26c805dce6c7a855aed4629e69e34f8638a2f. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ea1f050..6922ebb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ font ==== -[![Build Status](https://travis-ci.org/ConradIrwin/font.svg?branch=master)](https://travis-ci.org/ConradIrwin/font) [![GoDoc](https://godoc.org/github.com/ConradIrwin/font?status.svg)](https://godoc.org/github.com/ConradIrwin/font) A collection of Go packages for parsing and encoding OpenType fonts. From a9790ab65e9b2940f4590cdc36c70486bb98d766 Mon Sep 17 00:00:00 2001 From: Rohit Kumbhar Date: Tue, 16 Jun 2026 20:02:12 -0700 Subject: [PATCH 5/6] Revert "Reapply "updated readme for test"" This reverts commit 57565113751aff12eef2ff236211666f67e2448c. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6922ebb..ea1f050 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ font ==== +[![Build Status](https://travis-ci.org/ConradIrwin/font.svg?branch=master)](https://travis-ci.org/ConradIrwin/font) [![GoDoc](https://godoc.org/github.com/ConradIrwin/font?status.svg)](https://godoc.org/github.com/ConradIrwin/font) A collection of Go packages for parsing and encoding OpenType fonts. From 49c7b8b0bd39d50cbfdfbec6c0a4b3ad2b701be6 Mon Sep 17 00:00:00 2001 From: Rohit Kumbhar Date: Tue, 16 Jun 2026 20:04:39 -0700 Subject: [PATCH 6/6] Reapply "Reapply "updated readme for test"" This reverts commit a9790ab65e9b2940f4590cdc36c70486bb98d766. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ea1f050..6922ebb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ font ==== -[![Build Status](https://travis-ci.org/ConradIrwin/font.svg?branch=master)](https://travis-ci.org/ConradIrwin/font) [![GoDoc](https://godoc.org/github.com/ConradIrwin/font?status.svg)](https://godoc.org/github.com/ConradIrwin/font) A collection of Go packages for parsing and encoding OpenType fonts.