📄 cairo-pattern.c
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2004 David Reveman * Copyright © 2005 Red Hat, 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 David * Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior * permission. David Reveman makes no representations about the * suitability of this software for any purpose. It is provided "as * is" without express or implied warranty. * * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS, IN NO EVENT SHALL DAVID REVEMAN 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. * * Authors: David Reveman <davidr@novell.com> * Keith Packard <keithp@keithp.com> * Carl Worth <cworth@cworth.org> */#include "cairoint.h"const cairo_solid_pattern_t cairo_pattern_nil = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ (unsigned int)-1, /* ref_count */ CAIRO_STATUS_NO_MEMORY, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */};static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ (unsigned int)-1, /* ref_count */ CAIRO_STATUS_NULL_POINTER,/* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */};static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ (unsigned int)-1, /* ref_count */ CAIRO_STATUS_FILE_NOT_FOUND, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */};static const cairo_solid_pattern_t cairo_pattern_nil_read_error = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ (unsigned int)-1, /* ref_count */ CAIRO_STATUS_READ_ERROR, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */};static const cairo_pattern_t *_cairo_pattern_nil_for_status (cairo_status_t status){ switch (status) { case CAIRO_STATUS_NULL_POINTER: return &cairo_pattern_nil_null_pointer.base; case CAIRO_STATUS_FILE_NOT_FOUND: return &cairo_pattern_nil_file_not_found.base; case CAIRO_STATUS_READ_ERROR: return &cairo_pattern_nil_read_error.base; default: case CAIRO_STATUS_NO_MEMORY: return &cairo_pattern_nil.base; }}/** * _cairo_pattern_set_error: * @pattern: a pattern * @status: a status value indicating an error, (eg. not * CAIRO_STATUS_SUCCESS) * * Sets pattern->status to @status and calls _cairo_error; * * All assignments of an error status to pattern->status should happen * through _cairo_pattern_set_error() or else _cairo_error() should be * called immediately after the assignment. * * 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 void_cairo_pattern_set_error (cairo_pattern_t *pattern, cairo_status_t status){ /* Don't overwrite an existing error. This preserves the first * error, which is the most significant. It also avoids attempting * to write to read-only data (eg. from a nil pattern). */ if (pattern->status == CAIRO_STATUS_SUCCESS) pattern->status = status; _cairo_error (status);}static void_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type){ pattern->type = type; pattern->ref_count = 1; pattern->status = CAIRO_STATUS_SUCCESS; if (type == CAIRO_PATTERN_TYPE_SURFACE) pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT; else pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT; pattern->filter = CAIRO_FILTER_DEFAULT; cairo_matrix_init_identity (&pattern->matrix);}static void_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern, const cairo_gradient_pattern_t *other){ if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR) { cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern; cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other; *dst = *src; } else { cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern; cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other; *dst = *src; } if (other->n_stops) { pattern->stops = malloc (other->n_stops * sizeof (pixman_gradient_stop_t)); if (pattern->stops == NULL) { _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY); return; } memcpy (pattern->stops, other->stops, other->n_stops * sizeof (pixman_gradient_stop_t)); }}void_cairo_pattern_init_copy (cairo_pattern_t *pattern, const cairo_pattern_t *other){ if (other->status) { _cairo_pattern_set_error (pattern, other->status); return; } switch (other->type) { case CAIRO_PATTERN_TYPE_SOLID: { cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern; cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other; *dst = *src; } break; case CAIRO_PATTERN_TYPE_SURFACE: { cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern; cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other; *dst = *src; cairo_surface_reference (dst->surface); } break; case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: { cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern; cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other; _cairo_gradient_pattern_init_copy (dst, src); } break; } pattern->ref_count = 1;}void_cairo_pattern_fini (cairo_pattern_t *pattern){ switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: break; case CAIRO_PATTERN_TYPE_SURFACE: { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; cairo_surface_destroy (surface_pattern->surface); } break; case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: { cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; if (gradient->stops) free (gradient->stops); } break; }}void_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, const cairo_color_t *color){ _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID); pattern->color = *color;}void_cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern, cairo_surface_t *surface){ if (surface->status) { /* Force to solid to simplify the pattern_fini process. */ pattern->base.type = CAIRO_PATTERN_TYPE_SOLID; _cairo_pattern_set_error (&pattern->base, surface->status); return; } _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE); pattern->surface = cairo_surface_reference (surface);}static void_cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern, cairo_pattern_type_t type){ _cairo_pattern_init (&pattern->base, type); pattern->stops = NULL; pattern->n_stops = 0;}void_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern, double x0, double y0, double x1, double y1){ _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR); pattern->gradient.p1.x = _cairo_fixed_from_double (x0); pattern->gradient.p1.y = _cairo_fixed_from_double (y0); pattern->gradient.p2.x = _cairo_fixed_from_double (x1); pattern->gradient.p2.y = _cairo_fixed_from_double (y1);}void_cairo_pattern_init_radial (cairo_radial_pattern_t *pattern, double cx0, double cy0, double radius0, double cx1, double cy1, double radius1){ _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL); pattern->gradient.inner.x = _cairo_fixed_from_double (cx0); pattern->gradient.inner.y = _cairo_fixed_from_double (cy0); pattern->gradient.inner.radius = _cairo_fixed_from_double (fabs (radius0)); pattern->gradient.outer.x = _cairo_fixed_from_double (cx1); pattern->gradient.outer.y = _cairo_fixed_from_double (cy1); pattern->gradient.outer.radius = _cairo_fixed_from_double (fabs (radius1));}cairo_pattern_t *_cairo_pattern_create_solid (const cairo_color_t *color){ cairo_solid_pattern_t *pattern; pattern = malloc (sizeof (cairo_solid_pattern_t)); if (pattern == NULL) return (cairo_pattern_t *) &cairo_pattern_nil.base; _cairo_pattern_init_solid (pattern, color); return &pattern->base;}/** * 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 succesful, 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(). **/cairo_pattern_t *cairo_pattern_create_rgb (double red, double green, double blue){ cairo_pattern_t *pattern; cairo_color_t color; _cairo_restrict_value (&red, 0.0, 1.0); _cairo_restrict_value (&green, 0.0, 1.0); _cairo_restrict_value (&blue, 0.0, 1.0); _cairo_color_init_rgb (&color, red, green, blue); pattern = _cairo_pattern_create_solid (&color); if (pattern->status) _cairo_error (pattern->status); return pattern;}/** * 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. * * Return value: the newly created #cairo_pattern_t if succesful, 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(). **/cairo_pattern_t *cairo_pattern_create_rgba (double red, double green, double blue, double alpha){ cairo_pattern_t *pattern; cairo_color_t color; _cairo_restrict_value (&red, 0.0, 1.0); _cairo_restrict_value (&green, 0.0, 1.0); _cairo_restrict_value (&blue, 0.0, 1.0); _cairo_restrict_value (&alpha, 0.0, 1.0); _cairo_color_init_rgba (&color, red, green, blue, alpha); pattern = _cairo_pattern_create_solid (&color); if (pattern->status) _cairo_error (pattern->status); return pattern;}/** * 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 succesful, 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(). **/cairo_pattern_t *cairo_pattern_create_for_surface (cairo_surface_t *surface){ cairo_surface_pattern_t *pattern; if (surface == NULL) return (cairo_pattern_t*) _cairo_pattern_nil_for_status (CAIRO_STATUS_NULL_POINTER); if (surface->status) return (cairo_pattern_t*) _cairo_pattern_nil_for_status (surface->status); pattern = malloc (sizeof (cairo_surface_pattern_t)); if (pattern == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *)&cairo_pattern_nil.base; } _cairo_pattern_init_for_surface (pattern, surface); return &pattern->base;}/** * 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 succesful, 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(). **/cairo_pattern_t *cairo_pattern_create_linear (double x0, double y0, double x1, double y1){ cairo_linear_pattern_t *pattern; pattern = malloc (sizeof (cairo_linear_pattern_t)); if (pattern == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *) &cairo_pattern_nil.base; } _cairo_pattern_init_linear (pattern, x0, y0, x1, y1); return &pattern->base.base;}/** * 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 * @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 * * Creates a new radial gradient cairo_pattern_t between the two * circles defined by (x0, y0, c0) and (x1, y1, c0). 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 succesful, 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(). **/cairo_pattern_t *cairo_pattern_create_radial (double cx0, double cy0, double radius0, double cx1, double cy1, double radius1){ cairo_radial_pattern_t *pattern;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -