[cairo-commit] 3 commits - boilerplate/cairo-boilerplate-pdf.c
src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h
test/gradient-alpha.c test/linear-gradient.c
test/text-pattern.c test/trap-clip.c
Carl Worth
cworth at kemper.freedesktop.org
Fri Apr 27 16:41:32 PDT 2007
boilerplate/cairo-boilerplate-pdf.c | 15
src/cairo-pdf-surface-private.h | 14
src/cairo-pdf-surface.c | 1005 +++++++++++++++++++++++++++---------
test/gradient-alpha.c | 3
test/linear-gradient.c | 3
test/text-pattern.c | 3
test/trap-clip.c | 3
7 files changed, 802 insertions(+), 244 deletions(-)
New commits:
diff-tree 2dcfb944b044172640a3784246d6b3129b686b60 (from 179e3399101b5a0daa907dcfe1f9f11ae8fe691e)
Author: Carl Worth <cworth at cworth.org>
Date: Fri Apr 27 16:41:17 2007 -0700
Don't test PDF tests known to fail due to poppler limitations
The following four tests are disabled:
gradient-alpha, linear-gradient, text-pattern, trap-clip
We don't use XFAIL as that would disable all backends, (but
we can still usefully use these tests on backends other than
PDF).
diff --git a/boilerplate/cairo-boilerplate-pdf.c b/boilerplate/cairo-boilerplate-pdf.c
index e0a610e..0d8ac1a 100644
--- a/boilerplate/cairo-boilerplate-pdf.c
+++ b/boilerplate/cairo-boilerplate-pdf.c
@@ -42,6 +42,14 @@ typedef struct _pdf_target_closure
cairo_surface_t *target;
} pdf_target_closure_t;
+#define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
+static const char *pdf_ignored_tests[] = {
+ "gradient-alpha",
+ "linear-gradient",
+ "text-pattern",
+ "trap-clip"
+};
+
cairo_surface_t *
_cairo_boilerplate_pdf_create_surface (const char *name,
cairo_content_t content,
@@ -53,6 +61,13 @@ _cairo_boilerplate_pdf_create_surface (c
pdf_target_closure_t *ptc;
cairo_surface_t *surface;
+ if (mode == CAIRO_BOILERPLATE_MODE_TEST) {
+ int i;
+ for (i = 0; i < ARRAY_LENGTH (pdf_ignored_tests); i++)
+ if (strcmp (name, pdf_ignored_tests[i]) == 0)
+ return NULL;
+ }
+
/* Sanitize back to a real cairo_content_t value. */
if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
content = CAIRO_CONTENT_COLOR_ALPHA;
diff --git a/test/gradient-alpha.c b/test/gradient-alpha.c
index a56b507..6646aec 100644
--- a/test/gradient-alpha.c
+++ b/test/gradient-alpha.c
@@ -29,7 +29,8 @@ static cairo_test_draw_function_t draw;
cairo_test_t test = {
"gradient-alpha",
- "Tests drawing of a gradient with various alpha values in the color stops",
+ "Tests drawing of a gradient with various alpha values in the color stops\n"
+ "PDF backend will not be tested due to limitations in poppler.",
10, 10,
draw
};
diff --git a/test/linear-gradient.c b/test/linear-gradient.c
index 7681cbf..71a57f6 100644
--- a/test/linear-gradient.c
+++ b/test/linear-gradient.c
@@ -58,7 +58,8 @@ static cairo_test_draw_function_t draw;
cairo_test_t test = {
"linear-gradient",
- "Tests the drawing of linear gradients",
+ "Tests the drawing of linear gradients\n"
+ "PDF backend will not be tested due to limitations in poppler.",
WIDTH, HEIGHT,
draw
};
diff --git a/test/text-pattern.c b/test/text-pattern.c
index 02feb22..99ac9fd 100644
--- a/test/text-pattern.c
+++ b/test/text-pattern.c
@@ -32,7 +32,8 @@ static cairo_test_draw_function_t draw;
cairo_test_t test = {
"text-pattern",
- "Patterned Text",
+ "Patterned Text\n"
+ "PDF backend will not be tested due to limitations in poppler.",
IMAGE_WIDTH, IMAGE_HEIGHT,
draw
};
diff --git a/test/trap-clip.c b/test/trap-clip.c
index ba4d148..a33985f 100644
--- a/test/trap-clip.c
+++ b/test/trap-clip.c
@@ -168,7 +168,8 @@ static cairo_test_draw_function_t draw;
cairo_test_t test = {
"trap-clip",
- "Trapezoid clipping",
+ "Trapezoid clipping\n"
+ "PDF backend will not be tested due to limitations in poppler.",
IMAGE_WIDTH, IMAGE_HEIGHT,
draw
};
diff-tree 179e3399101b5a0daa907dcfe1f9f11ae8fe691e (from 1816d7c590ae4d423f9314a8a7794e2cae854da3)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Fri Apr 27 16:01:56 2007 -0700
PDF: Change CTM to identity
Some PDF viewers forget the CTM when drawing gradient patterns
with SMasks. This patch works around these bugs by using the default
identity matrix for the CTM. All paths are transformed from
cairo to pdf coordinates before writing to the pdf file.
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 31ebc26..1af2ad0 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -58,6 +58,7 @@ struct _cairo_pdf_surface {
double width;
double height;
+ cairo_matrix_t cairo_to_pdf;
cairo_array_t objects;
cairo_array_t pages;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 3398654..00dcd7c 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -245,6 +245,7 @@ _cairo_pdf_surface_create_for_stream_int
surface->width = width;
surface->height = height;
+ cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
_cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
_cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
@@ -663,10 +664,6 @@ _cairo_pdf_surface_start_page (void *abs
if (status)
return status;
- _cairo_output_stream_printf (surface->output,
- "1 0 0 -1 0 %f cm\r\n",
- surface->height);
-
return CAIRO_STATUS_SUCCESS;
}
@@ -1422,8 +1419,8 @@ _cairo_pdf_surface_emit_linear_pattern (
{
cairo_pdf_resource_t pattern_resource, smask;
cairo_pdf_resource_t color_function, alpha_function;
- double x0, y0, x1, y1;
- cairo_matrix_t p2u;
+ double x1, y1, x2, y2;
+ cairo_matrix_t pat_to_pdf;
cairo_extend_t extend;
cairo_status_t status;
@@ -1439,32 +1436,33 @@ _cairo_pdf_surface_emit_linear_pattern (
if (status)
return status;
- p2u = pattern->base.base.matrix;
- status = cairo_matrix_invert (&p2u);
+ pat_to_pdf = pattern->base.base.matrix;
+ status = cairo_matrix_invert (&pat_to_pdf);
if (status)
return status;
- x0 = _cairo_fixed_to_double (pattern->gradient.p1.x);
- y0 = _cairo_fixed_to_double (pattern->gradient.p1.y);
- cairo_matrix_transform_point (&p2u, &x0, &y0);
- x1 = _cairo_fixed_to_double (pattern->gradient.p2.x);
- y1 = _cairo_fixed_to_double (pattern->gradient.p2.y);
- cairo_matrix_transform_point (&p2u, &x1, &y1);
+ cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
+ x1 = _cairo_fixed_to_double (pattern->gradient.p1.x);
+ y1 = _cairo_fixed_to_double (pattern->gradient.p1.y);
+ x2 = _cairo_fixed_to_double (pattern->gradient.p2.x);
+ y2 = _cairo_fixed_to_double (pattern->gradient.p2.y);
pattern_resource = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Type /Pattern\r\n"
" /PatternType 2\r\n"
- " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
+ " /Matrix [ %f %f %f %f %f %f ]\r\n"
" /Shading\r\n"
" << /ShadingType 2\r\n"
" /ColorSpace /DeviceRGB\r\n"
" /Coords [ %f %f %f %f ]\r\n"
" /Function %d 0 R\r\n",
pattern_resource.id,
- surface->height,
- x0, y0, x1, y1,
+ pat_to_pdf.xx, pat_to_pdf.yx,
+ pat_to_pdf.xy, pat_to_pdf.yy,
+ pat_to_pdf.x0, pat_to_pdf.y0,
+ x1, y1, x2, y2,
color_function.id);
if (extend == CAIRO_EXTEND_PAD) {
@@ -1491,15 +1489,17 @@ _cairo_pdf_surface_emit_linear_pattern (
"%d 0 obj\r\n"
"<< /Type /Pattern\r\n"
" /PatternType 2\r\n"
- " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
+ " /Matrix [ %f %f %f %f %f %f ]\r\n"
" /Shading\r\n"
" << /ShadingType 2\r\n"
" /ColorSpace /DeviceGray\r\n"
" /Coords [ %f %f %f %f ]\r\n"
" /Function %d 0 R\r\n",
mask_resource.id,
- surface->height,
- x0, y0, x1, y1,
+ pat_to_pdf.xx, pat_to_pdf.yx,
+ pat_to_pdf.xy, pat_to_pdf.yy,
+ pat_to_pdf.x0, pat_to_pdf.y0,
+ x1, y1, x2, y2,
alpha_function.id);
if (extend == CAIRO_EXTEND_PAD) {
@@ -1541,8 +1541,8 @@ _cairo_pdf_surface_emit_radial_pattern (
{
cairo_pdf_resource_t pattern_resource, smask;
cairo_pdf_resource_t color_function, alpha_function;
- double x0, y0, x1, y1, r0, r1;
- cairo_matrix_t p2u, pdf_p2d;
+ double x1, y1, x2, y2, r1, r2;
+ cairo_matrix_t pat_to_pdf;
cairo_extend_t extend;
cairo_status_t status;
@@ -1558,22 +1558,18 @@ _cairo_pdf_surface_emit_radial_pattern (
if (status)
return status;
- p2u = pattern->base.base.matrix;
- status = cairo_matrix_invert (&p2u);
+ pat_to_pdf = pattern->base.base.matrix;
+ status = cairo_matrix_invert (&pat_to_pdf);
if (status)
return status;
- x0 = _cairo_fixed_to_double (pattern->gradient.c1.x);
- y0 = _cairo_fixed_to_double (pattern->gradient.c1.y);
- r0 = _cairo_fixed_to_double (pattern->gradient.c1.radius);
- x1 = _cairo_fixed_to_double (pattern->gradient.c2.x);
- y1 = _cairo_fixed_to_double (pattern->gradient.c2.y);
- r1 = _cairo_fixed_to_double (pattern->gradient.c2.radius);
-
- cairo_matrix_init_identity (&pdf_p2d);
- cairo_matrix_translate (&pdf_p2d, 0.0, surface->height);
- cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
- cairo_matrix_multiply (&pdf_p2d, &p2u, &pdf_p2d);
+ cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
+ x1 = _cairo_fixed_to_double (pattern->gradient.c1.x);
+ y1 = _cairo_fixed_to_double (pattern->gradient.c1.y);
+ r1 = _cairo_fixed_to_double (pattern->gradient.c1.radius);
+ x2 = _cairo_fixed_to_double (pattern->gradient.c2.x);
+ y2 = _cairo_fixed_to_double (pattern->gradient.c2.y);
+ r2 = _cairo_fixed_to_double (pattern->gradient.c2.radius);
pattern_resource = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
@@ -1587,10 +1583,10 @@ _cairo_pdf_surface_emit_radial_pattern (
" /Coords [ %f %f %f %f %f %f ]\r\n"
" /Function %d 0 R\r\n",
pattern_resource.id,
- pdf_p2d.xx, pdf_p2d.yx,
- pdf_p2d.xy, pdf_p2d.yy,
- pdf_p2d.x0, pdf_p2d.y0,
- x0, y0, r0, x1, y1, r1,
+ pat_to_pdf.xx, pat_to_pdf.yx,
+ pat_to_pdf.xy, pat_to_pdf.yy,
+ pat_to_pdf.x0, pat_to_pdf.y0,
+ x1, y1, r1, x2, y2, r2,
color_function.id);
if (extend == CAIRO_EXTEND_PAD) {
@@ -1624,10 +1620,10 @@ _cairo_pdf_surface_emit_radial_pattern (
" /Coords [ %f %f %f %f %f %f ]\r\n"
" /Function %d 0 R\r\n",
mask_resource.id,
- pdf_p2d.xx, pdf_p2d.yx,
- pdf_p2d.xy, pdf_p2d.yy,
- pdf_p2d.x0, pdf_p2d.y0,
- x0, y0, r0, x1, y1, r1,
+ pat_to_pdf.xx, pat_to_pdf.yx,
+ pat_to_pdf.xy, pat_to_pdf.yy,
+ pat_to_pdf.x0, pat_to_pdf.y0,
+ x1, y1, r1, x2, y2, r2,
alpha_function.id);
if (extend == CAIRO_EXTEND_PAD) {
@@ -1767,6 +1763,7 @@ _cairo_pdf_surface_get_extents (void
typedef struct _pdf_path_info {
cairo_output_stream_t *output;
+ cairo_matrix_t *cairo_to_pdf;
cairo_matrix_t *ctm_inverse;
} pdf_path_info_t;
@@ -1777,6 +1774,8 @@ _cairo_pdf_path_move_to (void *closure,
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
+ if (info->cairo_to_pdf)
+ cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
if (info->ctm_inverse)
cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
@@ -1793,6 +1792,8 @@ _cairo_pdf_path_line_to (void *closure,
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
+ if (info->cairo_to_pdf)
+ cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
if (info->ctm_inverse)
cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
@@ -1815,6 +1816,11 @@ _cairo_pdf_path_curve_to (void
double dx = _cairo_fixed_to_double (d->x);
double dy = _cairo_fixed_to_double (d->y);
+ if (info->cairo_to_pdf) {
+ cairo_matrix_transform_point (info->cairo_to_pdf, &bx, &by);
+ cairo_matrix_transform_point (info->cairo_to_pdf, &cx, &cy);
+ cairo_matrix_transform_point (info->cairo_to_pdf, &dx, &dy);
+ }
if (info->ctm_inverse) {
cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
@@ -1863,6 +1869,7 @@ _cairo_pdf_surface_intersect_clip_path (
}
info.output = surface->output;
+ info.cairo_to_pdf = &surface->cairo_to_pdf;
info.ctm_inverse = NULL;
status = _cairo_path_fixed_interpret (path,
@@ -2581,6 +2588,7 @@ _cairo_pdf_surface_emit_outline_glyph (c
-_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
info.output = surface->output;
+ info.cairo_to_pdf = &surface->cairo_to_pdf;
info.ctm_inverse = NULL;
status = _cairo_path_fixed_interpret (scaled_glyph->path,
@@ -3143,9 +3151,6 @@ _cairo_pdf_surface_paint (void *abstra
status = _cairo_pdf_surface_begin_group (surface, &group);
if (status)
return status;
- _cairo_output_stream_printf (surface->output,
- "1 0 0 -1 0 %f cm\r\n",
- surface->height);
} else {
_cairo_output_stream_printf (surface->output, "q ");
}
@@ -3160,8 +3165,7 @@ _cairo_pdf_surface_paint (void *abstra
_cairo_pdf_surface_end_group (surface);
_cairo_output_stream_printf (surface->output,
- "q 1 0 0 -1 0 %f cm /sm%d gs /res%d Do Q\r\n",
- surface->height,
+ "q /sm%d gs /res%d Do Q\r\n",
surface->emitted_pattern.smask,
group.id);
} else {
@@ -3268,6 +3272,7 @@ _cairo_pdf_surface_stroke (void *abstr
cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
pdf_path_info_t info;
cairo_status_t status;
+ cairo_matrix_t m;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
@@ -3282,9 +3287,6 @@ _cairo_pdf_surface_stroke (void *abstr
status = _cairo_pdf_surface_begin_group (surface, &group);
if (status)
return status;
- _cairo_output_stream_printf (surface->output,
- "1 0 0 -1 0 %f cm\r\n",
- surface->height);
} else {
_cairo_output_stream_printf (surface->output, "q ");
}
@@ -3297,12 +3299,14 @@ _cairo_pdf_surface_stroke (void *abstr
return status;
info.output = surface->output;
+ info.cairo_to_pdf = NULL;
info.ctm_inverse = ctm_inverse;
+ cairo_matrix_multiply (&m, ctm, &surface->cairo_to_pdf);
_cairo_output_stream_printf (surface->output,
"q %f %f %f %f %f %f cm\r\n",
- ctm->xx, ctm->yx, ctm->xy, ctm->yy,
- ctm->x0, ctm->y0);
+ m.xx, m.yx, m.xy, m.yy,
+ m.x0, m.y0);
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
@@ -3318,8 +3322,7 @@ _cairo_pdf_surface_stroke (void *abstr
_cairo_pdf_surface_end_group (surface);
_cairo_output_stream_printf (surface->output,
- "q 1 0 0 -1 0 %f cm /sm%d gs /res%d Do Q\r\n",
- surface->height,
+ "q /sm%d gs /res%d Do Q\r\n",
surface->emitted_pattern.smask,
group.id);
} else {
@@ -3357,15 +3360,13 @@ _cairo_pdf_surface_fill (void *abstrac
status = _cairo_pdf_surface_begin_group (surface, &group);
if (status)
return status;
- _cairo_output_stream_printf (surface->output,
- "1 0 0 -1 0 %f cm\r\n",
- surface->height);
} else {
_cairo_output_stream_printf (surface->output, "q ");
}
_cairo_pdf_surface_select_pattern (surface, FALSE);
info.output = surface->output;
+ info.cairo_to_pdf = &surface->cairo_to_pdf;
info.ctm_inverse = NULL;
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
@@ -3394,8 +3395,7 @@ _cairo_pdf_surface_fill (void *abstrac
_cairo_pdf_surface_end_group (surface);
_cairo_output_stream_printf (surface->output,
- "q 1 0 0 -1 0 %f cm /sm%d gs /res%d Do Q\r\n",
- surface->height,
+ "q /sm%d gs /res%d Do Q\r\n",
surface->emitted_pattern.smask,
group.id);
} else {
@@ -3438,9 +3438,6 @@ _cairo_pdf_surface_show_glyphs (void *
status = _cairo_pdf_surface_begin_group (surface, &group);
if (status)
return status;
- _cairo_output_stream_printf (surface->output,
- "1 0 0 -1 0 %f cm\r\n",
- surface->height);
} else {
_cairo_output_stream_printf (surface->output, "q ");
}
@@ -3491,11 +3488,11 @@ _cairo_pdf_surface_show_glyphs (void *
_cairo_output_stream_printf (surface->output,
"%f %f %f %f %f %f Tm\r\n",
scaled_font->scale.xx,
- scaled_font->scale.yx,
+ -scaled_font->scale.yx,
-scaled_font->scale.xy,
- -scaled_font->scale.yy,
+ scaled_font->scale.yy,
glyphs[i].x,
- glyphs[i].y);
+ surface->height - glyphs[i].y);
current_subset_id = subset_glyph.subset_id;
Tlm_x = glyphs[i].x;
Tlm_y = glyphs[i].y;
@@ -3512,7 +3509,8 @@ _cairo_pdf_surface_show_glyphs (void *
_cairo_output_stream_printf (surface->output,
"%f %f Td\r\n",
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
- (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
+ -(glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
+
Tlm_x = glyphs[i].x;
Tlm_y = glyphs[i].y;
Tm_x = Tlm_x;
@@ -3588,8 +3586,7 @@ _cairo_pdf_surface_show_glyphs (void *
_cairo_pdf_surface_end_group (surface);
_cairo_output_stream_printf (surface->output,
- "q 1 0 0 -1 0 %f cm /sm%d gs /res%d Do Q\r\n",
- surface->height,
+ "q /sm%d gs /res%d Do Q\r\n",
surface->emitted_pattern.smask,
group.id);
} else {
diff-tree 1816d7c590ae4d423f9314a8a7794e2cae854da3 (from 050dad71734739f1eaf8976ca5bb88e47c76409c)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Fri Apr 27 09:49:45 2007 -0700
Add support for transparent gradients
This is based on the gradient patch written by Miklós Erdélyi at
http://lists.freedesktop.org/archives/cairo/2006-August/007648.html
Currently only EXTEND_NONE and EXTEND_PAD are supported. Other extend
types will go through the image fallback path.
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 1fcf774..31ebc26 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -65,6 +65,9 @@ struct _cairo_pdf_surface {
cairo_array_t xobjects;
cairo_array_t streams;
cairo_array_t alphas;
+ cairo_array_t smasks;
+ cairo_array_t rgb_linear_functions;
+ cairo_array_t alpha_linear_functions;
cairo_scaled_font_subsets_t *font_subsets;
cairo_array_t fonts;
@@ -81,6 +84,16 @@ struct _cairo_pdf_surface {
cairo_output_stream_t *old_output;
} current_stream;
+ struct {
+ cairo_pattern_type_t type;
+ double red;
+ double green;
+ double blue;
+ int alpha;
+ cairo_pdf_resource_t smask;
+ cairo_pdf_resource_t pattern;
+ } emitted_pattern;
+
cairo_bool_t has_clip;
cairo_paginated_mode_t paginated_mode;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 073191e..3398654 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -64,8 +64,6 @@
*
* - Surface patterns.
*
- * - Alpha channels in gradients.
- *
* - Should/does cairo support drawing into a scratch surface and then
* using that as a fill pattern? For this backend, that would involve
* using a tiling pattern (4.6.2). How do you create such a scratch
@@ -97,6 +95,18 @@ typedef struct _cairo_pdf_font {
cairo_pdf_resource_t subset_resource;
} cairo_pdf_font_t;
+typedef struct _cairo_pdf_rgb_linear_function {
+ cairo_pdf_resource_t resource;
+ double color1[3];
+ double color2[3];
+} cairo_pdf_rgb_linear_function_t;
+
+typedef struct _cairo_pdf_alpha_linear_function {
+ cairo_pdf_resource_t resource;
+ double alpha1;
+ double alpha2;
+} cairo_pdf_alpha_linear_function_t;
+
static cairo_pdf_resource_t
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
@@ -182,28 +192,33 @@ _cairo_pdf_surface_add_pattern (cairo_pd
}
static cairo_status_t
-_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
- double alpha,
- cairo_pdf_resource_t *resource)
+_cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface,
+ cairo_pdf_resource_t smask)
+{
+ return _cairo_array_append (&surface->smasks, &smask);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface, double alpha, int *index)
{
- cairo_status_t status;
int num_alphas, i;
double other;
+ cairo_status_t status;
num_alphas = _cairo_array_num_elements (&surface->alphas);
for (i = 0; i < num_alphas; i++) {
- _cairo_array_copy_element (&surface->alphas, i, &other);
- if (alpha == other) {
- resource->id = i;
- return CAIRO_STATUS_SUCCESS;
- }
+ _cairo_array_copy_element (&surface->alphas, i, &other);
+ if (alpha == other) {
+ *index = i;
+ return CAIRO_STATUS_SUCCESS;
+ }
}
status = _cairo_array_append (&surface->alphas, &alpha);
if (status)
return status;
- resource->id = _cairo_array_num_elements (&surface->alphas) - 1;
+ *index = _cairo_array_num_elements (&surface->alphas) - 1;
return CAIRO_STATUS_SUCCESS;
}
@@ -214,6 +229,8 @@ _cairo_pdf_surface_create_for_stream_int
double height)
{
cairo_pdf_surface_t *surface;
+ cairo_status_t status;
+ int alpha;
surface = malloc (sizeof (cairo_pdf_surface_t));
if (surface == NULL) {
@@ -235,12 +252,23 @@ _cairo_pdf_surface_create_for_stream_int
_cairo_array_init (&surface->xobjects, sizeof (cairo_pdf_resource_t));
_cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t));
_cairo_array_init (&surface->alphas, sizeof (double));
+ _cairo_array_init (&surface->smasks, sizeof (cairo_pdf_resource_t));
+ _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
+ _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
+
+
+ /* Add alpha=1 as the first element in the list of alpha values as
+ * this is the most frequently referenced value. */
+ status = _cairo_pdf_surface_add_alpha (surface, 1, &alpha);
+ if (status) {
+ _cairo_error (status);
+ goto fail1;
+ }
surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
if (! surface->font_subsets) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
- free (surface);
- return (cairo_surface_t*) &_cairo_surface_nil;
+ goto fail2;
}
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
@@ -266,6 +294,11 @@ _cairo_pdf_surface_create_for_stream_int
CAIRO_CONTENT_COLOR_ALPHA,
width, height,
&cairo_pdf_surface_paginated_backend);
+
+fail1:
+ free (surface);
+fail2:
+ return (cairo_surface_t*) &_cairo_surface_nil;
}
/**
@@ -542,6 +575,9 @@ _cairo_pdf_surface_finish (void *abstrac
_cairo_array_fini (&surface->xobjects);
_cairo_array_fini (&surface->streams);
_cairo_array_fini (&surface->alphas);
+ _cairo_array_fini (&surface->smasks);
+ _cairo_array_fini (&surface->rgb_linear_functions);
+ _cairo_array_fini (&surface->alpha_linear_functions);
if (surface->font_subsets) {
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
@@ -575,6 +611,39 @@ _cairo_pdf_surface_resume_content_stream
return _cairo_pdf_surface_add_stream (surface, stream);
}
+static cairo_status_t
+_cairo_pdf_surface_begin_group (cairo_pdf_surface_t *surface, cairo_pdf_resource_t *group)
+{
+ cairo_pdf_resource_t g;
+ cairo_status_t status;
+
+ _cairo_pdf_surface_pause_content_stream (surface);
+ g = _cairo_pdf_surface_open_stream (surface,
+ TRUE,
+ " /Type /XObject\r\n"
+ " /Subtype /Form\r\n"
+ " /BBox [ 0 0 %f %f ]\r\n"
+ " /Group <<\r\n"
+ " /Type /Group\r\n"
+ " /S /Transparency\r\n"
+ " /CS /DeviceRGB\r\n"
+ " >>\r\n",
+ surface->width,
+ surface->height);
+
+ status = _cairo_array_append (&surface->xobjects, &g);
+ *group = g;
+
+ return status;
+}
+
+static void
+_cairo_pdf_surface_end_group (cairo_pdf_surface_t *surface)
+{
+ _cairo_pdf_surface_close_stream (surface);
+ _cairo_pdf_surface_resume_content_stream (surface);
+}
+
static cairo_int_status_t
_cairo_pdf_surface_start_page (void *abstract_surface)
{
@@ -696,9 +765,9 @@ _cairo_pdf_surface_emit_smask (cairo_pdf
/* Emit image data into the given surface, providing a resource that
* can be used to reference the data in image_ret. */
static cairo_status_t
-_cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
- cairo_image_surface_t *image,
- cairo_pdf_resource_t *image_ret)
+_cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
+ cairo_image_surface_t *image,
+ cairo_pdf_resource_t *image_ret)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
char *rgb, *compressed;
@@ -809,38 +878,30 @@ _cairo_pdf_surface_emit_image (cairo_pdf
}
static cairo_status_t
-_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface,
- cairo_solid_pattern_t *pattern)
+_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface,
+ cairo_solid_pattern_t *pattern)
{
+ int alpha;
cairo_status_t status;
- cairo_pdf_resource_t alpha;
- status = _cairo_pdf_surface_add_alpha (surface,
- pattern->color.alpha,
- &alpha);
+ status = _cairo_pdf_surface_add_alpha (surface, pattern->color.alpha, &alpha);
if (status)
return status;
- /* With some work, we could separate the stroking
- * or non-stroking color here as actually needed. */
- _cairo_output_stream_printf (surface->output,
- "%f %f %f RG "
- "%f %f %f rg "
- "/a%d gs\r\n",
- pattern->color.red,
- pattern->color.green,
- pattern->color.blue,
- pattern->color.red,
- pattern->color.green,
- pattern->color.blue,
- alpha.id);
+ surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SOLID;
+ surface->emitted_pattern.red = pattern->color.red;
+ surface->emitted_pattern.green = pattern->color.green;
+ surface->emitted_pattern.blue = pattern->color.blue;
+ surface->emitted_pattern.alpha = alpha;
+ surface->emitted_pattern.smask.id = 0;
+ surface->emitted_pattern.pattern.id = 0;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
- cairo_surface_pattern_t *pattern)
+_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
+ cairo_surface_pattern_t *pattern)
{
cairo_pdf_resource_t stream;
cairo_surface_t *pat_surface;
@@ -848,7 +909,7 @@ _cairo_pdf_surface_emit_surface_pattern
cairo_image_surface_t *image;
void *image_extra;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_pdf_resource_t alpha, image_resource = {0}; /* squelch bogus compiler warning */
+ cairo_pdf_resource_t image_resource = {0}; /* squelch bogus compiler warning */
cairo_matrix_t cairo_p2d, pdf_p2d;
cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
double xstep, ystep;
@@ -997,17 +1058,12 @@ _cairo_pdf_surface_emit_surface_pattern
if (status)
goto BAIL;
- status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
+ status = _cairo_pdf_surface_add_alpha (surface, 1.0, &surface->emitted_pattern.alpha);
if (status)
goto BAIL;
-
- /* With some work, we could separate the stroking
- * or non-stroking pattern here as actually needed. */
- _cairo_output_stream_printf (surface->output,
- "/Pattern CS /res%d SCN "
- "/Pattern cs /res%d scn "
- "/a%d gs\r\n",
- stream.id, stream.id, alpha.id);
+ surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SURFACE;
+ surface->emitted_pattern.smask.id = 0;
+ surface->emitted_pattern.pattern = stream;
BAIL:
_cairo_surface_release_source_image (pat_surface, image, image_extra);
@@ -1018,90 +1074,168 @@ _cairo_pdf_surface_emit_surface_pattern
}
typedef struct _cairo_pdf_color_stop {
- double offset;
- cairo_pdf_resource_t gradient;
- unsigned char color_char[4];
+ double offset;
+ double color[4];
+ cairo_pdf_resource_t resource;
} cairo_pdf_color_stop_t;
-static cairo_pdf_resource_t
-_cairo_pdf_surface_emit_linear_colorgradient (cairo_pdf_surface_t *surface,
- cairo_pdf_color_stop_t *stop1,
- cairo_pdf_color_stop_t *stop2)
+static cairo_status_t
+cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
+ cairo_pdf_color_stop_t *stop1,
+ cairo_pdf_color_stop_t *stop2,
+ cairo_pdf_resource_t *function)
{
- cairo_pdf_resource_t function = _cairo_pdf_surface_new_object (surface);
+ int num_elems, i;
+ cairo_pdf_rgb_linear_function_t elem;
+ cairo_pdf_resource_t res;
+ cairo_status_t status;
+
+ num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
+ for (i = 0; i < num_elems; i++) {
+ _cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
+ if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
+ continue;
+ if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
+ continue;
+ *function = elem.resource;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ res = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
- "<< /FunctionType 0\r\n"
+ "<< /FunctionType 2\r\n"
" /Domain [ 0 1 ]\r\n"
- " /Size [ 2 ]\r\n"
- " /BitsPerSample 8\r\n"
- " /Range [ 0 1 0 1 0 1 ]\r\n"
- " /Length 6\r\n"
+ " /C0 [ %f %f %f ]\r\n"
+ " /C1 [ %f %f %f ]\r\n"
+ " /N 1\r\n"
">>\r\n"
- "stream\r\n",
- function.id);
+ "endobj\r\n",
+ res.id,
+ stop1->color[0],
+ stop1->color[1],
+ stop1->color[2],
+ stop2->color[0],
+ stop2->color[1],
+ stop2->color[2]);
+
+ elem.resource = res;
+ memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
+ memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
+
+ status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
+ *function = res;
+
+ return status;
+}
+
+static cairo_status_t
+cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
+ cairo_pdf_color_stop_t *stop1,
+ cairo_pdf_color_stop_t *stop2,
+ cairo_pdf_resource_t *function)
+{
+ int num_elems, i;
+ cairo_pdf_alpha_linear_function_t elem;
+ cairo_pdf_resource_t res;
+ cairo_status_t status;
+
+ num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
+ for (i = 0; i < num_elems; i++) {
+ _cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
+ if (elem.alpha1 != stop1->color[3])
+ continue;
+ if (elem.alpha2 != stop2->color[3])
+ continue;
+ *function = elem.resource;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ res = _cairo_pdf_surface_new_object (surface);
- _cairo_output_stream_write (surface->output, stop1->color_char, 3);
- _cairo_output_stream_write (surface->output, stop2->color_char, 3);
_cairo_output_stream_printf (surface->output,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
+ "%d 0 obj\r\n"
+ "<< /FunctionType 2\r\n"
+ " /Domain [ 0 1 ]\r\n"
+ " /C0 [ %f ]\r\n"
+ " /C1 [ %f ]\r\n"
+ " /N 1\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ res.id,
+ stop1->color[3],
+ stop2->color[3]);
+
+ elem.resource = res;
+ elem.alpha1 = stop1->color[3];
+ elem.alpha2 = stop2->color[3];
+
+ status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
+ *function = res;
- return function;
+ return status;
}
-static cairo_pdf_resource_t
-_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
- unsigned int n_stops,
- cairo_pdf_color_stop_t stops[])
+static cairo_status_t
+_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
+ unsigned int n_stops,
+ cairo_pdf_color_stop_t *stops,
+ cairo_bool_t is_alpha,
+ cairo_pdf_resource_t *function)
{
- cairo_pdf_resource_t function;
+ cairo_pdf_resource_t res;
unsigned int i;
+ cairo_status_t status;
/* emit linear gradients between pairs of subsequent stops... */
for (i = 0; i < n_stops-1; i++) {
- stops[i].gradient = _cairo_pdf_surface_emit_linear_colorgradient (surface,
- &stops[i],
- &stops[i+1]);
+ if (is_alpha) {
+ status = cairo_pdf_surface_emit_alpha_linear_function (surface,
+ &stops[i],
+ &stops[i+1],
+ &stops[i].resource);
+ if (status)
+ return status;
+ } else {
+ status = cairo_pdf_surface_emit_rgb_linear_function (surface,
+ &stops[i],
+ &stops[i+1],
+ &stops[i].resource);
+ if (status)
+ return status;
+ }
}
/* ... and stitch them together */
- function = _cairo_pdf_surface_new_object (surface);
+ res = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /FunctionType 3\r\n"
" /Domain [ 0 1 ]\r\n",
- function.id);
+ res.id);
_cairo_output_stream_printf (surface->output,
" /Functions [ ");
for (i = 0; i < n_stops-1; i++)
- {
_cairo_output_stream_printf (surface->output,
- "%d 0 R ", stops[i].gradient.id);
- }
+ "%d 0 R ", stops[i].resource.id);
_cairo_output_stream_printf (surface->output,
"]\r\n");
_cairo_output_stream_printf (surface->output,
" /Bounds [ ");
for (i = 1; i < n_stops-1; i++)
- {
_cairo_output_stream_printf (surface->output,
"%f ", stops[i].offset);
- }
_cairo_output_stream_printf (surface->output,
"]\r\n");
_cairo_output_stream_printf (surface->output,
" /Encode [ ");
for (i = 1; i < n_stops; i++)
- {
_cairo_output_stream_printf (surface->output,
"0 1 ");
- }
_cairo_output_stream_printf (surface->output,
"]\r\n");
@@ -1109,34 +1243,43 @@ _cairo_pdf_surface_emit_stitched_colorgr
">>\r\n"
"endobj\r\n");
- return function;
+ *function = res;
+
+ return CAIRO_STATUS_SUCCESS;
}
#define COLOR_STOP_EPSILON 1e-6
-static cairo_pdf_resource_t
-_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
+static cairo_status_t
+_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
+ cairo_gradient_pattern_t *pattern,
+ cairo_pdf_resource_t *color_function,
+ cairo_pdf_resource_t *alpha_function)
{
- cairo_pdf_resource_t function;
cairo_pdf_color_stop_t *allstops, *stops;
- unsigned int i, n_stops;
+ unsigned int n_stops;
+ unsigned int i;
+ cairo_bool_t emit_alpha = FALSE;
+ cairo_status_t status;
- function = _cairo_pdf_surface_new_object (surface);
+ color_function->id = 0;
+ alpha_function->id = 0;
allstops = malloc ((pattern->n_stops + 2) * sizeof (cairo_pdf_color_stop_t));
if (allstops == NULL) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- function.id = 0;
- return function;
+ return CAIRO_STATUS_NO_MEMORY;
}
+
stops = &allstops[1];
n_stops = pattern->n_stops;
- for (i = 0; i < pattern->n_stops; i++) {
- stops[i].color_char[0] = pattern->stops[i].color.red >> 8;
- stops[i].color_char[1] = pattern->stops[i].color.green >> 8;
- stops[i].color_char[2] = pattern->stops[i].color.blue >> 8;
- stops[i].color_char[3] = pattern->stops[i].color.alpha >> 8;
+ for (i = 0; i < n_stops; i++) {
+ stops[i].color[0] = pattern->stops[i].color.red / 65535.0;
+ stops[i].color[1] = pattern->stops[i].color.green / 65535.0;
+ stops[i].color[2] = pattern->stops[i].color.blue / 65535.0;
+ stops[i].color[3] = pattern->stops[i].color.alpha / 65535.0;
+ if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
+ emit_alpha = TRUE;
stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
}
@@ -1145,48 +1288,156 @@ _cairo_pdf_surface_emit_pattern_stops (c
if (stops[0].offset > COLOR_STOP_EPSILON) {
memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
stops = allstops;
- stops[0].offset = 0.0;
n_stops++;
}
+ stops[0].offset = 0.0;
+
if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
memcpy (&stops[n_stops],
&stops[n_stops - 1],
sizeof (cairo_pdf_color_stop_t));
- stops[n_stops].offset = 1.0;
n_stops++;
}
+ stops[n_stops].offset = 1.0;
if (n_stops == 2) {
- /* no need for stitched function */
- function = _cairo_pdf_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]);
+ /* no need for stitched function */
+ status = cairo_pdf_surface_emit_rgb_linear_function (surface,
+ &stops[0],
+ &stops[1],
+ color_function);
+ if (status)
+ return status;
+
+ if (emit_alpha) {
+ status = cairo_pdf_surface_emit_alpha_linear_function (surface,
+ &stops[0],
+ &stops[1],
+ alpha_function);
+ if (status)
+ return status;
+ }
} else {
- /* multiple stops: stitch. XXX possible optimization: regulary spaced
- * stops do not require stitching. XXX */
- function = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
- n_stops,
- stops);
- }
+ /* multiple stops: stitch. XXX possible optimization: regulary spaced
+ * stops do not require stitching. XXX */
+ status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
+ n_stops,
+ stops,
+ FALSE,
+ color_function);
+ if (status)
+ return status;
+ if (emit_alpha) {
+ status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
+ n_stops,
+ stops,
+ TRUE,
+ alpha_function);
+ if (status)
+ return status;
+ }
+ }
free (allstops);
- return function;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_pdf_resource_t
+cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
+ cairo_pdf_resource_t gradient_mask)
+{
+ cairo_pdf_resource_t xobj_resource, smask_resource, gstate_resource;
+
+ xobj_resource = _cairo_pdf_surface_open_stream (surface,
+ TRUE,
+ " /Type /XObject\r\n"
+ " /Subtype /Form\r\n"
+ " /FormType 1\r\n"
+ " /BBox [ 0 0 %f %f ]\r\n"
+ " /Resources\r\n"
+ " << /ExtGState\r\n"
+ " << /a0 << /ca 1 /CA 1 >>"
+ " >>\r\n"
+ " /Pattern\r\n"
+ " << /res%d %d 0 R >>\r\n"
+ " >>\r\n"
+ " /Group\r\n"
+ " << /Type /Group\r\n"
+ " /S /Transparency\r\n"
+ " /CS /DeviceGray\r\n"
+ " >>\r\n",
+ surface->width,
+ surface->height,
+ gradient_mask.id,
+ gradient_mask.id);
+
+ _cairo_output_stream_printf (surface->output,
+ "q\r\n"
+ "/a0 gs\r\n"
+ "/Pattern cs /res%d scn\r\n"
+ "0 0 %f %f re\r\n"
+ "f\r\n"
+ "Q\r\n",
+ gradient_mask.id,
+ surface->width,
+ surface->height);
+
+ _cairo_pdf_surface_close_stream (surface);
+
+ smask_resource = _cairo_pdf_surface_new_object (surface);
+ _cairo_output_stream_printf (surface->output,
+ "%d 0 obj\r\n"
+ "<< /Type /Mask\r\n"
+ " /S /Luminosity\r\n"
+ " /G %d 0 R\r\n"
+ " /BC [ 0.0 ]\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ smask_resource.id,
+ xobj_resource.id);
+
+ /* Create GState which uses the transparency group as an SMask. */
+ gstate_resource = _cairo_pdf_surface_new_object (surface);
+ _cairo_output_stream_printf (surface->output,
+ "%d 0 obj\r\n"
+ "<< /Type /ExtGState\r\n"
+ " /SMask %d 0 R\r\n"
+ " /ca 1\r\n"
+ " /CA 1\r\n"
+ " /AIS false\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ gstate_resource.id,
+ smask_resource.id);
+
+ _cairo_pdf_surface_add_smask (surface, gstate_resource);
+
+ return gstate_resource;
}
static cairo_status_t
-_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
+_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
+ cairo_linear_pattern_t *pattern)
{
- cairo_pdf_resource_t function, pattern_resource, alpha;
+ cairo_pdf_resource_t pattern_resource, smask;
+ cairo_pdf_resource_t color_function, alpha_function;
double x0, y0, x1, y1;
cairo_matrix_t p2u;
+ cairo_extend_t extend;
cairo_status_t status;
+ extend = cairo_pattern_get_extend (&pattern->base.base);
status = _cairo_pdf_surface_pause_content_stream (surface);
if (status)
return status;
- function = _cairo_pdf_surface_emit_pattern_stops (surface, &pattern->base);
- if (function.id == 0)
- return CAIRO_STATUS_NO_MEMORY;
+ status = _cairo_pdf_surface_emit_pattern_stops (surface,
+ &pattern->base,
+ &color_function,
+ &alpha_function);
+ if (status)
+ return status;
p2u = pattern->base.base.matrix;
status = cairo_matrix_invert (&p2u);
@@ -1202,61 +1453,110 @@ _cairo_pdf_surface_emit_linear_pattern (
pattern_resource = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
- "%d 0 obj\r\n"
- "<< /Type /Pattern\r\n"
- " /PatternType 2\r\n"
- " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
- " /Shading\r\n"
- " << /ShadingType 2\r\n"
- " /ColorSpace /DeviceRGB\r\n"
- " /Coords [ %f %f %f %f ]\r\n"
- " /Function %d 0 R\r\n"
- " /Extend [ true true ]\r\n"
- " >>\r\n"
- ">>\r\n"
- "endobj\r\n",
- pattern_resource.id,
- surface->height,
- x0, y0, x1, y1,
- function.id);
+ "%d 0 obj\r\n"
+ "<< /Type /Pattern\r\n"
+ " /PatternType 2\r\n"
+ " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
+ " /Shading\r\n"
+ " << /ShadingType 2\r\n"
+ " /ColorSpace /DeviceRGB\r\n"
+ " /Coords [ %f %f %f %f ]\r\n"
+ " /Function %d 0 R\r\n",
+ pattern_resource.id,
+ surface->height,
+ x0, y0, x1, y1,
+ color_function.id);
- status = _cairo_pdf_surface_add_pattern (surface, pattern_resource);
- if (status)
- return status;
+ if (extend == CAIRO_EXTEND_PAD) {
+ _cairo_output_stream_printf (surface->output,
+ " /Extend [ true true ]\r\n");
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ " /Extend [ false false ]\r\n");
+ }
+
+ _cairo_output_stream_printf (surface->output,
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n");
+
+ if (alpha_function.id == 0) {
+ surface->emitted_pattern.smask.id = 0;
+ } else {
+ cairo_pdf_resource_t mask_resource;
+
+ /* Create pattern for SMask. */
+ mask_resource = _cairo_pdf_surface_new_object (surface);
+ _cairo_output_stream_printf (surface->output,
+ "%d 0 obj\r\n"
+ "<< /Type /Pattern\r\n"
+ " /PatternType 2\r\n"
+ " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
+ " /Shading\r\n"
+ " << /ShadingType 2\r\n"
+ " /ColorSpace /DeviceGray\r\n"
+ " /Coords [ %f %f %f %f ]\r\n"
+ " /Function %d 0 R\r\n",
+ mask_resource.id,
+ surface->height,
+ x0, y0, x1, y1,
+ alpha_function.id);
+
+ if (extend == CAIRO_EXTEND_PAD) {
+ _cairo_output_stream_printf (surface->output,
+ " /Extend [ true true ]\r\n");
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ " /Extend [ false false ]\r\n");
+ }
- status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
+ _cairo_output_stream_printf (surface->output,
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n");
+ status = _cairo_pdf_surface_add_pattern (surface, mask_resource);
+ if (status)
+ return status;
+
+ smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
+ surface->emitted_pattern.smask = smask;
+ }
+
+ surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_LINEAR;
+ status = _cairo_pdf_surface_add_alpha (surface, 1, &surface->emitted_pattern.alpha);
if (status)
- return status;
+ return status;
- /* Use pattern */
- /* With some work, we could separate the stroking
- * or non-stroking pattern here as actually needed. */
- _cairo_output_stream_printf (surface->output,
- "/Pattern CS /res%d SCN "
- "/Pattern cs /res%d scn "
- "/a%d gs\r\n",
- pattern_resource.id,
- pattern_resource.id,
- alpha.id);
+ surface->emitted_pattern.pattern = pattern_resource;
+ status = _cairo_pdf_surface_add_pattern (surface, pattern_resource);
+ if (status)
+ return status;
return _cairo_pdf_surface_resume_content_stream (surface);
}
static cairo_status_t
-_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
+_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface,
+ cairo_radial_pattern_t *pattern)
{
- cairo_pdf_resource_t function, pattern_resource, alpha;
+ cairo_pdf_resource_t pattern_resource, smask;
+ cairo_pdf_resource_t color_function, alpha_function;
double x0, y0, x1, y1, r0, r1;
- cairo_matrix_t p2u;
+ cairo_matrix_t p2u, pdf_p2d;
+ cairo_extend_t extend;
cairo_status_t status;
+ extend = cairo_pattern_get_extend (&pattern->base.base);
status = _cairo_pdf_surface_pause_content_stream (surface);
if (status)
return status;
- function = _cairo_pdf_surface_emit_pattern_stops (surface, &pattern->base);
- if (function.id == 0)
- return CAIRO_STATUS_NO_MEMORY;
+ status = _cairo_pdf_surface_emit_pattern_stops (surface,
+ &pattern->base,
+ &color_function,
+ &alpha_function);
+ if (status)
+ return status;
p2u = pattern->base.base.matrix;
status = cairo_matrix_invert (&p2u);
@@ -1266,62 +1566,99 @@ _cairo_pdf_surface_emit_radial_pattern (
x0 = _cairo_fixed_to_double (pattern->gradient.c1.x);
y0 = _cairo_fixed_to_double (pattern->gradient.c1.y);
r0 = _cairo_fixed_to_double (pattern->gradient.c1.radius);
- cairo_matrix_transform_point (&p2u, &x0, &y0);
x1 = _cairo_fixed_to_double (pattern->gradient.c2.x);
y1 = _cairo_fixed_to_double (pattern->gradient.c2.y);
r1 = _cairo_fixed_to_double (pattern->gradient.c2.radius);
- cairo_matrix_transform_point (&p2u, &x1, &y1);
- /* FIXME: This is surely crack, but how should you scale a radius
- * in a non-orthogonal coordinate system? */
- cairo_matrix_transform_distance (&p2u, &r0, &r1);
-
- /* FIXME: There is a difference between the cairo gradient extend
- * semantics and PDF extend semantics. PDFs extend=false means
- * that nothing is painted outside the gradient boundaries,
- * whereas cairo takes this to mean that the end color is padded
- * to infinity. Setting extend=true in PDF gives the cairo default
- * behavoir, not yet sure how to implement the cairo mirror and
- * repeat behaviour. */
+ cairo_matrix_init_identity (&pdf_p2d);
+ cairo_matrix_translate (&pdf_p2d, 0.0, surface->height);
+ cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
+ cairo_matrix_multiply (&pdf_p2d, &p2u, &pdf_p2d);
+
pattern_resource = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
- "%d 0 obj\r\n"
- "<< /Type /Pattern\r\n"
- " /PatternType 2\r\n"
- " /Matrix [ 1 0 0 -1 0 %f ]\r\n"
- " /Shading\r\n"
- " << /ShadingType 3\r\n"
- " /ColorSpace /DeviceRGB\r\n"
- " /Coords [ %f %f %f %f %f %f ]\r\n"
- " /Function %d 0 R\r\n"
- " /Extend [ true true ]\r\n"
- " >>\r\n"
- ">>\r\n"
- "endobj\r\n",
- pattern_resource.id,
- surface->height,
- x0, y0, r0, x1, y1, r1,
- function.id);
+ "%d 0 obj\r\n"
+ "<< /Type /Pattern\r\n"
+ " /PatternType 2\r\n"
+ " /Matrix [ %f %f %f %f %f %f ]\r\n"
+ " /Shading\r\n"
+ " << /ShadingType 3\r\n"
+ " /ColorSpace /DeviceRGB\r\n"
+ " /Coords [ %f %f %f %f %f %f ]\r\n"
+ " /Function %d 0 R\r\n",
+ pattern_resource.id,
+ pdf_p2d.xx, pdf_p2d.yx,
+ pdf_p2d.xy, pdf_p2d.yy,
+ pdf_p2d.x0, pdf_p2d.y0,
+ x0, y0, r0, x1, y1, r1,
+ color_function.id);
- status = _cairo_pdf_surface_add_pattern (surface, pattern_resource);
+ if (extend == CAIRO_EXTEND_PAD) {
+ _cairo_output_stream_printf (surface->output,
+ " /Extend [ true true ]\r\n");
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ " /Extend [ false false ]\r\n");
+ }
+
+ _cairo_output_stream_printf (surface->output,
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n");
+
+ if (alpha_function.id == 0) {
+ surface->emitted_pattern.smask.id = 0;
+ } else {
+ cairo_pdf_resource_t mask_resource;
+
+ /* Create pattern for SMask. */
+ mask_resource = _cairo_pdf_surface_new_object (surface);
+ _cairo_output_stream_printf (surface->output,
+ "%d 0 obj\r\n"
+ "<< /Type /Pattern\r\n"
+ " /PatternType 2\r\n"
+ " /Matrix [ %f %f %f %f %f %f ]\r\n"
+ " /Shading\r\n"
+ " << /ShadingType 3\r\n"
+ " /ColorSpace /DeviceGray\r\n"
+ " /Coords [ %f %f %f %f %f %f ]\r\n"
+ " /Function %d 0 R\r\n",
+ mask_resource.id,
+ pdf_p2d.xx, pdf_p2d.yx,
+ pdf_p2d.xy, pdf_p2d.yy,
+ pdf_p2d.x0, pdf_p2d.y0,
+ x0, y0, r0, x1, y1, r1,
+ alpha_function.id);
+
+ if (extend == CAIRO_EXTEND_PAD) {
+ _cairo_output_stream_printf (surface->output,
+ " /Extend [ true true ]\r\n");
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ " /Extend [ false false ]\r\n");
+ }
+
+ _cairo_output_stream_printf (surface->output,
+ " >>\r\n"
+ ">>\r\n"
+ "endobj\r\n");
+
+ smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
+ surface->emitted_pattern.smask = smask;
+ }
+
+ surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_RADIAL;
+
+ status = _cairo_pdf_surface_add_alpha (surface, 1.0, &surface->emitted_pattern.alpha);
if (status)
return status;
- status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
+ surface->emitted_pattern.pattern = pattern_resource;
+
+ status = _cairo_pdf_surface_add_pattern (surface, pattern_resource);
if (status)
return status;
- /* Use pattern */
- /* With some work, we could separate the stroking
- * or non-stroking pattern here as actually needed. */
- _cairo_output_stream_printf (surface->output,
- "/Pattern CS /res%d SCN "
- "/Pattern cs /res%d scn "
- "/a%d gs\r\n",
- pattern_resource.id,
- pattern_resource.id,
- alpha.id);
-
return _cairo_pdf_surface_resume_content_stream (surface);
}
@@ -1340,13 +1677,52 @@ _cairo_pdf_surface_emit_pattern (cairo_p
case CAIRO_PATTERN_TYPE_RADIAL:
return _cairo_pdf_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
-
}
ASSERT_NOT_REACHED;
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
}
+static cairo_status_t
+_cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
+ cairo_bool_t is_stroke)
+{
+ if (surface->emitted_pattern.type == CAIRO_PATTERN_TYPE_SOLID) {
+ _cairo_output_stream_printf (surface->output,
+ "%f %f %f ",
+ surface->emitted_pattern.red,
+ surface->emitted_pattern.green,
+ surface->emitted_pattern.blue);
+
+ if (is_stroke)
+ _cairo_output_stream_printf (surface->output, "RG ");
+ else
+ _cairo_output_stream_printf (surface->output, "rg ");
+
+ _cairo_output_stream_printf (surface->output,
+ "/a%d gs\r\n",
+ surface->emitted_pattern.alpha);
+ } else {
+ if (is_stroke) {
+ _cairo_output_stream_printf (surface->output,
+ "/Pattern CS /res%d SCN ",
+ surface->emitted_pattern.pattern);
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ "/Pattern cs /res%d scn ",
+ surface->emitted_pattern.pattern);
+ }
+
+ _cairo_output_stream_printf (surface->output,
+ "/a%d gs ",
+ surface->emitted_pattern.alpha );
+
+ _cairo_output_stream_printf (surface->output, "\r\n");
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
static cairo_int_status_t
_cairo_pdf_surface_copy_page (void *abstract_surface)
{
@@ -1548,10 +1924,10 @@ _cairo_pdf_surface_write_info (cairo_pdf
static void
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
{
- cairo_pdf_resource_t page, *res;
+ cairo_pdf_resource_t page, *res, smask;
cairo_pdf_font_t font;
int num_pages, num_fonts, i;
- int num_alphas, num_resources;
+ int num_alphas, num_smasks, num_resources;
double alpha;
_cairo_pdf_surface_update_object (surface, surface->pages_resource);
@@ -1573,19 +1949,25 @@ _cairo_pdf_surface_write_pages (cairo_pd
_cairo_output_stream_printf (surface->output, " /Resources <<\r\n");
num_alphas = _cairo_array_num_elements (&surface->alphas);
- if (num_alphas > 0) {
+ num_smasks = _cairo_array_num_elements (&surface->smasks);
+ if (num_alphas > 0 || num_smasks > 0) {
_cairo_output_stream_printf (surface->output,
" /ExtGState <<\r\n");
for (i = 0; i < num_alphas; i++) {
- /* With some work, we could separate the stroking
- * or non-stroking alpha here as actually needed. */
_cairo_array_copy_element (&surface->alphas, i, &alpha);
_cairo_output_stream_printf (surface->output,
" /a%d << /CA %f /ca %f >>\r\n",
i, alpha, alpha);
}
+ for (i = 0; i < num_smasks; i++) {
+ _cairo_array_copy_element (&surface->smasks, i, &smask);
+ _cairo_output_stream_printf (surface->output,
+ " /sm%d %d 0 R\r\n",
+ smask.id, smask.id);
+ }
+
_cairo_output_stream_printf (surface->output,
" >>\r\n");
}
@@ -1621,14 +2003,20 @@ _cairo_pdf_surface_write_pages (cairo_pd
" >>\r\n");
}
- _cairo_output_stream_printf (surface->output," /Font <<\r\n");
num_fonts = _cairo_array_num_elements (&surface->fonts);
- for (i = 0; i < num_fonts; i++) {
- _cairo_array_copy_element (&surface->fonts, i, &font);
- _cairo_output_stream_printf (surface->output, " /CairoFont-%d-%d %d 0 R\r\n",
- font.font_id, font.subset_id, font.subset_resource.id);
+ if (num_fonts > 0) {
+ _cairo_output_stream_printf (surface->output," /Font <<\r\n");
+ num_fonts = _cairo_array_num_elements (&surface->fonts);
+ for (i = 0; i < num_fonts; i++) {
+ _cairo_array_copy_element (&surface->fonts, i, &font);
+ _cairo_output_stream_printf (surface->output,
+ " /CairoFont-%d-%d %d 0 R\r\n",
+ font.font_id,
+ font.subset_id,
+ font.subset_resource.id);
+ }
+ _cairo_output_stream_printf (surface->output, " >>\r\n");
}
- _cairo_output_stream_printf (surface->output, " >>\r\n");
_cairo_output_stream_printf (surface->output,
" >>\r\n");
@@ -2646,11 +3034,49 @@ _surface_pattern_supported (cairo_surfac
}
static cairo_bool_t
+_gradient_pattern_supported (cairo_pattern_t *pattern)
+{
+ cairo_extend_t extend;
+
+ extend = cairo_pattern_get_extend (pattern);
+
+ if (extend == CAIRO_EXTEND_REPEAT ||
+ extend == CAIRO_EXTEND_REFLECT) {
+ return FALSE;
+ }
+
+ /* Radial gradients are currently only supported when one circle
+ * is inside the other. */
+ if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
+ double x1, y1, x2, y2, r1, r2, d;
+ cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
+
+ x1 = _cairo_fixed_to_double (radial->gradient.c1.x);
+ y1 = _cairo_fixed_to_double (radial->gradient.c1.y);
+ r1 = _cairo_fixed_to_double (radial->gradient.c1.radius);
+ x2 = _cairo_fixed_to_double (radial->gradient.c2.x);
+ y2 = _cairo_fixed_to_double (radial->gradient.c2.y);
+ r2 = _cairo_fixed_to_double (radial->gradient.c2.radius);
+
+ d = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
+ if (d > fabs(r2 - r1)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static cairo_bool_t
_pattern_supported (cairo_pattern_t *pattern)
{
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
return TRUE;
+ if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
+ pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
+ return _gradient_pattern_supported (pattern);
+
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
@@ -2693,6 +3119,7 @@ _cairo_pdf_surface_paint (void *abstra
cairo_pattern_t *source)
{
cairo_pdf_surface_t *surface = abstract_surface;
+ cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
cairo_status_t status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@@ -2712,10 +3139,35 @@ _cairo_pdf_surface_paint (void *abstra
if (status)
return status;
+ if (surface->emitted_pattern.smask.id != 0) {
+ status = _cairo_pdf_surface_begin_group (surface, &group);
+ if (status)
+ return status;
+ _cairo_output_stream_printf (surface->output,
+ "1 0 0 -1 0 %f cm\r\n",
+ surface->height);
+ } else {
+ _cairo_output_stream_printf (surface->output, "q ");
+ }
+
+ _cairo_pdf_surface_select_pattern (surface, FALSE);
+
_cairo_output_stream_printf (surface->output,
"0 0 %f %f re f\r\n",
surface->width, surface->height);
+ if (surface->emitted_pattern.smask.id != 0) {
+ _cairo_pdf_surface_end_group (surface);
+
+ _cairo_output_stream_printf (surface->output,
+ "q 1 0 0 -1 0 %f cm /sm%d gs /res%d Do Q\r\n",
+ surface->height,
+ surface->emitted_pattern.smask,
+ group.id);
+ } else {
+ _cairo_output_stream_printf (surface->output, "Q\r\n");
+ }
+
return _cairo_output_stream_get_status (surface->output);
}
@@ -2813,6 +3265,7 @@ _cairo_pdf_surface_stroke (void *abstr
cairo_antialias_t antialias)
{
cairo_pdf_surface_t *surface = abstract_surface;
+ cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
pdf_path_info_t info;
cairo_status_t status;
@@ -2825,6 +3278,19 @@ _cairo_pdf_surface_stroke (void *abstr
if (status)
return status;
+ if (surface->emitted_pattern.smask.id != 0) {
+ status = _cairo_pdf_surface_begin_group (surface, &group);
+ if (status)
+ return status;
+ _cairo_output_stream_printf (surface->output,
+ "1 0 0 -1 0 %f cm\r\n",
+ surface->height);
+ } else {
+ _cairo_output_stream_printf (surface->output, "q ");
+ }
+
+ _cairo_pdf_surface_select_pattern (surface, TRUE);
+
status = _cairo_pdf_surface_emit_stroke_style (surface,
style);
if (status)
@@ -2848,6 +3314,18 @@ _cairo_pdf_surface_stroke (void *abstr
_cairo_output_stream_printf (surface->output, "S Q\r\n");
+ if (surface->emitted_pattern.smask.id != 0) {
+ _cairo_pdf_surface_end_group (surface);
+
+ _cairo_output_stream_printf (surface->output,
+ "q 1 0 0 -1 0 %f cm /sm%d gs /res%d Do Q\r\n",
+ surface->height,
+ surface->emitted_pattern.smask,
+ group.id);
+ } else {
+ _cairo_output_stream_printf (surface->output, "Q\r\n");
+ }
+
return status;
}
@@ -2861,6 +3339,7 @@ _cairo_pdf_surface_fill (void *abstrac
cairo_antialias_t antialias)
{
cairo_pdf_surface_t *surface = abstract_surface;
+ cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
const char *pdf_operator;
cairo_status_t status;
pdf_path_info_t info;
@@ -2874,9 +3353,20 @@ _cairo_pdf_surface_fill (void *abstrac
if (status)
return status;
+ if (surface->emitted_pattern.smask.id != 0) {
+ status = _cairo_pdf_surface_begin_group (surface, &group);
+ if (status)
+ return status;
+ _cairo_output_stream_printf (surface->output,
+ "1 0 0 -1 0 %f cm\r\n",
+ surface->height);
+ } else {
+ _cairo_output_stream_printf (surface->output, "q ");
+ }
+
+ _cairo_pdf_surface_select_pattern (surface, FALSE);
info.output = surface->output;
info.ctm_inverse = NULL;
-
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
@@ -2900,6 +3390,18 @@ _cairo_pdf_surface_fill (void *abstrac
"%s\r\n",
pdf_operator);
+ if (surface->emitted_pattern.smask.id != 0) {
+ _cairo_pdf_surface_end_group (surface);
+
+ _cairo_output_stream_printf (surface->output,
+ "q 1 0 0 -1 0 %f cm /sm%d gs /res%d Do Q\r\n",
+ surface->height,
+ surface->emitted_pattern.smask,
+ group.id);
+ } else {
+ _cairo_output_stream_printf (surface->output, "Q\r\n");
+ }
+
return status;
}
@@ -2914,6 +3416,7 @@ _cairo_pdf_surface_show_glyphs (void *
cairo_scaled_font_t *scaled_font)
{
cairo_pdf_surface_t *surface = abstract_surface;
+ cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
unsigned int current_subset_id = (unsigned int)-1;
cairo_scaled_font_subsets_glyph_t subset_glyph;
cairo_bool_t diagonal, in_TJ;
@@ -2931,6 +3434,19 @@ _cairo_pdf_surface_show_glyphs (void *
if (status)
return status;
+ if (surface->emitted_pattern.smask.id != 0) {
+ status = _cairo_pdf_surface_begin_group (surface, &group);
+ if (status)
+ return status;
+ _cairo_output_stream_printf (surface->output,
+ "1 0 0 -1 0 %f cm\r\n",
+ surface->height);
+ } else {
+ _cairo_output_stream_printf (surface->output, "q ");
+ }
+
+ _cairo_pdf_surface_select_pattern (surface, FALSE);
+
_cairo_output_stream_printf (surface->output,
"BT\r\n");
@@ -3068,6 +3584,18 @@ _cairo_pdf_surface_show_glyphs (void *
_cairo_output_stream_printf (surface->output,
"ET\r\n");
+ if (surface->emitted_pattern.smask.id != 0) {
+ _cairo_pdf_surface_end_group (surface);
+
+ _cairo_output_stream_printf (surface->output,
+ "q 1 0 0 -1 0 %f cm /sm%d gs /res%d Do Q\r\n",
+ surface->height,
+ surface->emitted_pattern.smask,
+ group.id);
+ } else {
+ _cairo_output_stream_printf (surface->output, "Q\r\n");
+ }
+
return _cairo_output_stream_get_status (surface->output);
}
More information about the cairo-commit
mailing list