This commit is contained in:
Laurent Le Goff 2012-01-13 10:14:12 +01:00
parent 72c07eba44
commit c595982fba
36 changed files with 1181 additions and 1228 deletions

View file

@ -18,15 +18,15 @@
package main package main
import ( import (
"os" "code.google.com/p/draw2d/draw2dgl"
"math" "code.google.com/p/draw2d/postscript"
"io/ioutil"
"strings"
"gl" "gl"
"glut" "glut"
"draw2d.googlecode.com/hg/draw2dgl" "io/ioutil"
"draw2d.googlecode.com/hg/postscript"
"log" "log"
"math"
"os"
"strings"
"time" "time"
) )
@ -69,9 +69,9 @@ func display() {
gc.Translate(-380, -400) gc.Translate(-380, -400)
interpreter := postscript.NewInterpreter(gc) interpreter := postscript.NewInterpreter(gc)
reader := strings.NewReader(postscriptContent) reader := strings.NewReader(postscriptContent)
lastTime := time.Nanoseconds() lastTime := time.Now()
interpreter.Execute(reader) interpreter.Execute(reader)
dt := time.Nanoseconds() - lastTime dt := time.Now().Sub(lastTime)
log.Printf("Redraw in : %f ms\n", float64(dt)*1e-6) log.Printf("Redraw in : %f ms\n", float64(dt)*1e-6)
gl.Flush() /* Single buffered, so needs a flush. */ gl.Flush() /* Single buffered, so needs a flush. */
glut.PostRedisplay() glut.PostRedisplay()

View file

@ -4,17 +4,16 @@
package main package main
import ( import (
"bufio"
"fmt" "fmt"
"log" "log"
"os" "os"
"bufio"
"code.google.com/p/draw2d/draw2d"
"image" "image"
"image/png" "image/png"
"draw2d.googlecode.com/hg/draw2d"
) )
func saveToPngFile(filePath string, m image.Image) { func saveToPngFile(filePath string, m image.Image) {
f, err := os.Create(filePath) f, err := os.Create(filePath)
if err != nil { if err != nil {
@ -37,7 +36,7 @@ func saveToPngFile(filePath string, m image.Image) {
} }
func main() { func main() {
i := image.NewRGBA(image.Rect(0,0,200, 200)) i := image.NewRGBA(image.Rect(0, 0, 200, 200))
gc := draw2d.NewGraphicContext(i) gc := draw2d.NewGraphicContext(i)
gc.MoveTo(10.0, 10.0) gc.MoveTo(10.0, 10.0)
gc.LineTo(100.0, 10.0) gc.LineTo(100.0, 10.0)

View file

@ -5,17 +5,18 @@
package main package main
import ( import (
"code.google.com/p/draw2d/draw2d"
"code.google.com/p/draw2d/postscript"
"code.google.com/p/draw2d/wingui"
"fmt" "fmt"
"syscall"
"os"
"unsafe"
"image" "image"
"image/color"
"io/ioutil" "io/ioutil"
"os"
"strings" "strings"
"syscall"
"time" "time"
"draw2d.googlecode.com/hg/draw2d" "unsafe"
"draw2d.googlecode.com/hg/postscript"
"draw2d.googlecode.com/hg/wingui"
) )
// some help functions // some help functions
@ -31,7 +32,6 @@ func abortErrNo(funcname string, err int) {
// global vars // global vars
func TestDrawCubicCurve(gc draw2d.GraphicContext) { func TestDrawCubicCurve(gc draw2d.GraphicContext) {
// draw a cubic curve // draw a cubic curve
x, y := 25.6, 128.0 x, y := 25.6, 128.0
@ -39,13 +39,13 @@ func TestDrawCubicCurve(gc draw2d.GraphicContext) {
x2, y2 := 153.6, 25.6 x2, y2 := 153.6, 25.6
x3, y3 := 230.4, 128.0 x3, y3 := 230.4, 128.0
gc.SetFillColor(image.NRGBAColor{0xAA, 0xAA, 0xAA, 0xFF}) gc.SetFillColor(color.NRGBA{0xAA, 0xAA, 0xAA, 0xFF})
gc.SetLineWidth(10) gc.SetLineWidth(10)
gc.MoveTo(x, y) gc.MoveTo(x, y)
gc.CubicCurveTo(x1, y1, x2, y2, x3, y3) gc.CubicCurveTo(x1, y1, x2, y2, x3, y3)
gc.Stroke() gc.Stroke()
gc.SetStrokeColor(image.NRGBAColor{0xFF, 0x33, 0x33, 0x88}) gc.SetStrokeColor(color.NRGBA{0xFF, 0x33, 0x33, 0x88})
gc.SetLineWidth(6) gc.SetLineWidth(6)
// draw segment of curve // draw segment of curve
@ -61,7 +61,7 @@ var (
wndBufferHeader uint32 wndBufferHeader uint32
wndBuffer wingui.BITMAP wndBuffer wingui.BITMAP
hdcWndBuffer uint32 hdcWndBuffer uint32
ppvBits *image.RGBAColor ppvBits *color.RGBA
backBuffer *image.RGBA backBuffer *image.RGBA
postscriptContent string postscriptContent string
) )
@ -102,7 +102,7 @@ func WndProc(hwnd, msg uint32, wparam, lparam int32) uintptr {
hdcWndBuffer = wingui.CreateCompatibleDC(hdc) hdcWndBuffer = wingui.CreateCompatibleDC(hdc)
wingui.SelectObject(hdcWndBuffer, wndBufferHeader) wingui.SelectObject(hdcWndBuffer, wndBufferHeader)
pixel := (*[600 * 800]image.RGBAColor)(unsafe.Pointer(ppvBits)) pixel := (*[600 * 800]color.RGBA)(unsafe.Pointer(ppvBits))
pixelSlice := pixel[:] pixelSlice := pixel[:]
backBuffer = &image.RGBA{pixelSlice, 600, image.Rect(0, 0, 600, 800)} backBuffer = &image.RGBA{pixelSlice, 600, image.Rect(0, 0, 600, 800)}
fmt.Println("Create windows") fmt.Println("Create windows")
@ -114,17 +114,17 @@ func WndProc(hwnd, msg uint32, wparam, lparam int32) uintptr {
} }
case wingui.WM_PAINT: case wingui.WM_PAINT:
var ps wingui.PAINTSTRUCT var ps wingui.PAINTSTRUCT
lastTime := time.Nanoseconds() lastTime := time.Now()
hdc := wingui.BeginPaint(hwnd, &ps) hdc := wingui.BeginPaint(hwnd, &ps)
gc := draw2d.NewGraphicContext(backBuffer) gc := draw2d.NewGraphicContext(backBuffer)
gc.SetFillColor(image.RGBAColor{0xFF, 0xFF, 0xFF, 0xFF}) gc.SetFillColor(color.RGBA{0xFF, 0xFF, 0xFF, 0xFF})
// gc.Clear() // gc.Clear()
gc.Save() gc.Save()
//gc.Translate(0, -380) //gc.Translate(0, -380)
interpreter := postscript.NewInterpreter(gc) interpreter := postscript.NewInterpreter(gc)
reader := strings.NewReader(postscriptContent) reader := strings.NewReader(postscriptContent)
interpreter.Execute(reader) interpreter.Execute(reader)
dt := time.Nanoseconds() - lastTime dt := time.Now().Sub(lastTime)
gc.Restore() gc.Restore()
// back buf in // back buf in

View file

@ -1,12 +1,12 @@
package main package main
import ( import (
"fmt" "code.google.com/p/draw2d/draw2d"
"exp/gui" "exp/gui"
"exp/gui/x11" "exp/gui/x11"
"fmt"
"image" "image"
"math" "math"
"draw2d.googlecode.com/hg/draw2d"
) )
func main() { func main() {

View file

@ -1,17 +1,17 @@
package main package main
import ( import (
"bufio"
"fmt" "fmt"
"log" "log"
"os" "os"
"bufio"
"time" "time"
"math" "code.google.com/p/draw2d/draw2d"
"image" "image"
"image/color"
"image/png" "image/png"
"draw2d.googlecode.com/hg/draw2d" "math"
) )
const ( const (
@ -24,9 +24,9 @@ var (
) )
func initGc(w, h int) (image.Image, draw2d.GraphicContext) { func initGc(w, h int) (image.Image, draw2d.GraphicContext) {
i := image.NewRGBA(image.Rect(0, 0,w, h)) i := image.NewRGBA(image.Rect(0, 0, w, h))
gc := draw2d.NewGraphicContext(i) gc := draw2d.NewGraphicContext(i)
lastTime = time.Nanoseconds() lastTime = time.Now()
gc.SetStrokeColor(image.Black) gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White) gc.SetFillColor(image.White)
@ -37,7 +37,7 @@ func initGc(w, h int) (image.Image, draw2d.GraphicContext) {
} }
func saveToPngFile(TestName string, m image.Image) { func saveToPngFile(TestName string, m image.Image) {
dt := time.Nanoseconds() - lastTime dt := time.Now().Sub(lastTime)
fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*1e-6) fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*1e-6)
filePath := folder + TestName + ".png" filePath := folder + TestName + ".png"
f, err := os.Create(filePath) f, err := os.Create(filePath)
@ -88,11 +88,10 @@ func android(gc draw2d.GraphicContext, x, y float64) {
gc.FillStroke() gc.FillStroke()
} }
func main() { func main() {
i, gc := initGc(width, height) i, gc := initGc(width, height)
gc.SetFillColor(image.RGBAColor{0x44, 0xff, 0x44, 0xff}) gc.SetFillColor(color.RGBA{0x44, 0xff, 0x44, 0xff})
gc.SetStrokeColor(image.RGBAColor{0x44, 0x44, 0x44, 0xff}) gc.SetStrokeColor(color.RGBA{0x44, 0x44, 0x44, 0xff})
android(gc, 10, 10) android(gc, 10, 10)
saveToPngFile("TestAndroid", i) saveToPngFile("TestAndroid", i)
} }

View file

@ -4,16 +4,17 @@
package main package main
import ( import (
"bufio"
"fmt" "fmt"
"log" "log"
"os" "os"
"bufio"
"time" "time"
"math" "code.google.com/p/draw2d/draw2d"
"image" "image"
"image/color"
"image/png" "image/png"
"draw2d.googlecode.com/hg/draw2d" "math"
) )
const ( const (
@ -28,7 +29,7 @@ var (
func initGc(w, h int) (image.Image, draw2d.GraphicContext) { func initGc(w, h int) (image.Image, draw2d.GraphicContext) {
i := image.NewRGBA(image.Rect(0, 0, w, h)) i := image.NewRGBA(image.Rect(0, 0, w, h))
gc := draw2d.NewGraphicContext(i) gc := draw2d.NewGraphicContext(i)
lastTime = time.Nanoseconds() lastTime = time.Now()
gc.SetStrokeColor(image.Black) gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White) gc.SetFillColor(image.White)
@ -39,8 +40,8 @@ func initGc(w, h int) (image.Image, draw2d.GraphicContext) {
} }
func saveToPngFile(TestName string, m image.Image) { func saveToPngFile(TestName string, m image.Image) {
t := time.Nanoseconds() t := time.Now()
dt := t - lastTime dt := t.Sub(lastTime)
fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*1e-6) fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*1e-6)
filePath := folder + TestName + ".png" filePath := folder + TestName + ".png"
f, err := os.Create(filePath) f, err := os.Create(filePath)
@ -60,7 +61,7 @@ func saveToPngFile(TestName string, m image.Image) {
log.Println(err) log.Println(err)
os.Exit(1) os.Exit(1)
} }
dt = time.Nanoseconds() - t dt = time.Now().Sub(t)
fmt.Printf("Wrote %s OK in %f ms.\n", filePath, float64(dt)*1e-6) fmt.Printf("Wrote %s OK in %f ms.\n", filePath, float64(dt)*1e-6)
} }
@ -79,7 +80,6 @@ func TestPath() {
saveToPngFile("TestPath", i) saveToPngFile("TestPath", i)
} }
/* /*
<img src="../test_results/TestDrawArc.png"/> <img src="../test_results/TestDrawArc.png"/>
*/ */
@ -96,8 +96,8 @@ func TestDrawArc() {
gc.ArcTo(xc, yc, radiusX, radiusY, startAngle, angle) gc.ArcTo(xc, yc, radiusX, radiusY, startAngle, angle)
gc.Stroke() gc.Stroke()
// fill a circle // fill a circle
gc.SetStrokeColor(image.NRGBAColor{255, 0x33, 0x33, 0x80}) gc.SetStrokeColor(color.NRGBA{255, 0x33, 0x33, 0x80})
gc.SetFillColor(image.NRGBAColor{255, 0x33, 0x33, 0x80}) gc.SetFillColor(color.NRGBA{255, 0x33, 0x33, 0x80})
gc.SetLineWidth(6) gc.SetLineWidth(6)
gc.MoveTo(xc, yc) gc.MoveTo(xc, yc)
@ -110,6 +110,7 @@ func TestDrawArc() {
gc.Fill() gc.Fill()
saveToPngFile("TestDrawArc", i) saveToPngFile("TestDrawArc", i)
} }
/* /*
<img src="../test_results/TestDrawArc.png"/> <img src="../test_results/TestDrawArc.png"/>
*/ */
@ -127,8 +128,8 @@ func TestDrawArcNegative() {
gc.ArcTo(xc, yc, radiusX, radiusY, startAngle, angle) gc.ArcTo(xc, yc, radiusX, radiusY, startAngle, angle)
gc.Stroke() gc.Stroke()
// fill a circle // fill a circle
gc.SetStrokeColor(image.NRGBAColor{255, 0x33, 0x33, 0x80}) gc.SetStrokeColor(color.NRGBA{255, 0x33, 0x33, 0x80})
gc.SetFillColor(image.NRGBAColor{255, 0x33, 0x33, 0x80}) gc.SetFillColor(color.NRGBA{255, 0x33, 0x33, 0x80})
gc.SetLineWidth(6) gc.SetLineWidth(6)
gc.MoveTo(xc, yc) gc.MoveTo(xc, yc)
@ -189,13 +190,14 @@ func TestCurveRectangle() {
} }
gc.Close() gc.Close()
gc.SetFillColor(image.NRGBAColor{0x80, 0x80, 0xFF, 0xFF}) gc.SetFillColor(color.NRGBA{0x80, 0x80, 0xFF, 0xFF})
gc.SetStrokeColor(image.NRGBAColor{0x80, 0, 0, 0x80}) gc.SetStrokeColor(color.NRGBA{0x80, 0, 0, 0x80})
gc.SetLineWidth(10.0) gc.SetLineWidth(10.0)
gc.FillStroke() gc.FillStroke()
saveToPngFile("TestCurveRectangle", i) saveToPngFile("TestCurveRectangle", i)
} }
/* /*
<img src="../test_results/TestDrawCubicCurve.png"/> <img src="../test_results/TestDrawCubicCurve.png"/>
*/ */
@ -207,13 +209,13 @@ func TestDrawCubicCurve() {
x2, y2 := 153.6, 25.6 x2, y2 := 153.6, 25.6
x3, y3 := 230.4, 128.0 x3, y3 := 230.4, 128.0
gc.SetFillColor(image.NRGBAColor{0xAA, 0xAA, 0xAA, 0xFF}) gc.SetFillColor(color.NRGBA{0xAA, 0xAA, 0xAA, 0xFF})
gc.SetLineWidth(10) gc.SetLineWidth(10)
gc.MoveTo(x, y) gc.MoveTo(x, y)
gc.CubicCurveTo(x1, y1, x2, y2, x3, y3) gc.CubicCurveTo(x1, y1, x2, y2, x3, y3)
gc.Stroke() gc.Stroke()
gc.SetStrokeColor(image.NRGBAColor{0xFF, 0x33, 0x33, 0x88}) gc.SetStrokeColor(color.NRGBA{0xFF, 0x33, 0x33, 0x88})
gc.SetLineWidth(6) gc.SetLineWidth(6)
// draw segment of curve // draw segment of curve
@ -245,7 +247,6 @@ func TestDash() {
saveToPngFile("TestDash", i) saveToPngFile("TestDash", i)
} }
/* /*
<img src="../test_results/TestFillStroke.png"/> <img src="../test_results/TestFillStroke.png"/>
*/ */
@ -264,7 +265,7 @@ func TestFillStroke() {
gc.Close() gc.Close()
gc.SetLineWidth(10.0) gc.SetLineWidth(10.0)
gc.SetFillColor(image.NRGBAColor{0, 0, 0xFF, 0xFF}) gc.SetFillColor(color.NRGBA{0, 0, 0xFF, 0xFF})
gc.SetStrokeColor(image.Black) gc.SetStrokeColor(image.Black)
gc.FillStroke() gc.FillStroke()
saveToPngFile("TestFillStroke", i) saveToPngFile("TestFillStroke", i)
@ -285,7 +286,7 @@ func TestFillStyle() {
wheel2.ArcTo(192, 64, 40, 40, 0, 2*math.Pi) wheel2.ArcTo(192, 64, 40, 40, 0, 2*math.Pi)
gc.SetFillRule(draw2d.FillRuleEvenOdd) gc.SetFillRule(draw2d.FillRuleEvenOdd)
gc.SetFillColor(image.NRGBAColor{0, 0xB2, 0, 0xFF}) gc.SetFillColor(color.NRGBA{0, 0xB2, 0, 0xFF})
gc.SetStrokeColor(image.Black) gc.SetStrokeColor(image.Black)
gc.FillStroke(wheel1, wheel2) gc.FillStroke(wheel1, wheel2)
@ -297,7 +298,7 @@ func TestFillStyle() {
wheel2.ArcTo(192, 192, 40, 40, 0, -2*math.Pi) wheel2.ArcTo(192, 192, 40, 40, 0, -2*math.Pi)
gc.SetFillRule(draw2d.FillRuleWinding) gc.SetFillRule(draw2d.FillRuleWinding)
gc.SetFillColor(image.NRGBAColor{0, 0, 0xE5, 0xFF}) gc.SetFillColor(color.NRGBA{0, 0, 0xE5, 0xFF})
gc.FillStroke(wheel1, wheel2) gc.FillStroke(wheel1, wheel2)
saveToPngFile("TestFillStyle", i) saveToPngFile("TestFillStyle", i)
} }
@ -319,7 +320,6 @@ func TestMultiSegmentCaps() {
saveToPngFile("TestMultiSegmentCaps", i) saveToPngFile("TestMultiSegmentCaps", i)
} }
func TestRoundRectangle() { func TestRoundRectangle() {
i, gc := initGc(w, h) i, gc := initGc(w, h)
/* a custom shape that could be wrapped in a function */ /* a custom shape that could be wrapped in a function */
@ -337,8 +337,8 @@ func TestRoundRectangle() {
gc.ArcTo(x+radius, y+radius, radius, radius, 180*degrees, 90*degrees) gc.ArcTo(x+radius, y+radius, radius, radius, 180*degrees, 90*degrees)
gc.Close() gc.Close()
gc.SetFillColor(image.NRGBAColor{0x80, 0x80, 0xFF, 0xFF}) gc.SetFillColor(color.NRGBA{0x80, 0x80, 0xFF, 0xFF})
gc.SetStrokeColor(image.NRGBAColor{0x80, 0, 0, 0x80}) gc.SetStrokeColor(color.NRGBA{0x80, 0, 0, 0x80})
gc.SetLineWidth(10.0) gc.SetLineWidth(10.0)
gc.FillStroke() gc.FillStroke()
@ -362,7 +362,7 @@ func TestLineCap() {
gc.Stroke() gc.Stroke()
/* draw helping lines */ /* draw helping lines */
gc.SetStrokeColor(image.NRGBAColor{0xFF, 0x33, 0x33, 0xFF}) gc.SetStrokeColor(color.NRGBA{0xFF, 0x33, 0x33, 0xFF})
gc.SetLineWidth(2.56) gc.SetLineWidth(2.56)
gc.MoveTo(64.0, 50.0) gc.MoveTo(64.0, 50.0)
gc.LineTo(64.0, 200.0) gc.LineTo(64.0, 200.0)
@ -513,7 +513,7 @@ func TestBigPicture() {
} }
func main() { func main() {
t := time.Nanoseconds() t := time.Now()
TestPath() TestPath()
TestDrawArc() TestDrawArc()
TestDrawArcNegative() TestDrawArcNegative()
@ -532,6 +532,6 @@ func main() {
TestPathTransform() TestPathTransform()
TestFillString() TestFillString()
TestBigPicture() TestBigPicture()
dt := time.Nanoseconds() - t dt := time.Now().Sub(t)
fmt.Printf("All tests during: %f ms\n", float64(dt)*1e-6) fmt.Printf("All tests during: %f ms\n", float64(dt)*1e-6)
} }

View file

@ -1,17 +1,17 @@
package main package main
import ( import (
"bufio"
"fmt" "fmt"
"log" "log"
"os"
"bufio"
"time"
"math" "math"
"os"
"time"
"code.google.com/p/draw2d/draw2d"
"image" "image"
"image/color"
"image/png" "image/png"
"draw2d.googlecode.com/hg/draw2d"
) )
const ( const (
@ -26,7 +26,7 @@ var (
func initGc(w, h int) (image.Image, draw2d.GraphicContext) { func initGc(w, h int) (image.Image, draw2d.GraphicContext) {
i := image.NewRGBA(image.Rect(0, 0, w, h)) i := image.NewRGBA(image.Rect(0, 0, w, h))
gc := draw2d.NewGraphicContext(i) gc := draw2d.NewGraphicContext(i)
lastTime = time.Nanoseconds() lastTime = time.Now()
gc.SetStrokeColor(image.Black) gc.SetStrokeColor(image.Black)
gc.SetFillColor(image.White) gc.SetFillColor(image.White)
@ -37,7 +37,7 @@ func initGc(w, h int) (image.Image, draw2d.GraphicContext) {
} }
func saveToPngFile(TestName string, m image.Image) { func saveToPngFile(TestName string, m image.Image) {
dt := time.Nanoseconds() - lastTime dt := time.Now().Sub(lastTime)
fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*1e-6) fmt.Printf("%s during: %f ms\n", TestName, float64(dt)*1e-6)
filePath := folder + TestName + ".png" filePath := folder + TestName + ".png"
f, err := os.Create(filePath) f, err := os.Create(filePath)
@ -63,11 +63,11 @@ func saveToPngFile(TestName string, m image.Image) {
func gordon(gc draw2d.GraphicContext, x, y, w, h float64) { func gordon(gc draw2d.GraphicContext, x, y, w, h float64) {
h23 := (h * 2) / 3 h23 := (h * 2) / 3
blf := image.RGBAColor{0, 0, 0, 0xff} blf := color.RGBA{0, 0, 0, 0xff}
wf := image.RGBAColor{0xff, 0xff, 0xff, 0xff} wf := color.RGBA{0xff, 0xff, 0xff, 0xff}
nf := image.RGBAColor{0x8B, 0x45, 0x13, 0xff} nf := color.RGBA{0x8B, 0x45, 0x13, 0xff}
brf := image.RGBAColor{0x8B, 0x45, 0x13, 0x99} brf := color.RGBA{0x8B, 0x45, 0x13, 0x99}
brb := image.RGBAColor{0x8B, 0x45, 0x13, 0xBB} brb := color.RGBA{0x8B, 0x45, 0x13, 0xBB}
gc.MoveTo(x, y+h) gc.MoveTo(x, y+h)
gc.CubicCurveTo(x, y+h, x+w/2, y-h, x+w, y+h) gc.CubicCurveTo(x, y+h, x+w/2, y-h, x+w, y+h)

View file

@ -1,19 +1,18 @@
package main package main
import ( import (
"fmt"
"log"
"os"
"bufio" "bufio"
"math" "code.google.com/p/draw2d/draw2d"
"fmt"
"image" "image"
"time"
"image/png"
"image/draw" "image/draw"
"draw2d.googlecode.com/hg/draw2d" "image/png"
"log"
"math"
"os"
"time"
) )
func saveToPngFile(filePath string, m image.Image) { func saveToPngFile(filePath string, m image.Image) {
f, err := os.Create(filePath) f, err := os.Create(filePath)
if err != nil { if err != nil {
@ -52,7 +51,6 @@ func loadFromPngFile(filePath string) image.Image {
return i return i
} }
func main() { func main() {
source := loadFromPngFile("../resource/image/TestAndroid.png") source := loadFromPngFile("../resource/image/TestAndroid.png")
dest := image.NewRGBA(image.Rect(0, 0, 1024, 768)) dest := image.NewRGBA(image.Rect(0, 0, 1024, 768))
@ -63,9 +61,9 @@ func main() {
//tr.Scale(3, 3) //tr.Scale(3, 3)
tr.Translate(-width/2, -height/2) tr.Translate(-width/2, -height/2)
tr.Translate(200, 5) tr.Translate(200, 5)
lastTime := time.Nanoseconds() lastTime := time.Now()
draw2d.DrawImage(source, dest, tr, draw.Over, draw2d.BilinearFilter) draw2d.DrawImage(source, dest, tr, draw.Over, draw2d.BilinearFilter)
dt := time.Nanoseconds() - lastTime dt := time.Now().Sub(lastTime)
fmt.Printf("Draw image: %f ms\n", float64(dt)*1e-6) fmt.Printf("Draw image: %f ms\n", float64(dt)*1e-6)
saveToPngFile("../resource/result/TestDrawImage.png", dest) saveToPngFile("../resource/result/TestDrawImage.png", dest)
} }

View file

@ -1,21 +1,19 @@
package main package main
import ( import (
"fmt"
"time"
"log"
"os"
"io/ioutil"
"bufio" "bufio"
"strings" "code.google.com/p/draw2d/draw2d"
"code.google.com/p/draw2d/postscript"
"fmt"
"image" "image"
"image/png" "image/png"
"draw2d.googlecode.com/hg/draw2d" "io/ioutil"
"draw2d.googlecode.com/hg/postscript" "log"
"os"
"strings"
"time"
) )
func saveToPngFile(filePath string, m image.Image) { func saveToPngFile(filePath string, m image.Image) {
f, err := os.Create(filePath) f, err := os.Create(filePath)
if err != nil { if err != nil {
@ -51,9 +49,9 @@ func main() {
bytes, err := ioutil.ReadAll(src) bytes, err := ioutil.ReadAll(src)
reader := strings.NewReader(string(bytes)) reader := strings.NewReader(string(bytes))
interpreter := postscript.NewInterpreter(gc) interpreter := postscript.NewInterpreter(gc)
lastTime := time.Nanoseconds() lastTime := time.Now()
interpreter.Execute(reader) interpreter.Execute(reader)
dt := time.Nanoseconds() - lastTime dt := time.Now().Sub(lastTime)
fmt.Printf("Draw image: %f ms\n", float64(dt)*1e-6) fmt.Printf("Draw image: %f ms\n", float64(dt)*1e-6)
saveToPngFile("../resource/result/TestPostscript.png", i) saveToPngFile("../resource/result/TestPostscript.png", i)
} }

View file

@ -1,6 +1,6 @@
include $(GOROOT)/src/Make.inc include $(GOROOT)/src/Make.inc
TARG=draw2d.googlecode.com/hg/draw2d TARG=code.google.com/p/draw2d/draw2d
GOFILES=\ GOFILES=\
draw2d.go\ draw2d.go\
arc.go\ arc.go\

View file

@ -3,7 +3,7 @@
package draw2d package draw2d
import ( import (
"freetype-go.googlecode.com/hg/freetype/raster" "code.google.com/p/freetype-go/freetype/raster"
"math" "math"
) )
@ -13,7 +13,7 @@ func arc(t VertexConverter, x, y, rx, ry, start, angle, scale float64) (lastX, l
if angle < 0 { if angle < 0 {
clockWise = false clockWise = false
} }
ra := (math.Fabs(rx) + math.Fabs(ry)) / 2 ra := (math.Abs(rx) + math.Abs(ry)) / 2
da := math.Acos(ra/(ra+0.125/scale)) * 2 da := math.Acos(ra/(ra+0.125/scale)) * 2
//normalize //normalize
if !clockWise { if !clockWise {
@ -36,14 +36,13 @@ func arc(t VertexConverter, x, y, rx, ry, start, angle, scale float64) (lastX, l
return curX, curY return curX, curY
} }
func arcAdder(adder raster.Adder, x, y, rx, ry, start, angle, scale float64) raster.Point { func arcAdder(adder raster.Adder, x, y, rx, ry, start, angle, scale float64) raster.Point {
end := start + angle end := start + angle
clockWise := true clockWise := true
if angle < 0 { if angle < 0 {
clockWise = false clockWise = false
} }
ra := (math.Fabs(rx) + math.Fabs(ry)) / 2 ra := (math.Abs(rx) + math.Abs(ry)) / 2
da := math.Acos(ra/(ra+0.125/scale)) * 2 da := math.Acos(ra/(ra+0.125/scale)) * 2
//normalize //normalize
if !clockWise { if !clockWise {

View file

@ -1,6 +1,6 @@
package main package main
import "draw2d.googlecode.com/hg/draw2d/curve" import "code.google.com/p/draw2d/draw2d/curve"
import "testing" import "testing"
import __os__ "os" import __os__ "os"
import __regexp__ "regexp" import __regexp__ "regexp"
@ -14,7 +14,7 @@ var tests = []testing.InternalTest{
{"curve.TestQuadCurve", curve.TestQuadCurve}, {"curve.TestQuadCurve", curve.TestQuadCurve},
} }
var benchmarks = []testing.InternalBenchmark{ {"curve.BenchmarkCubicCurveRec", curve.BenchmarkCubicCurveRec}, var benchmarks = []testing.InternalBenchmark{{"curve.BenchmarkCubicCurveRec", curve.BenchmarkCubicCurveRec},
{"curve.BenchmarkCubicCurve", curve.BenchmarkCubicCurve}, {"curve.BenchmarkCubicCurve", curve.BenchmarkCubicCurve},
{"curve.BenchmarkCubicCurveAdaptiveRec", curve.BenchmarkCubicCurveAdaptiveRec}, {"curve.BenchmarkCubicCurveAdaptiveRec", curve.BenchmarkCubicCurveAdaptiveRec},
{"curve.BenchmarkCubicCurveAdaptive", curve.BenchmarkCubicCurveAdaptive}, {"curve.BenchmarkCubicCurveAdaptive", curve.BenchmarkCubicCurveAdaptive},

View file

@ -3,7 +3,7 @@
package draw2d package draw2d
import ( import (
"freetype-go.googlecode.com/hg/freetype/raster" "code.google.com/p/freetype-go/freetype/raster"
"math" "math"
) )
@ -13,7 +13,7 @@ func SegmentArc(t LineTracer, x, y, rx, ry, start, angle, scale float64) {
if angle < 0 { if angle < 0 {
clockWise = false clockWise = false
} }
ra := (math.Fabs(rx) + math.Fabs(ry)) / 2 ra := (math.Abs(rx) + math.Abs(ry)) / 2
da := math.Acos(ra/(ra+0.125/scale)) * 2 da := math.Acos(ra/(ra+0.125/scale)) * 2
//normalize //normalize
if !clockWise { if !clockWise {

View file

@ -1,67 +1,67 @@
// Copyright 2010 The draw2d Authors. All rights reserved. // Copyright 2010 The draw2d Authors. All rights reserved.
// created: 17/05/2011 by Laurent Le Goff // created: 17/05/2011 by Laurent Le Goff
package curve package curve
import ( import (
"math" "math"
) )
const ( const (
CurveRecursionLimit = 32 CurveRecursionLimit = 32
) )
// X1, Y1, X2, Y2, X3, Y3, X4, Y4 float64 // X1, Y1, X2, Y2, X3, Y3, X4, Y4 float64
type CubicCurveFloat64 [8]float64 type CubicCurveFloat64 [8]float64
type LineTracer interface { type LineTracer interface {
LineTo(x, y float64) LineTo(x, y float64)
} }
func (c *CubicCurveFloat64) Subdivide(c1, c2 *CubicCurveFloat64) (x23, y23 float64) { func (c *CubicCurveFloat64) Subdivide(c1, c2 *CubicCurveFloat64) (x23, y23 float64) {
// Calculate all the mid-points of the line segments // Calculate all the mid-points of the line segments
//---------------------- //----------------------
c1[0], c1[1] = c[0], c[1] c1[0], c1[1] = c[0], c[1]
c2[6], c2[7] = c[6], c[7] c2[6], c2[7] = c[6], c[7]
c1[2] = (c[0] + c[2]) / 2 c1[2] = (c[0] + c[2]) / 2
c1[3] = (c[1] + c[3]) / 2 c1[3] = (c[1] + c[3]) / 2
x23 = (c[2] + c[4]) / 2 x23 = (c[2] + c[4]) / 2
y23 = (c[3] + c[5]) / 2 y23 = (c[3] + c[5]) / 2
c2[4] = (c[4] + c[6]) / 2 c2[4] = (c[4] + c[6]) / 2
c2[5] = (c[5] + c[7]) / 2 c2[5] = (c[5] + c[7]) / 2
c1[4] = (c1[2] + x23) / 2 c1[4] = (c1[2] + x23) / 2
c1[5] = (c1[3] + y23) / 2 c1[5] = (c1[3] + y23) / 2
c2[2] = (x23 + c2[4]) / 2 c2[2] = (x23 + c2[4]) / 2
c2[3] = (y23 + c2[5]) / 2 c2[3] = (y23 + c2[5]) / 2
c1[6] = (c1[4] + c2[2]) / 2 c1[6] = (c1[4] + c2[2]) / 2
c1[7] = (c1[5] + c2[3]) / 2 c1[7] = (c1[5] + c2[3]) / 2
c2[0], c2[1] = c1[6], c1[7] c2[0], c2[1] = c1[6], c1[7]
return return
} }
func (curve *CubicCurveFloat64) Segment(t LineTracer, flattening_threshold float64) { func (curve *CubicCurveFloat64) Segment(t LineTracer, flattening_threshold float64) {
var curves [CurveRecursionLimit]CubicCurveFloat64 var curves [CurveRecursionLimit]CubicCurveFloat64
curves[0] = *curve curves[0] = *curve
i := 0 i := 0
// current curve // current curve
var c *CubicCurveFloat64 var c *CubicCurveFloat64
var dx, dy, d2, d3 float64 var dx, dy, d2, d3 float64
for i >= 0 { for i >= 0 {
c = &curves[i] c = &curves[i]
dx = c[6] - c[0] dx = c[6] - c[0]
dy = c[7] - c[1] dy = c[7] - c[1]
d2 = math.Fabs(((c[2]-c[6])*dy - (c[3]-c[7])*dx)) d2 = math.Abs(((c[2]-c[6])*dy - (c[3]-c[7])*dx))
d3 = math.Fabs(((c[4]-c[6])*dy - (c[5]-c[7])*dx)) d3 = math.Abs(((c[4]-c[6])*dy - (c[5]-c[7])*dx))
if (d2+d3)*(d2+d3) < flattening_threshold*(dx*dx+dy*dy) || i == len(curves)-1 { if (d2+d3)*(d2+d3) < flattening_threshold*(dx*dx+dy*dy) || i == len(curves)-1 {
t.LineTo(c[6], c[7]) t.LineTo(c[6], c[7])
i-- i--
} else { } else {
// second half of bezier go lower onto the stack // second half of bezier go lower onto the stack
c.Subdivide(&curves[i+1], &curves[i]) c.Subdivide(&curves[i+1], &curves[i])
i++ i++
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1,94 +1,94 @@
package curve package curve
import ( import (
"testing" "bufio"
"log" "code.google.com/p/draw2d/draw2d/raster"
"fmt" "fmt"
"os" "image"
"bufio" "image/color"
"image" "image/draw"
"image/png" "image/png"
"image/draw" "log"
"draw2d.googlecode.com/hg/draw2d/raster" "os"
) "testing"
)
var ( var (
flattening_threshold float64 = 0.5 flattening_threshold float64 = 0.5
testsCubicFloat64 = []CubicCurveFloat64{ testsCubicFloat64 = []CubicCurveFloat64{
CubicCurveFloat64{100, 100, 200, 100, 100, 200, 200, 200}, CubicCurveFloat64{100, 100, 200, 100, 100, 200, 200, 200},
CubicCurveFloat64{100, 100, 300, 200, 200, 200, 300, 100}, CubicCurveFloat64{100, 100, 300, 200, 200, 200, 300, 100},
CubicCurveFloat64{100, 100, 0, 300, 200, 0, 300, 300}, CubicCurveFloat64{100, 100, 0, 300, 200, 0, 300, 300},
CubicCurveFloat64{150, 290, 10, 10, 290, 10, 150, 290}, CubicCurveFloat64{150, 290, 10, 10, 290, 10, 150, 290},
CubicCurveFloat64{10, 290, 10, 10, 290, 10, 290, 290}, CubicCurveFloat64{10, 290, 10, 10, 290, 10, 290, 290},
CubicCurveFloat64{100, 290, 290, 10, 10, 10, 200, 290}, CubicCurveFloat64{100, 290, 290, 10, 10, 10, 200, 290},
} }
testsQuadFloat64 = []QuadCurveFloat64{ testsQuadFloat64 = []QuadCurveFloat64{
QuadCurveFloat64{100, 100, 200, 100, 200, 200}, QuadCurveFloat64{100, 100, 200, 100, 200, 200},
QuadCurveFloat64{100, 100, 290, 200, 290, 100}, QuadCurveFloat64{100, 100, 290, 200, 290, 100},
QuadCurveFloat64{100, 100, 0, 290, 200, 290}, QuadCurveFloat64{100, 100, 0, 290, 200, 290},
QuadCurveFloat64{150, 290, 10, 10, 290, 290}, QuadCurveFloat64{150, 290, 10, 10, 290, 290},
QuadCurveFloat64{10, 290, 10, 10, 290, 290}, QuadCurveFloat64{10, 290, 10, 10, 290, 290},
QuadCurveFloat64{100, 290, 290, 10, 120, 290}, QuadCurveFloat64{100, 290, 290, 10, 120, 290},
} }
) )
type Path struct { type Path struct {
points []float64 points []float64
} }
func (p *Path) LineTo(x, y float64) { func (p *Path) LineTo(x, y float64) {
if len(p.points)+2 > cap(p.points) { if len(p.points)+2 > cap(p.points) {
points := make([]float64, len(p.points)+2, len(p.points)+32) points := make([]float64, len(p.points)+2, len(p.points)+32)
copy(points, p.points) copy(points, p.points)
p.points = points p.points = points
} else { } else {
p.points = p.points[0 : len(p.points)+2] p.points = p.points[0 : len(p.points)+2]
} }
p.points[len(p.points)-2] = x p.points[len(p.points)-2] = x
p.points[len(p.points)-1] = y p.points[len(p.points)-1] = y
} }
func init() { func init() {
f, err := os.Create("_test.html") f, err := os.Create("_test.html")
if err != nil { if err != nil {
log.Println(err) log.Println(err)
os.Exit(1) os.Exit(1)
} }
defer f.Close() defer f.Close()
log.Printf("Create html viewer") log.Printf("Create html viewer")
f.Write([]byte("<html><body>")) f.Write([]byte("<html><body>"))
for i := 0; i < len(testsCubicFloat64); i++ { for i := 0; i < len(testsCubicFloat64); i++ {
f.Write([]byte(fmt.Sprintf("<div><img src='_testRec%d.png'/>\n<img src='_test%d.png'/>\n<img src='_testAdaptiveRec%d.png'/>\n<img src='_testAdaptive%d.png'/>\n<img src='_testParabolic%d.png'/>\n</div>\n", i, i, i, i, i))) f.Write([]byte(fmt.Sprintf("<div><img src='_testRec%d.png'/>\n<img src='_test%d.png'/>\n<img src='_testAdaptiveRec%d.png'/>\n<img src='_testAdaptive%d.png'/>\n<img src='_testParabolic%d.png'/>\n</div>\n", i, i, i, i, i)))
} }
for i := 0; i < len(testsQuadFloat64); i++ { for i := 0; i < len(testsQuadFloat64); i++ {
f.Write([]byte(fmt.Sprintf("<div><img src='_testQuad%d.png'/>\n</div>\n", i))) f.Write([]byte(fmt.Sprintf("<div><img src='_testQuad%d.png'/>\n</div>\n", i)))
} }
f.Write([]byte("</body></html>")) f.Write([]byte("</body></html>"))
} }
func savepng(filePath string, m image.Image) { func savepng(filePath string, m image.Image) {
f, err := os.Create(filePath) f, err := os.Create(filePath)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
os.Exit(1) os.Exit(1)
} }
defer f.Close() defer f.Close()
b := bufio.NewWriter(f) b := bufio.NewWriter(f)
err = png.Encode(b, m) err = png.Encode(b, m)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
os.Exit(1) os.Exit(1)
} }
err = b.Flush() err = b.Flush()
if err != nil { if err != nil {
log.Println(err) log.Println(err)
os.Exit(1) os.Exit(1)
} }
} }
func drawPoints(img draw.Image, c image.Color, s ...float64) image.Image { func drawPoints(img draw.Image, c color.Color, s ...float64) image.Image {
/*for i := 0; i < len(s); i += 2 { /*for i := 0; i < len(s); i += 2 {
x, y := int(s[i]+0.5), int(s[i+1]+0.5) x, y := int(s[i]+0.5), int(s[i+1]+0.5)
img.Set(x, y, c) img.Set(x, y, c)
@ -100,164 +100,163 @@ func drawPoints(img draw.Image, c image.Color, s ...float64) image.Image {
img.Set(x-1, y, c) img.Set(x-1, y, c)
img.Set(x-1, y+1, c) img.Set(x-1, y+1, c)
img.Set(x-1, y-1, c) img.Set(x-1, y-1, c)
}*/ }*/
return img return img
} }
func TestCubicCurveRec(t *testing.T) { func TestCubicCurveRec(t *testing.T) {
for i, curve := range testsCubicFloat64 { for i, curve := range testsCubicFloat64 {
var p Path var p Path
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.SegmentRec(&p, flattening_threshold) curve.SegmentRec(&p, flattening_threshold)
img := image.NewNRGBA(300, 300) img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve[:]...) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...)
raster.PolylineBresenham(img, image.Black, p.points...) raster.PolylineBresenham(img, image.Black, p.points...)
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...) //drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, p.points...) drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
savepng(fmt.Sprintf("_testRec%d.png", i), img) savepng(fmt.Sprintf("_testRec%d.png", i), img)
log.Printf("Num of points: %d\n", len(p.points)) log.Printf("Num of points: %d\n", len(p.points))
} }
fmt.Println() fmt.Println()
} }
func TestCubicCurve(t *testing.T) { func TestCubicCurve(t *testing.T) {
for i, curve := range testsCubicFloat64 { for i, curve := range testsCubicFloat64 {
var p Path var p Path
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.Segment(&p, flattening_threshold) curve.Segment(&p, flattening_threshold)
img := image.NewNRGBA(300, 300) img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve[:]...) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...)
raster.PolylineBresenham(img, image.Black, p.points...) raster.PolylineBresenham(img, image.Black, p.points...)
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...) //drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, p.points...) drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
savepng(fmt.Sprintf("_test%d.png", i), img) savepng(fmt.Sprintf("_test%d.png", i), img)
log.Printf("Num of points: %d\n", len(p.points)) log.Printf("Num of points: %d\n", len(p.points))
} }
fmt.Println() fmt.Println()
} }
func TestCubicCurveAdaptiveRec(t *testing.T) { func TestCubicCurveAdaptiveRec(t *testing.T) {
for i, curve := range testsCubicFloat64 { for i, curve := range testsCubicFloat64 {
var p Path var p Path
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.AdaptiveSegmentRec(&p, 1, 0, 0) curve.AdaptiveSegmentRec(&p, 1, 0, 0)
img := image.NewNRGBA(300, 300) img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve[:]...) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...)
raster.PolylineBresenham(img, image.Black, p.points...) raster.PolylineBresenham(img, image.Black, p.points...)
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...) //drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, p.points...) drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
savepng(fmt.Sprintf("_testAdaptiveRec%d.png", i), img) savepng(fmt.Sprintf("_testAdaptiveRec%d.png", i), img)
log.Printf("Num of points: %d\n", len(p.points)) log.Printf("Num of points: %d\n", len(p.points))
} }
fmt.Println() fmt.Println()
} }
func TestCubicCurveAdaptive(t *testing.T) { func TestCubicCurveAdaptive(t *testing.T) {
for i, curve := range testsCubicFloat64 { for i, curve := range testsCubicFloat64 {
var p Path var p Path
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.AdaptiveSegment(&p, 1, 0, 0) curve.AdaptiveSegment(&p, 1, 0, 0)
img := image.NewNRGBA(300, 300) img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve[:]...) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...)
raster.PolylineBresenham(img, image.Black, p.points...) raster.PolylineBresenham(img, image.Black, p.points...)
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...) //drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, p.points...) drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
savepng(fmt.Sprintf("_testAdaptive%d.png", i), img) savepng(fmt.Sprintf("_testAdaptive%d.png", i), img)
log.Printf("Num of points: %d\n", len(p.points)) log.Printf("Num of points: %d\n", len(p.points))
} }
fmt.Println() fmt.Println()
} }
func TestCubicCurveParabolic(t *testing.T) { func TestCubicCurveParabolic(t *testing.T) {
for i, curve := range testsCubicFloat64 { for i, curve := range testsCubicFloat64 {
var p Path var p Path
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.ParabolicSegment(&p, flattening_threshold) curve.ParabolicSegment(&p, flattening_threshold)
img := image.NewNRGBA(300, 300) img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve[:]...) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...)
raster.PolylineBresenham(img, image.Black, p.points...) raster.PolylineBresenham(img, image.Black, p.points...)
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...) //drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, p.points...) drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
savepng(fmt.Sprintf("_testParabolic%d.png", i), img) savepng(fmt.Sprintf("_testParabolic%d.png", i), img)
log.Printf("Num of points: %d\n", len(p.points)) log.Printf("Num of points: %d\n", len(p.points))
} }
fmt.Println() fmt.Println()
} }
func TestQuadCurve(t *testing.T) {
func TestQuadCurve(t *testing.T) { for i, curve := range testsQuadFloat64 {
for i, curve := range testsQuadFloat64 { var p Path
var p Path p.LineTo(curve[0], curve[1])
p.LineTo(curve[0], curve[1]) curve.Segment(&p, flattening_threshold)
curve.Segment(&p, flattening_threshold) img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
img := image.NewNRGBA(300, 300) raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...)
raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve[:]...) raster.PolylineBresenham(img, image.Black, p.points...)
raster.PolylineBresenham(img, image.Black, p.points...)
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...) //drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, p.points...) drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
savepng(fmt.Sprintf("_testQuad%d.png", i), img) savepng(fmt.Sprintf("_testQuad%d.png", i), img)
log.Printf("Num of points: %d\n", len(p.points)) log.Printf("Num of points: %d\n", len(p.points))
} }
fmt.Println() fmt.Println()
} }
func BenchmarkCubicCurveRec(b *testing.B) { func BenchmarkCubicCurveRec(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, curve := range testsCubicFloat64 { for _, curve := range testsCubicFloat64 {
p := Path{make([]float64, 0, 32)} p := Path{make([]float64, 0, 32)}
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.SegmentRec(&p, flattening_threshold) curve.SegmentRec(&p, flattening_threshold)
} }
} }
} }
func BenchmarkCubicCurve(b *testing.B) { func BenchmarkCubicCurve(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, curve := range testsCubicFloat64 { for _, curve := range testsCubicFloat64 {
p := Path{make([]float64, 0, 32)} p := Path{make([]float64, 0, 32)}
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.Segment(&p, flattening_threshold) curve.Segment(&p, flattening_threshold)
} }
} }
} }
func BenchmarkCubicCurveAdaptiveRec(b *testing.B) { func BenchmarkCubicCurveAdaptiveRec(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, curve := range testsCubicFloat64 { for _, curve := range testsCubicFloat64 {
p := Path{make([]float64, 0, 32)} p := Path{make([]float64, 0, 32)}
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.AdaptiveSegmentRec(&p, 1, 0, 0) curve.AdaptiveSegmentRec(&p, 1, 0, 0)
} }
} }
} }
func BenchmarkCubicCurveAdaptive(b *testing.B) { func BenchmarkCubicCurveAdaptive(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, curve := range testsCubicFloat64 { for _, curve := range testsCubicFloat64 {
p := Path{make([]float64, 0, 32)} p := Path{make([]float64, 0, 32)}
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.AdaptiveSegment(&p, 1, 0, 0) curve.AdaptiveSegment(&p, 1, 0, 0)
} }
} }
} }
func BenchmarkCubicCurveParabolic(b *testing.B) { func BenchmarkCubicCurveParabolic(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, curve := range testsCubicFloat64 { for _, curve := range testsCubicFloat64 {
p := Path{make([]float64, 0, 32)} p := Path{make([]float64, 0, 32)}
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.ParabolicSegment(&p, flattening_threshold) curve.ParabolicSegment(&p, flattening_threshold)
} }
} }
} }
func BenchmarkQuadCurve(b *testing.B) { func BenchmarkQuadCurve(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, curve := range testsQuadFloat64 { for _, curve := range testsQuadFloat64 {
p := Path{make([]float64, 0, 32)} p := Path{make([]float64, 0, 32)}
p.LineTo(curve[0], curve[1]) p.LineTo(curve[0], curve[1])
curve.Segment(&p, flattening_threshold) curve.Segment(&p, flattening_threshold)
} }
} }
} }

View file

@ -1,53 +1,51 @@
// Copyright 2010 The draw2d Authors. All rights reserved. // Copyright 2010 The draw2d Authors. All rights reserved.
// created: 17/05/2011 by Laurent Le Goff // created: 17/05/2011 by Laurent Le Goff
package curve package curve
import ( import (
"math" "math"
) )
//X1, Y1, X2, Y2, X3, Y3 float64 //X1, Y1, X2, Y2, X3, Y3 float64
type QuadCurveFloat64 [6]float64 type QuadCurveFloat64 [6]float64
func (c *QuadCurveFloat64) Subdivide(c1, c2 *QuadCurveFloat64) {
func (c *QuadCurveFloat64) Subdivide(c1, c2 *QuadCurveFloat64) {
// Calculate all the mid-points of the line segments // Calculate all the mid-points of the line segments
//---------------------- //----------------------
c1[0], c1[1] = c[0], c[1] c1[0], c1[1] = c[0], c[1]
c2[4], c2[5] = c[4], c[5] c2[4], c2[5] = c[4], c[5]
c1[2] = (c[0] + c[2]) / 2 c1[2] = (c[0] + c[2]) / 2
c1[3] = (c[1] + c[3]) / 2 c1[3] = (c[1] + c[3]) / 2
c2[2] = (c[2] + c[4]) / 2 c2[2] = (c[2] + c[4]) / 2
c2[3] = (c[3] + c[5]) / 2 c2[3] = (c[3] + c[5]) / 2
c1[4] = (c1[2] + c2[2]) / 2 c1[4] = (c1[2] + c2[2]) / 2
c1[5] = (c1[3] + c2[3]) / 2 c1[5] = (c1[3] + c2[3]) / 2
c2[0], c2[1] = c1[4], c1[5] c2[0], c2[1] = c1[4], c1[5]
return return
} }
func (curve *QuadCurveFloat64) Segment(t LineTracer, flattening_threshold float64) {
func (curve *QuadCurveFloat64) Segment(t LineTracer, flattening_threshold float64) { var curves [CurveRecursionLimit]QuadCurveFloat64
var curves [CurveRecursionLimit]QuadCurveFloat64 curves[0] = *curve
curves[0] = *curve i := 0
i := 0
// current curve // current curve
var c *QuadCurveFloat64 var c *QuadCurveFloat64
var dx, dy, d float64 var dx, dy, d float64
for i >= 0 { for i >= 0 {
c = &curves[i] c = &curves[i]
dx = c[4] - c[0] dx = c[4] - c[0]
dy = c[5] - c[1] dy = c[5] - c[1]
d = math.Fabs(((c[2]-c[4])*dy - (c[3]-c[5])*dx)) d = math.Abs(((c[2]-c[4])*dy - (c[3]-c[5])*dx))
if (d*d) < flattening_threshold*(dx*dx+dy*dy) || i == len(curves)-1 { if (d*d) < flattening_threshold*(dx*dx+dy*dy) || i == len(curves)-1 {
t.LineTo(c[4], c[5]) t.LineTo(c[4], c[5])
i-- i--
} else { } else {
// second half of bezier go lower onto the stack // second half of bezier go lower onto the stack
c.Subdivide(&curves[i+1], &curves[i]) c.Subdivide(&curves[i+1], &curves[i])
i++ i++
} }
} }
} }

View file

@ -39,7 +39,6 @@ func cubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4, approximatio
recursiveCubicBezier(v, x1, y1, x2, y2, x3, y3, x4, y4, 0, distanceToleranceSquare, angleTolerance, cuspLimit) recursiveCubicBezier(v, x1, y1, x2, y2, x3, y3, x4, y4, 0, distanceToleranceSquare, angleTolerance, cuspLimit)
} }
/* /*
* see cubicBezier comments for approximationScale and angleTolerance definition * see cubicBezier comments for approximationScale and angleTolerance definition
*/ */
@ -50,7 +49,6 @@ func quadraticBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, approximationSca
recursiveQuadraticBezierBezier(v, x1, y1, x2, y2, x3, y3, 0, distanceToleranceSquare, angleTolerance) recursiveQuadraticBezierBezier(v, x1, y1, x2, y2, x3, y3, 0, distanceToleranceSquare, angleTolerance)
} }
func computeCuspLimit(v float64) (r float64) { func computeCuspLimit(v float64) (r float64) {
if v == 0.0 { if v == 0.0 {
r = 0.0 r = 0.0
@ -60,7 +58,6 @@ func computeCuspLimit(v float64) (r float64) {
return return
} }
/** /**
* http://www.antigrain.com/research/adaptive_bezier/index.html * http://www.antigrain.com/research/adaptive_bezier/index.html
*/ */
@ -80,7 +77,7 @@ func recursiveQuadraticBezierBezier(v VertexConverter, x1, y1, x2, y2, x3, y3 fl
dx := x3 - x1 dx := x3 - x1
dy := y3 - y1 dy := y3 - y1
d := math.Fabs(((x2-x3)*dy - (y2-y3)*dx)) d := math.Abs(((x2-x3)*dy - (y2-y3)*dx))
if d > CurveCollinearityEpsilon { if d > CurveCollinearityEpsilon {
// Regular case // Regular case
@ -96,7 +93,7 @@ func recursiveQuadraticBezierBezier(v VertexConverter, x1, y1, x2, y2, x3, y3 fl
// Angle & Cusp Condition // Angle & Cusp Condition
//---------------------- //----------------------
da := math.Fabs(math.Atan2(y3-y2, x3-x2) - math.Atan2(y2-y1, x2-x1)) da := math.Abs(math.Atan2(y3-y2, x3-x2) - math.Atan2(y2-y1, x2-x1))
if da >= math.Pi { if da >= math.Pi {
da = 2*math.Pi - da da = 2*math.Pi - da
} }
@ -169,8 +166,8 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
dx := x4 - x1 dx := x4 - x1
dy := y4 - y1 dy := y4 - y1
d2 := math.Fabs(((x2-x4)*dy - (y2-y4)*dx)) d2 := math.Abs(((x2-x4)*dy - (y2-y4)*dx))
d3 := math.Fabs(((x3-x4)*dy - (y3-y4)*dx)) d3 := math.Abs(((x3-x4)*dy - (y3-y4)*dx))
switch { switch {
case d2 <= CurveCollinearityEpsilon && d3 <= CurveCollinearityEpsilon: case d2 <= CurveCollinearityEpsilon && d3 <= CurveCollinearityEpsilon:
@ -233,7 +230,7 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
// Angle Condition // Angle Condition
//---------------------- //----------------------
da1 := math.Fabs(math.Atan2(y4-y3, x4-x3) - math.Atan2(y3-y2, x3-x2)) da1 := math.Abs(math.Atan2(y4-y3, x4-x3) - math.Atan2(y3-y2, x3-x2))
if da1 >= math.Pi { if da1 >= math.Pi {
da1 = 2*math.Pi - da1 da1 = 2*math.Pi - da1
} }
@ -264,7 +261,7 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
// Angle Condition // Angle Condition
//---------------------- //----------------------
da1 := math.Fabs(math.Atan2(y3-y2, x3-x2) - math.Atan2(y2-y1, x2-x1)) da1 := math.Abs(math.Atan2(y3-y2, x3-x2) - math.Atan2(y2-y1, x2-x1))
if da1 >= math.Pi { if da1 >= math.Pi {
da1 = 2*math.Pi - da1 da1 = 2*math.Pi - da1
} }
@ -299,8 +296,8 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
// Angle & Cusp Condition // Angle & Cusp Condition
//---------------------- //----------------------
k := math.Atan2(y3-y2, x3-x2) k := math.Atan2(y3-y2, x3-x2)
da1 := math.Fabs(k - math.Atan2(y2-y1, x2-x1)) da1 := math.Abs(k - math.Atan2(y2-y1, x2-x1))
da2 := math.Fabs(math.Atan2(y4-y3, x4-x3) - k) da2 := math.Abs(math.Atan2(y4-y3, x4-x3) - k)
if da1 >= math.Pi { if da1 >= math.Pi {
da1 = 2*math.Pi - da1 da1 = 2*math.Pi - da1
} }

View file

@ -2,22 +2,19 @@
// created: 13/12/2010 by Laurent Le Goff // created: 13/12/2010 by Laurent Le Goff
package draw2d package draw2d
import ( import (
"freetype-go.googlecode.com/hg/freetype" "code.google.com/p/freetype-go/freetype"
"freetype-go.googlecode.com/hg/freetype/truetype" "code.google.com/p/freetype-go/freetype/truetype"
"path"
"log"
"io/ioutil" "io/ioutil"
"log"
"path"
) )
var ( var (
fontFolder = "../resource/font/" fontFolder = "../resource/font/"
fonts = make(map[string]*truetype.Font) fonts = make(map[string]*truetype.Font)
) )
type FontStyle byte type FontStyle byte
const ( const (
@ -34,14 +31,12 @@ const (
FontFamilyMono FontFamilyMono
) )
type FontData struct { type FontData struct {
Name string Name string
Family FontFamily Family FontFamily
Style FontStyle Style FontStyle
} }
func GetFont(fontData FontData) *truetype.Font { func GetFont(fontData FontData) *truetype.Font {
fontFileName := fontData.Name fontFileName := fontData.Name
switch fontData.Family { switch fontData.Family {

View file

@ -4,6 +4,7 @@ package draw2d
import ( import (
"image" "image"
"image/color"
) )
type FillRule int type FillRule int
@ -22,8 +23,8 @@ type GraphicContext interface {
Rotate(angle float64) Rotate(angle float64)
Translate(tx, ty float64) Translate(tx, ty float64)
Scale(sx, sy float64) Scale(sx, sy float64)
SetStrokeColor(c image.Color) SetStrokeColor(c color.Color)
SetFillColor(c image.Color) SetFillColor(c color.Color)
SetFillRule(f FillRule) SetFillRule(f FillRule)
SetLineWidth(lineWidth float64) SetLineWidth(lineWidth float64)
SetLineCap(cap Cap) SetLineCap(cap Cap)

View file

@ -3,16 +3,17 @@
package draw2d package draw2d
import ( import (
"image/draw" "code.google.com/p/freetype-go/freetype"
"code.google.com/p/freetype-go/freetype/raster"
"image" "image"
"image/color"
"image/draw"
"log" "log"
"freetype-go.googlecode.com/hg/freetype"
"freetype-go.googlecode.com/hg/freetype/raster"
) )
type Painter interface { type Painter interface {
raster.Painter raster.Painter
SetColor(color image.Color) SetColor(color color.Color)
} }
var ( var (
@ -60,7 +61,6 @@ func NewGraphicContext(img draw.Image) *ImageGraphicContext {
return gc return gc
} }
func (gc *ImageGraphicContext) SetDPI(dpi int) { func (gc *ImageGraphicContext) SetDPI(dpi int) {
gc.DPI = dpi gc.DPI = dpi
gc.freetype.SetDPI(dpi) gc.freetype.SetDPI(dpi)
@ -76,7 +76,7 @@ func (gc *ImageGraphicContext) Clear() {
} }
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.NewUniform(gc.Current.FillColor)
draw.Draw(gc.img, image.Rect(x1, y1, x2, y2), imageColor, image.ZP, draw.Over) draw.Draw(gc.img, image.Rect(x1, y1, x2, y2), imageColor, image.ZP, draw.Over)
} }
@ -85,7 +85,7 @@ func (gc *ImageGraphicContext) DrawImage(img image.Image) {
} }
func (gc *ImageGraphicContext) FillString(text string) (cursor float64) { func (gc *ImageGraphicContext) FillString(text string) (cursor float64) {
gc.freetype.SetSrc(image.NewColorImage(gc.Current.StrokeColor)) gc.freetype.SetSrc(image.NewUniform(gc.Current.StrokeColor))
// Draw the text. // Draw the text.
x, y := gc.Current.Path.LastPoint() x, y := gc.Current.Path.LastPoint()
gc.Current.Tr.Transform(&x, &y) gc.Current.Tr.Transform(&x, &y)
@ -112,8 +112,7 @@ func (gc *ImageGraphicContext) FillString(text string) (cursor float64) {
return width return width
} }
func (gc *ImageGraphicContext) paint(rasterizer *raster.Rasterizer, color color.Color) {
func (gc *ImageGraphicContext) paint(rasterizer *raster.Rasterizer, color image.Color) {
gc.painter.SetColor(color) gc.painter.SetColor(color)
rasterizer.Rasterize(gc.painter) rasterizer.Rasterize(gc.painter)
rasterizer.Clear() rasterizer.Clear()
@ -173,7 +172,6 @@ func (gc *ImageGraphicContext) FillStroke(paths ...*PathStorage) {
gc.paint(gc.strokeRasterizer, gc.Current.StrokeColor) gc.paint(gc.strokeRasterizer, gc.Current.StrokeColor)
} }
func (f FillRule) UseNonZeroWinding() bool { func (f FillRule) UseNonZeroWinding() bool {
switch f { switch f {
case FillRuleEvenOdd: case FillRuleEvenOdd:

View file

@ -2,12 +2,10 @@
// created: 13/12/2010 by Laurent Le Goff // created: 13/12/2010 by Laurent Le Goff
package draw2d package draw2d
import ( import (
"freetype-go.googlecode.com/hg/freetype/raster" "code.google.com/p/freetype-go/freetype/raster"
) )
type VertexAdder struct { type VertexAdder struct {
command VertexCommand command VertexCommand
adder raster.Adder adder raster.Adder
@ -31,7 +29,6 @@ func (vertexAdder *VertexAdder) Vertex(x, y float64) {
vertexAdder.command = VertexNoCommand vertexAdder.command = VertexNoCommand
} }
type PathAdder struct { type PathAdder struct {
adder raster.Adder adder raster.Adder
firstPoint raster.Point firstPoint raster.Point
@ -42,7 +39,6 @@ func NewPathAdder(adder raster.Adder) *PathAdder {
return &PathAdder{adder, raster.Point{0, 0}, 1} return &PathAdder{adder, raster.Point{0, 0}, 1}
} }
func (pathAdder *PathAdder) Convert(paths ...*PathStorage) { func (pathAdder *PathAdder) Convert(paths ...*PathStorage) {
for _, path := range paths { for _, path := range paths {
j := 0 j := 0

View file

@ -4,6 +4,7 @@ package raster
import ( import (
"image" "image"
"image/color"
"unsafe" "unsafe"
) )
@ -87,7 +88,7 @@ func intersect(r1, r2 [4]float64) [4]float64 {
return r1 return r1
} }
func (r *Rasterizer8BitsSample) RenderEvenOdd(img *image.RGBA, color *image.RGBAColor, polygon *Polygon, tr [6]float64) { func (r *Rasterizer8BitsSample) RenderEvenOdd(img *image.RGBA, color *color.RGBA, polygon *Polygon, tr [6]float64) {
// memset 0 the mask buffer // memset 0 the mask buffer
r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height) r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height)
@ -169,7 +170,7 @@ func (r *Rasterizer8BitsSample) addNonZeroEdge(edge *PolygonEdge) {
} }
// Renders the mask to the canvas with even-odd fill. // Renders the mask to the canvas with even-odd fill.
func (r *Rasterizer8BitsSample) fillEvenOdd(img *image.RGBA, color *image.RGBAColor, clipBound [4]float64) { func (r *Rasterizer8BitsSample) fillEvenOdd(img *image.RGBA, color *color.RGBA, clipBound [4]float64) {
var x, y uint32 var x, y uint32
minX := uint32(clipBound[0]) minX := uint32(clipBound[0])
@ -221,7 +222,7 @@ func (r *Rasterizer8BitsSample) fillEvenOdd(img *image.RGBA, color *image.RGBACo
* param aColor the color to be used for rendering. * param aColor the color to be used for rendering.
* param aTransformation the transformation matrix. * param aTransformation the transformation matrix.
*/ */
func (r *Rasterizer8BitsSample) RenderNonZeroWinding(img *image.RGBA, color *image.RGBAColor, polygon *Polygon, tr [6]float64) { func (r *Rasterizer8BitsSample) RenderNonZeroWinding(img *image.RGBA, color *color.RGBA, polygon *Polygon, tr [6]float64) {
r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height) r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height)
r.WindingBuffer = make([]NON_ZERO_MASK_DATA_UNIT, r.BufferWidth*r.Height*SUBPIXEL_COUNT) r.WindingBuffer = make([]NON_ZERO_MASK_DATA_UNIT, r.BufferWidth*r.Height*SUBPIXEL_COUNT)
@ -253,9 +254,8 @@ func (r *Rasterizer8BitsSample) RenderNonZeroWinding(img *image.RGBA, color *ima
r.fillNonZero(img, color, clipRect) r.fillNonZero(img, color, clipRect)
} }
//! Renders the mask to the canvas with non-zero winding fill. //! Renders the mask to the canvas with non-zero winding fill.
func (r *Rasterizer8BitsSample) fillNonZero(img *image.RGBA, color *image.RGBAColor, clipBound [4]float64) { func (r *Rasterizer8BitsSample) fillNonZero(img *image.RGBA, color *color.RGBA, clipBound [4]float64) {
var x, y uint32 var x, y uint32
minX := uint32(clipBound[0]) minX := uint32(clipBound[0])

View file

@ -4,6 +4,7 @@ package raster
import ( import (
"image" "image"
"image/color"
"unsafe" "unsafe"
) )
@ -87,7 +88,7 @@ func intersect(r1, r2 [4]float64) [4]float64 {
return r1 return r1
} }
func (r *Rasterizer8BitsSample) RenderEvenOdd(img *image.RGBA, color *image.RGBAColor, polygon *Polygon, tr [6]float64) { func (r *Rasterizer8BitsSample) RenderEvenOdd(img *image.RGBA, color *color.RGBA, polygon *Polygon, tr [6]float64) {
// memset 0 the mask buffer // memset 0 the mask buffer
r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height) r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height)
@ -134,7 +135,7 @@ func (r *Rasterizer8BitsSample) addEvenOddEdge(edge *PolygonEdge) {
} }
// Renders the mask to the canvas with even-odd fill. // Renders the mask to the canvas with even-odd fill.
func (r *Rasterizer8BitsSample) fillEvenOdd(img *image.RGBA, color *image.RGBAColor, clipBound [4]float64) { func (r *Rasterizer8BitsSample) fillEvenOdd(img *image.RGBA, color *color.RGBA, clipBound [4]float64) {
var x, y uint32 var x, y uint32
minX := uint32(clipBound[0]) minX := uint32(clipBound[0])
@ -186,7 +187,7 @@ func (r *Rasterizer8BitsSample) fillEvenOdd(img *image.RGBA, color *image.RGBACo
* param aColor the color to be used for rendering. * param aColor the color to be used for rendering.
* param aTransformation the transformation matrix. * param aTransformation the transformation matrix.
*/ */
func (r *Rasterizer8BitsSample) RenderNonZeroWinding(img *image.RGBA, color *image.RGBAColor, polygon *Polygon, tr [6]float64) { func (r *Rasterizer8BitsSample) RenderNonZeroWinding(img *image.RGBA, color *color.RGBA, polygon *Polygon, tr [6]float64) {
r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height) r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height)
r.WindingBuffer = make([]NON_ZERO_MASK_DATA_UNIT, r.BufferWidth*r.Height*SUBPIXEL_COUNT) r.WindingBuffer = make([]NON_ZERO_MASK_DATA_UNIT, r.BufferWidth*r.Height*SUBPIXEL_COUNT)
@ -237,7 +238,7 @@ func (r *Rasterizer8BitsSample) addNonZeroEdge(edge *PolygonEdge) {
} }
//! Renders the mask to the canvas with non-zero winding fill. //! Renders the mask to the canvas with non-zero winding fill.
func (r *Rasterizer8BitsSample) fillNonZero(img *image.RGBA, color *image.RGBAColor, clipBound [4]float64) { func (r *Rasterizer8BitsSample) fillNonZero(img *image.RGBA, color *color.RGBA, clipBound [4]float64) {
var x, y uint32 var x, y uint32
minX := uint32(clipBound[0]) minX := uint32(clipBound[0])

View file

@ -4,6 +4,7 @@ package raster
import ( import (
"image" "image"
"image/color"
"unsafe" "unsafe"
) )
@ -87,7 +88,7 @@ func intersect(r1, r2 [4]float64) [4]float64 {
return r1 return r1
} }
func (r *Rasterizer8BitsSample) RenderEvenOdd(img *image.RGBA, color *image.RGBAColor, polygon *Polygon, tr [6]float64) { func (r *Rasterizer8BitsSample) RenderEvenOdd(img *image.RGBA, color *color.RGBA, polygon *Polygon, tr [6]float64) {
// memset 0 the mask buffer // memset 0 the mask buffer
r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height) r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height)
@ -169,7 +170,7 @@ func (r *Rasterizer8BitsSample) addNonZeroEdge(edge *PolygonEdge) {
} }
// Renders the mask to the canvas with even-odd fill. // Renders the mask to the canvas with even-odd fill.
func (r *Rasterizer8BitsSample) fillEvenOdd(img *image.RGBA, color *image.RGBAColor, clipBound [4]float64) { func (r *Rasterizer8BitsSample) fillEvenOdd(img *image.RGBA, color *color.RGBA, clipBound [4]float64) {
var x, y uint32 var x, y uint32
minX := uint32(clipBound[0]) minX := uint32(clipBound[0])
@ -221,7 +222,7 @@ func (r *Rasterizer8BitsSample) fillEvenOdd(img *image.RGBA, color *image.RGBACo
* param aColor the color to be used for rendering. * param aColor the color to be used for rendering.
* param aTransformation the transformation matrix. * param aTransformation the transformation matrix.
*/ */
func (r *Rasterizer8BitsSample) RenderNonZeroWinding(img *image.RGBA, color *image.RGBAColor, polygon *Polygon, tr [6]float64) { func (r *Rasterizer8BitsSample) RenderNonZeroWinding(img *image.RGBA, color *color.RGBA, polygon *Polygon, tr [6]float64) {
r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height) r.MaskBuffer = make([]SUBPIXEL_DATA, r.BufferWidth*r.Height)
r.WindingBuffer = make([]NON_ZERO_MASK_DATA_UNIT, r.BufferWidth*r.Height*SUBPIXEL_COUNT) r.WindingBuffer = make([]NON_ZERO_MASK_DATA_UNIT, r.BufferWidth*r.Height*SUBPIXEL_COUNT)
@ -253,9 +254,8 @@ func (r *Rasterizer8BitsSample) RenderNonZeroWinding(img *image.RGBA, color *ima
r.fillNonZero(img, color, clipRect) r.fillNonZero(img, color, clipRect)
} }
//! Renders the mask to the canvas with non-zero winding fill. //! Renders the mask to the canvas with non-zero winding fill.
func (r *Rasterizer8BitsSample) fillNonZero(img *image.RGBA, color *image.RGBAColor, clipBound [4]float64) { func (r *Rasterizer8BitsSample) fillNonZero(img *image.RGBA, color *color.RGBA, clipBound [4]float64) {
var x, y uint32 var x, y uint32
minX := uint32(clipBound[0]) minX := uint32(clipBound[0])

View file

@ -3,8 +3,8 @@
package raster package raster
import ( import (
"image/color"
"image/draw" "image/draw"
"image"
) )
func abs(i int) int { func abs(i int) int {
@ -14,13 +14,13 @@ func abs(i int) int {
return i return i
} }
func PolylineBresenham(img draw.Image, c image.Color, s ...float64) { func PolylineBresenham(img draw.Image, c color.Color, s ...float64) {
for i := 2; i < len(s); i += 2 { for i := 2; i < len(s); i += 2 {
Bresenham(img, c, int(s[i-2]+0.5), int(s[i-1]+0.5), int(s[i]+0.5), int(s[i+1]+0.5)) Bresenham(img, c, int(s[i-2]+0.5), int(s[i-1]+0.5), int(s[i]+0.5), int(s[i+1]+0.5))
} }
} }
func Bresenham(img draw.Image, color image.Color, x0, y0, x1, y1 int) { func Bresenham(img draw.Image, color color.Color, x0, y0, x1, y1 int) {
dx := abs(x1 - x0) dx := abs(x1 - x0)
dy := abs(y1 - y0) dy := abs(y1 - y0)
var sx, sy int var sx, sy int

View file

@ -1,14 +1,15 @@
package raster package raster
import ( import (
"testing"
"log"
"image"
"os"
"bufio" "bufio"
"code.google.com/p/draw2d/draw2d/curve"
"code.google.com/p/freetype-go/freetype/raster"
"image"
"image/color"
"image/png" "image/png"
"draw2d.googlecode.com/hg/draw2d/curve" "log"
"freetype-go.googlecode.com/hg/freetype/raster" "os"
"testing"
) )
var flattening_threshold float64 = 0.5 var flattening_threshold float64 = 0.5
@ -55,9 +56,9 @@ func TestFreetype(t *testing.T) {
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
c.Segment(&p, flattening_threshold) c.Segment(&p, flattening_threshold)
poly := Polygon(p.points) poly := Polygon(p.points)
color := image.RGBAColor{0, 0, 0, 0xff} color := color.RGBA{0, 0, 0, 0xff}
img := image.NewRGBA(200, 200) img := image.NewRGBA(image.Rect(0, 0, 200, 200))
rasterizer := raster.NewRasterizer(200, 200) rasterizer := raster.NewRasterizer(200, 200)
rasterizer.UseNonZeroWinding = false rasterizer.UseNonZeroWinding = false
rasterizer.Start(raster.Point{raster.Fix32(10 * 256), raster.Fix32(190 * 256)}) rasterizer.Start(raster.Point{raster.Fix32(10 * 256), raster.Fix32(190 * 256)})
@ -77,9 +78,9 @@ func TestFreetypeNonZeroWinding(t *testing.T) {
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
c.Segment(&p, flattening_threshold) c.Segment(&p, flattening_threshold)
poly := Polygon(p.points) poly := Polygon(p.points)
color := image.RGBAColor{0, 0, 0, 0xff} color := color.RGBA{0, 0, 0, 0xff}
img := image.NewRGBA(200, 200) img := image.NewRGBA(image.Rect(0, 0, 200, 200))
rasterizer := raster.NewRasterizer(200, 200) rasterizer := raster.NewRasterizer(200, 200)
rasterizer.UseNonZeroWinding = true rasterizer.UseNonZeroWinding = true
rasterizer.Start(raster.Point{raster.Fix32(10 * 256), raster.Fix32(190 * 256)}) rasterizer.Start(raster.Point{raster.Fix32(10 * 256), raster.Fix32(190 * 256)})
@ -94,35 +95,33 @@ func TestFreetypeNonZeroWinding(t *testing.T) {
} }
func TestRasterizer(t *testing.T) { func TestRasterizer(t *testing.T) {
img := image.NewRGBA(200, 200) img := image.NewRGBA(image.Rect(0, 0, 200, 200))
var p Path var p Path
p.LineTo(10, 190) p.LineTo(10, 190)
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
c.Segment(&p, flattening_threshold) c.Segment(&p, flattening_threshold)
poly := Polygon(p.points) poly := Polygon(p.points)
color := image.RGBAColor{0, 0, 0, 0xff} color := color.RGBA{0, 0, 0, 0xff}
tr := [6]float64{1, 0, 0, 1, 0, 0} tr := [6]float64{1, 0, 0, 1, 0, 0}
r := NewRasterizer8BitsSample(200, 200) r := NewRasterizer8BitsSample(200, 200)
//PolylineBresenham(img, image.Black, poly...) //PolylineBresenham(img, image.Black, poly...)
r.RenderEvenOdd(img, &color, &poly, tr) r.RenderEvenOdd(img, &color, &poly, tr)
savepng("_testRasterizer.png", img) savepng("_testRasterizer.png", img)
} }
func TestRasterizerNonZeroWinding(t *testing.T) { func TestRasterizerNonZeroWinding(t *testing.T) {
img := image.NewRGBA(200, 200) img := image.NewRGBA(image.Rect(0, 0, 200, 200))
var p Path var p Path
p.LineTo(10, 190) p.LineTo(10, 190)
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
c.Segment(&p, flattening_threshold) c.Segment(&p, flattening_threshold)
poly := Polygon(p.points) poly := Polygon(p.points)
color := image.RGBAColor{0, 0, 0, 0xff} color := color.RGBA{0, 0, 0, 0xff}
tr := [6]float64{1, 0, 0, 1, 0, 0} tr := [6]float64{1, 0, 0, 1, 0, 0}
r := NewRasterizer8BitsSample(200, 200) r := NewRasterizer8BitsSample(200, 200)
//PolylineBresenham(img, image.Black, poly...) //PolylineBresenham(img, image.Black, poly...)
r.RenderNonZeroWinding(img, &color, &poly, tr) r.RenderNonZeroWinding(img, &color, &poly, tr)
savepng("_testRasterizerNonZeroWinding.png", img) savepng("_testRasterizerNonZeroWinding.png", img)
} }
@ -133,10 +132,10 @@ func BenchmarkFreetype(b *testing.B) {
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
c.Segment(&p, flattening_threshold) c.Segment(&p, flattening_threshold)
poly := Polygon(p.points) poly := Polygon(p.points)
color := image.RGBAColor{0, 0, 0, 0xff} color := color.RGBA{0, 0, 0, 0xff}
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
img := image.NewRGBA(200, 200) img := image.NewRGBA(image.Rect(0, 0, 200, 200))
rasterizer := raster.NewRasterizer(200, 200) rasterizer := raster.NewRasterizer(200, 200)
rasterizer.UseNonZeroWinding = false rasterizer.UseNonZeroWinding = false
rasterizer.Start(raster.Point{raster.Fix32(10 * 256), raster.Fix32(190 * 256)}) rasterizer.Start(raster.Point{raster.Fix32(10 * 256), raster.Fix32(190 * 256)})
@ -154,10 +153,10 @@ func BenchmarkFreetypeNonZeroWinding(b *testing.B) {
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
c.Segment(&p, flattening_threshold) c.Segment(&p, flattening_threshold)
poly := Polygon(p.points) poly := Polygon(p.points)
color := image.RGBAColor{0, 0, 0, 0xff} color := color.RGBA{0, 0, 0, 0xff}
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
img := image.NewRGBA(200, 200) img := image.NewRGBA(image.Rect(0, 0, 200, 200))
rasterizer := raster.NewRasterizer(200, 200) rasterizer := raster.NewRasterizer(200, 200)
rasterizer.UseNonZeroWinding = true rasterizer.UseNonZeroWinding = true
rasterizer.Start(raster.Point{raster.Fix32(10 * 256), raster.Fix32(190 * 256)}) rasterizer.Start(raster.Point{raster.Fix32(10 * 256), raster.Fix32(190 * 256)})
@ -176,10 +175,10 @@ func BenchmarkRasterizerNonZeroWinding(b *testing.B) {
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
c.Segment(&p, flattening_threshold) c.Segment(&p, flattening_threshold)
poly := Polygon(p.points) poly := Polygon(p.points)
color := image.RGBAColor{0, 0, 0, 0xff} color := color.RGBA{0, 0, 0, 0xff}
tr := [6]float64{1, 0, 0, 1, 0, 0} tr := [6]float64{1, 0, 0, 1, 0, 0}
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
img := image.NewRGBA(200, 200) img := image.NewRGBA(image.Rect(0, 0, 200, 200))
rasterizer := NewRasterizer8BitsSample(200, 200) rasterizer := NewRasterizer8BitsSample(200, 200)
rasterizer.RenderNonZeroWinding(img, &color, &poly, tr) rasterizer.RenderNonZeroWinding(img, &color, &poly, tr)
} }
@ -191,10 +190,10 @@ func BenchmarkRasterizer(b *testing.B) {
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190} c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
c.Segment(&p, flattening_threshold) c.Segment(&p, flattening_threshold)
poly := Polygon(p.points) poly := Polygon(p.points)
color := image.RGBAColor{0, 0, 0, 0xff} color := color.RGBA{0, 0, 0, 0xff}
tr := [6]float64{1, 0, 0, 1, 0, 0} tr := [6]float64{1, 0, 0, 1, 0, 0}
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
img := image.NewRGBA(200, 200) img := image.NewRGBA(image.Rect(0, 0, 200, 200))
rasterizer := NewRasterizer8BitsSample(200, 200) rasterizer := NewRasterizer8BitsSample(200, 200)
rasterizer.RenderEvenOdd(img, &color, &poly, tr) rasterizer.RenderEvenOdd(img, &color, &poly, tr)
} }

View file

@ -2,8 +2,9 @@
package draw2d package draw2d
import ( import (
"image/draw"
"image" "image"
"image/color"
"image/draw"
"math" "math"
) )
@ -16,11 +17,11 @@ const (
) )
//see http://pippin.gimp.org/image_processing/chap_resampling.html //see http://pippin.gimp.org/image_processing/chap_resampling.html
func getColorLinear(img image.Image, x, y float64) image.Color { func getColorLinear(img image.Image, x, y float64) color.Color {
return img.At(int(x), int(y)) return img.At(int(x), int(y))
} }
func getColorBilinear(img image.Image, x, y float64) image.Color { func getColorBilinear(img image.Image, x, y float64) color.Color {
x0 := math.Floor(x) x0 := math.Floor(x)
y0 := math.Floor(y) y0 := math.Floor(y)
dx := x - x0 dx := x - x0
@ -39,8 +40,9 @@ func getColorBilinear(img image.Image, x, y float64) image.Color {
g := int(lerp(lerp(g0, g1, dx), lerp(g3, g2, dx), dy)) g := int(lerp(lerp(g0, g1, dx), lerp(g3, g2, dx), dy))
b := int(lerp(lerp(b0, b1, dx), lerp(b3, b2, dx), dy)) b := int(lerp(lerp(b0, b1, dx), lerp(b3, b2, dx), dy))
a := int(lerp(lerp(a0, a1, dx), lerp(a3, a2, dx), dy)) a := int(lerp(lerp(a0, a1, dx), lerp(a3, a2, dx), dy))
return image.RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)} return color.RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
} }
/** /**
-- LERP -- LERP
-- /lerp/, vi.,n. -- /lerp/, vi.,n.
@ -53,8 +55,7 @@ func lerp(v1, v2, ratio float64) float64 {
return v1*(1-ratio) + v2*ratio return v1*(1-ratio) + v2*ratio
} }
func getColorCubicRow(img image.Image, x, y, offset float64) color.Color {
func getColorCubicRow(img image.Image, x, y, offset float64) image.Color {
c0 := img.At(int(x), int(y)) c0 := img.At(int(x), int(y))
c1 := img.At(int(x+1), int(y)) c1 := img.At(int(x+1), int(y))
c2 := img.At(int(x+2), int(y)) c2 := img.At(int(x+2), int(y))
@ -68,10 +69,10 @@ func getColorCubicRow(img image.Image, x, y, offset float64) image.Color {
rt, gt, bt, at = c3.RGBA() rt, gt, bt, at = c3.RGBA()
r3, g3, b3, a3 := float64(rt), float64(gt), float64(bt), float64(at) r3, g3, b3, a3 := float64(rt), float64(gt), float64(bt), float64(at)
r, g, b, a := cubic(offset, r0, r1, r2, r3), cubic(offset, g0, g1, g2, g3), cubic(offset, b0, b1, b2, b3), cubic(offset, a0, a1, a2, a3) r, g, b, a := cubic(offset, r0, r1, r2, r3), cubic(offset, g0, g1, g2, g3), cubic(offset, b0, b1, b2, b3), cubic(offset, a0, a1, a2, a3)
return image.RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)} return color.RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
} }
func getColorBicubic(img image.Image, x, y float64) image.Color { func getColorBicubic(img image.Image, x, y float64) color.Color {
x0 := math.Floor(x) x0 := math.Floor(x)
y0 := math.Floor(y) y0 := math.Floor(y)
dx := x - x0 dx := x - x0
@ -89,7 +90,7 @@ func getColorBicubic(img image.Image, x, y float64) image.Color {
rt, gt, bt, at = c3.RGBA() rt, gt, bt, at = c3.RGBA()
r3, g3, b3, a3 := float64(rt), float64(gt), float64(bt), float64(at) r3, g3, b3, a3 := float64(rt), float64(gt), float64(bt), float64(at)
r, g, b, a := cubic(dy, r0, r1, r2, r3), cubic(dy, g0, g1, g2, g3), cubic(dy, b0, b1, b2, b3), cubic(dy, a0, a1, a2, a3) r, g, b, a := cubic(dy, r0, r1, r2, r3), cubic(dy, g0, g1, g2, g3), cubic(dy, b0, b1, b2, b3), cubic(dy, a0, a1, a2, a3)
return image.RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)} return color.RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
} }
func cubic(offset, v0, v1, v2, v3 float64) uint32 { func cubic(offset, v0, v1, v2, v3 float64) uint32 {
@ -104,9 +105,9 @@ func DrawImage(src image.Image, dest draw.Image, tr MatrixTransform, op draw.Op,
x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y) x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y)
tr.TransformRectangle(&x0, &y0, &x1, &y1) tr.TransformRectangle(&x0, &y0, &x1, &y1)
var x, y, u, v float64 var x, y, u, v float64
var c1, c2, cr image.Color var c1, c2, cr color.Color
var r, g, b, a, ia, r1, g1, b1, a1, r2, g2, b2, a2 uint32 var r, g, b, a, ia, r1, g1, b1, a1, r2, g2, b2, a2 uint32
var color image.RGBAColor var color color.RGBA
for x = x0; x < x1; x++ { for x = x0; x < x1; x++ {
for y = y0; y < y1; y++ { for y = y0; y < y1; y++ {
u = x u = x

View file

@ -4,6 +4,7 @@ package draw2d
import ( import (
"image" "image"
"image/color"
) )
type StackGraphicContext struct { type StackGraphicContext struct {
@ -16,8 +17,8 @@ type ContextStack struct {
LineWidth float64 LineWidth float64
Dash []float64 Dash []float64
DashOffset float64 DashOffset float64
StrokeColor image.Color StrokeColor color.Color
FillColor image.Color FillColor color.Color
FillRule FillRule FillRule FillRule
Cap Cap Cap Cap
Join Join Join Join
@ -26,7 +27,6 @@ type ContextStack struct {
previous *ContextStack previous *ContextStack
} }
/** /**
* Create a new Graphic context from an image * Create a new Graphic context from an image
*/ */
@ -46,7 +46,6 @@ func NewStackGraphicContext() *StackGraphicContext {
return gc return gc
} }
func (gc *StackGraphicContext) GetMatrixTransform() MatrixTransform { func (gc *StackGraphicContext) GetMatrixTransform() MatrixTransform {
return gc.Current.Tr return gc.Current.Tr
} }
@ -71,11 +70,11 @@ func (gc *StackGraphicContext) Scale(sx, sy float64) {
gc.Current.Tr = NewScaleMatrix(sx, sy).Multiply(gc.Current.Tr) gc.Current.Tr = NewScaleMatrix(sx, sy).Multiply(gc.Current.Tr)
} }
func (gc *StackGraphicContext) SetStrokeColor(c image.Color) { func (gc *StackGraphicContext) SetStrokeColor(c color.Color) {
gc.Current.StrokeColor = c gc.Current.StrokeColor = c
} }
func (gc *StackGraphicContext) SetFillColor(c image.Color) { func (gc *StackGraphicContext) SetFillColor(c color.Color) {
gc.Current.FillColor = c gc.Current.FillColor = c
} }

View file

@ -3,7 +3,7 @@
package draw2d package draw2d
import ( import (
"freetype-go.googlecode.com/hg/freetype/raster" "code.google.com/p/freetype-go/freetype/raster"
"math" "math"
) )
@ -140,7 +140,6 @@ func (tr MatrixTransform) GetInverseTransformation() MatrixTransform {
(tr[1]*tr[4] - tr[0]*tr[5]) / d} (tr[1]*tr[4] - tr[0]*tr[5]) / d}
} }
func (tr1 MatrixTransform) Multiply(tr2 MatrixTransform) MatrixTransform { func (tr1 MatrixTransform) Multiply(tr2 MatrixTransform) MatrixTransform {
return [6]float64{ return [6]float64{
tr1[0]*tr2[0] + tr1[1]*tr2[2], tr1[0]*tr2[0] + tr1[1]*tr2[2],
@ -151,7 +150,6 @@ func (tr1 MatrixTransform) Multiply(tr2 MatrixTransform) MatrixTransform {
tr1[5]*tr2[3] + tr1[4]*tr2[1] + tr2[5]} tr1[5]*tr2[3] + tr1[4]*tr2[1] + tr2[5]}
} }
func (tr *MatrixTransform) Scale(sx, sy float64) *MatrixTransform { func (tr *MatrixTransform) Scale(sx, sy float64) *MatrixTransform {
tr[0] = sx * tr[0] tr[0] = sx * tr[0]
tr[1] = sx * tr[1] tr[1] = sx * tr[1]
@ -195,8 +193,8 @@ func (tr MatrixTransform) GetScale() float64 {
} }
func (tr MatrixTransform) GetMaxAbsScaling() (s float64) { func (tr MatrixTransform) GetMaxAbsScaling() (s float64) {
sx := math.Fabs(tr[0]) sx := math.Abs(tr[0])
sy := math.Fabs(tr[3]) sy := math.Abs(tr[3])
if sx > sy { if sx > sy {
return sx return sx
} }
@ -204,8 +202,8 @@ func (tr MatrixTransform) GetMaxAbsScaling() (s float64) {
} }
func (tr MatrixTransform) GetMinAbsScaling() (s float64) { func (tr MatrixTransform) GetMinAbsScaling() (s float64) {
sx := math.Fabs(tr[0]) sx := math.Abs(tr[0])
sy := math.Fabs(tr[3]) sy := math.Abs(tr[3])
if sx > sy { if sx > sy {
return sy return sy
} }
@ -248,7 +246,7 @@ func (tr MatrixTransform) IsTranslation() bool {
* return true if the distance between the two floats is less than epsilon, false otherwise * return true if the distance between the two floats is less than epsilon, false otherwise
*/ */
func fequals(float1, float2 float64) bool { func fequals(float1, float2 float64) bool {
return math.Fabs(float1-float2) <= epsilon return math.Abs(float1-float2) <= epsilon
} }
// this VertexConverter apply the Matrix transformation tr // this VertexConverter apply the Matrix transformation tr
@ -272,7 +270,6 @@ func (vmt *VertexMatrixTransform) Vertex(x, y float64) {
vmt.Next.Vertex(u, v) vmt.Next.Vertex(u, v)
} }
// this adder apply a Matrix transformation to points // this adder apply a Matrix transformation to points
type MatrixTransformAdder struct { type MatrixTransformAdder struct {
tr MatrixTransform tr MatrixTransform
@ -283,7 +280,6 @@ func NewMatrixTransformAdder(tr MatrixTransform, adder raster.Adder) *MatrixTran
return &MatrixTransformAdder{tr, adder} return &MatrixTransformAdder{tr, adder}
} }
// Start starts a new curve at the given point. // Start starts a new curve at the given point.
func (mta MatrixTransformAdder) Start(a raster.Point) { func (mta MatrixTransformAdder) Start(a raster.Point) {
mta.tr.TransformRasterPoint(&a) mta.tr.TransformRasterPoint(&a)

View file

@ -1,11 +1,12 @@
package draw2dgl package draw2dgl
import ( import (
"image" "code.google.com/p/draw2d/draw2d"
"image/draw" "code.google.com/p/freetype-go/freetype/raster"
"gl" "gl"
"freetype-go.googlecode.com/hg/freetype/raster" "image"
"draw2d.googlecode.com/hg/draw2d" "image/color"
"image/draw"
//"log" //"log"
) )
@ -81,9 +82,8 @@ func (p *GLPainter) Flush() {
} }
} }
// SetColor sets the color to paint the spans. // SetColor sets the color to paint the spans.
func (p *GLPainter) SetColor(c image.Color) { func (p *GLPainter) SetColor(c color.Color) {
r, g, b, a := c.RGBA() r, g, b, a := c.RGBA()
if a == 0 { if a == 0 {
p.cr = 0 p.cr = 0
@ -106,7 +106,6 @@ func NewGLPainter() *GLPainter {
return p return p
} }
type GraphicContext struct { type GraphicContext struct {
*draw2d.StackGraphicContext *draw2d.StackGraphicContext
painter *GLPainter painter *GLPainter
@ -118,7 +117,6 @@ type GLVertex struct {
x, y float64 x, y float64
} }
func NewGLVertex() *GLVertex { func NewGLVertex() *GLVertex {
return &GLVertex{} return &GLVertex{}
} }
@ -168,8 +166,7 @@ func (gc *GraphicContext) FillString(text string) (cursor float64) {
return 0 return 0
} }
func (gc *GraphicContext) paint(rasterizer *raster.Rasterizer, color color.Color) {
func (gc *GraphicContext) paint(rasterizer *raster.Rasterizer, color image.Color) {
gc.painter.SetColor(color) gc.painter.SetColor(color)
rasterizer.Rasterize(gc.painter) rasterizer.Rasterize(gc.painter)
rasterizer.Clear() rasterizer.Clear()
@ -207,6 +204,7 @@ func (gc *GraphicContext) Fill(paths ...*draw2d.PathStorage) {
gc.paint(gc.fillRasterizer, gc.Current.FillColor) gc.paint(gc.fillRasterizer, gc.Current.FillColor)
gc.Current.Path.Clear() gc.Current.Path.Clear()
} }
/* /*
func (gc *GraphicContext) Fill(paths ...*draw2d.PathStorage) { func (gc *GraphicContext) Fill(paths ...*draw2d.PathStorage) {
paths = append(paths, gc.Current.Path) paths = append(paths, gc.Current.Path)

View file

@ -1,6 +1,6 @@
include $(GOROOT)/src/Make.inc include $(GOROOT)/src/Make.inc
TARG=draw2d.googlecode.com/hg/postscript TARG=code.google.com/p/draw2d/postscript
GOFILES=operators_array.go\ GOFILES=operators_array.go\
operators_dictionary.go\ operators_dictionary.go\
operators_misc.go\ operators_misc.go\

View file

@ -4,14 +4,13 @@
package postscript package postscript
import ( import (
"os" "code.google.com/p/draw2d/draw2d"
"log"
"strconv"
"io" "io"
"draw2d.googlecode.com/hg/draw2d" "log"
"os"
"strconv"
) )
type Interpreter struct { type Interpreter struct {
valueStack ValueStack valueStack ValueStack
dictionaryStack DictionaryStack dictionaryStack DictionaryStack
@ -58,10 +57,10 @@ func (interpreter *Interpreter) Execute(reader io.Reader) {
} }
} }
func (interpreter *Interpreter) ExecuteFile(filePath string) os.Error { func (interpreter *Interpreter) ExecuteFile(filePath string) error {
src, err := os.Open(filePath) src, err := os.Open(filePath)
if src == nil { if src == nil {
log.Printf("can't open file; err=%s\n", err.String()) log.Printf("can't open file; err=%s\n", err.Error())
return err return err
} }
defer src.Close() defer src.Close()
@ -102,7 +101,7 @@ func (interpreter *Interpreter) scan(scanner *Scanner, token int) {
// procedure // procedure
interpreter.Push(interpreter.scanProcedure(scanner)) interpreter.Push(interpreter.scanProcedure(scanner))
} else if token == Float || token == Int { } else if token == Float || token == Int {
f, err := strconv.Atof64(scanner.TokenText()) f, err := strconv.ParseFloat(scanner.TokenText(), 64)
if err != nil { if err != nil {
log.Printf("Float expected: %s\n", scanner.TokenText()) log.Printf("Float expected: %s\n", scanner.TokenText())
interpreter.Push(scanner.TokenText()) interpreter.Push(scanner.TokenText())
@ -217,7 +216,6 @@ func (interpreter *Interpreter) SystemDefine(name string, value Value) {
interpreter.dictionaryStack[0][name] = value interpreter.dictionaryStack[0][name] = value
} }
//Operand Operation //Operand Operation
func (interpreter *Interpreter) Push(operand Value) { func (interpreter *Interpreter) Push(operand Value) {

View file

@ -5,13 +5,12 @@
package postscript package postscript
import ( import (
"image" "code.google.com/p/draw2d/draw2d"
"draw2d.googlecode.com/hg/draw2d" "image/color"
"math"
"log" "log"
"math"
) )
//Path Construction Operators //Path Construction Operators
func newpath(interpreter *Interpreter) { func newpath(interpreter *Interpreter) {
interpreter.GetGraphicContext().BeginPath() interpreter.GetGraphicContext().BeginPath()
@ -102,7 +101,7 @@ func grestore(interpreter *Interpreter) {
func setgray(interpreter *Interpreter) { func setgray(interpreter *Interpreter) {
gray := interpreter.PopFloat() gray := interpreter.PopFloat()
color := image.RGBAColor{uint8(gray * 0xff), uint8(gray * 0xff), uint8(gray * 0xff), 0xff} color := color.RGBA{uint8(gray * 0xff), uint8(gray * 0xff), uint8(gray * 0xff), 0xff}
interpreter.GetGraphicContext().SetStrokeColor(color) interpreter.GetGraphicContext().SetStrokeColor(color)
interpreter.GetGraphicContext().SetFillColor(color) interpreter.GetGraphicContext().SetFillColor(color)
} }
@ -111,7 +110,7 @@ func setrgbcolor(interpreter *Interpreter) {
blue := interpreter.PopFloat() blue := interpreter.PopFloat()
green := interpreter.PopFloat() green := interpreter.PopFloat()
red := interpreter.PopFloat() red := interpreter.PopFloat()
color := image.RGBAColor{uint8(red * 0xff), uint8(green * 0xff), uint8(blue * 0xff), 0xff} color := color.RGBA{uint8(red * 0xff), uint8(green * 0xff), uint8(blue * 0xff), 0xff}
interpreter.GetGraphicContext().SetStrokeColor(color) interpreter.GetGraphicContext().SetStrokeColor(color)
interpreter.GetGraphicContext().SetFillColor(color) interpreter.GetGraphicContext().SetFillColor(color)
} }
@ -169,7 +168,7 @@ func sethsbcolor(interpreter *Interpreter) {
saturation := interpreter.PopFloat() saturation := interpreter.PopFloat()
hue := interpreter.PopFloat() hue := interpreter.PopFloat()
red, green, blue := hsbtorgb(hue, saturation, brightness) red, green, blue := hsbtorgb(hue, saturation, brightness)
color := image.RGBAColor{uint8(red), uint8(green), uint8(blue), 0xff} color := color.RGBA{uint8(red), uint8(green), uint8(blue), 0xff}
interpreter.GetGraphicContext().SetStrokeColor(color) interpreter.GetGraphicContext().SetStrokeColor(color)
interpreter.GetGraphicContext().SetFillColor(color) interpreter.GetGraphicContext().SetFillColor(color)
} }
@ -193,7 +192,7 @@ func setcmybcolor(interpreter *Interpreter) {
green = (1.0-green)*255.0 + 0.5 green = (1.0-green)*255.0 + 0.5
blue = (1.0-blue)*255.0 + 0.5 blue = (1.0-blue)*255.0 + 0.5
color := image.RGBAColor{uint8(red), uint8(green), uint8(blue), 0xff} color := color.RGBA{uint8(red), uint8(green), uint8(blue), 0xff}
interpreter.GetGraphicContext().SetStrokeColor(color) interpreter.GetGraphicContext().SetStrokeColor(color)
interpreter.GetGraphicContext().SetFillColor(color) interpreter.GetGraphicContext().SetFillColor(color)
} }
@ -246,6 +245,7 @@ func show(interpreter *Interpreter) {
interpreter.GetGraphicContext().FillString(s) interpreter.GetGraphicContext().FillString(s)
log.Printf("show not really implemented") log.Printf("show not really implemented")
} }
//ax ay string ashow -> Add (ax , ay) to width of each glyph while showing string //ax ay string ashow -> Add (ax , ay) to width of each glyph while showing string
func ashow(interpreter *Interpreter) { func ashow(interpreter *Interpreter) {
log.Printf("ashow not really implemented") log.Printf("ashow not really implemented")
@ -283,7 +283,6 @@ func currentflat(interpreter *Interpreter) {
log.Printf("currentflat not yet implemented") log.Printf("currentflat not yet implemented")
} }
// Coordinate System and Matrix operators // Coordinate System and Matrix operators
func matrix(interpreter *Interpreter) { func matrix(interpreter *Interpreter) {
interpreter.Push(draw2d.NewIdentityMatrix()) interpreter.Push(draw2d.NewIdentityMatrix())
@ -420,7 +419,6 @@ func scale(interpreter *Interpreter) {
} }
} }
func initDrawingOperators(interpreter *Interpreter) { func initDrawingOperators(interpreter *Interpreter) {
interpreter.SystemDefine("stroke", NewOperator(stroke)) interpreter.SystemDefine("stroke", NewOperator(stroke))

View file

@ -6,8 +6,9 @@ package postscript
import ( import (
"math" "math"
"rand" "math/rand"
) )
// begin Primitive Operator implementation // begin Primitive Operator implementation
//num1 num2 add sum -> Return num1 plus num2 //num1 num2 add sum -> Return num1 plus num2
@ -16,6 +17,7 @@ func add(interpreter *Interpreter) {
num1 := interpreter.PopFloat() num1 := interpreter.PopFloat()
interpreter.Push(num1 + num2) interpreter.Push(num1 + num2)
} }
//num1 num2 div quotient -> Return num1 divided by num2 //num1 num2 div quotient -> Return num1 divided by num2
func div(interpreter *Interpreter) { func div(interpreter *Interpreter) {
num2 := interpreter.PopFloat() num2 := interpreter.PopFloat()
@ -29,6 +31,7 @@ func idiv(interpreter *Interpreter) {
int1 := interpreter.PopInt() int1 := interpreter.PopInt()
interpreter.Push(float64(int1 / int2)) interpreter.Push(float64(int1 / int2))
} }
//int int mod remainder -> Return remainder after dividing int by int //int int mod remainder -> Return remainder after dividing int by int
func mod(interpreter *Interpreter) { func mod(interpreter *Interpreter) {
int2 := interpreter.PopInt() int2 := interpreter.PopInt()
@ -42,89 +45,106 @@ func mul(interpreter *Interpreter) {
num1 := interpreter.PopFloat() num1 := interpreter.PopFloat()
interpreter.Push(num1 * num2) interpreter.Push(num1 * num2)
} }
//num1 num2 sub difference -> Return num1 minus num2 //num1 num2 sub difference -> Return num1 minus num2
func sub(interpreter *Interpreter) { func sub(interpreter *Interpreter) {
num2 := interpreter.PopFloat() num2 := interpreter.PopFloat()
num1 := interpreter.PopFloat() num1 := interpreter.PopFloat()
interpreter.Push(num1 - num2) interpreter.Push(num1 - num2)
} }
//num1 abs num2 -> Return absolute value of num1 //num1 abs num2 -> Return absolute value of num1
func abs(interpreter *Interpreter) { func abs(interpreter *Interpreter) {
f := interpreter.PopFloat() f := interpreter.PopFloat()
interpreter.Push(math.Fabs(f)) interpreter.Push(math.Abs(f))
} }
//num1 neg num2 -> Return negative of num1 //num1 neg num2 -> Return negative of num1
func neg(interpreter *Interpreter) { func neg(interpreter *Interpreter) {
f := interpreter.PopFloat() f := interpreter.PopFloat()
interpreter.Push(-f) interpreter.Push(-f)
} }
//num1 ceiling num2 -> Return ceiling of num1 //num1 ceiling num2 -> Return ceiling of num1
func ceiling(interpreter *Interpreter) { func ceiling(interpreter *Interpreter) {
f := interpreter.PopFloat() f := interpreter.PopFloat()
interpreter.Push(float64(int(f + 1))) interpreter.Push(float64(int(f + 1)))
} }
//num1 floor num2 -> Return floor of num1 //num1 floor num2 -> Return floor of num1
func floor(interpreter *Interpreter) { func floor(interpreter *Interpreter) {
f := interpreter.PopFloat() f := interpreter.PopFloat()
interpreter.Push(math.Floor(f)) interpreter.Push(math.Floor(f))
} }
//num1 round num2 -> Round num1 to nearest integer //num1 round num2 -> Round num1 to nearest integer
func round(interpreter *Interpreter) { func round(interpreter *Interpreter) {
f := interpreter.PopFloat() f := interpreter.PopFloat()
interpreter.Push(float64(int(f + 0.5))) interpreter.Push(float64(int(f + 0.5)))
} }
//num1 truncate num2 -> Remove fractional part of num1 //num1 truncate num2 -> Remove fractional part of num1
func truncate(interpreter *Interpreter) { func truncate(interpreter *Interpreter) {
f := interpreter.PopFloat() f := interpreter.PopFloat()
interpreter.Push(float64(int(f))) interpreter.Push(float64(int(f)))
} }
//num sqrt real -> Return square root of num //num sqrt real -> Return square root of num
func sqrt(interpreter *Interpreter) { func sqrt(interpreter *Interpreter) {
f := interpreter.PopFloat() f := interpreter.PopFloat()
interpreter.Push(float64(math.Sqrt(f))) interpreter.Push(float64(math.Sqrt(f)))
} }
//num den atan angle -> Return arctangent of num/den in degrees //num den atan angle -> Return arctangent of num/den in degrees
func atan(interpreter *Interpreter) { func atan(interpreter *Interpreter) {
den := interpreter.PopFloat() den := interpreter.PopFloat()
num := interpreter.PopFloat() num := interpreter.PopFloat()
interpreter.Push(math.Atan2(num, den) * (180.0 / math.Pi)) interpreter.Push(math.Atan2(num, den) * (180.0 / math.Pi))
} }
//angle cos real -> Return cosine of angle degrees //angle cos real -> Return cosine of angle degrees
func cos(interpreter *Interpreter) { func cos(interpreter *Interpreter) {
a := interpreter.PopFloat() * math.Pi / 180 a := interpreter.PopFloat() * math.Pi / 180
interpreter.Push(math.Cos(a)) interpreter.Push(math.Cos(a))
} }
//angle sin real -> Return sine of angle degrees //angle sin real -> Return sine of angle degrees
func sin(interpreter *Interpreter) { func sin(interpreter *Interpreter) {
a := interpreter.PopFloat() * math.Pi / 180 a := interpreter.PopFloat() * math.Pi / 180
interpreter.Push(math.Sin(a)) interpreter.Push(math.Sin(a))
} }
//base exponent exp real -> Raise base to exponent power //base exponent exp real -> Raise base to exponent power
func exp(interpreter *Interpreter) { func exp(interpreter *Interpreter) {
exponent := interpreter.PopFloat() exponent := interpreter.PopFloat()
base := interpreter.PopFloat() base := interpreter.PopFloat()
interpreter.Push(math.Pow(base, exponent)) interpreter.Push(math.Pow(base, exponent))
} }
//num ln real -> Return natural logarithm (base e) //num ln real -> Return natural logarithm (base e)
func ln(interpreter *Interpreter) { func ln(interpreter *Interpreter) {
num := interpreter.PopFloat() num := interpreter.PopFloat()
interpreter.Push(math.Log(num)) interpreter.Push(math.Log(num))
} }
//num log real -> Return common logarithm (base 10) //num log real -> Return common logarithm (base 10)
func log10(interpreter *Interpreter) { func log10(interpreter *Interpreter) {
num := interpreter.PopFloat() num := interpreter.PopFloat()
interpreter.Push(math.Log10(num)) interpreter.Push(math.Log10(num))
} }
// rand int Generate pseudo-random integer // rand int Generate pseudo-random integer
func randInt(interpreter *Interpreter) { func randInt(interpreter *Interpreter) {
interpreter.Push(float64(rand.Int())) interpreter.Push(float64(rand.Int()))
} }
var randGenerator *rand.Rand var randGenerator *rand.Rand
//int srand -> Set random number seed //int srand -> Set random number seed
func srand(interpreter *Interpreter) { func srand(interpreter *Interpreter) {
randGenerator = rand.New(rand.NewSource(int64(interpreter.PopInt()))) randGenerator = rand.New(rand.NewSource(int64(interpreter.PopInt())))
} }
// rrand int -> Return random number seed // rrand int -> Return random number seed
func rrand(interpreter *Interpreter) { func rrand(interpreter *Interpreter) {
interpreter.Push(float64(randGenerator.Int())) interpreter.Push(float64(randGenerator.Int()))

View file

@ -10,10 +10,9 @@ import (
"io" "io"
"os" "os"
"unicode" "unicode"
"utf8" "unicode/utf8"
) )
// A source position is represented by a Position value. // A source position is represented by a Position value.
// A position is valid if Line > 0. // A position is valid if Line > 0.
type Position struct { type Position struct {
@ -23,11 +22,9 @@ type Position struct {
Column int // column number, starting at 0 (character count per line) Column int // column number, starting at 0 (character count per line)
} }
// IsValid returns true if the position is valid. // IsValid returns true if the position is valid.
func (pos *Position) IsValid() bool { return pos.Line > 0 } func (pos *Position) IsValid() bool { return pos.Line > 0 }
func (pos Position) String() string { func (pos Position) String() string {
s := pos.Filename s := pos.Filename
if pos.IsValid() { if pos.IsValid() {
@ -42,7 +39,6 @@ func (pos Position) String() string {
return s return s
} }
// Predefined mode bits to control recognition of tokens. For instance, // Predefined mode bits to control recognition of tokens. For instance,
// to configure a Scanner such that it only recognizes (Go) identifiers, // to configure a Scanner such that it only recognizes (Go) identifiers,
// integers, and skips comments, set the Scanner's Mode field to: // integers, and skips comments, set the Scanner's Mode field to:
@ -61,7 +57,6 @@ const (
GoTokens = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments GoTokens = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments
) )
// The result of Scan is one of the following tokens or a Unicode character. // The result of Scan is one of the following tokens or a Unicode character.
const ( const (
EOF = -(iota + 1) EOF = -(iota + 1)
@ -75,7 +70,6 @@ const (
skipComment skipComment
) )
var tokenString = map[int]string{ var tokenString = map[int]string{
EOF: "EOF", EOF: "EOF",
Ident: "Ident", Ident: "Ident",
@ -87,7 +81,6 @@ var tokenString = map[int]string{
Comment: "Comment", Comment: "Comment",
} }
// TokenString returns a (visible) string for a token or Unicode character. // TokenString returns a (visible) string for a token or Unicode character.
func TokenString(tok int) string { func TokenString(tok int) string {
if s, found := tokenString[tok]; found { if s, found := tokenString[tok]; found {
@ -96,12 +89,10 @@ func TokenString(tok int) string {
return fmt.Sprintf("U+%04X", tok) return fmt.Sprintf("U+%04X", tok)
} }
// GoWhitespace is the default value for the Scanner's Whitespace field. // GoWhitespace is the default value for the Scanner's Whitespace field.
// Its value selects Go's white space characters. // Its value selects Go's white space characters.
const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' ' const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '
const bufLen = 1024 // at least utf8.UTFMax const bufLen = 1024 // at least utf8.UTFMax
// A Scanner implements reading of Unicode characters and tokens from an io.Reader. // A Scanner implements reading of Unicode characters and tokens from an io.Reader.
@ -128,7 +119,7 @@ type Scanner struct {
tokEnd int // token text tail end (srcBuf index) tokEnd int // token text tail end (srcBuf index)
// One character look-ahead // One character look-ahead
ch int // character before current srcPos ch rune // character before current srcPos
// Error is called for each error encountered. If no Error // Error is called for each error encountered. If no Error
// function is set, the error is reported to os.Stderr. // function is set, the error is reported to os.Stderr.
@ -154,7 +145,6 @@ type Scanner struct {
Position Position
} }
// Init initializes a Scanner with a new source and returns itself. // Init initializes a Scanner with a new source and returns itself.
// Error is set to nil, ErrorCount is set to 0, Mode is set to GoTokens, // Error is set to nil, ErrorCount is set to 0, Mode is set to GoTokens,
// and Whitespace is set to GoWhitespace. // and Whitespace is set to GoWhitespace.
@ -186,13 +176,12 @@ func (s *Scanner) Init(src io.Reader) *Scanner {
return s return s
} }
// next reads and returns the next Unicode character. It is designed such // next reads and returns the next Unicode character. It is designed such
// that only a minimal amount of work needs to be done in the common ASCII // that only a minimal amount of work needs to be done in the common ASCII
// case (one test to check for both ASCII and end-of-buffer, and one test // case (one test to check for both ASCII and end-of-buffer, and one test
// to check for newlines). // to check for newlines).
func (s *Scanner) next() int { func (s *Scanner) next() rune {
ch := int(s.srcBuf[s.srcPos]) ch := rune(s.srcBuf[s.srcPos])
if ch >= utf8.RuneSelf { if ch >= utf8.RuneSelf {
// uncommon case: not ASCII or not enough bytes // uncommon case: not ASCII or not enough bytes
@ -216,14 +205,14 @@ func (s *Scanner) next() int {
if s.srcEnd == 0 { if s.srcEnd == 0 {
return EOF return EOF
} }
if err != os.EOF { if err != io.EOF {
s.error(err.String()) s.error(err.Error())
break break
} }
} }
} }
// at least one byte // at least one byte
ch = int(s.srcBuf[s.srcPos]) ch = rune(s.srcBuf[s.srcPos])
if ch >= utf8.RuneSelf { if ch >= utf8.RuneSelf {
// uncommon case: not ASCII // uncommon case: not ASCII
var width int var width int
@ -249,29 +238,26 @@ func (s *Scanner) next() int {
return ch return ch
} }
// Next reads and returns the next Unicode character. // Next reads and returns the next Unicode character.
// It returns EOF at the end of the source. It reports // It returns EOF at the end of the source. It reports
// a read error by calling s.Error, if set, or else // a read error by calling s.Error, if set, or else
// prints an error message to os.Stderr. Next does not // prints an error message to os.Stderr. Next does not
// update the Scanner's Position field; use Pos() to // update the Scanner's Position field; use Pos() to
// get the current position. // get the current position.
func (s *Scanner) Next() int { func (s *Scanner) Next() rune {
s.tokPos = -1 // don't collect token text s.tokPos = -1 // don't collect token text
ch := s.ch ch := s.ch
s.ch = s.next() s.ch = s.next()
return ch return ch
} }
// Peek returns the next Unicode character in the source without advancing // Peek returns the next Unicode character in the source without advancing
// the scanner. It returns EOF if the scanner's position is at the last // the scanner. It returns EOF if the scanner's position is at the last
// character of the source. // character of the source.
func (s *Scanner) Peek() int { func (s *Scanner) Peek() rune {
return s.ch return s.ch
} }
func (s *Scanner) error(msg string) { func (s *Scanner) error(msg string) {
s.ErrorCount++ s.ErrorCount++
if s.Error != nil { if s.Error != nil {
@ -281,8 +267,7 @@ func (s *Scanner) error(msg string) {
fmt.Fprintf(os.Stderr, "%s: %s", s.Position, msg) fmt.Fprintf(os.Stderr, "%s: %s", s.Position, msg)
} }
func (s *Scanner) scanIdentifier() rune {
func (s *Scanner) scanIdentifier() int {
ch := s.next() // read character after first '_' or letter ch := s.next() // read character after first '_' or letter
for ch == '_' || unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '.' || ch == '-' || ch == '`' { for ch == '_' || unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '.' || ch == '-' || ch == '`' {
ch = s.next() ch = s.next()
@ -290,8 +275,7 @@ func (s *Scanner) scanIdentifier() int {
return ch return ch
} }
func digitVal(ch rune) rune {
func digitVal(ch int) int {
switch { switch {
case '0' <= ch && ch <= '9': case '0' <= ch && ch <= '9':
return ch - '0' return ch - '0'
@ -303,27 +287,23 @@ func digitVal(ch int) int {
return 16 // larger than any legal digit val return 16 // larger than any legal digit val
} }
func isDecimal(ch rune) bool { return '0' <= ch && ch <= '9' }
func isDecimal(ch int) bool { return '0' <= ch && ch <= '9' } func (s *Scanner) scanMantissa(ch rune) rune {
func (s *Scanner) scanMantissa(ch int) int {
for isDecimal(ch) { for isDecimal(ch) {
ch = s.next() ch = s.next()
} }
return ch return ch
} }
func (s *Scanner) scanFraction(ch rune) rune {
func (s *Scanner) scanFraction(ch int) int {
if ch == '.' { if ch == '.' {
ch = s.scanMantissa(s.next()) ch = s.scanMantissa(s.next())
} }
return ch return ch
} }
func (s *Scanner) scanExponent(ch rune) rune {
func (s *Scanner) scanExponent(ch int) int {
if ch == 'e' || ch == 'E' { if ch == 'e' || ch == 'E' {
ch = s.next() ch = s.next()
if ch == '-' || ch == '+' { if ch == '-' || ch == '+' {
@ -334,8 +314,7 @@ func (s *Scanner) scanExponent(ch int) int {
return ch return ch
} }
func (s *Scanner) scanNumber(ch rune) (int, rune) {
func (s *Scanner) scanNumber(ch int) (int, int) {
// isDecimal(ch) // isDecimal(ch)
if ch == '0' { if ch == '0' {
// int or float // int or float
@ -379,9 +358,8 @@ func (s *Scanner) scanNumber(ch int) (int, int) {
return Int, ch return Int, ch
} }
func (s *Scanner) scanDigits(ch rune, base, n int) rune {
func (s *Scanner) scanDigits(ch, base, n int) int { for n > 0 && int(digitVal(ch)) < base {
for n > 0 && digitVal(ch) < base {
ch = s.next() ch = s.next()
n-- n--
} }
@ -391,8 +369,7 @@ func (s *Scanner) scanDigits(ch, base, n int) int {
return ch return ch
} }
func (s *Scanner) scanEscape(quote rune) rune {
func (s *Scanner) scanEscape(quote int) int {
ch := s.next() // read character after '/' ch := s.next() // read character after '/'
switch ch { switch ch {
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote: case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
@ -412,8 +389,7 @@ func (s *Scanner) scanEscape(quote int) int {
return ch return ch
} }
func (s *Scanner) scanString(quote rune) (n int) {
func (s *Scanner) scanString(quote int) (n int) {
ch := s.next() // read character after quote ch := s.next() // read character after quote
for ch != quote { for ch != quote {
if ch == '\n' || ch < 0 { if ch == '\n' || ch < 0 {
@ -430,7 +406,6 @@ func (s *Scanner) scanString(quote int) (n int) {
return return
} }
func (s *Scanner) scanRawString() { func (s *Scanner) scanRawString() {
ch := s.next() // read character after '`' ch := s.next() // read character after '`'
for ch != '`' { for ch != '`' {
@ -442,7 +417,6 @@ func (s *Scanner) scanRawString() {
} }
} }
func (s *Scanner) scanLineComment() { func (s *Scanner) scanLineComment() {
ch := s.next() // read character after "//" ch := s.next() // read character after "//"
for ch != '\n' { for ch != '\n' {
@ -454,12 +428,10 @@ func (s *Scanner) scanLineComment() {
} }
} }
func (s *Scanner) scanComment(ch rune) {
func (s *Scanner) scanComment(ch int) {
s.scanLineComment() s.scanLineComment()
} }
// Scan reads the next token or Unicode character from source and returns it. // Scan reads the next token or Unicode character from source and returns it.
// It only recognizes tokens t for which the respective Mode bit (1<<-t) is set. // It only recognizes tokens t for which the respective Mode bit (1<<-t) is set.
// It returns EOF at the end of the source. It reports scanner errors (read and // It returns EOF at the end of the source. It reports scanner errors (read and
@ -487,7 +459,7 @@ redo:
s.Column = s.column s.Column = s.column
// determine token value // determine token value
tok := ch tok := int(ch)
switch { switch {
case unicode.IsLetter(ch) || ch == '_' || ch == '`': case unicode.IsLetter(ch) || ch == '_' || ch == '`':
if s.Mode&ScanIdents != 0 { if s.Mode&ScanIdents != 0 {
@ -560,7 +532,6 @@ redo:
return tok return tok
} }
// Position returns the current source position. If called before Next() // Position returns the current source position. If called before Next()
// or Scan(), it returns the position of the next Unicode character or token // or Scan(), it returns the position of the next Unicode character or token
// returned by these functions. If called afterwards, it returns the position // returned by these functions. If called afterwards, it returns the position
@ -575,7 +546,6 @@ func (s *Scanner) Pos() Position {
} }
} }
// TokenText returns the string corresponding to the most recently scanned token. // TokenText returns the string corresponding to the most recently scanned token.
// Valid after calling Scan(). // Valid after calling Scan().
func (s *Scanner) TokenText() string { func (s *Scanner) TokenText() string {