[cairo-commit] 6 commits - src/cairo-ps-surface.c test/clip-operator-ps-rgb24-ref.png test/.gitignore test/gradient-alpha-ps-argb32-ref.png test/gradient-alpha-ps-rgb24-ref.png test/gradient-constant-alpha.c test/gradient-constant-alpha-ps-ref.png test/gradient-constant-alpha-ps-rgb24-ref.png test/gradient-constant-alpha-ref.png test/gradient-constant-alpha-rgb24-ref.png test/Makefile.am

Chris Wilson ickle at kemper.freedesktop.org
Sun Sep 7 07:04:16 PDT 2008


 src/cairo-ps-surface.c                        |   76 +++++++++++++++++++-------
 test/.gitignore                               |    1 
 test/Makefile.am                              |    8 ++
 test/clip-operator-ps-rgb24-ref.png           |binary
 test/gradient-alpha-ps-argb32-ref.png         |binary
 test/gradient-alpha-ps-rgb24-ref.png          |binary
 test/gradient-constant-alpha-ps-ref.png       |binary
 test/gradient-constant-alpha-ps-rgb24-ref.png |binary
 test/gradient-constant-alpha-ref.png          |binary
 test/gradient-constant-alpha-rgb24-ref.png    |binary
 test/gradient-constant-alpha.c                |   69 +++++++++++++++++++++++
 11 files changed, 134 insertions(+), 20 deletions(-)

New commits:
commit 7960fc94dccdf4f4e7362e1cd69eeb3c132939e5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 7 12:56:14 2008 +0100

    [ps] Set used level to 3 only if we use native gradients.
    
    Set the used level after performing the checks that the native Type2/3
    gradients support the pattern.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 155d9b3..9afb694 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1456,7 +1456,6 @@ _gradient_pattern_supported (cairo_ps_surface_t    *surface,
 	    return FALSE;
     }
 
-    surface->ps_level_used = CAIRO_PS_LEVEL_3;
     extend = cairo_pattern_get_extend (pattern);
 
     /* Radial gradients are currently only supported when one circle
@@ -1483,6 +1482,8 @@ _gradient_pattern_supported (cairo_ps_surface_t    *surface,
         }
     }
 
+    surface->ps_level_used = CAIRO_PS_LEVEL_3;
+
     return TRUE;
 }
 
commit 7439c45039a2c4342f626864324a5b4989a3153d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 7 14:57:16 2008 +0100

    [ps] Only use fallback images if the gradient has non-constant alpha.
    
    If the gradient has constant alpha, then we can express it as a flattened
    linear gradient. Otherwise, should the opacity vary across the gradient we
    need to fallback.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 2944717..155d9b3 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1437,11 +1437,25 @@ static cairo_bool_t
 _gradient_pattern_supported (cairo_ps_surface_t    *surface,
 			     cairo_pattern_t *pattern)
 {
+    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
+    uint16_t alpha;
     cairo_extend_t extend;
+    int i;
 
     if (surface->ps_level == CAIRO_PS_LEVEL_2)
 	return FALSE;
 
+    if (gradient->n_stops == 0)
+	return TRUE;
+
+    /* Alpha gradients are only supported (by flattening the alpha)
+     * if there is no variation in the alpha across the gradient. */
+    alpha = gradient->stops[0].color.alpha_short;
+    for (i = 0; i < gradient->n_stops; i++) {
+	if (gradient->stops[i].color.alpha_short != alpha)
+	    return FALSE;
+    }
+
     surface->ps_level_used = CAIRO_PS_LEVEL_3;
     extend = cairo_pattern_get_extend (pattern);
 
diff --git a/test/.gitignore b/test/.gitignore
index 14cc7df..456b969 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -91,6 +91,7 @@ get-xrender-format
 glitz-surface-source
 glyph-cache-pressure
 gradient-alpha
+gradient-constant-alpha
 gradient-zero-stops
 group-paint
 imagediff
diff --git a/test/Makefile.am b/test/Makefile.am
index 0ded81d..e00cbd6 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -455,7 +455,6 @@ REFERENCE_IMAGES = \
 	gradient-alpha-rgb24-ref.png	\
 	gradient-constant-alpha-pdf-argb32-ref.png	\
 	gradient-constant-alpha-pdf-rgb24-ref.png	\
-	gradient-constant-alpha-ps-argb32-ref.png	\
 	gradient-constant-alpha-ps-rgb24-ref.png	\
 	gradient-constant-alpha-ref.png	\
 	gradient-constant-alpha-rgb24-ref.png	\
diff --git a/test/clip-operator-ps-argb32-ref.png b/test/clip-operator-ps-argb32-ref.png
deleted file mode 100644
index 35014bd..0000000
Binary files a/test/clip-operator-ps-argb32-ref.png and /dev/null differ
diff --git a/test/clip-operator-ps-rgb24-ref.png b/test/clip-operator-ps-rgb24-ref.png
index 1736e4b..6ed9fc4 100644
Binary files a/test/clip-operator-ps-rgb24-ref.png and b/test/clip-operator-ps-rgb24-ref.png differ
diff --git a/test/gradient-alpha-ps-argb32-ref.png b/test/gradient-alpha-ps-argb32-ref.png
index 323238b..37eafba 100644
Binary files a/test/gradient-alpha-ps-argb32-ref.png and b/test/gradient-alpha-ps-argb32-ref.png differ
diff --git a/test/gradient-alpha-ps-rgb24-ref.png b/test/gradient-alpha-ps-rgb24-ref.png
index 430052c..2432c29 100644
Binary files a/test/gradient-alpha-ps-rgb24-ref.png and b/test/gradient-alpha-ps-rgb24-ref.png differ
diff --git a/test/gradient-constant-alpha-ps-ref.png b/test/gradient-constant-alpha-ps-ref.png
new file mode 100644
index 0000000..7089f4f
Binary files /dev/null and b/test/gradient-constant-alpha-ps-ref.png differ
diff --git a/test/gradient-constant-alpha-ps-rgb24-ref.png b/test/gradient-constant-alpha-ps-rgb24-ref.png
new file mode 100644
index 0000000..5962925
Binary files /dev/null and b/test/gradient-constant-alpha-ps-rgb24-ref.png differ
diff --git a/test/gradient-constant-alpha-ref.png b/test/gradient-constant-alpha-ref.png
new file mode 100644
index 0000000..9a24e8c
Binary files /dev/null and b/test/gradient-constant-alpha-ref.png differ
diff --git a/test/gradient-constant-alpha-rgb24-ref.png b/test/gradient-constant-alpha-rgb24-ref.png
new file mode 100644
index 0000000..f190009
Binary files /dev/null and b/test/gradient-constant-alpha-rgb24-ref.png differ
diff --git a/test/operator-clear-ps-argb32-ref.png b/test/operator-clear-ps-argb32-ref.png
deleted file mode 100644
index d9a7769..0000000
Binary files a/test/operator-clear-ps-argb32-ref.png and /dev/null differ
diff --git a/test/operator-source-ps-argb32-ref.png b/test/operator-source-ps-argb32-ref.png
deleted file mode 100644
index d5cb053..0000000
Binary files a/test/operator-source-ps-argb32-ref.png and /dev/null differ
diff --git a/test/operator-source-ps-rgb24-ref.png b/test/operator-source-ps-rgb24-ref.png
deleted file mode 100644
index eb73a9e..0000000
Binary files a/test/operator-source-ps-rgb24-ref.png and /dev/null differ
commit 94fd60d5ec2ef7705a8dc53f74817c1e067ba8e6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 7 12:12:59 2008 +0100

    [test] Add gradient-constant-alpha.
    
    PostScript can handle alpha gradients, iff they have a constant alpha. So
    exercise that path.

diff --git a/test/Makefile.am b/test/Makefile.am
index 562f4d4..0ded81d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -66,6 +66,7 @@ get-clip$(EXEEXT)					\
 get-group-target$(EXEEXT)				\
 get-path-extents$(EXEEXT)				\
 gradient-alpha$(EXEEXT)					\
+gradient-constant-alpha$(EXEEXT)			\
 gradient-zero-stops$(EXEEXT)				\
 group-paint$(EXEEXT)					\
 image-surface-source$(EXEEXT)				\
@@ -452,6 +453,12 @@ REFERENCE_IMAGES = \
 	gradient-alpha-ps-rgb24-ref.png	\
 	gradient-alpha-ref.png	\
 	gradient-alpha-rgb24-ref.png	\
+	gradient-constant-alpha-pdf-argb32-ref.png	\
+	gradient-constant-alpha-pdf-rgb24-ref.png	\
+	gradient-constant-alpha-ps-argb32-ref.png	\
+	gradient-constant-alpha-ps-rgb24-ref.png	\
+	gradient-constant-alpha-ref.png	\
+	gradient-constant-alpha-rgb24-ref.png	\
 	gradient-zero-stops-ref.png	\
 	gradient-zero-stops-rgb24-ref.png	\
 	group-paint-ref.png	\
diff --git a/test/gradient-constant-alpha.c b/test/gradient-constant-alpha.c
new file mode 100644
index 0000000..0607621
--- /dev/null
+++ b/test/gradient-constant-alpha.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ *         Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+static cairo_test_draw_function_t draw;
+
+static const cairo_test_t test = {
+    "gradient-constant-alpha",
+    "Tests drawing of a gradient with constant alpha values in the color stops\n",
+    10, 10,
+    draw
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_pattern_t *gradient;
+
+    gradient = cairo_pattern_create_linear (0, 0,
+					    0, height);
+    cairo_pattern_add_color_stop_rgba (gradient, 0.0,
+				       1.0, 0.0, 0.0,
+				       0.5);
+    cairo_pattern_add_color_stop_rgba (gradient, 0.0,
+				       0.0, 1.0, 0.0,
+				       0.5);
+    cairo_pattern_add_color_stop_rgba (gradient, 1.0,
+				       0.0, 0.0, 1.0,
+				       0.5);
+
+    cairo_set_source (cr, gradient);
+
+    cairo_paint (cr);
+
+    cairo_pattern_destroy (gradient);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}
commit a33f2f6962a5cb09eca60825fa1a022c3e00991c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 7 10:26:32 2008 +0100

    Revert "[ps] A flattened gradient is not linear."
    
    This reverts commit 85ed37da33522efa101eb508a4091bcfa24ae944.
    
    Adrian Johnson pointed out that iff the gradient has constant alpha then
    it can be flattened. Reverting this commit in order to restore the
    capability to handle gradient flattening.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 6a9c900..2944717 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1442,10 +1442,6 @@ _gradient_pattern_supported (cairo_ps_surface_t    *surface,
     if (surface->ps_level == CAIRO_PS_LEVEL_2)
 	return FALSE;
 
-    /* alpha-blended gradients cannot be expressed as a linear function */
-    if (! _cairo_pattern_is_opaque (pattern))
-	return FALSE;
-
     surface->ps_level_used = CAIRO_PS_LEVEL_3;
     extend = cairo_pattern_get_extend (pattern);
 
@@ -2432,7 +2428,7 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t      *surface,
 
 typedef struct _cairo_ps_color_stop {
     double offset;
-    double color[3];
+    double color[4];
 } cairo_ps_color_stop_t;
 
 static void
@@ -2457,7 +2453,7 @@ _cairo_ps_surface_emit_linear_colorgradient (cairo_ps_surface_t     *surface,
 
 static void
 _cairo_ps_surface_emit_stitched_colorgradient (cairo_ps_surface_t    *surface,
-					       unsigned int	      n_stops,
+					       unsigned int 	      n_stops,
 					       cairo_ps_color_stop_t  stops[])
 {
     unsigned int i;
@@ -2487,14 +2483,11 @@ calc_gradient_color (cairo_ps_color_stop_t *new_stop,
 		     cairo_ps_color_stop_t *stop1,
 		     cairo_ps_color_stop_t *stop2)
 {
-    double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
-    double one_minus_offset = 1. - offset;
     int i;
+    double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
 
-    for (i = 0; i < 3; i++) {
-	new_stop->color[i] = stop1->color[i] * one_minus_offset +
-	                     stop2->color[i] * offset;
-    }
+    for (i = 0; i < 4; i++)
+	new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
 }
 
 #define COLOR_STOP_EPSILON 1e-6
@@ -2506,8 +2499,7 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t       *surface,
     cairo_ps_color_stop_t *allstops, *stops;
     unsigned int i, n_stops;
 
-    allstops = _cairo_malloc_ab (pattern->n_stops + 2,
-				 sizeof (cairo_ps_color_stop_t));
+    allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_ps_color_stop_t));
     if (allstops == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
@@ -2520,6 +2512,7 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t       *surface,
 	stops[i].color[0] = stop->color.red;
 	stops[i].color[1] = stop->color.green;
 	stops[i].color[2] = stop->color.blue;
+	stops[i].color[3] = stop->color.alpha;
 	stops[i].offset = pattern->stops[i].offset;
     }
 
@@ -2529,8 +2522,7 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t       *surface,
 	    if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
 		memcpy (allstops, stops, sizeof (cairo_ps_color_stop_t));
 	    else
-		calc_gradient_color (&allstops[0], &stops[0],
-				     &stops[n_stops-1]);
+		calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
 	    stops = allstops;
 	    n_stops++;
 	}
@@ -2542,20 +2534,34 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t       *surface,
 			&stops[n_stops - 1],
 			sizeof (cairo_ps_color_stop_t));
 	    } else {
-		calc_gradient_color (&stops[n_stops], &stops[0],
-				     &stops[n_stops-1]);
+		calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
 	    }
 	    n_stops++;
 	}
 	stops[n_stops-1].offset = 1.0;
     }
 
+    for (i = 0; i < n_stops; i++) {
+	double red, green, blue;
+	cairo_color_t color;
+
+	_cairo_color_init_rgba (&color,
+				stops[i].color[0],
+				stops[i].color[1],
+				stops[i].color[2],
+				stops[i].color[3]);
+	_cairo_ps_surface_flatten_transparency (surface, &color,
+						&red, &green, &blue);
+	stops[i].color[0] = red;
+	stops[i].color[1] = green;
+	stops[i].color[2] = blue;
+    }
+
     _cairo_output_stream_printf (surface->stream,
 				 "/CairoFunction\n");
     if (n_stops == 2) {
 	/* no need for stitched function */
-	_cairo_ps_surface_emit_linear_colorgradient (surface,
-						     &stops[0], &stops[1]);
+	_cairo_ps_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]);
     } else {
 	/* multiple stops: stitch. XXX possible optimization: regulary spaced
 	 * stops do not require stitching. XXX */
diff --git a/test/Makefile.am b/test/Makefile.am
index 9424d2e..562f4d4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -448,6 +448,8 @@ REFERENCE_IMAGES = \
 	glyph-cache-pressure-quartz-ref.png	\
 	gradient-alpha-pdf-argb32-ref.png	\
 	gradient-alpha-pdf-rgb24-ref.png	\
+	gradient-alpha-ps-argb32-ref.png	\
+	gradient-alpha-ps-rgb24-ref.png	\
 	gradient-alpha-ref.png	\
 	gradient-alpha-rgb24-ref.png	\
 	gradient-zero-stops-ref.png	\
diff --git a/test/clip-operator-ps-argb32-ref.png b/test/clip-operator-ps-argb32-ref.png
new file mode 100644
index 0000000..35014bd
Binary files /dev/null and b/test/clip-operator-ps-argb32-ref.png differ
diff --git a/test/clip-operator-ps-rgb24-ref.png b/test/clip-operator-ps-rgb24-ref.png
new file mode 100644
index 0000000..1736e4b
Binary files /dev/null and b/test/clip-operator-ps-rgb24-ref.png differ
diff --git a/test/gradient-alpha-ps-argb32-ref.png b/test/gradient-alpha-ps-argb32-ref.png
new file mode 100644
index 0000000..323238b
Binary files /dev/null and b/test/gradient-alpha-ps-argb32-ref.png differ
diff --git a/test/gradient-alpha-ps-rgb24-ref.png b/test/gradient-alpha-ps-rgb24-ref.png
new file mode 100644
index 0000000..430052c
Binary files /dev/null and b/test/gradient-alpha-ps-rgb24-ref.png differ
diff --git a/test/operator-clear-ps-argb32-ref.png b/test/operator-clear-ps-argb32-ref.png
new file mode 100644
index 0000000..d9a7769
Binary files /dev/null and b/test/operator-clear-ps-argb32-ref.png differ
diff --git a/test/operator-source-ps-argb32-ref.png b/test/operator-source-ps-argb32-ref.png
new file mode 100644
index 0000000..d5cb053
Binary files /dev/null and b/test/operator-source-ps-argb32-ref.png differ
diff --git a/test/operator-source-ps-rgb24-ref.png b/test/operator-source-ps-rgb24-ref.png
new file mode 100644
index 0000000..eb73a9e
Binary files /dev/null and b/test/operator-source-ps-rgb24-ref.png differ
commit 1a6f2b08a16ffe2af28ddb3fcf0e7295226ad73d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 7 10:24:46 2008 +0100

    [ps] Support B PDF operator.
    
    Add the procedure definition for fill-stroke path operators, B and B*.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 9006dc0..6a9c900 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -186,6 +186,8 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
 				 "/S { stroke } bind def\n"
 				 "/f { fill } bind def\n"
 				 "/f* { eofill } bind def\n"
+				 "/B { fill stroke } bind def\n"
+				 "/B* { eofill stroke } bind def\n"
 				 "/n { newpath } bind def\n"
 				 "/W { clip } bind def\n"
 				 "/W* { eoclip } bind def\n"
commit ab3bb369d5d531446f4a5482672204dc479f10b2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 7 10:23:28 2008 +0100

    [ps] Add comments about design of output.
    
    Add some snippets from Adrian Johnson about how and why the PS output is
    factored in terms of PDF operators.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index c1ec6ad..9006dc0 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -40,6 +40,19 @@
  *	Adrian Johnson <ajohnson at redneon.com>
  */
 
+
+/*
+ * Design of the PS output:
+ *
+ * The PS output is harmonised with the PDF operations using PS procedures
+ * to emulate the PDF operators.
+ *
+ * This has a number of advantages:
+ *   1. A large chunk of code is shared between the PDF and PS backends.
+ *      See cairo-pdf-operators.
+ *   2. Using gs to do PS -> PDF and PDF -> PS will always work well.
+ */
+
 #define _BSD_SOURCE /* for ctime_r(), snprintf(), strdup() */
 #include "cairoint.h"
 #include "cairo-ps.h"


More information about the cairo-commit mailing list