Skip to content

Try to replace skia-pathops with linesweeper#2552

Draft
justvanrossum wants to merge 8 commits into
mainfrom
linesweeper-pathops
Draft

Try to replace skia-pathops with linesweeper#2552
justvanrossum wants to merge 8 commits into
mainfrom
linesweeper-pathops

Conversation

@justvanrossum

@justvanrossum justvanrossum commented Apr 16, 2026

Copy link
Copy Markdown
Member

Trying to replace skia-pathops with linesweeper. This is an experiment, as I'm not sure we should switch to linesweeper without addressing the findings mentioned below.

This PR fixes #2551, but at a price:

  • skia-pathops optionally keeps the starting points of contours, I haven't found a linesweeper option for this
  • skia-pathops offers control over the output winding direction, linesweeper seems to output clockwise
  • skia-pathop cleans up straight lines, linesweeper keeps intersection points (union two rectangles that are aligned on one side)
  • while linesweeper does not seem to introduce quadratics when working on cubics, it does introduce cubics when working on quadratics
  • linesweeper inserts points for TT-style implied on-curve points

(The latter two points may have to do with path conversion rather than with linesweeper itself?)

(The Fontra test cases are too minimal and don't fully reflect the findings above.)

References:

@justvanrossum justvanrossum marked this pull request as draft April 16, 2026 18:29
@justvanrossum justvanrossum changed the title [discussion] Try to replace skia-pathops with linesweeper Try to replace skia-pathops with linesweeper Apr 16, 2026
@justvanrossum

Copy link
Copy Markdown
Member Author

Cc @anthrotype @simoncozens

@anthrotype

Copy link
Copy Markdown

linesweeper inserts points for TT-style implied on-curve points

Skia does too, the TrueType style spline with implied oncurves only exists in font-land. Skia-pathops pen protocol adapter cleans them up afterwards

@anthrotype

Copy link
Copy Markdown

skia-pathops optionally keeps the starting points of contours

Similarly, that is also some extra code I added in the bindings, the underlying skia pathops module doesn't care about the starting points.

@justvanrossum

Copy link
Copy Markdown
Member Author

Ok, so if indeed the following features are not in scope for linesweeper:

  • maintaining start points where possible
  • keeping TT-implied-on-curve-points where possible

Then they could be a layer on top of linesweeper, or Fontra could deal with this itself (I'll check how skia-pathops does it).

I don't think they should be part of a binding per se, because Fontra would need this functionality whether it is using it via Python or via JS/TS/WASM.

Fontra could also deal with the desired winding direction.

What remains is the "sometimes outputs cubics when feeding it quadratics" issue: IMO that is a bug, but I'm not sure this is caused by linesweeper itself or by linesweeper-py.

Here's a reproducer for the cubic-for-quads problem:

import linesweeper
from kurbopy import Point
from fontTools.pens.recordingPen import RecordingPen


path = linesweeper.BezPath()
path.move_to(Point(0, 0))
path.quad_to(Point(0, 30), Point(15, 60))
path.quad_to(Point(30, 93), Point(90, 90))
path.line_to
path.close_path()

simplifiedPaths = linesweeper.simplify([path])

pen = RecordingPen()
for path in simplifiedPaths:
    path.draw(pen)

for command, args in pen.value:
    print(command, args)

This outputs:

moveTo ((0.0, 0.0),)
curveTo ((0.0, 20.0), (5.0, 40.0), (15.0, 60.0))
qCurveTo ((30.0, 93.0), (90.0, 90.0))
lineTo ((0.0, 0.0),)
closePath ()

The curveTo line is unexpected. (The behavior depends a bit on the actual coordinates: change the 93 to 90 and it outputs two cubics, despite the input being quadratic.)

I can't find the implementation of path.draw() in linesweeper-py, so perhaps this is indeed a pure linesweeper issue. Unless it's also out of scope to maintain the curve type.

@justvanrossum

Copy link
Copy Markdown
Member Author

@anthrotype, @simoncozens, can either of you advise me on the quadratics issue described above? My main questions at this point are:

  • Is it linesweeper's goal to output quadratics when feeding quadratics?
  • If it is, do you have an idea which (part) of linesweeper-py/linesweeper/kurbopy/kurbo could be responsible for the described problem? In other words, what would be a good place to open an issue?

@simoncozens

Copy link
Copy Markdown
Contributor

It looks like linesweeper does raise the order (quad to cubic) while adding paths to its "arena", so I guess this is considered deliberate, rather than a bug.

@yisibl

yisibl commented May 5, 2026

Copy link
Copy Markdown

@justvanrossum Could you summarize what issues remain? We could ask @jneem to take a look.

@justvanrossum

Copy link
Copy Markdown
Member Author

I'm not sure there are any real issues, except that I'm missing some functionality that seems to be outside the scope of linesweeper. What I need can be implemented on top of linesweeper, but if I could ask for a single feature it would be "output quadratic segments for quadratic input segments instead of raising the order".

@jneem

jneem commented May 5, 2026

Copy link
Copy Markdown

but if I could ask for a single feature it would be "output quadratic segments for quadratic input segments instead of raising the order"

That's definitely in-scope (I'll open an issue for it), but I don't have an ETA

@justvanrossum

Copy link
Copy Markdown
Member Author

That's definitely in-scope (I'll open an issue for it), but I don't have an ETA

That's great! Thanks for the head-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Path operations sometimes convert cubics to quadratics

5 participants