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:
parent
0c4b93bdc3
commit
5836d0e202
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue