image/font: expose caret slope
Change-Id: I775224dd3fc7e5b6c2fc5c4a7d3db83bb36d047d Reviewed-on: https://go-review.googlesource.com/136255 Run-TryBot: Elias Naur <elias.naur@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Nigel Tao <nigeltao@golang.org>
This commit is contained in:
parent
e1a1ede689
commit
991ec62608
|
@ -77,11 +77,12 @@ func (f *Face) Kern(r0, r1 rune) fixed.Int26_6 { return 0 }
|
||||||
|
|
||||||
func (f *Face) Metrics() font.Metrics {
|
func (f *Face) Metrics() font.Metrics {
|
||||||
return font.Metrics{
|
return font.Metrics{
|
||||||
Height: fixed.I(f.Height),
|
Height: fixed.I(f.Height),
|
||||||
Ascent: fixed.I(f.Ascent),
|
Ascent: fixed.I(f.Ascent),
|
||||||
Descent: fixed.I(f.Descent),
|
Descent: fixed.I(f.Descent),
|
||||||
XHeight: fixed.I(f.Ascent),
|
XHeight: fixed.I(f.Ascent),
|
||||||
CapHeight: fixed.I(f.Ascent),
|
CapHeight: fixed.I(f.Ascent),
|
||||||
|
CaretSlope: image.Point{X: 0, Y: 1},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
package basicfont
|
package basicfont
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
"golang.org/x/image/font"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMetrics(t *testing.T) {
|
func TestMetrics(t *testing.T) {
|
||||||
want := font.Metrics{Height: 832, Ascent: 704, Descent: 128, XHeight: 704, CapHeight: 704}
|
want := font.Metrics{Height: 832, Ascent: 704, Descent: 128, XHeight: 704, CapHeight: 704, CaretSlope: image.Point{X: 0, Y: 1}}
|
||||||
if got := Face7x13.Metrics(); got != want {
|
if got := Face7x13.Metrics(); got != want {
|
||||||
t.Errorf("Face7x13: Metrics: got %v want %v", got, want)
|
t.Errorf("Face7x13: Metrics: got %v want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,10 @@ type Metrics struct {
|
||||||
// CapHeight is the distance from the top of uppercase letters to the
|
// CapHeight is the distance from the top of uppercase letters to the
|
||||||
// baseline.
|
// baseline.
|
||||||
CapHeight fixed.Int26_6
|
CapHeight fixed.Int26_6
|
||||||
|
|
||||||
|
// CaretSlope is the slope of a caret as a vector with the Y axis pointing up.
|
||||||
|
// The slope {0, 1} is the vertical caret.
|
||||||
|
CaretSlope image.Point
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drawer draws text on a destination image.
|
// Drawer draws text on a destination image.
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package opentype
|
package opentype
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
"golang.org/x/image/font"
|
||||||
|
@ -82,7 +83,8 @@ func TestFaceKern(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFaceMetrics(t *testing.T) {
|
func TestFaceMetrics(t *testing.T) {
|
||||||
want := font.Metrics{Height: 888, Ascent: 726, Descent: 162, XHeight: 407, CapHeight: 555}
|
want := font.Metrics{Height: 888, Ascent: 726, Descent: 162, XHeight: 407, CapHeight: 555,
|
||||||
|
CaretSlope: image.Point{X: 0, Y: 1}}
|
||||||
got := regular.Metrics()
|
got := regular.Metrics()
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Fatalf("metrics failed. got=%#v. want=%#v", got, want)
|
t.Fatalf("metrics failed. got=%#v. want=%#v", got, want)
|
||||||
|
|
|
@ -67,11 +67,12 @@ func (f *subface) Metrics() font.Metrics {
|
||||||
// The same applies to CapHeight, using the uppercase 'H'.
|
// The same applies to CapHeight, using the uppercase 'H'.
|
||||||
hbounds, _, _ := f.GlyphBounds('H')
|
hbounds, _, _ := f.GlyphBounds('H')
|
||||||
return font.Metrics{
|
return font.Metrics{
|
||||||
Height: fixed.I(f.height),
|
Height: fixed.I(f.height),
|
||||||
Ascent: fixed.I(f.ascent),
|
Ascent: fixed.I(f.ascent),
|
||||||
Descent: fixed.I(f.height - f.ascent),
|
Descent: fixed.I(f.height - f.ascent),
|
||||||
XHeight: -xbounds.Min.Y,
|
XHeight: -xbounds.Min.Y,
|
||||||
CapHeight: -hbounds.Min.Y,
|
CapHeight: -hbounds.Min.Y,
|
||||||
|
CaretSlope: image.Point{X: 0, Y: 1},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,11 +154,12 @@ func (f *face) Metrics() font.Metrics {
|
||||||
xbounds, _, _ := f.GlyphBounds('x')
|
xbounds, _, _ := f.GlyphBounds('x')
|
||||||
hbounds, _, _ := f.GlyphBounds('H')
|
hbounds, _, _ := f.GlyphBounds('H')
|
||||||
return font.Metrics{
|
return font.Metrics{
|
||||||
Height: fixed.I(f.height),
|
Height: fixed.I(f.height),
|
||||||
Ascent: fixed.I(f.ascent),
|
Ascent: fixed.I(f.ascent),
|
||||||
Descent: fixed.I(f.height - f.ascent),
|
Descent: fixed.I(f.height - f.ascent),
|
||||||
XHeight: -xbounds.Min.Y,
|
XHeight: -xbounds.Min.Y,
|
||||||
CapHeight: -hbounds.Min.Y,
|
CapHeight: -hbounds.Min.Y,
|
||||||
|
CaretSlope: image.Point{X: 0, Y: 1},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package plan9font
|
package plan9font
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -25,7 +26,8 @@ func TestMetrics(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
want := font.Metrics{Height: 832, Ascent: 704, Descent: 128, XHeight: 704, CapHeight: 704}
|
want := font.Metrics{Height: 832, Ascent: 704, Descent: 128, XHeight: 704, CapHeight: 704,
|
||||||
|
CaretSlope: image.Point{X: 0, Y: 1}}
|
||||||
if got := face.Metrics(); got != want {
|
if got := face.Metrics(); got != want {
|
||||||
t.Errorf("unicode.7x13.font: Metrics: got %v, want %v", got, want)
|
t.Errorf("unicode.7x13.font: Metrics: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ package sfnt // import "golang.org/x/image/font/sfnt"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"image"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
"golang.org/x/image/font"
|
||||||
|
@ -579,6 +580,7 @@ type Font struct {
|
||||||
lineGap int32
|
lineGap int32
|
||||||
numHMetrics int32
|
numHMetrics int32
|
||||||
postTableVersion uint32
|
postTableVersion uint32
|
||||||
|
slope [2]int32
|
||||||
unitsPerEm Units
|
unitsPerEm Units
|
||||||
xHeight int32
|
xHeight int32
|
||||||
}
|
}
|
||||||
|
@ -627,7 +629,7 @@ func (f *Font) initialize(offset int, isDfont bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buf, ascent, descent, lineGap, numHMetrics, err := f.parseHhea(buf, numGlyphs)
|
buf, ascent, descent, lineGap, run, rise, numHMetrics, err := f.parseHhea(buf, numGlyphs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -658,6 +660,7 @@ func (f *Font) initialize(offset int, isDfont bool) error {
|
||||||
f.cached.lineGap = lineGap
|
f.cached.lineGap = lineGap
|
||||||
f.cached.numHMetrics = numHMetrics
|
f.cached.numHMetrics = numHMetrics
|
||||||
f.cached.postTableVersion = postTableVersion
|
f.cached.postTableVersion = postTableVersion
|
||||||
|
f.cached.slope = [2]int32{run, rise}
|
||||||
f.cached.unitsPerEm = unitsPerEm
|
f.cached.unitsPerEm = unitsPerEm
|
||||||
f.cached.xHeight = xHeight
|
f.cached.xHeight = xHeight
|
||||||
|
|
||||||
|
@ -853,32 +856,40 @@ func (f *Font) parseHead(buf []byte) (buf1 []byte, bounds [4]int16, indexToLocFo
|
||||||
return buf, bounds, indexToLocFormat, unitsPerEm, nil
|
return buf, bounds, indexToLocFormat, unitsPerEm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Font) parseHhea(buf []byte, numGlyphs int32) (buf1 []byte, ascent, descent, lineGap, numHMetrics int32, err error) {
|
func (f *Font) parseHhea(buf []byte, numGlyphs int32) (buf1 []byte, ascent, descent, lineGap, run, rise, numHMetrics int32, err error) {
|
||||||
// https://www.microsoft.com/typography/OTSPEC/hhea.htm
|
// https://www.microsoft.com/typography/OTSPEC/hhea.htm
|
||||||
|
|
||||||
if f.hhea.length != 36 {
|
if f.hhea.length != 36 {
|
||||||
return nil, 0, 0, 0, 0, errInvalidHheaTable
|
return nil, 0, 0, 0, 0, 0, 0, errInvalidHheaTable
|
||||||
}
|
}
|
||||||
u, err := f.src.u16(buf, f.hhea, 34)
|
u, err := f.src.u16(buf, f.hhea, 34)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, 0, 0, err
|
return nil, 0, 0, 0, 0, 0, 0, err
|
||||||
}
|
}
|
||||||
if int32(u) > numGlyphs || u == 0 {
|
if int32(u) > numGlyphs || u == 0 {
|
||||||
return nil, 0, 0, 0, 0, errInvalidHheaTable
|
return nil, 0, 0, 0, 0, 0, 0, errInvalidHheaTable
|
||||||
}
|
}
|
||||||
a, err := f.src.u16(buf, f.hhea, 4)
|
a, err := f.src.u16(buf, f.hhea, 4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, 0, 0, err
|
return nil, 0, 0, 0, 0, 0, 0, err
|
||||||
}
|
}
|
||||||
d, err := f.src.u16(buf, f.hhea, 6)
|
d, err := f.src.u16(buf, f.hhea, 6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, 0, 0, err
|
return nil, 0, 0, 0, 0, 0, 0, err
|
||||||
}
|
}
|
||||||
l, err := f.src.u16(buf, f.hhea, 8)
|
l, err := f.src.u16(buf, f.hhea, 8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, 0, 0, err
|
return nil, 0, 0, 0, 0, 0, 0, err
|
||||||
}
|
}
|
||||||
return buf, int32(int16(a)), int32(int16(d)), int32(int16(l)), int32(u), nil
|
ru, err := f.src.u16(buf, f.hhea, 20)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, 0, 0, 0, 0, 0, err
|
||||||
|
}
|
||||||
|
ri, err := f.src.u16(buf, f.hhea, 18)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, 0, 0, 0, 0, 0, err
|
||||||
|
}
|
||||||
|
return buf, int32(int16(a)), int32(int16(d)), int32(int16(l)), int32(int16(ru)), int32(int16(ri)), int32(u), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Font) parseHmtx(buf []byte, numGlyphs, numHMetrics int32) (buf1 []byte, err error) {
|
func (f *Font) parseHmtx(buf []byte, numGlyphs, numHMetrics int32) (buf1 []byte, err error) {
|
||||||
|
@ -1384,11 +1395,12 @@ func (f *Font) Kern(b *Buffer, x0, x1 GlyphIndex, ppem fixed.Int26_6, h font.Hin
|
||||||
// Metrics returns the metrics of this font.
|
// Metrics returns the metrics of this font.
|
||||||
func (f *Font) Metrics(b *Buffer, ppem fixed.Int26_6, h font.Hinting) (font.Metrics, error) {
|
func (f *Font) Metrics(b *Buffer, ppem fixed.Int26_6, h font.Hinting) (font.Metrics, error) {
|
||||||
m := font.Metrics{
|
m := font.Metrics{
|
||||||
Height: scale(fixed.Int26_6(f.cached.ascent-f.cached.descent+f.cached.lineGap)*ppem, f.cached.unitsPerEm),
|
Height: scale(fixed.Int26_6(f.cached.ascent-f.cached.descent+f.cached.lineGap)*ppem, f.cached.unitsPerEm),
|
||||||
Ascent: +scale(fixed.Int26_6(f.cached.ascent)*ppem, f.cached.unitsPerEm),
|
Ascent: +scale(fixed.Int26_6(f.cached.ascent)*ppem, f.cached.unitsPerEm),
|
||||||
Descent: -scale(fixed.Int26_6(f.cached.descent)*ppem, f.cached.unitsPerEm),
|
Descent: -scale(fixed.Int26_6(f.cached.descent)*ppem, f.cached.unitsPerEm),
|
||||||
XHeight: scale(fixed.Int26_6(f.cached.xHeight)*ppem, f.cached.unitsPerEm),
|
XHeight: scale(fixed.Int26_6(f.cached.xHeight)*ppem, f.cached.unitsPerEm),
|
||||||
CapHeight: scale(fixed.Int26_6(f.cached.capHeight)*ppem, f.cached.unitsPerEm),
|
CapHeight: scale(fixed.Int26_6(f.cached.capHeight)*ppem, f.cached.unitsPerEm),
|
||||||
|
CaretSlope: image.Point{X: int(f.cached.slope[0]), Y: int(f.cached.slope[1])},
|
||||||
}
|
}
|
||||||
if h == font.HintingFull {
|
if h == font.HintingFull {
|
||||||
// Quantize up to a whole pixel.
|
// Quantize up to a whole pixel.
|
||||||
|
|
|
@ -7,6 +7,7 @@ package sfnt
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -223,9 +224,11 @@ func TestMetrics(t *testing.T) {
|
||||||
font []byte
|
font []byte
|
||||||
want font.Metrics
|
want font.Metrics
|
||||||
}{
|
}{
|
||||||
"goregular": {goregular.TTF, font.Metrics{Height: 2367, Ascent: 1935, Descent: 432, XHeight: 1086, CapHeight: 1480}},
|
"goregular": {goregular.TTF, font.Metrics{Height: 2367, Ascent: 1935, Descent: 432, XHeight: 1086, CapHeight: 1480,
|
||||||
|
CaretSlope: image.Point{X: 0, Y: 1}}},
|
||||||
// cmapTest.ttf has a non-zero lineGap.
|
// cmapTest.ttf has a non-zero lineGap.
|
||||||
"cmapTest": {cmapFont, font.Metrics{Height: 1549, Ascent: 1365, Descent: 0, XHeight: 800, CapHeight: 800}},
|
"cmapTest": {cmapFont, font.Metrics{Height: 1549, Ascent: 1365, Descent: 0, XHeight: 800, CapHeight: 800,
|
||||||
|
CaretSlope: image.Point{X: 20, Y: 100}}},
|
||||||
}
|
}
|
||||||
var b Buffer
|
var b Buffer
|
||||||
for name, tc := range testCases {
|
for name, tc := range testCases {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user