diff --git a/freetype.go b/freetype.go index 54d6436..39730de 100644 --- a/freetype.go +++ b/freetype.go @@ -199,9 +199,9 @@ func (c *frContext) glyphAdvance(glyph truetype.Index) (fixed.Int26_6, error) { return c.glyphBuf.AdvanceWidth, nil } -func (c *frContext) glyphBounds(glyph truetype.Index, p fixed.Point26_6) (image.Rectangle, error) { +func (c *frContext) glyphMeasure(glyph truetype.Index, p fixed.Point26_6) (fixed.Int26_6, image.Rectangle, error) { if err := c.glyphBuf.Load(c.f, c.scale, glyph, c.hinting); err != nil { - return image.Rectangle{}, err + return 0, image.Rectangle{}, err } fx := p.X & 0x3f @@ -214,7 +214,12 @@ func (c *frContext) glyphBounds(glyph truetype.Index, p fixed.Point26_6) (image. Min: image.Point{X: xmin, Y: ymin}, Max: image.Point{X: xmax, Y: ymax}} - return bounds, nil + return c.glyphBuf.AdvanceWidth, bounds, nil +} + +func (c *frContext) glyphBounds(glyph truetype.Index, p fixed.Point26_6) (image.Rectangle, error) { + _, bounds, err := c.glyphMeasure(glyph, p) + return bounds, err } const maxInt = int(^uint(0) >> 1) diff --git a/text.go b/text.go index 0bca441..747ad89 100644 --- a/text.go +++ b/text.go @@ -86,7 +86,7 @@ func (cv *Canvas) FillText(str string, x, y float64) { if idx == 0 { idx = fnt.Index(' ') } - bounds, err := frc.glyphBounds(idx, p) + advance, bounds, err := frc.glyphMeasure(idx, p) if err != nil { continue } @@ -108,10 +108,6 @@ func (cv *Canvas) FillText(str string, x, y float64) { break } - advance, err := frc.glyphAdvance(idx) - if err != nil { - continue - } if i == 0 { textOffset.X = bounds.Min.X } @@ -233,7 +229,9 @@ func (cv *Canvas) FillText(str string, x, y float64) { // TextMetrics is the result of a MeasureText call type TextMetrics struct { - Width float64 + Width float64 + ActualBoundingBoxAscent float64 + ActualBoundingBoxDescent float64 } // MeasureText measures the given string using the @@ -248,7 +246,10 @@ func (cv *Canvas) MeasureText(str string) TextMetrics { frc.setFontSize(float64(cv.state.fontSize)) fnt := cv.state.font.font + var p fixed.Point26_6 var x float64 + var minY float64 + var maxY float64 prev, hasPrev := truetype.Index(0), false for _, rn := range str { idx := fnt.Index(rn) @@ -264,14 +265,26 @@ func (cv *Canvas) MeasureText(str string) TextMetrics { } x += float64(kern) / 64 } - advance, err := frc.glyphAdvance(idx) + + advance, glyphBounds, err := frc.glyphMeasure(idx, p) if err != nil { prev = 0 hasPrev = false continue } + if glyphMinY := float64(glyphBounds.Min.Y); glyphMinY < minY { + minY = glyphMinY + } + if glyphMaxY := float64(glyphBounds.Max.Y); glyphMaxY > maxY { + maxY = glyphMaxY + } x += float64(advance) / 64 + p.X += advance } - return TextMetrics{Width: x} + return TextMetrics{ + Width: x, + ActualBoundingBoxAscent: -minY, + ActualBoundingBoxDescent: +maxY, + } }