Skip to content

Commit

Permalink
font: introduce Cache.AddFrom convenience method
Browse files Browse the repository at this point in the history
Update gonum#702.
  • Loading branch information
sbinet committed Jun 24, 2021
1 parent bd0e370 commit 0c88fa1
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 0 deletions.
147 changes: 147 additions & 0 deletions font/face_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Copyright ©2021 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package font

import (
"testing"

"github.com/go-fonts/latin-modern/lmmono10italic"
"github.com/go-fonts/liberation/liberationmonobold"
"github.com/go-fonts/liberation/liberationmonobolditalic"
"github.com/go-fonts/liberation/liberationmonoitalic"
"github.com/go-fonts/liberation/liberationmonoregular"
"github.com/go-fonts/liberation/liberationsansbold"
"github.com/go-fonts/liberation/liberationsansbolditalic"
"github.com/go-fonts/liberation/liberationsansitalic"
"github.com/go-fonts/liberation/liberationsansregular"
"github.com/go-fonts/liberation/liberationserifbold"
"github.com/go-fonts/liberation/liberationserifbolditalic"
"github.com/go-fonts/liberation/liberationserifitalic"
"github.com/go-fonts/liberation/liberationserifregular"
xfnt "golang.org/x/image/font"
)

func TestFaceFrom(t *testing.T) {
for _, tc := range []struct {
raw []byte
want Font
}{
{
raw: lmmono10italic.TTF,
want: Font{
Typeface: "Latin Modern Mono",
Style: xfnt.StyleItalic,
Weight: xfnt.WeightNormal,
},
},
{
raw: liberationmonobold.TTF,
want: Font{
Typeface: "Liberation Mono",
Style: xfnt.StyleNormal,
Weight: xfnt.WeightBold,
},
},
{
raw: liberationmonobolditalic.TTF,
want: Font{
Typeface: "Liberation Mono",
Style: xfnt.StyleItalic,
Weight: xfnt.WeightBold,
},
},
{
raw: liberationmonoitalic.TTF,
want: Font{
Typeface: "Liberation Mono",
Style: xfnt.StyleItalic,
Weight: xfnt.WeightNormal,
},
},
{
raw: liberationmonoregular.TTF,
want: Font{
Typeface: "Liberation Mono",
Style: xfnt.StyleNormal,
Weight: xfnt.WeightNormal,
},
},
{
raw: liberationsansbold.TTF,
want: Font{
Typeface: "Liberation Sans",
Style: xfnt.StyleNormal,
Weight: xfnt.WeightBold,
},
},
{
raw: liberationsansbolditalic.TTF,
want: Font{
Typeface: "Liberation Sans",
Style: xfnt.StyleItalic,
Weight: xfnt.WeightBold,
},
},
{
raw: liberationsansitalic.TTF,
want: Font{
Typeface: "Liberation Sans",
Style: xfnt.StyleItalic,
Weight: xfnt.WeightNormal,
},
},
{
raw: liberationsansregular.TTF,
want: Font{
Typeface: "Liberation Sans",
Style: xfnt.StyleNormal,
Weight: xfnt.WeightNormal,
},
},
{
raw: liberationserifbold.TTF,
want: Font{
Typeface: "Liberation Serif",
Style: xfnt.StyleNormal,
Weight: xfnt.WeightBold,
},
},
{
raw: liberationserifbolditalic.TTF,
want: Font{
Typeface: "Liberation Serif",
Style: xfnt.StyleItalic,
Weight: xfnt.WeightBold,
},
},
{
raw: liberationserifitalic.TTF,
want: Font{
Typeface: "Liberation Serif",
Style: xfnt.StyleItalic,
Weight: xfnt.WeightNormal,
},
},
{
raw: liberationserifregular.TTF,
want: Font{
Typeface: "Liberation Serif",
Style: xfnt.StyleNormal,
Weight: xfnt.WeightNormal,
},
},
} {
face, err := faceFrom(tc.raw)
if err != nil {
t.Errorf("could not create Face: %+v", err)
continue
}
got := face.Font
if got != tc.want {
t.Errorf("invalid font face:\ngot= %+v\nwant=%+v", got, tc.want)
continue
}
}
}
79 changes: 79 additions & 0 deletions font/font.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package font
import (
"errors"
"fmt"
"strings"
"sync"

"golang.org/x/image/font"
Expand Down Expand Up @@ -94,6 +95,34 @@ type Face struct {
Face *opentype.Font
}

func faceFrom(raw []byte) (Face, error) {
var face Face
otf, err := opentype.Parse(raw)
if err != nil {
return face, fmt.Errorf("font: could not parse font data: %w", err)
}

var buf sfnt.Buffer
name, err := otf.Name(&buf, sfnt.NameIDFamily)
if err != nil {
return face, fmt.Errorf("font: could not retrieve font name: %w", err)
}

full, err := otf.Name(&buf, sfnt.NameIDFull)
if err != nil {
return face, fmt.Errorf("font: could not retrieve font fullname: %w", err)
}

face.Font = Font{
Typeface: Typeface(name),
Style: styleFrom(full),
Weight: weightFrom(full),
}
face.Face = otf

return face, nil
}

// Name returns a fully qualified name for the given font.
func (f *Face) Name() string {
return f.Font.Name()
Expand Down Expand Up @@ -235,6 +264,17 @@ func (c *Cache) Add(coll Collection) {
}
}

// AddFrom adds a font to the font cache.
func (c *Cache) AddFrom(raw []byte) error {
face, err := faceFrom(raw)
if err != nil {
return fmt.Errorf("font: could not load font/face: %w", err)
}
c.Add(Collection([]Face{face}))

return nil
}

// Lookup returns the font Face corresponding to the provided Font descriptor,
// with the provided font size set.
//
Expand Down Expand Up @@ -319,6 +359,33 @@ func weightName(w font.Weight) string {
return fmt.Sprintf("weight(%d)", w)
}

func weightFrom(v string) font.Weight {
v = strings.ToLower(v)
switch {
case strings.Contains(v, "thin"):
return font.WeightThin
case strings.Contains(v, "extralight"):
return font.WeightExtraLight
case strings.Contains(v, "light"):
return font.WeightLight
case strings.Contains(v, "regular"):
return font.WeightNormal
case strings.Contains(v, "medium"):
return font.WeightMedium
case strings.Contains(v, "extrabold"):
return font.WeightExtraBold
case strings.Contains(v, "semibold"):
return font.WeightSemiBold
case strings.Contains(v, "bold"):
return font.WeightBold
case strings.Contains(v, "black"):
return font.WeightBlack

default:
return font.WeightNormal
}
}

func styleName(sty font.Style) string {
switch sty {
case font.StyleNormal:
Expand All @@ -330,3 +397,15 @@ func styleName(sty font.Style) string {
}
return fmt.Sprintf("style(%d)", sty)
}

func styleFrom(v string) font.Style {
v = strings.ToLower(v)
switch {
case strings.Contains(v, "italic"):
return font.StyleItalic
case strings.Contains(v, "oblique"):
return font.StyleOblique
default:
return font.StyleNormal
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
gioui.org v0.0.0-20210308172011-57750fc8a0a6
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af
github.com/fogleman/gg v1.3.0
github.com/go-fonts/latin-modern v0.2.0
github.com/go-fonts/liberation v0.1.1
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07
github.com/go-pdf/fpdf v0.4.0
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/go-fonts/dejavu v0.1.0 h1:JSajPXURYqpr+Cu8U9bt8K+XcACIHWqWrvWCKyeFmVQ=
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
github.com/go-fonts/latin-modern v0.2.0 h1:5/Tv1Ek/QCr20C6ZOz15vw3g7GELYL98KWr8Hgo+3vk=
github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
github.com/go-fonts/liberation v0.1.1 h1:wBrPaMkrXFBW3qXpXAjiKljdVUMxn9bX2ia3XjPHoik=
github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
Expand Down

0 comments on commit 0c88fa1

Please sign in to comment.