[cairo-commit] 4 commits - src/cairo-pattern.c src/cairo-xlib-display.c test/filter-bilinear-extents.c test/filter-bilinear-extents-ref.png test/.gitignore test/Makefile.am
Carl Worth
cworth at kemper.freedesktop.org
Fri Apr 4 19:00:48 PDT 2008
src/cairo-pattern.c | 83 ++++++++++++++++++-------------
src/cairo-xlib-display.c | 11 ++++
test/.gitignore | 1
test/Makefile.am | 2
test/filter-bilinear-extents-ref.png |binary
test/filter-bilinear-extents.c | 91 +++++++++++++++++++++++++++++++++++
6 files changed, 154 insertions(+), 34 deletions(-)
New commits:
commit 731e121c802a7b1c3429d1bde7a93bc471d70880
Author: Carl Worth <cworth at cworth.org>
Date: Fri Apr 4 19:00:28 2008 -0700
_cairo_pattern_get_extents: Fix to allow for expansion based on filter
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).
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 0eb90ae..e1d4b5c 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1991,6 +1991,28 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
x2 = x1 + surface_extents.width;
y2 = y1 + surface_extents.height;
+ /* The filter can effectively enlarge the extents of the
+ * pattern, so extend as necessary. Note: We aren't doing any
+ * backend-specific querying of filter box sizes at this time,
+ * (since currently no specific backends that could do custom
+ * filters are calling _cairo_pattern_get_extents). */
+ switch (pattern->filter) {
+ case CAIRO_FILTER_GOOD:
+ case CAIRO_FILTER_BEST:
+ case CAIRO_FILTER_BILINEAR:
+ x1 -= 0.5;
+ y1 -= 0.5;
+ x2 += 0.5;
+ y2 += 0.5;
+ break;
+ case CAIRO_FILTER_FAST:
+ case CAIRO_FILTER_NEAREST:
+ case CAIRO_FILTER_GAUSSIAN:
+ default:
+ /* Nothing to do */
+ break;
+ }
+
imatrix = pattern->matrix;
status = cairo_matrix_invert (&imatrix);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
commit 04608952e2efb9bffaa131ab39780c3e1a7430ba
Author: Carl Worth <cworth at cworth.org>
Date: Fri Apr 4 18:56:38 2008 -0700
Replace open-coded transformation with a call to _cairo_matrix_transform_bounding_box
It's a wonderful feeiling to remove duplicate code.
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index bd67163..0eb90ae 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1980,50 +1980,43 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
(cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;
cairo_matrix_t imatrix;
- double x, y;
- /* Initialize to keep the compiler quiet. */
- int left=0, right=0, top=0, bottom=0;
- int lx, rx, ty, by;
- int sx, sy;
- cairo_bool_t set = FALSE;
+ double x1, y1, x2, y2;
status = _cairo_surface_get_extents (surface, &surface_extents);
if (status)
return status;
+ x1 = surface_extents.x;
+ y1 = surface_extents.y;
+ x2 = x1 + surface_extents.width;
+ y2 = y1 + surface_extents.height;
+
imatrix = pattern->matrix;
status = cairo_matrix_invert (&imatrix);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
- /* XXX Use _cairo_matrix_transform_bounding_box here */
- for (sy = 0; sy <= 1; sy++) {
- for (sx = 0; sx <= 1; sx++) {
- x = surface_extents.x + sx * surface_extents.width;
- y = surface_extents.y + sy * surface_extents.height;
- cairo_matrix_transform_point (&imatrix, &x, &y);
- if (x < 0) x = 0;
- if (x > CAIRO_RECT_INT_MAX) x = CAIRO_RECT_INT_MAX;
- if (y < 0) y = 0;
- if (y > CAIRO_RECT_INT_MAX) y = CAIRO_RECT_INT_MAX;
- lx = floor (x); rx = ceil (x);
- ty = floor (y); by = ceil (y);
- if (!set) {
- left = lx;
- right = rx;
- top = ty;
- bottom = by;
- set = TRUE;
- } else {
- if (lx < left) left = lx;
- if (rx > right) right = rx;
- if (ty < top) top = ty;
- if (by > bottom) bottom = by;
- }
- }
- }
- extents->x = left; extents->width = right - left;
- extents->y = top; extents->height = bottom - top;
+ _cairo_matrix_transform_bounding_box (&imatrix,
+ &x1, &y1, &x2, &y2,
+ NULL);
+
+ x1 = floor (x1);
+ if (x1 < 0)
+ x1 = 0;
+ y1 = floor (y1);
+ if (y1 < 0)
+ y1 = 0;
+
+ x2 = ceil (x2);
+ if (x2 > CAIRO_RECT_INT_MAX)
+ x2 = CAIRO_RECT_INT_MAX;
+ y2 = ceil (y2);
+ if (y2 > CAIRO_RECT_INT_MAX)
+ y2 = CAIRO_RECT_INT_MAX;
+
+ extents->x = x1; extents->width = x2 - x1;
+ extents->y = y1; extents->height = y2 - y1;
+
return CAIRO_STATUS_SUCCESS;
}
commit 89567f9278c002ac5e4e25ddccec88b1b1eea420
Author: Carl Worth <cworth at cworth.org>
Date: Fri Apr 4 18:28:23 2008 -0700
Add new filter-bilinear-extents test
This test exercises code that computes the extents of a surface
pattern with CAIRO_FILTER_BILINEAR, (where the filtering
effectively increases the extents of the pattern).
The original bug was reported by Owen Taylor here:
bad clipping with EXTEND_NONE
http://bugs.freedesktop.org/show_bug.cgi?id=15349
diff --git a/test/.gitignore b/test/.gitignore
index af0387a..564a8ed 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -63,6 +63,7 @@ fill-and-stroke-alpha-add
fill-degenerate-sort-order
fill-missed-stop
fill-rule
+filter-bilinear-extents
filter-nearest-offset
finer-grained-fallbacks
ft-text-antialias-none
diff --git a/test/Makefile.am b/test/Makefile.am
index f02a5ac..a6f0bd9 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -51,6 +51,7 @@ fill-and-stroke-alpha-add$(EXEEXT) \
fill-degenerate-sort-order$(EXEEXT) \
fill-missed-stop$(EXEEXT) \
fill-rule$(EXEEXT) \
+filter-bilinear-extents$(EXEEXT) \
filter-nearest-offset$(EXEEXT) \
finer-grained-fallbacks$(EXEEXT) \
font-face-get-type$(EXEEXT) \
@@ -383,6 +384,7 @@ REFERENCE_IMAGES = \
fill-rule-ref.png \
fill-rule-rgb24-ref.png \
fill-rule-ps-rgb24-ref.png \
+ filter-bilinear-extents-ref.png \
filter-nearest-offset-ref.png \
finer-grained-fallbacks-ref.png \
finer-grained-fallbacks-rgb24-ref.png \
diff --git a/test/filter-bilinear-extents-ref.png b/test/filter-bilinear-extents-ref.png
new file mode 100644
index 0000000..61e416b
Binary files /dev/null and b/test/filter-bilinear-extents-ref.png differ
diff --git a/test/filter-bilinear-extents.c b/test/filter-bilinear-extents.c
new file mode 100644
index 0000000..a39a37c
--- /dev/null
+++ b/test/filter-bilinear-extents.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors: Carl D. Worth <cworth at cworth.org>
+ * Owen Taylor <otaylor at redhat.com>
+ */
+
+#include "cairo-test.h"
+
+static cairo_test_draw_function_t draw;
+
+/* This test exercises code that computes the extents of a surface
+ * pattern with CAIRO_FILTER_BILINEAR, (where the filtering
+ * effectively increases the extents of the pattern).
+ *
+ * The original bug was reported by Owen Taylor here:
+ *
+ * bad clipping with EXTEND_NONE
+ * http://bugs.freedesktop.org/show_bug.cgi?id=15349
+ */
+
+#define SCALE 10
+#define PAD 3
+#define WIDTH (PAD + 3 * SCALE + PAD)
+#define HEIGHT WIDTH
+
+cairo_test_t test = {
+ "filter-bilinear-extents",
+ "Test that pattern extents are properly computed for CAIRO_FILTER_BILINEAR",
+ WIDTH, HEIGHT,
+ draw
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_surface_t *checker;
+ cairo_t *cr2;
+
+ /* Create a 2x2 blue+red checker */
+ checker = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 2, 2);
+ cr2 = cairo_create (checker);
+
+ cairo_set_source_rgb (cr2, 1, 0 ,0); /* red */
+ cairo_paint (cr2);
+ cairo_set_source_rgb (cr2, 0, 0, 1); /* blue */
+ cairo_rectangle (cr2, 0, 1, 1, 1);
+ cairo_rectangle (cr2, 1, 0, 1, 1);
+ cairo_fill (cr2);
+ cairo_destroy (cr2);
+
+ /* Draw our surface scaled with EXTEND_NONE */
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ cairo_save (cr);
+ cairo_translate (cr, PAD, PAD);
+ cairo_scale (cr, SCALE, SCALE);
+ cairo_translate (cr, 0.5, 0.5);
+ cairo_set_source_surface (cr, checker, 0, 0);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test);
+}
commit 80f7aa03b35921a96683a0442f885c4b8335f3d9
Author: Carl Worth <cworth at cworth.org>
Date: Fri Apr 4 11:29:47 2008 -0700
Enable buggy_repeat workaround for X.Org servers < 1.4
This covers the known-to-broken 1.3 servers such as appeared
in Fedora 8. It also leaves the workaround off, (since it's
a severe slowdown), for the known-to-be-working 1.4.99.901
server as appears in Fedora 9 Betas.
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index 20bad2e..b1fc67e 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -298,6 +298,17 @@ _cairo_xlib_display_get (Display *dpy)
* back up to 6.7 or 6.8. */
if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) <= 60802000)
display->buggy_repeat = TRUE;
+
+ /* But even the new modular server has bugs, (bad enough to
+ * crash the X server), that it so happens we can avoid with
+ * the exact same buggy_repeat workaround. We've verified that
+ * this bug exists as least as late as version 1.3.0.0, (which
+ * is in Fedora 8), and is gone again in version 1.4.99.901
+ * (from a Fedora 9 Beta). Versions between those are still
+ * unknown, but until we learn more, we'll assume that any 1.3
+ * version is buggy. */
+ if (VendorRelease (dpy) < 10400000)
+ display->buggy_repeat = TRUE;
} else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
if (VendorRelease (dpy) <= 40500000)
display->buggy_repeat = TRUE;
More information about the cairo-commit
mailing list