Skip to content

Conversation

@tomcur
Copy link
Member

@tomcur tomcur commented Jan 2, 2026

This is just a logic change and slight simplification of the lines representation. By moving the burden of closing input subpaths to flattening itself, this will allow, e.g., culling geometry at the level of Béziers. Before, the closing of subpaths lived as a post-processing step after flattening.

The actual change that starts using this for something more exciting is in #1341.

This by itself does not really bring down timings (plus noise makes it hard to measure).

flatten/Ghostscript_Tiger
                        time:   [203.93 µs 204.28 µs 204.68 µs]
                        change: [-2.1022% -1.8481% -1.5684%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 12 outliers among 100 measurements (12.00%)
  10 (10.00%) high mild
  2 (2.00%) high severe
flatten/paris-30k       time:   [12.222 ms 12.298 ms 12.384 ms]
                        change: [+0.7747% +1.3966% +2.2290%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 13 outliers among 100 measurements (13.00%)
  13 (13.00%) high severe

This is just a logic change and slight simplification of the lines
representation. By moving the burden of closing input subpaths to
flattening itself, this will allow to, e.g., cull geometry at the level
of Bèziers. Before, the closing of subpaths lived as a post-processing
step after flattening.

The actual change that starts using this for something more exciting is
in a follow-up PR.

This by itself does not really bring down timings (plus noise makes it
hard to measure).

```
flatten/Ghostscript_Tiger
                        time:   [203.93 µs 204.28 µs 204.68 µs]
                        change: [-2.1022% -1.8481% -1.5684%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 12 outliers among 100 measurements (12.00%)
  10 (10.00%) high mild
  2 (2.00%) high severe
flatten/paris-30k       time:   [12.222 ms 12.298 ms 12.384 ms]
                        change: [+0.7747% +1.3966% +2.2290%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 13 outliers among 100 measurements (13.00%)
  13 (13.00%) high severe
```
Copy link
Contributor

@LaurenzV LaurenzV left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not seeing anything that speaks against this, but it's not entirely clear to me why it's necessary. If culling of cubic's happens before flattening, why does it matter whether we close unclosed sub-paths during flattening or afterwards? 🤔

@tomcur
Copy link
Member Author

tomcur commented Jan 5, 2026

why does it matter whether we close unclosed sub-paths during flattening or afterwards? 🤔

We need to ensure open input subpaths get closed at some point (as we've been doing before), but then want to allow open subpaths later in rendering for culling reasons.

Say we we have a path like the following, with the box describing the viewport and * marking the path.

                  * * * * *
                *         *
   ---------- * -----     *
   |        *       |     *
   |      *         |     *
   |    *           |     *
   |  *             |     *
   |*               |     *
  *|                |     *
*  |                |     *
*  |                |     *
*  ------------------     *
*                         *
*                         *
*                         *
*                         *
*                         *
*                         *
*                         *
* * * * * * * * * * * * * *

The two elements of that path that matter for rendering are the diagonal line and the left-of-viewport vertical line, and we'd want to render as follows.

                  *
                * 
   ---------- * -----
   |        *░░░░░░░|
   |      *░░░░░░░░░|
   |    *░░░░░░░░░░░|
   |  *░░░░░░░░░░░░░|
   |*░░░░░░░░░░░░░░░|
  *|░░░░░░░░░░░░░░░░|
*  |░░░░░░░░░░░░░░░░|
*  |░░░░░░░░░░░░░░░░|
*  ------------------
*
*
* 
*
*
*
*

If we cull the three elements that do not matter, and as a post-processing step enforce paths to be closed, we instead get

                  *
                **
   ---------- * *----
   |        *░░*    |
   |      *░░░*     |
   |    *░░░░*      |
   |  *░░░░░*       |
   |*░░░░░░*        |
  *|░░░░░░*         |
*  |░░░░░*          |
*  |░░░░*           |
*  --- * ------------
*     *
*    *
*   *
*  *
* *
**
*

@tomcur tomcur added this pull request to the merge queue Jan 5, 2026
Merged via the queue into linebender:main with commit cc2dd70 Jan 5, 2026
17 checks passed
@tomcur tomcur deleted the subpath-closing branch January 5, 2026 13:04
@tomcur
Copy link
Member Author

tomcur commented Jan 5, 2026

I've added the above as docstrings to #1341.

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.

2 participants