diff --git a/examples/texti18n/main.go b/examples/texti18n/main.go index 3eb2b5dc0..336a419c4 100644 --- a/examples/texti18n/main.go +++ b/examples/texti18n/main.go @@ -122,7 +122,7 @@ func (g *Game) Update() error { } func (g *Game) Draw(screen *ebiten.Image) { - ebitenutil.DebugPrint(screen, "Press O to show/hide origins") + ebitenutil.DebugPrint(screen, "Press O to show/hide origins.\nRed points are the original origin positions.\nThe green points are the origin positions after applying the offset.") gray := color.RGBA{0x80, 0x80, 0x80, 0xff} @@ -134,7 +134,7 @@ func (g *Game) Draw(screen *ebiten.Image) { Size: 24, Language: language.Arabic, } - x, y := screenWidth-20, 40 + x, y := screenWidth-20, 50 w, h := text.Measure(arabicText, f, 0) // The left upper point is not x but x-w, since the text runs in the rigth-to-left direction. vector.DrawFilledRect(screen, float32(x)-float32(w), float32(y), float32(w), float32(h), gray, false) @@ -145,6 +145,7 @@ func (g *Game) Draw(screen *ebiten.Image) { if g.showOrigins { op := &text.LayoutOptions{} for _, g := range text.AppendGlyphs(nil, arabicText, f, op) { + vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX+g.OriginOffsetX), float32(y)+float32(g.OriginY+g.OriginOffsetY), 2, color.RGBA{0, 0xff, 0, 0xff}, true) vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX), float32(y)+float32(g.OriginY), 2, color.RGBA{0xff, 0, 0, 0xff}, true) } } @@ -156,7 +157,7 @@ func (g *Game) Draw(screen *ebiten.Image) { Size: 24, Language: language.Hindi, } - x, y := 20, 100 + x, y := 20, 110 w, h := text.Measure(hindiText, f, 0) vector.DrawFilledRect(screen, float32(x), float32(y), float32(w), float32(h), gray, false) op := &text.DrawOptions{} @@ -166,6 +167,7 @@ func (g *Game) Draw(screen *ebiten.Image) { if g.showOrigins { op := &text.LayoutOptions{} for _, g := range text.AppendGlyphs(nil, hindiText, f, op) { + vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX+g.OriginOffsetX), float32(y)+float32(g.OriginY+g.OriginOffsetY), 2, color.RGBA{0, 0xff, 0, 0xff}, true) vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX), float32(y)+float32(g.OriginY), 2, color.RGBA{0xff, 0, 0, 0xff}, true) } } @@ -177,7 +179,7 @@ func (g *Game) Draw(screen *ebiten.Image) { Size: 24, Language: language.Burmese, } - x, y := 20, 160 + x, y := 20, 170 w, h := text.Measure(myanmarText, f, 0) vector.DrawFilledRect(screen, float32(x), float32(y), float32(w), float32(h), gray, false) op := &text.DrawOptions{} @@ -187,6 +189,7 @@ func (g *Game) Draw(screen *ebiten.Image) { if g.showOrigins { op := &text.LayoutOptions{} for _, g := range text.AppendGlyphs(nil, myanmarText, f, op) { + vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX+g.OriginOffsetX), float32(y)+float32(g.OriginY+g.OriginOffsetY), 2, color.RGBA{0, 0xff, 0, 0xff}, true) vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX), float32(y)+float32(g.OriginY), 2, color.RGBA{0xff, 0, 0, 0xff}, true) } } @@ -198,7 +201,7 @@ func (g *Game) Draw(screen *ebiten.Image) { Size: 24, Language: language.Thai, } - x, y := 20, 220 + x, y := 20, 230 w, h := text.Measure(thaiText, f, 0) vector.DrawFilledRect(screen, float32(x), float32(y), float32(w), float32(h), gray, false) op := &text.DrawOptions{} @@ -208,6 +211,7 @@ func (g *Game) Draw(screen *ebiten.Image) { if g.showOrigins { op := &text.LayoutOptions{} for _, g := range text.AppendGlyphs(nil, thaiText, f, op) { + vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX+g.OriginOffsetX), float32(y)+float32(g.OriginY+g.OriginOffsetY), 2, color.RGBA{0, 0xff, 0, 0xff}, true) vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX), float32(y)+float32(g.OriginY), 2, color.RGBA{0xff, 0, 0, 0xff}, true) } } @@ -223,7 +227,7 @@ func (g *Game) Draw(screen *ebiten.Image) { Script: language.MustParseScript("Mong"), } const lineSpacing = 48 - x, y := 20, 280 + x, y := 20, 290 w, h := text.Measure(mongolianText, f, lineSpacing) vector.DrawFilledRect(screen, float32(x), float32(y), float32(w), float32(h), gray, false) op := &text.DrawOptions{} @@ -235,6 +239,7 @@ func (g *Game) Draw(screen *ebiten.Image) { op := &text.LayoutOptions{} op.LineSpacing = lineSpacing for _, g := range text.AppendGlyphs(nil, mongolianText, f, op) { + vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX+g.OriginOffsetX), float32(y)+float32(g.OriginY+g.OriginOffsetY), 2, color.RGBA{0, 0xff, 0, 0xff}, true) vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX), float32(y)+float32(g.OriginY), 2, color.RGBA{0xff, 0, 0, 0xff}, true) } } @@ -248,7 +253,7 @@ func (g *Game) Draw(screen *ebiten.Image) { Language: language.Japanese, } const lineSpacing = 48 - x, y := screenWidth-20, 280 + x, y := screenWidth-20, 290 w, h := text.Measure(japaneseText, f, lineSpacing) // The left upper point is not x but x-w, since the text runs in the rigth-to-left direction as the secondary direction. vector.DrawFilledRect(screen, float32(x)-float32(w), float32(y), float32(w), float32(h), gray, false) @@ -262,6 +267,7 @@ func (g *Game) Draw(screen *ebiten.Image) { op.LineSpacing = lineSpacing for _, g := range text.AppendGlyphs(nil, japaneseText, f, op) { vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX), float32(y)+float32(g.OriginY), 2, color.RGBA{0xff, 0, 0, 0xff}, true) + vector.DrawFilledCircle(screen, float32(x)+float32(g.OriginX+g.OriginOffsetX), float32(y)+float32(g.OriginY+g.OriginOffsetY), 2, color.RGBA{0, 0xff, 0, 0xff}, true) } } } diff --git a/text/v2/gotext.go b/text/v2/gotext.go index 527bd0810..227cc92b0 100644 --- a/text/v2/gotext.go +++ b/text/v2/gotext.go @@ -318,8 +318,10 @@ func (g *GoTextFace) appendGlyphsForLine(glyphs []Glyph, line string, indexOffse Image: img, X: float64(imgX), Y: float64(imgY), - OriginX: fixed26_6ToFloat64(o.X), - OriginY: fixed26_6ToFloat64(o.Y), + OriginX: fixed26_6ToFloat64(origin.X), + OriginY: fixed26_6ToFloat64(origin.Y), + OriginOffsetX: fixed26_6ToFloat64(glyph.shapingGlyph.XOffset), + OriginOffsetY: fixed26_6ToFloat64(-glyph.shapingGlyph.YOffset), }) origin = origin.Add(fixed.Point26_6{ X: glyph.shapingGlyph.XAdvance, diff --git a/text/v2/gox.go b/text/v2/gox.go index d101d2dc7..13914db94 100644 --- a/text/v2/gox.go +++ b/text/v2/gox.go @@ -126,6 +126,8 @@ func (s *GoXFace) appendGlyphsForLine(glyphs []Glyph, line string, indexOffset i Y: float64(imgY), OriginX: fixed26_6ToFloat64(origin.X), OriginY: fixed26_6ToFloat64(origin.Y), + OriginOffsetX: 0, + OriginOffsetY: 0, }) origin.X += a prevR = r diff --git a/text/v2/text.go b/text/v2/text.go index 5e4171ee0..302a20d39 100644 --- a/text/v2/text.go +++ b/text/v2/text.go @@ -147,6 +147,14 @@ type Glyph struct { // OriginY is the Y position of the origin of this glyph. OriginY float64 + + // OriginOffsetX is the adjustment value to the X position of the origin of this glyph. + // OriginOffsetX is usually 0, but can be non-zero for some special glyphs or glyphs in the vertical text layout. + OriginOffsetX float64 + + // OriginOffsetY is the adjustment value to the Y position of the origin of this glyph. + // OriginOffsetY is usually 0, but can be non-zero for some special glyphs or glyphs in the vertical text layout. + OriginOffsetY float64 } // Advance returns the advanced distance from the origin position when rendering the given text with the given face.