use draw.Image instead of image.Image
This commit is contained in:
parent
fe47a2e9d7
commit
0c9ae150bf
4 changed files with 155 additions and 53 deletions
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,5 +18,6 @@ GOFILES=\
|
|||
advanced_path.go\
|
||||
vertex2d.go\
|
||||
gc.go\
|
||||
paint.go\
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
||||
|
|
|
@ -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
94
draw2d/paint.go
Normal 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}
|
||||
}
|
Loading…
Reference in a new issue