[cairo] add solid/gradient pattern info getters

Vladimir Vukicevic vladimirv at gmail.com
Wed Sep 13 18:56:11 PDT 2006


Ok, updated with comments.  This patch also implements
cairo_get_dash().  Test cases for get_dash added to get-and-set, and a
new pattern-getters testcase added for the other stuff.

The new functions now looks like:

cairo_public cairo_status_t
cairo_get_dash (cairo_t *cr, int *num_dashes, double *dashes, double *offset);


cairo_public cairo_status_t
cairo_pattern_get_rgba (cairo_pattern_t *pattern,
			double *r, double *g, double *b, double *a);

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_stops (cairo_pattern_t *pattern,
			       int *num_stops, double *stop_data);

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);

    - Vlad
-------------- next part --------------
--- 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_COUNT: invalid element count 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_COUNT
 } cairo_status_t;
 
 /**
@@ -1073,7 +1075,8 @@ 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 (cairo_t *cr, int *num_dashes, double *dashes, double *offset);
 
 cairo_public void
 cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix);
@@ -1549,6 +1552,28 @@ 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 *r, double *g, double *b, double *a);
+
+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_stops (cairo_pattern_t *pattern,
+			       int *num_stops, double *stop_data);
+
+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/src/cairo-pattern.c b/src/cairo-pattern.c
index a859e52..1902cce 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1,2 +1,3 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
@@ -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,215 @@ _cairo_pattern_get_extents (cairo_patter
 
     return CAIRO_STATUS_SUCCESS;
 }
+
+/**
+ * cairo_pattern_get_rgba
+ * @pattern: a #cairo_pattern_t
+ * @r: a double to return the red color value in.
+ * @g: a double to return the green color value in.
+ * @b: a double to return the blue color value in.
+ * @a: a double to return the alpha value in.
+ *
+ * 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 *r, double *g, double *b, double *a)
+{
+    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 (r)
+	*r = r0;
+    if (g)
+	*g = g0;
+    if (b)
+	*b = b0;
+    if (a)
+	*a = a0;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_pattern_get_surface
+ * @pattern: a #cairo_pattern_t
+ * @surface: a pointer to a surface to return the pattern's surface in.
+ * 
+ * Gets the surface of a surface pattern.
+ *
+ * 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_stops
+ * @pattern: a #cairo_pattern_t
+ * @num_stops: an in/out integer either giving the number of allocated
+ *   color stops, or receiving the number of color stops in the gradient.
+ * @stop_data: a pointer to 5*@num_stops doubles in which to place the
+ *   color stop data, or NULL to indicate that the number of stops
+ *   is to be queried.
+ *
+ * cairo_pattern_get_color_stops() is used to retrieve the color stops
+ * associated with a gradient pattern.  Passing NULL for @stop_data will
+ * return the number of color stops in the pattern in @num_stops.
+ * The caller should allocate 5*@num_stops doubles to hold the data,
+ * and call the function again with @num_stops set to the returned
+ * value and @stop_data set to the newly allocated array.
+ *
+ * The array contents will be filled in with the stop offset, red,
+ * green, blue, alpha values in sequence, per stop.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS, or CAIRO_STATUS_INVALID_COUNT
+ * if @stop_data is not NULL and @num_stops does not equal the actual
+ * number of color stops in the gradient. If the pattern is not a
+ * gradient pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
+ * CAIRO_NULL_POINTER is returned if @num_stops is NULL.
+ *
+ * Since: 1.4
+ **/
+cairo_status_t
+cairo_pattern_get_color_stops (cairo_pattern_t *pattern,
+			       int *num_stops, double *stop_data)
+{
+    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
+    int i, j;
+
+    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
+	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
+	return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+
+    if (num_stops == NULL)
+	return CAIRO_STATUS_NULL_POINTER;
+
+    if (stop_data == NULL) {
+	*num_stops = gradient->n_stops;
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    if (*num_stops != gradient->n_stops)
+	return CAIRO_STATUS_INVALID_COUNT;
+
+    j = 0;
+    for (i = 0; i < gradient->n_stops; i++) {
+	stop_data[j++] = _cairo_fixed_to_double(gradient->stops[i].x);
+	stop_data[j++] = gradient->stops[i].color.red / (double) 0xffff;
+	stop_data[j++] = gradient->stops[i].color.green / (double) 0xffff;
+	stop_data[j++] = gradient->stops[i].color.blue / (double) 0xffff;
+	stop_data[j++] = gradient->stops[i].color.alpha / (double) 0xffff;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_pattern_get_linear_points
+ * @pattern: a #cairo_pattern_t
+ * @x0: a double to return the x coordinate of the first point in.
+ * @y0: a double to return the y coordinate of the first point in.
+ * @x1: a double to return the x coordinate of the second point in.
+ * @y1: a double to return the y coordinate of the second point in.
+ *
+ * Gets the gradient endpoints for a linear gradient.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS unless the operation fails.  If
+ * the pattern is not a linear gradient pattern,
+ * CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
+ *
+ * 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: double to return the x coordinate of the center of the first (inner) circle
+ * @y0: double to return the y coordinate of the center of the first (inner) circle
+ * @r0: double to return the radius of the first (inner) circle
+ * @x1: double to return the x coordinate of the center of the second (outer) circle
+ * @y1: double to return the y coordinate of the center of the second (outer) circle
+ * @r1: double to return the radius of the second (outer) circle
+ *
+ * Gets the circle endpoints for a radial gradient.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS unless the operation fails.  If
+ * the pattern is not a radial gradient pattern,
+ * CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
+ *
+ * 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-scaled-font.c b/src/cairo-scaled-font.c
old mode 100755
new mode 100644
diff --git a/src/cairo.c b/src/cairo.c
index 26fe1c1..18c3e0b 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 @@ #include <assert.h>
  * 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_COUNT
 
 /**
  * _cairo_error:
@@ -947,6 +948,61 @@ cairo_set_dash (cairo_t	     *cr,
 	_cairo_set_error (cr, cr->status);
 }
 
+/**
+ * cairo_get_dash:
+ * @cr: a #cairo_t
+ * @num_dashes: an in/out integer either giving the number of allocated
+ *   dash entires, or receiving the number of dashes.
+ * @dashes: a pointer to @num_dashes doubles in which to place the dash
+ *   data, or NULL to indicate that the number of dashes is to be queried.
+ * @offset: a double in which to return the current dash offset
+ *
+ * cairo_get_dash() is used to retrieve the current dash state.
+ * Passing NULL for @dashes will return the number of color stops in
+ * the pattern in @num_dashes.  The caller should allocate @num_dashes
+ * doubles to hold the data, and call the function again with
+ * @num_dashes set to the returned value and @dashes set to the newly
+ * allocated array.
+ *
+ * The dash offset is always returned in @offset, if @offset is not NULL.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS, or CAIRO_STATUS_INVALID_COUNT if
+ * @stop_data is not NULL and @num_stops does not equal the actual
+ * number of dashes.  CAIRO_NULL_POINTER is returned if @num_dashes is
+ * NULL.
+ **/
+cairo_status_t
+cairo_get_dash (cairo_t *cr,
+                int     *num_dashes,
+                double  *dashes,
+                double  *offset)
+{
+    if (cr->status)
+	return cr->status;
+
+    if (num_dashes == NULL)
+	return CAIRO_STATUS_NULL_POINTER;
+
+    /* Always return this */
+    if (offset)
+	*offset = cr->gstate->stroke_style.dash_offset;
+
+    if (dashes == NULL) {
+	*num_dashes = cr->gstate->stroke_style.num_dashes;
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    if (*num_dashes != cr->gstate->stroke_style.num_dashes)
+	return CAIRO_STATUS_INVALID_COUNT;
+
+    memcpy (dashes,
+	    cr->gstate->stroke_style.dash,
+	    sizeof(double) * cr->gstate->stroke_style.num_dashes);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 void
 cairo_set_miter_limit (cairo_t *cr, double limit)
 {
@@ -3010,6 +3066,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_COUNT:
+	return "invalid element count passed to getter";
     }
 
     return "<unknown error status>";
diff --git a/src/cairo.h b/src/cairo.h
index ca8c375..549f9ee 100644
diff --git a/src/cairoint.h b/src/cairoint.h
old mode 100755
new mode 100644
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..2b44d40 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
old mode 100644
new mode 100755
index ae17cc8..daa40c0
--- a/test/get-and-set.c
+++ b/test/get-and-set.c
@@ -43,6 +43,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 +57,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 +69,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 +86,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 +100,26 @@ 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 ival;
+
+	ival = 1;
+	status = cairo_get_dash (cr, &ival, settings->dash, NULL);
+	if (status != CAIRO_STATUS_INVALID_COUNT)
+	    return -1;
+
+	status = cairo_get_dash (cr, &ival, NULL, NULL);
+	if (status || ival != 5)
+	    return -1;
+
+	status = cairo_get_dash (cr, &ival, settings->dash, &settings->dash_offset);
+	if (status)
+	    return -1;
+    }
+
+    return 0;
 }
 
 static int
@@ -110,7 +137,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 +152,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


More information about the cairo mailing list