Freetype-Go: take the RGBAPainter out of a RGBAContext. Instead,

a Context can now take any Painter during DrawText.

R=r
CC=rog, golang-dev
http://codereview.appspot.com/1341041
This commit is contained in:
Nigel Tao 2010-05-27 22:22:49 -07:00
parent 0c4b93bdc3
commit 5836d0e202
2 changed files with 33 additions and 48 deletions

View File

@ -1,3 +1,8 @@
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
// Use of this source code is governed by your choice of either the
// FreeType License or the GNU General Public License version 2,
// both of which can be found in the LICENSE file.
package main
import (
@ -6,6 +11,7 @@ import (
"flag"
"fmt"
"freetype-go.googlecode.com/hg/freetype"
"freetype-go.googlecode.com/hg/freetype/raster"
"image"
"image/png"
"io/ioutil"
@ -83,12 +89,13 @@ func main() {
}
rgba := image.NewRGBA(640, 480)
draw.Draw(rgba, draw.Rect(0, 0, rgba.Width(), rgba.Height()), bg, draw.ZP)
c := freetype.NewRGBAContext(rgba)
c.SetColor(fg)
c := freetype.NewContext()
c.SetDPI(*dpi)
c.SetFont(font)
c.SetFontSize(*size)
c.SetGamma(*gamma)
rp := raster.NewRGBAPainter(rgba)
rp.SetColor(fg)
gcp := raster.NewGammaCorrectionPainter(rp, *gamma)
// Draw the guidelines.
for i := 0; i < 200; i++ {
@ -99,7 +106,7 @@ func main() {
// Draw the text.
pt := freetype.Pt(10, 10)
for _, s := range text {
err = c.DrawText(pt, s)
err = c.DrawText(gcp, pt, s)
if err != nil {
log.Stderr(err)
return

View File

@ -11,7 +11,6 @@ package freetype
import (
"freetype-go.googlecode.com/hg/freetype/raster"
"freetype-go.googlecode.com/hg/freetype/truetype"
"image"
"os"
)
@ -28,12 +27,9 @@ func Pt(x, y int) raster.Point {
return raster.Point{raster.Fixed(x << 8), raster.Fixed(y << 8)}
}
// An RGBAContext holds the state for drawing text from a given font at a
// given size.
type RGBAContext struct {
// A Context holds the state for drawing text in a given font and size.
type Context struct {
r *raster.Rasterizer
rp *raster.RGBAPainter
gp *raster.GammaCorrectionPainter
font *truetype.Font
glyphBuf *truetype.GlyphBuf
fontSize float
@ -59,30 +55,30 @@ type RGBAContext struct {
// FUnitToFixed converts the given number of FUnits into fixed point units,
// rounding to nearest.
func (c *RGBAContext) FUnitToFixed(x int) raster.Fixed {
func (c *Context) FUnitToFixed(x int) raster.Fixed {
return raster.Fixed((x*c.scale + 128) >> 8)
}
// FUnitToPixelRD converts the given number of FUnits into pixel units,
// rounding down.
func (c *RGBAContext) FUnitToPixelRD(x int) int {
func (c *Context) FUnitToPixelRD(x int) int {
return x * c.scale >> 16
}
// FUnitToPixelRU converts the given number of FUnits into pixel units,
// rounding up.
func (c *RGBAContext) FUnitToPixelRU(x int) int {
func (c *Context) FUnitToPixelRU(x int) int {
return (x*c.scale + 0xffff) >> 16
}
// PointToFixed converts the given number of points (as in ``a 12 point font'')
// into fixed point units.
func (c *RGBAContext) PointToFixed(x float) raster.Fixed {
func (c *Context) PointToFixed(x float) raster.Fixed {
return raster.Fixed(x * float(c.dpi) * (256.0 / 72.0))
}
// drawContour draws the given closed contour with the given offset.
func (c *RGBAContext) drawContour(ps []truetype.Point, dx, dy raster.Fixed) {
func (c *Context) drawContour(ps []truetype.Point, dx, dy raster.Fixed) {
if len(ps) == 0 {
return
}
@ -128,18 +124,18 @@ func (c *RGBAContext) drawContour(ps []truetype.Point, dx, dy raster.Fixed) {
}
}
// DrawText draws s at pt. The text is placed so that the top left of the em
// square of the first character of s is equal to pt. The majority of the
// affected pixels will be below and to the right of pt, but some may be above
// or to the left. For example, drawing a string that starts with a 'J' in an
// italic font may affect pixels to the left of pt.
// DrawText draws s at pt using p. The text is placed so that the top left of
// the em square of the first character of s is equal to pt. The majority of
// the affected pixels will be below and to the right of pt, but some may be
// above or to the left. For example, drawing a string that starts with a 'J'
// in an italic font may affect pixels to the left of pt.
// pt is a raster.Point and can therefore represent sub-pixel positions.
func (c *RGBAContext) DrawText(pt raster.Point, s string) (err os.Error) {
func (c *Context) DrawText(p raster.Painter, pt raster.Point, s string) (err os.Error) {
if c.font == nil {
return os.NewError("freetype: DrawText called with a nil font")
}
// pt.X, pt.Y, x, y, dx, dy and x0 are measured in raster.Fixed units,
// c.p.Dx, c.p.Dy, c.xmin and c.ymin are measured in pixels, and
// c.r.Dx, c.r.Dy, c.xmin and c.ymin are measured in pixels, and
// advance is measured in FUnits.
var x, y raster.Fixed
advance, x0 := 0, pt.X
@ -179,7 +175,7 @@ func (c *RGBAContext) DrawText(pt raster.Point, s string) (err os.Error) {
c.drawContour(c.glyphBuf.Point[e0:e], x, y)
e0 = e
}
c.r.Rasterize(c.gp)
c.r.Rasterize(p)
// Advance the cursor.
advance += int(c.font.HMetric(index).AdvanceWidth)
prev, hasPrev = index, true
@ -189,7 +185,7 @@ func (c *RGBAContext) DrawText(pt raster.Point, s string) (err os.Error) {
// recalc recalculates scale and bounds values from the font size, screen
// resolution and font metrics.
func (c *RGBAContext) recalc() {
func (c *Context) recalc() {
c.scale = int((c.fontSize * float(c.dpi) * 256 * 256) / (float(c.upe) * 72))
if c.font == nil {
c.xmin, c.ymin = 0, 0
@ -203,19 +199,14 @@ func (c *RGBAContext) recalc() {
}
}
// SetColor sets the color to draw text.
func (c *RGBAContext) SetColor(color image.Color) {
c.rp.SetColor(color)
}
// SetDPI sets the screen resolution in dots per inch.
func (c *RGBAContext) SetDPI(dpi int) {
func (c *Context) SetDPI(dpi int) {
c.dpi = dpi
c.recalc()
}
// SetFont sets the font used to draw text.
func (c *RGBAContext) SetFont(font *truetype.Font) {
func (c *Context) SetFont(font *truetype.Font) {
c.font = font
c.upe = font.UnitsPerEm()
if c.upe <= 0 {
@ -225,32 +216,19 @@ func (c *RGBAContext) SetFont(font *truetype.Font) {
}
// SetFontSize sets the font size in points (as in ``a 12 point font'').
func (c *RGBAContext) SetFontSize(fontSize float) {
func (c *Context) SetFontSize(fontSize float) {
c.fontSize = fontSize
c.recalc()
}
// SetGamma sets the gamma correction parameter.
func (c *RGBAContext) SetGamma(g float) {
c.gp.SetGamma(g)
}
// SetRGBA sets the image that the RGBAContext draws onto.
func (c *RGBAContext) SetRGBA(m *image.RGBA) {
c.rp.Image = m
}
// NewRGBAContext creates a new RGBAContext.
func NewRGBAContext(m *image.RGBA) *RGBAContext {
c := &RGBAContext{
// NewContext creates a new Context.
func NewContext() *Context {
return &Context{
r: raster.NewRasterizer(0, 0),
rp: raster.NewRGBAPainter(m),
glyphBuf: truetype.NewGlyphBuf(),
fontSize: 12,
dpi: 72,
upe: 2048,
scale: (12 * 72 * 256 * 256) / (2048 * 72),
}
c.gp = raster.NewGammaCorrectionPainter(c.rp, 1.0)
return c
}