Surface sources were not respecting EXTEND_NONE when composited
because the part outside of the surface rectangle was not changed.
To correctly extend the source, it's sufficient to composite a
transparent rectangle with a hole in the region covered by the surface.
Fixes clip-unbounded and operator-source. Changes the output of
surface-pattern-operator.
Stroking was not fixed up correctly when the stroke trasform
was not the identity and when the stroked path was dashed.
Instead of building a mask image and clearing through it
(forgetting to use the CTM and the dash setting), the code now
simply fills the outside of the stroke with tranparent black.
Additionally this commit moves the CTM composition so that the invocation
of _cairo_quartz_setup_source is always done with the base CTM.
This commit changes the result of clip-stroke-unbounded (the clip
mask is now correctly aligned to the stroked path).
A8 images were cosidered grayscale, whereas they should behave like
transparency mask. They are now alpha-only images and the stride is
16-bytes aligned, as suggested.
Fixes alpha-similar and mask-transformed-similar. Makes the patterns
behave (as expected) as masks in surface-pattern-operator.
Affects the output of operator-alpha-alpha, but the result is not
correct because of wrong compositing.
CTM was changed and not restored when painting gradients.
Fixes the alignment of surface patterns in surface-pattern-operator.
Patch by Robert O'Callahan, see Mozilla bug #507939.
Gah, that was a horrible mistake. It was a flawed hack to create Pixmaps
of the correct depth when cloning patterns for blitting to the xlib
backend. However, it had the nasty side-effect of discarding alpha when
targeting Window surfaces. The correct solution is to simply correct the
Pixmap of the desired depth and render a matching pattern onto the
surface - i.e. a reversal the current acquire -> clone. See the
forthcoming revised xcb backend on how I should have done it originally.
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
▏
This patch adds more implementation of the snapshot method. For
surface types where acquire_source_image is already making a copy
of the bits, doing another one as is the case for the fallback
implementation is a waste.
Damian Frank noted
[http://lists.cairographics.org/archives/cairo/2009-May/017095.html]
a performance problem with an older XServer with an
unaccelerated composite - similar problems will be seen with non-XRender
servers which will trigger extraneous fallbacks. The problem he found was
that painting an ARGB32 image onto an RGB24 destination window (using
SOURCE) was going via the RENDER protocol and not core. He was able to
demonstrate that this could be worked around by declaring the pixel data as
an RGB24 image. The issue is that the image is uploaded into a temporary
pixmap of matching depth (i.e. 32 bit for ARGB32 and 24 bit for RGB23
data), however the core protocol can only blit between Drawables of
matching depth - so without the work-around the Drawables are mismatched
and we either need to use RENDER or fallback.
This patch adds a content mask to _cairo_surface_clone_similar() to
provide the extra bit of information to the backends for when it is
possible for them to drop channels from the clone. This is used by the
xlib backend to only create a 24 bit source when blitting to a Window.
Adds an error code replacing CAIRO_STATUS_NO_MEMORY in one case where it
is not really appropriate. CAIRO_STATUS_INVALID_SIZE is used by several
backends that do not support image sizes beyond 2^15 pixels on each side.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
RTLD_DEFAULT is a gnu-ism (at least according to the manpage on my linux
system) so declare _GNU_SOURCE before including dlfcn.h and failing that
provide our own definition.
The pattern could be stack allocated so we can't take a reference to it.
Some testing of quartz shows that it doesn't deal with malloc failure particularily
well. In the best case CGFunctionCreate returns NULL, in the worst case it just crashes.
Quartz does seem to be able to handle a NULL CGFunctionRef, so returning NULL if
we fail to copy the pattern avoids complicating the code to deal with
propagating the failure and shouldn't cause any additional crashes.
Based on a patch by Paolo Bonzini.
As part of this avoid using cairo_pattern_get_matrix() because it requires a
'cairo_pattern_t *' instead of 'const cairo_pattern *'
Also, make a copy of the pattern before pasing it in to cairo_set_source()
A surface will have the chance to use span rendering at cairo_fill()
time by creating a renderer for a specific combination of
pattern/dst/op before the path is scan converted. The protocol is to
first call check_span_renderer() to see if the surface wants to render
with spans and then later call create_span_renderer() to create the
renderer for real once the extents of the path are known.
No backends have an implementation yet.
7944601864 broke the quartz backend.
Fix it by adding const to the appropriate parameters in the function
declarations and copying the pattern when needed.
Add a "cairo_rectangle_int_t *extents" argument to to the following
backend functions:
paint
mask,
stroke
fill
show_glyphs
show_text_glyphs
This will be used to pass the extents of each operation computed by
the analysis surface to the backend. This is required for implementing
EXTEND_PAD.
Only copy the pattern if we need to modify it, e.g. preserve a copy in a
snapshot or a soft-mask, or to modify the matrix. Otherwise we can
continue to use the original pattern and mark it as const in order to
generate compiler warnings if we do attempt to write to it.
Avoid masking fatal errors by enforcing any error to be returned via an
error surface, so that the NULL return only means UNSUPPORTED. A few
backends called their create_similar() directly, without correctly checking
for a potential NULL (for example, the directfb backend was a timebomb,
since it used NULL to indicate out-of-memory).
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...
Instead of allocating the union of all possible pattern types, just
allocate the specific pattern as used by the function in order to trim
the stack space consumption and flag potential misuse.
Originally reported here:
http://lists.cairographics.org/archives/cairo/2008-May/014032.html
and analyized later in the thread.
Change (font and surface) backend show_glyphs() API to take a
int *remaining_glyphs argument. It's used to communicate to the caller,
by way of setting remaining_glyphs and returning INT_STATUS_UNSUPPORTED,
that some of the glyphs were shown but not the others. The xlib backend
now correctly uses this to handle failure to upload a glyph to the server.
So the large-font test passes now.
An alternative approach could be to add some public value for glyphs
indices that are not shown. -1 perhaps (the xlib backend already uses
that value internally). Then instead of remaining_glyphs, a backend
could simply set glyph indices of glyphs shown to that -1 value.
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.
We use the floating-point value later, and we can end up with weirdness
such as negative colors due to the precision mismatch of our fixed
point vs. floating point type. So just do everything in floating
point.
In some cases (in my case, having an external monitor attached to my
MBP), Quartz seems to default to grayscale AA even when it should be
using subpixel AA. CGContextGetAllowsFontSmoothing returns FALSE in
this case (pretty sure this is a Quartz bug). We can force subpixel
AA in this case by setting CGContextSetAllowsFontSmoothing.
Creating a CGImage with interpolation set to FALSE means that
it will never be interpolated; otherwise the interoplation
is controlled by the destination context's interpolation
quality setting.
Implement REPEAT/REFLECT for gradients in Quartz: for linear gradients,
they're implemented natively (by extending the gradient region); for
radial gradients, we generate a fallback image using pixman and render
that.
A CoreGraphics bug was fixed so strokes are no longer incorrectly
drawn with antialiasing disabled; we no longer have to ignore
antialiasing for stroke(). Also, antialiasing was not being
correctly set for clip(). This fixes both issues.