Added new pattern API

This commit is contained in:
David Reveman 2004-04-06 09:36:12 +00:00
parent b17b04aa38
commit e309090d2a
24 changed files with 1339 additions and 530 deletions

View file

@ -1,3 +1,85 @@
2004-04-04 David Reveman <c99drn@cs.umu.se>
* src/cairoint.h: Added create_pattern backend function and pattern
prototypes.
* src/cairo_xlib_surface.c: Added _cairo_xlib_surface_create_pattern.
* src/cairo_xcb_surface.c: Added _cairo_xcb_surface_create_pattern.
* src/cairo_traps.c: Added _cairo_trap_extents and
_cairo_traps_extents.
* src/cairo_surface.c: Added _cairo_surface_create_pattern.
* src/cairo_ps_surface.c: Added _cairo_ps_surface_create_pattern.
* src/cairo_png_surface.c: Added _cairo_png_surface_create_pattern.
* src/cairo_pattern.c (added): All functions needed for the new
pattern API.
* src/cairo_image_surface.c: Added
_cairo_image_abstract_surface_create_pattern.
* src/cairo_gstate.c (_cairo_gstate_init): Create solid pattern
and set alpha to 0.0.
(_cairo_gstate_init_copy): Increment pattern references.
(_cairo_gstate_fini): Destroy pattern.
(_cairo_gstate_set_pattern): Destroy current pattern,
increment references to the new pattern and update pattern
offset with the current point.
(_cairo_gstate_set_rgb_color): Destroy current pattern and
create a new solid pattern.
(_cairo_gstate_current_rgb_color): Get RGB from current pattern.
(_cairo_gstate_set_alpha): Set gstate->alpha without modifying
the current pattern.
(_cairo_gstate_stroke):
(_cairo_gstate_fill): Removed surface matrix computations as
they are now handled by _cairo_gstate_create_pattern.
(_cairo_gstate_clip_and_composite_trapezoids): Create a
possibly backend accelerated pattern source and use it for
compositing trapezoids.
(_cairo_gstate_clip): Allow backends to not support rectangular
clipping regions. Use solid pattern for creating clip surface.
(_cairo_gstate_show_surface): Use solid pattern for alpha mask.
(_cairo_gstate_show_text):
(_cairo_gstate_show_glyphs): Use current pattern when compositing
glyphs.
Added _cairo_gstate_current_pattern and _cairo_gstate_create_pattern,
_cairo_gstate_stroke_extents, _cairo_gstate_fill_extents.
Removed restore_text_rendering_context, setup_text_rendering_context,
_cairo_gstate_ensure_source.
* src/cairo_ft_font.c (_cairo_ft_font_show_glyphs): Advance
source offset.
* src/cairo.h: Added cairo_current_pattern,
cairo_pattern_create_for_surface, cairo_pattern_create_linear,
cairo_pattern_create_radial, cairo_pattern_reference,
cairo_pattern_destroy, cairo_pattern_add_color_stop,
cairo_pattern_set_matrix, cairo_pattern_get_matrix,
cairo_pattern_set_extend, cairo_pattern_get_extend,
cairo_pattern_set_filter, cairo_pattern_get_filter. cairo_set_pattern
now takes a cairo_pattern_t pointer instead of a cairo_surface_t
pointer. Added CAIRO_FILTER_GAUSSIAN filter type. Added cairo_extend_t
enum.
* src/cairo.c: _cairo_restrict_value declared not static as it's
used in cairo_pattern.c. Added rectangular extents functions
cairo_stroke_extents and cairo_fill_extents. cairo_set_pattern now
takes a cairo_pattern_t pointer instead of a cairo_surface_t
pointer. Added cairo_current_pattern function.
* src/Makefile.am (libcairo_la_LIBADD): Removed -lz and added PS_LIBS.
* configure.in: Bump version to 0.1.20. Includes new pattern
API. Removed an extra AC_SUBST(XRENDER_LIBS).
PS_SURFACE_LIBS -> PS_LIBS.
* cairo.pc.in: PS_SURFACE_LIBS -> PS_LIBS.
2004-04-02 Carl Worth <cworth@east.isi.edu>
* src/cairo.h: Move weight after slant to match the order in

View file

@ -8,6 +8,6 @@ Description: Multi-platform 2D graphics library
Version: @VERSION@
Requires: fontconfig libpixman @XRENDER_REQUIRES@ @PNG_REQUIRES@
Libs: -L${libdir} -lcairo -lm @PS_SURFACE_LIBS@ @FREETYPE_LIBS@ @XRENDER_LIBS@
Libs: -L${libdir} -lcairo -lm @XRENDER_LIBS@ @PS_LIBS@ @FREETYPE_LIBS@
Cflags: -I${includedir} @FREETYPE_CFLAGS@

View file

@ -3,7 +3,7 @@ AC_INIT(src/cairo.h)
dnl ===========================================================================
# Package version number, (as distinct from shared library version)
CAIRO_VERSION=0.1.19
CAIRO_VERSION=0.1.20
# libtool shared library version
@ -59,7 +59,6 @@ AC_SUBST(XLIB_SURFACE_FEATURE)
AC_SUBST(XRENDER_CFLAGS)
AC_SUBST(XRENDER_LIBS)
AC_SUBST(XRENDER_REQUIRES)
AC_SUBST(XRENDER_LIBS)
dnl ===========================================================================
@ -91,12 +90,12 @@ if test "x$use_ps" != "xyes"; then
AM_CONDITIONAL(CAIRO_HAS_PS_SURFACE, false)
else
PS_SURFACE_FEATURE=CAIRO_HAS_PS_SURFACE
PS_SURFACE_LIBS=-lz
PS_LIBS=-lz
AM_CONDITIONAL(CAIRO_HAS_PS_SURFACE, true)
fi
AC_SUBST(PS_SURFACE_LIBS)
AC_SUBST(PS_SURFACE_FEATURE)
AC_SUBST(PS_LIBS)
dnl ===========================================================================

View file

@ -45,6 +45,7 @@ libcairo_la_SOURCES = \
cairo_spline.c \
cairo_surface.c \
cairo_traps.c \
cairo_pattern.c \
$(libcairo_ps_sources) \
$(libcairo_png_sources) \
$(libcairo_xlib_sources)\
@ -55,5 +56,4 @@ libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined
INCLUDES = -I$(srcdir) $(CAIRO_CFLAGS) $(FONTCONFIG_CFLAGS) $(XRENDER_CFLAGS) $(XCB_CFLAGS) $(PNG_CFLAGS)
libcairo_la_LIBADD = $(CAIRO_LIBS) $(FONTCONFIG_LIBS) $(XRENDER_LIBS) $(XCB_LIBS) $(PNG_LIBS) -lm -lz
libcairo_la_LIBADD = $(CAIRO_LIBS) $(FONTCONFIG_LIBS) $(XRENDER_LIBS) $(XCB_LIBS) $(PS_LIBS) $(PNG_LIBS) -lm

View file

@ -477,6 +477,7 @@ _cairo_ft_font_show_glyphs (void *abstract_font,
cairo_ft_font_t *ft = NULL;
FT_GlyphSlot glyphslot;
cairo_surface_t *mask = NULL;
cairo_point_double_t origin;
double x, y;
int width, height, stride;
@ -504,7 +505,12 @@ _cairo_ft_font_show_glyphs (void *abstract_font,
bitmap = glyphslot->bitmap.buffer;
x = glyphs[i].x;
y = glyphs[i].y;
y = glyphs[i].y;
if (i == 0) {
origin.x = x;
origin.y = y;
}
/* X gets upset with zero-sized images (such as whitespace) */
if (width * height == 0)
@ -547,11 +553,14 @@ _cairo_ft_font_show_glyphs (void *abstract_font,
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_surface_composite (operator, source, mask, surface,
0, 0, 0, 0,
x + glyphslot->bitmap_left,
y - glyphslot->bitmap_top,
(double)width, (double)height);
status =
_cairo_surface_composite (operator, source, mask, surface,
-origin.x + x + glyphslot->bitmap_left,
-origin.y + y - glyphslot->bitmap_top,
0, 0,
x + glyphslot->bitmap_left,
y - glyphslot->bitmap_top,
(double) width, (double) height);
cairo_surface_destroy (mask);
if (bitmap != glyphslot->bitmap.buffer)

View file

@ -30,12 +30,9 @@
#include "cairoint.h"
static cairo_status_t
_cairo_gstate_ensure_source (cairo_gstate_t *gstate);
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_t *src,
cairo_pattern_t *src,
cairo_operator_t operator,
cairo_surface_t *dst,
cairo_traps_t *traps);
@ -76,16 +73,14 @@ _cairo_gstate_init (cairo_gstate_t *gstate)
CAIRO_FONT_WEIGHT_DEFAULT);
gstate->surface = NULL;
gstate->source = NULL;
gstate->source_offset.x = 0.0;
gstate->source_offset.y = 0.0;
gstate->source_is_solid = 1;
gstate->clip.region = NULL;
gstate->clip.surface = NULL;
gstate->pattern = _cairo_pattern_create_solid (1.0, 1.0, 1.0);
gstate->pattern_offset.x = 0.0;
gstate->pattern_offset.y = 0.0;
gstate->alpha = 1.0;
_cairo_color_init (&gstate->color);
gstate->pixels_per_inch = CAIRO_GSTATE_PIXELS_PER_INCH_DEFAULT;
_cairo_gstate_default_matrix (gstate);
@ -131,8 +126,9 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
}
cairo_surface_reference (gstate->surface);
cairo_surface_reference (gstate->source);
cairo_surface_reference (gstate->clip.surface);
cairo_pattern_reference (gstate->pattern);
status = _cairo_path_init_copy (&gstate->path, &other->path);
if (status)
@ -164,11 +160,6 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_surface_destroy (gstate->surface);
gstate->surface = NULL;
if (gstate->source)
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_is_solid = 1;
if (gstate->clip.surface)
cairo_surface_destroy (gstate->clip.surface);
gstate->clip.surface = NULL;
@ -177,7 +168,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
pixman_region_destroy (gstate->clip.region);
gstate->clip.region = NULL;
_cairo_color_fini (&gstate->color);
cairo_pattern_destroy (gstate->pattern);
_cairo_matrix_fini (&gstate->ctm);
_cairo_matrix_fini (&gstate->ctm_inverse);
@ -362,22 +353,37 @@ _cairo_gstate_current_target_surface (cairo_gstate_t *gstate)
}
cairo_status_t
_cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_surface_t *pattern)
_cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_pattern_t *pattern)
{
cairo_surface_destroy (gstate->source);
if (pattern == NULL)
return CAIRO_STATUS_NULL_POINTER;
gstate->source = pattern;
gstate->source_is_solid = 0;
cairo_surface_reference (gstate->source);
if (gstate->pattern)
cairo_pattern_destroy (gstate->pattern);
gstate->pattern = pattern;
cairo_pattern_reference (pattern);
_cairo_gstate_current_point (gstate,
&gstate->source_offset.x,
&gstate->source_offset.y);
&gstate->pattern_offset.x,
&gstate->pattern_offset.y);
return CAIRO_STATUS_SUCCESS;
}
cairo_pattern_t *
_cairo_gstate_current_pattern (cairo_gstate_t *gstate)
{
if (gstate == NULL)
return NULL;
/* XXX: Do we want this?
cairo_pattern_reference (gstate->pattern);
*/
return gstate->pattern;
}
cairo_status_t
_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t operator)
{
@ -395,25 +401,19 @@ _cairo_gstate_current_operator (cairo_gstate_t *gstate)
cairo_status_t
_cairo_gstate_set_rgb_color (cairo_gstate_t *gstate, double red, double green, double blue)
{
_cairo_color_set_rgb (&gstate->color, red, green, blue);
if (gstate->source)
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_offset.x = 0;
gstate->source_offset.y = 0;
gstate->source_is_solid = 1;
cairo_pattern_destroy (gstate->pattern);
gstate->pattern = _cairo_pattern_create_solid (red, green, blue);
gstate->pattern_offset.x = 0.0;
gstate->pattern_offset.y = 0.0;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_current_rgb_color (cairo_gstate_t *gstate, double *red, double *green, double *blue)
{
_cairo_color_get_rgb (&gstate->color, red, green, blue);
return CAIRO_STATUS_SUCCESS;
return _cairo_pattern_get_rgb (gstate->pattern, red, green, blue);
}
cairo_status_t
@ -430,20 +430,11 @@ _cairo_gstate_current_tolerance (cairo_gstate_t *gstate)
return gstate->tolerance;
}
/* XXX: Need to fix this so it does the right thing after set_pattern. */
cairo_status_t
_cairo_gstate_set_alpha (cairo_gstate_t *gstate, double alpha)
{
gstate->alpha = alpha;
_cairo_color_set_alpha (&gstate->color, alpha);
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_offset.x = 0;
gstate->source_offset.y = 0;
return CAIRO_STATUS_SUCCESS;
}
@ -1259,24 +1250,49 @@ _cairo_gstate_interpret_path (cairo_gstate_t *gstate,
&gpi);
}
/* This function modifies the pattern and the state of the pattern surface it
may contain. The pattern surface will be restored to its orignal state
when the pattern is destroyed. The appropriate way is to pass a copy of
the original pattern to this function just before the pattern should be
used and destroy the copy when done. */
static cairo_status_t
_cairo_gstate_ensure_source (cairo_gstate_t *gstate)
_cairo_gstate_create_pattern (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_box_t *extents)
{
if (gstate->source)
return CAIRO_STATUS_SUCCESS;
if (gstate->surface == NULL)
cairo_int_status_t status;
if (gstate->surface == NULL) {
_cairo_pattern_fini (pattern);
return CAIRO_STATUS_NO_TARGET_SURFACE;
}
gstate->source = _cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_ARGB32,
1, 1,
&gstate->color);
if (gstate->source == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (pattern->type == CAIRO_PATTERN_LINEAR ||
pattern->type == CAIRO_PATTERN_RADIAL) {
if (pattern->n_stops < 2) {
pattern->type = CAIRO_PATTERN_SOLID;
if (pattern->n_stops)
pattern->color = pattern->stops->color;
}
}
_cairo_pattern_set_alpha (pattern, gstate->alpha);
_cairo_pattern_transform (pattern, &gstate->ctm, &gstate->ctm_inverse);
cairo_surface_set_repeat (gstate->source, 1);
status = _cairo_surface_create_pattern (gstate->surface, pattern, extents);
if (status) {
_cairo_pattern_fini (pattern);
return status;
}
if (pattern->type == CAIRO_PATTERN_SURFACE)
_cairo_pattern_prepare_surface (pattern);
_cairo_pattern_add_source_offset (pattern,
gstate->pattern_offset.x,
gstate->pattern_offset.y);
return CAIRO_STATUS_SUCCESS;
}
@ -1285,15 +1301,10 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_traps_t traps;
cairo_matrix_t user_to_source, device_to_source;
if (gstate->line_width <= 0.0)
return CAIRO_STATUS_SUCCESS;
status = _cairo_gstate_ensure_source (gstate);
if (status)
return status;
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
_cairo_traps_init (&traps);
@ -1304,21 +1315,11 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate)
return status;
}
if (! gstate->source_is_solid) {
cairo_surface_get_matrix (gstate->source, &user_to_source);
cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, &user_to_source);
cairo_surface_set_matrix (gstate->source, &device_to_source);
}
_cairo_gstate_clip_and_composite_trapezoids (gstate,
gstate->source,
gstate->operator,
gstate->surface,
&traps);
/* restore the matrix originally in the source surface */
if (! gstate->source_is_solid)
cairo_surface_set_matrix (gstate->source, &user_to_source);
gstate->pattern,
gstate->operator,
gstate->surface,
&traps);
_cairo_traps_fini (&traps);
@ -1357,12 +1358,14 @@ BAIL:
/* Warning: This call modifies the coordinates of traps */
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_t *src,
cairo_pattern_t *src,
cairo_operator_t operator,
cairo_surface_t *dst,
cairo_traps_t *traps)
{
cairo_status_t status;
cairo_pattern_t pattern;
cairo_box_t extents;
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
@ -1371,19 +1374,8 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_fixed_t xoff, yoff;
cairo_trapezoid_t *t;
int i;
cairo_surface_t *white, *intermediate;
cairo_color_t white_color, empty_color;
_cairo_color_init (&white_color);
white = _cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_A8,
1, 1,
&white_color);
if (white == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL0;
}
cairo_surface_set_repeat (white, 1);
cairo_surface_t *intermediate;
cairo_color_t empty_color;
_cairo_color_init (&empty_color);
_cairo_color_set_alpha (&empty_color, 0.);
@ -1391,10 +1383,10 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
CAIRO_FORMAT_A8,
gstate->clip.width,
gstate->clip.height,
&empty_color);
&empty_color);
if (intermediate == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL1;
goto BAIL0;
}
/* Ugh. The cairo_composite/(Render) interface doesn't allow
@ -1416,8 +1408,16 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
t->right.p2.y -= yoff;
}
_cairo_pattern_init_solid (&pattern, 1.0, 1.0, 1.0);
_cairo_pattern_set_alpha (&pattern, 1.0);
_cairo_traps_extents (traps, &extents);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
goto BAIL1;
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
white, intermediate,
pattern.source, intermediate,
0, 0,
traps->traps,
traps->num_traps);
@ -1432,9 +1432,23 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
gstate->clip.width, gstate->clip.height);
if (status)
goto BAIL2;
_cairo_pattern_fini (&pattern);
_cairo_pattern_init_copy (&pattern, src);
extents.p1.x = _cairo_fixed_from_int (gstate->clip.x);
extents.p1.y = _cairo_fixed_from_int (gstate->clip.y);
extents.p2.x =
_cairo_fixed_from_int (gstate->clip.x + gstate->clip.width);
extents.p2.y =
_cairo_fixed_from_int (gstate->clip.y + gstate->clip.height);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
goto BAIL2;
status = _cairo_surface_composite (operator,
src, intermediate, dst,
pattern.source, intermediate, dst,
0, 0,
0, 0,
gstate->clip.x,
@ -1445,12 +1459,12 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
BAIL2:
cairo_surface_destroy (intermediate);
BAIL1:
cairo_surface_destroy (white);
_cairo_pattern_fini (&pattern);
BAIL0:
if (status)
return status;
} else {
int xoff, yoff;
@ -1462,16 +1476,26 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
yoff = _cairo_fixed_to_double (traps->traps[0].left.p2.y);
}
_cairo_pattern_init_copy (&pattern, src);
_cairo_traps_extents (traps, &extents);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
return status;
status = _cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
xoff - gstate->source_offset.x,
yoff - gstate->source_offset.y,
pattern.source, dst,
xoff - pattern.source_offset.x,
yoff - pattern.source_offset.y,
traps->traps,
traps->num_traps);
_cairo_pattern_fini (&pattern);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}
@ -1480,11 +1504,6 @@ _cairo_gstate_fill (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_traps_t traps;
cairo_matrix_t user_to_source, device_to_source;
status = _cairo_gstate_ensure_source (gstate);
if (status)
return status;
_cairo_traps_init (&traps);
@ -1494,21 +1513,11 @@ _cairo_gstate_fill (cairo_gstate_t *gstate)
return status;
}
if (! gstate->source_is_solid) {
cairo_surface_get_matrix (gstate->source, &user_to_source);
cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, &user_to_source);
cairo_surface_set_matrix (gstate->source, &device_to_source);
}
_cairo_gstate_clip_and_composite_trapezoids (gstate,
gstate->source,
gstate->operator,
gstate->surface,
&traps);
/* restore the matrix originally in the source surface */
if (! gstate->source_is_solid)
cairo_surface_set_matrix (gstate->source, &user_to_source);
gstate->pattern,
gstate->operator,
gstate->surface,
&traps);
_cairo_traps_fini (&traps);
@ -1535,7 +1544,7 @@ _cairo_gstate_in_fill (cairo_gstate_t *gstate,
goto BAIL;
*inside_ret = _cairo_traps_contain (&traps, x, y);
BAIL:
_cairo_traps_fini (&traps);
@ -1560,6 +1569,67 @@ _cairo_gstate_show_page (cairo_gstate_t *gstate)
return _cairo_surface_show_page (gstate->surface);
}
cairo_status_t
_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
double *x1, double *y1,
double *x2, double *y2)
{
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t extents;
_cairo_traps_init (&traps);
status = _cairo_path_stroke_to_traps (&gstate->path, gstate, &traps);
if (status)
goto BAIL;
_cairo_traps_extents (&traps, &extents);
*x1 = _cairo_fixed_to_double (extents.p1.x);
*y1 = _cairo_fixed_to_double (extents.p1.y);
*x2 = _cairo_fixed_to_double (extents.p2.x);
*y2 = _cairo_fixed_to_double (extents.p2.y);
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
BAIL:
_cairo_traps_fini (&traps);
return status;
}
cairo_status_t
_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
double *x1, double *y1,
double *x2, double *y2)
{
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t extents;
_cairo_traps_init (&traps);
status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
if (status)
goto BAIL;
_cairo_traps_extents (&traps, &extents);
*x1 = _cairo_fixed_to_double (extents.p1.x);
*y1 = _cairo_fixed_to_double (extents.p1.y);
*x2 = _cairo_fixed_to_double (extents.p2.x);
*y2 = _cairo_fixed_to_double (extents.p2.y);
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
BAIL:
_cairo_traps_fini (&traps);
return status;
}
cairo_status_t
_cairo_gstate_init_clip (cairo_gstate_t *gstate)
@ -1625,7 +1695,7 @@ cairo_status_t
_cairo_gstate_clip (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_surface_t *alpha_one;
cairo_pattern_t pattern;
cairo_traps_t traps;
cairo_color_t white_color;
pixman_box16_t box;
@ -1668,12 +1738,16 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
}
pixman_region_destroy (rect);
}
_cairo_surface_set_clip_region (gstate->surface,
gstate->clip.region);
if (!status)
status = _cairo_surface_set_clip_region (gstate->surface,
gstate->clip.region);
}
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
_cairo_traps_fini (&traps);
return status;
}
_cairo_traps_fini (&traps);
return status;
}
/* Otherwise represent the clip as a mask surface. */
@ -1682,39 +1756,35 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
if (gstate->clip.surface == NULL) {
double x1, y1, x2, y2;
_cairo_path_bounds (&gstate->path,
&x1, &y1, &x2, &y2);
gstate->clip.x = floor (x1);
gstate->clip.y = floor (y1);
gstate->clip.width = ceil (x2 - gstate->clip.x);
gstate->clip.height = ceil (y2 - gstate->clip.y);
gstate->clip.surface = _cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
gstate->clip.width,
gstate->clip.height,
&white_color);
if (gstate->clip.surface == NULL)
_cairo_path_bounds (&gstate->path,
&x1, &y1, &x2, &y2);
gstate->clip.x = floor (x1);
gstate->clip.y = floor (y1);
gstate->clip.width = ceil (x2 - gstate->clip.x);
gstate->clip.height = ceil (y2 - gstate->clip.y);
gstate->clip.surface =
_cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
gstate->clip.width,
gstate->clip.height,
&white_color);
if (gstate->clip.surface == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
alpha_one = _cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_A8,
1, 1,
&white_color);
if (alpha_one == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_surface_set_repeat (alpha_one, 1);
_cairo_pattern_init_solid (&pattern, 1.0, 1.0, 1.0);
_cairo_pattern_set_alpha (&pattern, 1.0);
_cairo_gstate_clip_and_composite_trapezoids (gstate,
alpha_one,
&pattern,
CAIRO_OPERATOR_IN,
gstate->clip.surface,
&traps);
_cairo_pattern_fini (&pattern);
_cairo_traps_fini (&traps);
cairo_surface_destroy (alpha_one);
return status;
}
@ -1725,27 +1795,12 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
int height)
{
cairo_status_t status;
cairo_surface_t *mask;
cairo_matrix_t user_to_image, image_to_user;
cairo_matrix_t image_to_device, device_to_image;
double device_x, device_y;
double device_width, device_height;
cairo_color_t alpha_color;
if (gstate->alpha != 1.0) {
_cairo_color_init (&alpha_color);
_cairo_color_set_alpha (&alpha_color, gstate->alpha);
mask = _cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
1, 1,
&alpha_color);
if (mask == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_surface_set_repeat (mask, 1);
} else {
mask = NULL;
}
cairo_pattern_t pattern;
cairo_box_t extents;
cairo_surface_get_matrix (surface, &user_to_image);
cairo_matrix_multiply (&device_to_image, &gstate->ctm_inverse, &user_to_image);
@ -1761,25 +1816,40 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
_cairo_matrix_transform_bounding_box (&image_to_device,
&device_x, &device_y,
&device_width, &device_height);
_cairo_pattern_init (&pattern);
if ((gstate->pattern->type != CAIRO_PATTERN_SOLID) ||
(gstate->alpha != 1.0)) {
/* I'm allowing any type of pattern for the mask right now.
Maybe this is bad. Will allow for some cool effects though. */
_cairo_pattern_init_copy (&pattern, gstate->pattern);
extents.p1.x = _cairo_fixed_from_double (device_x);
extents.p1.y = _cairo_fixed_from_double (device_y);
extents.p2.x = _cairo_fixed_from_double (device_x + device_width);
extents.p2.y = _cairo_fixed_from_double (device_y + device_height);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
return status;
}
/* XXX: The rendered size is sometimes 1 or 2 pixels short from
what I expect. Need to fix this. */
status = _cairo_surface_composite (gstate->operator,
surface, mask, gstate->surface,
surface, pattern.source, gstate->surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
if (mask)
cairo_surface_destroy (mask);
if (status)
return status;
_cairo_pattern_fini (&pattern);
/* restore the matrix originally in the surface */
cairo_surface_set_matrix (surface, &user_to_image);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
@ -1908,39 +1978,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
return status;
}
static cairo_status_t
setup_text_rendering_context(cairo_gstate_t *gstate,
cairo_matrix_t *user_to_source)
{
cairo_status_t status;
cairo_matrix_t device_to_source;
status = _cairo_gstate_ensure_source (gstate);
if (status)
return status;
/* XXX: This same source matrix manipulation code shows up in
about 3 or 4 places. We should move that into a shared function
or two. */
if (! gstate->source_is_solid) {
cairo_surface_get_matrix (gstate->source, user_to_source);
cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, user_to_source);
cairo_surface_set_matrix (gstate->source, &device_to_source);
}
return CAIRO_STATUS_SUCCESS;
}
static void
restore_text_rendering_context(cairo_gstate_t *gstate,
cairo_matrix_t *user_to_source)
{
/* restore the matrix originally in the source surface */
if (! gstate->source_is_solid)
cairo_surface_set_matrix (gstate->source, user_to_source);
}
cairo_status_t
_cairo_gstate_show_text (cairo_gstate_t *gstate,
const unsigned char *utf8)
@ -1948,8 +1985,10 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate,
cairo_status_t status;
cairo_point_t point;
double x, y;
cairo_matrix_t user_to_source;
cairo_matrix_t saved_font_matrix;
cairo_pattern_t pattern;
cairo_text_extents_t text_extents;
cairo_box_t extents;
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
@ -1960,35 +1999,47 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate,
x = _cairo_fixed_to_double (point.x);
y = _cairo_fixed_to_double (point.y);
}
status = setup_text_rendering_context (gstate, &user_to_source);
if (status)
return status;
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
_cairo_pattern_init_copy (&pattern, gstate->pattern);
status = _cairo_gstate_text_extents (gstate, utf8, &text_extents);
if (status)
return status;
extents.p1.x = _cairo_fixed_from_double (x);
extents.p1.y = _cairo_fixed_from_double (y);
extents.p2.x = _cairo_fixed_from_double (x + text_extents.width);
extents.p2.y = _cairo_fixed_from_double (y + text_extents.height);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
return status;
status = _cairo_font_show_text (gstate->font,
gstate->operator, gstate->source,
gstate->operator, pattern.source,
gstate->surface, x, y, utf8);
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
restore_text_rendering_context (gstate, &user_to_source);
_cairo_pattern_fini (&pattern);
return status;
}
cairo_status_t
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
cairo_matrix_t user_to_source;
cairo_matrix_t saved_font_matrix;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_pattern_t pattern;
cairo_text_extents_t text_extents;
cairo_box_t extents;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
@ -2002,20 +2053,33 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
&(transformed_glyphs[i].y));
}
status = setup_text_rendering_context (gstate, &user_to_source);
if (status)
return status;
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
_cairo_pattern_init_copy (&pattern, gstate->pattern);
_cairo_gstate_glyph_extents (gstate, transformed_glyphs, num_glyphs,
&text_extents);
if (status)
return status;
extents.p1.x = _cairo_fixed_from_double (transformed_glyphs[0].x);
extents.p1.y = _cairo_fixed_from_double (transformed_glyphs[0].y);
extents.p2.x = _cairo_fixed_from_double (transformed_glyphs[0].x +
text_extents.width);
extents.p2.y = _cairo_fixed_from_double (transformed_glyphs[0].y +
text_extents.height);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
return status;
status = _cairo_font_show_glyphs (gstate->font,
gstate->operator, gstate->source,
gstate->operator, pattern.source,
gstate->surface,
transformed_glyphs, num_glyphs);
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
restore_text_rendering_context (gstate, &user_to_source);
_cairo_pattern_fini (&pattern);
free (transformed_glyphs);
@ -2028,15 +2092,10 @@ _cairo_gstate_text_path (cairo_gstate_t *gstate,
const unsigned char *utf8)
{
cairo_status_t status;
cairo_matrix_t user_to_source;
cairo_matrix_t saved_font_matrix;
cairo_point_t point;
double x, y;
status = setup_text_rendering_context (gstate, &user_to_source);
if (status)
return status;
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
x = 0;
@ -2056,7 +2115,6 @@ _cairo_gstate_text_path (cairo_gstate_t *gstate,
&gstate->path);
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
restore_text_rendering_context (gstate, &user_to_source);
return status;
}
@ -2070,7 +2128,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
cairo_status_t status;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_matrix_t user_to_source;
cairo_matrix_t saved_font_matrix;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
@ -2085,10 +2142,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
&(transformed_glyphs[i].y));
}
status = setup_text_rendering_context (gstate, &user_to_source);
if (status)
return status;
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
@ -2097,8 +2150,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
&gstate->path);
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
restore_text_rendering_context (gstate, &user_to_source);
free (transformed_glyphs);
return status;
}

View file

@ -467,6 +467,26 @@ _cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_abstract_surface_create_pattern (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_box_t *box)
{
cairo_image_surface_t *image;
/* Fall back to general pattern creation for surface patterns. */
if (pattern->type == CAIRO_PATTERN_SURFACE)
return CAIRO_INT_STATUS_UNSUPPORTED;
image = _cairo_pattern_get_image (pattern, box);
if (image) {
pattern->source = &image->base;
return CAIRO_STATUS_SUCCESS;
} else
return CAIRO_STATUS_NO_MEMORY;
}
static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
_cairo_image_abstract_surface_destroy,
@ -481,5 +501,6 @@ static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_composite_trapezoids,
_cairo_image_surface_copy_page,
_cairo_image_surface_show_page,
_cairo_image_abstract_surface_set_clip_region
_cairo_image_abstract_surface_set_clip_region,
_cairo_image_abstract_surface_create_pattern
};

View file

@ -403,6 +403,13 @@ _cairo_ps_surface_set_clip_region (void *abstract_surface,
return _cairo_image_surface_set_clip_region (surface->image, region);
}
static cairo_int_status_t
_cairo_ps_surface_create_pattern (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_box_t *extents)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static const cairo_surface_backend_t cairo_ps_surface_backend = {
_cairo_ps_surface_create_similar,
@ -418,5 +425,6 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = {
_cairo_ps_surface_composite_trapezoids,
_cairo_ps_surface_copy_page,
_cairo_ps_surface_show_page,
_cairo_ps_surface_set_clip_region
_cairo_ps_surface_set_clip_region,
_cairo_ps_surface_create_pattern
};

View file

@ -377,3 +377,111 @@ _cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *reg
{
return surface->backend->set_clip_region (surface, region);
}
cairo_status_t
_cairo_surface_create_pattern (cairo_surface_t *surface,
cairo_pattern_t *pattern,
cairo_box_t *box)
{
cairo_int_status_t status;
status = surface->backend->create_pattern (surface, pattern, box);
/* The backend cannot accelerate this pattern, lets create an
unaccelerated source instead. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = CAIRO_STATUS_SUCCESS;
switch (pattern->type) {
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL: {
cairo_image_surface_t *image;
image = _cairo_pattern_get_image (pattern, box);
if (image) {
pattern->source = &image->base;
return CAIRO_STATUS_SUCCESS;
} else
return CAIRO_STATUS_NO_MEMORY;
} break;
case CAIRO_PATTERN_SOLID:
pattern->source =
_cairo_surface_create_similar_solid (surface,
CAIRO_FORMAT_ARGB32,
1, 1,
&pattern->color);
if (pattern->source) {
cairo_surface_set_repeat (pattern->source, 1);
return CAIRO_STATUS_SUCCESS;
} else
return CAIRO_STATUS_NO_MEMORY;
break;
case CAIRO_PATTERN_SURFACE:
status = CAIRO_INT_STATUS_UNSUPPORTED;
/* handle pattern opacity */
if (pattern->color.alpha != 1.0) {
int width = ceil (_cairo_fixed_to_double (box->p2.x) -
_cairo_fixed_to_double (box->p1.x));
int height = ceil (_cairo_fixed_to_double (box->p2.y) -
_cairo_fixed_to_double (box->p1.y));
cairo_pattern_t alpha;
pattern->source =
cairo_surface_create_similar (surface,
CAIRO_FORMAT_ARGB32,
width, height);
if (pattern->source) {
_cairo_pattern_init_solid (&alpha, 1.0, 1.0, 1.0);
_cairo_pattern_set_alpha (&alpha, pattern->color.alpha);
status = _cairo_surface_create_pattern (pattern->source,
&alpha, box);
if (status == CAIRO_STATUS_SUCCESS) {
int save_repeat = pattern->u.surface.surface->repeat;
if (pattern->extend == CAIRO_EXTEND_REPEAT ||
pattern->u.surface.surface->repeat == 1)
cairo_surface_set_repeat (pattern->u.surface.surface, 1);
else
cairo_surface_set_repeat (pattern->u.surface.surface, 0);
status =
_cairo_surface_composite (CAIRO_OPERATOR_OVER,
pattern->u.surface.surface,
alpha.source,
pattern->source,
0, 0, 0, 0, 0, 0,
width, height);
cairo_surface_set_repeat (pattern->u.surface.surface,
save_repeat);
if (status == CAIRO_STATUS_SUCCESS) {
_cairo_pattern_add_source_offset (pattern,
_cairo_fixed_to_double (box->p1.x),
_cairo_fixed_to_double (box->p1.y));
} else
cairo_surface_destroy (pattern->source);
}
_cairo_pattern_fini (&alpha);
}
}
if (status != CAIRO_STATUS_SUCCESS) {
pattern->source = pattern->u.surface.surface;
cairo_surface_reference (pattern->u.surface.surface);
return CAIRO_STATUS_SUCCESS;
}
break;
}
}
return status;
}

View file

@ -608,3 +608,40 @@ _cairo_traps_contain (cairo_traps_t *traps, double x, double y)
return 0;
}
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
static void
_cairo_trap_extents (cairo_trapezoid_t *t, cairo_box_t *extents)
{
cairo_fixed_t x;
if (t->top < extents->p1.y)
extents->p1.y = t->top;
if (t->bottom > extents->p2.y)
extents->p2.y = t->bottom;
x = MIN (_compute_x (&t->left, t->top),
_compute_x (&t->left, t->bottom));
if (x < extents->p1.x)
extents->p1.x = x;
x = MAX (_compute_x (&t->right, t->top),
_compute_x (&t->right, t->bottom));
if (x > extents->p2.x)
extents->p2.x = x;
}
void
_cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
{
int i;
extents->p1.x = extents->p1.y = SHRT_MAX << 16;
extents->p2.x = extents->p2.y = SHRT_MIN << 16;
for (i = 0; i < traps->num_traps; i++)
_cairo_trap_extents (&traps->traps[i], extents);
}

View file

@ -712,6 +712,14 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_int_status_t
_cairo_xcb_surface_create_pattern (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_box_t *extents)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static const struct cairo_surface_backend cairo_xcb_surface_backend = {
_cairo_xcb_surface_create_similar,
_cairo_xcb_surface_destroy,
@ -726,7 +734,8 @@ static const struct cairo_surface_backend cairo_xcb_surface_backend = {
_cairo_xcb_surface_composite_trapezoids,
_cairo_xcb_surface_copy_page,
_cairo_xcb_surface_show_page,
_cairo_xcb_surface_set_clip_region
_cairo_xcb_surface_set_clip_region,
_cairo_xcb_surface_create_pattern
};
static void

View file

@ -455,7 +455,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
cairo_xlib_surface_t *mask = (cairo_xlib_surface_t *) generic_mask;
cairo_xlib_surface_t *src_clone = NULL;
cairo_xlib_surface_t *mask_clone = NULL;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -619,6 +619,14 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_xlib_surface_create_pattern (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_box_t *extents)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_create_similar,
_cairo_xlib_surface_destroy,
@ -633,7 +641,8 @@ static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_composite_trapezoids,
_cairo_xlib_surface_copy_page,
_cairo_xlib_surface_show_page,
_cairo_xlib_surface_set_clip_region
_cairo_xlib_surface_set_clip_region,
_cairo_xlib_surface_create_pattern
};
cairo_surface_t *
@ -692,7 +701,7 @@ cairo_xlib_surface_create (Display *dpy,
0, NULL);
else
surface->picture = 0;
return (cairo_surface_t *) surface;
}
DEPRECATE (cairo_surface_create_for_drawable, cairo_xlib_surface_create);

View file

@ -29,9 +29,6 @@
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
static void
_cairo_restrict_value (double *value, double min, double max);
cairo_t *
cairo_create (void)
{
@ -220,7 +217,7 @@ cairo_set_rgb_color (cairo_t *cr, double red, double green, double blue)
}
void
cairo_set_pattern (cairo_t *cr, cairo_surface_t *pattern)
cairo_set_pattern (cairo_t *cr, cairo_pattern_t *pattern)
{
if (cr->status)
return;
@ -228,6 +225,12 @@ cairo_set_pattern (cairo_t *cr, cairo_surface_t *pattern)
cr->status = _cairo_gstate_set_pattern (cr->gstate, pattern);
}
cairo_pattern_t *
cairo_current_pattern (cairo_t *cr)
{
return _cairo_gstate_current_pattern (cr->gstate);
}
void
cairo_set_tolerance (cairo_t *cr, double tolerance)
{
@ -635,6 +638,26 @@ cairo_in_fill (cairo_t *cr, double x, double y)
return inside;
}
void
cairo_stroke_extents (cairo_t *cr,
double *x1, double *y1, double *x2, double *y2)
{
if (cr->status)
return;
cr->status = _cairo_gstate_stroke_extents (cr->gstate, x1, y1, x2, y2);
}
void
cairo_fill_extents (cairo_t *cr,
double *x1, double *y1, double *x2, double *y2)
{
if (cr->status)
return;
cr->status = _cairo_gstate_fill_extents (cr->gstate, x1, y1, x2, y2);
}
void
cairo_init_clip (cairo_t *cr)
{
@ -942,7 +965,7 @@ cairo_status_string (cairo_t *cr)
}
DEPRECATE (cairo_get_status_string, cairo_status_string);
static void
void
_cairo_restrict_value (double *value, double min, double max)
{
if (*value < min)

View file

@ -36,6 +36,7 @@
typedef struct cairo cairo_t;
typedef struct cairo_surface cairo_surface_t;
typedef struct cairo_matrix cairo_matrix_t;
typedef struct cairo_pattern cairo_pattern_t;
#ifdef __cplusplus
extern "C" {
@ -181,10 +182,10 @@ void
cairo_set_rgb_color (cairo_t *cr, double red, double green, double blue);
void
cairo_set_alpha (cairo_t *cr, double alpha);
cairo_set_pattern (cairo_t *cr, cairo_pattern_t *pattern);
void
cairo_set_pattern (cairo_t *cr, cairo_surface_t *pattern);
cairo_set_alpha (cairo_t *cr, double alpha);
/* XXX: Currently, the tolerance value is specified by the user in
terms of device-space units. If I'm not mistaken, this is the only
@ -353,6 +354,17 @@ cairo_in_stroke (cairo_t *cr, double x, double y);
int
cairo_in_fill (cairo_t *cr, double x, double y);
/* Rectangular extents */
void
cairo_stroke_extents (cairo_t *cr,
double *x1, double *y1,
double *x2, double *y2);
void
cairo_fill_extents (cairo_t *cr,
double *x1, double *y1,
double *x2, double *y2);
/* Clipping */
void
cairo_init_clip (cairo_t *cr);
@ -505,6 +517,8 @@ cairo_current_operator (cairo_t *cr);
void
cairo_current_rgb_color (cairo_t *cr, double *red, double *green, double *blue);
cairo_pattern_t *
cairo_current_pattern (cairo_t *cr);
double
cairo_current_alpha (cairo_t *cr);
@ -640,14 +654,15 @@ cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix);
cairo_status_t
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix);
typedef enum cairo_filter {
typedef enum {
CAIRO_FILTER_FAST,
CAIRO_FILTER_GOOD,
CAIRO_FILTER_BEST,
CAIRO_FILTER_NEAREST,
CAIRO_FILTER_BILINEAR
CAIRO_FILTER_BILINEAR,
CAIRO_FILTER_GAUSSIAN
} cairo_filter_t;
/* XXX: Rework this as a cairo function: cairo_set_pattern_filter */
cairo_status_t
cairo_surface_set_filter (cairo_surface_t *surface, cairo_filter_t filter);
@ -669,6 +684,54 @@ cairo_image_surface_create_for_data (char *data,
int height,
int stride);
/* Pattern creation functions */
cairo_pattern_t *
cairo_pattern_create_for_surface (cairo_surface_t *surface);
cairo_pattern_t *
cairo_pattern_create_linear (double x0, double y0,
double x1, double y1);
cairo_pattern_t *
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
double cx1, double cy1, double radius1);
void
cairo_pattern_reference (cairo_pattern_t *pattern);
void
cairo_pattern_destroy (cairo_pattern_t *pattern);
cairo_status_t
cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
double offset,
double red, double green, double blue,
double alpha);
cairo_status_t
cairo_pattern_set_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix);
cairo_status_t
cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix);
typedef enum {
CAIRO_EXTEND_NONE,
CAIRO_EXTEND_REPEAT,
CAIRO_EXTEND_REFLECT
} cairo_extend_t;
cairo_status_t
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend);
cairo_extend_t
cairo_pattern_get_extend (cairo_pattern_t *pattern);
cairo_status_t
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter);
cairo_filter_t
cairo_pattern_get_filter (cairo_pattern_t *pattern);
#ifdef CAIRO_HAS_PS_SURFACE
/* PS-surface functions */
@ -707,7 +770,7 @@ cairo_xlib_surface_create (Display *dpy,
Visual *visual,
cairo_format_t format,
Colormap colormap);
/* XXX: This has been proposed
cairo_status_t
cairo_xlib_surface_set_size (cairo_surface_t *surface, int width, int height);

View file

@ -477,6 +477,7 @@ _cairo_ft_font_show_glyphs (void *abstract_font,
cairo_ft_font_t *ft = NULL;
FT_GlyphSlot glyphslot;
cairo_surface_t *mask = NULL;
cairo_point_double_t origin;
double x, y;
int width, height, stride;
@ -504,7 +505,12 @@ _cairo_ft_font_show_glyphs (void *abstract_font,
bitmap = glyphslot->bitmap.buffer;
x = glyphs[i].x;
y = glyphs[i].y;
y = glyphs[i].y;
if (i == 0) {
origin.x = x;
origin.y = y;
}
/* X gets upset with zero-sized images (such as whitespace) */
if (width * height == 0)
@ -547,11 +553,14 @@ _cairo_ft_font_show_glyphs (void *abstract_font,
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_surface_composite (operator, source, mask, surface,
0, 0, 0, 0,
x + glyphslot->bitmap_left,
y - glyphslot->bitmap_top,
(double)width, (double)height);
status =
_cairo_surface_composite (operator, source, mask, surface,
-origin.x + x + glyphslot->bitmap_left,
-origin.y + y - glyphslot->bitmap_top,
0, 0,
x + glyphslot->bitmap_left,
y - glyphslot->bitmap_top,
(double) width, (double) height);
cairo_surface_destroy (mask);
if (bitmap != glyphslot->bitmap.buffer)

View file

@ -30,12 +30,9 @@
#include "cairoint.h"
static cairo_status_t
_cairo_gstate_ensure_source (cairo_gstate_t *gstate);
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_t *src,
cairo_pattern_t *src,
cairo_operator_t operator,
cairo_surface_t *dst,
cairo_traps_t *traps);
@ -76,16 +73,14 @@ _cairo_gstate_init (cairo_gstate_t *gstate)
CAIRO_FONT_WEIGHT_DEFAULT);
gstate->surface = NULL;
gstate->source = NULL;
gstate->source_offset.x = 0.0;
gstate->source_offset.y = 0.0;
gstate->source_is_solid = 1;
gstate->clip.region = NULL;
gstate->clip.surface = NULL;
gstate->pattern = _cairo_pattern_create_solid (1.0, 1.0, 1.0);
gstate->pattern_offset.x = 0.0;
gstate->pattern_offset.y = 0.0;
gstate->alpha = 1.0;
_cairo_color_init (&gstate->color);
gstate->pixels_per_inch = CAIRO_GSTATE_PIXELS_PER_INCH_DEFAULT;
_cairo_gstate_default_matrix (gstate);
@ -131,8 +126,9 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
}
cairo_surface_reference (gstate->surface);
cairo_surface_reference (gstate->source);
cairo_surface_reference (gstate->clip.surface);
cairo_pattern_reference (gstate->pattern);
status = _cairo_path_init_copy (&gstate->path, &other->path);
if (status)
@ -164,11 +160,6 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_surface_destroy (gstate->surface);
gstate->surface = NULL;
if (gstate->source)
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_is_solid = 1;
if (gstate->clip.surface)
cairo_surface_destroy (gstate->clip.surface);
gstate->clip.surface = NULL;
@ -177,7 +168,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
pixman_region_destroy (gstate->clip.region);
gstate->clip.region = NULL;
_cairo_color_fini (&gstate->color);
cairo_pattern_destroy (gstate->pattern);
_cairo_matrix_fini (&gstate->ctm);
_cairo_matrix_fini (&gstate->ctm_inverse);
@ -362,22 +353,37 @@ _cairo_gstate_current_target_surface (cairo_gstate_t *gstate)
}
cairo_status_t
_cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_surface_t *pattern)
_cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_pattern_t *pattern)
{
cairo_surface_destroy (gstate->source);
if (pattern == NULL)
return CAIRO_STATUS_NULL_POINTER;
gstate->source = pattern;
gstate->source_is_solid = 0;
cairo_surface_reference (gstate->source);
if (gstate->pattern)
cairo_pattern_destroy (gstate->pattern);
gstate->pattern = pattern;
cairo_pattern_reference (pattern);
_cairo_gstate_current_point (gstate,
&gstate->source_offset.x,
&gstate->source_offset.y);
&gstate->pattern_offset.x,
&gstate->pattern_offset.y);
return CAIRO_STATUS_SUCCESS;
}
cairo_pattern_t *
_cairo_gstate_current_pattern (cairo_gstate_t *gstate)
{
if (gstate == NULL)
return NULL;
/* XXX: Do we want this?
cairo_pattern_reference (gstate->pattern);
*/
return gstate->pattern;
}
cairo_status_t
_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t operator)
{
@ -395,25 +401,19 @@ _cairo_gstate_current_operator (cairo_gstate_t *gstate)
cairo_status_t
_cairo_gstate_set_rgb_color (cairo_gstate_t *gstate, double red, double green, double blue)
{
_cairo_color_set_rgb (&gstate->color, red, green, blue);
if (gstate->source)
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_offset.x = 0;
gstate->source_offset.y = 0;
gstate->source_is_solid = 1;
cairo_pattern_destroy (gstate->pattern);
gstate->pattern = _cairo_pattern_create_solid (red, green, blue);
gstate->pattern_offset.x = 0.0;
gstate->pattern_offset.y = 0.0;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_current_rgb_color (cairo_gstate_t *gstate, double *red, double *green, double *blue)
{
_cairo_color_get_rgb (&gstate->color, red, green, blue);
return CAIRO_STATUS_SUCCESS;
return _cairo_pattern_get_rgb (gstate->pattern, red, green, blue);
}
cairo_status_t
@ -430,20 +430,11 @@ _cairo_gstate_current_tolerance (cairo_gstate_t *gstate)
return gstate->tolerance;
}
/* XXX: Need to fix this so it does the right thing after set_pattern. */
cairo_status_t
_cairo_gstate_set_alpha (cairo_gstate_t *gstate, double alpha)
{
gstate->alpha = alpha;
_cairo_color_set_alpha (&gstate->color, alpha);
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_offset.x = 0;
gstate->source_offset.y = 0;
return CAIRO_STATUS_SUCCESS;
}
@ -1259,24 +1250,49 @@ _cairo_gstate_interpret_path (cairo_gstate_t *gstate,
&gpi);
}
/* This function modifies the pattern and the state of the pattern surface it
may contain. The pattern surface will be restored to its orignal state
when the pattern is destroyed. The appropriate way is to pass a copy of
the original pattern to this function just before the pattern should be
used and destroy the copy when done. */
static cairo_status_t
_cairo_gstate_ensure_source (cairo_gstate_t *gstate)
_cairo_gstate_create_pattern (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_box_t *extents)
{
if (gstate->source)
return CAIRO_STATUS_SUCCESS;
if (gstate->surface == NULL)
cairo_int_status_t status;
if (gstate->surface == NULL) {
_cairo_pattern_fini (pattern);
return CAIRO_STATUS_NO_TARGET_SURFACE;
}
gstate->source = _cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_ARGB32,
1, 1,
&gstate->color);
if (gstate->source == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (pattern->type == CAIRO_PATTERN_LINEAR ||
pattern->type == CAIRO_PATTERN_RADIAL) {
if (pattern->n_stops < 2) {
pattern->type = CAIRO_PATTERN_SOLID;
if (pattern->n_stops)
pattern->color = pattern->stops->color;
}
}
_cairo_pattern_set_alpha (pattern, gstate->alpha);
_cairo_pattern_transform (pattern, &gstate->ctm, &gstate->ctm_inverse);
cairo_surface_set_repeat (gstate->source, 1);
status = _cairo_surface_create_pattern (gstate->surface, pattern, extents);
if (status) {
_cairo_pattern_fini (pattern);
return status;
}
if (pattern->type == CAIRO_PATTERN_SURFACE)
_cairo_pattern_prepare_surface (pattern);
_cairo_pattern_add_source_offset (pattern,
gstate->pattern_offset.x,
gstate->pattern_offset.y);
return CAIRO_STATUS_SUCCESS;
}
@ -1285,15 +1301,10 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_traps_t traps;
cairo_matrix_t user_to_source, device_to_source;
if (gstate->line_width <= 0.0)
return CAIRO_STATUS_SUCCESS;
status = _cairo_gstate_ensure_source (gstate);
if (status)
return status;
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
_cairo_traps_init (&traps);
@ -1304,21 +1315,11 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate)
return status;
}
if (! gstate->source_is_solid) {
cairo_surface_get_matrix (gstate->source, &user_to_source);
cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, &user_to_source);
cairo_surface_set_matrix (gstate->source, &device_to_source);
}
_cairo_gstate_clip_and_composite_trapezoids (gstate,
gstate->source,
gstate->operator,
gstate->surface,
&traps);
/* restore the matrix originally in the source surface */
if (! gstate->source_is_solid)
cairo_surface_set_matrix (gstate->source, &user_to_source);
gstate->pattern,
gstate->operator,
gstate->surface,
&traps);
_cairo_traps_fini (&traps);
@ -1357,12 +1358,14 @@ BAIL:
/* Warning: This call modifies the coordinates of traps */
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_t *src,
cairo_pattern_t *src,
cairo_operator_t operator,
cairo_surface_t *dst,
cairo_traps_t *traps)
{
cairo_status_t status;
cairo_pattern_t pattern;
cairo_box_t extents;
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
@ -1371,19 +1374,8 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_fixed_t xoff, yoff;
cairo_trapezoid_t *t;
int i;
cairo_surface_t *white, *intermediate;
cairo_color_t white_color, empty_color;
_cairo_color_init (&white_color);
white = _cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_A8,
1, 1,
&white_color);
if (white == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL0;
}
cairo_surface_set_repeat (white, 1);
cairo_surface_t *intermediate;
cairo_color_t empty_color;
_cairo_color_init (&empty_color);
_cairo_color_set_alpha (&empty_color, 0.);
@ -1391,10 +1383,10 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
CAIRO_FORMAT_A8,
gstate->clip.width,
gstate->clip.height,
&empty_color);
&empty_color);
if (intermediate == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL1;
goto BAIL0;
}
/* Ugh. The cairo_composite/(Render) interface doesn't allow
@ -1416,8 +1408,16 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
t->right.p2.y -= yoff;
}
_cairo_pattern_init_solid (&pattern, 1.0, 1.0, 1.0);
_cairo_pattern_set_alpha (&pattern, 1.0);
_cairo_traps_extents (traps, &extents);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
goto BAIL1;
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
white, intermediate,
pattern.source, intermediate,
0, 0,
traps->traps,
traps->num_traps);
@ -1432,9 +1432,23 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
gstate->clip.width, gstate->clip.height);
if (status)
goto BAIL2;
_cairo_pattern_fini (&pattern);
_cairo_pattern_init_copy (&pattern, src);
extents.p1.x = _cairo_fixed_from_int (gstate->clip.x);
extents.p1.y = _cairo_fixed_from_int (gstate->clip.y);
extents.p2.x =
_cairo_fixed_from_int (gstate->clip.x + gstate->clip.width);
extents.p2.y =
_cairo_fixed_from_int (gstate->clip.y + gstate->clip.height);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
goto BAIL2;
status = _cairo_surface_composite (operator,
src, intermediate, dst,
pattern.source, intermediate, dst,
0, 0,
0, 0,
gstate->clip.x,
@ -1445,12 +1459,12 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
BAIL2:
cairo_surface_destroy (intermediate);
BAIL1:
cairo_surface_destroy (white);
_cairo_pattern_fini (&pattern);
BAIL0:
if (status)
return status;
} else {
int xoff, yoff;
@ -1462,16 +1476,26 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
yoff = _cairo_fixed_to_double (traps->traps[0].left.p2.y);
}
_cairo_pattern_init_copy (&pattern, src);
_cairo_traps_extents (traps, &extents);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
return status;
status = _cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
xoff - gstate->source_offset.x,
yoff - gstate->source_offset.y,
pattern.source, dst,
xoff - pattern.source_offset.x,
yoff - pattern.source_offset.y,
traps->traps,
traps->num_traps);
_cairo_pattern_fini (&pattern);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}
@ -1480,11 +1504,6 @@ _cairo_gstate_fill (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_traps_t traps;
cairo_matrix_t user_to_source, device_to_source;
status = _cairo_gstate_ensure_source (gstate);
if (status)
return status;
_cairo_traps_init (&traps);
@ -1494,21 +1513,11 @@ _cairo_gstate_fill (cairo_gstate_t *gstate)
return status;
}
if (! gstate->source_is_solid) {
cairo_surface_get_matrix (gstate->source, &user_to_source);
cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, &user_to_source);
cairo_surface_set_matrix (gstate->source, &device_to_source);
}
_cairo_gstate_clip_and_composite_trapezoids (gstate,
gstate->source,
gstate->operator,
gstate->surface,
&traps);
/* restore the matrix originally in the source surface */
if (! gstate->source_is_solid)
cairo_surface_set_matrix (gstate->source, &user_to_source);
gstate->pattern,
gstate->operator,
gstate->surface,
&traps);
_cairo_traps_fini (&traps);
@ -1535,7 +1544,7 @@ _cairo_gstate_in_fill (cairo_gstate_t *gstate,
goto BAIL;
*inside_ret = _cairo_traps_contain (&traps, x, y);
BAIL:
_cairo_traps_fini (&traps);
@ -1560,6 +1569,67 @@ _cairo_gstate_show_page (cairo_gstate_t *gstate)
return _cairo_surface_show_page (gstate->surface);
}
cairo_status_t
_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
double *x1, double *y1,
double *x2, double *y2)
{
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t extents;
_cairo_traps_init (&traps);
status = _cairo_path_stroke_to_traps (&gstate->path, gstate, &traps);
if (status)
goto BAIL;
_cairo_traps_extents (&traps, &extents);
*x1 = _cairo_fixed_to_double (extents.p1.x);
*y1 = _cairo_fixed_to_double (extents.p1.y);
*x2 = _cairo_fixed_to_double (extents.p2.x);
*y2 = _cairo_fixed_to_double (extents.p2.y);
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
BAIL:
_cairo_traps_fini (&traps);
return status;
}
cairo_status_t
_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
double *x1, double *y1,
double *x2, double *y2)
{
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t extents;
_cairo_traps_init (&traps);
status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
if (status)
goto BAIL;
_cairo_traps_extents (&traps, &extents);
*x1 = _cairo_fixed_to_double (extents.p1.x);
*y1 = _cairo_fixed_to_double (extents.p1.y);
*x2 = _cairo_fixed_to_double (extents.p2.x);
*y2 = _cairo_fixed_to_double (extents.p2.y);
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
BAIL:
_cairo_traps_fini (&traps);
return status;
}
cairo_status_t
_cairo_gstate_init_clip (cairo_gstate_t *gstate)
@ -1625,7 +1695,7 @@ cairo_status_t
_cairo_gstate_clip (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_surface_t *alpha_one;
cairo_pattern_t pattern;
cairo_traps_t traps;
cairo_color_t white_color;
pixman_box16_t box;
@ -1668,12 +1738,16 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
}
pixman_region_destroy (rect);
}
_cairo_surface_set_clip_region (gstate->surface,
gstate->clip.region);
if (!status)
status = _cairo_surface_set_clip_region (gstate->surface,
gstate->clip.region);
}
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
_cairo_traps_fini (&traps);
return status;
}
_cairo_traps_fini (&traps);
return status;
}
/* Otherwise represent the clip as a mask surface. */
@ -1682,39 +1756,35 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
if (gstate->clip.surface == NULL) {
double x1, y1, x2, y2;
_cairo_path_bounds (&gstate->path,
&x1, &y1, &x2, &y2);
gstate->clip.x = floor (x1);
gstate->clip.y = floor (y1);
gstate->clip.width = ceil (x2 - gstate->clip.x);
gstate->clip.height = ceil (y2 - gstate->clip.y);
gstate->clip.surface = _cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
gstate->clip.width,
gstate->clip.height,
&white_color);
if (gstate->clip.surface == NULL)
_cairo_path_bounds (&gstate->path,
&x1, &y1, &x2, &y2);
gstate->clip.x = floor (x1);
gstate->clip.y = floor (y1);
gstate->clip.width = ceil (x2 - gstate->clip.x);
gstate->clip.height = ceil (y2 - gstate->clip.y);
gstate->clip.surface =
_cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
gstate->clip.width,
gstate->clip.height,
&white_color);
if (gstate->clip.surface == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
alpha_one = _cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_A8,
1, 1,
&white_color);
if (alpha_one == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_surface_set_repeat (alpha_one, 1);
_cairo_pattern_init_solid (&pattern, 1.0, 1.0, 1.0);
_cairo_pattern_set_alpha (&pattern, 1.0);
_cairo_gstate_clip_and_composite_trapezoids (gstate,
alpha_one,
&pattern,
CAIRO_OPERATOR_IN,
gstate->clip.surface,
&traps);
_cairo_pattern_fini (&pattern);
_cairo_traps_fini (&traps);
cairo_surface_destroy (alpha_one);
return status;
}
@ -1725,27 +1795,12 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
int height)
{
cairo_status_t status;
cairo_surface_t *mask;
cairo_matrix_t user_to_image, image_to_user;
cairo_matrix_t image_to_device, device_to_image;
double device_x, device_y;
double device_width, device_height;
cairo_color_t alpha_color;
if (gstate->alpha != 1.0) {
_cairo_color_init (&alpha_color);
_cairo_color_set_alpha (&alpha_color, gstate->alpha);
mask = _cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
1, 1,
&alpha_color);
if (mask == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_surface_set_repeat (mask, 1);
} else {
mask = NULL;
}
cairo_pattern_t pattern;
cairo_box_t extents;
cairo_surface_get_matrix (surface, &user_to_image);
cairo_matrix_multiply (&device_to_image, &gstate->ctm_inverse, &user_to_image);
@ -1761,25 +1816,40 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
_cairo_matrix_transform_bounding_box (&image_to_device,
&device_x, &device_y,
&device_width, &device_height);
_cairo_pattern_init (&pattern);
if ((gstate->pattern->type != CAIRO_PATTERN_SOLID) ||
(gstate->alpha != 1.0)) {
/* I'm allowing any type of pattern for the mask right now.
Maybe this is bad. Will allow for some cool effects though. */
_cairo_pattern_init_copy (&pattern, gstate->pattern);
extents.p1.x = _cairo_fixed_from_double (device_x);
extents.p1.y = _cairo_fixed_from_double (device_y);
extents.p2.x = _cairo_fixed_from_double (device_x + device_width);
extents.p2.y = _cairo_fixed_from_double (device_y + device_height);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
return status;
}
/* XXX: The rendered size is sometimes 1 or 2 pixels short from
what I expect. Need to fix this. */
status = _cairo_surface_composite (gstate->operator,
surface, mask, gstate->surface,
surface, pattern.source, gstate->surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
if (mask)
cairo_surface_destroy (mask);
if (status)
return status;
_cairo_pattern_fini (&pattern);
/* restore the matrix originally in the surface */
cairo_surface_set_matrix (surface, &user_to_image);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
@ -1908,39 +1978,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
return status;
}
static cairo_status_t
setup_text_rendering_context(cairo_gstate_t *gstate,
cairo_matrix_t *user_to_source)
{
cairo_status_t status;
cairo_matrix_t device_to_source;
status = _cairo_gstate_ensure_source (gstate);
if (status)
return status;
/* XXX: This same source matrix manipulation code shows up in
about 3 or 4 places. We should move that into a shared function
or two. */
if (! gstate->source_is_solid) {
cairo_surface_get_matrix (gstate->source, user_to_source);
cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, user_to_source);
cairo_surface_set_matrix (gstate->source, &device_to_source);
}
return CAIRO_STATUS_SUCCESS;
}
static void
restore_text_rendering_context(cairo_gstate_t *gstate,
cairo_matrix_t *user_to_source)
{
/* restore the matrix originally in the source surface */
if (! gstate->source_is_solid)
cairo_surface_set_matrix (gstate->source, user_to_source);
}
cairo_status_t
_cairo_gstate_show_text (cairo_gstate_t *gstate,
const unsigned char *utf8)
@ -1948,8 +1985,10 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate,
cairo_status_t status;
cairo_point_t point;
double x, y;
cairo_matrix_t user_to_source;
cairo_matrix_t saved_font_matrix;
cairo_pattern_t pattern;
cairo_text_extents_t text_extents;
cairo_box_t extents;
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
@ -1960,35 +1999,47 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate,
x = _cairo_fixed_to_double (point.x);
y = _cairo_fixed_to_double (point.y);
}
status = setup_text_rendering_context (gstate, &user_to_source);
if (status)
return status;
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
_cairo_pattern_init_copy (&pattern, gstate->pattern);
status = _cairo_gstate_text_extents (gstate, utf8, &text_extents);
if (status)
return status;
extents.p1.x = _cairo_fixed_from_double (x);
extents.p1.y = _cairo_fixed_from_double (y);
extents.p2.x = _cairo_fixed_from_double (x + text_extents.width);
extents.p2.y = _cairo_fixed_from_double (y + text_extents.height);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
return status;
status = _cairo_font_show_text (gstate->font,
gstate->operator, gstate->source,
gstate->operator, pattern.source,
gstate->surface, x, y, utf8);
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
restore_text_rendering_context (gstate, &user_to_source);
_cairo_pattern_fini (&pattern);
return status;
}
cairo_status_t
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
cairo_matrix_t user_to_source;
cairo_matrix_t saved_font_matrix;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_pattern_t pattern;
cairo_text_extents_t text_extents;
cairo_box_t extents;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
@ -2002,20 +2053,33 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
&(transformed_glyphs[i].y));
}
status = setup_text_rendering_context (gstate, &user_to_source);
if (status)
return status;
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
_cairo_pattern_init_copy (&pattern, gstate->pattern);
_cairo_gstate_glyph_extents (gstate, transformed_glyphs, num_glyphs,
&text_extents);
if (status)
return status;
extents.p1.x = _cairo_fixed_from_double (transformed_glyphs[0].x);
extents.p1.y = _cairo_fixed_from_double (transformed_glyphs[0].y);
extents.p2.x = _cairo_fixed_from_double (transformed_glyphs[0].x +
text_extents.width);
extents.p2.y = _cairo_fixed_from_double (transformed_glyphs[0].y +
text_extents.height);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
return status;
status = _cairo_font_show_glyphs (gstate->font,
gstate->operator, gstate->source,
gstate->operator, pattern.source,
gstate->surface,
transformed_glyphs, num_glyphs);
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
restore_text_rendering_context (gstate, &user_to_source);
_cairo_pattern_fini (&pattern);
free (transformed_glyphs);
@ -2028,15 +2092,10 @@ _cairo_gstate_text_path (cairo_gstate_t *gstate,
const unsigned char *utf8)
{
cairo_status_t status;
cairo_matrix_t user_to_source;
cairo_matrix_t saved_font_matrix;
cairo_point_t point;
double x, y;
status = setup_text_rendering_context (gstate, &user_to_source);
if (status)
return status;
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
x = 0;
@ -2056,7 +2115,6 @@ _cairo_gstate_text_path (cairo_gstate_t *gstate,
&gstate->path);
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
restore_text_rendering_context (gstate, &user_to_source);
return status;
}
@ -2070,7 +2128,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
cairo_status_t status;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_matrix_t user_to_source;
cairo_matrix_t saved_font_matrix;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
@ -2085,10 +2142,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
&(transformed_glyphs[i].y));
}
status = setup_text_rendering_context (gstate, &user_to_source);
if (status)
return status;
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
@ -2097,8 +2150,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
&gstate->path);
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
restore_text_rendering_context (gstate, &user_to_source);
free (transformed_glyphs);
return status;
}

View file

@ -467,6 +467,26 @@ _cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_abstract_surface_create_pattern (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_box_t *box)
{
cairo_image_surface_t *image;
/* Fall back to general pattern creation for surface patterns. */
if (pattern->type == CAIRO_PATTERN_SURFACE)
return CAIRO_INT_STATUS_UNSUPPORTED;
image = _cairo_pattern_get_image (pattern, box);
if (image) {
pattern->source = &image->base;
return CAIRO_STATUS_SUCCESS;
} else
return CAIRO_STATUS_NO_MEMORY;
}
static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
_cairo_image_abstract_surface_destroy,
@ -481,5 +501,6 @@ static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_composite_trapezoids,
_cairo_image_surface_copy_page,
_cairo_image_surface_show_page,
_cairo_image_abstract_surface_set_clip_region
_cairo_image_abstract_surface_set_clip_region,
_cairo_image_abstract_surface_create_pattern
};

View file

@ -306,6 +306,13 @@ _cairo_png_surface_set_clip_region (void *abstract_surface,
return _cairo_image_surface_set_clip_region (surface->image, region);
}
static cairo_int_status_t
_cairo_png_surface_create_pattern (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_box_t *extents)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static const cairo_surface_backend_t cairo_png_surface_backend = {
_cairo_png_surface_create_similar,
@ -321,5 +328,6 @@ static const cairo_surface_backend_t cairo_png_surface_backend = {
_cairo_png_surface_composite_trapezoids,
_cairo_png_surface_copy_page,
_cairo_png_surface_show_page,
_cairo_png_surface_set_clip_region
_cairo_png_surface_set_clip_region,
_cairo_png_surface_create_pattern
};

View file

@ -403,6 +403,13 @@ _cairo_ps_surface_set_clip_region (void *abstract_surface,
return _cairo_image_surface_set_clip_region (surface->image, region);
}
static cairo_int_status_t
_cairo_ps_surface_create_pattern (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_box_t *extents)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static const cairo_surface_backend_t cairo_ps_surface_backend = {
_cairo_ps_surface_create_similar,
@ -418,5 +425,6 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = {
_cairo_ps_surface_composite_trapezoids,
_cairo_ps_surface_copy_page,
_cairo_ps_surface_show_page,
_cairo_ps_surface_set_clip_region
_cairo_ps_surface_set_clip_region,
_cairo_ps_surface_create_pattern
};

View file

@ -377,3 +377,111 @@ _cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *reg
{
return surface->backend->set_clip_region (surface, region);
}
cairo_status_t
_cairo_surface_create_pattern (cairo_surface_t *surface,
cairo_pattern_t *pattern,
cairo_box_t *box)
{
cairo_int_status_t status;
status = surface->backend->create_pattern (surface, pattern, box);
/* The backend cannot accelerate this pattern, lets create an
unaccelerated source instead. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = CAIRO_STATUS_SUCCESS;
switch (pattern->type) {
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL: {
cairo_image_surface_t *image;
image = _cairo_pattern_get_image (pattern, box);
if (image) {
pattern->source = &image->base;
return CAIRO_STATUS_SUCCESS;
} else
return CAIRO_STATUS_NO_MEMORY;
} break;
case CAIRO_PATTERN_SOLID:
pattern->source =
_cairo_surface_create_similar_solid (surface,
CAIRO_FORMAT_ARGB32,
1, 1,
&pattern->color);
if (pattern->source) {
cairo_surface_set_repeat (pattern->source, 1);
return CAIRO_STATUS_SUCCESS;
} else
return CAIRO_STATUS_NO_MEMORY;
break;
case CAIRO_PATTERN_SURFACE:
status = CAIRO_INT_STATUS_UNSUPPORTED;
/* handle pattern opacity */
if (pattern->color.alpha != 1.0) {
int width = ceil (_cairo_fixed_to_double (box->p2.x) -
_cairo_fixed_to_double (box->p1.x));
int height = ceil (_cairo_fixed_to_double (box->p2.y) -
_cairo_fixed_to_double (box->p1.y));
cairo_pattern_t alpha;
pattern->source =
cairo_surface_create_similar (surface,
CAIRO_FORMAT_ARGB32,
width, height);
if (pattern->source) {
_cairo_pattern_init_solid (&alpha, 1.0, 1.0, 1.0);
_cairo_pattern_set_alpha (&alpha, pattern->color.alpha);
status = _cairo_surface_create_pattern (pattern->source,
&alpha, box);
if (status == CAIRO_STATUS_SUCCESS) {
int save_repeat = pattern->u.surface.surface->repeat;
if (pattern->extend == CAIRO_EXTEND_REPEAT ||
pattern->u.surface.surface->repeat == 1)
cairo_surface_set_repeat (pattern->u.surface.surface, 1);
else
cairo_surface_set_repeat (pattern->u.surface.surface, 0);
status =
_cairo_surface_composite (CAIRO_OPERATOR_OVER,
pattern->u.surface.surface,
alpha.source,
pattern->source,
0, 0, 0, 0, 0, 0,
width, height);
cairo_surface_set_repeat (pattern->u.surface.surface,
save_repeat);
if (status == CAIRO_STATUS_SUCCESS) {
_cairo_pattern_add_source_offset (pattern,
_cairo_fixed_to_double (box->p1.x),
_cairo_fixed_to_double (box->p1.y));
} else
cairo_surface_destroy (pattern->source);
}
_cairo_pattern_fini (&alpha);
}
}
if (status != CAIRO_STATUS_SUCCESS) {
pattern->source = pattern->u.surface.surface;
cairo_surface_reference (pattern->u.surface.surface);
return CAIRO_STATUS_SUCCESS;
}
break;
}
}
return status;
}

View file

@ -608,3 +608,40 @@ _cairo_traps_contain (cairo_traps_t *traps, double x, double y)
return 0;
}
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
static void
_cairo_trap_extents (cairo_trapezoid_t *t, cairo_box_t *extents)
{
cairo_fixed_t x;
if (t->top < extents->p1.y)
extents->p1.y = t->top;
if (t->bottom > extents->p2.y)
extents->p2.y = t->bottom;
x = MIN (_compute_x (&t->left, t->top),
_compute_x (&t->left, t->bottom));
if (x < extents->p1.x)
extents->p1.x = x;
x = MAX (_compute_x (&t->right, t->top),
_compute_x (&t->right, t->bottom));
if (x > extents->p2.x)
extents->p2.x = x;
}
void
_cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
{
int i;
extents->p1.x = extents->p1.y = SHRT_MAX << 16;
extents->p2.x = extents->p2.y = SHRT_MIN << 16;
for (i = 0; i < traps->num_traps; i++)
_cairo_trap_extents (&traps->traps[i], extents);
}

View file

@ -712,6 +712,14 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_int_status_t
_cairo_xcb_surface_create_pattern (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_box_t *extents)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static const struct cairo_surface_backend cairo_xcb_surface_backend = {
_cairo_xcb_surface_create_similar,
_cairo_xcb_surface_destroy,
@ -726,7 +734,8 @@ static const struct cairo_surface_backend cairo_xcb_surface_backend = {
_cairo_xcb_surface_composite_trapezoids,
_cairo_xcb_surface_copy_page,
_cairo_xcb_surface_show_page,
_cairo_xcb_surface_set_clip_region
_cairo_xcb_surface_set_clip_region,
_cairo_xcb_surface_create_pattern
};
static void

View file

@ -455,7 +455,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
cairo_xlib_surface_t *mask = (cairo_xlib_surface_t *) generic_mask;
cairo_xlib_surface_t *src_clone = NULL;
cairo_xlib_surface_t *mask_clone = NULL;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -619,6 +619,14 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_xlib_surface_create_pattern (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_box_t *extents)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_create_similar,
_cairo_xlib_surface_destroy,
@ -633,7 +641,8 @@ static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_composite_trapezoids,
_cairo_xlib_surface_copy_page,
_cairo_xlib_surface_show_page,
_cairo_xlib_surface_set_clip_region
_cairo_xlib_surface_set_clip_region,
_cairo_xlib_surface_create_pattern
};
cairo_surface_t *
@ -692,7 +701,7 @@ cairo_xlib_surface_create (Display *dpy,
0, NULL);
else
surface->picture = 0;
return (cairo_surface_t *) surface;
}
DEPRECATE (cairo_surface_create_for_drawable, cairo_xlib_surface_create);

View file

@ -135,10 +135,15 @@ typedef struct cairo_point_double {
double y;
} cairo_point_double_t;
typedef struct cairo_distance_double {
double dx;
double dy;
} cairo_distance_double_t;
typedef struct cairo_line {
cairo_point_t p1;
cairo_point_t p2;
} cairo_line_t;
} cairo_line_t, cairo_box_t;
typedef struct cairo_trapezoid {
cairo_fixed_t top, bottom;
@ -376,6 +381,10 @@ typedef struct cairo_surface_backend {
cairo_int_status_t
(*set_clip_region) (void *surface,
pixman_region16_t *region);
cairo_int_status_t
(*create_pattern) (void *surface,
cairo_pattern_t *pattern,
cairo_box_t *extents);
} cairo_surface_backend_t;
struct cairo_matrix {
@ -433,6 +442,59 @@ struct cairo_color {
unsigned short alpha_short;
};
#define CAIRO_EXTEND_DEFAULT CAIRO_EXTEND_NONE
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_NEAREST
typedef enum {
CAIRO_PATTERN_SOLID,
CAIRO_PATTERN_SURFACE,
CAIRO_PATTERN_LINEAR,
CAIRO_PATTERN_RADIAL
} cairo_pattern_type_t;
typedef struct cairo_color_stop {
double offset;
int id;
cairo_color_t color;
unsigned char color_char[4];
} cairo_color_stop_t;
struct cairo_pattern {
unsigned int ref_count;
cairo_extend_t extend;
cairo_filter_t filter;
cairo_matrix_t matrix;
cairo_color_stop_t *stops;
int n_stops;
cairo_color_t color;
cairo_surface_t *source;
cairo_point_double_t source_offset;
cairo_pattern_type_t type;
union {
struct {
cairo_surface_t *surface;
cairo_matrix_t save_matrix;
int save_repeat;
cairo_filter_t save_filter;
} surface;
struct {
cairo_point_double_t point0;
cairo_point_double_t point1;
} linear;
struct {
cairo_point_double_t center0;
cairo_point_double_t center1;
cairo_distance_double_t radius0;
cairo_distance_double_t radius1;
} radial;
} u;
};
typedef struct cairo_traps {
cairo_trapezoid_t *traps;
int num_traps;
@ -492,15 +554,12 @@ typedef struct cairo_gstate {
cairo_surface_t *surface;
cairo_surface_t *source;
cairo_point_double_t source_offset;
int source_is_solid;
cairo_pattern_t *pattern;
cairo_point_double_t pattern_offset;
double alpha;
cairo_clip_rec_t clip;
double alpha;
cairo_color_t color;
double pixels_per_inch;
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
@ -526,6 +585,10 @@ typedef struct cairo_stroke_face {
cairo_point_double_t usr_vector;
} cairo_stroke_face_t;
/* cairo.c */
extern void __internal_linkage
_cairo_restrict_value (double *value, double min, double max);
/* cairo_fixed.c */
extern cairo_fixed_t __internal_linkage
_cairo_fixed_from_int (int i);
@ -574,7 +637,10 @@ extern cairo_surface_t * __internal_linkage
_cairo_gstate_current_target_surface (cairo_gstate_t *gstate);
extern cairo_status_t __internal_linkage
_cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_surface_t *pattern);
_cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_pattern_t *pattern);
extern cairo_pattern_t *__internal_linkage
_cairo_gstate_current_pattern (cairo_gstate_t *gstate);
extern cairo_status_t __internal_linkage
_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t operator);
@ -744,6 +810,16 @@ _cairo_gstate_copy_page (cairo_gstate_t *gstate);
extern cairo_status_t __internal_linkage
_cairo_gstate_show_page (cairo_gstate_t *gstate);
extern cairo_status_t __internal_linkage
_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
double *x1, double *y1,
double *x2, double *y2);
extern cairo_status_t __internal_linkage
_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
double *x1, double *y1,
double *x2, double *y2);
extern cairo_status_t __internal_linkage
_cairo_gstate_in_stroke (cairo_gstate_t *gstate,
double x,
@ -1042,9 +1118,6 @@ _cairo_surface_copy_page (cairo_surface_t *surface);
extern cairo_status_t __internal_linkage
_cairo_surface_show_page (cairo_surface_t *surface);
extern cairo_status_t __internal_linkage
_cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *region);
extern double __internal_linkage
_cairo_surface_pixels_per_inch (cairo_surface_t *surface);
@ -1055,6 +1128,14 @@ extern cairo_status_t __internal_linkage
_cairo_surface_set_image (cairo_surface_t *surface,
cairo_image_surface_t *image);
extern cairo_status_t __internal_linkage
_cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *region);
extern cairo_status_t __internal_linkage
_cairo_surface_create_pattern (cairo_surface_t *surface,
cairo_pattern_t *pattern,
cairo_box_t *extents);
/* cairo_image_surface.c */
extern cairo_image_surface_t * __internal_linkage
@ -1209,6 +1290,9 @@ _cairo_traps_tessellate_polygon (cairo_traps_t *traps,
extern int __internal_linkage
_cairo_traps_contain (cairo_traps_t *traps, double x, double y);
extern void __internal_linkage
_cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents);
/* cairo_slope.c */
extern void __internal_linkage
_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b);
@ -1222,6 +1306,50 @@ _cairo_slope_clockwise (cairo_slope_t *a, cairo_slope_t *b);
extern int __internal_linkage
_cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b);
/* cairo_pattern.c */
extern void __internal_linkage
_cairo_pattern_init (cairo_pattern_t *pattern);
extern cairo_status_t __internal_linkage
_cairo_pattern_init_copy (cairo_pattern_t *pattern, cairo_pattern_t *other);
extern void __internal_linkage
_cairo_pattern_fini (cairo_pattern_t *pattern);
extern void __internal_linkage
_cairo_pattern_init_solid (cairo_pattern_t *pattern,
double red, double green, double blue);
extern cairo_pattern_t *__internal_linkage
_cairo_pattern_create_solid (double red, double green, double blue);
extern cairo_status_t __internal_linkage
_cairo_pattern_get_rgb (cairo_pattern_t *pattern,
double *red, double *green, double *blue);
extern void __internal_linkage
_cairo_pattern_set_alpha (cairo_pattern_t *pattern, double alpha);
extern void __internal_linkage
_cairo_pattern_add_source_offset (cairo_pattern_t *pattern,
double x, double y);
extern void __internal_linkage
_cairo_pattern_transform (cairo_pattern_t *pattern,
cairo_matrix_t *matrix,
cairo_matrix_t *matrix_inverse);
extern void __internal_linkage
_cairo_pattern_prepare_surface (cairo_pattern_t *pattern);
extern void __internal_linkage
_cairo_pattern_calc_color_at_pixel (cairo_pattern_t *pattern,
double factor,
int *pixel);
extern cairo_image_surface_t *__internal_linkage
_cairo_pattern_get_image (cairo_pattern_t *pattern, cairo_box_t *box);
/* Avoid unnecessary PLT entries. */
slim_hidden_proto(cairo_close_path)