572
581
slim_hidden_def (cairo_pattern_destroy);
584
* cairo_pattern_get_reference_count:
585
* @pattern: a #cairo_pattern_t
587
* Returns the current reference count of @pattern.
589
* Return value: the current reference count of @pattern. If the
590
* object is a nil object, 0 will be returned.
595
cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
597
if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
600
return pattern->ref_count;
604
* cairo_pattern_get_user_data:
605
* @pattern: a #cairo_pattern_t
606
* @key: the address of the #cairo_user_data_key_t the user data was
609
* Return user data previously attached to @pattern using the
610
* specified key. If no user data has been attached with the given
611
* key this function returns %NULL.
613
* Return value: the user data previously attached or %NULL.
618
cairo_pattern_get_user_data (cairo_pattern_t *pattern,
619
const cairo_user_data_key_t *key)
621
return _cairo_user_data_array_get_data (&pattern->user_data,
626
* cairo_pattern_set_user_data:
627
* @pattern: a #cairo_pattern_t
628
* @key: the address of a #cairo_user_data_key_t to attach the user data to
629
* @user_data: the user data to attach to the #cairo_pattern_t
630
* @destroy: a #cairo_destroy_func_t which will be called when the
631
* #cairo_t is destroyed or when new user data is attached using the
634
* Attach user data to @pattern. To remove user data from a surface,
635
* call this function with the key that was used to set it and %NULL
638
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
639
* slot could not be allocated for the user data.
644
cairo_pattern_set_user_data (cairo_pattern_t *pattern,
645
const cairo_user_data_key_t *key,
647
cairo_destroy_func_t destroy)
649
if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
650
return CAIRO_STATUS_NO_MEMORY;
652
return _cairo_user_data_array_set_data (&pattern->user_data,
653
key, user_data, destroy);
656
/* make room for at least one more color stop */
657
static cairo_status_t
658
_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
660
pixman_gradient_stop_t *new_stops;
661
int old_size = pattern->stops_size;
662
int embedded_size = sizeof (pattern->stops_embedded) / sizeof (pattern->stops_embedded[0]);
663
int new_size = 2 * MAX (old_size, 4);
665
/* we have a local buffer at pattern->stops_embedded. try to fulfill the request
667
if (old_size < embedded_size) {
668
pattern->stops = pattern->stops_embedded;
669
pattern->stops_size = embedded_size;
670
return CAIRO_STATUS_SUCCESS;
673
assert (pattern->n_stops <= pattern->stops_size);
675
if (pattern->stops == pattern->stops_embedded) {
676
new_stops = malloc (new_size * sizeof (pixman_gradient_stop_t));
678
memcpy (new_stops, pattern->stops, old_size * sizeof (pixman_gradient_stop_t));
680
new_stops = realloc (pattern->stops, new_size * sizeof (pixman_gradient_stop_t));
683
if (new_stops == NULL) {
684
return CAIRO_STATUS_NO_MEMORY;
687
pattern->stops = new_stops;
688
pattern->stops_size = new_size;
690
return CAIRO_STATUS_SUCCESS;
575
694
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
1157
1277
attr->matrix = pattern->base.matrix;
1158
1278
attr->x_offset = attr->y_offset = 0;
1285
* The way we currently support CAIRO_EXTEND_REFLECT is to create
1286
* an image twice bigger on each side, and create a pattern of four
1287
* images such that the new image, when repeated, has the same effect
1288
* of reflecting the original pattern.
1290
* This is because the reflect support in pixman is broken and we
1291
* pass repeat instead of reflect to pixman. See
1292
* _cairo_image_surface_set_attributes() for that.
1294
if (attr->extend == CAIRO_EXTEND_REFLECT) {
1298
cairo_rectangle_int16_t extents;
1299
status = _cairo_surface_get_extents (pattern->surface, &extents);
1303
attr->extend = CAIRO_EXTEND_REPEAT;
1307
w = 2 * extents.width;
1308
h = 2 * extents.height;
1310
*out = cairo_surface_create_similar (dst, dst->content, w, h);
1312
return CAIRO_STATUS_NO_MEMORY;
1314
(*out)->device_transform = pattern->surface->device_transform;
1315
(*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
1317
cr = cairo_create (*out);
1319
cairo_set_source_surface (cr, pattern->surface, -x, -y);
1322
cairo_scale (cr, -1, +1);
1323
cairo_set_source_surface (cr, pattern->surface, x-w, -y);
1326
cairo_scale (cr, +1, -1);
1327
cairo_set_source_surface (cr, pattern->surface, x-w, y-h);
1330
cairo_scale (cr, -1, +1);
1331
cairo_set_source_surface (cr, pattern->surface, -x, y-h);
1334
status = cairo_status (cr);
1340
if (_cairo_surface_is_image (dst))
1342
cairo_image_surface_t *image;
1344
status = _cairo_surface_acquire_source_image (pattern->surface,
1350
*out = &image->base;
1351
attr->acquired = TRUE;
1355
cairo_rectangle_int16_t extents;
1356
status = _cairo_surface_get_extents (pattern->surface, &extents);
1360
/* If we're repeating, we just play it safe and clone the entire surface. */
1361
/* If requested width and height are -1, clone the entire surface.
1362
* This is relied on in the svg backend. */
1363
if (attr->extend == CAIRO_EXTEND_REPEAT ||
1364
(width == (unsigned int) -1 && height == (unsigned int) -1)) {
1367
width = extents.width;
1368
height = extents.height;
1370
/* Otherwise, we first transform the rectangle to the
1371
* coordinate space of the source surface so that we can
1372
* clone only that portion of the surface that will be
1374
if (! _cairo_matrix_is_identity (&attr->matrix)) {
1377
double x2 = x + width;
1378
double y2 = y + height;
1379
cairo_bool_t is_tight;
1381
_cairo_matrix_transform_bounding_box (&attr->matrix,
1385
/* The transform_bounding_box call may have resulted
1386
* in a region larger than the surface, but we never
1387
* want to clone more than the surface itself, (we
1388
* know we're not repeating at this point due to the
1390
x = MAX (0, floor (x1));
1391
y = MAX (0, floor (y1));
1392
width = MIN (extents.width, ceil (x2)) - x;
1393
height = MIN (extents.height, ceil (y2)) - y;
1399
status = _cairo_surface_clone_similar (dst, pattern->surface,
1400
x, y, width, height, out);
1402
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1406
*out = cairo_surface_create_similar (dst, dst->content,
1409
return CAIRO_STATUS_NO_MEMORY;
1411
(*out)->device_transform = pattern->surface->device_transform;
1412
(*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
1414
/* XXX Use _cairo_surface_composite directly */
1415
cr = cairo_create (*out);
1417
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
1418
cairo_set_source_surface (cr, pattern->surface, -x, -y);
1421
status = cairo_status (cr);
1457
1723
return CAIRO_STATUS_SUCCESS;
1727
* cairo_pattern_get_rgba
1728
* @pattern: a #cairo_pattern_t
1729
* @red: return value for red component of color, or %NULL
1730
* @green: return value for green component of color, or %NULL
1731
* @blue: return value for blue component of color, or %NULL
1732
* @alpha: return value for alpha component of color, or %NULL
1734
* Gets the solid color for a solid color pattern.
1736
* Return value: %CAIRO_STATUS_SUCCESS, or
1737
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
1743
cairo_pattern_get_rgba (cairo_pattern_t *pattern,
1744
double *red, double *green,
1745
double *blue, double *alpha)
1747
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
1748
double r0, g0, b0, a0;
1750
if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
1751
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
1753
_cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
1764
return CAIRO_STATUS_SUCCESS;
1768
* cairo_pattern_get_surface
1769
* @pattern: a #cairo_pattern_t
1770
* @surface: return value for surface of pattern, or %NULL
1772
* Gets the surface of a surface pattern. The reference returned in
1773
* @surface is owned by the pattern; the caller should call
1774
* cairo_surface_reference() if the surface is to be retained.
1776
* Return value: %CAIRO_STATUS_SUCCESS, or
1777
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
1783
cairo_pattern_get_surface (cairo_pattern_t *pattern,
1784
cairo_surface_t **surface)
1786
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
1788
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
1789
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
1792
*surface = spat->surface;
1794
return CAIRO_STATUS_SUCCESS;
1798
* cairo_pattern_get_color_stop_rgba
1799
* @pattern: a #cairo_pattern_t
1800
* @index: index of the stop to return data for
1801
* @offset: return value for the offset of the stop, or %NULL
1802
* @red: return value for red component of color, or %NULL
1803
* @green: return value for green component of color, or %NULL
1804
* @blue: return value for blue component of color, or %NULL
1805
* @alpha: return value for alpha component of color, or %NULL
1807
* Gets the color and offset information at the given @index for a
1808
* gradient pattern. Values of @index are 0 to 1 less than the number
1809
* returned by cairo_pattern_get_color_stop_count().
1811
* Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
1812
* if @index is not valid for the given pattern. If the pattern is
1813
* not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
1819
cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
1820
int index, double *offset,
1821
double *red, double *green,
1822
double *blue, double *alpha)
1824
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
1826
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
1827
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
1828
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
1830
if (index < 0 || (unsigned int) index >= gradient->n_stops)
1831
return CAIRO_STATUS_INVALID_INDEX;
1834
*offset = _cairo_fixed_to_double(gradient->stops[index].x);
1836
*red = gradient->stops[index].color.red / (double) 0xffff;
1838
*green = gradient->stops[index].color.green / (double) 0xffff;
1840
*blue = gradient->stops[index].color.blue / (double) 0xffff;
1842
*alpha = gradient->stops[index].color.alpha / (double) 0xffff;
1844
return CAIRO_STATUS_SUCCESS;
1848
* cairo_pattern_get_color_stop_count
1849
* @pattern: a #cairo_pattern_t
1850
* @count: return value for the number of color stops, or %NULL
1852
* Gets the number of color stops specified in the given gradient
1855
* Return value: %CAIRO_STATUS_SUCCESS, or
1856
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
1862
cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
1865
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
1867
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
1868
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
1869
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
1872
*count = gradient->n_stops;
1874
return CAIRO_STATUS_SUCCESS;
1878
* cairo_pattern_get_linear_points
1879
* @pattern: a #cairo_pattern_t
1880
* @x0: return value for the x coordinate of the first point, or %NULL
1881
* @y0: return value for the y coordinate of the first point, or %NULL
1882
* @x1: return value for the x coordinate of the second point, or %NULL
1883
* @y1: return value for the y coordinate of the second point, or %NULL
1885
* Gets the gradient endpoints for a linear gradient.
1887
* Return value: %CAIRO_STATUS_SUCCESS, or
1888
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
1894
cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
1895
double *x0, double *y0,
1896
double *x1, double *y1)
1898
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
1900
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
1901
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
1904
*x0 = _cairo_fixed_to_double (linear->gradient.p1.x);
1906
*y0 = _cairo_fixed_to_double (linear->gradient.p1.y);
1908
*x1 = _cairo_fixed_to_double (linear->gradient.p2.x);
1910
*y1 = _cairo_fixed_to_double (linear->gradient.p2.y);
1912
return CAIRO_STATUS_SUCCESS;
1916
* cairo_pattern_get_radial_circles
1917
* @pattern: a #cairo_pattern_t
1918
* @x0: return value for the x coordinate of the center of the first circle, or %NULL
1919
* @y0: return value for the y coordinate of the center of the first circle, or %NULL
1920
* @r0: return value for the radius of the first circle, or %NULL
1921
* @x1: return value for the x coordinate of the center of the second circle, or %NULL
1922
* @y1: return value for the y coordinate of the center of the second circle, or %NULL
1923
* @r1: return value for the radius of the second circle, or %NULL
1925
* Gets the gradient endpoint circles for a radial gradient, each
1926
* specified as a center coordinate and a radius.
1928
* Return value: %CAIRO_STATUS_SUCCESS, or
1929
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
1935
cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
1936
double *x0, double *y0, double *r0,
1937
double *x1, double *y1, double *r1)
1939
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
1941
if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
1942
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
1945
*x0 = _cairo_fixed_to_double (radial->gradient.c1.x);
1947
*y0 = _cairo_fixed_to_double (radial->gradient.c1.y);
1949
*r0 = _cairo_fixed_to_double (radial->gradient.c1.radius);
1951
*x1 = _cairo_fixed_to_double (radial->gradient.c2.x);
1953
*y1 = _cairo_fixed_to_double (radial->gradient.c2.y);
1955
*r1 = _cairo_fixed_to_double (radial->gradient.c2.radius);
1957
return CAIRO_STATUS_SUCCESS;