Skip to content

Commit

Permalink
vector: add (*Path).ApplyGeoM
Browse files Browse the repository at this point in the history
Closes #3150
Closes #3159
  • Loading branch information
hajimehoshi committed Nov 9, 2024
1 parent e860747 commit db04c37
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 68 deletions.
36 changes: 4 additions & 32 deletions examples/fontvector/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package main

import (
"bytes"
"image"
"image/color"
"log"
"math"
Expand All @@ -27,28 +26,13 @@ import (
"github.com/hajimehoshi/ebiten/v2/vector"
)

var (
whiteImage = ebiten.NewImage(3, 3)

// whiteSubImage is an internal sub image of whiteImage.
// Use whiteSubImage at DrawTriangles instead of whiteImage in order to avoid bleeding edges.
whiteSubImage = whiteImage.SubImage(image.Rect(1, 1, 2, 2)).(*ebiten.Image)
)

func init() {
whiteImage.Fill(color.White)
}

const (
screenWidth = 640
screenHeight = 480
)

type Game struct {
path vector.Path
vertices []ebiten.Vertex
indices []uint16

path vector.Path
tick int
}

Expand All @@ -72,25 +56,13 @@ func (g *Game) Update() error {
}

func (g *Game) Draw(screen *ebiten.Image) {
g.vertices = g.vertices[:0]
g.indices = g.indices[:0]

op := &vector.StrokeOptions{}
op.Width = 2*(float32(math.Sin(float64(g.tick)*2*math.Pi/180))+1) + 1
op.LineJoin = vector.LineJoinRound
op.LineCap = vector.LineCapRound
g.vertices, g.indices = g.path.AppendVerticesAndIndicesForStroke(g.vertices, g.indices, op)

for i := range g.vertices {
g.vertices[i].DstX += 50
g.vertices[i].DstY += 0
g.vertices[i].SrcX = 1
g.vertices[i].SrcY = 1
}

screen.DrawTriangles(g.vertices, g.indices, whiteSubImage, &ebiten.DrawTrianglesOptions{
AntiAlias: true,
})
var geoM ebiten.GeoM
geoM.Translate(50, 0)
vector.StrokePath(screen, g.path.ApplyGeoM(geoM), color.White, true, op)
}

func (*Game) Layout(width, height int) (int, int) {
Expand Down
40 changes: 4 additions & 36 deletions examples/vector/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package main

import (
"fmt"
"image"
"image/color"
"log"
"math"
Expand All @@ -27,18 +26,6 @@ import (
"github.com/hajimehoshi/ebiten/v2/vector"
)

var (
whiteImage = ebiten.NewImage(3, 3)

// whiteSubImage is an internal sub image of whiteImage.
// Use whiteSubImage at DrawTriangles instead of whiteImage in order to avoid bleeding edges.
whiteSubImage = whiteImage.SubImage(image.Rect(1, 1, 2, 2)).(*ebiten.Image)
)

func init() {
whiteImage.Fill(color.White)
}

const (
screenWidth = 640
screenHeight = 480
Expand All @@ -49,9 +36,6 @@ type Game struct {

aa bool
line bool

vertices []ebiten.Vertex
indices []uint16
}

func (g *Game) drawEbitenText(screen *ebiten.Image, x, y int, aa bool, line bool) {
Expand Down Expand Up @@ -162,32 +146,16 @@ func (g *Game) drawEbitenLogo(screen *ebiten.Image, x, y int, aa bool, line bool
path.LineTo(unit, 4*unit)
path.Close()

var geoM ebiten.GeoM
geoM.Translate(float64(x), float64(y))
if line {
op := &vector.StrokeOptions{}
op.Width = 5
op.LineJoin = vector.LineJoinRound
// TODO: Use vector.StrokePath, but this requries to 'shift' the path by (x, y).
g.vertices, g.indices = path.AppendVerticesAndIndicesForStroke(g.vertices[:0], g.indices[:0], op)
vector.StrokePath(screen, path.ApplyGeoM(geoM), color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, op)
} else {
// TODO: Use vector.DrawFilledPath, but this requries to 'shift' the path by (x, y).
g.vertices, g.indices = path.AppendVerticesAndIndicesForFilling(g.vertices[:0], g.indices[:0])
}

for i := range g.vertices {
g.vertices[i].DstX = (g.vertices[i].DstX + float32(x))
g.vertices[i].DstY = (g.vertices[i].DstY + float32(y))
g.vertices[i].SrcX = 1
g.vertices[i].SrcY = 1
g.vertices[i].ColorR = 0xdb / float32(0xff)
g.vertices[i].ColorG = 0x56 / float32(0xff)
g.vertices[i].ColorB = 0x20 / float32(0xff)
g.vertices[i].ColorA = 1
vector.DrawFilledPath(screen, path.ApplyGeoM(geoM), color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, vector.FillRuleNonZero)
}

op := &ebiten.DrawTrianglesOptions{}
op.AntiAlias = aa
op.FillRule = ebiten.FillRuleNonZero
screen.DrawTriangles(g.vertices, g.indices, whiteSubImage, op)
}

func (g *Game) drawArc(screen *ebiten.Image, count int, aa bool, line bool) {
Expand Down
21 changes: 21 additions & 0 deletions vector/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func (s *subpath) close() {
type Path struct {
ops []op

// subpaths is a cached actual rendering positions.
subpaths []subpath
}

Expand Down Expand Up @@ -527,6 +528,26 @@ func (p *Path) AppendVerticesAndIndicesForFilling(vertices []ebiten.Vertex, indi
return vertices, indices
}

// ApplyGeoM applies the given GeoM to the path and returns a new path.
func (p *Path) ApplyGeoM(geoM ebiten.GeoM) *Path {
// subpaths are not copied.
np := &Path{
ops: make([]op, len(p.ops)),
}
for i, o := range p.ops {
x1, y1 := geoM.Apply(float64(o.p1.x), float64(o.p1.y))
x2, y2 := geoM.Apply(float64(o.p2.x), float64(o.p2.y))
x3, y3 := geoM.Apply(float64(o.p3.x), float64(o.p3.y))
np.ops[i] = op{
typ: o.typ,
p1: point{x: float32(x1), y: float32(y1)},
p2: point{x: float32(x2), y: float32(y2)},
p3: point{x: float32(x3), y: float32(y3)},
}
}
return np
}

// LineCap represents the way in which how the ends of the stroke are rendered.
type LineCap int

Expand Down

0 comments on commit db04c37

Please sign in to comment.