Freetype-Go: gamma is now a float instead of a float64.

R=r
CC=golang-dev
http://codereview.appspot.com/1236042
This commit is contained in:
Nigel Tao 2010-05-19 17:37:01 -07:00
parent 25c38cfec1
commit 9c4da76964
4 changed files with 50 additions and 30 deletions

View File

@ -16,6 +16,7 @@ import (
var (
dpi = flag.Int("dpi", 72, "screen resolution in Dots Per Inch")
fontfile = flag.String("fontfile", "../../luxi-fonts/luxisr.ttf", "filename of the ttf font")
gamma = flag.Float("gamma", 1.0, "gamma correction")
size = flag.Float("size", 12, "font size in points")
spacing = flag.Float("spacing", 1.5, "line spacing (e.g. 2 means double spaced)")
wonb = flag.Bool("whiteonblack", false, "white text on a black background")
@ -87,6 +88,7 @@ func main() {
c.SetDPI(*dpi)
c.SetFont(font)
c.SetFontSize(*size)
c.SetGamma(*gamma)
// Draw the guidelines.
for i := 0; i < 200; i++ {

View File

@ -53,7 +53,7 @@ func main() {
mask := image.NewAlpha(50, 50)
painter := raster.NewAlphaPainter(mask)
painter.Op = draw.Src
gammas := []float64{1.0 / 10.0, 1.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0, 4.0 / 5.0, 1.0, 5.0 / 4.0, 3.0 / 2.0, 2.0, 3.0, 10.0}
gammas := []float{1.0 / 10.0, 1.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0, 4.0 / 5.0, 1.0, 5.0 / 4.0, 3.0 / 2.0, 2.0, 3.0, 10.0}
for i, g := range gammas {
clear(mask)
r.Rasterize(raster.NewGammaCorrectionPainter(painter, g))

View File

@ -32,7 +32,8 @@ func Pt(x, y int) raster.Point {
// given size.
type RGBAContext struct {
r *raster.Rasterizer
p *raster.RGBAPainter
rp *raster.RGBAPainter
gp *raster.GammaCorrectionPainter
font *truetype.Font
glyphBuf *truetype.GlyphBuf
fontSize float
@ -144,7 +145,7 @@ func (c *RGBAContext) DrawText(pt raster.Point, s string) (err os.Error) {
advance, x0 := 0, pt.X
dx := raster.Fixed(-c.xmin << 8)
dy := raster.Fixed(-c.ymin << 8)
c.p.Dy, y = c.ymin+int(pt.Y>>8), pt.Y&0xff
c.rp.Dy, y = c.ymin+int(pt.Y>>8), pt.Y&0xff
y += dy
prev, hasPrev := truetype.Index(0), false
for _, ch := range s {
@ -169,7 +170,7 @@ func (c *RGBAContext) DrawText(pt raster.Point, s string) (err os.Error) {
x = x0 + c.FUnitToFixed(advance)
// Break the co-ordinate down into an integer pixel part and a
// sub-pixel part, making sure that the latter is non-negative.
c.p.Dx, x = c.xmin+int(x>>8), x&0xff
c.rp.Dx, x = c.xmin+int(x>>8), x&0xff
x += dx
// Draw the contours.
c.r.Clear()
@ -178,7 +179,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.p)
c.r.Rasterize(c.gp)
// Advance the cursor.
advance += int(c.font.HMetric(index).AdvanceWidth)
prev, hasPrev = index, true
@ -204,7 +205,7 @@ func (c *RGBAContext) recalc() {
// SetColor sets the color to draw text.
func (c *RGBAContext) SetColor(color image.Color) {
c.p.SetColor(color)
c.rp.SetColor(color)
}
// SetDPI sets the screen resolution in dots per inch.
@ -229,20 +230,27 @@ func (c *RGBAContext) SetFontSize(fontSize float) {
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.p.Image = m
c.rp.Image = m
}
// NewRGBAContext creates a new RGBAContext.
func NewRGBAContext(m *image.RGBA) *RGBAContext {
return &RGBAContext{
c := &RGBAContext{
r: raster.NewRasterizer(0, 0),
p: raster.NewRGBAPainter(m),
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
}

View File

@ -215,46 +215,56 @@ type GammaCorrectionPainter struct {
Painter Painter
// Precomputed alpha values for linear interpolation, with fully opaque == 1<<16-1.
a [256]uint16
// Whether gamma correction is a no-op.
gammaIsOne bool
}
// Paint delegates to the wrapped Painter after performing gamma-correction
// on each Span.
func (g *GammaCorrectionPainter) Paint(ss []Span) {
const (
M = 0x1010101 // 255*M == 1<<32-1
N = 0x8080 // N = M>>9, and N < 1<<16-1
)
for i, _ := range ss {
if ss[i].A == 0 || ss[i].A == 1<<32-1 {
continue
if !g.gammaIsOne {
const (
M = 0x1010101 // 255*M == 1<<32-1
N = 0x8080 // N = M>>9, and N < 1<<16-1
)
for i, _ := range ss {
if ss[i].A == 0 || ss[i].A == 1<<32-1 {
continue
}
p, q := ss[i].A/M, (ss[i].A%M)>>9
// The resultant alpha is a linear interpolation of g.a[p] and g.a[p+1].
a := uint32(g.a[p])*(N-q) + uint32(g.a[p+1])*q
a = (a + N/2) / N
// Convert the alpha from 16-bit (which is g.a's range) to 32-bit.
a |= a << 16
// A non-final Span can't have zero alpha.
if a == 0 {
a = 1
}
ss[i].A = a
}
p, q := ss[i].A/M, (ss[i].A%M)>>9
// The resultant alpha is a linear interpolation of g.a[p] and g.a[p+1].
a := uint32(g.a[p])*(N-q) + uint32(g.a[p+1])*q
a = (a + N/2) / N
// Convert the alpha from 16-bit (which is g.a's range) to 32-bit.
a |= a << 16
// A non-final Span can't have zero alpha.
if a == 0 {
a = 1
}
ss[i].A = a
}
g.Painter.Paint(ss)
}
// SetGamma sets the gamma value.
func (g *GammaCorrectionPainter) SetGamma(gamma float64) {
func (g *GammaCorrectionPainter) SetGamma(gamma float) {
if gamma == 1.0 {
g.gammaIsOne = true
return
}
g.gammaIsOne = false
gamma64 := float64(gamma)
for i := 0; i < 256; i++ {
a := float64(i) / 0xff
a = math.Pow(a, gamma)
a = math.Pow(a, gamma64)
g.a[i] = uint16(0xffff * a)
}
}
// NewGammaCorrectionPainter creates a new GammaCorrectionPainter that wraps
// the given Painter.
func NewGammaCorrectionPainter(p Painter, gamma float64) *GammaCorrectionPainter {
func NewGammaCorrectionPainter(p Painter, gamma float) *GammaCorrectionPainter {
g := &GammaCorrectionPainter{Painter: p}
g.SetGamma(gamma)
return g