Add a new surface type that multiplies it input onto several output
surfaces. The only limitation is that it requires a master surface that is
used whenever we need to query surface options, such as font options and
extents.
Add an even simpler sweep-line tessellator for rectangular trapezoids (as
produced by the rectilinear stoker and box filler).
This is so simple it even outperforms pixman's region validation code for the
purposes of path-to-region conversion.
Previously the contexts were permanently associated with the surface and
only destroyed along with the final reference to the surface. This meant
that we kept a large number of unwanted contexts in memory. Most
applications only have a few contexts active at any time, so remove
inactive contexts from the operand stack every time we perform an
operation on a different context.
cairo_script_context_t is an encapsulation object for interfacing with the
output - multiple surfaces can share the same context, meaning that they
write to the same destination file/stream.
We were hitting an assertion attempting to eliminate intersections inside
the rectilinear tessellator for empty strokes. We can avoid this
assertion, by only marking the traps as having potential intersections iff
it is non-empty.
As we now superimpose a per-operation clip, this defeats the current
top-level caching mechanism. Instead we need to cache the mask for
each path. This still seems quite wasteful, and an avenue would be to
avoid caching if the path is rectilinear and reduce the number of
required composite operations. (However, first find test case...)
Larry Ewing hit a bug in cairo-trace whereby it tried to create a similar
surface referencing an undefined object. This fix checks whether the
object has yet to be defined, and if not issues an index in order to copy
the appropriate operand from the stack.
As using mask() prevents various optimisations in the backends (for
example the use of geometric clips) and for some may trigger fallbacks,
perform the simplifications usually done (too late) by the pattern layer
in the generic gstate layer. This allows us on the odd occasion to
transform a mask() into a paint() but perhaps more importantly removes the
need for identical transformations in each backend.
Kerning is quite frequent, that is to apply a horizontal but no vertical
offset to a glyph. For instance by discarding the vertical coordinate
where it remains the same and only encoding the horizontal offset we
reduce the file size by ~12.5% when tracing poppler.
For the simple cases where the clip is an unaligned box (or boxes), apply
the clip directly to the geometry and avoid having to use an intermediate
clip-mask.
Add an interface to spans that accepts trapezoids. This allows backends
that have an efficient span-line interface but lack efficient handling
of boxes (partly due to the current poor compositor interface) to
redirect composite_trapezoids() to composite_polygon() and the
span-renderer.
First perform a simple geometric clip to catch the majority of cases where
an unaligned clip has been set outside the operation extents that can be
discarded without having to use an image surface.
This causes a dramatic increase of over 13x for the poppler-bug-12266
trace and little impact elsewhere for more sensible clippers.
We can ensure that we always produce a clip region when possible by using
the rectilinear tessellator to convert complex, device-aligned polygons to
regions. Prior to using the tessellator, we relied on pixman's region code
which could only handle a union of rectangles.
For the frequent cases where we know in advance that we are dealing with a
rectilinear path, but can not use the simple region code, implement a
variant of the Bentley-Ottmann tessellator. The advantages here are that
edge comparison is very simple (we only have vertical edges) and there are
no intersection, though possible overlaps. The idea is the same, maintain
a y-x sorted queue of start/stop events that demarcate traps and sweep
through the active edges at each event, looking for completed traps.
The motivation for this was noticing a performance regression in
box-fill-outline with the self-intersection work:
1.9.2 to HEAD^: 3.66x slowdown
HEAD^ to HEAD: 5.38x speedup
1.9.2 to HEAD: 1.57x speedup
The cause of which was choosing to use spans instead of the region handling
code, as the complex polygon was no longer being tessellated.