[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