⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-pattern.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 3 页
字号:
    pattern = malloc (sizeof (cairo_radial_pattern_t));    if (pattern == NULL) {	_cairo_error (CAIRO_STATUS_NO_MEMORY);	return (cairo_pattern_t *) &cairo_pattern_nil.base;    }    _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);    return &pattern->base.base;}/** * 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. * * Return value: the referenced #cairo_pattern_t. **/cairo_pattern_t *cairo_pattern_reference (cairo_pattern_t *pattern){    if (pattern == NULL)	return NULL;    if (pattern->ref_count == (unsigned int)-1)	return pattern;    assert (pattern->ref_count > 0);    pattern->ref_count++;    return pattern;}/** * cairo_pattern_get_type: * @pattern: a #cairo_pattern_t * * Return value: The type of @pattern. See #cairo_pattern_type_t. * * Since: 1.2 **/cairo_pattern_type_tcairo_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, or * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. **/cairo_status_tcairo_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(). **/voidcairo_pattern_destroy (cairo_pattern_t *pattern){    if (pattern == NULL)	return;    if (pattern->ref_count == (unsigned int)-1)	return;    assert (pattern->ref_count > 0);    pattern->ref_count--;    if (pattern->ref_count)	return;    _cairo_pattern_fini (pattern);    free (pattern);}static void_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,			       double			 offset,			       double			 red,			       double			 green,			       double			 blue,			       double			 alpha){    pixman_gradient_stop_t *new_stops;    cairo_fixed_t	   x;    int			   i;    new_stops = realloc (pattern->stops, (pattern->n_stops + 1) *			 sizeof (pixman_gradient_stop_t));    if (new_stops == NULL)    {	_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);	return;    }    pattern->stops = new_stops;    x = _cairo_fixed_from_double (offset);    for (i = 0; i < pattern->n_stops; i++)    {	if (x < new_stops[i].x)	{	    memmove (&new_stops[i + 1], &new_stops[i],		     sizeof (pixman_gradient_stop_t) * (pattern->n_stops - i));	    break;	}    }    new_stops[i].x = x;    new_stops[i].color.red   = red   * 65535.0;    new_stops[i].color.green = green * 65535.0;    new_stops[i].color.blue  = blue  * 65535.0;    new_stops[i].color.alpha = alpha * 65535.0;    pattern->n_stops++;}/** * 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(). * * 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. **/voidcairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,				  double	   offset,				  double	   red,				  double	   green,				  double	   blue){    if (pattern->status)	return;    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)    {	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);	return;    }    _cairo_restrict_value (&offset, 0.0, 1.0);    _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_pattern_add_color_stop ((cairo_gradient_pattern_t *) 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(). * * 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. */voidcairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,				   double	   offset,				   double	   red,				   double	   green,				   double	   blue,				   double	   alpha){    if (pattern->status)	return;    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)    {	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);	return;    }    _cairo_restrict_value (&offset, 0.0, 1.0);    _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_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,				   offset, red, green, blue, alpha);}/** * 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 (&amp;matrix, 0.5, 0.5); * cairo_pattern_set_matrix (pattern, &amp;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(). **/voidcairo_pattern_set_matrix (cairo_pattern_t      *pattern,			  const cairo_matrix_t *matrix){    if (pattern->status)	return;    pattern->matrix = *matrix;}/** * cairo_pattern_get_matrix: * @pattern: a #cairo_pattern_t * @matrix: return value for the matrix * * Stores the pattern's transformation matrix into @matrix. **/voidcairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix){    *matrix = pattern->matrix;}voidcairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter){    if (pattern->status)	return;    pattern->filter = filter;}cairo_filter_tcairo_pattern_get_filter (cairo_pattern_t *pattern){    return pattern->filter;}/** * cairo_pattern_set_extend: * @pattern: a #cairo_pattern_t * @extend: a #cairo_extend_t describing how the area outside of the * pattern will be drawn * * Sets the mode to be used for drawing outside the area of a pattern. * See #cairo_extend_t for details on the semantics of each extend * strategy. **/voidcairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend){    if (pattern->status)	return;    pattern->extend = extend;}/** * cairo_pattern_get_extend: * @pattern: a #cairo_pattern_t * * Gets the current extend mode for a pattern.  See #cairo_extend_t * for details on the semantics of each extend strategy. * * Return value: the current extend strategy used for drawing the * pattern. **/cairo_extend_tcairo_pattern_get_extend (cairo_pattern_t *pattern){    return pattern->extend;}void_cairo_pattern_transform (cairo_pattern_t	*pattern,			  const cairo_matrix_t  *ctm_inverse){    assert (pattern->status == CAIRO_STATUS_SUCCESS);    cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);}static void_cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,				double		       offset_x,				double		       offset_y,				int		       width,				int		       height,				cairo_bool_t           *is_horizontal,				cairo_bool_t           *is_vertical){    cairo_point_double_t point0, point1;    double a, b, c, d, tx, ty;    double scale, start, dx, dy;    cairo_fixed_t factors[3];    int i;    /* To classidy a pattern as horizontal or vertical, we first     * compute the (fixed point) factors at the corners of the     * pattern. We actually only need 3/4 corners, so we skip the     * fourth.     */    point0.x = _cairo_fixed_to_double (pattern->gradient.p1.x);    point0.y = _cairo_fixed_to_double (pattern->gradient.p1.y);    point1.x = _cairo_fixed_to_double (pattern->gradient.p2.x);    point1.y = _cairo_fixed_to_double (pattern->gradient.p2.y);    _cairo_matrix_get_affine (&pattern->base.base.matrix,			      &a, &b, &c, &d, &tx, &ty);    dx = point1.x - point0.x;    dy = point1.y - point0.y;    scale = dx * dx + dy * dy;    scale = (scale) ? 1.0 / scale : 1.0;    start = dx * point0.x + dy * point0.y;    for (i = 0; i < 3; i++) {	double qx_device = (i % 2) * (width - 1) + offset_x;	double qy_device = (i / 2) * (height - 1) + offset_y;	/* transform fragment into pattern space */	double qx = a * qx_device + c * qy_device + tx;	double qy = b * qx_device + d * qy_device + ty;	factors[i] = _cairo_fixed_from_double (((dx * qx + dy * qy) - start) * scale);    }    /* We consider a pattern to be vertical if the fixed point factor     * at the two upper corners is the same. We could accept a small     * change, but determining what change is acceptable would require     * sorting the stops in the pattern and looking at the differences.     *     * Horizontal works the same way with the two left corners.     */    *is_vertical = factors[1] == factors[0];    *is_horizontal = factors[2] == factors[0];}static cairo_int_status_t_cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,					     cairo_surface_t	        *dst,					     int			x,					     int			y,					     unsigned int		width,					     unsigned int	        height,					     cairo_surface_t	        **out,					     cairo_surface_attributes_t *attr){    cairo_image_surface_t *image;    pixman_image_t	  *pixman_image;    pixman_transform_t	  pixman_transform;    cairo_status_t	  status;    cairo_bool_t	  repeat = FALSE;    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR)    {	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;	pixman_image = pixman_image_create_linear_gradient (&linear->gradient,							    pattern->stops,							    pattern->n_stops);    }    else    {	cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;	pixman_image = pixman_image_create_radial_gradient (&radial->gradient,							    pattern->stops,							    pattern->n_stops);    }    if (pixman_image == NULL)	return CAIRO_STATUS_NO_MEMORY;    if (_cairo_surface_is_image (dst))    {	image = (cairo_image_surface_t *)	    _cairo_image_surface_create_for_pixman_image (pixman_image,							  CAIRO_FORMAT_ARGB32);	if (image->base.status)	{	    pixman_image_destroy (pixman_image);	    return CAIRO_STATUS_NO_MEMORY;	}	attr->x_offset = attr->y_offset = 0;	attr->matrix = pattern->base.matrix;	attr->extend = pattern->base.extend;	attr->filter = CAIRO_FILTER_NEAREST;	attr->acquired = FALSE;	*out = &image->base;	return CAIRO_STATUS_SUCCESS;    }    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {	cairo_bool_t is_horizontal;	cairo_bool_t is_vertical;	_cairo_linear_pattern_classify ((cairo_linear_pattern_t *)pattern,					x, y, width, height,					&is_horizontal, &is_vertical);	if (is_horizontal) {	    height = 1;	    repeat = TRUE;	}	/* width-1 repeating patterns are quite slow with scan-line based	 * compositing code, so we use a wider strip and spend some extra	 * expense in computing the gradient. It's possible that for narrow	 * gradients we'd be better off using a 2 or 4 pixel strip; the	 * wider the gradient, the more it's worth spending extra time	 * computing a sample.	 */	if (is_vertical && width > 8) {	    width = 8;	    repeat = TRUE;	}    }    image = (cairo_image_surface_t *)	cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -