mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 11:18:54 +01:00
parent
f04e391cb4
commit
a75472b524
@ -63,6 +63,7 @@ func drawEbitenText(screen *ebiten.Image, x, y int, aa bool, line bool) {
|
|||||||
path.LineTo(30, 30)
|
path.LineTo(30, 30)
|
||||||
path.LineTo(70, 30)
|
path.LineTo(70, 30)
|
||||||
path.LineTo(70, 20)
|
path.LineTo(70, 20)
|
||||||
|
path.Close()
|
||||||
|
|
||||||
// B
|
// B
|
||||||
path.MoveTo(80, 20)
|
path.MoveTo(80, 20)
|
||||||
@ -70,12 +71,14 @@ func drawEbitenText(screen *ebiten.Image, x, y int, aa bool, line bool) {
|
|||||||
path.LineTo(100, 70)
|
path.LineTo(100, 70)
|
||||||
path.QuadTo(150, 57.5, 100, 45)
|
path.QuadTo(150, 57.5, 100, 45)
|
||||||
path.QuadTo(150, 32.5, 100, 20)
|
path.QuadTo(150, 32.5, 100, 20)
|
||||||
|
path.Close()
|
||||||
|
|
||||||
// I
|
// I
|
||||||
path.MoveTo(140, 20)
|
path.MoveTo(140, 20)
|
||||||
path.LineTo(140, 70)
|
path.LineTo(140, 70)
|
||||||
path.LineTo(150, 70)
|
path.LineTo(150, 70)
|
||||||
path.LineTo(150, 20)
|
path.LineTo(150, 20)
|
||||||
|
path.Close()
|
||||||
|
|
||||||
// T
|
// T
|
||||||
path.MoveTo(160, 20)
|
path.MoveTo(160, 20)
|
||||||
@ -86,6 +89,7 @@ func drawEbitenText(screen *ebiten.Image, x, y int, aa bool, line bool) {
|
|||||||
path.LineTo(190, 30)
|
path.LineTo(190, 30)
|
||||||
path.LineTo(210, 30)
|
path.LineTo(210, 30)
|
||||||
path.LineTo(210, 20)
|
path.LineTo(210, 20)
|
||||||
|
path.Close()
|
||||||
|
|
||||||
// E
|
// E
|
||||||
path.MoveTo(220, 20)
|
path.MoveTo(220, 20)
|
||||||
@ -100,6 +104,7 @@ func drawEbitenText(screen *ebiten.Image, x, y int, aa bool, line bool) {
|
|||||||
path.LineTo(230, 30)
|
path.LineTo(230, 30)
|
||||||
path.LineTo(270, 30)
|
path.LineTo(270, 30)
|
||||||
path.LineTo(270, 20)
|
path.LineTo(270, 20)
|
||||||
|
path.Close()
|
||||||
|
|
||||||
// N
|
// N
|
||||||
path.MoveTo(280, 20)
|
path.MoveTo(280, 20)
|
||||||
@ -112,6 +117,7 @@ func drawEbitenText(screen *ebiten.Image, x, y int, aa bool, line bool) {
|
|||||||
path.LineTo(320, 20)
|
path.LineTo(320, 20)
|
||||||
path.LineTo(320, 55)
|
path.LineTo(320, 55)
|
||||||
path.LineTo(290, 20)
|
path.LineTo(290, 20)
|
||||||
|
path.Close()
|
||||||
|
|
||||||
var vs []ebiten.Vertex
|
var vs []ebiten.Vertex
|
||||||
var is []uint16
|
var is []uint16
|
||||||
@ -166,6 +172,7 @@ func drawEbitenLogo(screen *ebiten.Image, x, y int, aa bool, line bool) {
|
|||||||
path.LineTo(2*unit, 3*unit)
|
path.LineTo(2*unit, 3*unit)
|
||||||
path.LineTo(unit, 3*unit)
|
path.LineTo(unit, 3*unit)
|
||||||
path.LineTo(unit, 4*unit)
|
path.LineTo(unit, 4*unit)
|
||||||
|
path.Close()
|
||||||
|
|
||||||
var vs []ebiten.Vertex
|
var vs []ebiten.Vertex
|
||||||
var is []uint16
|
var is []uint16
|
||||||
@ -209,6 +216,7 @@ func drawArc(screen *ebiten.Image, count int, aa bool, line bool) {
|
|||||||
theta2 := math.Pi * float64(count) / 180 / 3
|
theta2 := math.Pi * float64(count) / 180 / 3
|
||||||
path.MoveTo(550, 100)
|
path.MoveTo(550, 100)
|
||||||
path.Arc(550, 100, 50, float32(theta1), float32(theta2), vector.Clockwise)
|
path.Arc(550, 100, 50, float32(theta1), float32(theta2), vector.Clockwise)
|
||||||
|
path.Close()
|
||||||
|
|
||||||
var vs []ebiten.Vertex
|
var vs []ebiten.Vertex
|
||||||
var is []uint16
|
var is []uint16
|
||||||
|
115
vector/path.go
115
vector/path.go
@ -36,31 +36,67 @@ type point struct {
|
|||||||
y float32
|
y float32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path represents a collection of path segments.
|
type subpath struct {
|
||||||
type Path struct {
|
points []point
|
||||||
segs [][]point
|
closed bool
|
||||||
cur point
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveTo skips the current position of the path to the given position (x, y) without adding any strokes.
|
func (s *subpath) pointCount() int {
|
||||||
|
return len(s.points)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *subpath) lastPoint() point {
|
||||||
|
return s.points[len(s.points)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *subpath) appendPoint(pt point) {
|
||||||
|
if s.closed {
|
||||||
|
panic("vector: a closed subpathment cannot append a new point")
|
||||||
|
}
|
||||||
|
if s.lastPoint() == pt {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.points = append(s.points, pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *subpath) close() {
|
||||||
|
if s.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.appendPoint(s.points[0])
|
||||||
|
s.closed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path represents a collection of path subpathments.
|
||||||
|
type Path struct {
|
||||||
|
subpaths []*subpath
|
||||||
|
cur point
|
||||||
|
}
|
||||||
|
|
||||||
|
// MoveTo starts a new subpath with the given position (x, y) without adding any strokes,
|
||||||
|
//
|
||||||
|
// MoveTo updates the current position to (x, y).
|
||||||
func (p *Path) MoveTo(x, y float32) {
|
func (p *Path) MoveTo(x, y float32) {
|
||||||
p.cur = point{x: x, y: y}
|
p.cur = point{x: x, y: y}
|
||||||
p.segs = append(p.segs, []point{p.cur})
|
p.subpaths = append(p.subpaths, &subpath{
|
||||||
|
points: []point{p.cur},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// LineTo adds a line segument to the path, which starts from the current position and ends to the given position (x, y).
|
// LineTo adds a line segument to the path, which starts from the current position and ends to the given position (x, y).
|
||||||
//
|
//
|
||||||
// LineTo updates the current position to (x, y).
|
// LineTo updates the current position to (x, y).
|
||||||
func (p *Path) LineTo(x, y float32) {
|
func (p *Path) LineTo(x, y float32) {
|
||||||
if len(p.segs) == 0 {
|
if len(p.subpaths) == 0 || p.subpaths[len(p.subpaths)-1].closed {
|
||||||
p.segs = append(p.segs, []point{{x: x, y: y}})
|
p.subpaths = append(p.subpaths, &subpath{
|
||||||
|
points: []point{{x: x, y: y}},
|
||||||
|
})
|
||||||
p.cur = point{x: x, y: y}
|
p.cur = point{x: x, y: y}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
seg := p.segs[len(p.segs)-1]
|
|
||||||
if seg[len(seg)-1].x != x || seg[len(seg)-1].y != y {
|
p.subpaths[len(p.subpaths)-1].appendPoint(point{x: x, y: y})
|
||||||
p.segs[len(p.segs)-1] = append(seg, point{x: x, y: y})
|
|
||||||
}
|
|
||||||
p.cur = point{x: x, y: y}
|
p.cur = point{x: x, y: y}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,6 +347,19 @@ func (p *Path) Arc(x, y, radius, startAngle, endAngle float32, dir Direction) {
|
|||||||
p.CubicTo(cx0, cy0, cx1, cy1, x1, y1)
|
p.CubicTo(cx0, cy0, cx1, cy1, x1, y1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close adds a new line from the current position to the first position of the current subpath,
|
||||||
|
// and marks the current subpath closed.
|
||||||
|
// Following operations for this path will start with a new subpath.
|
||||||
|
//
|
||||||
|
// Close updates the current position to the first position of the current subpath.
|
||||||
|
func (p *Path) Close() {
|
||||||
|
if len(p.subpaths) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
subpath := p.subpaths[len(p.subpaths)-1]
|
||||||
|
subpath.close()
|
||||||
|
}
|
||||||
|
|
||||||
// AppendVerticesAndIndicesForFilling appends vertices and indices to fill this path and returns them.
|
// AppendVerticesAndIndicesForFilling appends vertices and indices to fill this path and returns them.
|
||||||
// AppendVerticesAndIndicesForFilling works in a similar way to the built-in append function.
|
// AppendVerticesAndIndicesForFilling works in a similar way to the built-in append function.
|
||||||
// If the arguments are nils, AppendVerticesAndIndicesForFilling returns new slices.
|
// If the arguments are nils, AppendVerticesAndIndicesForFilling returns new slices.
|
||||||
@ -326,11 +375,11 @@ func (p *Path) AppendVerticesAndIndicesForFilling(vertices []ebiten.Vertex, indi
|
|||||||
// TODO: Add tests.
|
// TODO: Add tests.
|
||||||
|
|
||||||
base := uint16(len(vertices))
|
base := uint16(len(vertices))
|
||||||
for _, seg := range p.segs {
|
for _, subpath := range p.subpaths {
|
||||||
if len(seg) < 3 {
|
if subpath.pointCount() < 3 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for i, pt := range seg {
|
for i, pt := range subpath.points {
|
||||||
vertices = append(vertices, ebiten.Vertex{
|
vertices = append(vertices, ebiten.Vertex{
|
||||||
DstX: pt.x,
|
DstX: pt.x,
|
||||||
DstY: pt.y,
|
DstY: pt.y,
|
||||||
@ -346,7 +395,7 @@ func (p *Path) AppendVerticesAndIndicesForFilling(vertices []ebiten.Vertex, indi
|
|||||||
}
|
}
|
||||||
indices = append(indices, base, base+uint16(i-1), base+uint16(i))
|
indices = append(indices, base, base+uint16(i-1), base+uint16(i))
|
||||||
}
|
}
|
||||||
base += uint16(len(seg))
|
base += uint16(subpath.pointCount())
|
||||||
}
|
}
|
||||||
return vertices, indices
|
return vertices, indices
|
||||||
}
|
}
|
||||||
@ -372,13 +421,18 @@ const (
|
|||||||
// StokeOptions is options to render a stroke.
|
// StokeOptions is options to render a stroke.
|
||||||
type StrokeOptions struct {
|
type StrokeOptions struct {
|
||||||
// Width is the stroke width in pixels.
|
// Width is the stroke width in pixels.
|
||||||
|
//
|
||||||
|
// The default (zero) value is 0.
|
||||||
Width float32
|
Width float32
|
||||||
|
|
||||||
// LineCap is the way in which how the ends of the stroke are rendered.
|
// LineCap is the way in which how the ends of the stroke are rendered.
|
||||||
|
// Line caps are not rendered when the subpath is marked as closed.
|
||||||
|
//
|
||||||
// The default (zero) value is LineCapButt.
|
// The default (zero) value is LineCapButt.
|
||||||
LineCap LineCap
|
LineCap LineCap
|
||||||
|
|
||||||
// LineJoin is the way in which how two segments are joined.
|
// LineJoin is the way in which how two segments are joined.
|
||||||
|
//
|
||||||
// The default (zero) value is LineJoiMiter.
|
// The default (zero) value is LineJoiMiter.
|
||||||
LineJoin LineJoin
|
LineJoin LineJoin
|
||||||
|
|
||||||
@ -401,19 +455,16 @@ func (p *Path) AppendVerticesAndIndicesForStroke(vertices []ebiten.Vertex, indic
|
|||||||
return vertices, indices
|
return vertices, indices
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, seg := range p.segs {
|
for _, subpath := range p.subpaths {
|
||||||
if len(seg) < 2 {
|
if subpath.pointCount() < 2 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var rects [][4]point
|
var rects [][4]point
|
||||||
for i := 0; i < len(seg)-1; i++ {
|
for i := 0; i < subpath.pointCount()-1; i++ {
|
||||||
pt := seg[i]
|
pt := subpath.points[i]
|
||||||
if seg[i+1] == pt {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
nextPt := seg[i+1]
|
nextPt := subpath.points[i+1]
|
||||||
dx := nextPt.x - pt.x
|
dx := nextPt.x - pt.x
|
||||||
dy := nextPt.y - pt.y
|
dy := nextPt.y - pt.y
|
||||||
dist := float32(math.Sqrt(float64(dx*dx + dy*dy)))
|
dist := float32(math.Sqrt(float64(dx*dx + dy*dy)))
|
||||||
@ -456,13 +507,16 @@ func (p *Path) AppendVerticesAndIndicesForStroke(vertices []ebiten.Vertex, indic
|
|||||||
}
|
}
|
||||||
indices = append(indices, idx, idx+1, idx+2, idx+1, idx+2, idx+3)
|
indices = append(indices, idx, idx+1, idx+2, idx+1, idx+2, idx+3)
|
||||||
|
|
||||||
if i >= len(rects)-1 {
|
// Add line joints.
|
||||||
|
var nextRect [4]point
|
||||||
|
if i < len(rects)-1 {
|
||||||
|
nextRect = rects[i+1]
|
||||||
|
} else if subpath.closed {
|
||||||
|
nextRect = rects[0]
|
||||||
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add line joints.
|
|
||||||
nextRect := rects[i+1]
|
|
||||||
|
|
||||||
// c is the center of the 'end' edge of the current rect (= the second point of the segment).
|
// c is the center of the 'end' edge of the current rect (= the second point of the segment).
|
||||||
c := point{
|
c := point{
|
||||||
x: (rect[1].x + rect[3].x) / 2,
|
x: (rect[1].x + rect[3].x) / 2,
|
||||||
@ -532,6 +586,11 @@ func (p *Path) AppendVerticesAndIndicesForStroke(vertices []ebiten.Vertex, indic
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the subpath is closed, do not render line caps.
|
||||||
|
if subpath.closed {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
switch op.LineCap {
|
switch op.LineCap {
|
||||||
case LineCapButt:
|
case LineCapButt:
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
Loading…
Reference in New Issue
Block a user