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 package main
import ( import (
@ -6,6 +11,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"freetype-go.googlecode.com/hg/freetype" "freetype-go.googlecode.com/hg/freetype"
"freetype-go.googlecode.com/hg/freetype/raster"
"image" "image"
"image/png" "image/png"
"io/ioutil" "io/ioutil"
@ -83,12 +89,13 @@ func main() {
} }
rgba := image.NewRGBA(640, 480) rgba := image.NewRGBA(640, 480)
draw.Draw(rgba, draw.Rect(0, 0, rgba.Width(), rgba.Height()), bg, draw.ZP) draw.Draw(rgba, draw.Rect(0, 0, rgba.Width(), rgba.Height()), bg, draw.ZP)
c := freetype.NewRGBAContext(rgba) c := freetype.NewContext()
c.SetColor(fg)
c.SetDPI(*dpi) c.SetDPI(*dpi)
c.SetFont(font) c.SetFont(font)
c.SetFontSize(*size) c.SetFontSize(*size)
c.SetGamma(*gamma) rp := raster.NewRGBAPainter(rgba)
rp.SetColor(fg)
gcp := raster.NewGammaCorrectionPainter(rp, *gamma)
// Draw the guidelines. // Draw the guidelines.
for i := 0; i < 200; i++ { for i := 0; i < 200; i++ {
@ -99,7 +106,7 @@ func main() {
// Draw the text. // Draw the text.
pt := freetype.Pt(10, 10) pt := freetype.Pt(10, 10)
for _, s := range text { for _, s := range text {
err = c.DrawText(pt, s) err = c.DrawText(gcp, pt, s)
if err != nil { if err != nil {
log.Stderr(err) log.Stderr(err)
return return

View File

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