~eliasnaur/gio

8 3

stroke-path

Details
Message ID
<WeFEFUoutSiHXNV5gF_79vS1lvZvD7jHxn9YNpOh7sz0NeOMI5-GTOt_-9aa5O67EVEqjNqaMlyrkcs5MossjeW8qm3QL9THbzBkicJe7Oo=@sbinet.org>
DKIM signature
missing
Download raw message
hi,

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐

On Monday, October 26th, 2020 at 11:11 AM, Sebastien Binet <s@sbinet.org> wrote:

> thanks all.
>
> to be honest, the gpu/cpu-compute stuff is probably a tad above my "paygrade".
>
> so I'll probably stick w/ drawing to an image.Image and have Gio display it. while dedicating a few cycles to provide a stroke implementation to the old renderer (as that would still be useful for Gonum)

well... it seems I won't manage to reach the needed display performances on low-end hardware with sending image.Image to the Gio window and have a nice fluid rendering.

so I guess I'll need to dedicate these few cycles earlier :)

I am quite ignorant wrt rasters, renderers and what not.
I've looked at what fogleman/gg is doing to render stroked paths.
it's using https://github.com/golang/freetype/raster, which, I suspect is a no-go for Gio, license-wise.

duckduck-going around, I've found 3 other libraries:
- https://golang.org/x/image/vector
- https://github.com/srwiley/rasterx (uses x/image/vector under the hood)
- https://github.com/tdewolff/canvas (uses x/image/vector under the hood)

that provide a way to raster paths.

there's also this package that also provides a comparison between Gio's clip.Path and x/image/vector:
- https://github.com/reactivego/ivg

according to reactivego/ivg, it seems Gio's clip.Path is quite interesting performance-wise compared to x/image/vector.

so it seems implementing stroke-paths directly within Gio would be quite valuable.

after going through a minimal bibliography[1-6], and according to it: a stroked path is -at its heart- "just" a set of 2 paths displaced by the expected "pen width", an orthogonal line that's centered at the original stroked path and has length that "pen width". (there are of course all the interesting details of leading/trailing caps and how to join segments, but let's leave those on the table for the moment.)
the space delimited by those 2 paths can then be handled as a usual filled-path.

I would thus propose the following API:

package clip

// Stroke strokes a path with the provided stroke width.
// Stroke uses the provided Capper value for the heading and trailing caps if the path isn't closed.
// Stroke uses the provided Joiner to join segments of the path.
// Stroke does not modify the provided path.
func Stroke(p *Path, width float32, cr Capper, jr Joiner) Op

// offsetPath returns two paths offset by +/-width/2.
func offsetPath(p *Path, width float32) (lhs, rhs *Path)

type Capper interface { ... }
type Joiner interface { ... }

WDYT?

- should Stroke return a new *Path instead of an Op?
- should Stroke be a type? (StrokePath?)
- is it easy/sensible to clone a Path, read it back (decode all its ops) and create two parallel Paths?

-s

[1]: https://www.khronos.org/registry/OpenVG/specs/openvg_lite_spec.pdf
[2]: https://www.slideshare.net/Mark_Kilgard/22pathrender
[3]: https://en.wikipedia.org/wiki/Vector_graphics
[4]: https://en.wikipedia.org/wiki/Rasterisation
[5]: https://en.wikipedia.org/wiki/Nonzero-rule
[6]: https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule
Details
Message ID
<CABN121ij-r1Wc8ZVNz4Om==_=4maGmNvRtx_RtEjbgdPx2OQYg@mail.gmail.com>
In-Reply-To
<WeFEFUoutSiHXNV5gF_79vS1lvZvD7jHxn9YNpOh7sz0NeOMI5-GTOt_-9aa5O67EVEqjNqaMlyrkcs5MossjeW8qm3QL9THbzBkicJe7Oo=@sbinet.org> (view parent)
DKIM signature
missing
Download raw message
Sebastien,

It's not my area of expertise either, but stroking a line is not as
simple as offsetting a line if you want a solution that works for any
line
that can have sharp angels and is composed out of bezier curves.

From digging through the literature I've thought there isn't even a
closed-form-solution for stroking a bezier curve,
which means you have to use numerical approximations to create the
offsets for the bezier points.

Even then, you can't just ignore line joins, caps and stroke types.

There're also many different solutions for these problems, all with
their own tradeoffs, for example do you optimize for scrolling or
zooming.

Anyway these where some interesting links I found when researching
this topic some time ago:

https://mattdesl.svbtle.com/drawing-lines-is-hard
https://keithp.com/~keithp/talks/cairo2003.pdf
https://arxiv.org/pdf/2007.00308.pdf

If all you want to do is draw lines maybe my simple polyline
implementation can help:
https://github.com/wrnrlr/polyline

Kind Regards

On Wed, Oct 28, 2020 at 6:09 PM Sebastien Binet <s@sbinet.org> wrote:
>
> hi,
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
>
> On Monday, October 26th, 2020 at 11:11 AM, Sebastien Binet <s@sbinet.org> wrote:
>
> > thanks all.
> >
> > to be honest, the gpu/cpu-compute stuff is probably a tad above my "paygrade".
> >
> > so I'll probably stick w/ drawing to an image.Image and have Gio display it. while dedicating a few cycles to provide a stroke implementation to the old renderer (as that would still be useful for Gonum)
>
> well... it seems I won't manage to reach the needed display performances on low-end hardware with sending image.Image to the Gio window and have a nice fluid rendering.
>
> so I guess I'll need to dedicate these few cycles earlier :)
>
> I am quite ignorant wrt rasters, renderers and what not.
> I've looked at what fogleman/gg is doing to render stroked paths.
> it's using https://github.com/golang/freetype/raster, which, I suspect is a no-go for Gio, license-wise.
>
> duckduck-going around, I've found 3 other libraries:
> - https://golang.org/x/image/vector
> - https://github.com/srwiley/rasterx (uses x/image/vector under the hood)
> - https://github.com/tdewolff/canvas (uses x/image/vector under the hood)
>
> that provide a way to raster paths.
>
> there's also this package that also provides a comparison between Gio's clip.Path and x/image/vector:
> - https://github.com/reactivego/ivg
>
> according to reactivego/ivg, it seems Gio's clip.Path is quite interesting performance-wise compared to x/image/vector.
>
> so it seems implementing stroke-paths directly within Gio would be quite valuable.
>
> after going through a minimal bibliography[1-6], and according to it: a stroked path is -at its heart- "just" a set of 2 paths displaced by the expected "pen width", an orthogonal line that's centered at the original stroked path and has length that "pen width". (there are of course all the interesting details of leading/trailing caps and how to join segments, but let's leave those on the table for the moment.)
> the space delimited by those 2 paths can then be handled as a usual filled-path.
>
> I would thus propose the following API:
>
> package clip
>
> // Stroke strokes a path with the provided stroke width.
> // Stroke uses the provided Capper value for the heading and trailing caps if the path isn't closed.
> // Stroke uses the provided Joiner to join segments of the path.
> // Stroke does not modify the provided path.
> func Stroke(p *Path, width float32, cr Capper, jr Joiner) Op
>
> // offsetPath returns two paths offset by +/-width/2.
> func offsetPath(p *Path, width float32) (lhs, rhs *Path)
>
> type Capper interface { ... }
> type Joiner interface { ... }
>
> WDYT?
>
> - should Stroke return a new *Path instead of an Op?
> - should Stroke be a type? (StrokePath?)
> - is it easy/sensible to clone a Path, read it back (decode all its ops) and create two parallel Paths?
>
> -s
>
> [1]: https://www.khronos.org/registry/OpenVG/specs/openvg_lite_spec.pdf
> [2]: https://www.slideshare.net/Mark_Kilgard/22pathrender
> [3]: https://en.wikipedia.org/wiki/Vector_graphics
> [4]: https://en.wikipedia.org/wiki/Rasterisation
> [5]: https://en.wikipedia.org/wiki/Nonzero-rule
> [6]: https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule
Details
Message ID
<C6P98OYIGN5E.2ZHBC6QCQAP67@themachine>
In-Reply-To
<WeFEFUoutSiHXNV5gF_79vS1lvZvD7jHxn9YNpOh7sz0NeOMI5-GTOt_-9aa5O67EVEqjNqaMlyrkcs5MossjeW8qm3QL9THbzBkicJe7Oo=@sbinet.org> (view parent)
DKIM signature
pass
Download raw message
On Wed Oct 28, 2020 at 17:09, Sebastien Binet wrote:
> hi,
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
>
> On Monday, October 26th, 2020 at 11:11 AM, Sebastien Binet <s@sbinet.org> wrote:
>
> > thanks all.
> >
> > to be honest, the gpu/cpu-compute stuff is probably a tad above my "paygrade".
> >
> > so I'll probably stick w/ drawing to an image.Image and have Gio display it. while dedicating a few cycles to provide a stroke implementation to the old renderer (as that would still be useful for Gonum)
>
> well... it seems I won't manage to reach the needed display performances on low-end hardware with sending image.Image to the Gio window and have a nice fluid rendering.
>
> so I guess I'll need to dedicate these few cycles earlier :)
>
> I am quite ignorant wrt rasters, renderers and what not.
> I've looked at what fogleman/gg is doing to render stroked paths.
> it's using https://github.com/golang/freetype/raster, which, I suspect is a no-go for Gio, license-wise.
>
> duckduck-going around, I've found 3 other libraries:
> - https://golang.org/x/image/vector
> - https://github.com/srwiley/rasterx (uses x/image/vector under the hood)
> - https://github.com/tdewolff/canvas (uses x/image/vector under the hood)
>
> that provide a way to raster paths.
>
> there's also this package that also provides a comparison between Gio's clip.Path and x/image/vector:
> - https://github.com/reactivego/ivg
>
> according to reactivego/ivg, it seems Gio's clip.Path is quite interesting performance-wise compared to x/image/vector.
>
> so it seems implementing stroke-paths directly within Gio would be quite valuable.
>
> after going through a minimal bibliography[1-6], and according to it: a stroked path is -at its heart- "just" a set of 2 paths displaced by the expected "pen width", an orthogonal line that's centered at the original stroked path and has length that "pen width". (there are of course all the interesting details of leading/trailing caps and how to join segments, but let's leave those on the table for the moment.)
> the space delimited by those 2 paths can then be handled as a usual filled-path.
>
> I would thus propose the following API:
>
> package clip
>
> // Stroke strokes a path with the provided stroke width.
> // Stroke uses the provided Capper value for the heading and trailing caps if the path isn't closed.
> // Stroke uses the provided Joiner to join segments of the path.
> // Stroke does not modify the provided path.
> func Stroke(p *Path, width float32, cr Capper, jr Joiner) Op
>

I think it better to have Stroke as a method on Path and rename End.
Like so:

	package clip

	// Outline is the existing End renamed.
	func (p *Path) Outline() Op

	// Stroke returns a stroked path with the specified width
	// and configuration.
	func (p *Path) Stroke(width float32, cap ..., join ...) Op

I'm not sure how cap and join would be specified, but they can surely
wait until the basic implementation is there.


> // offsetPath returns two paths offset by +/-width/2.
> func offsetPath(p *Path, width float32) (lhs, rhs *Path)
>
> type Capper interface { ... }
> type Joiner interface { ... }
>

We can't use interfaces because of garbage and, more importantly,
because you can't run Go callbacks from the GPU.

>
> - should Stroke return a new *Path instead of an Op?

A *Path is just a builder, so I'd say no.

> - should Stroke be a type? (StrokePath?)

No. I see no reason not to share *Path for building outlines and stroked
paths.

> - is it easy/sensible to clone a Path, read it back (decode all its ops) and create two parallel Paths?
>

If you have a reference to a *Path, why not allow calling Outline/Stroke
more than once?

Elias
Details
Message ID
<NCJxDfAwAp-Nu2AXMQvO7wAbymItJcYZ73vV2TzkElkF40OWS8WsbghSA9Aa1Ma0abYaLZ1nP2UdiNKrHfVW6LY4azKofarmTokFNUyNbxE=@sbinet.org>
In-Reply-To
<C6P98OYIGN5E.2ZHBC6QCQAP67@themachine> (view parent)
DKIM signature
missing
Download raw message
Elias,

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐

On Thursday, October 29th, 2020 at 10:07 AM, Elias Naur <mail@eliasnaur.com> wrote:

> On Wed Oct 28, 2020 at 17:09, Sebastien Binet wrote:
>
> > hi,
> >
> > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> >
> > On Monday, October 26th, 2020 at 11:11 AM, Sebastien Binet s@sbinet.org wrote:
> >
> > > thanks all.
> > >
> > > to be honest, the gpu/cpu-compute stuff is probably a tad above my "paygrade".
> > >
> > > so I'll probably stick w/ drawing to an image.Image and have Gio display it. while dedicating a few cycles to provide a stroke implementation to the old renderer (as that would still be useful for Gonum)
> >
> > well... it seems I won't manage to reach the needed display performances on low-end hardware with sending image.Image to the Gio window and have a nice fluid rendering.
> >
> > so I guess I'll need to dedicate these few cycles earlier :)
> >
> > I am quite ignorant wrt rasters, renderers and what not.
> >
> > I've looked at what fogleman/gg is doing to render stroked paths.
> >
> > it's using https://github.com/golang/freetype/raster, which, I suspect is a no-go for Gio, license-wise.
> >
> > duckduck-going around, I've found 3 other libraries:
> >
> > -   https://golang.org/x/image/vector
> > -   https://github.com/srwiley/rasterx (uses x/image/vector under the hood)
> > -   https://github.com/tdewolff/canvas (uses x/image/vector under the hood)
> >
> > that provide a way to raster paths.
> >
> > there's also this package that also provides a comparison between Gio's clip.Path and x/image/vector:
> >
> > -   https://github.com/reactivego/ivg
> >
> > according to reactivego/ivg, it seems Gio's clip.Path is quite interesting performance-wise compared to x/image/vector.
> >
> > so it seems implementing stroke-paths directly within Gio would be quite valuable.
> >
> > after going through a minimal bibliography[1-6], and according to it: a stroked path is -at its heart- "just" a set of 2 paths displaced by the expected "pen width", an orthogonal line that's centered at the original stroked path and has length that "pen width". (there are of course all the interesting details of leading/trailing caps and how to join segments, but let's leave those on the table for the moment.)
> >
> > the space delimited by those 2 paths can then be handled as a usual filled-path.
> >
> > I would thus propose the following API:
> >
> > package clip
> >
> > // Stroke strokes a path with the provided stroke width.
> >
> > // Stroke uses the provided Capper value for the heading and trailing caps if the path isn't closed.
> >
> > // Stroke uses the provided Joiner to join segments of the path.
> >
> > // Stroke does not modify the provided path.
> >
> > func Stroke(p *Path, width float32, cr Capper, jr Joiner) Op
>
> I think it better to have Stroke as a method on Path and rename End.
>
> Like so:
>
> package clip
>
> // Outline is the existing End renamed.
>
> func (p *Path) Outline() Op
>
> // Stroke returns a stroked path with the specified width
>
> // and configuration.
>
> func (p *Path) Stroke(width float32, cap ..., join ...) Op

LGTM.
(internal) semantics of these calls should probably be specified to be able to have one Path in hand
and both fill+stroke it.

>
> I'm not sure how cap and join would be specified, but they can surely
>
> wait until the basic implementation is there.
>
> > // offsetPath returns two paths offset by +/-width/2.
> >
> > func offsetPath(p *Path, width float32) (lhs, rhs *Path)
> >
> > type Capper interface { ... }
> >
> > type Joiner interface { ... }
>
> We can't use interfaces because of garbage and, more importantly,
>
> because you can't run Go callbacks from the GPU.

ok.
providing const-iota values should do (e.g. CapStyle, JoinStyle).
the initial implementation would just default to a "ButtCapStyle" and a very naive JoinStyle.

>
> > -   should Stroke return a new *Path instead of an Op?
>
> A *Path is just a builder, so I'd say no.
ok.

>
> > -   should Stroke be a type? (StrokePath?)
>
> No. I see no reason not to share *Path for building outlines and stroked
> paths.
ok.

>
> > -   is it easy/sensible to clone a Path, read it back (decode all its ops) and create two parallel Paths?
>
> If you have a reference to a *Path, why not allow calling Outline/Stroke
> more than once?

I indeed believe it's sensible to call those methods more than once.
one immediate example is the "waiting wheel" spinner widget.

-s
Details
Message ID
<uWoWNBEW4w_y0TLrm08EBpsy7GHn-z1Mp9gQty-zhXOxyxW56YQYIM40pn4n_M7AmgBM9c2dXlBvy14jegEFy-f9FhnLMunrL0QhrEzlhBE=@sbinet.org>
In-Reply-To
<CABN121ij-r1Wc8ZVNz4Om==_=4maGmNvRtx_RtEjbgdPx2OQYg@mail.gmail.com> (view parent)
DKIM signature
missing
Download raw message
Werner,

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐

On Thursday, October 29th, 2020 at 9:04 AM, Werner Laurensse <werner@alman.ax> wrote:

> Sebastien,
>
> It's not my area of expertise either, but stroking a line is not as
> simple as offsetting a line if you want a solution that works for any
> line
> that can have sharp angels and is composed out of bezier curves.

apologies if I seemed like implying it was as easy as that.
I merely wanted to mention the 10,000ft overview of the technique.
digging through the code of the license-compatible Go projects and
the OpenVG reference implementation surely conveyed to me the rather
interesting devil-y details :)

> From digging through the literature I've thought there isn't even a
> closed-form-solution for stroking a bezier curve,
> which means you have to use numerical approximations to create the
> offsets for the bezier points.
>
> Even then, you can't just ignore line joins, caps and stroke types.
> There're also many different solutions for these problems, all with
> their own tradeoffs, for example do you optimize for scrolling or
> zooming.
>
> Anyway these where some interesting links I found when researching
> this topic some time ago:
>
> https://mattdesl.svbtle.com/drawing-lines-is-hard
> https://keithp.com/~keithp/talks/cairo2003.pdf
> https://arxiv.org/pdf/2007.00308.pdf

thanks for contributing to my bibtex :)

> If all you want to do is draw lines maybe my simple polyline
>
> implementation can help:
>
> https://github.com/wrnrlr/polyline

thanks for the pointer.
unfortunately, one of my goal is to be able to draw circles and ellipses
(to display a modelisation/simulation of our solar system) and general iso-curves
(magnetic fields, results of a local minimum search and other iso-lines, etc...)

cheers,
-s
Details
Message ID
<gDEPQ-H59UcP5wOuhm80v5o_qpx9LV5C1x5chEOd97JRdlrmya0pkSHrMvCAN0pp_ZIF7xdnzuTnOk1oG-Nf2GdAGY68yOH-mr1vemy0gnU=@sbinet.org>
In-Reply-To
<NCJxDfAwAp-Nu2AXMQvO7wAbymItJcYZ73vV2TzkElkF40OWS8WsbghSA9Aa1Ma0abYaLZ1nP2UdiNKrHfVW6LY4azKofarmTokFNUyNbxE=@sbinet.org> (view parent)
DKIM signature
missing
Download raw message
On Thursday, October 29th, 2020 at 10:46 AM, Sebastien Binet <s@sbinet.org> wrote:

[...]

> > > -   is it easy/sensible to clone a Path, read it back (decode all its ops) and create two parallel Paths?
> >
> > If you have a reference to a *Path, why not allow calling Outline/Stroke
> >
> > more than once?
>
> I indeed believe it's sensible to call those methods more than once.
>
> one immediate example is the "waiting wheel" spinner widget.

forgot to mention: it seems to me we currently lack a way to inspect the list of past commands
specified to a clip.Path.
this is needed to translate the original path into a set of paths that delimit the expected
stroked path.

for my tests I'll just add a []ops.Quad field to get me going, but I suspect that shouldn't be
the final design.

-s
Details
Message ID
<C6PHEI0N71WW.2W3UYU5V6GP83@themachine>
In-Reply-To
<gDEPQ-H59UcP5wOuhm80v5o_qpx9LV5C1x5chEOd97JRdlrmya0pkSHrMvCAN0pp_ZIF7xdnzuTnOk1oG-Nf2GdAGY68yOH-mr1vemy0gnU=@sbinet.org> (view parent)
DKIM signature
pass
Download raw message
On Thu Oct 29, 2020 at 15:27, Sebastien Binet wrote:
>
> On Thursday, October 29th, 2020 at 10:46 AM, Sebastien Binet <s@sbinet.org> wrote:
>
> [...]
>
> > > > -   is it easy/sensible to clone a Path, read it back (decode all its ops) and create two parallel Paths?
> > >
> > > If you have a reference to a *Path, why not allow calling Outline/Stroke
> > >
> > > more than once?
> >
> > I indeed believe it's sensible to call those methods more than once.
> >
> > one immediate example is the "waiting wheel" spinner widget.
>
> forgot to mention: it seems to me we currently lack a way to inspect the list of past commands
> specified to a clip.Path.
> this is needed to translate the original path into a set of paths that delimit the expected
> stroked path.
>
> for my tests I'll just add a []ops.Quad field to get me going, but I suspect that shouldn't be
> the final design.
>

Perhaps I misunderstand, but I think you're generating the faux stroke
outline in package clip. I think the correct place to expand a path
into its stroke is in package gpu. That's where the path is parsed, and
the decision to expand it or not can be made (the compute shader don't
need it).

Elias
Details
Message ID
<NgWnEDld8Q7ptdqS7V2XBJdHgTjBg74nmNM-jSslGcIALCdE3u7fJy1GKW9FOMUC4Rwb7frK2mkRQxUJIp8Xelh9oSDLKDIRm7yt0dy-its=@sbinet.org>
In-Reply-To
<C6PHEI0N71WW.2W3UYU5V6GP83@themachine> (view parent)
DKIM signature
missing
Download raw message
On Thursday, October 29th, 2020 at 4:31 PM, Elias Naur <mail@eliasnaur.com> wrote:

> On Thu Oct 29, 2020 at 15:27, Sebastien Binet wrote:
>
> > On Thursday, October 29th, 2020 at 10:46 AM, Sebastien Binet s@sbinet.org wrote:
> >
> > [...]
> >
> > > > > -   is it easy/sensible to clone a Path, read it back (decode all its ops) and create two parallel Paths?
> > > >
> > > > If you have a reference to a *Path, why not allow calling Outline/Stroke
> > > >
> > > > more than once?
> > >
> > > I indeed believe it's sensible to call those methods more than once.
> > >
> > > one immediate example is the "waiting wheel" spinner widget.
> >
> > forgot to mention: it seems to me we currently lack a way to inspect the list of past commands
> >
> > specified to a clip.Path.
> >
> > this is needed to translate the original path into a set of paths that delimit the expected
> >
> > stroked path.
> >
> > for my tests I'll just add a []ops.Quad field to get me going, but I suspect that shouldn't be
> >
> > the final design.
>
> Perhaps I misunderstand, but I think you're generating the faux stroke
>
> outline in package clip. I think the correct place to expand a path
>
> into its stroke is in package gpu. That's where the path is parsed, and
>
> the decision to expand it or not can be made (the compute shader don't
>
> need it).

ok, *I* was the one misunderstanding.
so clip.Path.Stroke(width, strokeSyle) would just append 2 values to the auxiliary buffer (a float32
and a uint8, presumably prepended with a new internal/ops tag value) that would then be decoded by
the gpu.drawOps.buildVerts method.

buildVerts is the place for my tests, right?

-s
Details
Message ID
<C6PK5C9VWYC7.18OUQ8Y4D83GE@themachine>
In-Reply-To
<NgWnEDld8Q7ptdqS7V2XBJdHgTjBg74nmNM-jSslGcIALCdE3u7fJy1GKW9FOMUC4Rwb7frK2mkRQxUJIp8Xelh9oSDLKDIRm7yt0dy-its=@sbinet.org> (view parent)
DKIM signature
pass
Download raw message
On Thu Oct 29, 2020 at 16:40, Sebastien Binet wrote:
> On Thursday, October 29th, 2020 at 4:31 PM, Elias Naur <mail@eliasnaur.com> wrote:
>
> > On Thu Oct 29, 2020 at 15:27, Sebastien Binet wrote:
> >
> > > On Thursday, October 29th, 2020 at 10:46 AM, Sebastien Binet s@sbinet.org wrote:
> > >
> > > [...]
> > >
> > > > > > -   is it easy/sensible to clone a Path, read it back (decode all its ops) and create two parallel Paths?
> > > > >
> > > > > If you have a reference to a *Path, why not allow calling Outline/Stroke
> > > > >
> > > > > more than once?
> > > >
> > > > I indeed believe it's sensible to call those methods more than once.
> > > >
> > > > one immediate example is the "waiting wheel" spinner widget.
> > >
> > > forgot to mention: it seems to me we currently lack a way to inspect the list of past commands
> > >
> > > specified to a clip.Path.
> > >
> > > this is needed to translate the original path into a set of paths that delimit the expected
> > >
> > > stroked path.
> > >
> > > for my tests I'll just add a []ops.Quad field to get me going, but I suspect that shouldn't be
> > >
> > > the final design.
> >
> > Perhaps I misunderstand, but I think you're generating the faux stroke
> >
> > outline in package clip. I think the correct place to expand a path
> >
> > into its stroke is in package gpu. That's where the path is parsed, and
> >
> > the decision to expand it or not can be made (the compute shader don't
> >
> > need it).
>
> ok, *I* was the one misunderstanding.
> so clip.Path.Stroke(width, strokeSyle) would just append 2 values to the auxiliary buffer (a float32
> and a uint8, presumably prepended with a new internal/ops tag value) that would then be decoded by
> the gpu.drawOps.buildVerts method.
>
> buildVerts is the place for my tests, right?
>

Sounds about right to me.

Elias
Reply to thread Export thread (mbox)