summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2006-02-13 16:46:06 -0800
committerCarl Worth <cworth@cworth.org>2006-02-13 16:46:06 -0800
commit1d28eecd8b8dd5b3082bcdbb0455df1ad825bba7 (patch)
tree8be9d3a1dfe0a25ba6eb98a45e719229e51b4f2f
parent7146e2fc48df28d462ddeab81dc3c55bee4a7527 (diff)
parent2f7b4a3ad7a0760af023d350685d1acfdc528d2c (diff)
Remove pixman from SNAPSHOT_0_1_23SNAPSHOT_0_1_23
-rw-r--r--BUGS19
-rw-r--r--ChangeLog159
-rw-r--r--NEWS41
-rw-r--r--RELEASING28
-rw-r--r--TODO7
-rw-r--r--configure.in4
-rw-r--r--src/cairo-ft-font.c2
-rw-r--r--src/cairo-gstate.c16
-rw-r--r--src/cairo-pattern.c439
-rw-r--r--src/cairo-spline.c7
-rw-r--r--src/cairo-surface.c16
-rw-r--r--src/cairo-traps.c4
-rw-r--r--src/cairo.h1
-rw-r--r--src/cairo_ft_font.c2
-rw-r--r--src/cairo_gl_surface.c194
-rw-r--r--src/cairo_gstate.c16
-rw-r--r--src/cairo_pattern.c439
-rw-r--r--src/cairo_png_surface.c231
-rw-r--r--src/cairo_spline.c7
-rw-r--r--src/cairo_surface.c16
-rw-r--r--src/cairo_traps.c4
-rw-r--r--src/cairoint.h54
22 files changed, 1056 insertions, 650 deletions
diff --git a/BUGS b/BUGS
index cbeacccd9..c53b26d41 100644
--- a/BUGS
+++ b/BUGS
@@ -1,3 +1,9 @@
+cairo_clip is returning the wrong result in several cases. And when it
+doesn't get the wrong result, it is horribly slow. This really needs
+to be fixed.
+
+--
+
Splines are not dashed.
--
@@ -57,5 +63,16 @@ Caps are added only to the last subpath in a complex path.
--
ref_counts will go negative if destroy is called with ref_count ==
-0. We noticed this is cairo_surface.c but it likely happens in several
+0. We noticed this in cairo_surface.c but it likely happens in several
places.
+
+--
+
+Patterns are broken in various ways. The SVG test case demonstrates
+some regressions, so something has changed in cairo. Also,
+transformation plus repeat doesn't work in either Xrender or
+libpixman, (nor in glitz?).
+
+--
+
+font-size="0" in an SVG file does very bad things.
diff --git a/ChangeLog b/ChangeLog
index 00a3f762c..4122184da 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,162 @@
+2004-05-11 Carl Worth <cworth@isi.edu>
+
+ * configure.in: Increment CAIRO_VERSION to 0.1.23.
+
+ * NEWS: Added notes for snapshot 0.1.23.
+
+ * RELEASING: Add reminder to mention incompatible API changes in
+ NEWS. Re-order steps to avoid clobbering pre-existing tar
+ files.
+
+2004-05-11 Carl Worth <cworth@isi.edu>
+
+ * BUGS: Several people have reported that cairo_clip is not
+ working right now. And it's always been slow.
+
+2004-05-11 David Reveman <c99drn@cs.umu.se>
+
+ * configure.in: Require glitz 0.1.2.
+
+ * src/cairo_gl_surface.c: Added opacity attribute. Fixed broken
+ CAIRO_GL_COMPOSITE_TRAPEZOIDS_SUPPORT macro.
+ (_cairo_gl_surface_composite_trapezoids): Use polygon opacity.
+ (_cairo_gl_surface_create_pattern): Added surface pattern support.
+ (_cairo_gl_surface_create): Initialize opacity to 0xffff.
+
+2004-05-07 Carl Worth <cworth@isi.edu>
+
+ * src/cairo_ft_font.c (_utf8_to_ucs4): Bail on NULL utf8 string.
+
+ * src/cairo_spline.c (_cairo_spline_add_point): Don't add two
+ consecutive, identical points when decomposing the spline, (which
+ was leading to an infinte loop in the stroke algorithm when it
+ found a slope of (0,0)).
+
+2004-05-04 Carl Worth <cworth@isi.edu>
+
+ * src/cairo_png_surface.c (cairo_png_surface_create): Move all
+ libpng-related code into copy_page.
+ (unpremultiply_data): Add missing unpremultiply step.
+ (_cairo_png_surface_copy_page): Move PNG output to copy_page. Add
+ support for A8 and A1 images. Remove time from header (we may want
+ to add it again later, but for now it messes up my test suite).
+ (_cairo_png_surface_destroy): Call copy_page if it hasn't been
+ called already.
+ (_cairo_png_surface_show_page): Add implementation.
+ (_cairo_png_surface_copy_page): Don't close a file we didn't open.
+
+2004-05-04 David Reveman <c99drn@cs.umu.se>
+
+ * src/cairo_pattern.c (_cairo_image_data_set_radial): Corrected some
+ confusing comments about the math used for radial gradients.
+
+2004-05-01 David Reveman <c99drn@cs.umu.se>
+
+ * src/cairo_gl_surface.c (_cairo_gl_surface_create_pattern):
+ cairo_surface_t pointer to cairo_surface_set_matrix.
+
+2004-04-29 Carl Worth <cworth@isi.edu>
+
+ * src/cairo_gstate.c (_cairo_gstate_set_pattern): Don't set
+ pattern_offset by the current point. Perhaps we can eliminate
+ pattern_offset altogether now?
+
+2004-04-30 David Reveman <c99drn@cs.umu.se>
+
+ * src/cairoint.h: Radial patterns only store radius per circle.
+ Only inverse CTM to _cairo_pattern_transform.
+
+ * src/cairo_pattern.c (cairo_pattern_create_radial): Only one radius
+ per circle now.
+ (_cairo_pattern_transform): A matrix multiplication with inverse CTM
+ is all that's needed here.
+ (_cairo_pattern_calc_color_at_pixel): Fixed extend type reflect.
+ (_cairo_image_data_set_linear): New linear gradient code.
+ Transformation of linear gradient is now handled correctly.
+ (_cairo_image_data_set_radial): New radial gradient code. Inner circle
+ is now used for creating radial gradients. Transformation of radial
+ gradient is now handled correctly.
+ (_cairo_pattern_get_image): Fixed handling of pattern offset.
+
+ * src/cairo_gstate.c (_cairo_gstate_create_pattern): All pattern types
+ are transformed using inverse CTM.
+
+ * src/cairo_gl_surface.c (_cairo_gl_surface_create_pattern): Updated
+ to use glitz's new linear and radial gradients.
+
+ * configure.in: Require glitz 0.1.1.
+
+2004-04-28 David Reveman <c99drn@cs.umu.se>
+
+ * src/cairo_gl_surface.c: Added CAIRO_GL_MULTITEXTURE_SUPPORT and
+ CAIRO_GL_SURFACE_IS_SOLID macros.
+ (_cairo_gl_surface_get_image): Simpler way for calculating rowstride.
+ (_cairo_gl_surface_composite): Support compositing with mask surface
+ when mask is solid or multi-texturing is available.
+
+2004-04-25 David Reveman <c99drn@cs.umu.se>
+
+ * src/cairo_gl_surface.c (_cairo_gl_surface_set_clip_region):
+ Fixed conversion of pixman_box16_t to glitz_rectangle_t.
+
+ * src/cairoint.h: Added scale factor value to cairo_color_stop_t.
+ Added cairo_shader_function_t and cairo_shader_op_t.
+
+ * src/cairo_surface.c (_cairo_surface_create_pattern):
+ Fixed point updates.
+
+ * src/cairo_pattern.c (cairo_pattern_create_radial): Use absolute value
+ of radius parameters.
+ (cairo_pattern_add_color_stop): Precalculate scale factors and convert
+ offset to fixed point value.
+ (_cairo_image_data_set_radial):
+ (_cairo_image_data_set_linear): Initialize and use shading operator.
+ (_cairo_pattern_get_image): Fixed point updates.
+ (_cairo_pattern_shader_nearest):
+ (_cairo_pattern_shader_linear):
+ (_cairo_pattern_shader_gaussian):
+ (_cairo_pattern_calc_color_at_pixel):
+ Converted shading routines to use fixed point values and introduced
+ a shading operator structure for more efficient shading calculations.
+ Added _cairo_pattern_shader_init function.
+
+ * src/cairo_gl_surface.c (_cairo_gl_surface_composite):
+ (_cairo_gl_surface_fill_rectangles):
+ (_cairo_gl_surface_composite_trapezoids):
+ Make sure that target surface is OK.
+ (_cairo_gl_create_color_range): Initialize and use shading operator.
+ (_cairo_gl_surface_create_pattern):
+ (_cairo_gl_surface_set_clip_region): Fixed point updates.
+
+2004-04-23 Carl Worth <cworth@isi.edu>
+
+ * src/cairoint.h:
+ * src/cairo_surface.c (_cairo_surface_composite):
+ * src/cairo_gstate.c (_cairo_gstate_current_fill_rule): Fixed
+ several function prototype mismatches between internal header file
+ and implementation (thanks to Carlos Romero and gcc-3.4).
+
+2004-04-22 David Reveman <c99drn@cs.umu.se>
+
+ * src/cairoint.h:
+ * src/cairo_surface.c (_cairo_surface_create_pattern):
+ * src/cairo_pattern.c (_cairo_pattern_set_source_offset)
+ (_cairo_pattern_get_image):
+ * src/cairo_gstate.c (_cairo_gstate_create_pattern):
+ * src/cairo_gl_surface.c (_cairo_gl_surface_create_pattern): Fixed
+ pattern source offset.
+
+2004-04-20 David Reveman <c99drn@cs.umu.se>
+
+ * src/cairo_pattern.c (_cairo_image_data_set_linear): Use
+ CAIRO_MAXSHORT instead of INT_MAX.
+
+ * src/cairo_traps.c (_cairo_traps_extents): Use CAIRO_MAXSHORT and
+ CAIRO_MINSHORT instead of SHRT_MAX and SHRT_MIN.
+
+ * src/cairoint.h: including limits.h and defining CAIRO_MAXSHORT and
+ CAIRO_MINSHORT.
+
2004-04-16 Carl Worth <cworth@isi.edu>
* NEWS: Added notes for snapshot 0.1.22.
diff --git a/NEWS b/NEWS
index 4ca426f65..5b1e62312 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,44 @@
+Snapshot 0.1.23 (2004-05-11 Carl Worth <cworth@isi.edu>)
+========================================================
+Fixes for gcc 3.4
+-----------------
+Fix prototype mismatches so that cairo can be built by gcc 3.4.
+
+Updates to track glitz
+----------------------
+Various fixes to support the latest glitz snapshot (0.1.2).
+
+Gradient updates
+----------------
+Radial gradients now support both inner and outer circles.
+Transformed linear gradients are now properly handled.
+Fixes for extend type reflect.
+
+Glitz updates
+-------------
+Converted shading routines to use fixed point values and introduced a
+shading operator structure for more efficient shading calculations.
+Support compositing with mask surface when mask is solid or
+multi-texturing is available.
+
+PNG backend cleanups
+--------------------
+Fix output to properly compensate for pre-multiplied alpha format in cairo.
+Add support for A8 and A1 image formats.
+
+Bug fixes
+---------
+Avoid crash or infinite loop on null strings and degeneratively short
+splines.
+
+New? bugs in cairo_clip
+-----------------------
+There are some fairly serious bugs in cairo_clip. It is sometimes
+causing an incorrect result. And even when it does work, it is
+sometimes so slow as to be unusable. Some of these bugs may not be
+new, (indeed cairo_clip has only ever had a braindead-slow
+implementation), but I think they're worth mentioning here.
+
Snapshot 0.1.22 (2004-04-16 Carl Worth <cworth@isi.edu>)
========================================================
Cairo was updated to track the changes in libpixman, and now depends
diff --git a/RELEASING b/RELEASING
index 05f821f76..64ebb43fa 100644
--- a/RELEASING
+++ b/RELEASING
@@ -13,7 +13,15 @@ snapshots.
version numbers in order to get access to a specific set of
features.
-2) Verify that the code passes "make distcheck"
+2) Increment CAIRO_VERSION in configure.in
+
+ Right now, in its pre-release form, we are incrementing
+ CAIRO_VERSION for each snapshot but we are not changing the
+ libtool shared library version information. Until now, we've
+ only incremented the sub-minor version. We'll invent rules for
+ incrementing major and minor numbers when the time is right.
+
+3) Verify that the code passes "make distcheck"
Running "make distcheck" should result in no warnings or
errors and end with a message of the form:
@@ -25,19 +33,13 @@ snapshots.
(But the tar file isn't actually ready yet, as we still have
some more steps to follow).
-3) Fill out an entry in the NEWS file
+4) Fill out an entry in the NEWS file
Sift through the information in ChangeLog since the last
snapshot. Summarize major changes briefly in a style similar
- to other entries in NEWS.
-
-4) Increment CAIRO_VERSION in configure.in
-
- Right now, in its pre-release form, we are incrementing
- CAIRO_VERSION for each snapshot but we are not changing the
- libtool shared library version information. Until now, we've
- only incremented the sub-minor version. We'll invent rules for
- incrementing major and minor numbers when the time is right.
+ to other entries in NEWS. Take special care to note any
+ incompatible changes in the API. These should be easy to find
+ by looking for cairo.h in the ChangeLog.
5) Commit the changes to NEWS and configure.in
@@ -45,8 +47,8 @@ snapshots.
other commit. It's especially important to mention the new
version number in the ChangeLog.
-6) Run "make distcheck" to generate the final tar file with the
- correct version number.
+6) Run "make distcheck" to generate the final tar file including the
+ changes to NEWS and ChangeLog.
7) Copy the resulting tar file to the cairo snapshots distribution
directory:
diff --git a/TODO b/TODO
index e4dd69d37..d06fee883 100644
--- a/TODO
+++ b/TODO
@@ -13,6 +13,9 @@ problems with stroking self-intersecting paths.
* Implement cairo_stroke_path, (very easy to do after the above change
is done).
+* Re-work the backend clipping interface to use geometry rather than
+images.
+
* Fix the intersection problem, (see reference to Hobby's paper
mentioned in cairo_traps.c).
@@ -57,8 +60,8 @@ functions:
* Re-implement the trapezoid rasterization algorithm according to the
new "specification".
-* Stroking degenerate paths should still draw caps. Round caps are
-easy; square should probably draw an axis aligned square.
+* Stroking closed, degenerate paths should still draw caps. Round
+caps are easy; square should probably draw an axis aligned square.
* Verification, profiling, optimization.
diff --git a/configure.in b/configure.in
index 674981551..3ac8f8459 100644
--- a/configure.in
+++ b/configure.in
@@ -3,7 +3,7 @@ AC_INIT(src/cairo.h)
dnl ===========================================================================
# Package version number, (as distinct from shared library version)
-CAIRO_VERSION=0.1.22
+CAIRO_VERSION=0.1.23
# libtool shared library version
@@ -141,7 +141,7 @@ AC_ARG_ENABLE(gl,
[use_gl=$enableval], [use_gl=yes])
if test "x$use_gl" = "xyes"; then
- PKG_CHECK_MODULES(GL, glitz >= 0.1.0, [
+ PKG_CHECK_MODULES(GL, glitz >= 0.1.2, [
GL_REQUIRES=glitz
use_gl=yes], [use_gl="no (requires glitz http://freedesktop.org/software/glitz)"])
fi
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 77cf59b0d..c1c8d6ea0 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -241,7 +241,7 @@ _utf8_to_ucs4 (char const *utf8,
size_t n = 0, alloc = 0;
FcChar32 u = 0;
- if (ucs4 == NULL || nchars == NULL)
+ if (utf8 == NULL || ucs4 == NULL || nchars == NULL)
return;
len = strlen (utf8);
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index ed8c8a1a8..0ff24c15d 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -363,10 +363,6 @@ _cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_pattern_t *pattern)
gstate->pattern = pattern;
cairo_pattern_reference (pattern);
-
- _cairo_gstate_current_point (gstate,
- &gstate->pattern_offset.x,
- &gstate->pattern_offset.y);
return CAIRO_STATUS_SUCCESS;
}
@@ -452,7 +448,7 @@ _cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
+cairo_fill_rule_t
_cairo_gstate_current_fill_rule (cairo_gstate_t *gstate)
{
return gstate->fill_rule;
@@ -1278,7 +1274,11 @@ _cairo_gstate_create_pattern (cairo_gstate_t *gstate,
}
_cairo_pattern_set_alpha (pattern, gstate->alpha);
- _cairo_pattern_transform (pattern, &gstate->ctm, &gstate->ctm_inverse);
+ _cairo_pattern_transform (pattern, &gstate->ctm_inverse);
+
+ _cairo_pattern_set_source_offset (pattern,
+ gstate->pattern_offset.x,
+ gstate->pattern_offset.y);
status = _cairo_surface_create_pattern (gstate->surface, pattern, extents);
if (status) {
@@ -1288,10 +1288,6 @@ _cairo_gstate_create_pattern (cairo_gstate_t *gstate,
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;
}
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 6464d23f9..b81b1bd01 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -175,12 +175,10 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
pattern->type = CAIRO_PATTERN_RADIAL;
pattern->u.radial.center0.x = cx0;
pattern->u.radial.center0.y = cy0;
- pattern->u.radial.radius0.dx = radius0;
- pattern->u.radial.radius0.dy = radius0;
+ pattern->u.radial.radius0 = fabs (radius0);
pattern->u.radial.center1.x = cx1;
pattern->u.radial.center1.y = cy1;
- pattern->u.radial.radius1.dx = radius1;
- pattern->u.radial.radius1.dy = radius1;
+ pattern->u.radial.radius1 = fabs (radius1);
return pattern;
}
@@ -229,6 +227,7 @@ cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
double alpha)
{
cairo_color_stop_t *stop;
+ int i;
_cairo_restrict_value (&offset, 0.0, 1.0);
_cairo_restrict_value (&red, 0.0, 1.0);
@@ -246,7 +245,7 @@ cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
stop = &pattern->stops[pattern->n_stops - 1];
- stop->offset = offset;
+ stop->offset = _cairo_fixed_from_double (offset);
stop->id = pattern->n_stops;
_cairo_color_init (&stop->color);
_cairo_color_set_rgb (&stop->color, red, green, blue);
@@ -260,6 +259,13 @@ cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
qsort (pattern->stops, pattern->n_stops, sizeof (cairo_color_stop_t),
_cairo_pattern_stop_compare);
+ for (i = 0; i < pattern->n_stops - 1; i++) {
+ pattern->stops[i + 1].scale =
+ pattern->stops[i + 1].offset - pattern->stops[i].offset;
+ if (pattern->stops[i + 1].scale == 65536)
+ pattern->stops[i + 1].scale = 0;
+ }
+
return CAIRO_STATUS_SUCCESS;
}
@@ -336,54 +342,18 @@ _cairo_pattern_set_alpha (cairo_pattern_t *pattern, double alpha)
}
void
-_cairo_pattern_add_source_offset (cairo_pattern_t *pattern,
+_cairo_pattern_set_source_offset (cairo_pattern_t *pattern,
double x, double y)
{
- pattern->source_offset.x += x;
- pattern->source_offset.y += y;
+ pattern->source_offset.x = x;
+ pattern->source_offset.y = y;
}
void
_cairo_pattern_transform (cairo_pattern_t *pattern,
- cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse)
{
- cairo_matrix_t matrix;
-
- switch (pattern->type) {
- case CAIRO_PATTERN_SURFACE:
- /* hmm, maybe we should instead multiply with the inverse of the
- pattern matrix here? */
- cairo_matrix_multiply (&pattern->matrix, ctm_inverse,
- &pattern->matrix);
- break;
- case CAIRO_PATTERN_LINEAR:
- cairo_matrix_multiply (&matrix, &pattern->matrix, ctm);
- cairo_matrix_transform_point (&matrix,
- &pattern->u.linear.point0.x,
- &pattern->u.linear.point0.y);
- cairo_matrix_transform_point (&matrix,
- &pattern->u.linear.point1.x,
- &pattern->u.linear.point1.y);
- break;
- case CAIRO_PATTERN_RADIAL:
- cairo_matrix_multiply (&matrix, &pattern->matrix, ctm);
- cairo_matrix_transform_point (&matrix,
- &pattern->u.radial.center0.x,
- &pattern->u.radial.center0.y);
- cairo_matrix_transform_distance (&matrix,
- &pattern->u.radial.radius0.dx,
- &pattern->u.radial.radius0.dy);
- cairo_matrix_transform_point (&matrix,
- &pattern->u.radial.center1.x,
- &pattern->u.radial.center1.y);
- cairo_matrix_transform_distance (&matrix,
- &pattern->u.radial.radius1.dx,
- &pattern->u.radial.radius1.dy);
- break;
- case CAIRO_PATTERN_SOLID:
- break;
- }
+ cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
}
void
@@ -419,135 +389,127 @@ _cairo_pattern_prepare_surface (cairo_pattern_t *pattern)
cairo_surface_set_filter (pattern->source, pattern->filter);
}
-typedef void (*cairo_shader_function_t) (unsigned char *color0,
- unsigned char *color1,
- double factor,
- unsigned char *result_color);
-
#define INTERPOLATE_COLOR_NEAREST(c1, c2, factor) \
- ((unsigned char) ((factor < 0.5)? c1: c2))
+ ((factor < 32768)? c1: c2)
static void
_cairo_pattern_shader_nearest (unsigned char *color0,
unsigned char *color1,
- double factor,
- unsigned char *result_color)
+ cairo_fixed_t factor,
+ int *pixel)
{
- result_color[0] = INTERPOLATE_COLOR_NEAREST (color0[0], color1[0], factor);
- result_color[1] = INTERPOLATE_COLOR_NEAREST (color0[1], color1[1], factor);
- result_color[2] = INTERPOLATE_COLOR_NEAREST (color0[2], color1[2], factor);
- result_color[3] = INTERPOLATE_COLOR_NEAREST (color0[3], color1[3], factor);
+ *pixel =
+ ((INTERPOLATE_COLOR_NEAREST (color0[3], color1[3], factor) << 24) |
+ (INTERPOLATE_COLOR_NEAREST (color0[0], color1[0], factor) << 16) |
+ (INTERPOLATE_COLOR_NEAREST (color0[1], color1[1], factor) << 8) |
+ (INTERPOLATE_COLOR_NEAREST (color0[2], color1[2], factor) << 0));
}
#undef INTERPOLATE_COLOR_NEAREST
#define INTERPOLATE_COLOR_LINEAR(c1, c2, factor) \
- ((unsigned char) ((c2 * factor) + (c1 * (1.0 - factor))))
+ (((c2 * factor) + (c1 * (65536 - factor))) / 65536)
static void
_cairo_pattern_shader_linear (unsigned char *color0,
unsigned char *color1,
- double factor,
- unsigned char *result_color)
+ cairo_fixed_t factor,
+ int *pixel)
{
- result_color[0] = INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor);
- result_color[1] = INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor);
- result_color[2] = INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor);
- result_color[3] = INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor);
+ *pixel = ((INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor) << 24) |
+ (INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor) << 16) |
+ (INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor) << 8) |
+ (INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0));
}
+#define E_MINUS_ONE 1.7182818284590452354
+
static void
_cairo_pattern_shader_gaussian (unsigned char *color0,
unsigned char *color1,
- double factor,
- unsigned char *result_color)
+ cairo_fixed_t factor,
+ int *pixel)
{
- factor = (exp (factor * factor) - 1.0) / (M_E - 1.0);
+ double f = ((double) factor) / 65536.0;
- result_color[0] = INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor);
- result_color[1] = INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor);
- result_color[2] = INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor);
- result_color[3] = INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor);
+ factor = (cairo_fixed_t) (((exp (f * f) - 1.0) / E_MINUS_ONE) * 65536);
+
+ *pixel = ((INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor) << 24) |
+ (INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor) << 16) |
+ (INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor) << 8) |
+ (INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0));
}
#undef INTERPOLATE_COLOR_LINEAR
void
-_cairo_pattern_calc_color_at_pixel (cairo_pattern_t *pattern,
- double factor,
- int *pixel)
+_cairo_pattern_shader_init (cairo_pattern_t *pattern,
+ cairo_shader_op_t *op)
{
- int p, colorstop;
- double factorscale;
- unsigned char result_color[4];
- cairo_shader_function_t shader_function;
-
+ op->stops = pattern->stops;
+ op->n_stops = pattern->n_stops - 1;
+ op->min_offset = pattern->stops[0].offset;
+ op->max_offset = pattern->stops[op->n_stops].offset;
+ op->extend = pattern->extend;
+
switch (pattern->filter) {
case CAIRO_FILTER_FAST:
case CAIRO_FILTER_NEAREST:
- shader_function = _cairo_pattern_shader_nearest;
+ op->shader_function = _cairo_pattern_shader_nearest;
break;
case CAIRO_FILTER_GAUSSIAN:
- shader_function = _cairo_pattern_shader_gaussian;
+ op->shader_function = _cairo_pattern_shader_gaussian;
break;
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:
- shader_function = _cairo_pattern_shader_linear;
+ op->shader_function = _cairo_pattern_shader_linear;
break;
}
+}
+
+void
+_cairo_pattern_calc_color_at_pixel (cairo_shader_op_t *op,
+ cairo_fixed_t factor,
+ int *pixel)
+{
+ int i;
- if (factor > 1.0 || factor < 0.0) {
- switch (pattern->extend) {
- case CAIRO_EXTEND_REPEAT:
- factor -= floor (factor);
- break;
- case CAIRO_EXTEND_REFLECT:
- if (factor >= 0.0) {
- if (((int) factor) % 2)
- factor = 1.0 - (factor - floor (factor));
- else
- factor -= floor (factor);
- } else {
- if (((int) factor) % 2)
- factor -= floor (factor);
- else
- factor = 1.0 - (factor - floor (factor));
- }
- break;
- case CAIRO_EXTEND_NONE:
- break;
+ switch (op->extend) {
+ case CAIRO_EXTEND_REPEAT:
+ factor -= factor & 0xffff0000;
+ break;
+ case CAIRO_EXTEND_REFLECT:
+ if (factor < 0 || factor > 65536) {
+ if ((factor >> 16) % 2)
+ factor = 65536 - (factor - (factor & 0xffff0000));
+ else
+ factor -= factor & 0xffff0000;
}
+ break;
+ case CAIRO_EXTEND_NONE:
+ break;
}
-
- if (factor < pattern->stops[0].offset)
- factor = pattern->stops[0].offset;
- if (factor > pattern->stops[pattern->n_stops - 1].offset)
- factor = pattern->stops[pattern->n_stops - 1].offset;
-
- for (colorstop = 0; colorstop < pattern->n_stops - 1; colorstop++) {
- if (factor <= pattern->stops[colorstop + 1].offset) {
- factorscale = fabs (pattern->stops[colorstop].offset -
- pattern->stops[colorstop + 1].offset);
-
- /* abrubt change, difference between two offsets == 0.0 */
- if (factorscale == 0)
- break;
-
- factor -= pattern->stops[colorstop].offset;
+ if (factor < op->min_offset)
+ factor = op->min_offset;
+ else if (factor > op->max_offset)
+ factor = op->max_offset;
+ for (i = 0; i < op->n_stops; i++) {
+ if (factor <= op->stops[i + 1].offset) {
+
/* take offset as new 0 of coordinate system */
- factor /= factorscale;
-
- shader_function (pattern->stops[colorstop].color_char,
- pattern->stops[colorstop + 1].color_char,
- factor, result_color);
-
- p = ((result_color[3] << 24) |
- (result_color[0] << 16) |
- (result_color[1] << 8) | (result_color[2] << 0));
- *pixel = p;
+ factor -= op->stops[i].offset;
+
+ /* difference between two offsets == 0, abrubt change */
+ if (op->stops[i + 1].scale)
+ factor = ((cairo_fixed_48_16_t) factor << 16) /
+ op->stops[i + 1].scale;
+
+ op->shader_function (op->stops[i].color_char,
+ op->stops[i + 1].color_char,
+ factor, pixel);
break;
}
}
@@ -557,92 +519,164 @@ static void
_cairo_image_data_set_linear (cairo_pattern_t *pattern,
double offset_x,
double offset_y,
- char *data,
+ int *pixels,
int width,
int height)
{
int x, y;
- cairo_point_double_t point0, point1, angle;
- double a, length, start, end;
- double factor;
+ cairo_point_double_t point0, point1;
+ double px, py, ex, ey;
+ double a, b, c, d, tx, ty;
+ double length, start, angle, fx, fy, factor;
+ cairo_shader_op_t op;
+
+ _cairo_pattern_shader_init (pattern, &op);
- point0.x = pattern->u.linear.point0.x - offset_x;
- point0.y = pattern->u.linear.point0.y - offset_y;
- point1.x = pattern->u.linear.point1.x - offset_x;
- point1.y = pattern->u.linear.point1.y - offset_y;
+ point0.x = pattern->u.linear.point0.x;
+ point0.y = pattern->u.linear.point0.y;
+ point1.x = pattern->u.linear.point1.x;
+ point1.y = pattern->u.linear.point1.y;
+ cairo_matrix_get_affine (&pattern->matrix, &a, &b, &c, &d, &tx, &ty);
+
length = sqrt ((point1.x - point0.x) * (point1.x - point0.x) +
(point1.y - point0.y) * (point1.y - point0.y));
- length = (length) ? 1.0 / length : INT_MAX;
-
- a = -atan2 (point1.y - point0.y, point1.x - point0.x);
- angle.x = cos (a);
- angle.y = -sin (a);
+ length = (length) ? 1.0 / length : CAIRO_MAXSHORT;
- start = angle.x * point0.x;
- start += angle.y * point0.y;
-
- end = angle.x * point1.x;
- end += angle.y * point1.y;
+ angle = -atan2 (point1.y - point0.y, point1.x - point0.x);
+ fx = cos (angle);
+ fy = -sin (angle);
+
+ start = fx * point0.x;
+ start += fy * point0.y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
-
- factor = angle.x * (double) x;
- factor += angle.y * (double) y;
-
- factor = factor - start;
- factor *= length;
-
- _cairo_pattern_calc_color_at_pixel (pattern, factor, (int *)
- &data[y * width * 4 + x * 4]);
+ px = x + offset_x;
+ py = y + offset_y;
+
+ /* transform fragment */
+ ex = a * px + c * py + tx;
+ ey = b * px + d * py + ty;
+
+ factor = ((fx * ex + fy * ey) - start) * length;
+
+ _cairo_pattern_calc_color_at_pixel (&op, factor * 65536, pixels++);
}
}
}
-/* TODO: Inner circle is currently ignored. */
static void
_cairo_image_data_set_radial (cairo_pattern_t *pattern,
double offset_x,
double offset_y,
- char *data,
+ int *pixels,
int width,
int height)
{
- int x, y;
- cairo_point_double_t center1, pos;
- cairo_distance_double_t length;
- double factor;
- double min_length;
-
- center1.x = pattern->u.radial.center1.x - offset_x;
- center1.y = pattern->u.radial.center1.y - offset_y;
-
- min_length =
- fabs ((pattern->u.radial.radius1.dx < pattern->u.radial.radius1.dy) ?
- pattern->u.radial.radius1.dx : pattern->u.radial.radius1.dy);
-
- /* ugly */
- if (min_length == 0.0)
- min_length = 0.000001;
-
- length.dx = min_length / pattern->u.radial.radius1.dx;
- length.dy = min_length / pattern->u.radial.radius1.dy;
+ int x, y, aligned_circles;
+ cairo_point_double_t c0, c1;
+ double px, py, ex, ey;
+ double a, b, c, d, tx, ty;
+ double r0, r1, c0_e_x, c0_e_y, c0_e, c1_e_x, c1_e_y, c1_e,
+ c0_c1_x, c0_c1_y, c0_c1, angle_c0, c1_y, y_x, c0_y, c0_x, r1_2,
+ denumerator, fraction, factor;
+ cairo_shader_op_t op;
+
+ _cairo_pattern_shader_init (pattern, &op);
+
+ c0.x = pattern->u.radial.center0.x;
+ c0.y = pattern->u.radial.center0.y;
+ r0 = pattern->u.radial.radius0;
+ c1.x = pattern->u.radial.center1.x;
+ c1.y = pattern->u.radial.center1.y;
+ r1 = pattern->u.radial.radius1;
+
+ if (c0.x != c1.x || c0.y != c1.y) {
+ aligned_circles = 0;
+ c0_c1_x = c1.x - c0.x;
+ c0_c1_y = c1.y - c0.y;
+ c0_c1 = sqrt (c0_c1_x * c0_c1_x + c0_c1_y * c0_c1_y);
+ r1_2 = r1 * r1;
+ } else {
+ aligned_circles = 1;
+ r1 = 1.0 / (r1 - r0);
+ }
- min_length = 1.0 / min_length;
+ cairo_matrix_get_affine (&pattern->matrix, &a, &b, &c, &d, &tx, &ty);
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
- pos.x = x - center1.x;
- pos.y = y - center1.y;
-
- pos.x *= length.dx;
- pos.y *= length.dy;
-
- factor = sqrt (pos.x * pos.x + pos.y * pos.y) * min_length;
+ px = x + offset_x;
+ py = y + offset_y;
+
+ /* transform fragment */
+ ex = a * px + c * py + tx;
+ ey = b * px + d * py + ty;
+
+ if (aligned_circles) {
+ ex = ex - c1.x;
+ ey = ey - c1.y;
+
+ factor = (sqrt (ex * ex + ey * ey) - r0) * r1;
+ } else {
+ /*
+ y (ex, ey)
+ c0 -------------------+---------- x
+ \ | __--
+ \ | __--
+ \ | __--
+ \ | __-- r1
+ \ | __--
+ c1 --
+
+ We need to calulate distance c0->x; the distance from
+ the inner circle center c0, through fragment position
+ (ex, ey) to point x where it crosses the outer circle.
+
+ From points c0, c1 and (ex, ey) we get angle C0. With
+ angle C0 we calculate distance c1->y and c0->y and by
+ knowing c1->y and r1, we also know y->x. Adding y->x to
+ c0->y gives us c0->x. The gradient offset can then be
+ calculated as:
+
+ offset = (c0->e - r0) / (c0->x - r0)
+
+ */
+
+ c0_e_x = ex - c0.x;
+ c0_e_y = ey - c0.y;
+ c0_e = sqrt (c0_e_x * c0_e_x + c0_e_y * c0_e_y);
+
+ c1_e_x = ex - c1.x;
+ c1_e_y = ey - c1.y;
+ c1_e = sqrt (c1_e_x * c1_e_x + c1_e_y * c1_e_y);
+
+ denumerator = -2.0 * c0_e * c0_c1;
+
+ if (denumerator != 0.0) {
+ fraction = (c1_e * c1_e - c0_e * c0_e - c0_c1 * c0_c1) /
+ denumerator;
+
+ if (fraction > 1.0)
+ fraction = 1.0;
+ else if (fraction < -1.0)
+ fraction = -1.0;
+
+ angle_c0 = acos (fraction);
+
+ c0_y = cos (angle_c0) * c0_c1;
+ c1_y = sin (angle_c0) * c0_c1;
+
+ y_x = sqrt (r1_2 - c1_y * c1_y);
+ c0_x = y_x + c0_y;
+
+ factor = (c0_e - r0) / (c0_x - r0);
+ } else
+ factor = -r0;
+ }
- _cairo_pattern_calc_color_at_pixel (pattern, factor, (int *)
- &data[y * width * 4 + x * 4]);
+ _cairo_pattern_calc_color_at_pixel (&op, factor * 65536, pixels++);
}
}
}
@@ -656,35 +690,35 @@ _cairo_pattern_get_image (cairo_pattern_t *pattern, cairo_box_t *box)
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL: {
char *data;
- int width = ceil (_cairo_fixed_to_double (box->p2.x)) -
- floor (_cairo_fixed_to_double (box->p1.x));
- int height = ceil (_cairo_fixed_to_double (box->p2.y)) -
- floor (_cairo_fixed_to_double (box->p1.y));
+ double x = box->p1.x >> 16;
+ double y = box->p1.y >> 16;
+ int width = ((box->p2.x + 65535) >> 16) - (box->p1.x >> 16);
+ int height = ((box->p2.y + 65535) >> 16) - (box->p1.y >> 16);
data = malloc (width * height * 4);
if (!data)
return NULL;
-
- _cairo_pattern_add_source_offset (pattern,
- floor (_cairo_fixed_to_double (box->p1.x)),
- floor (_cairo_fixed_to_double (box->p1.y)));
-
+
if (pattern->type == CAIRO_PATTERN_RADIAL)
_cairo_image_data_set_radial (pattern,
- pattern->source_offset.x,
- pattern->source_offset.y,
- data, width, height);
+ x - pattern->source_offset.x,
+ y - pattern->source_offset.y,
+ (int *) data,
+ width, height);
else
_cairo_image_data_set_linear (pattern,
- pattern->source_offset.x,
- pattern->source_offset.y,
- data, width, height);
+ x - pattern->source_offset.x,
+ y - pattern->source_offset.y,
+ (int *) data,
+ width, height);
+
+ _cairo_pattern_set_source_offset (pattern, x, y);
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
width, height,
width * 4);
-
+
if (surface)
_cairo_image_surface_assume_ownership_of_data (
(cairo_image_surface_t *) surface);
@@ -714,3 +748,4 @@ _cairo_pattern_get_image (cairo_pattern_t *pattern, cairo_box_t *box)
return (cairo_image_surface_t *) surface;
}
+
diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index f05a9da55..6192f8636 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -118,6 +118,13 @@ static cairo_status_t
_cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point)
{
cairo_status_t status;
+ cairo_point_t *prev;
+
+ if (spline->num_points) {
+ prev = &spline->points[spline->num_points - 1];
+ if (prev->x == point->x && prev->y == point->y)
+ return CAIRO_STATUS_SUCCESS;
+ }
if (spline->num_points >= spline->points_size) {
status = _cairo_spline_grow_by (spline, CAIRO_SPLINE_GROWTH_INC);
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 60b4487d4..79eee57b2 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -203,7 +203,7 @@ cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
}
slim_hidden_def(cairo_surface_set_repeat);
-cairo_int_status_t
+cairo_status_t
_cairo_surface_composite (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *mask,
@@ -424,10 +424,10 @@ _cairo_surface_create_pattern (cairo_surface_t *surface,
/* handle pattern opacity */
if (pattern->color.alpha != 1.0) {
- int width = ceil (_cairo_fixed_to_double (box->p2.x)) -
- floor (_cairo_fixed_to_double (box->p1.x));
- int height = ceil (_cairo_fixed_to_double (box->p2.y)) -
- floor (_cairo_fixed_to_double (box->p1.y));
+ double x = box->p1.x >> 16;
+ double y = box->p1.y >> 16;
+ int width = ((box->p2.x + 65535) >> 16) - (box->p1.x >> 16);
+ int height = ((box->p2.y + 65535) >> 16) - (box->p1.y >> 16);
cairo_pattern_t alpha;
pattern->source =
@@ -462,9 +462,9 @@ _cairo_surface_create_pattern (cairo_surface_t *surface,
save_repeat);
if (status == CAIRO_STATUS_SUCCESS) {
- _cairo_pattern_add_source_offset (pattern,
- floor (_cairo_fixed_to_double (box->p1.x)),
- floor (_cairo_fixed_to_double (box->p1.y)));
+ _cairo_pattern_set_source_offset (pattern,
+ pattern->source_offset.x + x,
+ pattern->source_offset.y + y);
} else
cairo_surface_destroy (pattern->source);
}
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 9b44d38ea..d17a27281 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -639,8 +639,8 @@ _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;
+ extents->p1.x = extents->p1.y = CAIRO_MAXSHORT << 16;
+ extents->p2.x = extents->p2.y = CAIRO_MINSHORT << 16;
for (i = 0; i < traps->num_traps; i++)
_cairo_trap_extents (&traps->traps[i], extents);
diff --git a/src/cairo.h b/src/cairo.h
index a5cb20cd2..ab7cca724 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -378,6 +378,7 @@ cairo_fill_extents (cairo_t *cr,
void
cairo_init_clip (cairo_t *cr);
+/* Note: cairo_clip does not consume the current path */
void
cairo_clip (cairo_t *cr);
diff --git a/src/cairo_ft_font.c b/src/cairo_ft_font.c
index 77cf59b0d..c1c8d6ea0 100644
--- a/src/cairo_ft_font.c
+++ b/src/cairo_ft_font.c
@@ -241,7 +241,7 @@ _utf8_to_ucs4 (char const *utf8,
size_t n = 0, alloc = 0;
FcChar32 u = 0;
- if (ucs4 == NULL || nchars == NULL)
+ if (utf8 == NULL || ucs4 == NULL || nchars == NULL)
return;
len = strlen (utf8);
diff --git a/src/cairo_gl_surface.c b/src/cairo_gl_surface.c
index cb9871f6b..3a60302bd 100644
--- a/src/cairo_gl_surface.c
+++ b/src/cairo_gl_surface.c
@@ -64,6 +64,7 @@ struct cairo_gl_surface {
long int features;
long int hints;
int owns_surface;
+ unsigned short opacity;
cairo_pattern_t pattern;
cairo_box_t pattern_box;
@@ -71,6 +72,9 @@ struct cairo_gl_surface {
glitz_surface_t *surface;
};
+#define CAIRO_GL_MULTITEXTURE_SUPPORT(surface) \
+ (surface->features & GLITZ_FEATURE_ARB_MULTITEXTURE_MASK)
+
#define CAIRO_GL_OFFSCREEN_SUPPORT(surface) \
(surface->features & GLITZ_FEATURE_OFFSCREEN_DRAWING_MASK)
@@ -87,13 +91,17 @@ struct cairo_gl_surface {
(surface->features & GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK)
#define CAIRO_GL_COMPOSITE_TRAPEZOIDS_SUPPORT(surface) \
- ((surface->format->stencil_size < \
- ((surface->hints & GLITZ_HINT_CLIPPING_MASK)? 2: 1)) && \
- (!CAIRO_GL_OFFSCREEN_SUPPORT (surface)))
+ ((surface->format->stencil_size >= \
+ ((surface->hints & GLITZ_HINT_CLIPPING_MASK)? 2: 1)) || \
+ CAIRO_GL_OFFSCREEN_SUPPORT (surface))
#define CAIRO_GL_SURFACE_IS_OFFSCREEN(surface) \
(surface->hints & GLITZ_HINT_OFFSCREEN_MASK)
+#define CAIRO_GL_SURFACE_IS_SOLID(surface) \
+ ((surface->hints & GLITZ_HINT_PROGRAMMATIC_MASK) && \
+ (surface->pattern.type == CAIRO_PATTERN_SOLID))
+
static void
_cairo_gl_surface_destroy (void *abstract_surface)
{
@@ -130,8 +138,7 @@ _cairo_gl_surface_get_image (void *abstract_surface)
width = glitz_surface_get_width (surface->surface);
height = glitz_surface_get_height (surface->surface);
- rowstride = width * (surface->format->bpp / 8);
- rowstride += (rowstride % 4) ? (4 - (rowstride % 4)) : 0;
+ rowstride = (width * (surface->format->bpp / 8) + 3) & -4;
pixels = (char *) malloc (sizeof (char) * height * rowstride);
@@ -382,16 +389,21 @@ _cairo_gl_surface_composite (cairo_operator_t operator,
cairo_gl_surface_t *src_clone = NULL;
cairo_gl_surface_t *mask_clone = NULL;
+ /* Make sure that target surface is OK. */
+ if (glitz_surface_get_status (dst->surface))
+ return CAIRO_STATUS_NO_TARGET_SURFACE;
+
/* If destination surface is offscreen, then offscreen drawing support is
required. */
if (CAIRO_GL_SURFACE_IS_OFFSCREEN (dst) &&
(!CAIRO_GL_OFFSCREEN_SUPPORT (dst)))
return CAIRO_INT_STATUS_UNSUPPORTED;
- /* Fragment program or offscreen drawing required for composite with
- mask. */
+ /* We need multi-texturing or offscreen drawing when compositing with
+ non-solid mask. */
if (mask &&
- (!CAIRO_GL_FRAGMENT_PROGRAM_SUPPORT (dst)) &&
+ (!CAIRO_GL_SURFACE_IS_SOLID (mask)) &&
+ (!CAIRO_GL_MULTITEXTURE_SUPPORT (dst)) &&
(!CAIRO_GL_OFFSCREEN_SUPPORT (dst)))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -440,6 +452,10 @@ _cairo_gl_surface_fill_rectangles (void *abstract_surface,
cairo_gl_surface_t *surface = abstract_surface;
glitz_color_t glitz_color;
+ /* Make sure that target surface is OK. */
+ if (glitz_surface_get_status (surface->surface))
+ return CAIRO_STATUS_NO_TARGET_SURFACE;
+
/* If destination surface is offscreen, then offscreen drawing support is
required. */
if (CAIRO_GL_SURFACE_IS_OFFSCREEN (surface) &&
@@ -495,13 +511,17 @@ _cairo_gl_surface_composite_trapezoids (cairo_operator_t operator,
cairo_gl_surface_t *src = (cairo_gl_surface_t *) generic_src;
cairo_gl_surface_t *src_clone = NULL;
+ /* Make sure that target surface is OK. */
+ if (glitz_surface_get_status (dst->surface))
+ return CAIRO_STATUS_NO_TARGET_SURFACE;
+
/* If destination surface is offscreen, then offscreen drawing support is
required. */
if (CAIRO_GL_SURFACE_IS_OFFSCREEN (dst) &&
(!CAIRO_GL_OFFSCREEN_SUPPORT (dst)))
return CAIRO_INT_STATUS_UNSUPPORTED;
- /* Need to get current hints as clipping might have changed. */
+ /* Need to get current hints as clipping may have changed. */
dst->hints = glitz_surface_get_hints (dst->surface);
/* Solid source? */
@@ -527,10 +547,14 @@ _cairo_gl_surface_composite_trapezoids (cairo_operator_t operator,
src = src_clone;
}
+ glitz_surface_set_polyopacity (dst->surface, src->opacity);
+
glitz_composite_trapezoids (_glitz_operator (operator),
src->surface, dst->surface,
x_src, y_src, (glitz_trapezoid_t *) traps,
num_traps);
+
+ glitz_surface_set_polyopacity (dst->surface, 0xffff);
if (src_clone)
cairo_surface_destroy (&src_clone->base);
@@ -570,9 +594,13 @@ _cairo_gl_create_color_range (cairo_pattern_t *pattern,
unsigned int size)
{
unsigned int i, bytes = size * 4;
+ cairo_shader_op_t op;
+
+ _cairo_pattern_shader_init (pattern, &op);
for (i = 0; i < bytes; i += 4)
- _cairo_pattern_calc_color_at_pixel (pattern, i / (double) bytes,
+ _cairo_pattern_calc_color_at_pixel (&op,
+ ((double) i / bytes) * 65536,
(int *) &data[i]);
}
@@ -582,10 +610,8 @@ _cairo_gl_surface_create_pattern (void *abstract_surface,
cairo_box_t *box)
{
cairo_gl_surface_t *surface = abstract_surface;
- glitz_surface_t *programmatic = NULL;
- cairo_gl_surface_t *gl_surface;
- double x = floor (_cairo_fixed_to_double (box->p1.x));
- double y = floor (_cairo_fixed_to_double (box->p1.y));
+ glitz_surface_t *source = NULL;
+ cairo_gl_surface_t *src;
switch (pattern->type) {
case CAIRO_PATTERN_SOLID: {
@@ -596,9 +622,8 @@ _cairo_gl_surface_create_pattern (void *abstract_surface,
color.blue = pattern->color.blue_short;
color.alpha = pattern->color.alpha_short;
- programmatic = glitz_surface_create_solid (&color);
- }
- break;
+ source = glitz_surface_create_solid (&color);
+ } break;
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL: {
unsigned int color_range_size;
@@ -617,26 +642,17 @@ _cairo_gl_surface_create_pattern (void *abstract_surface,
if (pattern->type == CAIRO_PATTERN_LINEAR) {
double dx, dy;
- dx = (pattern->u.linear.point1.x - x) -
- (pattern->u.linear.point0.x - x);
- dy = (pattern->u.linear.point1.y - y) -
- (pattern->u.linear.point0.y - y);
-
+ dx = pattern->u.linear.point1.x - pattern->u.linear.point0.x;
+ dy = pattern->u.linear.point1.y - pattern->u.linear.point0.y;
+
color_range_size = sqrt (dx * dx + dy * dy);
} else {
- /* libglitz doesn't support inner circle. */
- if (pattern->u.radial.center0.x !=
- pattern->u.radial.center1.x
- || pattern->u.radial.center0.y !=
- pattern->u.radial.center1.y
- || pattern->u.radial.radius0.dx
- || pattern->u.radial.radius0.dy)
+ /* glitz doesn't support inner circle yet. */
+ if (pattern->u.radial.center0.x != pattern->u.radial.center1.x ||
+ pattern->u.radial.center0.y != pattern->u.radial.center1.y)
return CAIRO_INT_STATUS_UNSUPPORTED;
- color_range_size = sqrt (pattern->u.radial.radius1.dx *
- pattern->u.radial.radius1.dx +
- pattern->u.radial.radius1.dy *
- pattern->u.radial.radius1.dy);
+ color_range_size = pattern->u.radial.radius1;
}
if ((!CAIRO_GL_TEXTURE_NPOT_SUPPORT (surface)))
@@ -647,8 +663,8 @@ _cairo_gl_surface_create_pattern (void *abstract_surface,
return CAIRO_STATUS_NO_MEMORY;
_cairo_gl_create_color_range (pattern,
- glitz_color_range_get_data
- (color_range), color_range_size);
+ glitz_color_range_get_data (color_range),
+ color_range_size);
switch (pattern->extend) {
case CAIRO_EXTEND_REPEAT:
@@ -662,62 +678,89 @@ _cairo_gl_surface_create_pattern (void *abstract_surface,
break;
}
+ glitz_color_range_set_filter (color_range, GLITZ_FILTER_BILINEAR);
+
if (pattern->type == CAIRO_PATTERN_LINEAR) {
glitz_point_fixed_t start;
glitz_point_fixed_t stop;
- start.x =
- _cairo_fixed_from_double (pattern->u.linear.point0.x - x);
- start.y =
- _cairo_fixed_from_double (pattern->u.linear.point0.y - y);
- stop.x = _cairo_fixed_from_double (pattern->u.linear.point1.x - x);
- stop.y = _cairo_fixed_from_double (pattern->u.linear.point1.y - y);
+ start.x = _cairo_fixed_from_double (pattern->u.linear.point0.x);
+ start.y = _cairo_fixed_from_double (pattern->u.linear.point0.y);
+ stop.x = _cairo_fixed_from_double (pattern->u.linear.point1.x);
+ stop.y = _cairo_fixed_from_double (pattern->u.linear.point1.y);
- programmatic =
- glitz_surface_create_linear (&start, &stop, color_range);
+ source = glitz_surface_create_linear (&start, &stop, color_range);
} else {
glitz_point_fixed_t center;
- glitz_distance_fixed_t radius;
-
- center.x =
- _cairo_fixed_from_double (pattern->u.radial.center1.x - x);
- center.y =
- _cairo_fixed_from_double (pattern->u.radial.center1.y - y);
- radius.dx =
- _cairo_fixed_from_double (pattern->u.radial.radius1.dx);
- radius.dy =
- _cairo_fixed_from_double (pattern->u.radial.radius1.dy);
-
- programmatic =
- glitz_surface_create_radial (&center, &radius, color_range);
+
+ center.x = _cairo_fixed_from_double (pattern->u.radial.center1.x);
+ center.y = _cairo_fixed_from_double (pattern->u.radial.center1.y);
+
+ source = glitz_surface_create_radial
+ (&center,
+ _cairo_fixed_from_double (pattern->u.radial.radius0),
+ _cairo_fixed_from_double (pattern->u.radial.radius1),
+ color_range);
}
glitz_color_range_destroy (color_range);
- }
- break;
- default:
+ } break;
+ case CAIRO_PATTERN_SURFACE:
+ if (CAIRO_GL_COMPOSITE_TRAPEZOIDS_SUPPORT (surface)) {
+ cairo_gl_surface_t *src_clone = NULL;
+ cairo_surface_t *generic_src = pattern->u.surface.surface;
+
+ src = (cairo_gl_surface_t *) generic_src;
+ if (generic_src->backend != surface->base.backend) {
+ src_clone =
+ _cairo_gl_surface_clone_similar (generic_src, surface,
+ CAIRO_FORMAT_ARGB32);
+ if (!src_clone)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ } else {
+ src_clone = (cairo_gl_surface_t *)
+ _cairo_gl_surface_create (src->surface, 0);
+ if (!src_clone)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ cairo_surface_set_filter
+ (&src_clone->base, cairo_surface_get_filter (generic_src));
+
+ cairo_surface_set_matrix (&src_clone->base,
+ &generic_src->matrix);
+ }
+
+ cairo_surface_set_repeat (&src_clone->base, generic_src->repeat);
+
+ src_clone->opacity = (unsigned short)
+ (pattern->color.alpha * 0xffff);
+
+ pattern->source = &src_clone->base;
+
+ return CAIRO_STATUS_SUCCESS;
+ }
return CAIRO_INT_STATUS_UNSUPPORTED;
break;
}
-
- if (!programmatic)
+
+ if (!source)
return CAIRO_STATUS_NO_MEMORY;
- gl_surface = (cairo_gl_surface_t *)
- _cairo_gl_surface_create (programmatic, 1);
- if (!gl_surface) {
- glitz_surface_destroy (programmatic);
-
+ src = (cairo_gl_surface_t *) _cairo_gl_surface_create (source, 1);
+ if (!src) {
+ glitz_surface_destroy (source);
+
return CAIRO_STATUS_NO_MEMORY;
}
+
+ if (pattern->type == CAIRO_PATTERN_LINEAR ||
+ pattern->type == CAIRO_PATTERN_RADIAL)
+ cairo_surface_set_matrix (&src->base, &pattern->matrix);
- _cairo_pattern_init_copy (&gl_surface->pattern, pattern);
- gl_surface->pattern_box = *box;
-
- pattern->source = &gl_surface->base;
- _cairo_pattern_add_source_offset (pattern,
- floor (_cairo_fixed_to_double (box->p1.x)),
- floor (_cairo_fixed_to_double (box->p1.y)));
+ _cairo_pattern_init_copy (&src->pattern, pattern);
+ src->pattern_box = *box;
+
+ pattern->source = &src->base;
return CAIRO_STATUS_SUCCESS;
}
@@ -757,8 +800,8 @@ _cairo_gl_surface_set_clip_region (void *abstract_surface,
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < n; n++, box++) {
- clip_rects[i].x = (short) box->x1;
- clip_rects[i].y = (short) box->y1;
+ clip_rects[i].x = box->x1;
+ clip_rects[i].y = box->y1;
clip_rects[i].width = (unsigned short) (box->x2 - box->x1);
clip_rects[i].height = (unsigned short) (box->y2 - box->y1);
}
@@ -810,6 +853,7 @@ _cairo_gl_surface_create (glitz_surface_t *surface, int owns_surface)
crsurface->features = glitz_surface_get_features (surface);
crsurface->hints = glitz_surface_get_hints (surface);
crsurface->owns_surface = owns_surface;
+ crsurface->opacity = 0xffff;
return (cairo_surface_t *) crsurface;
}
diff --git a/src/cairo_gstate.c b/src/cairo_gstate.c
index ed8c8a1a8..0ff24c15d 100644
--- a/src/cairo_gstate.c
+++ b/src/cairo_gstate.c
@@ -363,10 +363,6 @@ _cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_pattern_t *pattern)
gstate->pattern = pattern;
cairo_pattern_reference (pattern);
-
- _cairo_gstate_current_point (gstate,
- &gstate->pattern_offset.x,
- &gstate->pattern_offset.y);
return CAIRO_STATUS_SUCCESS;
}
@@ -452,7 +448,7 @@ _cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
+cairo_fill_rule_t
_cairo_gstate_current_fill_rule (cairo_gstate_t *gstate)
{
return gstate->fill_rule;
@@ -1278,7 +1274,11 @@ _cairo_gstate_create_pattern (cairo_gstate_t *gstate,
}
_cairo_pattern_set_alpha (pattern, gstate->alpha);
- _cairo_pattern_transform (pattern, &gstate->ctm, &gstate->ctm_inverse);
+ _cairo_pattern_transform (pattern, &gstate->ctm_inverse);
+
+ _cairo_pattern_set_source_offset (pattern,
+ gstate->pattern_offset.x,
+ gstate->pattern_offset.y);
status = _cairo_surface_create_pattern (gstate->surface, pattern, extents);
if (status) {
@@ -1288,10 +1288,6 @@ _cairo_gstate_create_pattern (cairo_gstate_t *gstate,
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;
}
diff --git a/src/cairo_pattern.c b/src/cairo_pattern.c
index 6464d23f9..b81b1bd01 100644
--- a/src/cairo_pattern.c
+++ b/src/cairo_pattern.c
@@ -175,12 +175,10 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
pattern->type = CAIRO_PATTERN_RADIAL;
pattern->u.radial.center0.x = cx0;
pattern->u.radial.center0.y = cy0;
- pattern->u.radial.radius0.dx = radius0;
- pattern->u.radial.radius0.dy = radius0;
+ pattern->u.radial.radius0 = fabs (radius0);
pattern->u.radial.center1.x = cx1;
pattern->u.radial.center1.y = cy1;
- pattern->u.radial.radius1.dx = radius1;
- pattern->u.radial.radius1.dy = radius1;
+ pattern->u.radial.radius1 = fabs (radius1);
return pattern;
}
@@ -229,6 +227,7 @@ cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
double alpha)
{
cairo_color_stop_t *stop;
+ int i;
_cairo_restrict_value (&offset, 0.0, 1.0);
_cairo_restrict_value (&red, 0.0, 1.0);
@@ -246,7 +245,7 @@ cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
stop = &pattern->stops[pattern->n_stops - 1];
- stop->offset = offset;
+ stop->offset = _cairo_fixed_from_double (offset);
stop->id = pattern->n_stops;
_cairo_color_init (&stop->color);
_cairo_color_set_rgb (&stop->color, red, green, blue);
@@ -260,6 +259,13 @@ cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
qsort (pattern->stops, pattern->n_stops, sizeof (cairo_color_stop_t),
_cairo_pattern_stop_compare);
+ for (i = 0; i < pattern->n_stops - 1; i++) {
+ pattern->stops[i + 1].scale =
+ pattern->stops[i + 1].offset - pattern->stops[i].offset;
+ if (pattern->stops[i + 1].scale == 65536)
+ pattern->stops[i + 1].scale = 0;
+ }
+
return CAIRO_STATUS_SUCCESS;
}
@@ -336,54 +342,18 @@ _cairo_pattern_set_alpha (cairo_pattern_t *pattern, double alpha)
}
void
-_cairo_pattern_add_source_offset (cairo_pattern_t *pattern,
+_cairo_pattern_set_source_offset (cairo_pattern_t *pattern,
double x, double y)
{
- pattern->source_offset.x += x;
- pattern->source_offset.y += y;
+ pattern->source_offset.x = x;
+ pattern->source_offset.y = y;
}
void
_cairo_pattern_transform (cairo_pattern_t *pattern,
- cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse)
{
- cairo_matrix_t matrix;
-
- switch (pattern->type) {
- case CAIRO_PATTERN_SURFACE:
- /* hmm, maybe we should instead multiply with the inverse of the
- pattern matrix here? */
- cairo_matrix_multiply (&pattern->matrix, ctm_inverse,
- &pattern->matrix);
- break;
- case CAIRO_PATTERN_LINEAR:
- cairo_matrix_multiply (&matrix, &pattern->matrix, ctm);
- cairo_matrix_transform_point (&matrix,
- &pattern->u.linear.point0.x,
- &pattern->u.linear.point0.y);
- cairo_matrix_transform_point (&matrix,
- &pattern->u.linear.point1.x,
- &pattern->u.linear.point1.y);
- break;
- case CAIRO_PATTERN_RADIAL:
- cairo_matrix_multiply (&matrix, &pattern->matrix, ctm);
- cairo_matrix_transform_point (&matrix,
- &pattern->u.radial.center0.x,
- &pattern->u.radial.center0.y);
- cairo_matrix_transform_distance (&matrix,
- &pattern->u.radial.radius0.dx,
- &pattern->u.radial.radius0.dy);
- cairo_matrix_transform_point (&matrix,
- &pattern->u.radial.center1.x,
- &pattern->u.radial.center1.y);
- cairo_matrix_transform_distance (&matrix,
- &pattern->u.radial.radius1.dx,
- &pattern->u.radial.radius1.dy);
- break;
- case CAIRO_PATTERN_SOLID:
- break;
- }
+ cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
}
void
@@ -419,135 +389,127 @@ _cairo_pattern_prepare_surface (cairo_pattern_t *pattern)
cairo_surface_set_filter (pattern->source, pattern->filter);
}
-typedef void (*cairo_shader_function_t) (unsigned char *color0,
- unsigned char *color1,
- double factor,
- unsigned char *result_color);
-
#define INTERPOLATE_COLOR_NEAREST(c1, c2, factor) \
- ((unsigned char) ((factor < 0.5)? c1: c2))
+ ((factor < 32768)? c1: c2)
static void
_cairo_pattern_shader_nearest (unsigned char *color0,
unsigned char *color1,
- double factor,
- unsigned char *result_color)
+ cairo_fixed_t factor,
+ int *pixel)
{
- result_color[0] = INTERPOLATE_COLOR_NEAREST (color0[0], color1[0], factor);
- result_color[1] = INTERPOLATE_COLOR_NEAREST (color0[1], color1[1], factor);
- result_color[2] = INTERPOLATE_COLOR_NEAREST (color0[2], color1[2], factor);
- result_color[3] = INTERPOLATE_COLOR_NEAREST (color0[3], color1[3], factor);
+ *pixel =
+ ((INTERPOLATE_COLOR_NEAREST (color0[3], color1[3], factor) << 24) |
+ (INTERPOLATE_COLOR_NEAREST (color0[0], color1[0], factor) << 16) |
+ (INTERPOLATE_COLOR_NEAREST (color0[1], color1[1], factor) << 8) |
+ (INTERPOLATE_COLOR_NEAREST (color0[2], color1[2], factor) << 0));
}
#undef INTERPOLATE_COLOR_NEAREST
#define INTERPOLATE_COLOR_LINEAR(c1, c2, factor) \
- ((unsigned char) ((c2 * factor) + (c1 * (1.0 - factor))))
+ (((c2 * factor) + (c1 * (65536 - factor))) / 65536)
static void
_cairo_pattern_shader_linear (unsigned char *color0,
unsigned char *color1,
- double factor,
- unsigned char *result_color)
+ cairo_fixed_t factor,
+ int *pixel)
{
- result_color[0] = INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor);
- result_color[1] = INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor);
- result_color[2] = INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor);
- result_color[3] = INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor);
+ *pixel = ((INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor) << 24) |
+ (INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor) << 16) |
+ (INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor) << 8) |
+ (INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0));
}
+#define E_MINUS_ONE 1.7182818284590452354
+
static void
_cairo_pattern_shader_gaussian (unsigned char *color0,
unsigned char *color1,
- double factor,
- unsigned char *result_color)
+ cairo_fixed_t factor,
+ int *pixel)
{
- factor = (exp (factor * factor) - 1.0) / (M_E - 1.0);
+ double f = ((double) factor) / 65536.0;
- result_color[0] = INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor);
- result_color[1] = INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor);
- result_color[2] = INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor);
- result_color[3] = INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor);
+ factor = (cairo_fixed_t) (((exp (f * f) - 1.0) / E_MINUS_ONE) * 65536);
+
+ *pixel = ((INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor) << 24) |
+ (INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor) << 16) |
+ (INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor) << 8) |
+ (INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0));
}
#undef INTERPOLATE_COLOR_LINEAR
void
-_cairo_pattern_calc_color_at_pixel (cairo_pattern_t *pattern,
- double factor,
- int *pixel)
+_cairo_pattern_shader_init (cairo_pattern_t *pattern,
+ cairo_shader_op_t *op)
{
- int p, colorstop;
- double factorscale;
- unsigned char result_color[4];
- cairo_shader_function_t shader_function;
-
+ op->stops = pattern->stops;
+ op->n_stops = pattern->n_stops - 1;
+ op->min_offset = pattern->stops[0].offset;
+ op->max_offset = pattern->stops[op->n_stops].offset;
+ op->extend = pattern->extend;
+
switch (pattern->filter) {
case CAIRO_FILTER_FAST:
case CAIRO_FILTER_NEAREST:
- shader_function = _cairo_pattern_shader_nearest;
+ op->shader_function = _cairo_pattern_shader_nearest;
break;
case CAIRO_FILTER_GAUSSIAN:
- shader_function = _cairo_pattern_shader_gaussian;
+ op->shader_function = _cairo_pattern_shader_gaussian;
break;
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:
- shader_function = _cairo_pattern_shader_linear;
+ op->shader_function = _cairo_pattern_shader_linear;
break;
}
+}
+
+void
+_cairo_pattern_calc_color_at_pixel (cairo_shader_op_t *op,
+ cairo_fixed_t factor,
+ int *pixel)
+{
+ int i;
- if (factor > 1.0 || factor < 0.0) {
- switch (pattern->extend) {
- case CAIRO_EXTEND_REPEAT:
- factor -= floor (factor);
- break;
- case CAIRO_EXTEND_REFLECT:
- if (factor >= 0.0) {
- if (((int) factor) % 2)
- factor = 1.0 - (factor - floor (factor));
- else
- factor -= floor (factor);
- } else {
- if (((int) factor) % 2)
- factor -= floor (factor);
- else
- factor = 1.0 - (factor - floor (factor));
- }
- break;
- case CAIRO_EXTEND_NONE:
- break;
+ switch (op->extend) {
+ case CAIRO_EXTEND_REPEAT:
+ factor -= factor & 0xffff0000;
+ break;
+ case CAIRO_EXTEND_REFLECT:
+ if (factor < 0 || factor > 65536) {
+ if ((factor >> 16) % 2)
+ factor = 65536 - (factor - (factor & 0xffff0000));
+ else
+ factor -= factor & 0xffff0000;
}
+ break;
+ case CAIRO_EXTEND_NONE:
+ break;
}
-
- if (factor < pattern->stops[0].offset)
- factor = pattern->stops[0].offset;
- if (factor > pattern->stops[pattern->n_stops - 1].offset)
- factor = pattern->stops[pattern->n_stops - 1].offset;
-
- for (colorstop = 0; colorstop < pattern->n_stops - 1; colorstop++) {
- if (factor <= pattern->stops[colorstop + 1].offset) {
- factorscale = fabs (pattern->stops[colorstop].offset -
- pattern->stops[colorstop + 1].offset);
-
- /* abrubt change, difference between two offsets == 0.0 */
- if (factorscale == 0)
- break;
-
- factor -= pattern->stops[colorstop].offset;
+ if (factor < op->min_offset)
+ factor = op->min_offset;
+ else if (factor > op->max_offset)
+ factor = op->max_offset;
+ for (i = 0; i < op->n_stops; i++) {
+ if (factor <= op->stops[i + 1].offset) {
+
/* take offset as new 0 of coordinate system */
- factor /= factorscale;
-
- shader_function (pattern->stops[colorstop].color_char,
- pattern->stops[colorstop + 1].color_char,
- factor, result_color);
-
- p = ((result_color[3] << 24) |
- (result_color[0] << 16) |
- (result_color[1] << 8) | (result_color[2] << 0));
- *pixel = p;
+ factor -= op->stops[i].offset;
+
+ /* difference between two offsets == 0, abrubt change */
+ if (op->stops[i + 1].scale)
+ factor = ((cairo_fixed_48_16_t) factor << 16) /
+ op->stops[i + 1].scale;
+
+ op->shader_function (op->stops[i].color_char,
+ op->stops[i + 1].color_char,
+ factor, pixel);
break;
}
}
@@ -557,92 +519,164 @@ static void
_cairo_image_data_set_linear (cairo_pattern_t *pattern,
double offset_x,
double offset_y,
- char *data,
+ int *pixels,
int width,
int height)
{
int x, y;
- cairo_point_double_t point0, point1, angle;
- double a, length, start, end;
- double factor;
+ cairo_point_double_t point0, point1;
+ double px, py, ex, ey;
+ double a, b, c, d, tx, ty;
+ double length, start, angle, fx, fy, factor;
+ cairo_shader_op_t op;
+
+ _cairo_pattern_shader_init (pattern, &op);
- point0.x = pattern->u.linear.point0.x - offset_x;
- point0.y = pattern->u.linear.point0.y - offset_y;
- point1.x = pattern->u.linear.point1.x - offset_x;
- point1.y = pattern->u.linear.point1.y - offset_y;
+ point0.x = pattern->u.linear.point0.x;
+ point0.y = pattern->u.linear.point0.y;
+ point1.x = pattern->u.linear.point1.x;
+ point1.y = pattern->u.linear.point1.y;
+ cairo_matrix_get_affine (&pattern->matrix, &a, &b, &c, &d, &tx, &ty);
+
length = sqrt ((point1.x - point0.x) * (point1.x - point0.x) +
(point1.y - point0.y) * (point1.y - point0.y));
- length = (length) ? 1.0 / length : INT_MAX;
-
- a = -atan2 (point1.y - point0.y, point1.x - point0.x);
- angle.x = cos (a);
- angle.y = -sin (a);
+ length = (length) ? 1.0 / length : CAIRO_MAXSHORT;
- start = angle.x * point0.x;
- start += angle.y * point0.y;
-
- end = angle.x * point1.x;
- end += angle.y * point1.y;
+ angle = -atan2 (point1.y - point0.y, point1.x - point0.x);
+ fx = cos (angle);
+ fy = -sin (angle);
+
+ start = fx * point0.x;
+ start += fy * point0.y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
-
- factor = angle.x * (double) x;
- factor += angle.y * (double) y;
-
- factor = factor - start;
- factor *= length;
-
- _cairo_pattern_calc_color_at_pixel (pattern, factor, (int *)
- &data[y * width * 4 + x * 4]);
+ px = x + offset_x;
+ py = y + offset_y;
+
+ /* transform fragment */
+ ex = a * px + c * py + tx;
+ ey = b * px + d * py + ty;
+
+ factor = ((fx * ex + fy * ey) - start) * length;
+
+ _cairo_pattern_calc_color_at_pixel (&op, factor * 65536, pixels++);
}
}
}
-/* TODO: Inner circle is currently ignored. */
static void
_cairo_image_data_set_radial (cairo_pattern_t *pattern,
double offset_x,
double offset_y,
- char *data,
+ int *pixels,
int width,
int height)
{
- int x, y;
- cairo_point_double_t center1, pos;
- cairo_distance_double_t length;
- double factor;
- double min_length;
-
- center1.x = pattern->u.radial.center1.x - offset_x;
- center1.y = pattern->u.radial.center1.y - offset_y;
-
- min_length =
- fabs ((pattern->u.radial.radius1.dx < pattern->u.radial.radius1.dy) ?
- pattern->u.radial.radius1.dx : pattern->u.radial.radius1.dy);
-
- /* ugly */
- if (min_length == 0.0)
- min_length = 0.000001;
-
- length.dx = min_length / pattern->u.radial.radius1.dx;
- length.dy = min_length / pattern->u.radial.radius1.dy;
+ int x, y, aligned_circles;
+ cairo_point_double_t c0, c1;
+ double px, py, ex, ey;
+ double a, b, c, d, tx, ty;
+ double r0, r1, c0_e_x, c0_e_y, c0_e, c1_e_x, c1_e_y, c1_e,
+ c0_c1_x, c0_c1_y, c0_c1, angle_c0, c1_y, y_x, c0_y, c0_x, r1_2,
+ denumerator, fraction, factor;
+ cairo_shader_op_t op;
+
+ _cairo_pattern_shader_init (pattern, &op);
+
+ c0.x = pattern->u.radial.center0.x;
+ c0.y = pattern->u.radial.center0.y;
+ r0 = pattern->u.radial.radius0;
+ c1.x = pattern->u.radial.center1.x;
+ c1.y = pattern->u.radial.center1.y;
+ r1 = pattern->u.radial.radius1;
+
+ if (c0.x != c1.x || c0.y != c1.y) {
+ aligned_circles = 0;
+ c0_c1_x = c1.x - c0.x;
+ c0_c1_y = c1.y - c0.y;
+ c0_c1 = sqrt (c0_c1_x * c0_c1_x + c0_c1_y * c0_c1_y);
+ r1_2 = r1 * r1;
+ } else {
+ aligned_circles = 1;
+ r1 = 1.0 / (r1 - r0);
+ }
- min_length = 1.0 / min_length;
+ cairo_matrix_get_affine (&pattern->matrix, &a, &b, &c, &d, &tx, &ty);
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
- pos.x = x - center1.x;
- pos.y = y - center1.y;
-
- pos.x *= length.dx;
- pos.y *= length.dy;
-
- factor = sqrt (pos.x * pos.x + pos.y * pos.y) * min_length;
+ px = x + offset_x;
+ py = y + offset_y;
+
+ /* transform fragment */
+ ex = a * px + c * py + tx;
+ ey = b * px + d * py + ty;
+
+ if (aligned_circles) {
+ ex = ex - c1.x;
+ ey = ey - c1.y;
+
+ factor = (sqrt (ex * ex + ey * ey) - r0) * r1;
+ } else {
+ /*
+ y (ex, ey)
+ c0 -------------------+---------- x
+ \ | __--
+ \ | __--
+ \ | __--
+ \ | __-- r1
+ \ | __--
+ c1 --
+
+ We need to calulate distance c0->x; the distance from
+ the inner circle center c0, through fragment position
+ (ex, ey) to point x where it crosses the outer circle.
+
+ From points c0, c1 and (ex, ey) we get angle C0. With
+ angle C0 we calculate distance c1->y and c0->y and by
+ knowing c1->y and r1, we also know y->x. Adding y->x to
+ c0->y gives us c0->x. The gradient offset can then be
+ calculated as:
+
+ offset = (c0->e - r0) / (c0->x - r0)
+
+ */
+
+ c0_e_x = ex - c0.x;
+ c0_e_y = ey - c0.y;
+ c0_e = sqrt (c0_e_x * c0_e_x + c0_e_y * c0_e_y);
+
+ c1_e_x = ex - c1.x;
+ c1_e_y = ey - c1.y;
+ c1_e = sqrt (c1_e_x * c1_e_x + c1_e_y * c1_e_y);
+
+ denumerator = -2.0 * c0_e * c0_c1;
+
+ if (denumerator != 0.0) {
+ fraction = (c1_e * c1_e - c0_e * c0_e - c0_c1 * c0_c1) /
+ denumerator;
+
+ if (fraction > 1.0)
+ fraction = 1.0;
+ else if (fraction < -1.0)
+ fraction = -1.0;
+
+ angle_c0 = acos (fraction);
+
+ c0_y = cos (angle_c0) * c0_c1;
+ c1_y = sin (angle_c0) * c0_c1;
+
+ y_x = sqrt (r1_2 - c1_y * c1_y);
+ c0_x = y_x + c0_y;
+
+ factor = (c0_e - r0) / (c0_x - r0);
+ } else
+ factor = -r0;
+ }
- _cairo_pattern_calc_color_at_pixel (pattern, factor, (int *)
- &data[y * width * 4 + x * 4]);
+ _cairo_pattern_calc_color_at_pixel (&op, factor * 65536, pixels++);
}
}
}
@@ -656,35 +690,35 @@ _cairo_pattern_get_image (cairo_pattern_t *pattern, cairo_box_t *box)
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL: {
char *data;
- int width = ceil (_cairo_fixed_to_double (box->p2.x)) -
- floor (_cairo_fixed_to_double (box->p1.x));
- int height = ceil (_cairo_fixed_to_double (box->p2.y)) -
- floor (_cairo_fixed_to_double (box->p1.y));
+ double x = box->p1.x >> 16;
+ double y = box->p1.y >> 16;
+ int width = ((box->p2.x + 65535) >> 16) - (box->p1.x >> 16);
+ int height = ((box->p2.y + 65535) >> 16) - (box->p1.y >> 16);
data = malloc (width * height * 4);
if (!data)
return NULL;
-
- _cairo_pattern_add_source_offset (pattern,
- floor (_cairo_fixed_to_double (box->p1.x)),
- floor (_cairo_fixed_to_double (box->p1.y)));
-
+
if (pattern->type == CAIRO_PATTERN_RADIAL)
_cairo_image_data_set_radial (pattern,
- pattern->source_offset.x,
- pattern->source_offset.y,
- data, width, height);
+ x - pattern->source_offset.x,
+ y - pattern->source_offset.y,
+ (int *) data,
+ width, height);
else
_cairo_image_data_set_linear (pattern,
- pattern->source_offset.x,
- pattern->source_offset.y,
- data, width, height);
+ x - pattern->source_offset.x,
+ y - pattern->source_offset.y,
+ (int *) data,
+ width, height);
+
+ _cairo_pattern_set_source_offset (pattern, x, y);
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
width, height,
width * 4);
-
+
if (surface)
_cairo_image_surface_assume_ownership_of_data (
(cairo_image_surface_t *) surface);
@@ -714,3 +748,4 @@ _cairo_pattern_get_image (cairo_pattern_t *pattern, cairo_box_t *box)
return (cairo_image_surface_t *) surface;
}
+
diff --git a/src/cairo_png_surface.c b/src/cairo_png_surface.c
index 851df98da..b012514b7 100644
--- a/src/cairo_png_surface.c
+++ b/src/cairo_png_surface.c
@@ -4,6 +4,9 @@
static const cairo_surface_backend_t cairo_png_surface_backend;
+static cairo_int_status_t
+_cairo_png_surface_copy_page (void *abstract_surface);
+
void
cairo_set_target_png (cairo_t *cr,
FILE *file,
@@ -31,12 +34,12 @@ typedef struct cairo_png_surface {
cairo_surface_t base;
/* PNG-specific fields */
+ cairo_image_surface_t *image;
FILE *file;
+ int copied;
- png_structp png_w;
- png_infop png_i;
+ cairo_format_t format;
- cairo_image_surface_t *image;
} cairo_png_surface_t;
@@ -50,98 +53,29 @@ cairo_png_surface_create (FILE *file,
int height)
{
cairo_png_surface_t *surface;
- time_t now = time (NULL);
- png_time png_time;
-
- if (format == CAIRO_FORMAT_A8 ||
- format == CAIRO_FORMAT_A1 ||
- file == NULL)
- return NULL;
surface = malloc (sizeof (cairo_png_surface_t));
if (surface == NULL)
- goto failure;
+ return NULL;
_cairo_surface_init (&surface->base, &cairo_png_surface_backend);
- surface->png_w = NULL;
- surface->png_i = NULL;
surface->image = (cairo_image_surface_t *)
cairo_image_surface_create (format, width, height);
- if (surface->image == NULL)
- goto failure;
-
- _cairo_png_surface_erase (surface);
-
- surface->file = file;
- surface->png_w = png_create_write_struct (PNG_LIBPNG_VER_STRING,
- NULL, NULL, NULL);
- if (surface->png_w == NULL)
- goto failure;
- surface->png_i = png_create_info_struct (surface->png_w);
- if (surface->png_i == NULL)
- goto failure;
-
- if (setjmp (png_jmpbuf (surface->png_w)))
- goto failure;
-
- png_init_io (surface->png_w, surface->file);
-
- switch (format) {
- case CAIRO_FORMAT_ARGB32:
- png_set_IHDR (surface->png_w, surface->png_i,
- width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
- PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT,
- PNG_FILTER_TYPE_DEFAULT);
- break;
- case CAIRO_FORMAT_RGB24:
- png_set_IHDR (surface->png_w, surface->png_i,
- width, height, 8, PNG_COLOR_TYPE_RGB,
- PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT,
- PNG_FILTER_TYPE_DEFAULT);
- break;
- case CAIRO_FORMAT_A8:
- case CAIRO_FORMAT_A1:
- /* These are not currently supported. */
- break;
+ if (surface->image == NULL) {
+ free (surface);
+ return NULL;
}
- png_convert_from_time_t (&png_time, now);
- png_set_tIME (surface->png_w, surface->png_i, &png_time);
+ _cairo_png_surface_erase (surface);
- png_write_info (surface->png_w, surface->png_i);
+ surface->file = file;
+ surface->copied = 0;
- switch (format) {
- case CAIRO_FORMAT_ARGB32:
- png_set_bgr (surface->png_w);
- break;
- case CAIRO_FORMAT_RGB24:
- png_set_filler (surface->png_w, 0, PNG_FILLER_AFTER);
- png_set_bgr (surface->png_w);
- break;
- case CAIRO_FORMAT_A8:
- case CAIRO_FORMAT_A1:
- /* These are not currently supported. */
- break;
- }
+ surface->format = format;
return &surface->base;
-
-
- failure:
- if (surface) {
- if (surface->image)
- cairo_surface_destroy (&surface->image->base);
- if (surface->png_i)
- png_destroy_write_struct (&surface->png_w, &surface->png_i);
- else if (surface->png_w)
- png_destroy_write_struct (&surface->png_w, NULL);
- free (surface);
- }
- return NULL;
}
@@ -155,25 +89,35 @@ _cairo_png_surface_create_similar (void *abstract_src,
}
static void
-_cairo_png_surface_destroy (void *abstract_surface)
+unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
{
- cairo_png_surface_t *surface = abstract_surface;
int i;
- png_byte *row;
-
- if (setjmp (png_jmpbuf (surface->png_w)))
- goto failure;
- row = surface->image->data;
- for (i=0; i < surface->image->height; i++) {
- png_write_row (surface->png_w, row);
- row += surface->image->stride;
+ for (i = 0; i < row_info->rowbytes; i += 4) {
+ unsigned char *b = &data[i];
+ unsigned int pixel;
+ unsigned char alpha;
+
+ memcpy (&pixel, b, sizeof (unsigned int));
+ alpha = (pixel & 0xff000000) >> 24;
+ if (alpha == 0) {
+ b[0] = b[1] = b[2] = b[3] = 0;
+ } else {
+ b[0] = (((pixel & 0x0000ff) >> 0) * 255) / alpha;
+ b[1] = (((pixel & 0x00ff00) >> 8) * 255) / alpha;
+ b[2] = (((pixel & 0xff0000) >> 16) * 255) / alpha;
+ b[3] = alpha;
+ }
}
+}
- png_write_end (surface->png_w, surface->png_i);
+static void
+_cairo_png_surface_destroy (void *abstract_surface)
+{
+ cairo_png_surface_t *surface = abstract_surface;
- failure:
- png_destroy_write_struct (&surface->png_w, &surface->png_i);
+ if (! surface->copied)
+ _cairo_png_surface_copy_page (surface);
cairo_surface_destroy (&surface->image->base);
@@ -296,13 +240,110 @@ _cairo_png_surface_composite_trapezoids (cairo_operator_t operator,
static cairo_int_status_t
_cairo_png_surface_copy_page (void *abstract_surface)
{
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ int i;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_png_surface_t *surface = abstract_surface;
+ png_struct *png;
+ png_info *info;
+ png_byte **rows;
+ png_color_16 white;
+ int png_color_type;
+ int depth;
+
+ rows = malloc (surface->image->height * sizeof(png_byte*));
+ if (rows == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ for (i = 0; i < surface->image->height; i++)
+ rows[i] = surface->image->data + i * surface->image->stride;
+
+ png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (png == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ info = png_create_info_struct (png);
+ if (info == NULL) {
+ png_destroy_write_struct (&png, NULL);
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ if (setjmp (png_jmpbuf (png))) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL;
+ }
+
+ png_init_io (png, surface->file);
+
+ switch (surface->format) {
+ case CAIRO_FORMAT_ARGB32:
+ depth = 8;
+ png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ break;
+ case CAIRO_FORMAT_RGB24:
+ depth = 8;
+ png_color_type = PNG_COLOR_TYPE_RGB;
+ break;
+ case CAIRO_FORMAT_A8:
+ depth = 8;
+ png_color_type = PNG_COLOR_TYPE_GRAY;
+ break;
+ case CAIRO_FORMAT_A1:
+ depth = 1;
+ png_color_type = PNG_COLOR_TYPE_GRAY;
+ break;
+ }
+
+ png_set_IHDR (png, info,
+ surface->image->width,
+ surface->image->height, depth,
+ png_color_type,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+
+ white.red = 0xff;
+ white.blue = 0xff;
+ white.green = 0xff;
+ png_set_bKGD (png, info, &white);
+
+/* XXX: Setting the time is interfereing with the image comparison
+ png_convert_from_time_t (&png_time, time (NULL));
+ png_set_tIME (png, info, &png_time);
+*/
+
+ png_set_write_user_transform_fn (png, unpremultiply_data);
+ if (surface->format == CAIRO_FORMAT_ARGB32 || surface->format == CAIRO_FORMAT_RGB24)
+ png_set_bgr (png);
+ if (surface->format == CAIRO_FORMAT_RGB24)
+ png_set_filler (png, 0, PNG_FILLER_AFTER);
+
+ png_write_info (png, info);
+ png_write_image (png, rows);
+ png_write_end (png, info);
+
+ surface->copied = 1;
+
+BAIL:
+ png_destroy_write_struct (&png, &info);
+
+ free (rows);
+
+ return status;
}
static cairo_int_status_t
_cairo_png_surface_show_page (void *abstract_surface)
{
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ cairo_int_status_t status;
+ cairo_png_surface_t *surface = abstract_surface;
+
+ status = _cairo_png_surface_copy_page (surface);
+ if (status)
+ return status;
+
+ _cairo_png_surface_erase (surface);
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
diff --git a/src/cairo_spline.c b/src/cairo_spline.c
index f05a9da55..6192f8636 100644
--- a/src/cairo_spline.c
+++ b/src/cairo_spline.c
@@ -118,6 +118,13 @@ static cairo_status_t
_cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point)
{
cairo_status_t status;
+ cairo_point_t *prev;
+
+ if (spline->num_points) {
+ prev = &spline->points[spline->num_points - 1];
+ if (prev->x == point->x && prev->y == point->y)
+ return CAIRO_STATUS_SUCCESS;
+ }
if (spline->num_points >= spline->points_size) {
status = _cairo_spline_grow_by (spline, CAIRO_SPLINE_GROWTH_INC);
diff --git a/src/cairo_surface.c b/src/cairo_surface.c
index 60b4487d4..79eee57b2 100644
--- a/src/cairo_surface.c
+++ b/src/cairo_surface.c
@@ -203,7 +203,7 @@ cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
}
slim_hidden_def(cairo_surface_set_repeat);
-cairo_int_status_t
+cairo_status_t
_cairo_surface_composite (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *mask,
@@ -424,10 +424,10 @@ _cairo_surface_create_pattern (cairo_surface_t *surface,
/* handle pattern opacity */
if (pattern->color.alpha != 1.0) {
- int width = ceil (_cairo_fixed_to_double (box->p2.x)) -
- floor (_cairo_fixed_to_double (box->p1.x));
- int height = ceil (_cairo_fixed_to_double (box->p2.y)) -
- floor (_cairo_fixed_to_double (box->p1.y));
+ double x = box->p1.x >> 16;
+ double y = box->p1.y >> 16;
+ int width = ((box->p2.x + 65535) >> 16) - (box->p1.x >> 16);
+ int height = ((box->p2.y + 65535) >> 16) - (box->p1.y >> 16);
cairo_pattern_t alpha;
pattern->source =
@@ -462,9 +462,9 @@ _cairo_surface_create_pattern (cairo_surface_t *surface,
save_repeat);
if (status == CAIRO_STATUS_SUCCESS) {
- _cairo_pattern_add_source_offset (pattern,
- floor (_cairo_fixed_to_double (box->p1.x)),
- floor (_cairo_fixed_to_double (box->p1.y)));
+ _cairo_pattern_set_source_offset (pattern,
+ pattern->source_offset.x + x,
+ pattern->source_offset.y + y);
} else
cairo_surface_destroy (pattern->source);
}
diff --git a/src/cairo_traps.c b/src/cairo_traps.c
index 9b44d38ea..d17a27281 100644
--- a/src/cairo_traps.c
+++ b/src/cairo_traps.c
@@ -639,8 +639,8 @@ _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;
+ extents->p1.x = extents->p1.y = CAIRO_MAXSHORT << 16;
+ extents->p2.x = extents->p2.y = CAIRO_MINSHORT << 16;
for (i = 0; i < traps->num_traps; i++)
_cairo_trap_extents (&traps->traps[i], extents);
diff --git a/src/cairoint.h b/src/cairoint.h
index 5b4ccb56e..97db3be5b 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -40,6 +40,7 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
+#include <limits.h>
#include "cairo.h"
@@ -119,6 +120,9 @@ typedef int32_t cairo_fixed_16_16_t;
/* The common 16.16 format gets a shorter name */
typedef cairo_fixed_16_16_t cairo_fixed_t;
+#define CAIRO_MAXSHORT SHRT_MAX
+#define CAIRO_MINSHORT SHRT_MIN
+
typedef struct cairo_point {
cairo_fixed_t x;
cairo_fixed_t y;
@@ -453,12 +457,27 @@ typedef enum {
} cairo_pattern_type_t;
typedef struct cairo_color_stop {
- double offset;
+ cairo_fixed_t offset;
+ cairo_fixed_48_16_t scale;
int id;
cairo_color_t color;
unsigned char color_char[4];
} cairo_color_stop_t;
+typedef void (*cairo_shader_function_t) (unsigned char *color0,
+ unsigned char *color1,
+ cairo_fixed_t factor,
+ int *pixel);
+
+typedef struct cairo_shader_op {
+ cairo_color_stop_t *stops;
+ int n_stops;
+ cairo_fixed_t min_offset;
+ cairo_fixed_t max_offset;
+ cairo_extend_t extend;
+ cairo_shader_function_t shader_function;
+} cairo_shader_op_t;
+
struct cairo_pattern {
unsigned int ref_count;
@@ -489,8 +508,8 @@ struct cairo_pattern {
struct {
cairo_point_double_t center0;
cairo_point_double_t center1;
- cairo_distance_double_t radius0;
- cairo_distance_double_t radius1;
+ double radius0;
+ double radius1;
} radial;
} u;
};
@@ -924,7 +943,7 @@ _cairo_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight);
-extern cairo_int_status_t __internal_linkage
+extern cairo_status_t __internal_linkage
_cairo_font_init (cairo_font_t *font,
const struct cairo_font_backend *backend);
@@ -937,22 +956,22 @@ _cairo_font_scale (cairo_font_t *font, double scale);
extern cairo_status_t __internal_linkage
_cairo_font_transform (cairo_font_t *font, cairo_matrix_t *matrix);
-extern cairo_int_status_t __internal_linkage
+extern cairo_status_t __internal_linkage
_cairo_font_font_extents (cairo_font_t *font,
cairo_font_extents_t *extents);
-extern cairo_int_status_t __internal_linkage
+extern cairo_status_t __internal_linkage
_cairo_font_text_extents (cairo_font_t *font,
const unsigned char *utf8,
cairo_text_extents_t *extents);
-extern cairo_int_status_t __internal_linkage
+extern cairo_status_t __internal_linkage
_cairo_font_glyph_extents (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
-extern cairo_int_status_t __internal_linkage
+extern cairo_status_t __internal_linkage
_cairo_font_show_text (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
@@ -962,7 +981,7 @@ _cairo_font_show_text (cairo_font_t *font,
const unsigned char *utf8);
-extern cairo_int_status_t __internal_linkage
+extern cairo_status_t __internal_linkage
_cairo_font_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
@@ -971,14 +990,14 @@ _cairo_font_show_glyphs (cairo_font_t *font,
int num_glyphs);
-extern cairo_int_status_t __internal_linkage
+extern cairo_status_t __internal_linkage
_cairo_font_text_path (cairo_font_t *font,
double x,
double y,
const unsigned char *utf8,
cairo_path_t *path);
-extern cairo_int_status_t __internal_linkage
+extern cairo_status_t __internal_linkage
_cairo_font_glyph_path (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
@@ -1331,20 +1350,23 @@ 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,
+_cairo_pattern_set_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);
+ cairo_matrix_t *ctm_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,
+_cairo_pattern_shader_init (cairo_pattern_t *pattern,
+ cairo_shader_op_t *op);
+
+extern void __internal_linkage
+_cairo_pattern_calc_color_at_pixel (cairo_shader_op_t *op,
+ cairo_fixed_t factor,
int *pixel);
extern cairo_image_surface_t *__internal_linkage