add advanced_path function
- Circle - Rect - RoundRect - Ellipse
This commit is contained in:
parent
bdf86580b2
commit
184115e3e1
12 changed files with 302 additions and 324 deletions
|
@ -11,8 +11,8 @@ import (
|
||||||
|
|
||||||
"image"
|
"image"
|
||||||
"image/png"
|
"image/png"
|
||||||
//"draw2d"
|
"draw2d"
|
||||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"exp/draw/x11"
|
"exp/draw/x11"
|
||||||
"image"
|
"image"
|
||||||
"math"
|
"math"
|
||||||
//"draw2d"
|
"draw2d"
|
||||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
|
|
||||||
"image"
|
"image"
|
||||||
"image/png"
|
"image/png"
|
||||||
//"draw2d"
|
"draw2d"
|
||||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -75,52 +75,52 @@ func gordon(gc *draw2d.GraphicContext, x, y, w, h float) {
|
||||||
gc.Close()
|
gc.Close()
|
||||||
gc.SetFillColor(brb)
|
gc.SetFillColor(brb)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.RoundRect(x, y+h, x+ w, y+h+h, 10, 10)
|
draw2d.RoundRect(gc, x, y+h, x+ w, y+h+h, 10, 10)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.Circle(x, y+h, w/12) // left ear
|
draw2d.Circle(gc,x, y+h, w/12) // left ear
|
||||||
gc.SetFillColor(brf)
|
gc.SetFillColor(brf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.Circle(x, y+h, w/12-10)
|
draw2d.Circle(gc, x, y+h, w/12-10)
|
||||||
gc.SetFillColor(nf)
|
gc.SetFillColor(nf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
|
|
||||||
gc.Circle(x+w, y+h, w/12) // right ear
|
draw2d.Circle(gc, x+w, y+h, w/12) // right ear
|
||||||
gc.SetFillColor(brf)
|
gc.SetFillColor(brf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.Circle(x+w, y+h, w/12-10)
|
draw2d.Circle(gc, x+w, y+h, w/12-10)
|
||||||
gc.SetFillColor(nf)
|
gc.SetFillColor(nf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
|
|
||||||
gc.Circle(x+w/3, y+h23, w/9) // left eye
|
draw2d.Circle(gc, x+w/3, y+h23, w/9) // left eye
|
||||||
gc.SetFillColor(wf)
|
gc.SetFillColor(wf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.Circle(x+w/3+10, y+h23, w / 10 - 10)
|
draw2d.Circle(gc, x+w/3+10, y+h23, w / 10 - 10)
|
||||||
gc.SetFillColor(blf)
|
gc.SetFillColor(blf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.Circle(x+w/3+15, y+h23, 5)
|
draw2d.Circle(gc, x+w/3+15, y+h23, 5)
|
||||||
gc.SetFillColor(wf)
|
gc.SetFillColor(wf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
|
|
||||||
gc.Circle(x+w-w/3, y+h23, w/9) // right eye
|
draw2d.Circle(gc, x+w-w/3, y+h23, w/9) // right eye
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.Circle(x+w-w/3+10, y+h23, w / 10 - 10)
|
draw2d.Circle(gc, x+w-w/3+10, y+h23, w / 10 - 10)
|
||||||
gc.SetFillColor(blf)
|
gc.SetFillColor(blf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.Circle(x+w-(w/3)+15, y+h23, 5)
|
draw2d.Circle(gc, x+w-(w/3)+15, y+h23, 5)
|
||||||
gc.SetFillColor(wf)
|
gc.SetFillColor(wf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
|
|
||||||
gc.SetFillColor(wf)
|
gc.SetFillColor(wf)
|
||||||
gc.RoundRect(x+w/2-w/8, y+h+30, x+w/2-w/8 + w/8, y+h+30 + w/6, 5, 5) // left tooth
|
draw2d.RoundRect(gc, x+w/2-w/8, y+h+30, x+w/2-w/8 + w/8, y+h+30 + w/6, 5, 5) // left tooth
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.RoundRect(x+w/2, y+h+30, x+w/2+w/8, y+h+30+w/6, 5, 5) // right tooth
|
draw2d.RoundRect(gc, x+w/2, y+h+30, x+w/2+w/8, y+h+30+w/6, 5, 5) // right tooth
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
|
|
||||||
|
|
||||||
gc.Ellipse(x+(w/2), y+h+30, w/6, w/12) // snout
|
draw2d.Ellipse(gc, x+(w/2), y+h+30, w/6, w/12) // snout
|
||||||
gc.SetFillColor(nf)
|
gc.SetFillColor(nf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
gc.Ellipse(x+(w/2), y+h+10, w/10, w/12) // nose
|
draw2d.Ellipse(gc, x+(w/2), y+h+10, w/10, w/12) // nose
|
||||||
gc.SetFillColor(blf)
|
gc.SetFillColor(blf)
|
||||||
gc.Fill()
|
gc.Fill()
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"image"
|
"image"
|
||||||
"image/png"
|
"image/png"
|
||||||
//"draw2d"
|
"draw2d"
|
||||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -71,21 +71,21 @@ func android(gc *draw2d.GraphicContext, x, y float) {
|
||||||
gc.MoveTo(x+100, y+25)
|
gc.MoveTo(x+100, y+25)
|
||||||
gc.LineTo( x+110, y+10)
|
gc.LineTo( x+110, y+10)
|
||||||
gc.Stroke()
|
gc.Stroke()
|
||||||
gc.Circle(x+60, y+45, 5) // left eye
|
draw2d.Circle(gc, x+60, y+45, 5) // left eye
|
||||||
gc.FillStroke()
|
gc.FillStroke()
|
||||||
gc.Circle(x+100, y+45, 5) // right eye
|
draw2d.Circle(gc, x+100, y+45, 5) // right eye
|
||||||
gc.FillStroke()
|
gc.FillStroke()
|
||||||
gc.RoundRect(x+30, y+75, x+30+100, y+75+90, 10, 10) // body
|
draw2d.RoundRect(gc, x+30, y+75, x+30+100, y+75+90, 10, 10) // body
|
||||||
gc.FillStroke()
|
gc.FillStroke()
|
||||||
gc.Rect(x+30, y+75, x+30+100, y+75+80)
|
draw2d.Rect(gc, x+30, y+75, x+30+100, y+75+80)
|
||||||
gc.FillStroke()
|
gc.FillStroke()
|
||||||
gc.RoundRect(x+5, y+80, x+5+20, y+80+70, 10, 10) // left arm
|
draw2d.RoundRect(gc, x+5, y+80, x+5+20, y+80+70, 10, 10) // left arm
|
||||||
gc.FillStroke()
|
gc.FillStroke()
|
||||||
gc.RoundRect(x+135, y+80, x+135+20, y+80+70, 10, 10) // right arm
|
draw2d.RoundRect(gc, x+135, y+80, x+135+20, y+80+70, 10, 10) // right arm
|
||||||
gc.FillStroke()
|
gc.FillStroke()
|
||||||
gc.RoundRect(x+50, y+150, x+50+20, y+150+50, 10, 10) // left leg
|
draw2d.RoundRect(gc, x+50, y+150, x+50+20, y+150+50, 10, 10) // left leg
|
||||||
gc.FillStroke()
|
gc.FillStroke()
|
||||||
gc.RoundRect(x+90, y+150, x+90+20, y+150+50, 10, 10) // right leg
|
draw2d.RoundRect(gc, x+90, y+150, x+90+20, y+150+50, 10, 10) // right leg
|
||||||
gc.FillStroke()
|
gc.FillStroke()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"image"
|
"image"
|
||||||
"image/png"
|
"image/png"
|
||||||
//"draw2d"
|
"draw2d"
|
||||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -283,11 +283,11 @@ func TestFillStyle() {
|
||||||
i, gc := initGc(w, h)
|
i, gc := initGc(w, h)
|
||||||
gc.SetLineWidth(6)
|
gc.SetLineWidth(6)
|
||||||
|
|
||||||
gc.Rect(12, 12, 244, 70)
|
draw2d.Rect(gc, 12, 12, 244, 70)
|
||||||
|
|
||||||
wheel1 := new(draw2d.Path)
|
wheel1 := new(draw2d.PathStorage)
|
||||||
wheel1.ArcTo(64, 64, 40, 40, 0, 2*math.Pi)
|
wheel1.ArcTo(64, 64, 40, 40, 0, 2*math.Pi)
|
||||||
wheel2 := new(draw2d.Path)
|
wheel2 := new(draw2d.PathStorage)
|
||||||
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)
|
||||||
|
@ -296,10 +296,10 @@ func TestFillStyle() {
|
||||||
gc.SetStrokeColor(image.Black)
|
gc.SetStrokeColor(image.Black)
|
||||||
gc.FillStroke(wheel1, wheel2)
|
gc.FillStroke(wheel1, wheel2)
|
||||||
|
|
||||||
gc.Rect(12, 140, 244, 198)
|
draw2d.Rect(gc, 12, 140, 244, 198)
|
||||||
wheel1 = new(draw2d.Path)
|
wheel1 = new(draw2d.PathStorage)
|
||||||
wheel1.ArcTo(64, 192, 40, 40, 0, 2*math.Pi)
|
wheel1.ArcTo(64, 192, 40, 40, 0, 2*math.Pi)
|
||||||
wheel2 = new(draw2d.Path)
|
wheel2 = new(draw2d.PathStorage)
|
||||||
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)
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright 2010 The draw2d Authors. All rights reserved.
|
|
||||||
// created: 21/11/2010 by Laurent Le Goff
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
//"draw2d"
|
|
||||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
path := new(draw2d.Path)
|
|
||||||
path.MoveTo(2.0, 3.0)
|
|
||||||
path.LineTo(2.0, 3.0)
|
|
||||||
path.QuadCurveTo(2.0, 3.0, 10, 20)
|
|
||||||
path.CubicCurveTo(2.0, 3.0, 10, 20, 13, 23)
|
|
||||||
path.Rect(2.0, 3.0, 100, 200)
|
|
||||||
path.ArcTo(2.0, 3.0, 100, 200, 200, 300)
|
|
||||||
fmt.Printf("%v\n", path)
|
|
||||||
}
|
|
39
draw2d/src/pkg/draw2d/advanced_path.go
Normal file
39
draw2d/src/pkg/draw2d/advanced_path.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package draw2d
|
||||||
|
|
||||||
|
import(
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
//high level path creation
|
||||||
|
func Rect(path Path, x1, y1, x2, y2 float) {
|
||||||
|
path.MoveTo(x1, y1)
|
||||||
|
path.LineTo(x2, y1)
|
||||||
|
path.LineTo(x2, y2)
|
||||||
|
path.LineTo(x1, y2)
|
||||||
|
path.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RoundRect(path Path, x1, y1, x2, y2, arcWidth, arcHeight float) {
|
||||||
|
arcWidth = arcWidth/2;
|
||||||
|
arcHeight = arcHeight/2;
|
||||||
|
path.MoveTo(x1, y1+ arcHeight);
|
||||||
|
path.QuadCurveTo(x1, y1, x1 + arcWidth, y1);
|
||||||
|
path.LineTo(x2-arcWidth, y1);
|
||||||
|
path.QuadCurveTo(x2, y1, x2, y1 + arcHeight);
|
||||||
|
path.LineTo(x2, y2-arcHeight);
|
||||||
|
path.QuadCurveTo(x2, y2, x2 - arcWidth, y2);
|
||||||
|
path.LineTo(x1 + arcWidth, y2);
|
||||||
|
path.QuadCurveTo(x1, y2, x1, y2 - arcHeight);
|
||||||
|
path.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ellipse(path Path, cx, cy, rx, ry float) {
|
||||||
|
path.ArcTo(cx, cy, rx, ry, 0, -math.Pi * 2)
|
||||||
|
path.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Circle(path Path, cx, cy, radius float) {
|
||||||
|
path.ArcTo(cx, cy, radius, radius, 0, -math.Pi * 2)
|
||||||
|
path.Close()
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ type DashAdder struct {
|
||||||
dashOffset float
|
dashOffset float
|
||||||
}
|
}
|
||||||
|
|
||||||
func traceDashPath(dash []float, dashOffset float, approximationScale float, adder raster.Adder, paths ...*Path) {
|
func traceDashPath(dash []float, dashOffset float, approximationScale float, adder raster.Adder, paths ...*PathStorage) {
|
||||||
var dasher DashAdder
|
var dasher DashAdder
|
||||||
if dash != nil && len(dash) > 0 {
|
if dash != nil && len(dash) > 0 {
|
||||||
dasher.dash = dash
|
dasher.dash = dash
|
||||||
|
|
|
@ -6,7 +6,6 @@ package draw2d
|
||||||
import (
|
import (
|
||||||
"exp/draw"
|
"exp/draw"
|
||||||
"image"
|
"image"
|
||||||
"math"
|
|
||||||
"freetype-go.googlecode.com/hg/freetype/raster"
|
"freetype-go.googlecode.com/hg/freetype/raster"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,7 +40,7 @@ type GraphicContext struct {
|
||||||
|
|
||||||
type contextStack struct {
|
type contextStack struct {
|
||||||
tr MatrixTransform
|
tr MatrixTransform
|
||||||
path *Path
|
path *PathStorage
|
||||||
lineWidth float
|
lineWidth float
|
||||||
dash []float
|
dash []float
|
||||||
dashOffset float
|
dashOffset float
|
||||||
|
@ -65,7 +64,7 @@ func NewGraphicContext(pi *image.RGBA) *GraphicContext {
|
||||||
gc.current = new(contextStack)
|
gc.current = new(contextStack)
|
||||||
|
|
||||||
gc.current.tr = NewIdentityMatrix()
|
gc.current.tr = NewIdentityMatrix()
|
||||||
gc.current.path = new(Path)
|
gc.current.path = new(PathStorage)
|
||||||
gc.current.lineWidth = 1.0
|
gc.current.lineWidth = 1.0
|
||||||
gc.current.strokeColor = image.Black
|
gc.current.strokeColor = image.Black
|
||||||
gc.current.fillColor = image.White
|
gc.current.fillColor = image.White
|
||||||
|
@ -159,7 +158,7 @@ func (gc *GraphicContext) Restore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *GraphicContext) BeginPath() {
|
func (gc *GraphicContext) BeginPath() {
|
||||||
gc.current.path = new(Path)
|
gc.current.path = new(PathStorage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *GraphicContext) MoveTo(x, y float) {
|
func (gc *GraphicContext) MoveTo(x, y float) {
|
||||||
|
@ -202,43 +201,6 @@ func (gc *GraphicContext) RArcTo(dcx, dcy, rx, ry, startAngle, angle float) {
|
||||||
gc.current.path.RArcTo(dcx, dcy, rx, ry, startAngle, angle)
|
gc.current.path.RArcTo(dcx, dcy, rx, ry, startAngle, angle)
|
||||||
}
|
}
|
||||||
|
|
||||||
//high level path creation
|
|
||||||
func (gc *GraphicContext) Rect(x1, y1, x2, y2 float) {
|
|
||||||
if gc.current.path.isEmpty() {
|
|
||||||
gc.current.path.MoveTo(x1, y1)
|
|
||||||
} else {
|
|
||||||
gc.current.path.LineTo(x1, y1)
|
|
||||||
}
|
|
||||||
gc.current.path.LineTo(x2, y1)
|
|
||||||
gc.current.path.LineTo(x2, y2)
|
|
||||||
gc.current.path.LineTo(x1, y2)
|
|
||||||
gc.current.path.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gc *GraphicContext) RoundRect(x1, y1, x2, y2, arcWidth, arcHeight float) {
|
|
||||||
arcWidth = arcWidth/2;
|
|
||||||
arcHeight = arcHeight/2;
|
|
||||||
gc.MoveTo(x1, y1+ arcHeight);
|
|
||||||
gc.QuadCurveTo(x1, y1, x1 + arcWidth, y1);
|
|
||||||
gc.LineTo(x2-arcWidth, y1);
|
|
||||||
gc.QuadCurveTo(x2, y1, x2, y1 + arcHeight);
|
|
||||||
gc.LineTo(x2, y2-arcHeight);
|
|
||||||
gc.QuadCurveTo(x2, y2, x2 - arcWidth, y2);
|
|
||||||
gc.LineTo(x1 + arcWidth, y2);
|
|
||||||
gc.QuadCurveTo(x1, y2, x1, y2 - arcHeight);
|
|
||||||
gc.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gc *GraphicContext) Ellipse(cx, cy, rx, ry float) {
|
|
||||||
gc.current.path.ArcTo(cx, cy, rx, ry, 0, -math.Pi * 2)
|
|
||||||
gc.current.path.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gc *GraphicContext) Circle(cx, cy, radius float) {
|
|
||||||
gc.current.path.ArcTo(cx, cy, radius, radius, 0, -math.Pi * 2)
|
|
||||||
gc.current.path.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gc *GraphicContext) Close() {
|
func (gc *GraphicContext) Close() {
|
||||||
gc.current.path.Close()
|
gc.current.path.Close()
|
||||||
}
|
}
|
||||||
|
@ -248,10 +210,10 @@ func (gc *GraphicContext) paint(color image.Color) {
|
||||||
painter.SetColor(color)
|
painter.SetColor(color)
|
||||||
gc.rasterizer.Rasterize(painter)
|
gc.rasterizer.Rasterize(painter)
|
||||||
gc.rasterizer.Clear()
|
gc.rasterizer.Clear()
|
||||||
gc.current.path = new(Path)
|
gc.current.path = new(PathStorage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *GraphicContext) Stroke(paths ...*Path) {
|
func (gc *GraphicContext) Stroke(paths ...*PathStorage) {
|
||||||
paths = append(paths, gc.current.path)
|
paths = append(paths, gc.current.path)
|
||||||
gc.rasterizer.UseNonZeroWinding = true
|
gc.rasterizer.UseNonZeroWinding = true
|
||||||
rasterPath := new(raster.Path)
|
rasterPath := new(raster.Path)
|
||||||
|
@ -265,7 +227,7 @@ func (gc *GraphicContext) Stroke(paths ...*Path) {
|
||||||
gc.paint(gc.current.strokeColor)
|
gc.paint(gc.current.strokeColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *GraphicContext) Fill(paths ...*Path) {
|
func (gc *GraphicContext) Fill(paths ...*PathStorage) {
|
||||||
paths = append(paths, gc.current.path)
|
paths = append(paths, gc.current.path)
|
||||||
gc.rasterizer.UseNonZeroWinding = gc.current.fillRule.fillRule()
|
gc.rasterizer.UseNonZeroWinding = gc.current.fillRule.fillRule()
|
||||||
mta := NewMatrixTransformAdder(gc.current.tr, gc.rasterizer)
|
mta := NewMatrixTransformAdder(gc.current.tr, gc.rasterizer)
|
||||||
|
@ -273,7 +235,7 @@ func (gc *GraphicContext) Fill(paths ...*Path) {
|
||||||
gc.paint(gc.current.fillColor)
|
gc.paint(gc.current.fillColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *GraphicContext) FillStroke(paths ...*Path) {
|
func (gc *GraphicContext) FillStroke(paths ...*PathStorage) {
|
||||||
paths = append(paths, gc.current.path)
|
paths = append(paths, gc.current.path)
|
||||||
mta := NewMatrixTransformAdder(gc.current.tr, gc.rasterizer)
|
mta := NewMatrixTransformAdder(gc.current.tr, gc.rasterizer)
|
||||||
tracePath(gc.current.tr.GetMaxAbsScaling(), mta, paths...)
|
tracePath(gc.current.tr.GetMaxAbsScaling(), mta, paths...)
|
||||||
|
|
|
@ -3,26 +3,18 @@
|
||||||
|
|
||||||
package draw2d
|
package draw2d
|
||||||
|
|
||||||
import (
|
type Path interface {
|
||||||
"fmt"
|
MoveTo(x, y float)
|
||||||
"math"
|
RMoveTo(dx, dy float)
|
||||||
)
|
LineTo(x, y float)
|
||||||
|
RLineTo(dx, dy float)
|
||||||
type PathCmd int
|
QuadCurveTo(cx, cy, x, y float)
|
||||||
|
RQuadCurveTo(dcx, dcy, dx, dy float)
|
||||||
const (
|
CubicCurveTo(cx1, cy1, cx2, cy2, x, y float)
|
||||||
MoveTo PathCmd = iota
|
RCubicCurveTo(dcx1, dcy1, dcx2, dcy2, dx, dy float)
|
||||||
LineTo
|
ArcTo(cx, cy, rx, ry, startAngle, angle float)
|
||||||
QuadCurveTo
|
RArcTo(dcx, dcy, rx, ry, startAngle, angle float)
|
||||||
CubicCurveTo
|
Close()
|
||||||
ArcTo
|
|
||||||
Close
|
|
||||||
)
|
|
||||||
|
|
||||||
type Path struct {
|
|
||||||
commands []PathCmd
|
|
||||||
vertices []float
|
|
||||||
x, y float
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type LineTracer interface {
|
type LineTracer interface {
|
||||||
|
@ -30,200 +22,3 @@ type LineTracer interface {
|
||||||
LineTo(x, y float)
|
LineTo(x, y float)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Path) appendToPath(cmd PathCmd, vertices ...float) {
|
|
||||||
p.commands = append(p.commands, cmd)
|
|
||||||
p.vertices = append(p.vertices, vertices...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (src *Path) Copy() (dest *Path) {
|
|
||||||
dest = new(Path)
|
|
||||||
dest.commands = make([]PathCmd, len(src.commands))
|
|
||||||
copy(dest.commands, src.commands)
|
|
||||||
dest.vertices = make([]float, len(src.vertices))
|
|
||||||
copy(dest.vertices, src.vertices)
|
|
||||||
return dest
|
|
||||||
}
|
|
||||||
func (p *Path) LastPoint() (x, y float) {
|
|
||||||
return p.x, p.y
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) isEmpty() bool {
|
|
||||||
return len(p.commands) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) Close() *Path {
|
|
||||||
p.appendToPath(Close)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) MoveTo(x, y float) *Path {
|
|
||||||
p.appendToPath(MoveTo, x, y)
|
|
||||||
p.x = x
|
|
||||||
p.y = y
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) RMoveTo(dx, dy float) *Path {
|
|
||||||
x, y := p.LastPoint()
|
|
||||||
p.MoveTo(x+dx, y+dy)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) LineTo(x, y float) *Path {
|
|
||||||
p.appendToPath(LineTo, x, y)
|
|
||||||
p.x = x
|
|
||||||
p.y = y
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) RLineTo(dx, dy float) *Path {
|
|
||||||
x, y := p.LastPoint()
|
|
||||||
p.LineTo(x+dx, y+dy)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) Rect(x1, y1, x2, y2 float) *Path {
|
|
||||||
w, h := x2-x1, y2-y1
|
|
||||||
if len(p.commands) > 0 {
|
|
||||||
p.LineTo(x1, y1)
|
|
||||||
} else {
|
|
||||||
p.MoveTo(x1, y1)
|
|
||||||
}
|
|
||||||
p.LineTo(x1+w, y1)
|
|
||||||
p.LineTo(x1+w, y1+h)
|
|
||||||
p.LineTo(x1, y1+h)
|
|
||||||
p.LineTo(x1, y1)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) RRect(dx1, dy1, dx2, dy2 float) *Path {
|
|
||||||
x, y := p.LastPoint()
|
|
||||||
p.Rect(x+dx1, y+dy1, x+dx2, y+dy2)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) QuadCurveTo(cx, cy, x, y float) *Path {
|
|
||||||
p.appendToPath(QuadCurveTo, cx, cy, x, y)
|
|
||||||
p.x = x
|
|
||||||
p.y = y
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) RQuadCurveTo(dcx, dcy, dx, dy float) *Path {
|
|
||||||
x, y := p.LastPoint()
|
|
||||||
p.RQuadCurveTo(x+dcx, y+dcy, x+dx, y+dy)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float) *Path {
|
|
||||||
p.appendToPath(CubicCurveTo, cx1, cy1, cx2, cy2, x, y)
|
|
||||||
p.x = x
|
|
||||||
p.y = y
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) RCubicCurveTo(dcx1, dcy1, dcx2, dcy2, dx, dy float) *Path {
|
|
||||||
x, y := p.LastPoint()
|
|
||||||
p.RCubicCurveTo(x+dcx1, y+dcy1, x+dcx2, y+dcy2, x+dx, y+dy)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) ArcTo(cx, cy, rx, ry, startAngle, angle float) *Path {
|
|
||||||
endAngle := startAngle + angle
|
|
||||||
clockWise := true
|
|
||||||
if angle < 0 {
|
|
||||||
clockWise = false
|
|
||||||
}
|
|
||||||
// normalize
|
|
||||||
if clockWise {
|
|
||||||
for endAngle < startAngle {
|
|
||||||
endAngle += math.Pi * 2.0
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for startAngle < endAngle {
|
|
||||||
startAngle += math.Pi * 2.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
startX := cx + cos(startAngle)*rx
|
|
||||||
startY := cy + sin(startAngle)*ry
|
|
||||||
if len(p.commands) > 0 {
|
|
||||||
p.LineTo(startX, startY)
|
|
||||||
} else {
|
|
||||||
p.MoveTo(startX, startY)
|
|
||||||
}
|
|
||||||
p.appendToPath(ArcTo, cx, cy, rx, ry, startAngle, angle)
|
|
||||||
p.x = cx + cos(endAngle)*rx
|
|
||||||
p.y = cy + sin(endAngle)*ry
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) RArcTo(dcx, dcy, rx, ry, startAngle, angle float) *Path {
|
|
||||||
x, y := p.LastPoint()
|
|
||||||
p.RArcTo(x+dcx, y+dcy, rx, ry, startAngle, angle)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) TraceLine(tracer LineTracer, approximationScale float) {
|
|
||||||
j := 0
|
|
||||||
x, y := 0.0, 0.0
|
|
||||||
firstX, firstY := x, y
|
|
||||||
if len(p.commands) > 0 {
|
|
||||||
if p.commands[0] == MoveTo {
|
|
||||||
firstX, firstY = p.vertices[0], p.vertices[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, cmd := range p.commands {
|
|
||||||
switch cmd {
|
|
||||||
case MoveTo:
|
|
||||||
tracer.MoveTo(p.vertices[j], p.vertices[j+1])
|
|
||||||
x, y = p.vertices[j], p.vertices[j+1]
|
|
||||||
firstX, firstY = x, y
|
|
||||||
j = j + 2
|
|
||||||
case LineTo:
|
|
||||||
tracer.LineTo(p.vertices[j], p.vertices[j+1])
|
|
||||||
x, y = p.vertices[j], p.vertices[j+1]
|
|
||||||
j = j + 2
|
|
||||||
case QuadCurveTo:
|
|
||||||
quadraticBezier(tracer, x, y, p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], approximationScale, 0)
|
|
||||||
x, y = p.vertices[j+2], p.vertices[j+3]
|
|
||||||
j = j + 4
|
|
||||||
case CubicCurveTo:
|
|
||||||
cubicBezier(tracer, x, y, p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5], approximationScale, 0, 0)
|
|
||||||
x, y = p.vertices[j+4], p.vertices[j+5]
|
|
||||||
j = j + 6
|
|
||||||
case ArcTo:
|
|
||||||
arc(tracer, p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5], approximationScale)
|
|
||||||
j = j + 6
|
|
||||||
case Close:
|
|
||||||
tracer.LineTo(firstX, firstY)
|
|
||||||
x, y = firstX, firstY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Path) String() string {
|
|
||||||
s := ""
|
|
||||||
j := 0
|
|
||||||
for _, cmd := range p.commands {
|
|
||||||
switch cmd {
|
|
||||||
case MoveTo:
|
|
||||||
s += fmt.Sprintf("MoveTo: %f, %f\n", p.vertices[j], p.vertices[j+1])
|
|
||||||
j = j + 2
|
|
||||||
case LineTo:
|
|
||||||
s += fmt.Sprintf("LineTo: %f, %f\n", p.vertices[j], p.vertices[j+1])
|
|
||||||
j = j + 2
|
|
||||||
case QuadCurveTo:
|
|
||||||
s += fmt.Sprintf("QuadCurveTo: %f, %f, %f, %f\n", p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3])
|
|
||||||
j = j + 4
|
|
||||||
case CubicCurveTo:
|
|
||||||
s += fmt.Sprintf("CubicCurveTo: %f, %f, %f, %f, %f, %f\n", p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5])
|
|
||||||
j = j + 6
|
|
||||||
case ArcTo:
|
|
||||||
s += fmt.Sprintf("ArcTo: %f, %f, %f, %f, %f, %f\n", p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5])
|
|
||||||
j = j + 6
|
|
||||||
case Close:
|
|
||||||
s += "Close\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ func floatToPoint(x, y float) raster.Point {
|
||||||
return raster.Point{raster.Fix32(x * 256), raster.Fix32(y * 256)}
|
return raster.Point{raster.Fix32(x * 256), raster.Fix32(y * 256)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tracePath(approximationScale float, adder raster.Adder, paths ...*Path) {
|
func tracePath(approximationScale float, adder raster.Adder, paths ...*PathStorage) {
|
||||||
pathAdder := &PathAdder{adder}
|
pathAdder := &PathAdder{adder}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
path.TraceLine(pathAdder, approximationScale)
|
path.TraceLine(pathAdder, approximationScale)
|
||||||
|
|
203
draw2d/src/pkg/draw2d/path_storage.go
Normal file
203
draw2d/src/pkg/draw2d/path_storage.go
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
// Copyright 2010 The draw2d Authors. All rights reserved.
|
||||||
|
// created: 21/11/2010 by Laurent Le Goff
|
||||||
|
package draw2d
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PathCmd int
|
||||||
|
|
||||||
|
const (
|
||||||
|
MoveTo PathCmd = iota
|
||||||
|
LineTo
|
||||||
|
QuadCurveTo
|
||||||
|
CubicCurveTo
|
||||||
|
ArcTo
|
||||||
|
Close
|
||||||
|
)
|
||||||
|
|
||||||
|
type PathStorage struct {
|
||||||
|
commands []PathCmd
|
||||||
|
vertices []float
|
||||||
|
x, y float
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) appendToPath(cmd PathCmd, vertices ...float) {
|
||||||
|
p.commands = append(p.commands, cmd)
|
||||||
|
p.vertices = append(p.vertices, vertices...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src *PathStorage) Copy() (dest *PathStorage) {
|
||||||
|
dest = new(PathStorage)
|
||||||
|
dest.commands = make([]PathCmd, len(src.commands))
|
||||||
|
copy(dest.commands, src.commands)
|
||||||
|
dest.vertices = make([]float, len(src.vertices))
|
||||||
|
copy(dest.vertices, src.vertices)
|
||||||
|
return dest
|
||||||
|
}
|
||||||
|
func (p *PathStorage) LastPoint() (x, y float) {
|
||||||
|
return p.x, p.y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) isEmpty() bool {
|
||||||
|
return len(p.commands) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) Close() *PathStorage {
|
||||||
|
p.appendToPath(Close)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) MoveTo(x, y float) *PathStorage {
|
||||||
|
p.appendToPath(MoveTo, x, y)
|
||||||
|
p.x = x
|
||||||
|
p.y = y
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) RMoveTo(dx, dy float) *PathStorage {
|
||||||
|
x, y := p.LastPoint()
|
||||||
|
p.MoveTo(x+dx, y+dy)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) LineTo(x, y float) *PathStorage {
|
||||||
|
p.appendToPath(LineTo, x, y)
|
||||||
|
p.x = x
|
||||||
|
p.y = y
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) RLineTo(dx, dy float) *PathStorage {
|
||||||
|
x, y := p.LastPoint()
|
||||||
|
p.LineTo(x+dx, y+dy)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) QuadCurveTo(cx, cy, x, y float) *PathStorage {
|
||||||
|
p.appendToPath(QuadCurveTo, cx, cy, x, y)
|
||||||
|
p.x = x
|
||||||
|
p.y = y
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) RQuadCurveTo(dcx, dcy, dx, dy float) *PathStorage {
|
||||||
|
x, y := p.LastPoint()
|
||||||
|
p.RQuadCurveTo(x+dcx, y+dcy, x+dx, y+dy)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float) *PathStorage {
|
||||||
|
p.appendToPath(CubicCurveTo, cx1, cy1, cx2, cy2, x, y)
|
||||||
|
p.x = x
|
||||||
|
p.y = y
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) RCubicCurveTo(dcx1, dcy1, dcx2, dcy2, dx, dy float) *PathStorage {
|
||||||
|
x, y := p.LastPoint()
|
||||||
|
p.RCubicCurveTo(x+dcx1, y+dcy1, x+dcx2, y+dcy2, x+dx, y+dy)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) ArcTo(cx, cy, rx, ry, startAngle, angle float) *PathStorage {
|
||||||
|
endAngle := startAngle + angle
|
||||||
|
clockWise := true
|
||||||
|
if angle < 0 {
|
||||||
|
clockWise = false
|
||||||
|
}
|
||||||
|
// normalize
|
||||||
|
if clockWise {
|
||||||
|
for endAngle < startAngle {
|
||||||
|
endAngle += math.Pi * 2.0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for startAngle < endAngle {
|
||||||
|
startAngle += math.Pi * 2.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startX := cx + cos(startAngle)*rx
|
||||||
|
startY := cy + sin(startAngle)*ry
|
||||||
|
if len(p.commands) > 0 {
|
||||||
|
p.LineTo(startX, startY)
|
||||||
|
} else {
|
||||||
|
p.MoveTo(startX, startY)
|
||||||
|
}
|
||||||
|
p.appendToPath(ArcTo, cx, cy, rx, ry, startAngle, angle)
|
||||||
|
p.x = cx + cos(endAngle)*rx
|
||||||
|
p.y = cy + sin(endAngle)*ry
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) RArcTo(dcx, dcy, rx, ry, startAngle, angle float) *PathStorage {
|
||||||
|
x, y := p.LastPoint()
|
||||||
|
p.RArcTo(x+dcx, y+dcy, rx, ry, startAngle, angle)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) TraceLine(tracer LineTracer, approximationScale float) {
|
||||||
|
j := 0
|
||||||
|
x, y := 0.0, 0.0
|
||||||
|
firstX, firstY := x, y
|
||||||
|
if len(p.commands) > 0 {
|
||||||
|
if p.commands[0] == MoveTo {
|
||||||
|
firstX, firstY = p.vertices[0], p.vertices[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, cmd := range p.commands {
|
||||||
|
switch cmd {
|
||||||
|
case MoveTo:
|
||||||
|
tracer.MoveTo(p.vertices[j], p.vertices[j+1])
|
||||||
|
x, y = p.vertices[j], p.vertices[j+1]
|
||||||
|
firstX, firstY = x, y
|
||||||
|
j = j + 2
|
||||||
|
case LineTo:
|
||||||
|
tracer.LineTo(p.vertices[j], p.vertices[j+1])
|
||||||
|
x, y = p.vertices[j], p.vertices[j+1]
|
||||||
|
j = j + 2
|
||||||
|
case QuadCurveTo:
|
||||||
|
quadraticBezier(tracer, x, y, p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], approximationScale, 0)
|
||||||
|
x, y = p.vertices[j+2], p.vertices[j+3]
|
||||||
|
j = j + 4
|
||||||
|
case CubicCurveTo:
|
||||||
|
cubicBezier(tracer, x, y, p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5], approximationScale, 0, 0)
|
||||||
|
x, y = p.vertices[j+4], p.vertices[j+5]
|
||||||
|
j = j + 6
|
||||||
|
case ArcTo:
|
||||||
|
arc(tracer, p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5], approximationScale)
|
||||||
|
j = j + 6
|
||||||
|
case Close:
|
||||||
|
tracer.LineTo(firstX, firstY)
|
||||||
|
x, y = firstX, firstY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PathStorage) String() string {
|
||||||
|
s := ""
|
||||||
|
j := 0
|
||||||
|
for _, cmd := range p.commands {
|
||||||
|
switch cmd {
|
||||||
|
case MoveTo:
|
||||||
|
s += fmt.Sprintf("MoveTo: %f, %f\n", p.vertices[j], p.vertices[j+1])
|
||||||
|
j = j + 2
|
||||||
|
case LineTo:
|
||||||
|
s += fmt.Sprintf("LineTo: %f, %f\n", p.vertices[j], p.vertices[j+1])
|
||||||
|
j = j + 2
|
||||||
|
case QuadCurveTo:
|
||||||
|
s += fmt.Sprintf("QuadCurveTo: %f, %f, %f, %f\n", p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3])
|
||||||
|
j = j + 4
|
||||||
|
case CubicCurveTo:
|
||||||
|
s += fmt.Sprintf("CubicCurveTo: %f, %f, %f, %f, %f, %f\n", p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5])
|
||||||
|
j = j + 6
|
||||||
|
case ArcTo:
|
||||||
|
s += fmt.Sprintf("ArcTo: %f, %f, %f, %f, %f, %f\n", p.vertices[j], p.vertices[j+1], p.vertices[j+2], p.vertices[j+3], p.vertices[j+4], p.vertices[j+5])
|
||||||
|
j = j + 6
|
||||||
|
case Close:
|
||||||
|
s += "Close\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
Loading…
Reference in a new issue