Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add parsing code for the Font Features, as well as new command #3

Merged
merged 7 commits into from Jan 23, 2018
61 changes: 61 additions & 0 deletions commands/features.go
@@ -0,0 +1,61 @@
package commands

import (
"fmt"
"os"

"github.com/ConradIrwin/font/sfnt"
)

// Features prints the gpos/gsub tables (contains font features).
func Features() {
if len(os.Args) < 2 {
panic(fmt.Errorf("Specify a font file"))
Copy link
Owner

Choose a reason for hiding this comment

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

Can we start to improve the code for handling these errors, we should make it clear how to fix the problem, and make the error message more legible. (I appreciate the other commands aren't yet very good).

fmt.Printf("Usage: font features <font-file>")
os.Exit(1)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll do that in a later PR.

}

file, err := os.Open(os.Args[1])
if err != nil {
panic(fmt.Errorf("Failed to open font: %s", err))
}
defer file.Close()

font, err := sfnt.Parse(file)
if err != nil {
panic(fmt.Errorf("Failed to parse font: %s", err))
}

layoutTable(font, sfnt.TagGsub, "Glyph Substitution Table (GSUB)")
layoutTable(font, sfnt.TagGpos, "Glyph Positioning Table (GPOS)")
}

func layoutTable(font *sfnt.Font, tag sfnt.Tag, name string) {
if font.HasTable(tag) {
fmt.Printf("%s:\n", name)

t := font.Table(tag).(*sfnt.TableLayout)
Copy link
Owner

Choose a reason for hiding this comment

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

@bramp This will panic if parsing fails. I'm not sure what to do about that except maybe change the library so that it parses tables on-demand instead of up-front so we can return a sensible error. Any better ideas?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, panic'ng sucks. After this I'd be happy to change the whole library to pass back the errors.

Copy link
Owner

Choose a reason for hiding this comment

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

That'd be incredible 😻

for _, script := range t.Scripts {
fmt.Printf("\tScript %q%s:\n", script.Tag, bracketString(script))

fmt.Printf("\t\tDefault Language:\n")
for _, feature := range script.DefaultLanguage.Features {
fmt.Printf("\t\t\tFeature %q%s\n", feature.Tag, bracketString(feature))
}

for _, lang := range script.Languages {
fmt.Printf("\t\tLanguage %q%s:\n", lang.Tag, bracketString(lang))
for _, feature := range lang.Features {
fmt.Printf("\t\t\tFeature %q%s\n", feature.Tag, bracketString(feature))
}
}
}
} else {
fmt.Printf("No %s\n", name)
}
}

func bracketString(o fmt.Stringer) string {
if s := o.String(); s != "" {
return fmt.Sprintf(" (%s)", s)
}
return ""
}
1 change: 0 additions & 1 deletion commands/info.go
Expand Up @@ -11,7 +11,6 @@ import (
)

func Info() {

file, err := os.Open(os.Args[1])
if err != nil {
panic(err)
Expand Down
9 changes: 6 additions & 3 deletions main.go
Expand Up @@ -25,14 +25,17 @@ func main() {
commands.Stats()
case "metrics":
commands.Metrics()
case "features":
commands.Features()
default:
fmt.Println(`
Usage: font [scrub|info|stats] font.[otf,ttf,woff]
Usage: font [features|info|metrics|scrub|stats] font.[otf,ttf,woff]

features: prints the gpos/gsub tables (contains font features)
info: prints the name table (contains metadata)
metrics: prints the hhea table (contains font metrics)
stats: prints each table and the amount of space used
scrub: remove the name table (saves significant space)`)
scrub: remove the name table (saves significant space)
stats: prints each table and the amount of space used`)
}

}
12 changes: 12 additions & 0 deletions sfnt/font.go
Expand Up @@ -120,6 +120,18 @@ func (font *Font) OS2Table() *TableOS2 {
return font.tables[TagOS2].(*TableOS2)
}

// GposTable returns the Glyph Positioning table identified with the 'GPOS' tag.
// This method will panic if the font doesn't have this table.
func (font *Font) GposTable() *TableLayout {
return font.tables[TagGpos].(*TableLayout)
}

// GsubTable returns the Glyph Substitution table identified with the 'GSUB' tag.
// This method will panic if the font doesn't have this table.
func (font *Font) GsubTable() *TableLayout {
return font.tables[TagGsub].(*TableLayout)
}

func (font *Font) Table(tag Tag) Table {
return font.tables[tag]
}
Expand Down