Skip to content

Draw the mesh shadings, and place a pattern in the form that names it - #11

Merged
tannevaled merged 1 commit into
mainfrom
mesh-shadings
Aug 26, 2026
Merged

Draw the mesh shadings, and place a pattern in the form that names it#11
tannevaled merged 1 commit into
mainfrom
mesh-shadings

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

The four kinds of shading that carry their colours in a stream rather than in a
function: free-form and lattice-form triangles, each corner its own
colour, and Coons and tensor patches, whose four sides are cubic curves.

Nothing can fill a curved-sided patch directly, so a patch is cut into a grid of
little quadrilaterals — sixteen a side, which is past the point where a step
shows at any size a page is looked at, and 512 triangles a patch — and every
triangle is filled by mixing the colours at its corners across it. The inside of
a Coons patch follows from its twelve boundary points and is worked out here; a
tensor patch says four more. A patch may carry on from the one before it,
sharing an edge and two of its colours, which is how a surface is written
without repeating a point.

The corpus was asked first. 184 of its pages carry a mesh: 114 of the fourth
kind, 17 of the fifth, 53 of the seventh, and none of the sixth — which is
implemented all the same, since it is the tensor patch with its inside left out.

The second thing, and the larger one

Putting those pages beside macOS's own renderer found a defect that has nothing
to do with meshes. A pattern is placed in the space of the content that names
it
, and inside a form XObject that is the form's matrix and the transform that
drew it — not the page's origin. Every pgfplots surface in the corpus was
landing in the bottom-left corner of the page instead of on the panel it was
meant to fill, and so was every gradient and hatch inside every figure, because
nearly every figure a plotting tool writes is a form.

TestAPatternInsideAFormIsPlacedInTheFormsSpace fails without the fix:
(52,30) = 0,0,255 want 242,0,12.

Measured

The whole corpus, drawn before and after and every page's pixels hashed:

pages drawn each way 120 617, no panics either way
pages changed 437 in 436 files
of those, carrying a mesh 175
of those, from the pattern fix 262 — 81 gaining ink, 95 losing it, 86 the same

The biggest changes on both sides were put beside qlmanage. Every one moves
towards it: blank plot panels fill in, stray grey bands over a figure go away,
bar charts get their hatching back, and a roadmap diagram that was missing all
of its coloured nodes gets them.

A mesh whose function gives back a different number of components than its
colour space takes is now refused rather than converted through a space that
cannot take it.

What this does not do

An ExtGState soft mask is still not applied, so an Illustrator figure that
fades a surface with a luminosity mask comes out at full strength. Constant
alpha, /ca and /CA, is honoured. That is what is left between this and
qlmanage on the two files where they still differ.

100% statement coverage, go vet and -race clean, and the nine cross-compile
targets green.

The four kinds of shading that carry their colours in a stream rather than
in a function: free-form and lattice-form triangles, each corner its own
colour, and Coons and tensor patches, whose four sides are cubic curves.

Nothing can fill a curved-sided patch directly, so a patch is cut into a
grid of little quadrilaterals — sixteen a side, which is past the point
where a step shows — and every triangle is filled by mixing the colours at
its corners across it. The inside of a Coons patch follows from its twelve
boundary points and is worked out here; a tensor patch says four more. A
patch may carry on from the one before it, sharing an edge and two of its
colours, which is how a surface is written without repeating a point.

The corpus was asked first: 184 of its pages carry a mesh — 114 of the
fourth kind, 17 of the fifth, 53 of the seventh, and none of the sixth,
which is implemented all the same because it is the tensor patch with its
inside left out.

Putting those pages beside macOS's own renderer found a second thing, and
a larger one: a pattern is placed in the space of the content that names
it, and inside a form XObject that is the form's matrix and the transform
that drew it, not the page's origin. Every pgfplots surface in the corpus
was landing in the bottom-left corner of the page instead of on the panel
it was meant to fill. That is fixed here, with a test that fails without
it, and it puts every shading and tiling pattern used inside a figure
where it belongs — not only the mesh ones.

A mesh whose function gives back a different number of components than its
colour space takes is now refused rather than converted through a space
that cannot take it.
@tannevaled
tannevaled merged commit ae29393 into main Aug 26, 2026
1 check passed
@tannevaled
tannevaled deleted the mesh-shadings branch August 26, 2026 02:18
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.

1 participant