Restrict the area we acquire from the source image to the bounds of
the source image, even when we have an identity matrix. This handles
circumstances where the pattern extents may be enlarged due to
filtering, for example when applying a bilinear filter.
This patch replaces the open-coded rectangle intersection which has
already proven itself to be a source of bugs.
(Patch ported to master by Chris Wilson, all bugs are his.)
Remove instances (abuses) of calling _cairo_pattern_acquire_surface() on
a known-surface-pattern with a hack to say "give me the entire surface".
If you know you just want the entire surface as an image surface, that
can be done more simply.
(Split from original patch on
https://bugs.freedesktop.org/attachment.cgi?id=15703, by Chris Wilson -
as usual all bugs are his.)
A little bit of sleep and reflection suggested that the use of
device_offset_[xy] was confusing and clone_offset_[xy] more consistent
with the function naming.
Previously the rule for clone_similar() was that the returned surface
had exactly the same size as the original, but only the contents within
the region of interest needed to be copied. This caused failures for very
large images in the xlib-backend (see test/large-source).
The obvious solution to allow cloning only the region of interest seemed
to be to simply set the device offset on the cloned surface. However, this
fails as a) nothing respects the device offset on the surface at that
layer in the compositing stack and b) possibly returning references to the
original source surface provides further confusion by mixing in another
source of device offset.
The second method was to add extra out parameters so that the
device offset could be returned separately and, for example, mixed into
the pattern matrix. Not as elegant, a couple of extra warts to the
interface, but it works - one less XFAIL...
A surface pattern under an extreme transformation could lie entirely in
the negative quadrant. This would trigger the fixup such that it's lower
left corner was clamped to the origin, but the upper right corner was left
unchecked. This could result in the width,height being negative and
wrapping around to large values instead of being clamped to 0.
Adding warn_unused_result to pixman detected a couple of instances where
we abused the knowledge that the code currently can not fail, but in
deference to its independent existence we should be more cautious.
Keep the reference count as zero for temporary, on-stack patterns in
order to detect attempts to keep references beyond their scope. (And
mismatched _init()/_destroy()).
Ickle knew something when he only extended cache size when we are
committed to inserting something into the cache. I broke that while
fixing other issues a while ago. This cache just doesn't want to
give us any rest...
This can be used by _cairo_pattern_acquire_surface_for_solid() to let
the backend create custom surfaces for solid fill instead of a 1x1
similar surface.
This was added in 41c6eebcd1, to avoid
allocating short-lived patterns. However, this was error prune as the
color information was duplicated in the pattern and could get out of
sync. Indeed, it was out of sync before this commit in the call from
cairo-clip.c.
By allocating the solid pattern on the stack we fix the original problem
without creating new ones.
The code in that cache is becoming uglier and uglier. But at least it
works correctly again. Time for a rewrite.
(Also move the destroy after unlocking)
Behdad Esfahbod complained that commit
8457374c9c overwhelmed the function with
added complexity and arbitrary limited a backend to one-quarter of the
cache. The elegant solution, he outlined, was to look at the surface that
would be evicted and if possible repaint it, instead of creating a
replacement. This not only simplifies the code, reduces the number of
checks performed to find a match (or victim) and allows the cache to be
naturally shared between the various backends.
cairo_surface_destroy and _cairo_scaled_font_fini will call destroy closures
which may call functions that attempt to acquire the mutex resulting in a
deadlock. We fix this by releasing the lock for the call to
cairo_surface_destroy or _cairo_scaled_font_fini.
This reverts commit ddcd6781a2.
This was an experimental commit that was intended to be on a side
branch but accidentally got committed and pushed to master. Sorry
for the noise.
This is an initial attempt at addressing the recently noticed
fallback-resolution bug. It isn't working correctly yet.
I'm just committing so that behdad can see what I'm up to.
With things like meta-surface, the assumption that coordinates are always
non-negative make no sense. Extend the "infinite" extents accordingly.
Also remove stale comment. extents->width/height are unsigned these days and
cover the full range.
The current solid surface cache returns an existing similar surface only
if it is an exact match for the desired colour. This gives a high hit
rate for the original goal of drawing text, but fails when using a lot
of colours - for example drawing a pie-chart, the mosaic perf case, or
browsing the web. So instead of creating a new surface from scratch we
can repaint an existing one, providing that we have sufficient surfaces
already cached, i.e. if we are going to evict a surface, we may as well
just repaint it.
This reverts commit 731e121c80.
This commit introduced various problems, (some likely noticeable
in the test suite, and others perhaps not). For some details, see
the latest comments in the original bug report leading to the
fix now being reverted:
http://bugs.freedesktop.org/show_bug.cgi?id=15349
This fixes the filter-bilinear-extents test case and the
related bug entry:
bad clipping with EXTEND_NONE
http://bugs.freedesktop.org/show_bug.cgi?id=15349
Though there are still differences in the PDF and PostScript
backends, (primarily because we can't capture cairo's filter
modes in those file formats).
Previously we were using the cairo_fixed_t type which meant we've
historically only been using 16 bits of precision for these offsets,
and recently only 8 bits. Meanwhile, all manipulatons of offsets
have been in floating-point anyway, so we might as well store them
that way.
This change also prevents a rendering regression introduced with the
24.8->16.16 change betwen snapshots 1.5.10 and 1.5.12 .
This change affected gradient-rendering details for the clip-operator
and operator-source tests, so the corresponding reference images are
updated here.
On the default case for an unknown pattern type, add an assert that the
code is never reached, and just in case upgrade the error to a fatal
PATTERN_TYPE_MISMATCH.
test/pattern-get-type exposes a bug whereby we try to acquire the
_cairo_pattern_solid_pattern_cache_lock before initializing the
mutexes. To fix this move the CAIRO_MUTEX_INITIALIZE() from the
depths of _cairo_pattern_init() and perform it at the public entry
points.
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.