Skip to content

Render: a curve with a point at infinity does not end the process - #224

Merged
timzifer merged 7 commits into
mainfrom
claude/curve-not-numbers
Oct 13, 2026
Merged

timzifer merged 7 commits into
mainfrom
claude/curve-not-numbers

Conversation

@timzifer

Copy link
Copy Markdown
Owner

Stacked on #223, which takes stilus v0.10.0.

The bug

A page could end the process that draws it. A coordinate of a curve that is too large for a single-precision number is infinite; under the matrix of a page turned by a quarter, infinity times zero is not a number; and stilus flattened a curve with such a point without end (timzifer/stilus#38). The stack ran out — a fatal error, not a panic, so Render did not return a *PanicError: the process was gone.

By SECURITY.md this is of the kind that counts ("a panic that escapes", and worse). cera v0.10.0 and before are affected; the fix is in stilus v0.10.0.

Here

TestCurveNotNumbers: pages with such curves — c, v, y; filled, stroked, dashed, as a clip; the large number as a control point, an end point, negative; in all four rotations — drawn by one and by three workers and read as text. The render returns, and the square beside the curve is drawn. With stilus v0.9.0 the test binary dies at the first turned page.

Nothing else changes: the fix came with the stilus version of #223.

fonts/cjk supplies Noto Sans JP, SC and KR, variable fonts whose default
is Thin, and the face was made of the default: text of a font a
document names and does not embed was drawn in hairlines, whatever
weight it named. The stroke of 「一」 at 100 points was three pixels.

A program a FontProvider supplies that has a weight axis is used at the
weight the document asks for: /FontWeight of the descriptor, else 700
for a bold font and 400 for any other, within what the axis has. The
instance is baked once and the last eight are kept by program and
weight, so the documents of a process share them where the provider
hands out the same bytes. A font that cannot be instanced is used as it
is, and an embedded variable font too: its writer meant the default.

The stroke is eight pixels now, wider for a bold font and thinner for
one of weight 100.

Fixes #167.
A render with RenderOptions.Form draws a widget whose value is not the
file's from a list of its own, after the page and all its annotations.
An annotation that lies on the widget and follows it in /Annots (a line
across a field, a stamp on it) was above the field as long as it showed
the file's value and under it once the value changed.

The page's list is now cut at such a widget: it is drawn up to the
widget, then the widget, then the annotations that follow, up to the
next widget something lies on. The list knows where its annotations
begin and what each of them can touch, so that a pass after the first
replays the clip to the page and the annotations of its range, in the
part of the region they touch. A widget nothing lies on is an overlay
over a page drawn in one piece, as before.

The later passes draw onto the background, as the widgets do: a blend
mode of such an annotation sees the background where the page drew
nothing.

Fixes #164
A page drawn in bands or tiles differed from the page drawn at once by
one or two levels in a few antialiased pixels, and so did a page drawn
by several workers from one drawn by one: of the first pages of 965
files of the pdf.js corpus at 72 dpi, 85.

It was not the sampling of images, as the issue guessed, but the
rasterizer: edges cut at the region and rounded there, runs and
coverage blended with different rounding, analytic stroke rows counted
from the region's first pixel (timzifer/stilus#36). stilus draws a
pixel alike in every region now; this takes that version.

TestRenderTiles draws a page that is all edges at once, in rows, columns
and tiles, by two and five workers and in grey, and holds them against
one another byte for byte. The corpus step "grey", which draws large
pages in bands, allowed two levels and allows none now.

Fixes #211
The release that has the change (timzifer/stilus#37), in place of its
commit.
A coordinate too large for a single-precision number is infinite, and
under the matrix of a page turned by a quarter infinity times zero is
not a number. stilus flattened a curve with such a point without end
(timzifer/stilus#38): the stack ran out, which ends the process and is
no panic a render could recover. stilus v0.10.0, which this branch
has, adds nothing for such a curve.

TestCurveNotNumbers draws pages with such curves — filled, stroked,
dashed, as a clip, in every rotation — and holds that the render
returns and that what stands beside the curve is drawn.
@timzifer timzifer added bug Something isn't working P1 Blocks a consumer (fyne-pdf, fons) or loses what a page or file shows labels Oct 13, 2026
@timzifer
timzifer merged commit ec117e5 into main Oct 13, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working P1 Blocks a consumer (fyne-pdf, fons) or loses what a page or file shows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant