Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
Use the cairo_list_t and its style of iterators to improve the readability
of the cairo_path_buf_t management. Note the complications that arise from
the embedding of the initial buf -- however the macros do help make the
unusual manipulations more identifiable.
Whilst constructing the path, if the operations continue to be
axis-aligned lines, allow the is_box and is_region flags to persist. These
are set to false as soon as a curve-to is added, a diagonal or in the case
of is_region a non-integer point.
We need to translate the path in order to compensate for the device offset
applied to the group surface when pushing and popping. (The path is
transformed to device space on creation, and so needs recomputing for the
new device.)
A cairo context is meant to be extremely cheap to create such that it can
be used in transient expose events. Thus these are allocated reasonably
frequently and show up malloc profiles.
When observing applications two patterns emerge. The first is due to
Pango, which wraps each glyph run within a context save/restore. This
causes the scaled font to be evicted after every run and reloaded on the
next. This is caught by the MRU slot on the cairo_scaled_font_map and
prevents a relatively costly traversal of the hash table and holdovers.
The second pattern is by applications that directly manage the rendering
of their own glyphs. The prime example of this is gnome-terminal/vte. Here
the application frequently alternates between a few scaled fonts - which
requires a hash table retrieval every time.
By introducing a MRU slot on the gstate we are able to directly recover
the scaled font around 90% of the time.
Of 110,000 set-scaled-fonts:
4,000 were setting the current font
96,000 were setting to the previous font
2,500 were recovered from the MRU on the cairo_scaled_font_map
7,500 needed a hash retrieval
which compares to ~106,000 hash lookups without the additional MRU slot on
the gstate.
This translates to an elapsed time saving of ~5% when replaying a
gnome-terminal trace using the drm backend.
When using MSVC, _cairo_error() can be folded into other identical functions.
If that happens, _cairo_error isn't really useful anymore. Using the
CAIRO_ENSURE_UNIQUE macro makes sure this doesn't happen.
Use __asm to serve as a line delimiter. This allows us to use the
__asm{} block in a macro.
This reverts commit 126824f5e6.
It turns out MSVC doesn't handle line continuation characters in __asm{}
blocks very well, so revert for now until I come up with something that
works.
When using MSVC, _cairo_error() can be folded into other identical functions. If
that happens, _cairo_error isn't really useful anymore. Using the
CAIRO_ENSURE_UNIQUE macro makes sure this doesn't happen.
Truc Troung reported that the behaviour of
cairo_set_tolerance()/cairo_get_tolerance() was inconsistent with the
documentation, i.e. we failed to mention that the tolerance would be
restricted to the smalled fixed-point value.
Add a sentence to the documentation that describes the restriction without
mentioning what that is... Hopefully that is sufficient detail to
accommodate the reporter, without exposing internal implementation details.
Fixes https://bugs.freedesktop.org/show_bug.cgi?id=20095
Bug 20095 - The cairo_set_tolerance() function behavior is inconsistency
with the spec
Profiling a silly video renderer that called set-source; rectangle; fill;
for each pixel, we can shave 5% off the cairo overhead by introducing an
early return if we attempt to reset the current colour.
Sascha Steinbiss reported a bug where the PDF backend was reading beyond
the end of the glyph array:
http://lists.cairographics.org/archives/cairo/2008-December/015976.html.
It transpires that in the early glyph culling in the gstate we were
not updating the clusters to skip culled glyphs.
When computing the bounds of the clip path, we care more for a fast result
than absolute precision as the extents are only used as a guide to trim
the future operations. So computing the extents of the path suffices.
First try to use a stack buffer for the glyphs and clusters if the user
calls cairo_show_text() - for example, as pango does to draw the unknown hex
box.
When discussing the implications of snapshot cow, one of the questions
that we raised was what happens on cairo_destroy()? The lifetime of the
context implicitly marks the extents of the drawing operations, typically
the expose event (or perhaps one phase of it). Therefore at the end of the
sequence we implicitly wish to flush the graphics events to the surface.
Avoid allocating a default source pattern by using the static black pattern
object. The one complication is that we need to ensure that the static
pattern does leak to the application, so we replace it with an allocated
solid pattern within _cairo_gstate_get_source().
With the addition of cairo_show_text_glyphs() came a couple of functions
to query whether the target supported the extended attributes. However,
at Carl's request cairo_has_show_text_glyphs() was removed - but the
documentation was not updated to reflect that.
The release notes for 1.7.6 say that we had dropped this
function, but apparently we had only planned to do that
and didn't actually get around to it until now.
Thanks to the RELEASING insctructions which gave a diff
command that pointed out this problem.
Chris rightfully complained that having a boolean function argument is
new in cairo_show_text_glyphs, and indeed avoiding them has been one
of the API design criteria for cairo. Trying to come up with alternatives,
Owen suggested using a flag type which nicely solves the problem AND
future-proofs such a complex API.
Please welcome _flags_t APIs to cairo.h