func (ig *ImageGraphics) TextLen(s string, font chart.Font) int { c := freetype.NewContext() c.SetDPI(dpi) c.SetFont(ig.font) fontsize := ig.relFontsizeToPixel(font.Size) c.SetFontSize(fontsize) // really draw it width, err := c.DrawString(s, freetype.Pt(0, 0)) if err != nil { return 10 * len(s) // BUG } return int(width.X+32)>>6 + 1 }
// textBox renders t into a tight fitting image func (ig *ImageGraphics) textBox(t string, font chart.Font, textCol color.Color) image.Image { // Initialize the context. bg := image.NewUniform(color.Alpha{0}) fg := image.NewUniform(textCol) width := ig.TextLen(t, font) size := ig.relFontsizeToPixel(font.Size) c := freetype.NewContext() c.SetDPI(dpi) c.SetFont(ig.font) c.SetFontSize(size) bb := ig.font.Bounds(c.PointToFixed(float64(size))) bbDelta := bb.Max.Sub(bb.Min) height := int(bbDelta.Y+32) >> 6 canvas := image.NewRGBA(image.Rect(0, 0, width, height)) draw.Draw(canvas, canvas.Bounds(), bg, image.ZP, draw.Src) c.SetDst(canvas) c.SetSrc(fg) c.SetClip(canvas.Bounds()) // Draw the text. extent, err := c.DrawString(t, fixed.Point26_6{X: 0, Y: bb.Max.Y}) if err != nil { log.Println(err) return nil } // Ugly heuristic hack: font bounds are pretty high resulting in white top border: Trim. topskip := 1 if size > 15 { topskip = 2 } else if size > 20 { topskip = 3 } return canvas.SubImage(image.Rect(0, topskip, int(extent.X)>>6, height)) }