Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
font
Comment thread
rohitkumbhar marked this conversation as resolved.
Comment thread
rohitkumbhar marked this conversation as resolved.
====

[![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)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[INFO] Info: Unrelated change

Removing the Travis CI badge appears unrelated to adding variable font stubs. Consider keeping this change in a separate commit or PR for cleaner history, unless Travis CI is no longer used.

A collection of Go packages for parsing and encoding OpenType fonts.

Expand Down
60 changes: 60 additions & 0 deletions sfnt/font.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment thread
rohitkumbhar marked this conversation as resolved.
func (font *Font) FvarTable() (*TableFvar, error) {
t, err := font.Table(TagFvar)
if err != nil {
return nil, err
}
return t.(*TableFvar), nil
Comment thread
rohitkumbhar marked this conversation as resolved.
Comment thread
rohitkumbhar marked this conversation as resolved.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ERROR] Security/Correctness: Unsafe type assertion

This uses an unsafe type assertion t.(*TableFvar) that will panic if the table is not of the expected type. While the parser is registered in parsers map, corrupted font files or parser bugs could return unexpected types.

Recommendation: Use the safe two-value assertion pattern like TableLayout() does:

fvar, ok := t.(*TableFvar)
if !ok {
    return nil, fmt.Errorf("table %q is not an fvar table", tag)
}
return fvar, nil

This pattern is already used in TableLayout() at line 153-157 and should be applied consistently for defensive programming.

}
Comment thread
rohitkumbhar marked this conversation as resolved.

// 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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ERROR] Security/Correctness: Unsafe type assertion

Same issue as FvarTable() - uses unsafe type assertion that will panic on type mismatch. See comment on line 176 for recommended fix pattern.

}

Comment thread
rohitkumbhar marked this conversation as resolved.
// 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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ERROR] Security/Correctness: Unsafe type assertion

Same issue as FvarTable() - uses unsafe type assertion that will panic on type mismatch. See comment on line 176 for recommended fix pattern.

}

// StatTable returns the style attributes table identified with the 'STAT' tag.
Comment thread
rohitkumbhar marked this conversation as resolved.
func (font *Font) StatTable() (*TableStat, error) {
t, err := font.Table(TagStat)
if err != nil {
return nil, err
}
return t.(*TableStat), nil

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ERROR] Security/Correctness: Unsafe type assertion

Same issue as FvarTable() - uses unsafe type assertion that will panic on type mismatch. See comment on line 176 for recommended fix pattern.

}

// HvarTable returns the horizontal metrics variations table identified with the 'HVAR' tag.
func (font *Font) HvarTable() (*TableHvar, error) {
Comment thread
rohitkumbhar marked this conversation as resolved.
t, err := font.Table(TagHvar)
if err != nil {
return nil, err
}
return t.(*TableHvar), nil

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ERROR] Security/Correctness: Unsafe type assertion

Same issue as FvarTable() - uses unsafe type assertion that will panic on type mismatch. See comment on line 176 for recommended fix pattern.

}

// MvarTable returns the metrics variations table identified with the 'MVAR' tag.
func (font *Font) MvarTable() (*TableMvar, error) {
t, err := font.Table(TagMvar)
Comment thread
rohitkumbhar marked this conversation as resolved.
if err != nil {
return nil, err
}
return t.(*TableMvar), nil
Comment thread
rohitkumbhar marked this conversation as resolved.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ERROR] Security/Correctness: Unsafe type assertion

Same issue as FvarTable() - uses unsafe type assertion that will panic on type mismatch. See comment on line 176 for recommended fix pattern.

}

// IsVariable returns true if this font contains an 'fvar' table,
Comment thread
rohitkumbhar marked this conversation as resolved.
// indicating it is a variable font.
func (font *Font) IsVariable() bool {
return font.HasTable(TagFvar)
Comment thread
rohitkumbhar marked this conversation as resolved.
}

func (font *Font) Table(tag Tag) (Table, error) {
s, found := font.tables[tag]
if !found {
Expand Down
6 changes: 6 additions & 0 deletions sfnt/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
20 changes: 20 additions & 0 deletions sfnt/table_avar.go
Original file line number Diff line number Diff line change
@@ -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) {
Comment thread
rohitkumbhar marked this conversation as resolved.
return &TableAvar{
baseTable: baseTable(tag),
bytes: buf,
}, nil
}

func (t *TableAvar) Bytes() []byte {
return t.bytes
}
20 changes: 20 additions & 0 deletions sfnt/table_fvar.go
Original file line number Diff line number Diff line change
@@ -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) {
Comment thread
rohitkumbhar marked this conversation as resolved.
Comment thread
rohitkumbhar marked this conversation as resolved.
Comment thread
rohitkumbhar marked this conversation as resolved.
return &TableFvar{

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[INFO] Info: Parser does not validate table data

The parser accepts any byte slice without validation. While this matches the stub implementation pattern, consider adding basic validation in future iterations:

  • Check minimum length requirements for the fvar table header
  • Validate version number
  • Verify axis count and instance count are reasonable

This is acceptable for a stub implementation but should be tracked for future work.

baseTable: baseTable(tag),
bytes: buf,
}, nil
}

func (t *TableFvar) Bytes() []byte {
return t.bytes
}
20 changes: 20 additions & 0 deletions sfnt/table_gvar.go
Original file line number Diff line number Diff line change
@@ -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) {
Comment thread
rohitkumbhar marked this conversation as resolved.
return &TableGvar{
baseTable: baseTable(tag),
bytes: buf,
}, nil
}

func (t *TableGvar) Bytes() []byte {
return t.bytes
}
20 changes: 20 additions & 0 deletions sfnt/table_hvar.go
Original file line number Diff line number Diff line change
@@ -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) {
Comment thread
rohitkumbhar marked this conversation as resolved.
return &TableHvar{
baseTable: baseTable(tag),
bytes: buf,
}, nil
}

func (t *TableHvar) Bytes() []byte {
return t.bytes
}
20 changes: 20 additions & 0 deletions sfnt/table_mvar.go
Original file line number Diff line number Diff line change
@@ -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) {
Comment thread
rohitkumbhar marked this conversation as resolved.
return &TableMvar{
baseTable: baseTable(tag),
bytes: buf,
}, nil
}

func (t *TableMvar) Bytes() []byte {
return t.bytes
}
21 changes: 21 additions & 0 deletions sfnt/table_stat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package sfnt

// TableStat contains the style attributes table, which describes
Comment thread
rohitkumbhar marked this conversation as resolved.
// 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
}

Comment thread
rohitkumbhar marked this conversation as resolved.
func parseTableStat(tag Tag, buf []byte) (Table, error) {
return &TableStat{
baseTable: baseTable(tag),
bytes: buf,
}, nil
}

func (t *TableStat) Bytes() []byte {
return t.bytes
}
13 changes: 13 additions & 0 deletions sfnt/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down