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/png"
|
||||
//"draw2d"
|
||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
"draw2d"
|
||||
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"exp/draw/x11"
|
||||
"image"
|
||||
"math"
|
||||
//"draw2d"
|
||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
"draw2d"
|
||||
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
|
||||
"image"
|
||||
"image/png"
|
||||
//"draw2d"
|
||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
"draw2d"
|
||||
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -75,52 +75,52 @@ func gordon(gc *draw2d.GraphicContext, x, y, w, h float) {
|
|||
gc.Close()
|
||||
gc.SetFillColor(brb)
|
||||
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.Circle(x, y+h, w/12) // left ear
|
||||
draw2d.Circle(gc,x, y+h, w/12) // left ear
|
||||
gc.SetFillColor(brf)
|
||||
gc.Fill()
|
||||
gc.Circle(x, y+h, w/12-10)
|
||||
draw2d.Circle(gc, x, y+h, w/12-10)
|
||||
gc.SetFillColor(nf)
|
||||
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.Fill()
|
||||
gc.Circle(x+w, y+h, w/12-10)
|
||||
draw2d.Circle(gc, x+w, y+h, w/12-10)
|
||||
gc.SetFillColor(nf)
|
||||
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.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.Fill()
|
||||
gc.Circle(x+w/3+15, y+h23, 5)
|
||||
draw2d.Circle(gc, x+w/3+15, y+h23, 5)
|
||||
gc.SetFillColor(wf)
|
||||
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.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.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.Fill()
|
||||
|
||||
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.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.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.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.Fill()
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
"math"
|
||||
"image"
|
||||
"image/png"
|
||||
//"draw2d"
|
||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
"draw2d"
|
||||
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -71,21 +71,21 @@ func android(gc *draw2d.GraphicContext, x, y float) {
|
|||
gc.MoveTo(x+100, y+25)
|
||||
gc.LineTo( x+110, y+10)
|
||||
gc.Stroke()
|
||||
gc.Circle(x+60, y+45, 5) // left eye
|
||||
draw2d.Circle(gc, x+60, y+45, 5) // left eye
|
||||
gc.FillStroke()
|
||||
gc.Circle(x+100, y+45, 5) // right eye
|
||||
draw2d.Circle(gc, x+100, y+45, 5) // right eye
|
||||
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.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.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.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.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.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()
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ import (
|
|||
"math"
|
||||
"image"
|
||||
"image/png"
|
||||
//"draw2d"
|
||||
"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
"draw2d"
|
||||
//"draw2d.googlecode.com/svn/trunk/draw2d/src/pkg/draw2d"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -283,11 +283,11 @@ func TestFillStyle() {
|
|||
i, gc := initGc(w, h)
|
||||
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)
|
||||
wheel2 := new(draw2d.Path)
|
||||
wheel2 := new(draw2d.PathStorage)
|
||||
wheel2.ArcTo(192, 64, 40, 40, 0, 2*math.Pi)
|
||||
|
||||
gc.SetFillRule(draw2d.FillRuleEvenOdd)
|
||||
|
@ -296,10 +296,10 @@ func TestFillStyle() {
|
|||
gc.SetStrokeColor(image.Black)
|
||||
gc.FillStroke(wheel1, wheel2)
|
||||
|
||||
gc.Rect(12, 140, 244, 198)
|
||||
wheel1 = new(draw2d.Path)
|
||||
draw2d.Rect(gc, 12, 140, 244, 198)
|
||||
wheel1 = new(draw2d.PathStorage)
|
||||
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)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
if dash != nil && len(dash) > 0 {
|
||||
dasher.dash = dash
|
||||
|
|
|
@ -6,7 +6,6 @@ package draw2d
|
|||
import (
|
||||
"exp/draw"
|
||||
"image"
|
||||
"math"
|
||||
"freetype-go.googlecode.com/hg/freetype/raster"
|
||||
)
|
||||
|
||||
|
@ -41,7 +40,7 @@ type GraphicContext struct {
|
|||
|
||||
type contextStack struct {
|
||||
tr MatrixTransform
|
||||
path *Path
|
||||
path *PathStorage
|
||||
lineWidth float
|
||||
dash []float
|
||||
dashOffset float
|
||||
|
@ -65,7 +64,7 @@ func NewGraphicContext(pi *image.RGBA) *GraphicContext {
|
|||
gc.current = new(contextStack)
|
||||
|
||||
gc.current.tr = NewIdentityMatrix()
|
||||
gc.current.path = new(Path)
|
||||
gc.current.path = new(PathStorage)
|
||||
gc.current.lineWidth = 1.0
|
||||
gc.current.strokeColor = image.Black
|
||||
gc.current.fillColor = image.White
|
||||
|
@ -159,7 +158,7 @@ func (gc *GraphicContext) Restore() {
|
|||
}
|
||||
|
||||
func (gc *GraphicContext) BeginPath() {
|
||||
gc.current.path = new(Path)
|
||||
gc.current.path = new(PathStorage)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
//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() {
|
||||
gc.current.path.Close()
|
||||
}
|
||||
|
@ -248,10 +210,10 @@ func (gc *GraphicContext) paint(color image.Color) {
|
|||
painter.SetColor(color)
|
||||
gc.rasterizer.Rasterize(painter)
|
||||
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)
|
||||
gc.rasterizer.UseNonZeroWinding = true
|
||||
rasterPath := new(raster.Path)
|
||||
|
@ -265,7 +227,7 @@ func (gc *GraphicContext) Stroke(paths ...*Path) {
|
|||
gc.paint(gc.current.strokeColor)
|
||||
}
|
||||
|
||||
func (gc *GraphicContext) Fill(paths ...*Path) {
|
||||
func (gc *GraphicContext) Fill(paths ...*PathStorage) {
|
||||
paths = append(paths, gc.current.path)
|
||||
gc.rasterizer.UseNonZeroWinding = gc.current.fillRule.fillRule()
|
||||
mta := NewMatrixTransformAdder(gc.current.tr, gc.rasterizer)
|
||||
|
@ -273,7 +235,7 @@ func (gc *GraphicContext) Fill(paths ...*Path) {
|
|||
gc.paint(gc.current.fillColor)
|
||||
}
|
||||
|
||||
func (gc *GraphicContext) FillStroke(paths ...*Path) {
|
||||
func (gc *GraphicContext) FillStroke(paths ...*PathStorage) {
|
||||
paths = append(paths, gc.current.path)
|
||||
mta := NewMatrixTransformAdder(gc.current.tr, gc.rasterizer)
|
||||
tracePath(gc.current.tr.GetMaxAbsScaling(), mta, paths...)
|
||||
|
|
|
@ -3,26 +3,18 @@
|
|||
|
||||
package draw2d
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
type PathCmd int
|
||||
|
||||
const (
|
||||
MoveTo PathCmd = iota
|
||||
LineTo
|
||||
QuadCurveTo
|
||||
CubicCurveTo
|
||||
ArcTo
|
||||
Close
|
||||
)
|
||||
|
||||
type Path struct {
|
||||
commands []PathCmd
|
||||
vertices []float
|
||||
x, y float
|
||||
type Path interface {
|
||||
MoveTo(x, y float)
|
||||
RMoveTo(dx, dy float)
|
||||
LineTo(x, y float)
|
||||
RLineTo(dx, dy float)
|
||||
QuadCurveTo(cx, cy, x, y float)
|
||||
RQuadCurveTo(dcx, dcy, dx, dy float)
|
||||
CubicCurveTo(cx1, cy1, cx2, cy2, x, y float)
|
||||
RCubicCurveTo(dcx1, dcy1, dcx2, dcy2, dx, dy float)
|
||||
ArcTo(cx, cy, rx, ry, startAngle, angle float)
|
||||
RArcTo(dcx, dcy, rx, ry, startAngle, angle float)
|
||||
Close()
|
||||
}
|
||||
|
||||
type LineTracer interface {
|
||||
|
@ -30,200 +22,3 @@ type LineTracer interface {
|
|||
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)}
|
||||
}
|
||||
|
||||
func tracePath(approximationScale float, adder raster.Adder, paths ...*Path) {
|
||||
func tracePath(approximationScale float, adder raster.Adder, paths ...*PathStorage) {
|
||||
pathAdder := &PathAdder{adder}
|
||||
for _, path := range paths {
|
||||
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