[cairo-commit] 2 commits - src/cairo-quartz-surface.c src/cairo-win32-surface.c
Vladimir Vukicevic
vladimir at kemper.freedesktop.org
Sun Jan 27 16:52:43 PST 2008
src/cairo-quartz-surface.c | 144 ++++++++++++++++++++++++---------------------
src/cairo-win32-surface.c | 3
2 files changed, 78 insertions(+), 69 deletions(-)
New commits:
commit 936edecb35b94213997fdb172f0256c658f416aa
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Sun Jan 27 16:52:39 2008 -0800
[quartz] only use DrawTiledImage if transformed image is integer aligned
This Quartz API seems to only tile at integer coordinates; if the source image is
scaled to anything less than integer-aligned, seams appear between tiles. Detect
this and fall back to slower but more general CGPattern path.
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 0688284..166b443 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -766,55 +766,99 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
solid->color.alpha);
return DO_SOLID;
- } else if (source->type == CAIRO_PATTERN_TYPE_LINEAR)
- {
+ }
+
+ if (source->type == CAIRO_PATTERN_TYPE_LINEAR) {
cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t *)source;
return _cairo_quartz_setup_linear_source (surface, lpat);
- } else if (source->type == CAIRO_PATTERN_TYPE_RADIAL) {
+ }
+
+ if (source->type == CAIRO_PATTERN_TYPE_RADIAL) {
cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t *)source;
return _cairo_quartz_setup_radial_source (surface, rpat);
- } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
- (source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT)))
+ }
+
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+ (source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT)))
{
- cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source;
- cairo_surface_t *pat_surf = spat->surface;
- cairo_quartz_surface_t *quartz_surf;
- CGImageRef img;
- cairo_matrix_t m = spat->base.matrix;
- cairo_rectangle_int_t extents;
- cairo_status_t status;
+ cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source;
+ cairo_surface_t *pat_surf = spat->surface;
+ cairo_quartz_surface_t *quartz_surf;
+ CGImageRef img;
+ cairo_matrix_t m = spat->base.matrix;
+ cairo_rectangle_int_t extents;
+ cairo_status_t status;
+ CGAffineTransform xform;
+ CGRect srcRect;
+ cairo_fixed_t fw, fh;
- status = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf, &quartz_surf);
- if (status)
- return DO_UNSUPPORTED;
+ status = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf, &quartz_surf);
+ if (status)
+ return DO_UNSUPPORTED;
- surface->sourceImageSurface = (cairo_surface_t *)quartz_surf;
+ surface->sourceImageSurface = (cairo_surface_t *)quartz_surf;
- if (IS_EMPTY(quartz_surf))
- return DO_NOTHING;
+ if (IS_EMPTY(quartz_surf))
+ return DO_NOTHING;
- img = CGBitmapContextCreateImage (quartz_surf->cgContext);
- if (!img)
- return DO_UNSUPPORTED;
+ img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+ if (!img)
+ return DO_UNSUPPORTED;
- surface->sourceImage = img;
+ surface->sourceImage = img;
- cairo_matrix_invert(&m);
- _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceImageTransform);
+ cairo_matrix_invert(&m);
+ _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceImageTransform);
- status = _cairo_surface_get_extents (pat_surf, &extents);
- if (status)
- return DO_UNSUPPORTED;
+ status = _cairo_surface_get_extents (pat_surf, &extents);
+ if (status)
+ return DO_UNSUPPORTED;
+ if (source->extend == CAIRO_EXTEND_NONE) {
surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height);
+ return DO_IMAGE;
+ }
+
+ /* Quartz seems to tile images at pixel-aligned regions only -- this
+ * leads to seams if the image doesn't end up scaling to fill the
+ * space exactly. The CGPattern tiling approach doesn't have this
+ * problem. Check if we're going to fill up the space (within some
+ * epsilon), and if not, fall back to the CGPattern type.
+ */
+
+ xform = CGAffineTransformConcat (CGContextGetCTM (surface->cgContext),
+ surface->sourceImageTransform);
+
+ srcRect = CGRectMake (0, 0, extents.width, extents.height);
+ srcRect = CGRectApplyAffineTransform (srcRect, xform);
- if (source->extend == CAIRO_EXTEND_NONE)
- return DO_IMAGE;
- else
- return DO_TILED_IMAGE;
- } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ fw = _cairo_fixed_from_double (srcRect.size.width);
+ fh = _cairo_fixed_from_double (srcRect.size.height);
+
+ if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON &&
+ (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON)
+ {
+ /* We're good to use DrawTiledImage, but ensure that
+ * the math works out */
+
+ srcRect.size.width = round(srcRect.size.width);
+ srcRect.size.height = round(srcRect.size.height);
+
+ xform = CGAffineTransformInvert (xform);
+
+ srcRect = CGRectApplyAffineTransform (srcRect, xform);
+
+ surface->sourceImageRect = srcRect;
+
+ return DO_TILED_IMAGE;
+ }
+
+ /* Fall through to generic SURFACE case */
+ }
+
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
float patternAlpha = 1.0f;
CGColorSpaceRef patternSpace;
CGPatternRef pattern;
@@ -845,11 +889,9 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
surface->sourcePattern = pattern;
return DO_PATTERN;
- } else {
- return DO_UNSUPPORTED;
}
- ASSERT_NOT_REACHED;
+ return DO_UNSUPPORTED;
}
static void
@@ -1245,14 +1287,6 @@ _cairo_quartz_surface_paint (void *abstract_surface,
CGContextSaveGState (surface->cgContext);
- if (action == DO_IMAGE && op != CAIRO_OPERATOR_OVER) {
- CGContextSetRGBFillColor (surface->cgContext, 0.0, 0.0, 0.0, 0.0);
- CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
- surface->extents.y,
- surface->extents.width,
- surface->extents.height));
- }
-
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
@@ -1335,14 +1369,6 @@ _cairo_quartz_surface_fill (void *abstract_surface,
else
CGContextEOClip (surface->cgContext);
- if (action == DO_IMAGE && op != CAIRO_OPERATOR_OVER) {
- CGContextSetRGBFillColor (surface->cgContext, 0.0, 0.0, 0.0, 0.0);
- CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
- surface->extents.y,
- surface->extents.width,
- surface->extents.height));
- }
-
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
@@ -1443,14 +1469,6 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
CGContextReplacePathWithStrokedPath (surface->cgContext);
CGContextClip (surface->cgContext);
- if (action == DO_IMAGE && op != CAIRO_OPERATOR_OVER) {
- CGContextSetRGBFillColor (surface->cgContext, 0.0, 0.0, 0.0, 0.0);
- CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
- surface->extents.y,
- surface->extents.width,
- surface->extents.height));
- }
-
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
@@ -1603,14 +1621,6 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
num_glyphs);
if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
- if (action == DO_IMAGE && op != CAIRO_OPERATOR_OVER) {
- CGContextSetRGBFillColor (surface->cgContext, 0.0, 0.0, 0.0, 0.0);
- CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
- surface->extents.y,
- surface->extents.width,
- surface->extents.height));
- }
-
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
commit 182b02240192c03b1fae5367573962d527f8aad4
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Sat Jan 26 10:57:20 2008 -0800
[win32] Fix initial clip region test
I misread the docs; GetClipBox's return value doesn't necessarily correspond to
GetClipRgn's region type.
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 69c6406..4017e2f 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -2052,8 +2052,7 @@ _cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface)
if (clipBoxType == COMPLEXREGION) {
surface->initial_clip_rgn = CreateRectRgn (0, 0, 0, 0);
- if (GetClipRgn (hdc, surface->initial_clip_rgn) == -1) {
- /* this should never happen */
+ if (GetClipRgn (hdc, surface->initial_clip_rgn) <= 0) {
DeleteObject(surface->initial_clip_rgn);
surface->initial_clip_rgn = NULL;
}
More information about the cairo-commit
mailing list