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
|
return
|
||||||
}
|
}
|
||||||
screen := window.Screen()
|
screen := window.Screen()
|
||||||
if rgba, ok := screen.(*image.RGBA); ok {
|
gc := draw2d.NewImageGraphicContext(screen)
|
||||||
gc := draw2d.NewImageGraphicContext(rgba)
|
gc.SetStrokeColor(image.Black)
|
||||||
gc.SetStrokeColor(image.Black)
|
gc.SetFillColor(image.White)
|
||||||
gc.SetFillColor(image.White)
|
gc.Clear()
|
||||||
gc.Clear()
|
for i := 0.0; i < 360; i = i + 10 { // Go from 0 to 360 degrees in 10 degree steps
|
||||||
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.BeginPath() // Start a new path
|
gc.Save() // Keep rotations temporary
|
||||||
gc.Save() // Keep rotations temporary
|
gc.MoveTo(144, 144)
|
||||||
gc.MoveTo(144, 144)
|
gc.Rotate(i * (math.Pi / 180.0)) // Rotate by degrees on stack from 'for'
|
||||||
gc.Rotate(i * (math.Pi / 180.0)) // Rotate by degrees on stack from 'for'
|
gc.RLineTo(72, 0)
|
||||||
gc.RLineTo(72, 0)
|
gc.Stroke()
|
||||||
gc.Stroke()
|
gc.Restore() // Get back the unrotated state
|
||||||
gc.Restore() // Get back the unrotated state
|
}
|
||||||
}
|
|
||||||
fmt.Printf("This is an rgba image\n")
|
|
||||||
|
|
||||||
window.FlushImage()
|
window.FlushImage()
|
||||||
|
|
||||||
gc.SetLineWidth(3)
|
gc.SetLineWidth(3)
|
||||||
nbclick := 0
|
nbclick := 0
|
||||||
for {
|
for {
|
||||||
|
|
||||||
switch evt := (<-window.EventChan()).(type) {
|
switch evt := (<-window.EventChan()).(type) {
|
||||||
case draw.KeyEvent:
|
case draw.KeyEvent:
|
||||||
if evt.Key == 'q' {
|
if evt.Key == 'q' {
|
||||||
window.Close()
|
window.Close()
|
||||||
}
|
}
|
||||||
case draw.MouseEvent:
|
case draw.MouseEvent:
|
||||||
if evt.Buttons&1 != 0 {
|
if evt.Buttons&1 != 0 {
|
||||||
if nbclick%2 == 0 {
|
if nbclick%2 == 0 {
|
||||||
gc.MoveTo(float64(evt.Loc.X), float64(evt.Loc.Y))
|
gc.MoveTo(float64(evt.Loc.X), float64(evt.Loc.Y))
|
||||||
} else {
|
} else {
|
||||||
gc.LineTo(float64(evt.Loc.X), float64(evt.Loc.Y))
|
gc.LineTo(float64(evt.Loc.X), float64(evt.Loc.Y))
|
||||||
gc.Stroke()
|
gc.Stroke()
|
||||||
window.FlushImage()
|
window.FlushImage()
|
||||||
}
|
|
||||||
nbclick = nbclick + 1
|
|
||||||
}
|
}
|
||||||
|
nbclick = nbclick + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
fmt.Printf("Not an RGBA image!\n")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,5 +18,6 @@ GOFILES=\
|
||||||
advanced_path.go\
|
advanced_path.go\
|
||||||
vertex2d.go\
|
vertex2d.go\
|
||||||
gc.go\
|
gc.go\
|
||||||
|
paint.go\
|
||||||
|
|
||||||
include $(GOROOT)/src/Make.pkg
|
include $(GOROOT)/src/Make.pkg
|
||||||
|
|
|
@ -10,8 +10,14 @@ import (
|
||||||
"freetype-go.googlecode.com/hg/freetype/raster"
|
"freetype-go.googlecode.com/hg/freetype/raster"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Painter interface{
|
||||||
|
raster.Painter
|
||||||
|
SetColor(color image.Color)
|
||||||
|
}
|
||||||
|
|
||||||
type ImageGraphicContext struct {
|
type ImageGraphicContext struct {
|
||||||
PaintedImage *image.RGBA
|
img draw.Image
|
||||||
|
painter Painter
|
||||||
fillRasterizer *raster.Rasterizer
|
fillRasterizer *raster.Rasterizer
|
||||||
strokeRasterizer *raster.Rasterizer
|
strokeRasterizer *raster.Rasterizer
|
||||||
freetype *freetype.Context
|
freetype *freetype.Context
|
||||||
|
@ -39,10 +45,19 @@ type contextStack struct {
|
||||||
/**
|
/**
|
||||||
* Create a new Graphic context from an image
|
* Create a new Graphic context from an image
|
||||||
*/
|
*/
|
||||||
func NewImageGraphicContext(pi *image.RGBA) *ImageGraphicContext {
|
func NewImageGraphicContext(img draw.Image) *ImageGraphicContext {
|
||||||
gc := new(ImageGraphicContext)
|
gc := new(ImageGraphicContext)
|
||||||
gc.PaintedImage = pi
|
gc.img = img
|
||||||
width, height := gc.PaintedImage.Bounds().Dx(), gc.PaintedImage.Bounds().Dy()
|
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.fillRasterizer = raster.NewRasterizer(width, height)
|
||||||
gc.strokeRasterizer = 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.defaultFontData = FontData{"luxi", FontFamilySans, FontStyleNormal}
|
||||||
gc.freetype = freetype.NewContext()
|
gc.freetype = freetype.NewContext()
|
||||||
gc.freetype.SetDPI(gc.DPI)
|
gc.freetype.SetDPI(gc.DPI)
|
||||||
gc.freetype.SetClip(pi.Bounds())
|
gc.freetype.SetClip(img.Bounds())
|
||||||
gc.freetype.SetDst(pi)
|
gc.freetype.SetDst(img)
|
||||||
|
|
||||||
gc.current = new(contextStack)
|
gc.current = new(contextStack)
|
||||||
|
|
||||||
|
@ -94,13 +109,13 @@ func (gc *ImageGraphicContext) Scale(sx, sy float64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *ImageGraphicContext) Clear() {
|
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)
|
gc.ClearRect(0, 0, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *ImageGraphicContext) ClearRect(x1, y1, x2, y2 int) {
|
func (gc *ImageGraphicContext) ClearRect(x1, y1, x2, y2 int) {
|
||||||
imageColor := image.NewColorImage(gc.current.fillColor)
|
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) {
|
func (gc *ImageGraphicContext) SetStrokeColor(c image.Color) {
|
||||||
|
@ -185,10 +200,8 @@ func (gc *ImageGraphicContext) Restore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *ImageGraphicContext) DrawImage(image image.Image) {
|
func (gc *ImageGraphicContext) DrawImage(image image.Image) {
|
||||||
width := raster.Fix32(gc.PaintedImage.Bounds().Dx() * 256)
|
width := raster.Fix32(gc.img.Bounds().Dx() * 256)
|
||||||
height := raster.Fix32(gc.PaintedImage.Bounds().Dy() * 256)
|
height := raster.Fix32(gc.img.Bounds().Dy() * 256)
|
||||||
|
|
||||||
painter := raster.NewRGBAPainter(gc.PaintedImage)
|
|
||||||
|
|
||||||
p0 := raster.Point{0, 0}
|
p0 := raster.Point{0, 0}
|
||||||
p1 := 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(p2)
|
||||||
gc.fillRasterizer.Add1(p3)
|
gc.fillRasterizer.Add1(p3)
|
||||||
gc.fillRasterizer.Add1(p0)
|
gc.fillRasterizer.Add1(p0)
|
||||||
painter.SetColor(image.At(int(i>>8), int(j>>8)))
|
gc.painter.SetColor(image.At(int(i>>8), int(j>>8)))
|
||||||
gc.fillRasterizer.Rasterize(painter)
|
gc.fillRasterizer.Rasterize(gc.painter)
|
||||||
gc.fillRasterizer.Clear()
|
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) {
|
func (gc *ImageGraphicContext) paint(rasterizer *raster.Rasterizer, color image.Color) {
|
||||||
painter := raster.NewRGBAPainter(gc.PaintedImage)
|
gc.painter.SetColor(color)
|
||||||
painter.SetColor(color)
|
rasterizer.Rasterize(gc.painter)
|
||||||
rasterizer.Rasterize(painter)
|
|
||||||
rasterizer.Clear()
|
rasterizer.Clear()
|
||||||
gc.current.path = new(PathStorage)
|
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