[cairo-commit] 4 commits - boilerplate/.gitignore perf/cairo-perf.c perf/cairo-perf.h perf/cairo-perf-win32.c perf/.gitignore perf/Makefile.win32 perf/paint.c pixman/src src/cairo.c src/cairo.h src/cairo-pattern.c src/.gitignore test/get-and-set.c test/.gitignore test/Makefile.am test/Makefile.win32 test/pattern-getters.c test/pattern-getters-ref.png

Vladimir Vukicevic vladimir at kemper.freedesktop.org
Tue Sep 19 12:20:06 PDT 2006


 boilerplate/.gitignore       |    7 +
 perf/.gitignore              |    7 +
 perf/Makefile.win32          |   16 ++
 perf/cairo-perf-win32.c      |   14 ++
 perf/cairo-perf.c            |   45 +++++---
 perf/cairo-perf.h            |   13 +-
 perf/paint.c                 |  118 ++++++++++++++++++++-
 pixman/src/.gitignore        |    3 
 src/.gitignore               |    7 +
 src/cairo-pattern.c          |  238 ++++++++++++++++++++++++++++++++++++++++++-
 src/cairo.c                  |   63 +++++++++++
 src/cairo.h                  |   40 ++++++-
 test/.gitignore              |    6 +
 test/Makefile.am             |    1 
 test/Makefile.win32          |    1 
 test/get-and-set.c           |   39 +++++--
 test/pattern-getters-ref.png |binary
 test/pattern-getters.c       |  175 +++++++++++++++++++++++++++++++
 18 files changed, 762 insertions(+), 31 deletions(-)

New commits:
diff-tree 303b52919519854b9b5bbc38a9ac115e422dddad (from a56b962428c487d1c341f86e6719bad86374386c)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Sep 19 12:17:34 2006 -0700

    dash and pattern getter functions
    
    Adds API functions for inspecting the current dash state, as well as
    the contents of pattern objects:
    
      cairo_get_dash
      cairo_get_dash_count
      cairo_pattern_get_rgba
      cairo_pattern_get_surface
      cairo_pattern_get_color_stop_rgba
      cairo_pattern_get_color_stop_count
      cairo_pattern_get_linear_points
      cairo_pattern_get_radial_circles

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index a859e52..a2a08e0 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2004 David Reveman
@@ -460,10 +461,10 @@ cairo_pattern_create_linear (double x0, 
  * cairo_pattern_create_radial:
  * @cx0: x coordinate for the center of the start circle
  * @cy0: y coordinate for the center of the start circle
- * @radius0: radius of the start cirle
+ * @radius0: radius of the start circle
  * @cx1: x coordinate for the center of the end circle
  * @cy1: y coordinate for the center of the end circle
- * @radius1: radius of the end cirle
+ * @radius1: radius of the end circle
  *
  * Creates a new radial gradient cairo_pattern_t between the two
  * circles defined by (x0, y0, c0) and (x1, y1, c0).  Before using the
@@ -1475,3 +1476,236 @@ _cairo_pattern_get_extents (cairo_patter
 
     return CAIRO_STATUS_SUCCESS;
 }
+
+/**
+ * cairo_pattern_get_rgba
+ * @pattern: a #cairo_pattern_t
+ * @red: return value for red component of color, or %NULL
+ * @green: return value for green component of color, or %NULL
+ * @blue: return value for blue component of color, or %NULL
+ * @alpha: return value for alpha component of color, or %NULL
+ *
+ * Gets the solid color for a solid color pattern.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS, or
+ * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
+ * color pattern.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_pattern_get_rgba (cairo_pattern_t *pattern,
+			double *red, double *green,
+			double *blue, double *alpha)
+{
+    cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
+    double r0, g0, b0, a0;
+
+    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
+	return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+
+    _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
+
+    if (red)
+	*red = r0;
+    if (green)
+	*green = g0;
+    if (blue)
+	*blue = b0;
+    if (alpha)
+	*alpha = a0;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_pattern_get_surface
+ * @pattern: a #cairo_pattern_t
+ * @surface: return value for surface of pattern, or %NULL
+ * 
+ * Gets the surface of a surface pattern.  The reference returned in
+ * @surface is owned by the pattern; the caller should call
+ * cairo_surface_reference() if the surface is to be retained.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS, or
+ * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
+ * pattern.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_pattern_get_surface (cairo_pattern_t *pattern,
+			   cairo_surface_t **surface)
+{
+    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
+
+    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
+	return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+
+    if (surface)
+	*surface = spat->surface;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_pattern_get_color_stop_rgba
+ * @pattern: a #cairo_pattern_t
+ * @index: index of the stop to return data for
+ * @red: return value for red component of color, or %NULL
+ * @green: return value for green component of color, or %NULL
+ * @blue: return value for blue component of color, or %NULL
+ * @alpha: return value for alpha component of color, or %NULL
+ *
+ * Gets the color and offset information at the given @index for a
+ * gradient pattern.  Values of @index are 0 to 1 less than the number
+ * returned by cairo_pattern_get_color_stop_count().
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
+ * if @index is not valid for the given pattern.  If the pattern is
+ * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
+ * returned.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
+				   int index, double *offset,
+				   double *red, double *green,
+				   double *blue, double *alpha)
+{
+    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
+
+    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
+	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
+	return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+
+    if (index < 0 || index >= gradient->n_stops)
+	return CAIRO_STATUS_INVALID_INDEX;
+
+    if (offset)
+	*offset = _cairo_fixed_to_double(gradient->stops[index].x);
+    if (red)
+	*red = gradient->stops[index].color.red / (double) 0xffff;
+    if (green)
+	*green = gradient->stops[index].color.green / (double) 0xffff;
+    if (blue)
+	*blue = gradient->stops[index].color.blue / (double) 0xffff;
+    if (alpha)
+	*alpha = gradient->stops[index].color.alpha / (double) 0xffff;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_pattern_get_color_stop_count
+ * @pattern: a #cairo_pattern_t
+ * @count: return value for the number of color stops, or %NULL
+ *
+ * Gets the number of color stops specified in the given gradient
+ * pattern.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS, or
+ * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
+ * pattern.
+ *
+ * Since: 1.4
+ */
+cairo_status_t
+cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
+				    int *count)
+{
+    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
+
+    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
+	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
+	return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+
+    if (count)
+	*count = gradient->n_stops;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_pattern_get_linear_points
+ * @pattern: a #cairo_pattern_t
+ * @x0: return value for the x coordinate of the first point, or %NULL
+ * @y0: return value for the y coordinate of the first point, or %NULL
+ * @x1: return value for the x coordinate of the second point, or %NULL
+ * @y1: return value for the y coordinate of the second point, or %NULL
+ *
+ * Gets the gradient endpoints for a linear gradient.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS, or
+ * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
+ * gradient pattern.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
+				 double *x0, double *y0,
+				 double *x1, double *y1)
+{
+    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
+
+    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
+	return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+
+    if (x0)
+	*x0 = _cairo_fixed_to_double (linear->gradient.p1.x);
+    if (y0)
+	*y0 = _cairo_fixed_to_double (linear->gradient.p1.y);
+    if (x1)
+	*x1 = _cairo_fixed_to_double (linear->gradient.p2.x);
+    if (y1)
+	*y1 = _cairo_fixed_to_double (linear->gradient.p2.y);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_pattern_get_radial_circles
+ * @pattern: a #cairo_pattern_t
+ * @x0: return value for the x coordinate of the center of the first (inner) circle, or %NULL
+ * @y0: return value for the y coordinate of the center of the first (inner) circle, or %NULL
+ * @r0: return value for the radius of the first (inner) circle, or %NULL
+ * @x1: return value for the x coordinate of the center of the second (outer) circle, or %NULL
+ * @y1: return value for the y coordinate of the center of the second (outer) circle, or %NULL
+ * @r1: return value for the radius of the second (outer) circle, or %NULL
+ *
+ * Gets the gradient endpoint circles for a radial gradient, each
+ * specified as a center coordinate and a radius.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS, or
+ * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
+ * gradient pattern.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
+				  double *x0, double *y0, double *r0,
+				  double *x1, double *y1, double *r1)
+{
+    cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
+
+    if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
+	return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+
+    if (x0)
+	*x0 = _cairo_fixed_to_double (radial->gradient.inner.x);
+    if (y0)
+	*y0 = _cairo_fixed_to_double (radial->gradient.inner.y);
+    if (r0)
+	*r0 = _cairo_fixed_to_double (radial->gradient.inner.radius);
+    if (x1)
+	*x1 = _cairo_fixed_to_double (radial->gradient.outer.x);
+    if (y1)
+	*y1 = _cairo_fixed_to_double (radial->gradient.outer.y);
+    if (r1)
+	*r1 = _cairo_fixed_to_double (radial->gradient.outer.radius);
+
+    return CAIRO_STATUS_SUCCESS;
+}
diff --git a/src/cairo.c b/src/cairo.c
index 26fe1c1..0eb75cc 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2002 University of Southern California
@@ -62,7 +63,7 @@ static const cairo_t cairo_nil = {
  * a bit of a pain, but it should be easy to always catch as long as
  * one adds a new test case to test a trigger of the new status value.
  */
-#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_DSC_COMMENT
+#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_INDEX
 
 /**
  * _cairo_error:
@@ -947,6 +948,64 @@ cairo_set_dash (cairo_t	     *cr,
 	_cairo_set_error (cr, cr->status);
 }
 
+/**
+ * cairo_get_dash_count:
+ * @cr: a #cairo_t
+ * @count: return value for the number of dash values, or %NULL
+ *
+ * Gets the length of the dash array in @cr.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS, or error status set on
+ * @cr.
+ *
+ * Since: 1.4
+ */
+cairo_status_t
+cairo_get_dash_count (cairo_t *cr,
+		      int     *count)
+{
+    if (cr->status)
+	return cr->status;
+
+    if (count)
+	*count = cr->gstate->stroke_style.num_dashes;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_get_dash:
+ * @cr: a #cairo_t
+ * @dashes: return value for the dash array, or %NULL
+ * @offset: return value for the current dash offset, or %NULL
+ *
+ * Gets the current dash array.  If not %NULL, @dashes should be big
+ * enough to hold at least the number of values returned by
+ * cairo_get_dash_count().
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS, or error status set on
+ * @cr.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_get_dash (cairo_t *cr,
+		double  *dashes,
+		double  *offset)
+{
+    if (cr->status)
+	return cr->status;
+
+    memcpy (dashes,
+	    cr->gstate->stroke_style.dash,
+	    sizeof(double) * cr->gstate->stroke_style.num_dashes);
+
+    if (offset)
+	*offset = cr->gstate->stroke_style.dash_offset;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 void
 cairo_set_miter_limit (cairo_t *cr, double limit)
 {
@@ -3010,6 +3069,8 @@ cairo_status_to_string (cairo_status_t s
 	return "invalid value for a dash setting";
     case CAIRO_STATUS_INVALID_DSC_COMMENT:
 	return "invalid value for a DSC comment";
+    case CAIRO_STATUS_INVALID_INDEX:
+	return "invalid index passed to getter";
     }
 
     return "<unknown error status>";
diff --git a/src/cairo.h b/src/cairo.h
index 661a24e..a0c2f54 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -169,6 +169,7 @@ typedef struct _cairo_user_data_key {
  * @CAIRO_STATUS_FILE_NOT_FOUND: file not found
  * @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting
  * @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2)
+ * @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter
  *
  * #cairo_status_t is used to indicate errors that can occur when
  * using Cairo. In some cases it is returned directly by functions.
@@ -199,7 +200,8 @@ typedef enum _cairo_status {
     CAIRO_STATUS_INVALID_VISUAL,
     CAIRO_STATUS_FILE_NOT_FOUND,
     CAIRO_STATUS_INVALID_DASH,
-    CAIRO_STATUS_INVALID_DSC_COMMENT
+    CAIRO_STATUS_INVALID_DSC_COMMENT,
+    CAIRO_STATUS_INVALID_INDEX
 } cairo_status_t;
 
 /**
@@ -1073,7 +1075,11 @@ cairo_get_line_join (cairo_t *cr);
 cairo_public double
 cairo_get_miter_limit (cairo_t *cr);
 
-/* XXX: How to do cairo_get_dash??? Do we want to switch to a cairo_dash object? */
+cairo_public cairo_status_t
+cairo_get_dash_count (cairo_t *cr, int *count);
+
+cairo_public cairo_status_t
+cairo_get_dash (cairo_t *cr, double *dashes, double *offset);
 
 cairo_public void
 cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix);
@@ -1552,6 +1558,36 @@ cairo_pattern_set_filter (cairo_pattern_
 cairo_public cairo_filter_t
 cairo_pattern_get_filter (cairo_pattern_t *pattern);
 
+cairo_public cairo_status_t
+cairo_pattern_get_rgba (cairo_pattern_t *pattern,
+			double *red, double *green,
+			double *blue, double *alpha);
+
+cairo_public cairo_status_t
+cairo_pattern_get_surface (cairo_pattern_t *pattern,
+			   cairo_surface_t **surface);
+
+
+cairo_public cairo_status_t
+cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
+				   int index, double *offset,
+				   double *red, double *green,
+				   double *blue, double *alpha);
+
+cairo_public cairo_status_t
+cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
+				    int *count);
+
+cairo_public cairo_status_t
+cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
+				 double *x0, double *y0,
+				 double *x1, double *y1);
+
+cairo_public cairo_status_t
+cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
+				  double *x0, double *y0, double *r0,
+				  double *x1, double *y1, double *r1);
+
 /* Matrix functions */
 
 cairo_public void
diff --git a/test/Makefile.am b/test/Makefile.am
index 111f1c1..d1706ac 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -59,6 +59,7 @@ paint-source-alpha		\
 paint-with-alpha		\
 path-data			\
 pattern-get-type		\
+pattern-getters			\
 pixman-rotate			\
 rectangle-rounding-error	\
 scale-source-surface-paint	\
diff --git a/test/Makefile.win32 b/test/Makefile.win32
index 5eefded..e364de8 100644
--- a/test/Makefile.win32
+++ b/test/Makefile.win32
@@ -57,6 +57,7 @@ paint-source-alpha		\
 paint-with-alpha		\
 path-data			\
 pattern-get-type		\
+pattern-getters			\
 pixman-rotate			\
 rectangle-rounding-error	\
 scale-source-surface-paint	\
diff --git a/test/get-and-set.c b/test/get-and-set.c
index ae17cc8..ec35834 100644
--- a/test/get-and-set.c
+++ b/test/get-and-set.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /*
  * Copyright © 2005 Red Hat, Inc.
  *
@@ -43,6 +44,8 @@ typedef struct {
     cairo_line_join_t line_join;
     double miter_limit;
     cairo_matrix_t matrix;
+    double dash[5];
+    double dash_offset;
 } settings_t;
 
 /* Two sets of settings, no defaults */
@@ -55,7 +58,9 @@ settings_t settings[] = {
 	CAIRO_LINE_CAP_SQUARE,
 	CAIRO_LINE_JOIN_ROUND,
 	3.14,
-	{2.0, 0.0, 0.0, 2.0, 5.0, 5.0}
+	{2.0, 0.0, 0.0, 2.0, 5.0, 5.0},
+	{0.1, 0.2, 0.3, 0.4, 0.5},
+	2.0
     },
     {
 	CAIRO_OPERATOR_ATOP,
@@ -65,7 +70,9 @@ settings_t settings[] = {
 	CAIRO_LINE_CAP_ROUND,
 	CAIRO_LINE_JOIN_BEVEL,
 	1000.0,
-	{-3.0, 1.0, 1.0, -3.0, -4, -4}
+	{-3.0, 1.0, 1.0, -3.0, -4, -4},
+	{1.0, 2.0, 3.0, 4.0, 5.0},
+	3.0
     }
 };
 
@@ -80,9 +87,10 @@ settings_set (cairo_t *cr, settings_t *s
     cairo_set_line_join (cr, settings->line_join);
     cairo_set_miter_limit (cr, settings->miter_limit);
     cairo_set_matrix (cr, &settings->matrix);
+    cairo_set_dash (cr, settings->dash, 5, settings->dash_offset);
 }
 
-static void
+static int
 settings_get (cairo_t *cr, settings_t *settings)
 {
     settings->op = cairo_get_operator (cr);
@@ -93,6 +101,21 @@ settings_get (cairo_t *cr, settings_t *s
     settings->line_join = cairo_get_line_join (cr);
     settings->miter_limit = cairo_get_miter_limit (cr);
     cairo_get_matrix (cr, &settings->matrix);
+
+    {
+	cairo_status_t status;
+	int count;
+
+	status = cairo_get_dash_count (cr, &count);
+	if (status || count != 5)
+	    return -1;
+
+	status = cairo_get_dash (cr, settings->dash, &settings->dash_offset);
+	if (status)
+	    return -1;
+    }
+
+    return 0;
 }
 
 static int
@@ -110,7 +133,9 @@ settings_equal (settings_t *a, settings_
 	    a->matrix.x0 == b->matrix.x0 &&
 	    a->matrix.yx == b->matrix.yx &&
 	    a->matrix.yy == b->matrix.yy &&
-	    a->matrix.y0 == b->matrix.y0);
+	    a->matrix.y0 == b->matrix.y0 &&
+	    memcmp(a->dash, b->dash, sizeof(a->dash)) == 0 &&
+	    a->dash_offset == b->dash_offset);
 }
 
 static cairo_test_status_t
@@ -123,14 +148,16 @@ draw (cairo_t *cr, int width, int height
     cairo_save (cr);
     {
 	settings_set (cr, &settings[1]);
-	settings_get (cr, &check);
+	if (settings_get (cr, &check))
+	    return CAIRO_TEST_FAILURE;
 
 	if (!settings_equal (&settings[1], &check))
 	    return CAIRO_TEST_FAILURE;
     }
     cairo_restore (cr);
 
-    settings_get (cr, &check);
+    if (settings_get (cr, &check))
+	return CAIRO_TEST_FAILURE;
 
     if (!settings_equal (&settings[0], &check))
 	return CAIRO_TEST_FAILURE;
diff --git a/test/pattern-getters-ref.png b/test/pattern-getters-ref.png
new file mode 100644
index 0000000..80304b0
Binary files /dev/null and b/test/pattern-getters-ref.png differ
diff --git a/test/pattern-getters.c b/test/pattern-getters.c
new file mode 100644
index 0000000..db3d327
--- /dev/null
+++ b/test/pattern-getters.c
@@ -0,0 +1,175 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/*
+ * Copyright © 2005 Mozilla Corporation, Inc.
+ *
+ * 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
+ * Mozilla Corporation not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Mozilla Corporation makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL MOZILLA CORPORATION 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: Vladimir Vukicevic <vladimir at pobox.com>
+ */
+
+#include <stdlib.h>
+#include "cairo-test.h"
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+    "pattern-getters",
+    "Tests calls to pattern getter functions",
+    1, 1,
+    draw
+};
+
+#define CHECK_SUCCESS do { if (status) return CAIRO_TEST_FAILURE; } while (0)
+
+#define DOUBLE_EQUALS(a,b)  (fabs((a)-(b)) < 0.00001)
+
+int
+double_buf_equal (double *a, double *b, int nc)
+{
+    int i;
+    for (i = 0; i < nc; i++) {
+	if (!DOUBLE_EQUALS(a[i],b[i]))
+	    return 0;
+    }
+    return 1;
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_status_t status;
+    cairo_pattern_t *pat;
+
+    /* Test pattern_get_rgba */
+    {
+	double r, g, b, a;
+	pat = cairo_pattern_create_rgba (0.2, 0.3, 0.4, 0.5);
+
+	status = cairo_pattern_get_rgba (pat, &r, &g, &b, &a);
+	CHECK_SUCCESS;
+
+	if (!DOUBLE_EQUALS(r,0.2),
+	    !DOUBLE_EQUALS(g,0.3),
+	    !DOUBLE_EQUALS(b,0.4),
+	    !DOUBLE_EQUALS(a,0.5))
+	    return CAIRO_TEST_FAILURE;
+
+	cairo_pattern_destroy (pat);
+    }
+
+    /* Test pattern_get_surface */
+    {
+	cairo_surface_t *surf;
+
+	pat = cairo_pattern_create_for_surface (cairo_get_target (cr));
+
+	status = cairo_pattern_get_surface (pat, &surf);
+	CHECK_SUCCESS;
+
+	if (surf != cairo_get_target (cr))
+	    return CAIRO_TEST_FAILURE;
+
+	cairo_pattern_destroy (pat);
+    }
+
+    /* Test get_color_stops & linear_get_points */
+    {
+	int i;
+	double x0, y0, x1, y1;
+	double expected_values[15] = { 0.0, 0.2, 0.4, 0.2, 1.0,
+				       0.5, 0.4, 0.5, 0.2, 0.5,
+				       1.0, 0.2, 0.4, 0.5, 0.2 };
+	double new_buf[15];
+
+	pat = cairo_pattern_create_linear (1.0, 2.0, 3.0, 4.0);
+
+	for (i = 0; i < 3; i++) {
+	    cairo_pattern_add_color_stop_rgba (pat,
+					       expected_values[i*5+0],
+					       expected_values[i*5+1],
+					       expected_values[i*5+2],
+					       expected_values[i*5+3],
+					       expected_values[i*5+4]);
+	}
+
+	status = cairo_pattern_get_linear_points (pat, &x0, &y0, &x1, &y1);
+	CHECK_SUCCESS;
+
+	if (!DOUBLE_EQUALS(x0,1.0) ||
+	    !DOUBLE_EQUALS(y0,2.0) ||
+	    !DOUBLE_EQUALS(x1,3.0) ||
+	    !DOUBLE_EQUALS(y1,4.0))
+	    return CAIRO_TEST_FAILURE;
+
+	status = cairo_pattern_get_color_stop_count (pat, &i);
+	CHECK_SUCCESS;
+
+	if (i != 3)
+	    return CAIRO_TEST_FAILURE;
+
+	for (i = 0; i < 3; i++) {
+	    status = cairo_pattern_get_color_stop_rgba (pat, i,
+							&new_buf[i*5+0],
+							&new_buf[i*5+1],
+							&new_buf[i*5+2],
+							&new_buf[i*5+3],
+							&new_buf[i*5+4]);
+	    CHECK_SUCCESS;
+	}
+
+	status = cairo_pattern_get_color_stop_rgba (pat, 5, NULL, NULL, NULL, NULL, NULL);
+	if (status != CAIRO_STATUS_INVALID_INDEX)
+	    return CAIRO_TEST_FAILURE;
+
+	if (!double_buf_equal (new_buf, expected_values, sizeof(expected_values)/sizeof(double)) != 0)
+	    return CAIRO_TEST_FAILURE;
+
+	cairo_pattern_destroy (pat);
+    }
+
+    /* Test radial_get_circles */
+    {
+	double a, b, c, d, e, f;
+	pat = cairo_pattern_create_radial (1, 2, 3,
+					   4, 5, 6);
+
+	status = cairo_pattern_get_radial_circles (pat, &a, &b, &c, &d, &e, &f);
+	CHECK_SUCCESS;
+
+	if (!DOUBLE_EQUALS(a,1.0) ||
+	    !DOUBLE_EQUALS(b,2.0) ||
+	    !DOUBLE_EQUALS(c,3.0) ||
+	    !DOUBLE_EQUALS(d,4.0) ||
+	    !DOUBLE_EQUALS(e,5.0) ||
+	    !DOUBLE_EQUALS(f,6.0))
+	    return CAIRO_TEST_FAILURE;
+    }
+
+    cairo_set_source_rgb (cr, 0, 1, 0);
+    cairo_paint (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}
diff-tree a56b962428c487d1c341f86e6719bad86374386c (from 8a9b99e596a93049abeb8bbbe502f895df72f678)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Sep 19 12:10:12 2006 -0700

    Add win32 output files to gitignore

diff --git a/boilerplate/.gitignore b/boilerplate/.gitignore
index 66a3f3f..fb15c30 100644
--- a/boilerplate/.gitignore
+++ b/boilerplate/.gitignore
@@ -1,2 +1,9 @@
 *.lo
 *.la
+*.exe
+*.manifest
+*.obj
+*.ilk
+*.suo
+*.lib
+*.pdb
diff --git a/perf/.gitignore b/perf/.gitignore
index f182130..66b1d8f 100644
--- a/perf/.gitignore
+++ b/perf/.gitignore
@@ -1,2 +1,9 @@
 cairo-perf
 *.o
+*.exe
+*.manifest
+*.obj
+*.ilk
+*.suo
+*.lib
+*.pdb
diff --git a/pixman/src/.gitignore b/pixman/src/.gitignore
index 77798ce..1084758 100644
--- a/pixman/src/.gitignore
+++ b/pixman/src/.gitignore
@@ -6,5 +6,8 @@ Makefile.in
 *.lo
 .libs
 .deps
+*.obj
+*.lib
+*.pdb
 *.o
 *~
diff --git a/src/.gitignore b/src/.gitignore
index 82a14e2..03a976b 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -11,5 +11,12 @@ Makefile.in
 cairo-features.h
 cairo.def
 *.o
+*.obj
+*.pdb
+*.dll
+*.manifest
+*.ilk
+*.exp
+*.lib
 *~
 TAGS
diff --git a/test/.gitignore b/test/.gitignore
index d434149..83cf3c8 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -128,9 +128,15 @@ valgrind-log
 *-out.ps
 *-out.svg
 *-diff.png
+*.manifest
 *.gcno
+*.exe
+*.obj
+*.ilk
+*.pdb
 *.la
 *.lo
 *.log
+*.suo
 *.o
 *~
diff-tree 8a9b99e596a93049abeb8bbbe502f895df72f678 (from e42905b01bd5bab11008b7d6a78bc263ae2f9f5d)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Thu Sep 14 12:59:31 2006 -0700

    [perf] Change perf output format, report times in ms, add a few paint tests
    
    This changes the perf test output format to be a little more human friendly,
    reporting times in ms instead of seconds.  It also adds a test number
    that could be used in the future for specifying an explicit test to run
    (test number, target surface, test name, and size uniquiely identify
    a test).
    
    Also adds a few paint tests.

diff --git a/perf/Makefile.win32 b/perf/Makefile.win32
new file mode 100644
index 0000000..8c3b70f
--- /dev/null
+++ b/perf/Makefile.win32
@@ -0,0 +1,16 @@
+CC = cl
+CFLAGS = /nologo /Zi /O2 /MD /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /I../src /I../pixman/src /I../boilerplate
+LDFLAGS = ../src/cairo.lib ../pixman/src/pixman.lib ../boilerplate/boiler.lib libpng.lib zlib.lib gdi32.lib msimg32.lib user32.lib
+
+PERF_SOURCES = \
+	cairo-perf-win32.c \
+	cairo-perf.c \
+	paint.c \
+	tessellate.c \
+	$(NULL)
+
+all: cairo-perf.exe
+
+cairo-perf.exe: $(PERF_SOURCES)
+	$(CC) $(CFLAGS) /Fe"$@" $^ /link $(LDFLAGS)
+
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 976c0dc..6519c0b 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /*
  * Copyright © 2006 Mozilla Corporation
  * Copyright © 2006 Red Hat, Inc.
@@ -142,6 +143,8 @@ main (int argc, char *argv[])
     cairo_perf_ticks_t *times;
     stats_t stats;
     const char *cairo_test_target = getenv ("CAIRO_TEST_TARGET");
+    double ms;
+    int test_number;
 
     if (getenv("CAIRO_PERF_ITERATIONS"))
 	cairo_perf_iterations = strtol(getenv("CAIRO_PERF_ITERATIONS"), NULL, 0);
@@ -154,6 +157,9 @@ main (int argc, char *argv[])
 	    continue;
 	if (cairo_test_target && ! strstr (cairo_test_target, target->name))
 	    continue;
+
+	test_number = 0;
+
 	for (j = 0; perfs[j].name; j++) {
 	    perf = &perfs[j];
 	    for (size = perf->min_size; size <= perf->max_size; size *= 2) {
@@ -176,18 +182,19 @@ main (int argc, char *argv[])
 		_compute_stats (times, .85 * cairo_perf_iterations, &stats);
 
 		if (i==0 && j==0 && size == perf->min_size)
-		    printf ("backend-content\ttest-size\tmean time\tstd dev.\titerations\n");
-		if (perf->min_size == perf->max_size)
-		    printf ("%s-%s\t%s\t",
-			    target->name, _content_to_string (target->content),
-			    perf->name);
-		else
-		    printf ("%s-%s\t%s-%d\t",
-			    target->name, _content_to_string (target->content),
-			    perf->name, size);
-		printf ("%g\t%g%%\t%d\n",
-			stats.mean / cairo_perf_ticks_per_second (),
+		    printf ("[ # ] %8s-%-4s %27s %9s %5s %s\n",
+			    "backend", "content", "test-size", "mean ms",
+			    "std dev.", "iterations");
+
+		printf ("[%3d] %8s-%-4s %25s-%-3d ",
+			test_number, target->name, _content_to_string (target->content),
+			perf->name, size);
+
+		printf ("%#9.3f %#5.2f%% % 5d\n",
+			(stats.mean * 1000.0) / cairo_perf_ticks_per_second (),
 			stats.std_dev * 100.0, cairo_perf_iterations);
+
+		test_number++;
 	    }
 	}
     }
@@ -196,10 +203,18 @@ main (int argc, char *argv[])
 }
 
 cairo_perf_t perfs[] = {
-    { "paint", paint, 64, 512 },
-    { "paint_alpha", paint_alpha, 64, 512 },
-    { "tessellate-16",  tessellate_16,  100, 100},
-    { "tessellate-64",  tessellate_64,  100, 100},
+    { "paint_over_solid", paint_over_solid, 64, 512 },
+    { "paint_over_solid_alpha", paint_over_solid_alpha, 64, 512 },
+    { "paint_source_solid", paint_over_solid, 64, 512 },
+    { "paint_source_solid_alpha", paint_over_solid_alpha, 64, 512 },
+
+    { "paint_over_surf_rgb24", paint_over_solid, 64, 512 },
+    { "paint_over_surf_argb32", paint_over_solid_alpha, 64, 512 },
+    { "paint_source_surf_rgb24", paint_over_solid, 64, 512 },
+    { "paint_source_surf_argb32", paint_over_solid_alpha, 64, 512 },
+
+    { "tessellate-16",	tessellate_16,	100, 100},
+    { "tessellate-64",	tessellate_64,	100, 100},
     { "tessellate-256", tessellate_256, 100, 100},
     { NULL }
 };
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 4b4071b..f22d762 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -63,8 +63,17 @@ typedef cairo_perf_ticks_t
 
 #define CAIRO_PERF_DECL(func) cairo_perf_ticks_t func (cairo_t *cr, int width, int height)
 
-CAIRO_PERF_DECL (paint);
-CAIRO_PERF_DECL (paint_alpha);
+/* paint.c */
+CAIRO_PERF_DECL (paint_over_solid);
+CAIRO_PERF_DECL (paint_over_solid_alpha);
+CAIRO_PERF_DECL (paint_source_solid);
+CAIRO_PERF_DECL (paint_source_solid_alpha);
+CAIRO_PERF_DECL (paint_over_surface_rgb24);
+CAIRO_PERF_DECL (paint_over_surface_argb32);
+CAIRO_PERF_DECL (paint_source_surface_rgb24);
+CAIRO_PERF_DECL (paint_source_surface_argb32);
+
+/* tessellate.c */
 CAIRO_PERF_DECL (tessellate_16);
 CAIRO_PERF_DECL (tessellate_64);
 CAIRO_PERF_DECL (tessellate_256);
diff --git a/perf/paint.c b/perf/paint.c
index 2501a33..1556383 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -54,8 +54,12 @@ do_paint (cairo_t *cr, int size)
     return cairo_perf_timer_elapsed ();
 }
 
+/*
+ * paint with solid color
+ */
+
 cairo_perf_ticks_t
-paint (cairo_t *cr, int width, int height)
+paint_over_solid (cairo_t *cr, int width, int height)
 {
     cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
 
@@ -63,10 +67,120 @@ paint (cairo_t *cr, int width, int heigh
 }
 
 cairo_perf_ticks_t
-paint_alpha (cairo_t *cr, int width, int height)
+paint_over_solid_alpha (cairo_t *cr, int width, int height)
+{
+    cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
+
+    return do_paint (cr, width);
+}
+
+cairo_perf_ticks_t
+paint_source_solid (cairo_t *cr, int width, int height)
 {
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
     cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
 
     return do_paint (cr, width);
 }
 
+cairo_perf_ticks_t
+paint_source_solid_alpha (cairo_t *cr, int width, int height)
+{
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+    cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
+
+    return do_paint (cr, width);
+}
+
+/*
+ * paint with surface
+ */
+
+
+int cached_surface_width = 0;
+int cached_surface_height = 0;
+cairo_content_t cached_surface_content = 0;
+cairo_surface_t *cached_surface = NULL;
+
+void
+ensure_cached_surface (cairo_t *cr, cairo_content_t content, int w, int h)
+{
+    cairo_surface_t *target_surface = cairo_get_target (cr);
+
+    cairo_t *cr2;
+
+    if (w == cached_surface_width && h == cached_surface_height &&
+        content == cached_surface_content &&
+        cached_surface &&
+        cairo_surface_get_type (target_surface) == cairo_surface_get_type (cached_surface))
+    {
+        return;
+    }
+
+    if (cached_surface)
+        cairo_surface_destroy (cached_surface);
+    
+    cached_surface = cairo_surface_create_similar (target_surface, content, w, h);
+
+    cached_surface_width = w;
+    cached_surface_height = h;
+    cached_surface_content = content;
+
+    /* Fill it with something known */
+    cr2 = cairo_create (cached_surface);
+    cairo_set_operator (cr2, CAIRO_OPERATOR_CLEAR);
+    cairo_paint (cr2);
+
+    cairo_set_operator (cr2, CAIRO_OPERATOR_SOURCE);
+    cairo_set_source_rgb (cr2, 0, 0, 1);
+    cairo_paint (cr2);
+
+    cairo_set_source_rgba (cr2, 1, 0, 0, 0.5);
+    cairo_new_path (cr2);
+    cairo_rectangle (cr2, 0, 0, w/2.0, h/2.0);
+    cairo_rectangle (cr2, w/2.0, h/2.0, w/2.0, h/2.0);
+    cairo_fill (cr2);
+    cairo_destroy (cr2);
+}
+
+cairo_perf_ticks_t
+paint_over_surface_rgb24 (cairo_t *cr, int width, int height)
+{
+    ensure_cached_surface (cr, CAIRO_CONTENT_COLOR, width, height);
+
+    cairo_set_source_surface (cr, cached_surface, 0, 0);
+
+    return do_paint (cr, width);
+}
+
+cairo_perf_ticks_t
+paint_over_surface_argb32 (cairo_t *cr, int width, int height)
+{
+    ensure_cached_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
+
+    cairo_set_source_surface (cr, cached_surface, 0, 0);
+
+    return do_paint (cr, width);
+}
+
+cairo_perf_ticks_t
+paint_source_surface_rgb24 (cairo_t *cr, int width, int height)
+{
+    ensure_cached_surface (cr, CAIRO_CONTENT_COLOR, width, height);
+
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+    cairo_set_source_surface (cr, cached_surface, 0, 0);
+
+    return do_paint (cr, width);
+}
+
+cairo_perf_ticks_t
+paint_source_surface_argb32 (cairo_t *cr, int width, int height)
+{
+    ensure_cached_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
+
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+    cairo_set_source_surface (cr, cached_surface, 0, 0);
+
+    return do_paint (cr, width);
+}
diff-tree e42905b01bd5bab11008b7d6a78bc263ae2f9f5d (from 82b710ebc214c46df6666ede486c0174b335bfdb)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Wed Sep 13 16:12:52 2006 -0700

    [win32,perf] Fix cairo-perf-win32
    
    Make cairo-perf work on win32

diff --git a/perf/cairo-perf-win32.c b/perf/cairo-perf-win32.c
index dd82267..157d1b2 100644
--- a/perf/cairo-perf-win32.c
+++ b/perf/cairo-perf-win32.c
@@ -47,8 +47,20 @@ cairo_perf_timer_start (void) {
     QueryPerformanceCounter(&timer.start);
 }
 
+static cairo_perf_timer_finalize_t cairo_perf_timer_finalize = NULL;
+static void *cairo_perf_timer_finalize_closure = NULL;
+void
+cairo_perf_timer_set_finalize (cairo_perf_timer_finalize_t	 finalize,
+			       void				*closure)
+{
+    cairo_perf_timer_finalize = finalize;
+    cairo_perf_timer_finalize_closure = closure;
+}
+
 void
 cairo_perf_timer_stop (void) {
+    if (cairo_perf_timer_finalize)
+	cairo_perf_timer_finalize (cairo_perf_timer_finalize_closure);
     QueryPerformanceCounter(&timer.stop);
 }
 
@@ -63,7 +75,7 @@ cairo_perf_ticks_per_second (void) {
 
     QueryPerformanceFrequency(&freq);
 
-    return freq;
+    return freq.QuadPart;
 }
 
 


More information about the cairo-commit mailing list