Use _cairo_pattern_create_copy()/cairo_pattern_destroy() instead of
_cairo_pattern_init_copy()/_cairo_pattern_fini() so the PDF backend
can reference the patterns and destroy them later.
If the backend does not support fallbacks ie backend->acquire_dest_image
or backend->acquire_source_image is NULL, then return
CAIRO_INT_STATUS_UNSUPPORTED rather than attempt to jump to the NULL
hooks.
In http://bugs.freedesktop.org/show_bug.cgi?id=13699, Pavel Vozenilek
reports a duplicate define for computing the appropriate length for an
on-stack array. The macro in question, and a few other places, was
performing CAIRO_STACK_BUF_SIZE/sizeof(stack[0]) so we can simplify
them slightly by using a common macro.
_cairo_surface_fill_region(): avoid allocating the array of boxes if we
know that the region only contains one box and is therefore defined by its
extents.
Adrian Johnson hit a SEGV after
_cairo_paginaged_surface_create_image_surface() tried to set the font
options on an error surface after running out of memory. So add the
usual checks that the surface is not a snapshot, or in an error state or
finished before modifying its font options.
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.
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.
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.
This reverts commit 919bea6dbb.
Sadly as Behdad points out some backends do modify the glyph array and,
for example cairo-xlib-surface, hide this from the compiler with some
evil casts.
Skip the memory duplication of the incoming glyphs if we do not need
to transform them into the backend coordinate system.
As a consequence we need to constify the glyphs passed to the backend
functions.
This method is for use in vector backends, where fill immediatly followed by
stroke command with the same path can be emited in the same backend command.
This commit also factorize the detection of such cases in the meta surface
backend and automatically call the fill_stroke method on replay.
This patch introduces three macros: _cairo_malloc_ab,
_cairo_malloc_abc, _cairo_malloc_ab_plus_c and replaces various calls
to malloc(a*b), malloc(a*b*c), and malloc(a*b+c) with them. The macros
return NULL if int overflow would occur during the allocation. See
CODING_STYLE for more information.
Previously if the backend finish() function returned an error status,
surface->finished was not set true. This would result in the backend
finish() function being called twice which in the case of the PostScript
backend caused a seg fault.
During the copy, allocation of the gradient may fail and so the callers
need to check for a pattern that returned in an error state. No callers
did so and in order to force all callers to check the error status,
the status return was added to _cairo_pattern_init_copy(). The early
error checking may appear redundant for an object with an embedded
structure, however it does fix an error where an uninitialised pattern
was being used:
==1922== Process terminating with default action of signal 11 (SIGSEGV)
==1922== Access not within mapped region at address 0x55555555
==1922== at 0x402CF6F: _cairo_array_index (cairo-array.c:208)
==1922== by 0x402D4F3: _cairo_user_data_array_fini (cairo-array.c:370)
==1922== by 0x4046464: _cairo_pattern_fini (cairo-pattern.c:188)
==1922== by 0x404992A: _cairo_meta_surface_paint (cairo-meta-surface.c:266)
==1922== by 0x403FCE0: _cairo_surface_paint (cairo-surface.c:1331)
==1922== by 0x405CB5E: _test_meta_surface_paint (test-meta-surface.c:195)
==1922== by 0x403FCE0: _cairo_surface_paint (cairo-surface.c:1331)
==1922== by 0x4032A60: _cairo_gstate_paint (cairo-gstate.c:822)
==1922== by 0x402B2D1: cairo_paint (cairo.c:1879)
==1922== by 0x804A4F7: draw (radial-gradient.c:73)
==1922== by 0x804AFA4: cairo_test_expecting (cairo-test.c:326)
==1922== by 0x804A57C: main (radial-gradient.c:109)
==1922== Injected fault at:
==1922== at 0x4020EA5: malloc (vg_replace_malloc.c:207)
==1922== by 0x404475C: _cairo_pattern_init_copy (cairo-pattern.c:136)
==1922== by 0x403F779: _cairo_surface_copy_pattern_for_destination (cairo-surface.c:2153)
==1922== by 0x403FCC1: _cairo_surface_paint (cairo-surface.c:1328)
==1922== by 0x405CB5E: _test_meta_surface_paint (test-meta-surface.c:195)
==1922== by 0x403FCE0: _cairo_surface_paint (cairo-surface.c:1331)
==1922== by 0x4032A60: _cairo_gstate_paint (cairo-gstate.c:822)
==1922== by 0x402B2D1: cairo_paint (cairo.c:1879)
==1922== by 0x804A4F7: draw (radial-gradient.c:73)
==1922== by 0x804AFA4: cairo_test_expecting (cairo-test.c:326)
==1922== by 0x804A57C: main (radial-gradient.c:109)
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.
Original work by Jorn Baayen <jorn@openedhand.com>,
2715f20981
We use a small cache of size 16 for surfaces created for solid patterns.
This mainly helps with the X backends where we don't have to create a
pattern for every operation, so we save a lot on X traffic. Xft uses a
similar cache, so cairo's text rendering traffic with the xlib backend
now completely matches that of Xft.
The cache uses an static index variable, which itself acts like a cache of
size 1, remembering the most recently used solid pattern. So repeated
lookups for the same pattern hit immediately. If that fails, the cache is
searched linearly, and if that fails too, a new surface is created and a
random member of the cache is evicted.
A cached surface can only be reused if it is similar to the destination.
In order to check for similar surfaces a new test is introduced for the
backends to determine that the cached surface is as would be returned by
a _create_similar() call for the destination and content.
As surfaces are in general complex encapsulation of graphics state we
only return unshared cached surfaces and reset them (to clear any error
conditions and graphics state). In practice this makes little difference
to the efficacy of the cache during various benchmarks. However, in order
to transparently share solid surfaces it would be possible to implement a
COW scheme.
Cache hit rates: (hit same index + hit in cache) / lookups
cairo-perf: (42346 + 28480) / 159600 = 44.38%
gtk-theme-torturer: (3023 + 3502) / 6528 = 99.95%
gtk-perf: (8270 + 3190) / 21504 = 53.29%
This translates into a reduction of about 25% of the XRENDER traffic during
cairo-perf.
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
█
_cairo_surface_create_similar_solid() creates a fresh pattern to wrap
color, however sometimes the caller already has that pattern available.
In those circumstances we can pass the pattern as well as the color and
avoid the extra allocation.
Fixing this uncovered a leak of a CAIRO_INT_STATUS_UNSUPPORTED value
up to cairo_show_page, (and similarly to cairo_copy_page). There was
really no good reason for _cairo_surface_show_page and
_cairo_surface_copy_page to be returning cairo_int_status_t. Fix
this by simply handling the UNSUPPORTED return at the surface layer
instead of the gstate layer.
Most of the time pixman_region_init is called without any extents, and
followed by a pixman_region_union_rect, used to used to initialize
rectangular regions. pixman_region_union_rect is not that cheap, but
the sequence is called quite often. So it should be worth introducing
a specialized and fast function for this sequence.
This introduces pixman_region_init_rect. This new function makes
_cairo_region_init_from_rectangle obsolete.
Also removes the extent argument from pixman_region_init as it was
called with NULL most of the time. A pixman_region_init_with_extents
is added for the general case.
This is necessary to avoid many portability problems as cairoint.h includes
config.h. Without a test, we will regress again, hence add it.
The inclusion idiom for cairo now is:
#include "cairoint.h"
#include "cairo-something.h"
#include "cairo-anotherthing-private.h"
#include <some-library.h>
#include <other-library/other-file.h>
Moreover, some standard headers files are included from cairoint.h and need
not be included again.
All mutex declarations have been moved to cairo-mutex-list.h.
This should avoid breaking of less frequently tested backends,
when mutexes are introduced or when existing mutexes are renamed.
Instead of initializing mutexes on library startup, mutexes are
lazily initialized within the few entry points of now by calling
CAIRO_MUTEX_INITIALIZE(). Currently only the OS/2 backend takes
care about releasing global mutexes. Therefore there is no counter
part of that macro for finalizing all global mutexes yet - but
as cairo-backend-os2.c shows such a function would be quite
easy to implement.
We detect an error in the surface before calling into private surface-modifying
functions, (such as _cairo_surface_set_font_options), that don't have the
nil-surface protection of public functions.
This should fix the problem reported (again) in this bug report:
cairo crashes in cairo_create_simular if nil surface returned by other->backend->create_similar
https://bugs.freedesktop.org/show_bug.cgi?id=9844
Though I haven't succeeded in replicating the bug yet, (perhaps a system
difference in allowing writes to read-only memory or not, or something
like that).