This means, we have to malloc only one buffer, not two. Worst case
is that one always draws curves, which fills the arg (point) buffer
six times faster than op buffer. But that's not a big deal since
each op takes 1 byte, while each point takes 8 bytes. So op space
is cheap to spare, so to speak (about 10% memory waste at worst).
We do this by including an initial op and arg buf in cairo_path_fixed_t,
so for small paths we don't have to alloc those buffers.
The way this is done is a bit unusual. Specifically, using an array of
length one instead of a normal member:
- cairo_path_op_buf_t *op_buf_head;
+ cairo_path_op_buf_t op_buf_head[1];
Has the advantage that read-only use of the buffers does not need any
change as arrays act like pointers syntactically. All manipulation code
however needs to be updates, which the patch supposed does. Still, there
seems to be bugs remaining as cairo-perf quits with a Bad X Request error
with this patch.
Previously, an INVALID_RESTORE error would leave cr->gstate as NULL,
(which is generally impossible/invalid). This seems safe enough as
most cairo functions check cr->status first and bail if anything
looks fishy.
However, the many cairo_get functions happily march along in spite
of any current error. We could instrument all of those functions to
check for the error status and return some dummy value in that case.
But it's much easier to get the same basic effect by simply creating
a non-NULL cr->gstate which will hold all those dummy values, and
we can eliminate the crashes without having to touch up every
cairo_get function.
This fixes the bug reported here:
evolution crash to _cairo_gstate_backend_to_user()
https://bugs.freedesktop.org/show_bug.cgi?id=9906
It also eliminates the crash that was added to the nil-surface test
with the previous commit.
There was some leftover cut-and-paste description of get_font_face
in the documentation for get_scaled_font. That turned out to be a
good thing as it alerted me to the fact that the get_font_face
documentation was stale as well.
Add description of the 'nil' object return values, rather than NULL.
Previous commit broke cairo_surface_finish, since it was checking for
ref_count == CAIRO_REF_COUNT_INVALID and bailing. But, that condition
was reached from destroy, so finish was bailing out early.
user_data setters/getters were added to public refcounted objects
that were missing them (cairo_t, pattern, scaled_font). Also,
a refcount getter (cairo_*_get_reference_count) was added to all
public refcounted objects.
Make these functions consistent with other cairo_get functions
by making cairo_get_dash_count return the count directly, and
removing the cairo_status_t return value from cairo_get_dash.
This custom stroking code allows backends to use optimized region-based
drawing operations for rectilinear strokes. This results in a 5-25x
performance improvement when drawing rectilinear shapes:
image-rgb box-outline-stroke-100 0.18 -> 0.01: 25.58x speedup
████████████████████████▋
image-rgba box-outline-stroke-100 0.18 -> 0.01: 25.57x speedup
████████████████████████▋
xlib-rgb box-outline-stroke-100 0.49 -> 0.06: 8.67x speedup
███████▋
xlib-rgba box-outline-stroke-100 0.22 -> 0.04: 5.39x speedup
████▍
In other words, using cairo_stroke instead of cairo_fill to draw the
same shape was 5-15x slower before, but is 1.2-2x faster now.
The rule is: cairo_glyph_t* is always passed as const for measurement
purposes. This was not reflected in our public api previously. Fixed
Showing glyphs used to have cairo_glyph_t* always as const. With this
changed, it is only const on cairo_t and cairo_gstate_t operations.
cairo_surface_t, cairo_scaled_font_t, and individual backends receive
cairo_glyph_t* as non-const. The desired semantics is that they may modify
the contents of the array as long as they do not return
CAIRO_STATUS_UNSUPPORTED. This makes it possible to avoid copying the glyph
array again and again, and edit it in-place. Backends are in fact free to use
the array as a generic buffer as they see fit.
A nice side effect of this new approach is that the valid input range
was expanded back to (INT_MIN, INT_MAX]. No performance regressions observed.
Also included is documentation about the internal mysteries of _cairo_lround,
as previously promised.
The following documented symbols were missing this tag:
cairo_clip_extents
cairo_copy_clip_rectangles
CAIRO_STATUS_INVALID_INDEX
cairo_rectangle_t
cairo_rectangle_list_t
One of these functions was already documented to be doing this, and
the other one should have been. Now the documentation and behavior
for both are consistent, (and the path-data test case verifies this).
Adds API functions for inspecting the current dash state, as well as
the contents of pattern objects:
cairo_get_dash
cairo_get_dash_count
cairo_pattern_get_rgba
cairo_pattern_get_surface
cairo_pattern_get_color_stop_rgba
cairo_pattern_get_color_stop_count
cairo_pattern_get_linear_points
cairo_pattern_get_radial_circles
cairo_status_t is a signed type, so we need to check for invalid codes
that are < 0 as well.
Also removes the MSVC goop in path-data.c that was attempting to work
around the assert earlier.
Besides the bug fix, this is a user-visible change since the new
move_to element after the close_path element can be seen in the
results of cairo_copy_path, so we document that here.
We are also careful to fix up _cairo_path_fixed_line_to to defer to
_cairo_path_fixed_move_to to avoid letting the last_move_point state
get stale. This avoids introducing the second bug that is also tested
by the close-path test case.
This is a step toward allowing device scaling in addition to device offsets.
So far, the scale values are still always 1.0 so only the translation is
actually being used. But most of the code is in place for doing scaling as
well and it just needs to be hooked up.
There are some fragile parts in this code, all of which involve using the
translation without the scale, (so grep for device_transform.x0 or
device_transform->x0). Some of these are likely bugs that will hopefully
be obvious once we start using the scale. Others are OK if only because
we 'know' that we aren't ever setting device scaling on a surface that
has a device offset (we only set device scaling on surfaces we create
internally and we don't export device scaling to the user).
All of these fragile parts in the code have been marked with comments of
the form: XXX: FRAGILE.