use draw.Image instead of image.Image

This commit is contained in:
legoff.laurent 2011-03-22 21:23:03 +01:00
parent fe47a2e9d7
commit 0c9ae150bf
4 changed files with 155 additions and 53 deletions

View File

@ -16,47 +16,42 @@ func main() {
return
}
screen := window.Screen()
if rgba, ok := screen.(*image.RGBA); ok {
gc := draw2d.NewImageGraphicContext(rgba)
gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White)
gc.Clear()
for i := 0.0; i < 360; i = i + 10 { // Go from 0 to 360 degrees in 10 degree steps
gc.BeginPath() // Start a new path
gc.Save() // Keep rotations temporary
gc.MoveTo(144, 144)
gc.Rotate(i * (math.Pi / 180.0)) // Rotate by degrees on stack from 'for'
gc.RLineTo(72, 0)
gc.Stroke()
gc.Restore() // Get back the unrotated state
}
fmt.Printf("This is an rgba image\n")
gc := draw2d.NewImageGraphicContext(screen)
gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White)
gc.Clear()
for i := 0.0; i < 360; i = i + 10 { // Go from 0 to 360 degrees in 10 degree steps
gc.BeginPath() // Start a new path
gc.Save() // Keep rotations temporary
gc.MoveTo(144, 144)
gc.Rotate(i * (math.Pi / 180.0)) // Rotate by degrees on stack from 'for'
gc.RLineTo(72, 0)
gc.Stroke()
gc.Restore() // Get back the unrotated state
}
window.FlushImage()
window.FlushImage()
gc.SetLineWidth(3)
nbclick := 0
for {
gc.SetLineWidth(3)
nbclick := 0
for {
switch evt := (<-window.EventChan()).(type) {
case draw.KeyEvent:
if evt.Key == 'q' {
window.Close()
}
case draw.MouseEvent:
if evt.Buttons&1 != 0 {
if nbclick%2 == 0 {
gc.MoveTo(float64(evt.Loc.X), float64(evt.Loc.Y))
} else {
gc.LineTo(float64(evt.Loc.X), float64(evt.Loc.Y))
gc.Stroke()
window.FlushImage()
}
nbclick = nbclick + 1
switch evt := (<-window.EventChan()).(type) {
case draw.KeyEvent:
if evt.Key == 'q' {
window.Close()
}
case draw.MouseEvent:
if evt.Buttons&1 != 0 {
if nbclick%2 == 0 {
gc.MoveTo(float64(evt.Loc.X), float64(evt.Loc.Y))
} else {
gc.LineTo(float64(evt.Loc.X), float64(evt.Loc.Y))
gc.Stroke()
window.FlushImage()
}
nbclick = nbclick + 1
}
}
} else {
fmt.Printf("Not an RGBA image!\n")
}
}

View File

@ -18,5 +18,6 @@ GOFILES=\
advanced_path.go\
vertex2d.go\
gc.go\
paint.go\
include $(GOROOT)/src/Make.pkg

View File

@ -10,8 +10,14 @@ import (
"freetype-go.googlecode.com/hg/freetype/raster"
)
type Painter interface{
raster.Painter
SetColor(color image.Color)
}
type ImageGraphicContext struct {
PaintedImage *image.RGBA
img draw.Image
painter Painter
fillRasterizer *raster.Rasterizer
strokeRasterizer *raster.Rasterizer
freetype *freetype.Context
@ -39,10 +45,19 @@ type contextStack struct {
/**
* Create a new Graphic context from an image
*/
func NewImageGraphicContext(pi *image.RGBA) *ImageGraphicContext {
func NewImageGraphicContext(img draw.Image) *ImageGraphicContext {
gc := new(ImageGraphicContext)
gc.PaintedImage = pi
width, height := gc.PaintedImage.Bounds().Dx(), gc.PaintedImage.Bounds().Dy()
gc.img = img
switch selectImage := img.(type) {
case *image.RGBA:
gc.painter = raster.NewRGBAPainter(selectImage)
case *image.NRGBA:
gc.painter = NewNRGBAPainter(selectImage)
default:
panic("Image type not supported")
}
width, height := gc.img.Bounds().Dx(), gc.img.Bounds().Dy()
gc.fillRasterizer = raster.NewRasterizer(width, height)
gc.strokeRasterizer = raster.NewRasterizer(width, height)
@ -50,8 +65,8 @@ func NewImageGraphicContext(pi *image.RGBA) *ImageGraphicContext {
gc.defaultFontData = FontData{"luxi", FontFamilySans, FontStyleNormal}
gc.freetype = freetype.NewContext()
gc.freetype.SetDPI(gc.DPI)
gc.freetype.SetClip(pi.Bounds())
gc.freetype.SetDst(pi)
gc.freetype.SetClip(img.Bounds())
gc.freetype.SetDst(img)
gc.current = new(contextStack)
@ -94,13 +109,13 @@ func (gc *ImageGraphicContext) Scale(sx, sy float64) {
}
func (gc *ImageGraphicContext) Clear() {
width, height := gc.PaintedImage.Bounds().Dx(), gc.PaintedImage.Bounds().Dy()
width, height := gc.img.Bounds().Dx(), gc.img.Bounds().Dy()
gc.ClearRect(0, 0, width, height)
}
func (gc *ImageGraphicContext) ClearRect(x1, y1, x2, y2 int) {
imageColor := image.NewColorImage(gc.current.fillColor)
draw.Draw(gc.PaintedImage, image.Rect(x1, y1, x2, y2), imageColor, image.ZP)
draw.Draw(gc.img, image.Rect(x1, y1, x2, y2), imageColor, image.ZP)
}
func (gc *ImageGraphicContext) SetStrokeColor(c image.Color) {
@ -185,10 +200,8 @@ func (gc *ImageGraphicContext) Restore() {
}
func (gc *ImageGraphicContext) DrawImage(image image.Image) {
width := raster.Fix32(gc.PaintedImage.Bounds().Dx() * 256)
height := raster.Fix32(gc.PaintedImage.Bounds().Dy() * 256)
painter := raster.NewRGBAPainter(gc.PaintedImage)
width := raster.Fix32(gc.img.Bounds().Dx() * 256)
height := raster.Fix32(gc.img.Bounds().Dy() * 256)
p0 := raster.Point{0, 0}
p1 := raster.Point{0, 0}
@ -209,8 +222,8 @@ func (gc *ImageGraphicContext) DrawImage(image image.Image) {
gc.fillRasterizer.Add1(p2)
gc.fillRasterizer.Add1(p3)
gc.fillRasterizer.Add1(p0)
painter.SetColor(image.At(int(i>>8), int(j>>8)))
gc.fillRasterizer.Rasterize(painter)
gc.painter.SetColor(image.At(int(i>>8), int(j>>8)))
gc.fillRasterizer.Rasterize(gc.painter)
gc.fillRasterizer.Clear()
}
}
@ -302,9 +315,8 @@ func (gc *ImageGraphicContext) FillString(text string) (cursor float64) {
func (gc *ImageGraphicContext) paint(rasterizer *raster.Rasterizer, color image.Color) {
painter := raster.NewRGBAPainter(gc.PaintedImage)
painter.SetColor(color)
rasterizer.Rasterize(painter)
gc.painter.SetColor(color)
rasterizer.Rasterize(gc.painter)
rasterizer.Clear()
gc.current.path = new(PathStorage)
}

94
draw2d/paint.go Normal file
View File

@ -0,0 +1,94 @@
// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff
package draw2d
import (
"exp/draw"
"image"
"freetype-go.googlecode.com/hg/freetype/raster"
)
const M = 1<<16 - 1
type NRGBAPainter struct {
// The image to compose onto.
Image *image.NRGBA
// The Porter-Duff composition operator.
Op draw.Op
// The 16-bit color to paint the spans.
cr, cg, cb, ca uint32
}
func min(a, b uint32) uint32 {
if a < b {
return a
}
return b
}
// Paint satisfies the Painter interface by painting ss onto an image.RGBA.
func (r *NRGBAPainter) Paint(ss []raster.Span, done bool) {
b := r.Image.Bounds()
for _, s := range ss {
if s.Y < b.Min.Y {
continue
}
if s.Y >= b.Max.Y {
return
}
if s.X0 < b.Min.X {
s.X0 = b.Min.X
}
if s.X1 > b.Max.X {
s.X1 = b.Max.X
}
if s.X0 >= s.X1 {
continue
}
base := s.Y * r.Image.Stride
p := r.Image.Pix[base+s.X0 : base+s.X1]
// This code is duplicated from drawGlyphOver in $GOROOT/src/pkg/exp/draw/draw.go.
// TODO(nigeltao): Factor out common code into a utility function, once the compiler
// can inline such function calls.
ma := s.A >> 16
if r.Op == draw.Over {
for i, nrgba := range p {
dr, dg, db, da := nrgba.RGBA()
a := M - (r.ca*ma)/M
da = (da*a + r.ca*ma) / M
if da != 0 {
dr = min(M, (dr*a+r.cr*ma)/da)
dg = min(M, (dg*a+r.cg*ma)/da)
db = min(M, (db*a+r.cb*ma)/da)
} else {
dr, dg, db = 0, 0, 0
}
p[i] = image.NRGBAColor{uint8(dr >> 8), uint8(dg >> 8), uint8(db >> 8), uint8(da >> 8)}
}
} else {
for i, nrgba := range p {
dr, dg, db, da := nrgba.RGBA()
a := M - ma
da = (da*a + r.ca*ma) / M
if da != 0 {
dr = min(M, (dr*a+r.cr*ma)/da)
dg = min(M, (dg*a+r.cg*ma)/da)
db = min(M, (db*a+r.cb*ma)/da)
} else {
dr, dg, db = 0, 0, 0
}
p[i] = image.NRGBAColor{uint8(dr >> 8), uint8(dg >> 8), uint8(db >> 8), uint8(da >> 8)}
}
}
}
}
// SetColor sets the color to paint the spans.
func (r *NRGBAPainter) SetColor(c image.Color) {
r.cr, r.cg, r.cb, r.ca = c.RGBA()
}
// NewRGBAPainter creates a new RGBAPainter for the given image.
func NewNRGBAPainter(m *image.NRGBA) *NRGBAPainter {
return &NRGBAPainter{Image: m}
}