Skip to content

Commit

Permalink
Add support for WebP and AVIF only when CGO is enabled, fixes #304
Browse files Browse the repository at this point in the history
  • Loading branch information
tdewolff committed May 21, 2024
1 parent ba0de06 commit 699cfc2
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 55 deletions.
2 changes: 2 additions & 0 deletions path_intersection.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ func (p *Path) Settle(fillRule FillRule) *Path {
// among path manipulation libraries).
// Additionally, this ensures that the path X-monotone (which should be preserved if in the
// future we add support for quad/cube intersections).
// TODO: can we delay XMonotone until after pathIntersections to avoid processing longer paths?
// TODO: can we undo XMonotone at the end so we don't end up with longer paths?
quad := func(p0, p1, p2 Point) *Path {
return flattenQuadraticBezier(p0, p1, p2, Tolerance)
}
Expand Down
14 changes: 12 additions & 2 deletions path_intersection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -842,14 +842,24 @@ func TestSelfIntersections(t *testing.T) {
p string
zs []PathIntersection
}{
//{"L10 10L10 0L0 10z", Intersections{ {Point{5.0, 5.0}, 1, 3, 0.5, 0.5, 0.25 * math.Pi, 0.75 * math.Pi, BintoA, NoParallel, false},
//}},
{"L10 10L10 0L0 10z", []PathIntersection{
{Point{5.0, 5.0}, 1, 0.5, 0.25 * math.Pi, false, false, false},
{Point{5.0, 5.0}, 3, 0.5, 0.75 * math.Pi, true, false, false},
}},

// parallel segment
{"L10 0L5 0L15 0", []PathIntersection{
{Point{5.0, 0.0}, 1, 0.5, 0.0, false, true, false},
{Point{10.0, 0.0}, 3, 0.5, 0.0, false, true, false},
}},
{"L-5 0A5 5 0 0 1 5 0A5 5 0 0 1 -5 0z", []PathIntersection{
{Point{5.0, 0.0}, 1, 0.5, 0.0, false, true, false},
{Point{10.0, 0.0}, 3, 0.5, 0.0, false, true, false},
}},
{"L-5 0A5 5 0 0 1 5 0A5 5 0 0 1 -5 0L0 0L0 1L1 0L0 -1z", []PathIntersection{
{Point{0.0, 0.0}, 1, 0.0, math.Pi, false, true, false},
{Point{10.0, 0.0}, 3, 0.5, 0.0, false, true, false},
}},

// bugs
{"M3.512162397982181 1.239754268684486L3.3827323986701674 1.1467946944092953L3.522449858001167 1.2493787337129587A0.21166666666666667 0.21166666666666667 0 0 1 3.5121623979821806 1.2397542686844856z", []PathIntersection{}}, // #277, very small circular arc at the end of the path to the start
Expand Down
7 changes: 6 additions & 1 deletion path_intersection_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,11 +541,14 @@ func pathIntersections(p, q *Path, withTangents, withParallelTangents bool) ([]P
closedP: closedP,
closedQ: closedQ,
})
for i, z := range zs {
fmt.Println(z, segsP[i], segsQ[i])
}

// Remove degenerate tangent intersections at segment endpoint:
// - Intersection at endpoints for P and Q: 4 degenerate intersections
// - Intersection at endpoints for P or Q: 2 degenerate intersections
// - Parallel/overlapping sections: 4 degenerate intersections
// - Parallel/overlapping sections: 4 degenerate + 2N intersections
var n int
for i := 0; i < len(zs); i += n {
n = 1
Expand Down Expand Up @@ -615,12 +618,14 @@ func pathIntersections(p, q *Path, withTangents, withParallelTangents bool) ([]P
}

if parallelEnding := z.Aligned() || endQ && zs[i+1].AntiAligned() || !endQ && z.AntiAligned(); parallelEnding {
fmt.Println("parallelEnding", n)
// found end of parallel as it wraps around path end, skip until start
continue
}

reversed := endQ && zs[i+n-2].AntiAligned() || !endQ && zs[i+n-1].AntiAligned()
parallelStart := zs[i+n-1].Aligned() || reversed
fmt.Println("parallelStart", parallelStart)
if !parallelStart || self {
// intersection at segment endpoint of one or both paths
// (thetaP0,thetaP1) is the LHS angle range for Q
Expand Down
52 changes: 0 additions & 52 deletions renderers/renderers.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (
"path/filepath"
"strings"

"github.com/Kagami/go-avif"
webp "github.com/kolesa-team/go-webp/encoder"
"github.com/tdewolff/canvas"
"github.com/tdewolff/canvas/renderers/pdf"
"github.com/tdewolff/canvas/renderers/ps"
Expand Down Expand Up @@ -179,56 +177,6 @@ func BMP(opts ...interface{}) canvas.Writer {
}
}

// WebP returns a Webp writer that uses libwebp and accepts the following options: canvas.Resolution, canvas.Colorspace, github.com/kolesa-team/go-webp/encoder.*Options
func WebP(opts ...interface{}) canvas.Writer {
resolution := canvas.DPMM(1.0)
colorSpace := canvas.DefaultColorSpace
var options *webp.Options
for _, opt := range opts {
switch o := opt.(type) {
case canvas.Resolution:
resolution = o
case canvas.ColorSpace:
colorSpace = o
case *webp.Options:
options = o
default:
return errorWriter(fmt.Errorf("unknown WebP option: %T(%v)", opt, opt))
}
}
return func(w io.Writer, c *canvas.Canvas) error {
img := rasterizer.Draw(c, resolution, colorSpace)
enc, err := webp.NewEncoder(img, options)
if err != nil {
return err
}
return enc.Encode(w)
}
}

// AVIF returns a AVIF writer that uses libaom and accepts the following options: canvas.Resolution, canvas.Colorspace, github.com/Kagami/go-avif.*Options
func AVIF(opts ...interface{}) canvas.Writer {
resolution := canvas.DPMM(1.0)
colorSpace := canvas.DefaultColorSpace
var options *avif.Options
for _, opt := range opts {
switch o := opt.(type) {
case canvas.Resolution:
resolution = o
case canvas.ColorSpace:
colorSpace = o
case *avif.Options:
options = o
default:
return errorWriter(fmt.Errorf("unknown AVIF option: %T(%v)", opt, opt))
}
}
return func(w io.Writer, c *canvas.Canvas) error {
img := rasterizer.Draw(c, resolution, colorSpace)
return avif.Encode(w, img, options)
}
}

// SVG returns an SVG writer and accepts the following options: canvas/renderers/svg.*Options
func SVG(opts ...interface{}) canvas.Writer {
var options *svg.Options
Expand Down
61 changes: 61 additions & 0 deletions renderers/renderers_cgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//go:build cgo

package renderers

import (
"fmt"
"io"

"github.com/Kagami/go-avif"

Check failure on line 9 in renderers/renderers_cgo.go

View workflow job for this annotation

GitHub Actions / lint

could not import github.com/Kagami/go-avif (-: # github.com/Kagami/go-avif
webp "github.com/kolesa-team/go-webp/encoder"

Check failure on line 10 in renderers/renderers_cgo.go

View workflow job for this annotation

GitHub Actions / lint

could not import github.com/kolesa-team/go-webp/encoder (-: # github.com/kolesa-team/go-webp/encoder
"github.com/tdewolff/canvas"
"github.com/tdewolff/canvas/renderers/rasterizer"
)

func WebP(opts ...interface{}) canvas.Writer {
resolution := canvas.DPMM(1.0)
colorSpace := canvas.DefaultColorSpace
var options *webp.Options
for _, opt := range opts {
switch o := opt.(type) {
case canvas.Resolution:
resolution = o
case canvas.ColorSpace:
colorSpace = o
case *webp.Options:
options = o
default:
return errorWriter(fmt.Errorf("unknown WebP option: %T(%v)", opt, opt))
}
}
return func(w io.Writer, c *canvas.Canvas) error {
img := rasterizer.Draw(c, resolution, colorSpace)
enc, err := webp.NewEncoder(img, options)
if err != nil {
return err
}
return enc.Encode(w)
}
}

func AVIF(opts ...interface{}) canvas.Writer {
resolution := canvas.DPMM(1.0)
colorSpace := canvas.DefaultColorSpace
var options *avif.Options

Check failure on line 44 in renderers/renderers_cgo.go

View workflow job for this annotation

GitHub Actions / lint

undefined: avif (typecheck)
for _, opt := range opts {
switch o := opt.(type) {
case canvas.Resolution:
resolution = o
case canvas.ColorSpace:
colorSpace = o
case *avif.Options:

Check failure on line 51 in renderers/renderers_cgo.go

View workflow job for this annotation

GitHub Actions / lint

undefined: avif (typecheck)
options = o
default:
return errorWriter(fmt.Errorf("unknown AVIF option: %T(%v)", opt, opt))
}
}
return func(w io.Writer, c *canvas.Canvas) error {
img := rasterizer.Draw(c, resolution, colorSpace)
return avif.Encode(w, img, options)

Check failure on line 59 in renderers/renderers_cgo.go

View workflow job for this annotation

GitHub Actions / lint

undefined: avif (typecheck)
}
}
19 changes: 19 additions & 0 deletions renderers/renderers_nocgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//go:build !cgo

package renderers

import (
"fmt"

"github.com/tdewolff/canvas"
)

// WebP returns a Webp writer that uses libwebp and accepts the following options: canvas.Resolution, canvas.Colorspace, github.com/kolesa-team/go-webp/encoder.*Options
func WebP(opts ...interface{}) canvas.Writer {
return errorWriter(fmt.Errorf("unsupported WebP: CGO must be enabled"))
}

// AVIF returns a AVIF writer that uses libaom and accepts the following options: canvas.Resolution, canvas.Colorspace, github.com/Kagami/go-avif.*Options
func AVIF(opts ...interface{}) canvas.Writer {
return errorWriter(fmt.Errorf("unsupported AVIF: CGO must be enabled"))
}

0 comments on commit 699cfc2

Please sign in to comment.