Document this function as a required call to get the correct
stride value before calling cairo_image_surface_create_for_data.
This means that previously-failing calls with non-multiple-of-4
stride values are now documented as errors. Also, we now have
the possibility of moving to more stringent alignment constraints,
(one can imagine doing 64-bit or 128-bit boundaries for example).
It's a common idiom to stroke degenerate sub-paths made with
cairo_move_to(x,y);cairo_rel_line_to(0,0) to draw dots. Test
that we get the desired extents from cairo_fill_extents,
cairo_stroke_extents, and cairo_path_extents for these cases.
Also document that the cairo_path_extents result is equivalent
to the limit of stroking with CAIRO_LINE_CAP_ROUND, (so that
these "dot" points are included), as the line width
approaches 0.0 .
This new function gets the extents of the current path, whether
or not they would be inked by a 'fill'. It differs from
cairo_fill_extents() when the area enclosed by the path is 0.
Includes documentation and updated test.
The only caller of cairo_path_fixed_get_current_point(), used the status
return to determine whether or not the path had a current point (and did
not propagate the error) - for which we had already removed the
_cairo_error() markup. Now we reduce the boolean status return to a
cairo_bool_t, with a net reduction in code.
Put a guard that checks the context's status at the start of each
getter that prevents the function from trying to dereference NULL state.
Use the status, as opposed to the invalid reference count, for
consistency with the existing guards on some of the getters.
Every time we assign or return a hard-coded error status wrap that value
with a call to _cairo_error(). So the idiom becomes:
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
or
return _cairo_error (CAIRO_STATUS_INVALID_DASH);
This ensures that a breakpoint placed on _cairo_error() will trigger
immediately cairo detects the error.
As pointed out by Jeff Muizelaar, this allows for more concise code, as
_cairo_error(CAIRO_STATUS_NO_MEMORY)
return CAIRO_STATUS_NO_MEMORY
can become
return _cairo_error(CAIRO_STATUS_NO_MEMORY);
Since the objects can be shared and may be in use simultaneously across
multiple threads, setting the status needs to be atomic. We use a
locked compare and exchange in order to avoid overwriting an existing
error - that is we use an atomic operation that only sets the new status
value if the current value is CAIRO_STATUS_SUCCESS.
As we now generate empty paths, we must be able to handle empty paths
in the user facing API. cairo_append_path() has an explicit check, and
raises an error, for a NULL path->data, so we need to check the
path->num_data first for empty paths.
Introduce an opaque cairo_reference_count_t and define operations on it
in terms of atomic ops. Update all users of reference counters to use
the new opaque type.
This patch adds cairo_surface_copy_page and cairo_surface_show_page
as public methods, leaving the previous cairo_show_page variants as
shorthands. copy_page/show_page are specific to the surface, not
to the context, so they need to be surface methods.
Set the cairo_t status to be the surface->status when the context is
created, and special case the NO_MEMORY status in order to avoid a
redundant allocation.
cairo_pop_group() checks for a NULL return from
cairo_pattern_create_for_surface() instead of the nil cairo_pattern_t,
and then returns a NULL pattern instead of the nil object.
The design is for the user to create a cairo_font_options_t object with
cairo_font_options_create() and then is free to use it with any Cairo
operation. This requires us to check when we may be about to overwrite
the read-only nil object.
This allows for the surface acquired from the pattern to have the
same content. In particular, in a case such as cairo_paint_with_alpha
we can now acquire an A8 mask surface instead of an ARGB32 mask
surface which can be rendered much more efficiently. This results
in a 4x speedup when using the OVER operator with the recently
added paint-with-alpha test:
Speedups
========
image-rgb paint-with-alpha_image_rgb_over-256 2.25 -> 0.60: 4.45x speedup
███▌
It does slowdown the same test when using the SOURCE operator, but
I don't think we care. Performing SOURCE with a mask is already a very
slow operation, (hitting compositeGeneral), so the slowdown here is
likely from having to convert from A8 back to ARGB32 before the
generalized compositing. So if someone cares about this slowdown,
(though SOURCE with cairo_paint_with_alpha doesn't seem extremely
useful), they will probably be motivated enough to contribute a
customized compositing function to replace compositeGeneral in which
case this slowdown should go away:
image-rgba paint-with-alpha_image_rgb_source-256 3.84 -> 8.86%: 1.94x slowdown
█
This is just multiplication after all, so there's nothing that can fail.
And we can get rid of a lot of useless error-checking code this way.
The corrected functions are:
_cairo_gstate_user_to_device
_cairo_gstate_user_to_device_distance
_cairo_gstate_device_to_user
_cairo_gstate_device_to_user_distance
Now that we have the warn_unused_result attribute enabled, (thanks
Chris!), it's actually harmful to have a function return an
uncoditional value of CAIRO_STATUS_SUCCESS. The harm is that
it would force lots of unnecessary error-checking paths that
just add clutter.
It is much better to simply give a function that cannot fail
a return type of void.
The idiom for cairo.c is to do
cr->status = _cairo_op ();
if (cr->status) _cairo_set_error (cr, cr->status);
Unfortunately a trivial mistake for a _cairo_op () is to call a cairo_op ()
and forget to check cr->status but return CAIRO_STATUS_SUCCESS which will
mask the earlier error.
Obviously this is a bug in the lower level but the impact can be reduced
by chaning cairo.c to use a local status variable for its return:
cairo_status_t status = _cairo_op ();
if (status) _cairo_set_error (cr, cr->status);
Previously, the convention was that static ones started with cairo_, but
renamed to start with _cairo_ when they were needed from other files and
became cairo_private instead of static...
This is error prune indeed, and two symbols were already violating. Now
all nil objects start with _cairo_.
Frequently cairo_set_source_rgb[a]() is used to replace the current
solid-pattern source with a new one of a different colour. The current
pattern is very likely to be unshared and unmodified and so it is likely
just to be immediately freed [or rather simply moved to recently freed
cache]. However as the last active pattern it is likely to cache-warm and
suitable to satisfy the forthcoming allocation. So by setting the current
pattern to 'none' we can move the pattern to the freed list before we
create the new pattern and hopefully immediately reuse it.