#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
/** * SECTION:cairo-pattern * @Title: cairo_pattern_t * @Short_Description: Sources for drawing * @See_Also: #cairo_t, #cairo_surface_t * * #cairo_pattern_t is the paint with which cairo draws. * The primary use of patterns is as the source for all cairo drawing * operations, although they can also be used as masks, that is, as the * brush too. * * A cairo pattern is created by using one of the many constructors, * of the form * <function>cairo_pattern_create_<emphasis>type</emphasis>()</function> * or implicitly through * <function>cairo_set_source_<emphasis>type</emphasis>()</function> * functions.
**/
/** * _cairo_pattern_set_error: * @pattern: a pattern * @status: a status value indicating an error * * Atomically sets pattern->status to @status and calls _cairo_error; * Does nothing if status is %CAIRO_STATUS_SUCCESS. * * All assignments of an error status to pattern->status should happen * through _cairo_pattern_set_error(). Note that due to the nature of * the atomic operation, it is not safe to call this function on the nil * objects. * * The purpose of this function is to allow the user to set a * breakpoint in _cairo_error() to generate a stack trace for when the * user causes cairo to detect an error.
**/ static cairo_status_t
_cairo_pattern_set_error (cairo_pattern_t *pattern,
cairo_status_t status)
{ if (status == CAIRO_STATUS_SUCCESS) return status;
/* Don't overwrite an existing error. This preserves the first
* error, which is the most significant. */
_cairo_status_set_error (&pattern->status, status);
return _cairo_error (status);
}
void
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
{ #if HAVE_VALGRIND switch (type) { case CAIRO_PATTERN_TYPE_SOLID:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)); break; case CAIRO_PATTERN_TYPE_SURFACE:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)); break; case CAIRO_PATTERN_TYPE_LINEAR:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)); break; case CAIRO_PATTERN_TYPE_RADIAL:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t)); break; case CAIRO_PATTERN_TYPE_MESH:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)); break; case CAIRO_PATTERN_TYPE_RASTER_SOURCE: break;
} #endif
/* Set the reference count to zero for on-stack patterns.
* Callers needs to explicitly increment the count for heap allocations. */
CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
status = _cairo_mesh_pattern_init_copy (dst, src); if (unlikely (status)) return status;
} break;
case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
status = _cairo_raster_source_pattern_init_copy (pattern, other); if (unlikely (status)) return status;
} break;
}
/* The reference count and user_data array are unique to the copy. */
CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
_cairo_user_data_array_init (&pattern->user_data);
cairo_list_init (&pattern->observers);
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_pattern_init_static_copy (cairo_pattern_t *pattern, const cairo_pattern_t *other)
{ int size;
assert (other->status == CAIRO_STATUS_SUCCESS);
switch (other->type) { default:
ASSERT_NOT_REACHED; case CAIRO_PATTERN_TYPE_SOLID:
size = sizeof (cairo_solid_pattern_t); break; case CAIRO_PATTERN_TYPE_SURFACE:
size = sizeof (cairo_surface_pattern_t); break; case CAIRO_PATTERN_TYPE_LINEAR:
size = sizeof (cairo_linear_pattern_t); break; case CAIRO_PATTERN_TYPE_RADIAL:
size = sizeof (cairo_radial_pattern_t); break; case CAIRO_PATTERN_TYPE_MESH:
size = sizeof (cairo_mesh_pattern_t); break; case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
size = sizeof (cairo_raster_source_pattern_t); break;
}
/* We don't bother doing any fancy copy-on-write implementation
* for the pattern's data. It's generally quite tiny. */
status = _cairo_pattern_init_copy (pattern, other); if (unlikely (status)) return status;
/* But we do let the surface snapshot stuff be as fancy as it
* would like to be. */ if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern =
(cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;
if (status == CAIRO_STATUS_NO_MEMORY) return (cairo_pattern_t *)&_cairo_pattern_nil.base;
CAIRO_MUTEX_INITIALIZE ();
pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK); if (pattern->status == CAIRO_STATUS_SUCCESS)
status = _cairo_pattern_set_error (pattern, status);
return pattern;
}
/** * cairo_pattern_create_rgb: * @red: red component of the color * @green: green component of the color * @blue: blue component of the color * * Creates a new #cairo_pattern_t corresponding to an opaque color. The * color components are floating point numbers in the range 0 to 1. * If the values passed in are outside that range, they will be * clamped. * * Return value: the newly created #cairo_pattern_t if successful, or * an error pattern in case of no memory. The caller owns the * returned object and should call cairo_pattern_destroy() when * finished with it. * * This function will always return a valid pointer, but if an error * occurred the pattern status will be set to an error. To inspect * the status of a pattern use cairo_pattern_status(). * * Since: 1.0
**/
cairo_pattern_t *
cairo_pattern_create_rgb (double red, double green, double blue)
{ return cairo_pattern_create_rgba (red, green, blue, 1.0);
}
/** * cairo_pattern_create_rgba: * @red: red component of the color * @green: green component of the color * @blue: blue component of the color * @alpha: alpha component of the color * * Creates a new #cairo_pattern_t corresponding to a translucent color. * The color components are floating point numbers in the range 0 to * 1. If the values passed in are outside that range, they will be * clamped. * * The color is specified in the same way as in cairo_set_source_rgb(). * * Return value: the newly created #cairo_pattern_t if successful, or * an error pattern in case of no memory. The caller owns the * returned object and should call cairo_pattern_destroy() when * finished with it. * * This function will always return a valid pointer, but if an error * occurred the pattern status will be set to an error. To inspect * the status of a pattern use cairo_pattern_status(). * * Since: 1.0
**/
cairo_pattern_t *
cairo_pattern_create_rgba (double red, double green, double blue, double alpha)
{
cairo_color_t color;
red = _cairo_restrict_value (red, 0.0, 1.0);
green = _cairo_restrict_value (green, 0.0, 1.0);
blue = _cairo_restrict_value (blue, 0.0, 1.0);
alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
/** * cairo_pattern_create_for_surface: * @surface: the surface * * Create a new #cairo_pattern_t for the given surface. * * Return value: the newly created #cairo_pattern_t if successful, or * an error pattern in case of no memory. The caller owns the * returned object and should call cairo_pattern_destroy() when * finished with it. * * This function will always return a valid pointer, but if an error * occurred the pattern status will be set to an error. To inspect * the status of a pattern use cairo_pattern_status(). * * Since: 1.0
**/
cairo_pattern_t *
cairo_pattern_create_for_surface (cairo_surface_t *surface)
{
cairo_surface_pattern_t *pattern;
/** * cairo_pattern_create_linear: * @x0: x coordinate of the start point * @y0: y coordinate of the start point * @x1: x coordinate of the end point * @y1: y coordinate of the end point * * Create a new linear gradient #cairo_pattern_t along the line defined * by (x0, y0) and (x1, y1). Before using the gradient pattern, a * number of color stops should be defined using * cairo_pattern_add_color_stop_rgb() or * cairo_pattern_add_color_stop_rgba(). * * Note: The coordinates here are in pattern space. For a new pattern, * pattern space is identical to user space, but the relationship * between the spaces can be changed with cairo_pattern_set_matrix(). * * Return value: the newly created #cairo_pattern_t if successful, or * an error pattern in case of no memory. The caller owns the * returned object and should call cairo_pattern_destroy() when * finished with it. * * This function will always return a valid pointer, but if an error * occurred the pattern status will be set to an error. To inspect * the status of a pattern use cairo_pattern_status(). * * Since: 1.0
**/
cairo_pattern_t *
cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
{
cairo_linear_pattern_t *pattern;
/** * 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 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 circle * * Creates a new radial gradient #cairo_pattern_t between the two * circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1). Before using the * gradient pattern, a number of color stops should be defined using * cairo_pattern_add_color_stop_rgb() or * cairo_pattern_add_color_stop_rgba(). * * Note: The coordinates here are in pattern space. For a new pattern, * pattern space is identical to user space, but the relationship * between the spaces can be changed with cairo_pattern_set_matrix(). * * Return value: the newly created #cairo_pattern_t if successful, or * an error pattern in case of no memory. The caller owns the * returned object and should call cairo_pattern_destroy() when * finished with it. * * This function will always return a valid pointer, but if an error * occurred the pattern status will be set to an error. To inspect * the status of a pattern use cairo_pattern_status(). * * Since: 1.0
**/
cairo_pattern_t *
cairo_pattern_create_radial (double cx0, double cy0, double radius0, double cx1, double cy1, double radius1)
{
cairo_radial_pattern_t *pattern;
/* This order is specified in the diagram in the documentation for
* cairo_pattern_create_mesh() */ staticconstint mesh_path_point_i[12] = { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1 }; staticconstint mesh_path_point_j[12] = { 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0 }; staticconstint mesh_control_point_i[4] = { 1, 1, 2, 2 }; staticconstint mesh_control_point_j[4] = { 1, 2, 2, 1 };
/** * cairo_pattern_create_mesh: * * Create a new mesh pattern. * * Mesh patterns are tensor-product patch meshes (type 7 shadings in * PDF). Mesh patterns may also be used to create other types of * shadings that are special cases of tensor-product patch meshes such * as Coons patch meshes (type 6 shading in PDF) and Gouraud-shaded * triangle meshes (type 4 and 5 shadings in PDF). * * Mesh patterns consist of one or more tensor-product patches, which * should be defined before using the mesh pattern. Using a mesh * pattern with a partially defined patch as source or mask will put * the context in an error status with a status of * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * A tensor-product patch is defined by 4 Bézier curves (side 0, 1, 2, * 3) and by 4 additional control points (P0, P1, P2, P3) that provide * further control over the patch and complete the definition of the * tensor-product patch. The corner C0 is the first point of the * patch. * * Degenerate sides are permitted so straight lines may be used. A * zero length line on one side may be used to create 3 sided patches. * * <informalexample><screen> * C1 Side 1 C2 * +---------------+ * | | * | P1 P2 | * | | * Side 0 | | Side 2 * | | * | | * | P0 P3 | * | | * +---------------+ * C0 Side 3 C3 * </screen></informalexample> * * Each patch is constructed by first calling * cairo_mesh_pattern_begin_patch(), then cairo_mesh_pattern_move_to() * to specify the first point in the patch (C0). Then the sides are * specified with calls to cairo_mesh_pattern_curve_to() and * cairo_mesh_pattern_line_to(). * * The four additional control points (P0, P1, P2, P3) in a patch can * be specified with cairo_mesh_pattern_set_control_point(). * * At each corner of the patch (C0, C1, C2, C3) a color may be * specified with cairo_mesh_pattern_set_corner_color_rgb() or * cairo_mesh_pattern_set_corner_color_rgba(). Any corner whose color * is not explicitly specified defaults to transparent black. * * A Coons patch is a special case of the tensor-product patch where * the control points are implicitly defined by the sides of the * patch. The default value for any control point not specified is the * implicit value for a Coons patch, i.e. if no control points are * specified the patch is a Coons patch. * * A triangle is a special case of the tensor-product patch where the * control points are implicitly defined by the sides of the patch, * all the sides are lines and one of them has length 0, i.e. if the * patch is specified using just 3 lines, it is a triangle. If the * corners connected by the 0-length side have the same color, the * patch is a Gouraud-shaded triangle. * * Patches may be oriented differently to the above diagram. For * example the first point could be at the top left. The diagram only * shows the relationship between the sides, corners and control * points. Regardless of where the first point is located, when * specifying colors, corner 0 will always be the first point, corner * 1 the point between side 0 and side 1 etc. * * Calling cairo_mesh_pattern_end_patch() completes the current * patch. If less than 4 sides have been defined, the first missing * side is defined as a line from the current point to the first point * of the patch (C0) and the other sides are degenerate lines from C0 * to C0. The corners between the added sides will all be coincident * with C0 of the patch and their color will be set to be the same as * the color of C0. * * Additional patches may be added with additional calls to * cairo_mesh_pattern_begin_patch()/cairo_mesh_pattern_end_patch(). * * <informalexample><programlisting> * cairo_pattern_t *pattern = cairo_pattern_create_mesh (); * * /* Add a Coons patch */ * cairo_mesh_pattern_begin_patch (pattern); * cairo_mesh_pattern_move_to (pattern, 0, 0); * cairo_mesh_pattern_curve_to (pattern, 30, -30, 60, 30, 100, 0); * cairo_mesh_pattern_curve_to (pattern, 60, 30, 130, 60, 100, 100); * cairo_mesh_pattern_curve_to (pattern, 60, 70, 30, 130, 0, 100); * cairo_mesh_pattern_curve_to (pattern, 30, 70, -30, 30, 0, 0); * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0); * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0); * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1); * cairo_mesh_pattern_set_corner_color_rgb (pattern, 3, 1, 1, 0); * cairo_mesh_pattern_end_patch (pattern); * * /* Add a Gouraud-shaded triangle */ * cairo_mesh_pattern_begin_patch (pattern) * cairo_mesh_pattern_move_to (pattern, 100, 100); * cairo_mesh_pattern_line_to (pattern, 130, 130); * cairo_mesh_pattern_line_to (pattern, 130, 70); * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0); * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0); * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1); * cairo_mesh_pattern_end_patch (pattern) * </programlisting></informalexample> * * When two patches overlap, the last one that has been added is drawn * over the first one. * * When a patch folds over itself, points are sorted depending on * their parameter coordinates inside the patch. The v coordinate * ranges from 0 to 1 when moving from side 3 to side 1; the u * coordinate ranges from 0 to 1 when going from side 0 to side * 2. Points with higher v coordinate hide points with lower v * coordinate. When two points have the same v coordinate, the one * with higher u coordinate is above. This means that points nearer to * side 1 are above points nearer to side 3; when this is not * sufficient to decide which point is above (for example when both * points belong to side 1 or side 3) points nearer to side 2 are * above points nearer to side 0. * * For a complete definition of tensor-product patches, see the PDF * specification (ISO32000), which describes the parametrization in * detail. * * Note: The coordinates are always in pattern space. For a new * pattern, pattern space is identical to user space, but the * relationship between the spaces can be changed with * cairo_pattern_set_matrix(). * * Return value: the newly created #cairo_pattern_t if successful, or * an error pattern in case of no memory. The caller owns the returned * object and should call cairo_pattern_destroy() when finished with * it. * * This function will always return a valid pointer, but if an error * occurred the pattern status will be set to an error. To inspect the * status of a pattern use cairo_pattern_status(). * * Since: 1.12
**/
cairo_pattern_t *
cairo_pattern_create_mesh (void)
{
cairo_mesh_pattern_t *pattern;
/** * cairo_pattern_reference: * @pattern: a #cairo_pattern_t * * Increases the reference count on @pattern by one. This prevents * @pattern from being destroyed until a matching call to * cairo_pattern_destroy() is made. * * Use cairo_pattern_get_reference_count() to get the number of * references to a #cairo_pattern_t. * * Return value: the referenced #cairo_pattern_t. * * Since: 1.0
**/
cairo_pattern_t *
cairo_pattern_reference (cairo_pattern_t *pattern)
{ if (pattern == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count)) return pattern;
/** * cairo_pattern_get_type: * @pattern: a #cairo_pattern_t * * Get the pattern's type. See #cairo_pattern_type_t for available * types. * * Return value: The type of @pattern. * * Since: 1.2
**/
cairo_pattern_type_t
cairo_pattern_get_type (cairo_pattern_t *pattern)
{ return pattern->type;
}
/** * cairo_pattern_status: * @pattern: a #cairo_pattern_t * * Checks whether an error has previously occurred for this * pattern. * * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, * %CAIRO_STATUS_INVALID_MATRIX, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH, * or %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * Since: 1.0
**/
cairo_status_t
cairo_pattern_status (cairo_pattern_t *pattern)
{ return pattern->status;
}
/** * cairo_pattern_destroy: * @pattern: a #cairo_pattern_t * * Decreases the reference count on @pattern by one. If the result is * zero, then @pattern and all associated resources are freed. See * cairo_pattern_reference(). * * Since: 1.0
**/ void
cairo_pattern_destroy (cairo_pattern_t *pattern)
{
cairo_pattern_type_t type;
if (pattern == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count)) return;
if (! _cairo_reference_count_dec_and_test (&pattern->ref_count)) return;
type = pattern->type;
_cairo_pattern_fini (pattern);
/* maintain a small cache of freed patterns */ if (type < ARRAY_LENGTH (freed_pattern_pool))
_freed_pool_put (&freed_pattern_pool[type], pattern); else
free (pattern);
}
/** * cairo_pattern_get_reference_count: * @pattern: a #cairo_pattern_t * * Returns the current reference count of @pattern. * * Return value: the current reference count of @pattern. If the * object is a nil object, 0 will be returned. * * Since: 1.4
**/ unsignedint
cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
{ if (pattern == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count)) return 0;
/** * cairo_pattern_get_user_data: * @pattern: a #cairo_pattern_t * @key: the address of the #cairo_user_data_key_t the user data was * attached to * * Return user data previously attached to @pattern using the * specified key. If no user data has been attached with the given * key this function returns %NULL. * * Return value: the user data previously attached or %NULL. * * Since: 1.4
**/ void *
cairo_pattern_get_user_data (cairo_pattern_t *pattern, const cairo_user_data_key_t *key)
{ return _cairo_user_data_array_get_data (&pattern->user_data,
key);
}
/** * cairo_pattern_set_user_data: * @pattern: a #cairo_pattern_t * @key: the address of a #cairo_user_data_key_t to attach the user data to * @user_data: the user data to attach to the #cairo_pattern_t * @destroy: a #cairo_destroy_func_t which will be called when the * #cairo_t is destroyed or when new user data is attached using the * same key. * * Attach user data to @pattern. To remove user data from a surface, * call this function with the key that was used to set it and %NULL * for @data. * * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a * slot could not be allocated for the user data. * * Since: 1.4
**/
cairo_status_t
cairo_pattern_set_user_data (cairo_pattern_t *pattern, const cairo_user_data_key_t *key, void *user_data,
cairo_destroy_func_t destroy)
{ if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count)) return pattern->status;
/** * cairo_mesh_pattern_begin_patch: * @pattern: a #cairo_pattern_t * * Begin a patch in a mesh pattern. * * After calling this function, the patch shape should be defined with * cairo_mesh_pattern_move_to(), cairo_mesh_pattern_line_to() and * cairo_mesh_pattern_curve_to(). * * After defining the patch, cairo_mesh_pattern_end_patch() must be * called before using @pattern as a source or mask. * * Note: If @pattern is not a mesh pattern then @pattern will be put * into an error status with a status of * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern already has a * current patch, it will be put into an error status with a status of * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * Since: 1.12
**/ void
cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern)
{
cairo_mesh_pattern_t *mesh;
cairo_status_t status;
cairo_mesh_patch_t *current_patch; int i;
status = _cairo_array_allocate (&mesh->patches, 1, (void **) ¤t_patch); if (unlikely (status)) {
_cairo_pattern_set_error (pattern, status); return;
}
mesh->current_patch = current_patch;
mesh->current_side = -2; /* no current point */
for (i = 0; i < 4; i++)
mesh->has_control_point[i] = FALSE;
for (i = 0; i < 4; i++)
mesh->has_color[i] = FALSE;
}
staticvoid
_calc_control_point (cairo_mesh_patch_t *patch, int control_point)
{ /* The Coons patch is a special case of the Tensor Product patch * where the four control points are: * * P11 = S(1/3, 1/3) * P12 = S(1/3, 2/3) * P21 = S(2/3, 1/3) * P22 = S(2/3, 2/3) * * where S is the gradient surface. * * When one or more control points has not been specified * calculated the Coons patch control points are substituted. If * no control points are specified the gradient will be a Coons * patch. * * The equations below are defined in the ISO32000 standard.
*/
cairo_point_double_t *p[3][3]; int cp_i, cp_j, i, j;
/** * cairo_mesh_pattern_end_patch: * @pattern: a #cairo_pattern_t * * Indicates the end of the current patch in a mesh pattern. * * If the current patch has less than 4 sides, it is closed with a * straight line from the current point to the first point of the * patch as if cairo_mesh_pattern_line_to() was used. * * Note: If @pattern is not a mesh pattern then @pattern will be put * into an error status with a status of * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current * patch or the current patch has no current point, @pattern will be * put into an error status with a status of * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * Since: 1.12
**/ void
cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern)
{
cairo_mesh_pattern_t *mesh;
cairo_mesh_patch_t *current_patch; int i;
for (i = 0; i < 4; i++) { if (! mesh->has_control_point[i])
_calc_control_point (current_patch, i);
}
for (i = 0; i < 4; i++) { if (! mesh->has_color[i])
current_patch->colors[i] = *CAIRO_COLOR_TRANSPARENT;
}
mesh->current_patch = NULL;
}
/** * cairo_mesh_pattern_curve_to: * @pattern: a #cairo_pattern_t * @x1: the X coordinate of the first control point * @y1: the Y coordinate of the first control point * @x2: the X coordinate of the second control point * @y2: the Y coordinate of the second control point * @x3: the X coordinate of the end of the curve * @y3: the Y coordinate of the end of the curve * * Adds a cubic Bézier spline to the current patch from the current * point to position (@x3, @y3) in pattern-space coordinates, using * (@x1, @y1) and (@x2, @y2) as the control points. * * If the current patch has no current point before the call to * cairo_mesh_pattern_curve_to(), this function will behave as if * preceded by a call to cairo_mesh_pattern_move_to(@pattern, @x1, * @y1). * * After this call the current point will be (@x3, @y3). * * Note: If @pattern is not a mesh pattern then @pattern will be put * into an error status with a status of * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current * patch or the current patch already has 4 sides, @pattern will be * put into an error status with a status of * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * Since: 1.12
**/ void
cairo_mesh_pattern_curve_to (cairo_pattern_t *pattern, double x1, double y1, double x2, double y2, double x3, double y3)
{
cairo_mesh_pattern_t *mesh; int current_point, i, j;
current_point++; if (current_point < 12) {
i = mesh_path_point_i[current_point];
j = mesh_path_point_j[current_point];
mesh->current_patch->points[i][j].x = x3;
mesh->current_patch->points[i][j].y = y3;
}
}
/** * cairo_mesh_pattern_line_to: * @pattern: a #cairo_pattern_t * @x: the X coordinate of the end of the new line * @y: the Y coordinate of the end of the new line * * Adds a line to the current patch from the current point to position * (@x, @y) in pattern-space coordinates. * * If there is no current point before the call to * cairo_mesh_pattern_line_to() this function will behave as * cairo_mesh_pattern_move_to(@pattern, @x, @y). * * After this call the current point will be (@x, @y). * * Note: If @pattern is not a mesh pattern then @pattern will be put * into an error status with a status of * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current * patch or the current patch already has 4 sides, @pattern will be * put into an error status with a status of * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * Since: 1.12
**/ void
cairo_mesh_pattern_line_to (cairo_pattern_t *pattern, double x, double y)
{
cairo_mesh_pattern_t *mesh;
cairo_point_double_t last_point; int last_point_idx, i, j;
/** * cairo_mesh_pattern_move_to: * @pattern: a #cairo_pattern_t * @x: the X coordinate of the new position * @y: the Y coordinate of the new position * * Define the first point of the current patch in a mesh pattern. * * After this call the current point will be (@x, @y). * * Note: If @pattern is not a mesh pattern then @pattern will be put * into an error status with a status of * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current * patch or the current patch already has at least one side, @pattern * will be put into an error status with a status of * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * Since: 1.12
**/ void
cairo_mesh_pattern_move_to (cairo_pattern_t *pattern, double x, double y)
{
cairo_mesh_pattern_t *mesh;
/** * cairo_mesh_pattern_set_control_point: * @pattern: a #cairo_pattern_t * @point_num: the control point to set the position for * @x: the X coordinate of the control point * @y: the Y coordinate of the control point * * Set an internal control point of the current patch. * * Valid values for @point_num are from 0 to 3 and identify the * control points as explained in cairo_pattern_create_mesh(). * * Note: If @pattern is not a mesh pattern then @pattern will be put * into an error status with a status of * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @point_num is not valid, * @pattern will be put into an error status with a status of * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch, * @pattern will be put into an error status with a status of * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * Since: 1.12
**/ void
cairo_mesh_pattern_set_control_point (cairo_pattern_t *pattern, unsignedint point_num, double x, double y)
{
cairo_mesh_pattern_t *mesh; int i, j;
/* make room for at least one more color stop */ static cairo_status_t
_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
{
cairo_gradient_stop_t *new_stops; int old_size = pattern->stops_size; int embedded_size = ARRAY_LENGTH (pattern->stops_embedded); int new_size = 2 * MAX (old_size, 4);
/* we have a local buffer at pattern->stops_embedded. try to fulfill the request
* from there. */ if (old_size < embedded_size) {
pattern->stops = pattern->stops_embedded;
pattern->stops_size = embedded_size; return CAIRO_STATUS_SUCCESS;
}
if (CAIRO_INJECT_FAULT ()) return _cairo_error (CAIRO_STATUS_NO_MEMORY);
/** * cairo_mesh_pattern_set_corner_color_rgb: * @pattern: a #cairo_pattern_t * @corner_num: the corner to set the color for * @red: red component of color * @green: green component of color * @blue: blue component of color * * Sets the color of a corner of the current patch in a mesh pattern. * * The color is specified in the same way as in cairo_set_source_rgb(). * * Valid values for @corner_num are from 0 to 3 and identify the * corners as explained in cairo_pattern_create_mesh(). * * Note: If @pattern is not a mesh pattern then @pattern will be put * into an error status with a status of * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid, * @pattern will be put into an error status with a status of * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch, * @pattern will be put into an error status with a status of * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * Since: 1.12
**/ void
cairo_mesh_pattern_set_corner_color_rgb (cairo_pattern_t *pattern, unsignedint corner_num, double red, double green, double blue)
{
cairo_mesh_pattern_set_corner_color_rgba (pattern, corner_num, red, green, blue, 1.0);
}
/** * cairo_mesh_pattern_set_corner_color_rgba: * @pattern: a #cairo_pattern_t * @corner_num: the corner to set the color for * @red: red component of color * @green: green component of color * @blue: blue component of color * @alpha: alpha component of color * * Sets the color of a corner of the current patch in a mesh pattern. * * The color is specified in the same way as in cairo_set_source_rgba(). * * Valid values for @corner_num are from 0 to 3 and identify the * corners as explained in cairo_pattern_create_mesh(). * * Note: If @pattern is not a mesh pattern then @pattern will be put * into an error status with a status of * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid, * @pattern will be put into an error status with a status of * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch, * @pattern will be put into an error status with a status of * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION. * * Since: 1.12
**/ void
cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern, unsignedint corner_num, double red, double green, double blue, double alpha)
{
cairo_mesh_pattern_t *mesh;
/** * cairo_pattern_add_color_stop_rgb: * @pattern: a #cairo_pattern_t * @offset: an offset in the range [0.0 .. 1.0] * @red: red component of color * @green: green component of color * @blue: blue component of color * * Adds an opaque color stop to a gradient pattern. The offset * specifies the location along the gradient's control vector. For * example, a linear gradient's control vector is from (x0,y0) to * (x1,y1) while a radial gradient's control vector is from any point * on the start circle to the corresponding point on the end circle. * * The color is specified in the same way as in cairo_set_source_rgb(). * * If two (or more) stops are specified with identical offset values, * they will be sorted according to the order in which the stops are * added, (stops added earlier will compare less than stops added * later). This can be useful for reliably making sharp color * transitions instead of the typical blend. * * * Note: If the pattern is not a gradient pattern, (eg. a linear or * radial pattern), then the pattern will be put into an error status * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. * * Since: 1.0
**/ void
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, double offset, double red, double green, double blue)
{
cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, 1.0);
}
/** * cairo_pattern_add_color_stop_rgba: * @pattern: a #cairo_pattern_t * @offset: an offset in the range [0.0 .. 1.0] * @red: red component of color * @green: green component of color * @blue: blue component of color * @alpha: alpha component of color * * Adds a translucent color stop to a gradient pattern. The offset * specifies the location along the gradient's control vector. For * example, a linear gradient's control vector is from (x0,y0) to * (x1,y1) while a radial gradient's control vector is from any point * on the start circle to the corresponding point on the end circle. * * The color is specified in the same way as in cairo_set_source_rgba(). * * If two (or more) stops are specified with identical offset values, * they will be sorted according to the order in which the stops are * added, (stops added earlier will compare less than stops added * later). This can be useful for reliably making sharp color * transitions instead of the typical blend. * * Note: If the pattern is not a gradient pattern, (eg. a linear or * radial pattern), then the pattern will be put into an error status * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. * * Since: 1.0
**/ void
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, double offset, double red, double green, double blue, double alpha)
{ if (pattern->status) return;
/** * cairo_pattern_set_matrix: * @pattern: a #cairo_pattern_t * @matrix: a #cairo_matrix_t * * Sets the pattern's transformation matrix to @matrix. This matrix is * a transformation from user space to pattern space. * * When a pattern is first created it always has the identity matrix * for its transformation matrix, which means that pattern space is * initially identical to user space. * * Important: Please note that the direction of this transformation * matrix is from user space to pattern space. This means that if you * imagine the flow from a pattern to user space (and on to device * space), then coordinates in that flow will be transformed by the * inverse of the pattern matrix. * * For example, if you want to make a pattern appear twice as large as * it does by default the correct code to use is: * * <informalexample><programlisting> * cairo_matrix_init_scale (&matrix, 0.5, 0.5); * cairo_pattern_set_matrix (pattern, &matrix); * </programlisting></informalexample> * * Meanwhile, using values of 2.0 rather than 0.5 in the code above * would cause the pattern to appear at half of its default size. * * Also, please note the discussion of the user-space locking * semantics of cairo_set_source(). * * Since: 1.0
**/ void
cairo_pattern_set_matrix (cairo_pattern_t *pattern, const cairo_matrix_t *matrix)
{
cairo_matrix_t inverse;
cairo_status_t status;
if (pattern->status) return;
if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0) return;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.