From b121468991643ec929db3cdc5efcb4176dea4fda Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 8 Jun 2024 12:06:00 +0900 Subject: [PATCH] ebiten: add `FillRuleFillAll`, `FillRuleEvenOdd`, and `FillRuleNonZero` This change also deprecates the existing constants. Closes #3006 --- colorm/draw.go | 4 +-- examples/vector/main.go | 16 +++++------ image.go | 33 +++++++++++++++++----- image_test.go | 20 ++++++------- internal/processtest/testdata/issue2138.go | 4 +-- vector/path.go | 6 ++-- 6 files changed, 51 insertions(+), 32 deletions(-) diff --git a/colorm/draw.go b/colorm/draw.go index 56408fbb6..3992f527d 100644 --- a/colorm/draw.go +++ b/colorm/draw.go @@ -72,11 +72,11 @@ type DrawTrianglesOptions struct { // FillRule indicates the rule how an overlapped region is rendered. // - // The rules NonZero and EvenOdd are useful when you want to render a complex polygon. + // The rules FileRuleNonZero and FillRuleEvenOdd are useful when you want to render a complex polygon. // A complex polygon is a non-convex polygon like a concave polygon, a polygon with holes, or a self-intersecting polygon. // See examples/vector for actual usages. // - // The default (zero) value is ebiten.FillAll. + // The default (zero) value is ebiten.FillRuleFillAll. FillRule ebiten.FillRule // AntiAlias indicates whether the rendering uses anti-alias or not. diff --git a/examples/vector/main.go b/examples/vector/main.go index 674388d62..02ac37350 100644 --- a/examples/vector/main.go +++ b/examples/vector/main.go @@ -141,14 +141,14 @@ func drawEbitenText(screen *ebiten.Image, x, y int, aa bool, line bool) { op := &ebiten.DrawTrianglesOptions{} op.AntiAlias = aa - // For strokes (AppendVerticesAndIndicesForStroke), FillAll and NonZero work. + // For strokes (AppendVerticesAndIndicesForStroke), FillRuleFillAll and FillRuleNonZero work. // - // For filling (AppendVerticesAndIndicesForFilling), NonZero and EvenOdd work. - // NonZero and EvenOdd differ when rendering a complex polygons with self-intersections and/or holes. + // For filling (AppendVerticesAndIndicesForFilling), FillRuleNonZero and FillRuleEvenOdd work. + // FillRuleNonZero and FillRuleEvenOdd differ when rendering a complex polygons with self-intersections and/or holes. // See https://en.wikipedia.org/wiki/Nonzero-rule and https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule . // - // For simplicity, this example always uses NonZero, whichever strokes or filling is done. - op.FillRule = ebiten.NonZero + // For simplicity, this example always uses FillRuleNonZero, whichever strokes or filling is done. + op.FillRule = ebiten.FillRuleNonZero screen.DrawTriangles(vs, is, whiteSubImage, op) } @@ -203,7 +203,7 @@ func drawEbitenLogo(screen *ebiten.Image, x, y int, aa bool, line bool) { op := &ebiten.DrawTrianglesOptions{} op.AntiAlias = aa - op.FillRule = ebiten.NonZero + op.FillRule = ebiten.FillRuleNonZero screen.DrawTriangles(vs, is, whiteSubImage, op) } @@ -245,7 +245,7 @@ func drawArc(screen *ebiten.Image, count int, aa bool, line bool) { op := &ebiten.DrawTrianglesOptions{} op.AntiAlias = aa - op.FillRule = ebiten.NonZero + op.FillRule = ebiten.FillRuleNonZero screen.DrawTriangles(vs, is, whiteSubImage, op) } @@ -300,7 +300,7 @@ func drawWave(screen *ebiten.Image, counter int, aa bool, line bool) { op := &ebiten.DrawTrianglesOptions{} op.AntiAlias = aa - op.FillRule = ebiten.NonZero + op.FillRule = ebiten.FillRuleNonZero screen.DrawTriangles(vs, is, whiteSubImage, op) } diff --git a/image.go b/image.go index 18544565c..e60e40e81 100644 --- a/image.go +++ b/image.go @@ -310,17 +310,36 @@ const ( // FillRule is the rule whether an overlapped region is rendered with DrawTriangles(Shader). type FillRule int +const ( + // FillRuleFillAll indicates all the triangles are rendered regardless of overlaps. + FillRuleFillAll FillRule = FillRule(graphicsdriver.FillRuleFillAll) + + // FillRuleNonZero means that triangles are rendered based on the non-zero rule. + // If and only if the number of overlaps is not 0, the region is rendered. + FillRuleNonZero FillRule = FillRule(graphicsdriver.FillRuleNonZero) + + // FillRuleEvenOdd means that triangles are rendered based on the even-odd rule. + // If and only if the number of overlaps is odd, the region is rendered. + FillRuleEvenOdd FillRule = FillRule(graphicsdriver.FillRuleEvenOdd) +) + const ( // FillAll indicates all the triangles are rendered regardless of overlaps. - FillAll FillRule = FillRule(graphicsdriver.FillRuleFillAll) + // + // Deprecated: as of v2.8. Use FillRuleFillAll instead. + FillAll = FillRuleFillAll // NonZero means that triangles are rendered based on the non-zero rule. // If and only if the number of overlaps is not 0, the region is rendered. - NonZero FillRule = FillRule(graphicsdriver.FillRuleNonZero) + // + // Deprecated: as of v2.8. Use FillRuleNonZero instead. + NonZero = FillRuleNonZero // EvenOdd means that triangles are rendered based on the even-odd rule. // If and only if the number of overlaps is odd, the region is rendered. - EvenOdd FillRule = FillRule(graphicsdriver.FillRuleEvenOdd) + // + // Deprecated: as of v2.8. Use FillRuleEvenOdd instead. + EvenOdd = FillRuleEvenOdd ) // ColorScaleMode is the mode of color scales in vertices. @@ -371,11 +390,11 @@ type DrawTrianglesOptions struct { // FillRule indicates the rule how an overlapped region is rendered. // - // The rules NonZero and EvenOdd are useful when you want to render a complex polygon. + // The rules FillRuleNonZero and FillRuleEvenOdd are useful when you want to render a complex polygon. // A complex polygon is a non-convex polygon like a concave polygon, a polygon with holes, or a self-intersecting polygon. // See examples/vector for actual usages. // - // The default (zero) value is FillAll. + // The default (zero) value is FillRuleFillAll. FillRule FillRule // AntiAlias indicates whether the rendering uses anti-alias or not. @@ -547,11 +566,11 @@ type DrawTrianglesShaderOptions struct { // FillRule indicates the rule how an overlapped region is rendered. // - // The rules NonZero and EvenOdd are useful when you want to render a complex polygon. + // The rules FillRuleNonZero and FillRuleEvenOdd are useful when you want to render a complex polygon. // A complex polygon is a non-convex polygon like a concave polygon, a polygon with holes, or a self-intersecting polygon. // See examples/vector for actual usages. // - // The default (zero) value is FillAll. + // The default (zero) value is FillRuleFillAll. FillRule FillRule // AntiAlias indicates whether the rendering uses anti-alias or not. diff --git a/image_test.go b/image_test.go index 660418a48..2f58e7f36 100644 --- a/image_test.go +++ b/image_test.go @@ -2696,7 +2696,7 @@ func TestImageEvenOdd(t *testing.T) { // Draw all the vertices once. The even-odd rule is applied for all the vertices once. dst := ebiten.NewImage(16, 16) op := &ebiten.DrawTrianglesOptions{ - FillRule: ebiten.EvenOdd, + FillRule: ebiten.FillRuleEvenOdd, } dst.DrawTriangles(append(append(vs0, vs1...), vs2...), append(append(is0, is1...), is2...), emptySubImage, op) for j := 0; j < 16; j++ { @@ -2794,15 +2794,15 @@ func TestImageEvenOdd(t *testing.T) { } func TestImageFillRule(t *testing.T) { - for _, fillRule := range []ebiten.FillRule{ebiten.FillAll, ebiten.NonZero, ebiten.EvenOdd} { + for _, fillRule := range []ebiten.FillRule{ebiten.FillRuleFillAll, ebiten.FillRuleNonZero, ebiten.FillRuleEvenOdd} { fillRule := fillRule var name string switch fillRule { - case ebiten.FillAll: + case ebiten.FillRuleFillAll: name = "FillAll" - case ebiten.NonZero: + case ebiten.FillRuleNonZero: name = "NonZero" - case ebiten.EvenOdd: + case ebiten.FillRuleEvenOdd: name = "EvenOdd" } t.Run(name, func(t *testing.T) { @@ -2885,11 +2885,11 @@ func TestImageFillRule(t *testing.T) { var want color.RGBA switch { case 2 <= i && i < 7 && 2 <= j && j < 7: - if fillRule != ebiten.EvenOdd { + if fillRule != ebiten.FillRuleEvenOdd { want = color.RGBA{G: 0xff, A: 0xff} } case 9 <= i && i < 14 && 9 <= j && j < 14: - if fillRule == ebiten.FillAll { + if fillRule == ebiten.FillRuleFillAll { want = color.RGBA{B: 0xff, A: 0xff} } case 1 <= i && i < 15 && 1 <= j && j < 15: @@ -2922,11 +2922,11 @@ func TestImageFillRule(t *testing.T) { var want color.RGBA switch { case 3 <= i && i < 8 && 3 <= j && j < 8: - if fillRule != ebiten.EvenOdd { + if fillRule != ebiten.FillRuleEvenOdd { want = color.RGBA{G: 0xff, A: 0xff} } case 10 <= i && i < 15 && 10 <= j && j < 15: - if fillRule == ebiten.FillAll { + if fillRule == ebiten.FillRuleFillAll { want = color.RGBA{B: 0xff, A: 0xff} } case 2 <= i && i < 16 && 2 <= j && j < 16: @@ -3726,7 +3726,7 @@ func TestImageTooManyConstantBuffersInDirectX(t *testing.T) { dst0 := ebiten.NewImage(16, 16) dst1 := ebiten.NewImage(16, 16) op := &ebiten.DrawTrianglesOptions{ - FillRule: ebiten.EvenOdd, + FillRule: ebiten.FillRuleEvenOdd, } for i := 0; i < 100; i++ { dst0.DrawTriangles(vs, is, src, op) diff --git a/internal/processtest/testdata/issue2138.go b/internal/processtest/testdata/issue2138.go index 34e8dcb98..18f3ab214 100644 --- a/internal/processtest/testdata/issue2138.go +++ b/internal/processtest/testdata/issue2138.go @@ -59,7 +59,7 @@ func (g *Game) Update() error { } func (g *Game) Draw(screen *ebiten.Image) { - // Before the fix, some complex renderings with EvenOdd might cause a DirectX error like this (#2138): + // Before the fix, some complex renderings with FillRuleEvenOdd might cause a DirectX error like this (#2138): // panic: directx: IDXGISwapChain4::Present failed: HRESULT(2289696773) screen.DrawImage(debugCircleImage, nil) @@ -74,7 +74,7 @@ func (g *Game) Draw(screen *ebiten.Image) { p.Arc(100, 100, 6, 0, 2*math.Pi, vector.Clockwise) filling, indicies := p.AppendVerticesAndIndicesForFilling(nil, nil) screen.DrawTriangles(filling, indicies, whiteTextureImage, &ebiten.DrawTrianglesOptions{ - FillRule: ebiten.EvenOdd, + FillRule: ebiten.FillRuleEvenOdd, }) } diff --git a/vector/path.go b/vector/path.go index 0474d75de..b381b15ad 100644 --- a/vector/path.go +++ b/vector/path.go @@ -396,7 +396,7 @@ func (p *Path) Close() { // // The returned vertice's SrcX and SrcY are 0, and ColorR, ColorG, ColorB, and ColorA are 1. // -// The returned values are intended to be passed to DrawTriangles or DrawTrianglesShader with the fill rule NonZero or EvenOdd +// The returned values are intended to be passed to DrawTriangles or DrawTrianglesShader with FileRuleNonZero or FillRuleEvenOdd // in order to render a complex polygon like a concave polygon, a polygon with holes, or a self-intersecting polygon. // // The returned vertices and indices should be rendered with a solid (non-transparent) color with the default Blend (source-over). @@ -480,7 +480,7 @@ type StrokeOptions struct { // The returned vertice's SrcX and SrcY are 0, and ColorR, ColorG, ColorB, and ColorA are 1. // // The returned values are intended to be passed to DrawTriangles or DrawTrianglesShader with a solid (non-transparent) color -// with FillAll or NonZero fill rule, not EvenOdd fill rule. +// with FillRuleFillAll or FillRuleNonZero, not FileRuleEvenOdd. func (p *Path) AppendVerticesAndIndicesForStroke(vertices []ebiten.Vertex, indices []uint16, op *StrokeOptions) ([]ebiten.Vertex, []uint16) { if op == nil { return vertices, indices @@ -536,7 +536,7 @@ func (p *Path) AppendVerticesAndIndicesForStroke(vertices []ebiten.Vertex, indic ColorA: 1, }) } - // All the triangles are rendered in clockwise order to enable NonZero filling rule (#2833). + // All the triangles are rendered in clockwise order to enable FillRuleNonZero (#2833). indices = append(indices, idx, idx+1, idx+2, idx+1, idx+3, idx+2) // Add line joints.