mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
parent
d15b12b4e5
commit
cd90f083bc
@ -35,7 +35,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
inconsolataFace = text.NewStdFace(inconsolata.Bold8x16)
|
inconsolataFace = text.NewGoXFace(inconsolata.Bold8x16)
|
||||||
)
|
)
|
||||||
|
|
||||||
// mode is a blend mode with description.
|
// mode is a blend mode with description.
|
||||||
|
@ -35,7 +35,7 @@ const (
|
|||||||
screenHeight = 240
|
screenHeight = 240
|
||||||
)
|
)
|
||||||
|
|
||||||
var fontFace = text.NewStdFace(bitmapfont.Face)
|
var fontFace = text.NewGoXFace(bitmapfont.Face)
|
||||||
|
|
||||||
var keyboardImage *ebiten.Image
|
var keyboardImage *ebiten.Image
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fontFace = text.NewStdFace(bitmapfont.FaceEA)
|
var fontFace = text.NewGoXFace(bitmapfont.FaceEA)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
screenWidth = 640
|
screenWidth = 640
|
||||||
|
@ -25,29 +25,29 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Face = (*StdFace)(nil)
|
var _ Face = (*GoXFace)(nil)
|
||||||
|
|
||||||
type stdFaceGlyphImageCacheKey struct {
|
type goXFaceGlyphImageCacheKey struct {
|
||||||
rune rune
|
rune rune
|
||||||
xoffset fixed.Int26_6
|
xoffset fixed.Int26_6
|
||||||
|
|
||||||
// yoffset is always the same if the rune is the same, so this doesn't have to be a key.
|
// yoffset is always the same if the rune is the same, so this doesn't have to be a key.
|
||||||
}
|
}
|
||||||
|
|
||||||
// StdFace is a Face implementation for a semi-standard font.Face (golang.org/x/image/font).
|
// GoXFace is a Face implementation for a semi-standard font.Face (golang.org/x/image/font).
|
||||||
// StdFace is useful to transit from existing codebase with text v1, or to use some bitmap fonts defined as font.Face.
|
// GoXFace is useful to transit from existing codebase with text v1, or to use some bitmap fonts defined as font.Face.
|
||||||
// StdFace must not be copied by value.
|
// GoXFace must not be copied by value.
|
||||||
type StdFace struct {
|
type GoXFace struct {
|
||||||
f *faceWithCache
|
f *faceWithCache
|
||||||
|
|
||||||
glyphImageCache glyphImageCache[stdFaceGlyphImageCacheKey]
|
glyphImageCache glyphImageCache[goXFaceGlyphImageCacheKey]
|
||||||
|
|
||||||
addr *StdFace
|
addr *GoXFace
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStdFace creates a new StdFace from a semi-standard font.Face.
|
// NewGoXFace creates a new GoXFace from a semi-standard font.Face.
|
||||||
func NewStdFace(face font.Face) *StdFace {
|
func NewGoXFace(face font.Face) *GoXFace {
|
||||||
s := &StdFace{
|
s := &GoXFace{
|
||||||
f: &faceWithCache{
|
f: &faceWithCache{
|
||||||
f: face,
|
f: face,
|
||||||
},
|
},
|
||||||
@ -56,14 +56,14 @@ func NewStdFace(face font.Face) *StdFace {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StdFace) copyCheck() {
|
func (s *GoXFace) copyCheck() {
|
||||||
if s.addr != s {
|
if s.addr != s {
|
||||||
panic("text: illegal use of non-zero StdFace copied by value")
|
panic("text: illegal use of non-zero GoXFace copied by value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metrics implements Face.
|
// Metrics implements Face.
|
||||||
func (s *StdFace) Metrics() Metrics {
|
func (s *GoXFace) Metrics() Metrics {
|
||||||
s.copyCheck()
|
s.copyCheck()
|
||||||
|
|
||||||
m := s.f.Metrics()
|
m := s.f.Metrics()
|
||||||
@ -77,24 +77,24 @@ func (s *StdFace) Metrics() Metrics {
|
|||||||
// UnsafeInternal returns its internal font.Face.
|
// UnsafeInternal returns its internal font.Face.
|
||||||
//
|
//
|
||||||
// This is unsafe since this might make internal cache states out of sync.
|
// This is unsafe since this might make internal cache states out of sync.
|
||||||
func (s *StdFace) UnsafeInternal() font.Face {
|
func (s *GoXFace) UnsafeInternal() font.Face {
|
||||||
s.copyCheck()
|
s.copyCheck()
|
||||||
return s.f.f
|
return s.f.f
|
||||||
}
|
}
|
||||||
|
|
||||||
// advance implements Face.
|
// advance implements Face.
|
||||||
func (s *StdFace) advance(text string) float64 {
|
func (s *GoXFace) advance(text string) float64 {
|
||||||
return fixed26_6ToFloat64(font.MeasureString(s.f, text))
|
return fixed26_6ToFloat64(font.MeasureString(s.f, text))
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasGlyph implements Face.
|
// hasGlyph implements Face.
|
||||||
func (s *StdFace) hasGlyph(r rune) bool {
|
func (s *GoXFace) hasGlyph(r rune) bool {
|
||||||
_, ok := s.f.GlyphAdvance(r)
|
_, ok := s.f.GlyphAdvance(r)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// appendGlyphsForLine implements Face.
|
// appendGlyphsForLine implements Face.
|
||||||
func (s *StdFace) appendGlyphsForLine(glyphs []Glyph, line string, indexOffset int, originX, originY float64) []Glyph {
|
func (s *GoXFace) appendGlyphsForLine(glyphs []Glyph, line string, indexOffset int, originX, originY float64) []Glyph {
|
||||||
s.copyCheck()
|
s.copyCheck()
|
||||||
|
|
||||||
origin := fixed.Point26_6{
|
origin := fixed.Point26_6{
|
||||||
@ -129,8 +129,8 @@ func (s *StdFace) appendGlyphsForLine(glyphs []Glyph, line string, indexOffset i
|
|||||||
return glyphs
|
return glyphs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StdFace) glyphImage(r rune, origin fixed.Point26_6) (*ebiten.Image, int, int, fixed.Int26_6) {
|
func (s *GoXFace) glyphImage(r rune, origin fixed.Point26_6) (*ebiten.Image, int, int, fixed.Int26_6) {
|
||||||
// Assume that StdFace's direction is always horizontal.
|
// Assume that GoXFace's direction is always horizontal.
|
||||||
origin.X = adjustGranularity(origin.X, s)
|
origin.X = adjustGranularity(origin.X, s)
|
||||||
origin.Y &^= ((1 << 6) - 1)
|
origin.Y &^= ((1 << 6) - 1)
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ func (s *StdFace) glyphImage(r rune, origin fixed.Point26_6) (*ebiten.Image, int
|
|||||||
X: (origin.X + b.Min.X) & ((1 << 6) - 1),
|
X: (origin.X + b.Min.X) & ((1 << 6) - 1),
|
||||||
Y: (origin.Y + b.Min.Y) & ((1 << 6) - 1),
|
Y: (origin.Y + b.Min.Y) & ((1 << 6) - 1),
|
||||||
}
|
}
|
||||||
key := stdFaceGlyphImageCacheKey{
|
key := goXFaceGlyphImageCacheKey{
|
||||||
rune: r,
|
rune: r,
|
||||||
xoffset: subpixelOffset.X,
|
xoffset: subpixelOffset.X,
|
||||||
}
|
}
|
||||||
@ -151,7 +151,7 @@ func (s *StdFace) glyphImage(r rune, origin fixed.Point26_6) (*ebiten.Image, int
|
|||||||
return img, imgX, imgY, a
|
return img, imgX, imgY, a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StdFace) glyphImageImpl(r rune, subpixelOffset fixed.Point26_6, glyphBounds fixed.Rectangle26_6) *ebiten.Image {
|
func (s *GoXFace) glyphImageImpl(r rune, subpixelOffset fixed.Point26_6, glyphBounds fixed.Rectangle26_6) *ebiten.Image {
|
||||||
w, h := (glyphBounds.Max.X - glyphBounds.Min.X).Ceil(), (glyphBounds.Max.Y - glyphBounds.Min.Y).Ceil()
|
w, h := (glyphBounds.Max.X - glyphBounds.Min.X).Ceil(), (glyphBounds.Max.Y - glyphBounds.Min.Y).Ceil()
|
||||||
if w == 0 || h == 0 {
|
if w == 0 || h == 0 {
|
||||||
return nil
|
return nil
|
||||||
@ -179,14 +179,14 @@ func (s *StdFace) glyphImageImpl(r rune, subpixelOffset fixed.Point26_6, glyphBo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// direction implements Face.
|
// direction implements Face.
|
||||||
func (s *StdFace) direction() Direction {
|
func (s *GoXFace) direction() Direction {
|
||||||
return DirectionLeftToRight
|
return DirectionLeftToRight
|
||||||
}
|
}
|
||||||
|
|
||||||
// appendVectorPathForLine implements Face.
|
// appendVectorPathForLine implements Face.
|
||||||
func (s *StdFace) appendVectorPathForLine(path *vector.Path, line string, originX, originY float64) {
|
func (s *GoXFace) appendVectorPathForLine(path *vector.Path, line string, originX, originY float64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metrics implements Face.
|
// Metrics implements Face.
|
||||||
func (s *StdFace) private() {
|
func (s *GoXFace) private() {
|
||||||
}
|
}
|
@ -89,7 +89,7 @@ type LayoutOptions struct {
|
|||||||
//
|
//
|
||||||
// For horizontal directions, the start and end depends on the face.
|
// For horizontal directions, the start and end depends on the face.
|
||||||
// If the face is GoTextFace, the start and the end depend on the Direction property.
|
// If the face is GoTextFace, the start and the end depend on the Direction property.
|
||||||
// If the face is StdFace, the start and the end are always left and right respectively.
|
// If the face is GoXFace, the start and the end are always left and right respectively.
|
||||||
//
|
//
|
||||||
// For vertical directions, the start and end are top and bottom respectively.
|
// For vertical directions, the start and end are top and bottom respectively.
|
||||||
//
|
//
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestMultiFace(t *testing.T) {
|
func TestMultiFace(t *testing.T) {
|
||||||
faces := []text.Face{text.NewStdFace(bitmapfont.Face)}
|
faces := []text.Face{text.NewGoXFace(bitmapfont.Face)}
|
||||||
f, err := text.NewMultiFace(faces...)
|
f, err := text.NewMultiFace(faces...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Face is an interface representing a font face.
|
// Face is an interface representing a font face.
|
||||||
// The implementations are only faces defined in this package, like GoTextFace and StdFace.
|
// The implementations are only faces defined in this package, like GoTextFace and GoXFace.
|
||||||
type Face interface {
|
type Face interface {
|
||||||
// Metrics returns the metrics for this Face.
|
// Metrics returns the metrics for this Face.
|
||||||
Metrics() Metrics
|
Metrics() Metrics
|
||||||
@ -59,15 +59,15 @@ type Metrics struct {
|
|||||||
HDescent float64
|
HDescent float64
|
||||||
|
|
||||||
// VLineGap is the recommended amount of horizontal space between two lines of text in pixels.
|
// VLineGap is the recommended amount of horizontal space between two lines of text in pixels.
|
||||||
// If the face is StdFace or the font doesn't support a vertical direction, VLineGap is 0.
|
// If the face is GoXFace or the font doesn't support a vertical direction, VLineGap is 0.
|
||||||
VLineGap float64
|
VLineGap float64
|
||||||
|
|
||||||
// VAscent is the distance in pixels from the top of a line to its baseline for vertical lines.
|
// VAscent is the distance in pixels from the top of a line to its baseline for vertical lines.
|
||||||
// If the face is StdFace or the font doesn't support a vertical direction, VAscent is 0.
|
// If the face is GoXFace or the font doesn't support a vertical direction, VAscent is 0.
|
||||||
VAscent float64
|
VAscent float64
|
||||||
|
|
||||||
// VDescent is the distance in pixels from the top of a line to its baseline for vertical lines.
|
// VDescent is the distance in pixels from the top of a line to its baseline for vertical lines.
|
||||||
// If the face is StdFace or the font doesn't support a vertical direction, VDescent is 0.
|
// If the face is GoXFace or the font doesn't support a vertical direction, VDescent is 0.
|
||||||
VDescent float64
|
VDescent float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ func TestGlyphIndex(t *testing.T) {
|
|||||||
const sampleText = `The quick brown fox jumps
|
const sampleText = `The quick brown fox jumps
|
||||||
over the lazy dog.`
|
over the lazy dog.`
|
||||||
|
|
||||||
f := text.NewStdFace(bitmapfont.Face)
|
f := text.NewGoXFace(bitmapfont.Face)
|
||||||
got := sampleText
|
got := sampleText
|
||||||
for _, g := range text.AppendGlyphs(nil, sampleText, f, nil) {
|
for _, g := range text.AppendGlyphs(nil, sampleText, f, nil) {
|
||||||
got = got[:g.StartIndexInBytes] + strings.Repeat(" ", g.EndIndexInBytes-g.StartIndexInBytes) + got[g.EndIndexInBytes:]
|
got = got[:g.StartIndexInBytes] + strings.Repeat(" ", g.EndIndexInBytes-g.StartIndexInBytes) + got[g.EndIndexInBytes:]
|
||||||
@ -55,7 +55,7 @@ func TestTextColor(t *testing.T) {
|
|||||||
op := &text.DrawOptions{}
|
op := &text.DrawOptions{}
|
||||||
op.GeoM.Translate(0, 0)
|
op.GeoM.Translate(0, 0)
|
||||||
op.ColorScale.ScaleWithColor(clr)
|
op.ColorScale.ScaleWithColor(clr)
|
||||||
text.Draw(img, "Hello", text.NewStdFace(bitmapfont.Face), op)
|
text.Draw(img, "Hello", text.NewGoXFace(bitmapfont.Face), op)
|
||||||
|
|
||||||
w, h := img.Bounds().Dx(), img.Bounds().Dy()
|
w, h := img.Bounds().Dx(), img.Bounds().Dy()
|
||||||
allTransparent := true
|
allTransparent := true
|
||||||
@ -77,12 +77,12 @@ func TestTextColor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const testStdFaceSize = 6
|
const testGoXFaceSize = 6
|
||||||
|
|
||||||
type testStdFace struct{}
|
type testGoXFace struct{}
|
||||||
|
|
||||||
func (f *testStdFace) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
|
func (f *testGoXFace) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
|
||||||
dr = image.Rect(0, 0, testStdFaceSize, testStdFaceSize)
|
dr = image.Rect(0, 0, testGoXFaceSize, testGoXFaceSize)
|
||||||
a := image.NewAlpha(dr)
|
a := image.NewAlpha(dr)
|
||||||
switch r {
|
switch r {
|
||||||
case 'a':
|
case 'a':
|
||||||
@ -99,56 +99,56 @@ func (f *testStdFace) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectangle, ma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mask = a
|
mask = a
|
||||||
advance = fixed.I(testStdFaceSize)
|
advance = fixed.I(testGoXFaceSize)
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *testStdFace) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
|
func (f *testGoXFace) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
|
||||||
bounds = fixed.R(0, 0, testStdFaceSize, testStdFaceSize)
|
bounds = fixed.R(0, 0, testGoXFaceSize, testGoXFaceSize)
|
||||||
advance = fixed.I(testStdFaceSize)
|
advance = fixed.I(testGoXFaceSize)
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *testStdFace) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
func (f *testGoXFace) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
||||||
return fixed.I(testStdFaceSize), true
|
return fixed.I(testGoXFaceSize), true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *testStdFace) Kern(r0, r1 rune) fixed.Int26_6 {
|
func (f *testGoXFace) Kern(r0, r1 rune) fixed.Int26_6 {
|
||||||
if r1 == 'b' {
|
if r1 == 'b' {
|
||||||
return fixed.I(-testStdFaceSize)
|
return fixed.I(-testGoXFaceSize)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *testStdFace) Close() error {
|
func (f *testGoXFace) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *testStdFace) Metrics() font.Metrics {
|
func (f *testGoXFace) Metrics() font.Metrics {
|
||||||
return font.Metrics{
|
return font.Metrics{
|
||||||
Height: fixed.I(testStdFaceSize),
|
Height: fixed.I(testGoXFaceSize),
|
||||||
Ascent: 0,
|
Ascent: 0,
|
||||||
Descent: fixed.I(testStdFaceSize),
|
Descent: fixed.I(testGoXFaceSize),
|
||||||
XHeight: 0,
|
XHeight: 0,
|
||||||
CapHeight: fixed.I(testStdFaceSize),
|
CapHeight: fixed.I(testGoXFaceSize),
|
||||||
CaretSlope: image.Pt(0, 1),
|
CaretSlope: image.Pt(0, 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue #1378
|
// Issue #1378
|
||||||
func TestNegativeKern(t *testing.T) {
|
func TestNegativeKern(t *testing.T) {
|
||||||
f := text.NewStdFace(&testStdFace{})
|
f := text.NewGoXFace(&testGoXFace{})
|
||||||
dst := ebiten.NewImage(testStdFaceSize*2, testStdFaceSize)
|
dst := ebiten.NewImage(testGoXFaceSize*2, testGoXFaceSize)
|
||||||
|
|
||||||
// With testStdFace, 'b' is rendered at the previous position as 0xff.
|
// With testGoXFace, 'b' is rendered at the previous position as 0xff.
|
||||||
// 'a' is rendered at the current position as 0x80.
|
// 'a' is rendered at the current position as 0x80.
|
||||||
op := &text.DrawOptions{}
|
op := &text.DrawOptions{}
|
||||||
op.GeoM.Translate(0, 0)
|
op.GeoM.Translate(0, 0)
|
||||||
text.Draw(dst, "ab", f, op)
|
text.Draw(dst, "ab", f, op)
|
||||||
for j := 0; j < testStdFaceSize; j++ {
|
for j := 0; j < testGoXFaceSize; j++ {
|
||||||
for i := 0; i < testStdFaceSize; i++ {
|
for i := 0; i < testGoXFaceSize; i++ {
|
||||||
got := dst.At(i, j)
|
got := dst.At(i, j)
|
||||||
want := color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}
|
want := color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}
|
||||||
if got != want {
|
if got != want {
|
||||||
@ -159,10 +159,10 @@ func TestNegativeKern(t *testing.T) {
|
|||||||
|
|
||||||
// The glyph 'a' should be treated correctly.
|
// The glyph 'a' should be treated correctly.
|
||||||
op = &text.DrawOptions{}
|
op = &text.DrawOptions{}
|
||||||
op.GeoM.Translate(testStdFaceSize, 0)
|
op.GeoM.Translate(testGoXFaceSize, 0)
|
||||||
text.Draw(dst, "a", f, op)
|
text.Draw(dst, "a", f, op)
|
||||||
for j := 0; j < testStdFaceSize; j++ {
|
for j := 0; j < testGoXFaceSize; j++ {
|
||||||
for i := testStdFaceSize; i < testStdFaceSize*2; i++ {
|
for i := testGoXFaceSize; i < testGoXFaceSize*2; i++ {
|
||||||
got := dst.At(i, j)
|
got := dst.At(i, j)
|
||||||
want := color.RGBA{R: 0x80, G: 0x80, B: 0x80, A: 0x80}
|
want := color.RGBA{R: 0x80, G: 0x80, B: 0x80, A: 0x80}
|
||||||
if got != want {
|
if got != want {
|
||||||
@ -172,12 +172,12 @@ func TestNegativeKern(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type unhashableStdFace func()
|
type unhashableGoXFace func()
|
||||||
|
|
||||||
const unhashableStdFaceSize = 10
|
const unhashableGoXFaceSize = 10
|
||||||
|
|
||||||
func (u *unhashableStdFace) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
|
func (u *unhashableGoXFace) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
|
||||||
dr = image.Rect(0, 0, unhashableStdFaceSize, unhashableStdFaceSize)
|
dr = image.Rect(0, 0, unhashableGoXFaceSize, unhashableGoXFaceSize)
|
||||||
a := image.NewAlpha(dr)
|
a := image.NewAlpha(dr)
|
||||||
for j := dr.Min.Y; j < dr.Max.Y; j++ {
|
for j := dr.Min.Y; j < dr.Max.Y; j++ {
|
||||||
for i := dr.Min.X; i < dr.Max.X; i++ {
|
for i := dr.Min.X; i < dr.Max.X; i++ {
|
||||||
@ -185,53 +185,53 @@ func (u *unhashableStdFace) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectang
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mask = a
|
mask = a
|
||||||
advance = fixed.I(unhashableStdFaceSize)
|
advance = fixed.I(unhashableGoXFaceSize)
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *unhashableStdFace) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
|
func (u *unhashableGoXFace) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
|
||||||
bounds = fixed.R(0, 0, unhashableStdFaceSize, unhashableStdFaceSize)
|
bounds = fixed.R(0, 0, unhashableGoXFaceSize, unhashableGoXFaceSize)
|
||||||
advance = fixed.I(unhashableStdFaceSize)
|
advance = fixed.I(unhashableGoXFaceSize)
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *unhashableStdFace) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
func (u *unhashableGoXFace) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
||||||
return fixed.I(unhashableStdFaceSize), true
|
return fixed.I(unhashableGoXFaceSize), true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *unhashableStdFace) Kern(r0, r1 rune) fixed.Int26_6 {
|
func (u *unhashableGoXFace) Kern(r0, r1 rune) fixed.Int26_6 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *unhashableStdFace) Close() error {
|
func (u *unhashableGoXFace) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *unhashableStdFace) Metrics() font.Metrics {
|
func (u *unhashableGoXFace) Metrics() font.Metrics {
|
||||||
return font.Metrics{
|
return font.Metrics{
|
||||||
Height: fixed.I(unhashableStdFaceSize),
|
Height: fixed.I(unhashableGoXFaceSize),
|
||||||
Ascent: 0,
|
Ascent: 0,
|
||||||
Descent: fixed.I(unhashableStdFaceSize),
|
Descent: fixed.I(unhashableGoXFaceSize),
|
||||||
XHeight: 0,
|
XHeight: 0,
|
||||||
CapHeight: fixed.I(unhashableStdFaceSize),
|
CapHeight: fixed.I(unhashableGoXFaceSize),
|
||||||
CaretSlope: image.Pt(0, 1),
|
CaretSlope: image.Pt(0, 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue #2669
|
// Issue #2669
|
||||||
func TestUnhashableFace(t *testing.T) {
|
func TestUnhashableFace(t *testing.T) {
|
||||||
var face unhashableStdFace
|
var face unhashableGoXFace
|
||||||
f := text.NewStdFace(&face)
|
f := text.NewGoXFace(&face)
|
||||||
dst := ebiten.NewImage(unhashableStdFaceSize*2, unhashableStdFaceSize*2)
|
dst := ebiten.NewImage(unhashableGoXFaceSize*2, unhashableGoXFaceSize*2)
|
||||||
text.Draw(dst, "a", f, nil)
|
text.Draw(dst, "a", f, nil)
|
||||||
|
|
||||||
for j := 0; j < unhashableStdFaceSize*2; j++ {
|
for j := 0; j < unhashableGoXFaceSize*2; j++ {
|
||||||
for i := 0; i < unhashableStdFaceSize*2; i++ {
|
for i := 0; i < unhashableGoXFaceSize*2; i++ {
|
||||||
got := dst.At(i, j)
|
got := dst.At(i, j)
|
||||||
var want color.RGBA
|
var want color.RGBA
|
||||||
if i < unhashableStdFaceSize && j < unhashableStdFaceSize {
|
if i < unhashableGoXFaceSize && j < unhashableGoXFaceSize {
|
||||||
want = color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}
|
want = color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}
|
||||||
}
|
}
|
||||||
if got != want {
|
if got != want {
|
||||||
|
Loading…
Reference in New Issue
Block a user