diff --git a/context.go b/context.go index e183a75..7093f6e 100644 --- a/context.go +++ b/context.go @@ -567,7 +567,6 @@ func (dc *Context) DrawRegularPolygon(n int, x, y, r, rotation float64) { } // DrawImage draws the specified image at the specified point. -// Currently, rotation and scaling transforms are not supported. func (dc *Context) DrawImage(im image.Image, x, y int) { dc.DrawImageAnchored(im, x, y, 0, 0) } @@ -615,11 +614,34 @@ func (dc *Context) drawString(im *image.RGBA, s string, x, y float64) { Face: dc.fontFace, Dot: fixp(x, y), } - d.DrawString(s) + // based on Drawer.DrawString() in golang.org/x/image/font/font.go + prevC := rune(-1) + for _, c := range s { + if prevC >= 0 { + d.Dot.X += d.Face.Kern(prevC, c) + } + dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c) + if !ok { + // TODO: is falling back on the U+FFFD glyph the responsibility of + // the Drawer or the Face? + // TODO: set prevC = '\ufffd'? + continue + } + sr := dr.Sub(dr.Min) + transformer := draw.BiLinear + fx, fy := float64(dr.Min.X), float64(dr.Min.Y) + m := dc.matrix.Translate(fx, fy) + s2d := f64.Aff3{m.XX, m.XY, m.X0, m.YX, m.YY, m.Y0} + transformer.Transform(d.Dst, s2d, d.Src, sr, draw.Over, &draw.Options{ + SrcMask: mask, + SrcMaskP: maskp, + }) + d.Dot.X += advance + prevC = c + } } // DrawString draws the specified text at the specified point. -// Currently, rotation and scaling transforms are not supported. func (dc *Context) DrawString(s string, x, y float64) { dc.DrawStringAnchored(s, x, y, 0, 0) } @@ -629,7 +651,6 @@ func (dc *Context) DrawString(s string, x, y float64) { // text. Use ax=0.5, ay=0.5 to center the text at the specified point. func (dc *Context) DrawStringAnchored(s string, x, y, ax, ay float64) { w, h := dc.MeasureString(s) - x, y = dc.TransformPoint(x, y) x -= ax * w y += ay * h if dc.mask == nil { diff --git a/examples/rotated-text.go b/examples/rotated-text.go new file mode 100644 index 0000000..2a3171d --- /dev/null +++ b/examples/rotated-text.go @@ -0,0 +1,30 @@ +package main + +import ( + "github.com/fogleman/gg" + "github.com/golang/freetype/truetype" + "golang.org/x/image/font/gofont/goregular" +) + +func main() { + const S = 400 + dc := gg.NewContext(S, S) + dc.SetRGB(1, 1, 1) + dc.Clear() + dc.SetRGB(0, 0, 0) + font, err := truetype.Parse(goregular.TTF) + if err != nil { + panic("") + } + face := truetype.NewFace(font, &truetype.Options{ + Size: 40, + }) + dc.SetFontFace(face) + text := "Hello, world!" + w, h := dc.MeasureString(text) + dc.Rotate(gg.Radians(10)) + dc.DrawRectangle(100, 180, w, h) + dc.Stroke() + dc.DrawStringAnchored(text, 100, 180, 0.0, 0.0) + dc.SavePNG("out.png") +}