mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-08 10:18:02 +02:00
Added new pattern API
This commit is contained in:
parent
b17b04aa38
commit
e309090d2a
24 changed files with 1339 additions and 530 deletions
82
ChangeLog
82
ChangeLog
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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@
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ===========================================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
33
src/cairo.c
33
src/cairo.c
|
|
@ -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)
|
||||
|
|
|
|||
75
src/cairo.h
75
src/cairo.h
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
150
src/cairoint.h
150
src/cairoint.h
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue