示例#1
0
// MeasureString returns the width and height of the string in s, in terms of
// raster.Fix32 units.
//
// BUG(burntsushi): I don't think negative x-coordinates are handled at all, so
// that the bounding box could be smaller than what it actually is. (i.e., the
// first letter is an italic 'J'.)
func (c *Context) MeasureString(s string) (raster.Fix32, raster.Fix32, error) {
	if c.font == nil {
		return 0, 0, errors.New("freetype: DrawText called with a nil font")
	}

	var width, height, heightMax raster.Fix32
	oneLine := c.PointToFix32(c.fontSize) & 0xff
	height = c.PointToFix32(c.fontSize)
	prev, hasPrev := truetype.Index(0), false
	for _, rune := range s {
		index := c.font.Index(rune)
		if hasPrev {
			width += raster.Fix32(c.font.Kerning(c.scale, prev, index)) << 2
		}

		if err := c.glyphBuf.Load(c.font, c.scale, index, truetype.Hinting(c.hinting)); err != nil {
			return 0, 0, err
		}
		ymax := oneLine - raster.Fix32(c.glyphBuf.B.YMin<<2) + 0xff
		heightMax = max(heightMax, ymax)

		width += raster.Fix32(c.font.HMetric(c.scale, index).AdvanceWidth) << 2
		prev, hasPrev = index, true
	}

	if heightMax > 0 {
		height += heightMax
	}
	return width, height, nil
}
示例#2
0
// DrawString draws s at p and returns p advanced by the text extent. The text
// is placed so that the left edge of the em square of the first character of s
// and the baseline intersect at p. The majority of the affected pixels will be
// above and to the right of the point, but some may be below or to the left.
// For example, drawing a string that starts with a 'J' in an italic font may
// affect pixels below and left of the point.
// p is a raster.Point and can therefore represent sub-pixel positions.
func (c *Context) DrawString(s string, p raster.Point) (raster.Point, error) {
	if c.font == nil {
		return raster.Point{}, errors.New("freetype: DrawText called with a nil font")
	}
	prev, hasPrev := truetype.Index(0), false
	for _, rune := range s {
		index := c.font.Index(rune)
		if hasPrev {
			kern := raster.Fix32(c.font.Kerning(c.scale, prev, index)) << 2
			if c.hinting != NoHinting {
				kern = (kern + 128) &^ 255
			}
			p.X += kern
		}
		advanceWidth, mask, offset, err := c.glyph(index, p)
		if err != nil {
			return raster.Point{}, err
		}
		p.X += advanceWidth
		glyphRect := mask.Bounds().Add(offset)
		dr := c.clip.Intersect(glyphRect)
		if !dr.Empty() {
			mp := image.Point{0, dr.Min.Y - glyphRect.Min.Y}
			draw.DrawMask(c.dst, dr, c.src, image.ZP, mask, mp, draw.Over)
		}
		prev, hasPrev = index, true
	}
	return p, nil
}