提交 f42630ca 编写于 作者: N Nigel Tao

Use the common golang.org/x/exp/shiny/font.Hinting type.

上级 7e2154db
...@@ -23,6 +23,7 @@ import ( ...@@ -23,6 +23,7 @@ import (
"os" "os"
"github.com/golang/freetype" "github.com/golang/freetype"
"golang.org/x/exp/shiny/font"
) )
var ( var (
...@@ -80,7 +81,7 @@ func main() { ...@@ -80,7 +81,7 @@ func main() {
log.Println(err) log.Println(err)
return return
} }
font, err := freetype.ParseFont(fontBytes) f, err := freetype.ParseFont(fontBytes)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return return
...@@ -97,16 +98,16 @@ func main() { ...@@ -97,16 +98,16 @@ func main() {
draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src) draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src)
c := freetype.NewContext() c := freetype.NewContext()
c.SetDPI(*dpi) c.SetDPI(*dpi)
c.SetFont(font) c.SetFont(f)
c.SetFontSize(*size) c.SetFontSize(*size)
c.SetClip(rgba.Bounds()) c.SetClip(rgba.Bounds())
c.SetDst(rgba) c.SetDst(rgba)
c.SetSrc(fg) c.SetSrc(fg)
switch *hinting { switch *hinting {
default: default:
c.SetHinting(freetype.NoHinting) c.SetHinting(font.HintingNone)
case "full": case "full":
c.SetHinting(freetype.FullHinting) c.SetHinting(font.HintingFull)
} }
// Draw the guidelines. // Draw the guidelines.
...@@ -127,13 +128,13 @@ func main() { ...@@ -127,13 +128,13 @@ func main() {
} }
// Save that RGBA image to disk. // Save that RGBA image to disk.
f, err := os.Create("out.png") outFile, err := os.Create("out.png")
if err != nil { if err != nil {
log.Println(err) log.Println(err)
os.Exit(1) os.Exit(1)
} }
defer f.Close() defer outFile.Close()
b := bufio.NewWriter(f) b := bufio.NewWriter(outFile)
err = png.Encode(b, rgba) err = png.Encode(b, rgba)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
......
...@@ -64,13 +64,13 @@ func main() { ...@@ -64,13 +64,13 @@ func main() {
} }
// Save that RGBA image to disk. // Save that RGBA image to disk.
f, err := os.Create("out.png") outFile, err := os.Create("out.png")
if err != nil { if err != nil {
log.Println(err) log.Println(err)
os.Exit(1) os.Exit(1)
} }
defer f.Close() defer outFile.Close()
b := bufio.NewWriter(f) b := bufio.NewWriter(outFile)
err = png.Encode(b, rgba) err = png.Encode(b, rgba)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
......
...@@ -163,13 +163,13 @@ func main() { ...@@ -163,13 +163,13 @@ func main() {
showNodes(rgba, inside) showNodes(rgba, inside)
// Save that RGBA image to disk. // Save that RGBA image to disk.
f, err := os.Create("out.png") outFile, err := os.Create("out.png")
if err != nil { if err != nil {
log.Println(err) log.Println(err)
os.Exit(1) os.Exit(1)
} }
defer f.Close() defer outFile.Close()
b := bufio.NewWriter(f) b := bufio.NewWriter(outFile)
err = png.Encode(b, rgba) err = png.Encode(b, rgba)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
......
...@@ -88,13 +88,13 @@ func main() { ...@@ -88,13 +88,13 @@ func main() {
} }
// Save that RGBA image to disk. // Save that RGBA image to disk.
f, err := os.Create("out.png") outFile, err := os.Create("out.png")
if err != nil { if err != nil {
log.Println(err) log.Println(err)
os.Exit(1) os.Exit(1)
} }
defer f.Close() defer outFile.Close()
b := bufio.NewWriter(f) b := bufio.NewWriter(outFile)
err = png.Encode(b, m) err = png.Encode(b, m)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
......
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
"log" "log"
"github.com/golang/freetype/truetype" "github.com/golang/freetype/truetype"
"golang.org/x/exp/shiny/font"
"golang.org/x/image/math/fixed" "golang.org/x/image/math/fixed"
) )
...@@ -52,21 +53,21 @@ func main() { ...@@ -52,21 +53,21 @@ func main() {
log.Println(err) log.Println(err)
return return
} }
font, err := truetype.Parse(b) f, err := truetype.Parse(b)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return return
} }
fupe := fixed.Int26_6(font.FUnitsPerEm()) fupe := fixed.Int26_6(f.FUnitsPerEm())
printBounds(font.Bounds(fupe)) printBounds(f.Bounds(fupe))
fmt.Printf("FUnitsPerEm:%d\n\n", fupe) fmt.Printf("FUnitsPerEm:%d\n\n", fupe)
c0, c1 := 'A', 'V' c0, c1 := 'A', 'V'
i0 := font.Index(c0) i0 := f.Index(c0)
hm := font.HMetric(fupe, i0) hm := f.HMetric(fupe, i0)
g := truetype.NewGlyphBuf() g := truetype.NewGlyphBuf()
err = g.Load(font, fupe, i0, truetype.NoHinting) err = g.Load(f, fupe, i0, font.HintingNone)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return return
...@@ -74,6 +75,6 @@ func main() { ...@@ -74,6 +75,6 @@ func main() {
fmt.Printf("'%c' glyph\n", c0) fmt.Printf("'%c' glyph\n", c0)
fmt.Printf("AdvanceWidth:%d LeftSideBearing:%d\n", hm.AdvanceWidth, hm.LeftSideBearing) fmt.Printf("AdvanceWidth:%d LeftSideBearing:%d\n", hm.AdvanceWidth, hm.LeftSideBearing)
printGlyph(g) printGlyph(g)
i1 := font.Index(c1) i1 := f.Index(c1)
fmt.Printf("\n'%c', '%c' Kerning:%d\n", c0, c1, font.Kerning(fupe, i0, i1)) fmt.Printf("\n'%c', '%c' Kerning:%d\n", c0, c1, f.Kerning(fupe, i0, i1))
} }
...@@ -15,6 +15,7 @@ import ( ...@@ -15,6 +15,7 @@ import (
"github.com/golang/freetype/raster" "github.com/golang/freetype/raster"
"github.com/golang/freetype/truetype" "github.com/golang/freetype/truetype"
"golang.org/x/exp/shiny/font"
"golang.org/x/image/math/fixed" "golang.org/x/image/math/fixed"
) )
...@@ -55,20 +56,10 @@ func Pt(x, y int) fixed.Point26_6 { ...@@ -55,20 +56,10 @@ func Pt(x, y int) fixed.Point26_6 {
} }
} }
// Hinting is the policy for snapping a glyph's contours to pixel boundaries.
type Hinting int32
const (
// NoHinting means to not perform any hinting.
NoHinting = Hinting(truetype.NoHinting)
// FullHinting means to use the font's hinting instructions.
FullHinting = Hinting(truetype.FullHinting)
)
// A Context holds the state for drawing text in a given font and size. // A Context holds the state for drawing text in a given font and size.
type Context struct { type Context struct {
r *raster.Rasterizer r *raster.Rasterizer
font *truetype.Font f *truetype.Font
glyphBuf *truetype.GlyphBuf glyphBuf *truetype.GlyphBuf
// clip is the clip rectangle for drawing. // clip is the clip rectangle for drawing.
clip image.Rectangle clip image.Rectangle
...@@ -79,7 +70,7 @@ type Context struct { ...@@ -79,7 +70,7 @@ type Context struct {
// 26.6 fixed point units in 1 em. hinting is the hinting policy. // 26.6 fixed point units in 1 em. hinting is the hinting policy.
fontSize, dpi float64 fontSize, dpi float64
scale fixed.Int26_6 scale fixed.Int26_6
hinting Hinting hinting font.Hinting
// cache is the glyph cache. // cache is the glyph cache.
cache [nGlyphs * nXFractions * nYFractions]cacheEntry cache [nGlyphs * nXFractions * nYFractions]cacheEntry
} }
...@@ -170,7 +161,7 @@ func (c *Context) drawContour(ps []truetype.Point, dx, dy fixed.Int26_6) { ...@@ -170,7 +161,7 @@ func (c *Context) drawContour(ps []truetype.Point, dx, dy fixed.Int26_6) {
func (c *Context) rasterize(glyph truetype.Index, fx, fy fixed.Int26_6) ( func (c *Context) rasterize(glyph truetype.Index, fx, fy fixed.Int26_6) (
fixed.Int26_6, *image.Alpha, image.Point, error) { fixed.Int26_6, *image.Alpha, image.Point, error) {
if err := c.glyphBuf.Load(c.font, c.scale, glyph, truetype.Hinting(c.hinting)); err != nil { if err := c.glyphBuf.Load(c.f, c.scale, glyph, c.hinting); err != nil {
return 0, nil, image.Point{}, err return 0, nil, image.Point{}, err
} }
// Calculate the integer-pixel bounds for the glyph. // Calculate the integer-pixel bounds for the glyph.
...@@ -237,15 +228,15 @@ func (c *Context) glyph(glyph truetype.Index, p fixed.Point26_6) ( ...@@ -237,15 +228,15 @@ func (c *Context) glyph(glyph truetype.Index, p fixed.Point26_6) (
// //
// p is a fixed.Point26_6 and can therefore represent sub-pixel positions. // p is a fixed.Point26_6 and can therefore represent sub-pixel positions.
func (c *Context) DrawString(s string, p fixed.Point26_6) (fixed.Point26_6, error) { func (c *Context) DrawString(s string, p fixed.Point26_6) (fixed.Point26_6, error) {
if c.font == nil { if c.f == nil {
return fixed.Point26_6{}, errors.New("freetype: DrawText called with a nil font") return fixed.Point26_6{}, errors.New("freetype: DrawText called with a nil font")
} }
prev, hasPrev := truetype.Index(0), false prev, hasPrev := truetype.Index(0), false
for _, rune := range s { for _, rune := range s {
index := c.font.Index(rune) index := c.f.Index(rune)
if hasPrev { if hasPrev {
kern := fixed.Int26_6(c.font.Kerning(c.scale, prev, index)) kern := fixed.Int26_6(c.f.Kerning(c.scale, prev, index))
if c.hinting != NoHinting { if c.hinting != font.HintingNone {
kern = (kern + 32) &^ 63 kern = (kern + 32) &^ 63
} }
p.X += kern p.X += kern
...@@ -270,11 +261,11 @@ func (c *Context) DrawString(s string, p fixed.Point26_6) (fixed.Point26_6, erro ...@@ -270,11 +261,11 @@ func (c *Context) DrawString(s string, p fixed.Point26_6) (fixed.Point26_6, erro
// resolution and font metrics, and invalidates the glyph cache. // resolution and font metrics, and invalidates the glyph cache.
func (c *Context) recalc() { func (c *Context) recalc() {
c.scale = fixed.Int26_6(c.fontSize * c.dpi * (64.0 / 72.0)) c.scale = fixed.Int26_6(c.fontSize * c.dpi * (64.0 / 72.0))
if c.font == nil { if c.f == nil {
c.r.SetBounds(0, 0) c.r.SetBounds(0, 0)
} else { } else {
// Set the rasterizer's bounds to be big enough to handle the largest glyph. // Set the rasterizer's bounds to be big enough to handle the largest glyph.
b := c.font.Bounds(c.scale) b := c.f.Bounds(c.scale)
xmin := +int(b.XMin) >> 6 xmin := +int(b.XMin) >> 6
ymin := -int(b.YMax) >> 6 ymin := -int(b.YMax) >> 6
xmax := +int(b.XMax+63) >> 6 xmax := +int(b.XMax+63) >> 6
...@@ -296,11 +287,11 @@ func (c *Context) SetDPI(dpi float64) { ...@@ -296,11 +287,11 @@ func (c *Context) SetDPI(dpi float64) {
} }
// SetFont sets the font used to draw text. // SetFont sets the font used to draw text.
func (c *Context) SetFont(font *truetype.Font) { func (c *Context) SetFont(f *truetype.Font) {
if c.font == font { if c.f == f {
return return
} }
c.font = font c.f = f
c.recalc() c.recalc()
} }
...@@ -314,7 +305,7 @@ func (c *Context) SetFontSize(fontSize float64) { ...@@ -314,7 +305,7 @@ func (c *Context) SetFontSize(fontSize float64) {
} }
// SetHinting sets the hinting policy. // SetHinting sets the hinting policy.
func (c *Context) SetHinting(hinting Hinting) { func (c *Context) SetHinting(hinting font.Hinting) {
c.hinting = hinting c.hinting = hinting
for i := range c.cache { for i := range c.cache {
c.cache[i] = cacheEntry{} c.cache[i] = cacheEntry{}
......
...@@ -25,7 +25,7 @@ func BenchmarkDrawString(b *testing.B) { ...@@ -25,7 +25,7 @@ func BenchmarkDrawString(b *testing.B) {
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
font, err := ParseFont(data) f, err := ParseFont(data)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
...@@ -37,7 +37,7 @@ func BenchmarkDrawString(b *testing.B) { ...@@ -37,7 +37,7 @@ func BenchmarkDrawString(b *testing.B) {
c.SetDst(dst) c.SetDst(dst)
c.SetClip(dst.Bounds()) c.SetClip(dst.Bounds())
c.SetSrc(image.Black) c.SetSrc(image.Black)
c.SetFont(font) c.SetFont(f)
var ms runtime.MemStats var ms runtime.MemStats
runtime.ReadMemStats(&ms) runtime.ReadMemStats(&ms)
......
...@@ -6,20 +6,11 @@ ...@@ -6,20 +6,11 @@
package truetype package truetype
import ( import (
"golang.org/x/exp/shiny/font"
"golang.org/x/image/math/fixed" "golang.org/x/image/math/fixed"
) )
// Hinting is the policy for snapping a glyph's contours to pixel boundaries. // TODO: implement VerticalHinting.
type Hinting uint32
const (
// NoHinting means to not perform any hinting.
NoHinting Hinting = iota
// FullHinting means to use the font's hinting instructions.
FullHinting
// TODO: implement VerticalHinting.
)
// A Point is a co-ordinate pair plus whether it is 'on' a contour or an 'off' // A Point is a co-ordinate pair plus whether it is 'on' a contour or an 'off'
// control point. // control point.
...@@ -50,7 +41,7 @@ type GlyphBuf struct { ...@@ -50,7 +41,7 @@ type GlyphBuf struct {
font *Font font *Font
scale fixed.Int26_6 scale fixed.Int26_6
hinting Hinting hinting font.Hinting
hinter hinter hinter hinter
// phantomPoints are the co-ordinates of the synthetic phantom points // phantomPoints are the co-ordinates of the synthetic phantom points
// used for hinting and bounding box calculations. // used for hinting and bounding box calculations.
...@@ -91,7 +82,7 @@ const ( ...@@ -91,7 +82,7 @@ const (
// Load loads a glyph's contours from a Font, overwriting any previously loaded // Load loads a glyph's contours from a Font, overwriting any previously loaded
// contours for this GlyphBuf. scale is the number of 26.6 fixed point units in // contours for this GlyphBuf. scale is the number of 26.6 fixed point units in
// 1 em, i is the glyph index, and h is the hinting policy. // 1 em, i is the glyph index, and h is the hinting policy.
func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h Hinting) error { func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h font.Hinting) error {
g.Point = g.Point[:0] g.Point = g.Point[:0]
g.Unhinted = g.Unhinted[:0] g.Unhinted = g.Unhinted[:0]
g.InFontUnits = g.InFontUnits[:0] g.InFontUnits = g.InFontUnits[:0]
...@@ -103,7 +94,7 @@ func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h Hinting) error ...@@ -103,7 +94,7 @@ func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h Hinting) error
g.phantomPoints = [4]Point{} g.phantomPoints = [4]Point{}
g.metricsSet = false g.metricsSet = false
if h != NoHinting { if h != font.HintingNone {
if err := g.hinter.init(f, scale); err != nil { if err := g.hinter.init(f, scale); err != nil {
return err return err
} }
...@@ -115,7 +106,7 @@ func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h Hinting) error ...@@ -115,7 +106,7 @@ func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h Hinting) error
// and should be cleaned up once we have all the testScaling tests passing, // and should be cleaned up once we have all the testScaling tests passing,
// plus additional tests for Freetype-Go's bounding boxes matching C Freetype's. // plus additional tests for Freetype-Go's bounding boxes matching C Freetype's.
pp1x := g.pp1x pp1x := g.pp1x
if h != NoHinting { if h != font.HintingNone {
pp1x = g.phantomPoints[0].X pp1x = g.phantomPoints[0].X
} }
if pp1x != 0 { if pp1x != 0 {
...@@ -125,7 +116,7 @@ func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h Hinting) error ...@@ -125,7 +116,7 @@ func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h Hinting) error
} }
advanceWidth := g.phantomPoints[1].X - g.phantomPoints[0].X advanceWidth := g.phantomPoints[1].X - g.phantomPoints[0].X
if h != NoHinting { if h != font.HintingNone {
if len(f.hdmx) >= 8 { if len(f.hdmx) >= 8 {
if n := u32(f.hdmx, 4); n > 3+uint32(i) { if n := u32(f.hdmx, 4); n > 3+uint32(i) {
for hdmx := f.hdmx[8:]; uint32(len(hdmx)) >= n; hdmx = hdmx[n:] { for hdmx := f.hdmx[8:]; uint32(len(hdmx)) >= n; hdmx = hdmx[n:] {
...@@ -167,7 +158,7 @@ func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h Hinting) error ...@@ -167,7 +158,7 @@ func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h Hinting) error
} }
} }
// Snap the box to the grid, if hinting is on. // Snap the box to the grid, if hinting is on.
if h != NoHinting { if h != font.HintingNone {
g.B.XMin &^= 63 g.B.XMin &^= 63
g.B.YMin &^= 63 g.B.YMin &^= 63
g.B.XMax += 63 g.B.XMax += 63
...@@ -237,7 +228,7 @@ func (g *GlyphBuf) load(recursion uint32, i Index, useMyMetrics bool) (err error ...@@ -237,7 +228,7 @@ func (g *GlyphBuf) load(recursion uint32, i Index, useMyMetrics bool) (err error
program := g.loadSimple(glyf, ne) program := g.loadSimple(glyf, ne)
g.addPhantomsAndScale(np0, np0, true, true) g.addPhantomsAndScale(np0, np0, true, true)
pp1x = g.Point[len(g.Point)-4].X pp1x = g.Point[len(g.Point)-4].X
if g.hinting != NoHinting { if g.hinting != font.HintingNone {
if len(program) != 0 { if len(program) != 0 {
err := g.hinter.run( err := g.hinter.run(
program, program,
...@@ -443,7 +434,7 @@ func (g *GlyphBuf) loadCompound(recursion uint32, uhm HMetric, i Index, ...@@ -443,7 +434,7 @@ func (g *GlyphBuf) loadCompound(recursion uint32, uhm HMetric, i Index,
} }
instrLen := 0 instrLen := 0
if g.hinting != NoHinting && offset+2 <= len(glyf) { if g.hinting != font.HintingNone && offset+2 <= len(glyf) {
instrLen = int(u16(glyf, offset)) instrLen = int(u16(glyf, offset))
offset += 2 offset += 2
} }
...@@ -491,7 +482,7 @@ func (g *GlyphBuf) addPhantomsAndScale(np0, np1 int, simple, adjust bool) { ...@@ -491,7 +482,7 @@ func (g *GlyphBuf) addPhantomsAndScale(np0, np1 int, simple, adjust bool) {
// Add the four phantom points. // Add the four phantom points.
g.Point = append(g.Point, g.phantomPoints[:]...) g.Point = append(g.Point, g.phantomPoints[:]...)
// Scale the points. // Scale the points.
if simple && g.hinting != NoHinting { if simple && g.hinting != font.HintingNone {
g.InFontUnits = append(g.InFontUnits, g.Point[np1:]...) g.InFontUnits = append(g.InFontUnits, g.Point[np1:]...)
} }
for i := np1; i < len(g.Point); i++ { for i := np1; i < len(g.Point); i++ {
...@@ -499,7 +490,7 @@ func (g *GlyphBuf) addPhantomsAndScale(np0, np1 int, simple, adjust bool) { ...@@ -499,7 +490,7 @@ func (g *GlyphBuf) addPhantomsAndScale(np0, np1 int, simple, adjust bool) {
p.X = g.font.scale(g.scale * p.X) p.X = g.font.scale(g.scale * p.X)
p.Y = g.font.scale(g.scale * p.Y) p.Y = g.font.scale(g.scale * p.Y)
} }
if g.hinting == NoHinting { if g.hinting == font.HintingNone {
return return
} }
// Round the 1st phantom point to the grid, shifting all other points equally. // Round the 1st phantom point to the grid, shifting all other points equally.
......
...@@ -15,55 +15,56 @@ import ( ...@@ -15,55 +15,56 @@ import (
"strings" "strings"
"testing" "testing"
"golang.org/x/exp/shiny/font"
"golang.org/x/image/math/fixed" "golang.org/x/image/math/fixed"
) )
func parseTestdataFont(name string) (font *Font, testdataIsOptional bool, err error) { func parseTestdataFont(name string) (f *Font, testdataIsOptional bool, err error) {
b, err := ioutil.ReadFile(fmt.Sprintf("../testdata/%s.ttf", name)) b, err := ioutil.ReadFile(fmt.Sprintf("../testdata/%s.ttf", name))
if err != nil { if err != nil {
// The "x-foo" fonts are optional tests, as they are not checked // The "x-foo" fonts are optional tests, as they are not checked
// in for copyright or file size reasons. // in for copyright or file size reasons.
return nil, strings.HasPrefix(name, "x-"), fmt.Errorf("%s: ReadFile: %v", name, err) return nil, strings.HasPrefix(name, "x-"), fmt.Errorf("%s: ReadFile: %v", name, err)
} }
font, err = Parse(b) f, err = Parse(b)
if err != nil { if err != nil {
return nil, true, fmt.Errorf("%s: Parse: %v", name, err) return nil, true, fmt.Errorf("%s: Parse: %v", name, err)
} }
return font, false, nil return f, false, nil
} }
// TestParse tests that the luxisr.ttf metrics and glyphs are parsed correctly. // TestParse tests that the luxisr.ttf metrics and glyphs are parsed correctly.
// The numerical values can be manually verified by examining luxisr.ttx. // The numerical values can be manually verified by examining luxisr.ttx.
func TestParse(t *testing.T) { func TestParse(t *testing.T) {
font, _, err := parseTestdataFont("luxisr") f, _, err := parseTestdataFont("luxisr")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if got, want := font.FUnitsPerEm(), int32(2048); got != want { if got, want := f.FUnitsPerEm(), int32(2048); got != want {
t.Errorf("FUnitsPerEm: got %v, want %v", got, want) t.Errorf("FUnitsPerEm: got %v, want %v", got, want)
} }
fupe := fixed.Int26_6(font.FUnitsPerEm()) fupe := fixed.Int26_6(f.FUnitsPerEm())
if got, want := font.Bounds(fupe), (Bounds{-441, -432, 2024, 2033}); got != want { if got, want := f.Bounds(fupe), (Bounds{-441, -432, 2024, 2033}); got != want {
t.Errorf("Bounds: got %v, want %v", got, want) t.Errorf("Bounds: got %v, want %v", got, want)
} }
i0 := font.Index('A') i0 := f.Index('A')
i1 := font.Index('V') i1 := f.Index('V')
if i0 != 36 || i1 != 57 { if i0 != 36 || i1 != 57 {
t.Fatalf("Index: i0, i1 = %d, %d, want 36, 57", i0, i1) t.Fatalf("Index: i0, i1 = %d, %d, want 36, 57", i0, i1)
} }
if got, want := font.HMetric(fupe, i0), (HMetric{1366, 19}); got != want { if got, want := f.HMetric(fupe, i0), (HMetric{1366, 19}); got != want {
t.Errorf("HMetric: got %v, want %v", got, want) t.Errorf("HMetric: got %v, want %v", got, want)
} }
if got, want := font.VMetric(fupe, i0), (VMetric{2465, 553}); got != want { if got, want := f.VMetric(fupe, i0), (VMetric{2465, 553}); got != want {
t.Errorf("VMetric: got %v, want %v", got, want) t.Errorf("VMetric: got %v, want %v", got, want)
} }
if got, want := font.Kerning(fupe, i0, i1), fixed.Int26_6(-144); got != want { if got, want := f.Kerning(fupe, i0, i1), fixed.Int26_6(-144); got != want {
t.Errorf("Kerning: got %v, want %v", got, want) t.Errorf("Kerning: got %v, want %v", got, want)
} }
g := NewGlyphBuf() g := NewGlyphBuf()
err = g.Load(font, fupe, i0, NoHinting) err = g.Load(f, fupe, i0, font.HintingNone)
if err != nil { if err != nil {
t.Fatalf("Load: %v", err) t.Fatalf("Load: %v", err)
} }
...@@ -180,7 +181,7 @@ func TestIndex(t *testing.T) { ...@@ -180,7 +181,7 @@ func TestIndex(t *testing.T) {
}, },
} }
for name, wants := range testCases { for name, wants := range testCases {
font, testdataIsOptional, err := parseTestdataFont(name) f, testdataIsOptional, err := parseTestdataFont(name)
if err != nil { if err != nil {
if testdataIsOptional { if testdataIsOptional {
t.Log(err) t.Log(err)
...@@ -190,7 +191,7 @@ func TestIndex(t *testing.T) { ...@@ -190,7 +191,7 @@ func TestIndex(t *testing.T) {
continue continue
} }
for r, want := range wants { for r, want := range wants {
if got := font.Index(r); got != want { if got := f.Index(r); got != want {
t.Errorf("%s: Index of %q, aka %U: got %d, want %d", name, r, r, got, want) t.Errorf("%s: Index of %q, aka %U: got %d, want %d", name, r, r, got, want)
} }
} }
...@@ -268,9 +269,9 @@ var scalingTestCases = []struct { ...@@ -268,9 +269,9 @@ var scalingTestCases = []struct {
{"x-times-new-roman", 13}, {"x-times-new-roman", 13},
} }
func testScaling(t *testing.T, h Hinting) { func testScaling(t *testing.T, h font.Hinting) {
for _, tc := range scalingTestCases { for _, tc := range scalingTestCases {
font, testdataIsOptional, err := parseTestdataFont(tc.name) f, testdataIsOptional, err := parseTestdataFont(tc.name)
if err != nil { if err != nil {
if testdataIsOptional { if testdataIsOptional {
t.Log(err) t.Log(err)
...@@ -280,19 +281,19 @@ func testScaling(t *testing.T, h Hinting) { ...@@ -280,19 +281,19 @@ func testScaling(t *testing.T, h Hinting) {
continue continue
} }
hintingStr := "sans" hintingStr := "sans"
if h != NoHinting { if h != font.HintingNone {
hintingStr = "with" hintingStr = "with"
} }
f, err := os.Open(fmt.Sprintf( testFile, err := os.Open(fmt.Sprintf(
"../testdata/%s-%dpt-%s-hinting.txt", tc.name, tc.size, hintingStr)) "../testdata/%s-%dpt-%s-hinting.txt", tc.name, tc.size, hintingStr))
if err != nil { if err != nil {
t.Errorf("%s: Open: %v", tc.name, err) t.Errorf("%s: Open: %v", tc.name, err)
continue continue
} }
defer f.Close() defer testFile.Close()
wants := []scalingTestData{} wants := []scalingTestData{}
scanner := bufio.NewScanner(f) scanner := bufio.NewScanner(testFile)
if scanner.Scan() { if scanner.Scan() {
major, minor, patch := 0, 0, 0 major, minor, patch := 0, 0, 0
_, err := fmt.Sscanf(scanner.Text(), "freetype version %d.%d.%d", &major, &minor, &patch) _, err := fmt.Sscanf(scanner.Text(), "freetype version %d.%d.%d", &major, &minor, &patch)
...@@ -320,7 +321,7 @@ func testScaling(t *testing.T, h Hinting) { ...@@ -320,7 +321,7 @@ func testScaling(t *testing.T, h Hinting) {
glyphBuf := NewGlyphBuf() glyphBuf := NewGlyphBuf()
for i, want := range wants { for i, want := range wants {
if err = glyphBuf.Load(font, fixed.I(tc.size), Index(i), h); err != nil { if err = glyphBuf.Load(f, fixed.I(tc.size), Index(i), h); err != nil {
t.Errorf("%s: glyph #%d: Load: %v", tc.name, i, err) t.Errorf("%s: glyph #%d: Load: %v", tc.name, i, err)
continue continue
} }
...@@ -359,10 +360,5 @@ func testScaling(t *testing.T, h Hinting) { ...@@ -359,10 +360,5 @@ func testScaling(t *testing.T, h Hinting) {
} }
} }
func TestScalingSansHinting(t *testing.T) { func TestScalingHintingNone(t *testing.T) { testScaling(t, font.HintingNone) }
testScaling(t, NoHinting) func TestScalingHintingFull(t *testing.T) { testScaling(t, font.HintingFull) }
}
func TestScalingWithHinting(t *testing.T) {
testScaling(t, FullHinting)
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册