[cairo-commit] 14 commits - src/cairo-analysis-surface.c src/cairoint.h src/cairo-paginated-private.h src/cairo-paginated-surface.c src/cairo-pattern.c src/cairo-pdf-operators.c src/cairo-pdf-operators-private.h src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h src/cairo-surface.c src/cairo-types-private.h src/Makefile.am
Adrian Johnson
ajohnson at kemper.freedesktop.org
Mon Jan 7 03:11:43 PST 2008
src/Makefile.am | 1
src/cairo-analysis-surface.c | 11
src/cairo-paginated-private.h | 22
src/cairo-paginated-surface.c | 4
src/cairo-pattern.c | 28
src/cairo-pdf-operators-private.h | 106 +
src/cairo-pdf-operators.c | 531 +++++++++
src/cairo-pdf-surface-private.h | 69 -
src/cairo-pdf-surface.c | 2214 ++++++++++++++------------------------
src/cairo-surface.c | 84 -
src/cairo-types-private.h | 3
src/cairoint.h | 4
12 files changed, 1601 insertions(+), 1476 deletions(-)
New commits:
commit 25f24e79f84e0c04a8c6944cc6e018e9eb2df997
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 21:19:35 2008 +1030
PDF: Update the PDF page structure comment
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 614d655..40edb22 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -88,37 +88,6 @@
* that fallback images do not composite with any content under the
* fallback images.
*
- * The group containing the supported operations (content_group_list
- * in the example below) does not do any drawing directly. Instead it
- * paints groups containing the drawing operations and performs
- * clipping. The reason for this is that clipping operations performed
- * in a group do not affect the parent group.
- *
- * Example PDF Page Structure:
- *
- * Page Content
- * ------------
- * /knockout_group Do
- *
- * knockout_group
- * --------------
- * /content_group_list Do
- * /fallback_image_1 Do
- * /fallback_image_2 Do
- * ...
- *
- * content_group_list
- * ------------------
- * q
- * /content_group_1 Do
- * /content_group_2 Do
- * 10 10 m 10 20 l 20 20 l 20 10 l h W # clip
- * /content_group_3 Do
- * Q q # reset clip
- * /content_group_4 Do
- * Q
- *
- *
* Streams:
*
* This PDF surface has three types of streams:
@@ -139,42 +108,21 @@
*
* Content Stream:
* The Content Stream is opened and closed with the following functions:
- * _cairo_pdf_surface_start_content_stream ()
- * _cairo_pdf_surface_stop_content_stream ()
- *
- * The Content Stream is written to content_group_n groups (as shown
- * in the page structure example). The Content Stream may be paused
- * and resumed with the following functions:
- * _cairo_pdf_surface_pause_content_stream ()
- * _cairo_pdf_surface_resume_content_stream ()
- *
- * When the Content Stream is paused, a PDF Stream or Group Stream
- * may be opened. After closing the PDF Stream or Group Stream the
- * Content Stream may be resumed.
+ * _cairo_pdf_surface_open_content_stream ()
+ * _cairo_pdf_surface_close_content_stream ()
*
- * The Content Stream contains the text and graphics operators. When
- * a pattern is required the Content Stream is paused, a PDF Stream
- * is opened, the pattern is written to a PDF Stream, the PDF Stream
- * is closed, then the Content Stream is resumed.
- *
- * Each group comprising the Content Stream is stored in memory
- * until the stream is closed or the maximum group size is
- * exceeded. This is due to the need to list all resources used in
- * the group in the group's stream dictionary.
+ * The Content Stream contains the text and graphics operators.
*
* Group Stream:
* A Group Stream may be opened and closed with the following functions:
* _cairo_pdf_surface_open_group ()
* _cairo_pdf_surface_close_group ()
*
- * A Group Stream is written to a separate group in the PDF file
- * that is not part of the Content Stream. Group Streams are also
- * stored in memory until the stream is closed due to the need to
- * list the resources used in the group in the group's stream
- * dictionary.
- *
- * Group Streams are used for short sequences of graphics operations
- * that need to be in a separate group from the Content Stream.
+ * A Group Stream is a Form XObject. It is used for short sequences
+ * of operators. As the content is very short the group is stored in
+ * memory until it is closed. This allows some optimization such as
+ * including the Resource dictionary and stream length inside the
+ * XObject instead of using an indirect object.
*/
typedef struct _cairo_pdf_object {
commit 21f842f0dfd5dd3cc1fd3b56db034fc4e209adaa
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 21:17:26 2008 +1030
PDF: Remove copy_page
Now that the content stream is no longer split into multiple streams
it is not possible to implement a copy_page function that shares the
common content between pages.
Remove this function so the paginated surface will rewrite the
content from the meta surface.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index c018764..614d655 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2687,19 +2687,6 @@ _cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
}
static cairo_int_status_t
-_cairo_pdf_surface_copy_page (void *abstract_surface)
-{
- cairo_pdf_surface_t *surface = abstract_surface;
- cairo_int_status_t status;
-
- status = _cairo_pdf_surface_close_content_stream (surface);
- if (status)
- return status;
-
- return _cairo_pdf_surface_write_page (surface);
-}
-
-static cairo_int_status_t
_cairo_pdf_surface_show_page (void *abstract_surface)
{
cairo_pdf_surface_t *surface = abstract_surface;
@@ -4577,7 +4564,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
- _cairo_pdf_surface_copy_page,
+ NULL, /* _cairo_pdf_surface_copy_page */
_cairo_pdf_surface_show_page,
NULL, /* set_clip_region */
_cairo_pdf_surface_intersect_clip_path,
commit e2adb921f8b7619410db971d1524cbeab2dd6102
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 21:15:18 2008 +1030
PDF: Put each fallback image in a separate group
Each fallback image needs to be in a separate group in the knockout
group. Otherwise transparent edges of adjacent fallback images will
composite with each other creating visible seams between the images.
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 5e6ac82..233b01d 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -110,6 +110,7 @@ struct _cairo_pdf_surface {
cairo_array_t alpha_linear_functions;
cairo_array_t patterns;
cairo_array_t smask_groups;
+ cairo_array_t knockout_group;
cairo_scaled_font_subsets_t *font_subsets;
cairo_array_t fonts;
@@ -120,7 +121,6 @@ struct _cairo_pdf_surface {
cairo_bool_t compress_content;
cairo_pdf_resource_t content;
- cairo_pdf_resource_t fallback_content;
cairo_pdf_resource_t content_resources;
cairo_pdf_group_resources_t resources;
cairo_bool_t has_fallback_images;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index a4243d0..c018764 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -311,6 +311,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
_cairo_array_init (&surface->patterns, sizeof (cairo_pdf_pattern_t));
_cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
+ _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
_cairo_pdf_group_resources_init (&surface->resources);
@@ -540,6 +541,7 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
_cairo_pdf_smask_group_destroy (group);
}
_cairo_array_truncate (&surface->smask_groups, 0);
+ _cairo_array_truncate (&surface->knockout_group, 0);
}
static void
@@ -1250,6 +1252,7 @@ _cairo_pdf_surface_finish (void *abstract_surface)
_cairo_array_fini (&surface->patterns);
_cairo_array_fini (&surface->smask_groups);
_cairo_array_fini (&surface->fonts);
+ _cairo_array_fini (&surface->knockout_group);
if (surface->font_subsets) {
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
@@ -4005,8 +4008,9 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface
static cairo_status_t
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
{
- cairo_pdf_resource_t page, knockout;
+ cairo_pdf_resource_t page, knockout, res;
cairo_status_t status;
+ int i, len;
_cairo_pdf_group_resources_clear (&surface->resources);
if (surface->has_fallback_images) {
@@ -4014,13 +4018,19 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
if (status)
return status;
+ len = _cairo_array_num_elements (&surface->knockout_group);
+ for (i = 0; i < len; i++) {
+ _cairo_array_copy_element (&surface->knockout_group, i, &res);
+ _cairo_output_stream_printf (surface->output,
+ "/x%d Do\r\n",
+ res.id);
+ _cairo_pdf_surface_add_xobject (surface, res);
+ }
_cairo_output_stream_printf (surface->output,
- "/x%d Do\r\n"
"/x%d Do\r\n",
- surface->content.id,
- surface->fallback_content.id);
+ surface->content.id);
_cairo_pdf_surface_add_xobject (surface, surface->content);
- _cairo_pdf_surface_add_xobject (surface, surface->fallback_content);
+
status = _cairo_pdf_surface_close_group (surface, &knockout);
if (status)
return status;
@@ -4204,10 +4214,14 @@ _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
if (status)
return status;
+ status = _cairo_array_append (&surface->knockout_group, &surface->content);
+ if (status)
+ return status;
+
surface->has_fallback_images = TRUE;
_cairo_pdf_group_resources_clear (&surface->resources);
return _cairo_pdf_surface_open_content_stream (surface,
- &surface->fallback_content,
+ &surface->content,
TRUE);
}
commit d6a84302a07d2b7e67584029fdb7a882ad246a09
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 21:11:46 2008 +1030
Fix analysis of transformed meta surfaces
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index b6f09f8..29b74f3 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -70,7 +70,7 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *
cairo_surface_pattern_t *surface_pattern;
cairo_status_t status;
cairo_bool_t old_has_ctm;
- cairo_matrix_t old_ctm;
+ cairo_matrix_t old_ctm, p2d;
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
surface_pattern = (cairo_surface_pattern_t *) pattern;
@@ -78,7 +78,12 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *
old_ctm = surface->ctm;
old_has_ctm = surface->has_ctm;
- cairo_matrix_multiply (&surface->ctm, &pattern->matrix, &surface->ctm);
+ p2d = pattern->matrix;
+ status = cairo_matrix_invert (&p2d);
+ /* _cairo_pattern_set_matrix guarantees invertibility */
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface,
@@ -114,7 +119,7 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
&x1, &y1, &x2, &y2,
NULL);
rect->x = floor (x1);
- rect->y = floor (x2);
+ rect->y = floor (y1);
x2 = ceil (x2) - rect->x;
y2 = ceil (y2) - rect->y;
commit 3c725d50db43b848b4ad8f35bcabd5b1d0395924
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 21:09:04 2008 +1030
PDF: Make _SOURCE operator work inside meta surface patterns
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index a99267c..a4243d0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1595,6 +1595,7 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
{
double old_width, old_height;
cairo_matrix_t old_cairo_to_pdf;
+ cairo_paginated_mode_t old_paginated_mode;
cairo_rectangle_int16_t meta_extents;
cairo_status_t status;
int alpha = 0;
@@ -1606,8 +1607,14 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
old_width = surface->width;
old_height = surface->height;
old_cairo_to_pdf = surface->cairo_to_pdf;
+ old_paginated_mode = surface->paginated_mode;
surface->width = meta_extents.width;
surface->height = meta_extents.height;
+ /* Patterns are emitted after fallback images. The paginated mode
+ * needs to be set to _RENDER while the meta surface is replayed
+ * back to this surface.
+ */
+ surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
surface->cairo_to_pdf);
@@ -1641,6 +1648,7 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
CLEANUP_GROUP:
surface->width = old_width;
surface->height = old_height;
+ surface->paginated_mode = old_paginated_mode;
surface->cairo_to_pdf = old_cairo_to_pdf;
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
surface->cairo_to_pdf);
@@ -4157,15 +4165,17 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
if (! _pattern_supported (pattern))
return CAIRO_INT_STATUS_UNSUPPORTED;
- if (op == CAIRO_OPERATOR_OVER) {
+ if (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_SOURCE) {
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
if ( _cairo_surface_is_meta (surface_pattern->surface))
- return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
+ return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
}
- return CAIRO_STATUS_SUCCESS;
}
+ if (op == CAIRO_OPERATOR_OVER)
+ return CAIRO_STATUS_SUCCESS;
+
/* The SOURCE operator is only if there is nothing painted
* underneath. */
if (op == CAIRO_OPERATOR_SOURCE)
commit 6d6b74ac4ce3a9bcab45c338fc31e5a83823cde6
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 21:08:09 2008 +1030
PDF: Support _OPERATOR_SOURCE when nothing under the operation
CAIRO_OPERATOR_SOURCE operations on the PDF backend are now natively
supported when there is nothing already underneath the operation.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index c437ce4..a99267c 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -4166,10 +4166,10 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
- /* The SOURCE operator is only supported for the fallback images. */
- if (op == CAIRO_OPERATOR_SOURCE &&
- surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK)
- return CAIRO_STATUS_SUCCESS;
+ /* The SOURCE operator is only if there is nothing painted
+ * underneath. */
+ if (op == CAIRO_OPERATOR_SOURCE)
+ return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -4186,27 +4186,19 @@ _cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
}
static cairo_int_status_t
-_cairo_pdf_surface_set_operator (cairo_pdf_surface_t *surface,
- cairo_operator_t op)
+_cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
{
cairo_status_t status;
- if (op == CAIRO_OPERATOR_OVER)
- return CAIRO_STATUS_SUCCESS;
-
- if (op == CAIRO_OPERATOR_SOURCE) {
- status = _cairo_pdf_surface_close_content_stream (surface);
- if (status)
- return status;
-
- surface->has_fallback_images = TRUE;
- _cairo_pdf_group_resources_clear (&surface->resources);
- return _cairo_pdf_surface_open_content_stream (surface,
- &surface->fallback_content,
- TRUE);
- }
+ status = _cairo_pdf_surface_close_content_stream (surface);
+ if (status)
+ return status;
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ surface->has_fallback_images = TRUE;
+ _cairo_pdf_group_resources_clear (&surface->resources);
+ return _cairo_pdf_surface_open_content_stream (surface,
+ &surface->fallback_content,
+ TRUE);
}
static cairo_int_status_t
@@ -4219,15 +4211,16 @@ _cairo_pdf_surface_paint (void *abstract_surface,
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
- if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
return _cairo_pdf_surface_analyze_operation (surface, op, source);
+ } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
+ status = _cairo_pdf_surface_start_fallback (surface);
+ if (status)
+ return status;
+ }
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
- status = _cairo_pdf_surface_set_operator (surface, op);
- if (status)
- return status;
-
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
@@ -4291,15 +4284,15 @@ _cairo_pdf_surface_mask (void *abstract_surface,
return status2;
return status;
+ } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
+ status = _cairo_pdf_surface_start_fallback (surface);
+ if (status)
+ return status;
}
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
assert (_cairo_pdf_surface_operation_supported (surface, op, mask));
- status = _cairo_pdf_surface_set_operator (surface, op);
- if (status)
- return status;
-
group = _cairo_pdf_surface_create_smask_group (surface);
if (group == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -4414,15 +4407,16 @@ _cairo_pdf_surface_fill (void *abstract_surface,
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
- if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
return _cairo_pdf_surface_analyze_operation (surface, op, source);
+ } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
+ status = _cairo_pdf_surface_start_fallback (surface);
+ if (status)
+ return status;
+ }
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
- status = _cairo_pdf_surface_set_operator (surface, op);
- if (status)
- return status;
-
pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
commit e195cb551caa40f309127ac7a39e4a17653966c8
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 21:05:36 2008 +1030
Add FALLBACK mode to paginated surface
The PDF surface needs to know when the fallback images start so it can
close off the content stream and create a knockout transparency group
for the fallback images. Currently it does this by looking for
operations with CAIRO_OPERATOR_SOURCE. PDF returns unsupported for
_SOURCE during the analysis phase so _SOURCE will never appear during
native operations. However this prevents the PDF surface from
supporting _SOURCE operations that can be natively supported. For
example a _SOURCE operation with nothing painting under it can be
converted to _OVER and natively supported.
A third mode, CAIRO_PAGINATED_MODE_FALLBACK, has been added. The
paginated surface will set this mode before it paints finer-grained
fallback images.
diff --git a/src/cairo-paginated-private.h b/src/cairo-paginated-private.h
index 1ecb014..7b41191 100644
--- a/src/cairo-paginated-private.h
+++ b/src/cairo-paginated-private.h
@@ -110,18 +110,22 @@ struct _cairo_paginated_surface_backend {
*
* 6. Replays a subset of the meta-surface operations to the target surface
*
- * 7. Replays the remaining operations to an image surface, sets an
+ * 7. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_FALLBACK
+ *
+ * 8. Replays the remaining operations to an image surface, sets an
* appropriate clip on the target, then paints the resulting image
* surface to the target.
*
- * So, the target will see drawing operations during two separate
- * stages, (ANALYZE and RENDER). During the ANALYZE phase the target
- * should not actually perform any rendering, (for example, if
- * performing output to a file, no output should be generated during
- * this stage). Instead the drawing functions simply need to return
- * CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate
- * whether rendering would be supported. And it should do this as
- * quickly as possible.
+ * So, the target will see drawing operations during three separate
+ * stages, (ANALYZE, RENDER and FALLBACK). During the ANALYZE phase
+ * the target should not actually perform any rendering, (for example,
+ * if performing output to a file, no output should be generated
+ * during this stage). Instead the drawing functions simply need to
+ * return CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to
+ * indicate whether rendering would be supported. And it should do
+ * this as quickly as possible. The FALLBACK phase allows the surface
+ * to distinguish fallback images from native rendering in case they
+ * need to be handled as a special case.
*
* NOTE: The paginated surface layer assumes that the target surface
* is "blank" by default at the beginning of each page, without any
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 068a60c..d644d87 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -365,7 +365,9 @@ _paint_page (cairo_paginated_surface_t *surface)
cairo_box_int_t *boxes;
int num_boxes, i;
- /* Reset clip region before drawing the fall back images */
+ surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK);
+
+ /* Reset clip region before drawing the fall back images */
status = _cairo_surface_intersect_clip_path (surface->target,
NULL,
CAIRO_FILL_RULE_WINDING,
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index dae9e94..c437ce4 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -4168,7 +4168,7 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
/* The SOURCE operator is only supported for the fallback images. */
if (op == CAIRO_OPERATOR_SOURCE &&
- surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER)
+ surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK)
return CAIRO_STATUS_SUCCESS;
return CAIRO_INT_STATUS_UNSUPPORTED;
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index a7af712..3954f13 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -123,7 +123,8 @@ struct _cairo_cache {
typedef enum _cairo_paginated_mode {
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
- CAIRO_PAGINATED_MODE_RENDER /* render page contents */
+ CAIRO_PAGINATED_MODE_RENDER, /* render page contents */
+ CAIRO_PAGINATED_MODE_FALLBACK /* paint fallback images */
} cairo_paginated_mode_t;
/* Sure wish C had a real enum type so that this would be distinct
commit d2a5d1ace64cb9efabcb065e7fc28667dd8f779d
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 21:04:06 2008 +1030
PDF: Remove the remaining code for splitting the content
across multiple streams. This fixes the problem reported here
http://lists.cairographics.org/archives/cairo/2007-December/012197.html
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 7012155..5e6ac82 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -108,8 +108,6 @@ struct _cairo_pdf_surface {
cairo_array_t pages;
cairo_array_t rgb_linear_functions;
cairo_array_t alpha_linear_functions;
- cairo_array_t knockout_group;
- cairo_array_t content_group;
cairo_array_t patterns;
cairo_array_t smask_groups;
@@ -121,6 +119,12 @@ struct _cairo_pdf_surface {
cairo_bool_t compress_content;
+ cairo_pdf_resource_t content;
+ cairo_pdf_resource_t fallback_content;
+ cairo_pdf_resource_t content_resources;
+ cairo_pdf_group_resources_t resources;
+ cairo_bool_t has_fallback_images;
+
struct {
cairo_bool_t active;
cairo_pdf_resource_t self;
@@ -136,21 +140,9 @@ struct _cairo_pdf_surface {
cairo_output_stream_t *mem_stream;
cairo_output_stream_t *old_output;
cairo_pdf_resource_t resource;
- cairo_pdf_group_resources_t resources;
cairo_bool_t is_knockout;
- cairo_pdf_resource_t first_object;
} group_stream;
- struct {
- cairo_bool_t active;
- cairo_output_stream_t *stream;
- cairo_output_stream_t *mem_stream;
- cairo_output_stream_t *old_output;
- cairo_pdf_group_resources_t resources;
- } content_stream;
-
- cairo_array_t *current_group;
- cairo_pdf_group_resources_t *current_resources;
cairo_pdf_operators_t pdf_operators;
cairo_paginated_mode_t paginated_mode;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 0722cc5..dae9e94 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -131,7 +131,7 @@
*
* PDF Stream:
* A PDF Stream may be opened and closed with the following functions:
- * _cairo_pdf_surface_open_stream ()
+ * _cairo_pdf_surface_open stream ()
* _cairo_pdf_surface_close_stream ()
*
* PDF Streams are written directly to the PDF file. They are used for
@@ -177,11 +177,6 @@
* that need to be in a separate group from the Content Stream.
*/
-/* The group stream length is checked after each operation. When this
- * limit is exceeded the group is written out to the pdf stream and a
- * new group is created. */
-#define GROUP_STREAM_LIMIT 65536
-
typedef struct _cairo_pdf_object {
long offset;
} cairo_pdf_object_t;
@@ -204,17 +199,6 @@ typedef struct _cairo_pdf_alpha_linear_function {
double alpha2;
} cairo_pdf_alpha_linear_function_t;
-typedef enum group_element_type {
- ELEM_GROUP,
- ELEM_CLIP
-} group_element_type_t;
-
-typedef struct _cairo_pdf_group_element {
- group_element_type_t type;
- cairo_pdf_resource_t group;
-} cairo_pdf_group_element_t;
-
-
static cairo_pdf_resource_t
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
@@ -325,13 +309,10 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
_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));
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
- _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_group_element_t));
- _cairo_array_init (&surface->content_group, sizeof (cairo_pdf_group_element_t));
_cairo_array_init (&surface->patterns, sizeof (cairo_pdf_pattern_t));
_cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
- _cairo_pdf_group_resources_init (&surface->group_stream.resources);
- _cairo_pdf_group_resources_init (&surface->content_stream.resources);
+ _cairo_pdf_group_resources_init (&surface->resources);
surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
if (! surface->font_subsets) {
@@ -347,16 +328,10 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
surface->compress_content = TRUE;
surface->pdf_stream.active = FALSE;
surface->pdf_stream.old_output = NULL;
- surface->content_stream.active = FALSE;
- surface->content_stream.stream = NULL;
- surface->content_stream.mem_stream = NULL;
surface->group_stream.active = FALSE;
surface->group_stream.stream = NULL;
surface->group_stream.mem_stream = NULL;
- surface->current_group = NULL;
- surface->current_resources = NULL;
-
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
surface->force_fallbacks = FALSE;
@@ -552,11 +527,6 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
cairo_pdf_pattern_t *pattern;
cairo_pdf_smask_group_t *group;
- _cairo_array_truncate (&surface->content_group, 0);
- _cairo_array_truncate (&surface->knockout_group, 0);
- _cairo_array_truncate (&surface->content_group, 0);
- _cairo_array_truncate (&surface->knockout_group, 0);
-
size = _cairo_array_num_elements (&surface->patterns);
for (i = 0; i < size; i++) {
pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->patterns, i);
@@ -610,7 +580,7 @@ _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
int num_alphas, i;
double other;
cairo_status_t status;
- cairo_pdf_group_resources_t *res = surface->current_resources;
+ cairo_pdf_group_resources_t *res = &surface->resources;
num_alphas = _cairo_array_num_elements (&res->alphas);
for (i = 0; i < num_alphas; i++) {
@@ -634,21 +604,21 @@ static cairo_status_t
_cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t smask)
{
- return _cairo_array_append (&surface->current_resources->smasks, &smask);
+ return _cairo_array_append (&(surface->resources.smasks), &smask);
}
static cairo_status_t
_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t pattern)
{
- return _cairo_array_append (&surface->current_resources->patterns, &pattern);
+ return _cairo_array_append (&(surface->resources.patterns), &pattern);
}
static cairo_status_t
_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t xobject)
{
- return _cairo_array_append (&surface->current_resources->xobjects, &xobject);
+ return _cairo_array_append (&(surface->resources.xobjects), &xobject);
}
static cairo_status_t
@@ -660,7 +630,7 @@ _cairo_pdf_surface_add_font (unsigned int font_id,
cairo_pdf_font_t font;
int num_fonts, i;
cairo_status_t status;
- cairo_pdf_group_resources_t *res = surface->current_resources;
+ cairo_pdf_group_resources_t *res = &surface->resources;
num_fonts = _cairo_array_num_elements (&res->fonts);
for (i = 0; i < num_fonts; i++) {
@@ -720,36 +690,36 @@ _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t *smask, *pattern, *xobject;
cairo_pdf_font_t *font;
- _cairo_output_stream_printf (surface->output, " /Resources <<\r\n");
+ _cairo_output_stream_printf (surface->output, "<<\r\n");
num_alphas = _cairo_array_num_elements (&res->alphas);
num_smasks = _cairo_array_num_elements (&res->smasks);
if (num_alphas > 0 || num_smasks > 0) {
_cairo_output_stream_printf (surface->output,
- " /ExtGState <<\r\n");
+ " /ExtGState <<\r\n");
for (i = 0; i < num_alphas; i++) {
_cairo_array_copy_element (&res->alphas, i, &alpha);
_cairo_output_stream_printf (surface->output,
- " /a%d << /CA %f /ca %f >>\r\n",
+ " /a%d << /CA %f /ca %f >>\r\n",
i, alpha, alpha);
}
for (i = 0; i < num_smasks; i++) {
smask = _cairo_array_index (&res->smasks, i);
_cairo_output_stream_printf (surface->output,
- " /s%d %d 0 R\r\n",
+ " /s%d %d 0 R\r\n",
smask->id, smask->id);
}
_cairo_output_stream_printf (surface->output,
- " >>\r\n");
+ " >>\r\n");
}
num_resources = _cairo_array_num_elements (&res->patterns);
if (num_resources > 0) {
_cairo_output_stream_printf (surface->output,
- " /Pattern <<");
+ " /Pattern <<");
for (i = 0; i < num_resources; i++) {
pattern = _cairo_array_index (&res->patterns, i);
_cairo_output_stream_printf (surface->output,
@@ -764,7 +734,7 @@ _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
num_resources = _cairo_array_num_elements (&res->xobjects);
if (num_resources > 0) {
_cairo_output_stream_printf (surface->output,
- " /XObject <<");
+ " /XObject <<");
for (i = 0; i < num_resources; i++) {
xobject = _cairo_array_index (&res->xobjects, i);
@@ -779,20 +749,20 @@ _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
num_resources = _cairo_array_num_elements (&res->fonts);
if (num_resources > 0) {
- _cairo_output_stream_printf (surface->output," /Font <<\r\n");
+ _cairo_output_stream_printf (surface->output," /Font <<\r\n");
for (i = 0; i < num_resources; i++) {
font = _cairo_array_index (&res->fonts, i);
_cairo_output_stream_printf (surface->output,
- " /f-%d-%d %d 0 R\r\n",
+ " /f-%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");
+ ">>\r\n");
}
static cairo_pdf_smask_group_t *
@@ -1024,11 +994,12 @@ _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
surface->height);
if (is_knockout_group)
- _cairo_output_stream_printf (surface->output,
- " /K true\r\n");
+ _cairo_output_stream_printf (surface->output,
+ " /K true\r\n");
_cairo_output_stream_printf (surface->output,
- " >>\r\n");
+ " >>\r\n"
+ " /Resources\r\n");
_cairo_pdf_surface_emit_group_resources (surface, resources);
_cairo_output_stream_printf (surface->output,
">>\r\n"
@@ -1046,7 +1017,6 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
cairo_status_t status;
assert (surface->pdf_stream.active == FALSE);
- assert (surface->content_stream.active == FALSE);
assert (surface->group_stream.active == FALSE);
surface->group_stream.active = TRUE;
@@ -1064,9 +1034,7 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
surface->group_stream.old_output = surface->output;
surface->output = surface->group_stream.stream;
_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
- _cairo_pdf_group_resources_clear (&surface->group_stream.resources);
- surface->current_resources = &surface->group_stream.resources;
- surface->group_stream.is_knockout = FALSE;
+ _cairo_pdf_group_resources_clear (&surface->resources);
if (resource) {
surface->group_stream.resource = *resource;
@@ -1075,13 +1043,13 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
if (surface->group_stream.resource.id == 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
+ surface->group_stream.is_knockout = FALSE;
return status;
}
static cairo_status_t
-_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
- cairo_pdf_resource_t *first_object)
+_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface)
{
cairo_status_t status;
@@ -1090,7 +1058,6 @@ _cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
return status;
surface->group_stream.is_knockout = TRUE;
- surface->group_stream.first_object = *first_object;
return CAIRO_STATUS_SUCCESS;
}
@@ -1119,7 +1086,7 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
_cairo_pdf_surface_write_memory_stream (surface,
surface->group_stream.mem_stream,
surface->group_stream.resource,
- &surface->group_stream.resources,
+ &surface->resources,
surface->group_stream.is_knockout);
if (group)
*group = surface->group_stream.resource;
@@ -1132,148 +1099,69 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
}
static cairo_status_t
-_cairo_pdf_surface_write_group_list (cairo_pdf_surface_t *surface,
- cairo_array_t *group_list)
-{
- int i, len;
- cairo_pdf_group_element_t *elem;
- cairo_status_t status;
-
- _cairo_output_stream_printf (surface->output, "q\r\n");
- if (surface->group_stream.is_knockout) {
- _cairo_output_stream_printf (surface->output,
- "/x%d Do\r\n",
- surface->group_stream.first_object.id);
- status = _cairo_pdf_surface_add_xobject (surface, surface->group_stream.first_object);
- if (status)
- return status;
- }
- len = _cairo_array_num_elements (group_list);
- for (i = 0; i < len; i++) {
- elem = _cairo_array_index (group_list, i);
- if (elem->type == ELEM_GROUP) {
- _cairo_output_stream_printf (surface->output,
- "/x%d Do\r\n",
- elem->group.id);
- status = _cairo_pdf_surface_add_xobject (surface, elem->group);
- if (status)
- return status;
- }
- }
- _cairo_output_stream_printf (surface->output, "Q\r\n");
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_surface_start_content_stream (cairo_pdf_surface_t *surface)
+_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
+ cairo_pdf_resource_t *resource,
+ cairo_bool_t is_form)
{
- cairo_status_t status;
-
- if (surface->content_stream.active)
- return CAIRO_STATUS_SUCCESS;
-
assert (surface->pdf_stream.active == FALSE);
- assert (surface->content_stream.active == FALSE);
assert (surface->group_stream.active == FALSE);
- surface->content_stream.active = TRUE;
- surface->content_stream.mem_stream = _cairo_memory_stream_create ();
+ surface->content_resources = _cairo_pdf_surface_new_object (surface);
+ if (surface->content_resources.id == 0)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- if (surface->compress_content) {
- surface->content_stream.stream =
- _cairo_deflate_stream_create (surface->content_stream.mem_stream);
+ if (is_form) {
+ *resource =
+ _cairo_pdf_surface_open_stream (surface,
+ NULL,
+ surface->compress_content,
+ " /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"
+ " /Resources %d 0 R\r\n",
+ surface->width,
+ surface->height,
+ surface->content_resources.id);
} else {
- surface->content_stream.stream = surface->content_stream.mem_stream;
+ surface->content =
+ _cairo_pdf_surface_open_stream (surface,
+ NULL,
+ surface->compress_content,
+ NULL);
}
- status = _cairo_output_stream_get_status (surface->content_stream.stream);
-
- surface->content_stream.old_output = surface->output;
- surface->output = surface->content_stream.stream;
- _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
- _cairo_pdf_group_resources_clear (&surface->content_stream.resources);
- surface->current_resources = &surface->content_stream.resources;
+ if (surface->content.id == 0)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_output_stream_printf (surface->output, "q\r\n");
- return status;
-}
-
-static cairo_status_t
-_cairo_pdf_surface_add_group_to_content_stream (cairo_pdf_surface_t *surface,
- cairo_pdf_resource_t group)
-{
- cairo_pdf_group_element_t elem;
-
- memset (&elem, 0, sizeof elem);
- elem.type = ELEM_GROUP;
- elem.group = group;
-
- return _cairo_array_append (surface->current_group, &elem);
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-_cairo_pdf_surface_stop_content_stream (cairo_pdf_surface_t *surface)
+_cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
{
- cairo_pdf_resource_t group;
cairo_status_t status;
- assert (surface->pdf_stream.active == FALSE);
- assert (surface->content_stream.active == TRUE);
+ assert (surface->pdf_stream.active == TRUE);
+ assert (surface->group_stream.active == FALSE);
_cairo_output_stream_printf (surface->output, "Q\r\n");
+ status = _cairo_pdf_surface_close_stream (surface);
+ if (status)
+ return status;
- if (surface->compress_content) {
- status = _cairo_output_stream_destroy (surface->content_stream.stream);
- surface->content_stream.stream = NULL;
- if (status)
- return status;
-
- _cairo_output_stream_printf (surface->content_stream.mem_stream,
- "\r\n");
- }
- surface->output = surface->content_stream.old_output;
- _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
- surface->content_stream.active = FALSE;
- if (_cairo_memory_stream_length (surface->content_stream.mem_stream) > 0) {
- group = _cairo_pdf_surface_new_object (surface);
- if (group.id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _cairo_pdf_surface_write_memory_stream (surface,
- surface->content_stream.mem_stream,
- group,
- &surface->content_stream.resources,
- FALSE);
- status = _cairo_pdf_surface_add_group_to_content_stream (surface, group);
- if (status)
- return status;
- }
-
- status = _cairo_output_stream_destroy (surface->content_stream.mem_stream);
- surface->content_stream.mem_stream = NULL;
- surface->content_stream.stream = NULL;
-
- return status;
-}
-
-static cairo_status_t
-_cairo_pdf_surface_check_content_stream_size (cairo_pdf_surface_t *surface)
-{
- cairo_status_t status;
-
- if (surface->content_stream.active == FALSE)
- return CAIRO_STATUS_SUCCESS;
-
- if (_cairo_memory_stream_length (surface->content_stream.mem_stream) > GROUP_STREAM_LIMIT) {
- status = _cairo_pdf_surface_stop_content_stream (surface);
- if (status)
- return status;
-
- status = _cairo_pdf_surface_start_content_stream (surface);
- if (status)
- return status;
- }
+ _cairo_pdf_surface_update_object (surface, surface->content_resources);
+ _cairo_output_stream_printf (surface->output,
+ "%d 0 obj\r\n",
+ surface->content_resources.id);
+ _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
+ _cairo_output_stream_printf (surface->output,
+ "endobj\r\n");
return CAIRO_STATUS_SUCCESS;
}
@@ -1332,16 +1220,6 @@ _cairo_pdf_surface_finish (void *abstract_surface)
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
- if (surface->content_stream.stream != NULL) {
- status2 = _cairo_output_stream_destroy (surface->content_stream.stream);
- if (status == CAIRO_STATUS_SUCCESS)
- status = status2;
- }
- if (surface->content_stream.mem_stream != NULL) {
- status2 = _cairo_output_stream_destroy (surface->content_stream.mem_stream);
- if (status == CAIRO_STATUS_SUCCESS)
- status = status2;
- }
if (surface->group_stream.stream != NULL) {
status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
if (status == CAIRO_STATUS_SUCCESS)
@@ -1352,8 +1230,8 @@ _cairo_pdf_surface_finish (void *abstract_surface)
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
}
- if (surface->content_stream.active)
- surface->output = surface->content_stream.old_output;
+ if (surface->pdf_stream.active)
+ surface->output = surface->pdf_stream.old_output;
if (surface->group_stream.active)
surface->output = surface->group_stream.old_output;
@@ -1363,15 +1241,12 @@ _cairo_pdf_surface_finish (void *abstract_surface)
status = status2;
_cairo_pdf_surface_clear (surface);
- _cairo_pdf_group_resources_fini (&surface->group_stream.resources);
- _cairo_pdf_group_resources_fini (&surface->content_stream.resources);
+ _cairo_pdf_group_resources_fini (&surface->resources);
_cairo_array_fini (&surface->objects);
_cairo_array_fini (&surface->pages);
_cairo_array_fini (&surface->rgb_linear_functions);
_cairo_array_fini (&surface->alpha_linear_functions);
- _cairo_array_fini (&surface->knockout_group);
- _cairo_array_fini (&surface->content_group);
_cairo_array_fini (&surface->patterns);
_cairo_array_fini (&surface->smask_groups);
_cairo_array_fini (&surface->fonts);
@@ -1390,12 +1265,12 @@ _cairo_pdf_surface_start_page (void *abstract_surface)
cairo_status_t status;
cairo_pdf_surface_t *surface = abstract_surface;
- surface->current_group = &surface->content_group;
- status = _cairo_pdf_surface_start_content_stream (surface);
+ surface->has_fallback_images = FALSE;
+ _cairo_pdf_group_resources_clear (&surface->resources);
+ status = _cairo_pdf_surface_open_content_stream (surface, &surface->content, TRUE);
if (status)
return status;
-
return CAIRO_STATUS_SUCCESS;
}
@@ -1718,8 +1593,6 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
cairo_surface_t *meta_surface,
cairo_pdf_resource_t *resource)
{
- cairo_array_t group;
- cairo_array_t *old_group;
double old_width, old_height;
cairo_matrix_t old_cairo_to_pdf;
cairo_rectangle_int16_t meta_extents;
@@ -1730,22 +1603,21 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
if (status)
return status;
- _cairo_array_init (&group, sizeof (cairo_pdf_group_element_t));
- old_group = surface->current_group;
old_width = surface->width;
old_height = surface->height;
old_cairo_to_pdf = surface->cairo_to_pdf;
- surface->current_group = &group;
surface->width = meta_extents.width;
surface->height = meta_extents.height;
cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
surface->cairo_to_pdf);
- status = _cairo_pdf_surface_start_content_stream (surface);
+ _cairo_pdf_group_resources_clear (&surface->resources);
+ status = _cairo_pdf_surface_open_content_stream (surface, &surface->content, TRUE);
if (status)
- goto CLEANUP_GROUP;
+ return status;
+ *resource = surface->content;
if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
if (status)
@@ -1764,35 +1636,16 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
if (status)
goto CLEANUP_GROUP;
- status = _cairo_pdf_surface_stop_content_stream (surface);
- if (status)
- goto CLEANUP_GROUP;
-
- status = _cairo_pdf_surface_open_group (surface, NULL);
- if (status)
- goto CLEANUP_GROUP;
-
- status = _cairo_pdf_surface_write_group_list (surface, &group);
- if (status)
- goto CLEANUP_GROUP;
-
- status = _cairo_pdf_surface_close_group (surface, resource);
- if (status)
- goto CLEANUP_GROUP;
+ status = _cairo_pdf_surface_close_content_stream (surface);
CLEANUP_GROUP:
- surface->current_group = old_group;
surface->width = old_width;
surface->height = old_height;
surface->cairo_to_pdf = old_cairo_to_pdf;
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
surface->cairo_to_pdf);
- _cairo_array_fini (&group);
- if (status)
- return status;
-
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
static cairo_status_t
@@ -2828,7 +2681,7 @@ _cairo_pdf_surface_copy_page (void *abstract_surface)
cairo_pdf_surface_t *surface = abstract_surface;
cairo_int_status_t status;
- status = _cairo_pdf_surface_stop_content_stream (surface);
+ status = _cairo_pdf_surface_close_content_stream (surface);
if (status)
return status;
@@ -2841,7 +2694,7 @@ _cairo_pdf_surface_show_page (void *abstract_surface)
cairo_pdf_surface_t *surface = abstract_surface;
cairo_int_status_t status;
- status = _cairo_pdf_surface_stop_content_stream (surface);
+ status = _cairo_pdf_surface_close_content_stream (surface);
if (status)
return status;
@@ -4144,63 +3997,35 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface
static cairo_status_t
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
{
+ cairo_pdf_resource_t page, knockout;
cairo_status_t status;
- cairo_pdf_resource_t page;
- cairo_pdf_resource_t content_group, knockout_group, page_content;
- cairo_bool_t has_fallback_images = FALSE;
-
- if (_cairo_array_num_elements (&surface->knockout_group) > 0)
- has_fallback_images = TRUE;
- status = _cairo_pdf_surface_open_group (surface, NULL);
- if (status)
- return status;
-
- status = _cairo_pdf_surface_write_group_list (surface, &surface->content_group);
- if (status)
- return status;
-
- status = _cairo_pdf_surface_close_group (surface, &content_group);
- if (status)
- return status;
-
- if (has_fallback_images) {
- status = _cairo_pdf_surface_open_knockout_group (surface, &content_group);
+ _cairo_pdf_group_resources_clear (&surface->resources);
+ if (surface->has_fallback_images) {
+ status = _cairo_pdf_surface_open_knockout_group (surface);
if (status)
return status;
- status = _cairo_pdf_surface_write_group_list (surface, &surface->knockout_group);
+ _cairo_output_stream_printf (surface->output,
+ "/x%d Do\r\n"
+ "/x%d Do\r\n",
+ surface->content.id,
+ surface->fallback_content.id);
+ _cairo_pdf_surface_add_xobject (surface, surface->content);
+ _cairo_pdf_surface_add_xobject (surface, surface->fallback_content);
+ status = _cairo_pdf_surface_close_group (surface, &knockout);
if (status)
return status;
- status = _cairo_pdf_surface_close_group (surface, &knockout_group);
- if (status)
- return status;
+ _cairo_pdf_group_resources_clear (&surface->resources);
+ status = _cairo_pdf_surface_open_content_stream (surface, &surface->content, FALSE);
+ _cairo_output_stream_printf (surface->output,
+ "/x%d Do\r\n",
+ knockout.id);
+ _cairo_pdf_surface_add_xobject (surface, knockout);
+ _cairo_pdf_surface_close_content_stream (surface);
}
- page_content = _cairo_pdf_surface_open_stream (surface,
- NULL,
- FALSE,
- " /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);
- if (page_content.id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _cairo_output_stream_printf (surface->output,
- "/x%d Do\r\n",
- has_fallback_images ? knockout_group.id : content_group.id);
- status = _cairo_pdf_surface_close_stream (surface);
- if (status)
- return status;
-
page = _cairo_pdf_surface_new_object (surface);
if (page.id == 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -4210,24 +4035,21 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
"<< /Type /Page\r\n"
" /Parent %d 0 R\r\n"
" /MediaBox [ 0 0 %f %f ]\r\n"
- " /Contents [ %d 0 R ]\r\n"
+ " /Contents %d 0 R\r\n"
" /Group <<\r\n"
" /Type /Group\r\n"
" /S /Transparency\r\n"
" /CS /DeviceRGB\r\n"
" >>\r\n"
- " /Resources <<\r\n"
- " /XObject << /x%d %d 0 R >>\r\n"
- " >>\r\n"
+ " /Resources %d 0 R\r\n"
">>\r\n"
"endobj\r\n",
page.id,
surface->pages_resource.id,
surface->width,
surface->height,
- page_content.id,
- has_fallback_images ? knockout_group.id : content_group.id,
- has_fallback_images ? knockout_group.id : content_group.id);
+ surface->content.id,
+ surface->content_resources.id);
status = _cairo_array_append (&surface->pages, &page);
if (status)
@@ -4373,16 +4195,15 @@ _cairo_pdf_surface_set_operator (cairo_pdf_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
if (op == CAIRO_OPERATOR_SOURCE) {
- surface->current_group = &surface->knockout_group;
- status = _cairo_pdf_surface_stop_content_stream (surface);
+ status = _cairo_pdf_surface_close_content_stream (surface);
if (status)
return status;
- status = _cairo_pdf_surface_start_content_stream (surface);
- if (status)
- return status;
-
- return CAIRO_STATUS_SUCCESS;
+ surface->has_fallback_images = TRUE;
+ _cairo_pdf_group_resources_clear (&surface->resources);
+ return _cairo_pdf_surface_open_content_stream (surface,
+ &surface->fallback_content,
+ TRUE);
}
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -4446,11 +4267,7 @@ _cairo_pdf_surface_paint (void *abstract_surface,
_cairo_pdf_surface_unselect_pattern (surface);
}
- status = _cairo_output_stream_get_status (surface->output);
- if (status)
- return status;
-
- return _cairo_pdf_surface_check_content_stream_size (surface);
+ return _cairo_output_stream_get_status (surface->output);
}
static cairo_int_status_t
@@ -4580,11 +4397,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
_cairo_pdf_surface_unselect_pattern (surface);
}
- status = _cairo_output_stream_get_status (surface->output);
- if (status)
- return status;
-
- return _cairo_pdf_surface_check_content_stream_size (surface);
+ return _cairo_output_stream_get_status (surface->output);
}
static cairo_int_status_t
@@ -4656,11 +4469,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
_cairo_pdf_surface_unselect_pattern (surface);
}
- status = _cairo_output_stream_get_status (surface->output);
- if (status)
- return status;
-
- return _cairo_pdf_surface_check_content_stream_size (surface);
+ return _cairo_output_stream_get_status (surface->output);
}
static cairo_int_status_t
@@ -4726,11 +4535,7 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
_cairo_pdf_surface_unselect_pattern (surface);
}
- status = _cairo_output_stream_get_status (surface->output);
- if (status)
- return status;
-
- return _cairo_pdf_surface_check_content_stream_size (surface);
+ return _cairo_output_stream_get_status (surface->output);
}
static void
commit 099810b6c39cc6b5529f740282b64185cf56c8d7
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 20:59:22 2008 +1030
PDF: Perform all clipping in the content stream
Previously this was done in a separate group. Now that the PDF backend
has been re-organized to not interrupt the content stream the clipping
can be done in the same stream.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index b51b787..0722cc5 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -212,8 +212,6 @@ typedef enum group_element_type {
typedef struct _cairo_pdf_group_element {
group_element_type_t type;
cairo_pdf_resource_t group;
- cairo_path_fixed_t *clip_path;
- cairo_fill_rule_t fill_rule;
} cairo_pdf_group_element_t;
@@ -221,9 +219,6 @@ static cairo_pdf_resource_t
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
static void
-_cairo_pdf_group_element_array_finish (cairo_array_t *array);
-
-static void
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
static void
@@ -262,11 +257,6 @@ static long
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
static cairo_status_t
-_cairo_pdf_surface_emit_clip (cairo_pdf_surface_t *surface,
- cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule);
-
-static cairo_status_t
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
static cairo_status_t
@@ -562,8 +552,8 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
cairo_pdf_pattern_t *pattern;
cairo_pdf_smask_group_t *group;
- _cairo_pdf_group_element_array_finish (&surface->content_group);
- _cairo_pdf_group_element_array_finish (&surface->knockout_group);
+ _cairo_array_truncate (&surface->content_group, 0);
+ _cairo_array_truncate (&surface->knockout_group, 0);
_cairo_array_truncate (&surface->content_group, 0);
_cairo_array_truncate (&surface->knockout_group, 0);
@@ -1168,10 +1158,6 @@ _cairo_pdf_surface_write_group_list (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_add_xobject (surface, elem->group);
if (status)
return status;
- } else if (elem->type == ELEM_CLIP) {
- status = _cairo_pdf_surface_emit_clip (surface, elem->clip_path, elem->fill_rule);
- if (status)
- return status;
}
}
_cairo_output_stream_printf (surface->output, "Q\r\n");
@@ -1208,6 +1194,8 @@ _cairo_pdf_surface_start_content_stream (cairo_pdf_surface_t *surface)
_cairo_pdf_group_resources_clear (&surface->content_stream.resources);
surface->current_resources = &surface->content_stream.resources;
+ _cairo_output_stream_printf (surface->output, "q\r\n");
+
return status;
}
@@ -1233,6 +1221,8 @@ _cairo_pdf_surface_stop_content_stream (cairo_pdf_surface_t *surface)
assert (surface->pdf_stream.active == FALSE);
assert (surface->content_stream.active == TRUE);
+ _cairo_output_stream_printf (surface->output, "Q\r\n");
+
if (surface->compress_content) {
status = _cairo_output_stream_destroy (surface->content_stream.stream);
surface->content_stream.stream = NULL;
@@ -1288,20 +1278,6 @@ _cairo_pdf_surface_check_content_stream_size (cairo_pdf_surface_t *surface)
return CAIRO_STATUS_SUCCESS;
}
-static void
-_cairo_pdf_group_element_array_finish (cairo_array_t *array)
-{
- int i, len;
- cairo_pdf_group_element_t *elem;
-
- len = _cairo_array_num_elements (array);
- for (i = 0; i < len; i++) {
- elem = _cairo_array_index (array, i);
- if (elem->type == ELEM_CLIP && elem->clip_path)
- _cairo_path_fixed_destroy (elem->clip_path);
- }
-}
-
static cairo_surface_t *
_cairo_pdf_surface_create_similar (void *abstract_surface,
cairo_content_t content,
@@ -1812,7 +1788,6 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
surface->cairo_to_pdf);
- _cairo_pdf_group_element_array_finish (&group);
_cairo_array_fini (&group);
if (status)
return status;
@@ -2898,53 +2873,6 @@ _cairo_pdf_surface_get_extents (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
-_cairo_pdf_surface_add_clip (cairo_pdf_surface_t *surface,
- cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule)
-{
- cairo_pdf_group_element_t elem;
- cairo_status_t status;
-
- memset (&elem, 0, sizeof elem);
- elem.type = ELEM_CLIP;
-
- if (path == NULL) {
- elem.clip_path = NULL;
- } else {
- elem.clip_path = _cairo_path_fixed_create ();
- if (elem.clip_path == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- status = _cairo_path_fixed_init_copy (elem.clip_path, path);
- if (status) {
- _cairo_path_fixed_destroy (elem.clip_path);
- return status;
- }
- }
- elem.fill_rule = fill_rule;
-
- status = _cairo_pdf_surface_stop_content_stream (surface);
- if (status) {
- if (elem.clip_path != NULL)
- _cairo_path_fixed_destroy (elem.clip_path);
- return status;
- }
-
- status = _cairo_array_append (surface->current_group, &elem);
- if (status) {
- if (elem.clip_path != NULL)
- _cairo_path_fixed_destroy (elem.clip_path);
- return status;
- }
-
- status = _cairo_pdf_surface_start_content_stream (surface);
- if (status)
- return status;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
static cairo_int_status_t
_cairo_pdf_surface_intersect_clip_path (void *abstract_surface,
cairo_path_fixed_t *path,
@@ -2954,7 +2882,12 @@ _cairo_pdf_surface_intersect_clip_path (void *abstract_surface,
{
cairo_pdf_surface_t *surface = abstract_surface;
- return _cairo_pdf_surface_add_clip (surface, path, fill_rule);
+ if (path == NULL) {
+ _cairo_output_stream_printf (surface->output, "Q q\r\n");
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
}
static void
@@ -3979,19 +3912,6 @@ _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
}
static cairo_status_t
-_cairo_pdf_surface_emit_clip (cairo_pdf_surface_t *surface,
- cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule)
-{
- if (path == NULL) {
- _cairo_output_stream_printf (surface->output, "Q q\r\n");
- return CAIRO_STATUS_SUCCESS;
- }
-
- return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
-}
-
-static cairo_status_t
_cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
cairo_pdf_smask_group_t *group)
{
commit 83630b1c70b24035b333ccfbbda8b67bd5fdd32e
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 20:55:56 2008 +1030
PDF: Emit all patterns after content stream
To fix this performance issue
http://lists.cairographics.org/archives/cairo/2007-December/012197.html
the PDF surface needs to avoid starting and stopping the content
stream every time it emits a pattern. This patch makes the PDF surface
store a list of all patterns used while the content stream is written
out then write out all the patterns after the content stream is
closed.
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index d4318d6..7012155 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -1,8 +1,9 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Red Hat, Inc
* Copyright © 2006 Red Hat, Inc
- * Copyright © 2007 Adrian Johnson
+ * Copyright © 2007, 2008 Adrian Johnson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -45,6 +46,7 @@
#include "cairo-surface-private.h"
#include "cairo-pdf-operators-private.h"
+#include "cairo-path-fixed-private.h"
typedef struct _cairo_pdf_resource {
unsigned int id;
@@ -58,6 +60,37 @@ typedef struct _cairo_pdf_group_resources {
cairo_array_t fonts;
} cairo_pdf_group_resources_t;
+typedef struct _cairo_pdf_pattern {
+ cairo_pattern_t *pattern;
+ cairo_pdf_resource_t pattern_res;
+ cairo_pdf_resource_t gstate_res;
+} cairo_pdf_pattern_t;
+
+typedef enum _cairo_pdf_operation {
+ PDF_PAINT,
+ PDF_MASK,
+ PDF_FILL,
+ PDF_STROKE,
+ PDF_SHOW_GLYPHS
+} cairo_pdf_operation_t;
+
+typedef struct _cairo_pdf_smask_group
+{
+ cairo_pdf_resource_t group_res;
+ cairo_pdf_operation_t operation;
+ cairo_pattern_t *source;
+ cairo_pdf_resource_t source_res;
+ cairo_pattern_t *mask;
+ cairo_path_fixed_t path;
+ cairo_fill_rule_t fill_rule;
+ cairo_stroke_style_t *style;
+ cairo_matrix_t ctm;
+ cairo_matrix_t ctm_inverse;
+ cairo_glyph_t *glyphs;
+ int num_glyphs;
+ cairo_scaled_font_t *scaled_font;
+} cairo_pdf_smask_group_t;
+
typedef struct _cairo_pdf_surface cairo_pdf_surface_t;
struct _cairo_pdf_surface {
@@ -77,6 +110,8 @@ struct _cairo_pdf_surface {
cairo_array_t alpha_linear_functions;
cairo_array_t knockout_group;
cairo_array_t content_group;
+ cairo_array_t patterns;
+ cairo_array_t smask_groups;
cairo_scaled_font_subsets_t *font_subsets;
cairo_array_t fonts;
@@ -100,6 +135,7 @@ struct _cairo_pdf_surface {
cairo_output_stream_t *stream;
cairo_output_stream_t *mem_stream;
cairo_output_stream_t *old_output;
+ cairo_pdf_resource_t resource;
cairo_pdf_group_resources_t resources;
cairo_bool_t is_knockout;
cairo_pdf_resource_t first_object;
@@ -113,16 +149,6 @@ struct _cairo_pdf_surface {
cairo_pdf_group_resources_t resources;
} content_stream;
- struct {
- cairo_pattern_type_t type;
- double red;
- double green;
- double blue;
- double alpha;
- cairo_pdf_resource_t smask;
- cairo_pdf_resource_t pattern;
- } emitted_pattern;
-
cairo_array_t *current_group;
cairo_pdf_group_resources_t *current_resources;
cairo_pdf_operators_t pdf_operators;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 2e5cd2b..b51b787 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1,8 +1,9 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Red Hat, Inc
* Copyright © 2006 Red Hat, Inc
- * Copyright © 2007 Adrian Johnson
+ * Copyright © 2007, 2008 Adrian Johnson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -225,6 +226,9 @@ _cairo_pdf_group_element_array_finish (cairo_array_t *array);
static void
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
+static void
+_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
+
static cairo_status_t
_cairo_pdf_surface_add_font (unsigned int font_id,
unsigned int subset_id,
@@ -235,9 +239,10 @@ _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
static cairo_pdf_resource_t
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
+ cairo_pdf_resource_t *resource,
cairo_bool_t compressed,
const char *fmt,
- ...) CAIRO_PRINTF_FORMAT(3, 4);
+ ...) CAIRO_PRINTF_FORMAT(4, 5);
static cairo_status_t
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
@@ -321,7 +326,6 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
CAIRO_CONTENT_COLOR_ALPHA);
surface->output = output;
-
surface->width = width;
surface->height = height;
cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
@@ -333,6 +337,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
_cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_group_element_t));
_cairo_array_init (&surface->content_group, sizeof (cairo_pdf_group_element_t));
+ _cairo_array_init (&surface->patterns, sizeof (cairo_pdf_pattern_t));
+ _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
_cairo_pdf_group_resources_init (&surface->group_stream.resources);
_cairo_pdf_group_resources_init (&surface->content_stream.resources);
@@ -552,10 +558,28 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface,
static void
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
{
+ int i, size;
+ cairo_pdf_pattern_t *pattern;
+ cairo_pdf_smask_group_t *group;
+
_cairo_pdf_group_element_array_finish (&surface->content_group);
_cairo_pdf_group_element_array_finish (&surface->knockout_group);
_cairo_array_truncate (&surface->content_group, 0);
_cairo_array_truncate (&surface->knockout_group, 0);
+
+ size = _cairo_array_num_elements (&surface->patterns);
+ for (i = 0; i < size; i++) {
+ pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->patterns, i);
+ cairo_pattern_destroy (pattern->pattern);
+ }
+ _cairo_array_truncate (&surface->patterns, 0);
+
+ size = _cairo_array_num_elements (&surface->smask_groups);
+ for (i = 0; i < size; i++) {
+ _cairo_array_copy_element (&surface->smask_groups, i, &group);
+ _cairo_pdf_smask_group_destroy (group);
+ }
+ _cairo_array_truncate (&surface->smask_groups, 0);
}
static void
@@ -781,8 +805,100 @@ _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
" >>\r\n");
}
+static cairo_pdf_smask_group_t *
+_cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t *surface)
+{
+ cairo_pdf_smask_group_t *group;
+
+ group = calloc (1, sizeof (cairo_pdf_smask_group_t));
+ if (group == NULL) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return NULL;
+ }
+
+ group->group_res = _cairo_pdf_surface_new_object (surface);
+ if (group->group_res.id == 0) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ free (group);
+ return NULL;
+ }
+
+ return group;
+}
+
+static void
+_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
+{
+ if (group->operation == PDF_FILL || group->operation == PDF_STROKE)
+ _cairo_path_fixed_fini (&group->path);
+ if (group->source)
+ cairo_pattern_destroy (group->source);
+ if (group->mask)
+ cairo_pattern_destroy (group->mask);
+ if (group->scaled_font)
+ cairo_scaled_font_destroy (group->scaled_font);
+ free (group);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface,
+ cairo_pdf_smask_group_t *group)
+{
+ return _cairo_array_append (&surface->smask_groups, &group);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
+ cairo_pattern_t *pattern,
+ cairo_pdf_resource_t *pattern_res,
+ cairo_pdf_resource_t *gstate_res)
+{
+ cairo_pdf_pattern_t pdf_pattern;
+
+ /* Solid colors are emitted into the content stream */
+ if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
+ pattern_res->id = 0;
+ gstate_res->id = 0;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ /* Gradients with zero stops do not produce any output */
+ if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
+ pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
+ {
+ cairo_gradient_pattern_t *gradient;
+
+ gradient = (cairo_gradient_pattern_t *) pattern;
+ if (gradient->n_stops == 0)
+ return CAIRO_INT_STATUS_NOTHING_TO_DO;
+ }
+
+ pdf_pattern.pattern = cairo_pattern_reference (pattern);
+ pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
+ if (pdf_pattern.pattern_res.id == 0)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ pdf_pattern.gstate_res.id = 0;
+
+ /* gradient patterns require an smask object to implement transparency */
+ if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
+ pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
+ if (_cairo_pattern_is_opaque (pattern) == FALSE) {
+ pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
+ if (pdf_pattern.gstate_res.id == 0)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+ }
+
+ *pattern_res = pdf_pattern.pattern_res;
+ *gstate_res = pdf_pattern.gstate_res;
+
+ return _cairo_array_append (&surface->patterns, &pdf_pattern);
+}
+
static cairo_pdf_resource_t
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
+ cairo_pdf_resource_t *resource,
cairo_bool_t compressed,
const char *fmt,
...)
@@ -791,9 +907,14 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t self, length;
cairo_output_stream_t *output = NULL;
- self = _cairo_pdf_surface_new_object (surface);
- if (self.id == 0)
- return self;
+ if (resource) {
+ self = *resource;
+ _cairo_pdf_surface_update_object (surface, self);
+ } else {
+ self = _cairo_pdf_surface_new_object (surface);
+ if (self.id == 0)
+ return self;
+ }
length = _cairo_pdf_surface_new_object (surface);
if (length.id == 0)
@@ -881,23 +1002,20 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
return status;
}
-static cairo_pdf_resource_t
+static void
_cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
cairo_output_stream_t *mem_stream,
+ cairo_pdf_resource_t resource,
cairo_pdf_group_resources_t *resources,
cairo_bool_t is_knockout_group)
{
- cairo_pdf_resource_t group;
-
- group = _cairo_pdf_surface_new_object (surface);
- if (group.id == 0)
- return group;
+ _cairo_pdf_surface_update_object (surface, resource);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Type /XObject\r\n"
" /Length %d\r\n",
- group.id,
+ resource.id,
_cairo_memory_stream_length (mem_stream));
if (surface->compress_content) {
@@ -929,12 +1047,11 @@ _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
_cairo_output_stream_printf (surface->output,
"endstream\r\n"
"endobj\r\n");
-
- return group;
}
static cairo_status_t
-_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface)
+_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
+ cairo_pdf_resource_t *resource)
{
cairo_status_t status;
@@ -961,6 +1078,14 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface)
surface->current_resources = &surface->group_stream.resources;
surface->group_stream.is_knockout = FALSE;
+ if (resource) {
+ surface->group_stream.resource = *resource;
+ } else {
+ surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
+ if (surface->group_stream.resource.id == 0)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
return status;
}
@@ -970,7 +1095,7 @@ _cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
{
cairo_status_t status;
- status = _cairo_pdf_surface_open_group (surface);
+ status = _cairo_pdf_surface_open_group (surface, NULL);
if (status)
return status;
@@ -1001,15 +1126,17 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
surface->output = surface->group_stream.old_output;
_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
surface->group_stream.active = FALSE;
- *group = _cairo_pdf_surface_write_memory_stream (surface,
- surface->group_stream.mem_stream,
- &surface->group_stream.resources,
- surface->group_stream.is_knockout);
- if (group->id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_pdf_surface_write_memory_stream (surface,
+ surface->group_stream.mem_stream,
+ surface->group_stream.resource,
+ &surface->group_stream.resources,
+ surface->group_stream.is_knockout);
+ if (group)
+ *group = surface->group_stream.resource;
status = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
surface->group_stream.mem_stream = NULL;
+ surface->group_stream.stream = NULL;
return status;
}
@@ -1097,33 +1224,6 @@ _cairo_pdf_surface_add_group_to_content_stream (cairo_pdf_surface_t *surface,
return _cairo_array_append (surface->current_group, &elem);
}
-static void
-_cairo_pdf_surface_pause_content_stream (cairo_pdf_surface_t *surface)
-{
- assert (surface->pdf_stream.active == FALSE);
-
- if (surface->content_stream.active == FALSE)
- return;
-
- surface->output = surface->content_stream.old_output;
- _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
- surface->content_stream.active = FALSE;
-}
-
-static void
-_cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface)
-{
- assert (surface->pdf_stream.active == FALSE);
-
- if (surface->content_stream.active == TRUE)
- return;
-
- surface->output = surface->content_stream.stream;
- _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
- surface->current_resources = &surface->content_stream.resources;
- surface->content_stream.active = TRUE;
-}
-
static cairo_status_t
_cairo_pdf_surface_stop_content_stream (cairo_pdf_surface_t *surface)
{
@@ -1146,13 +1246,15 @@ _cairo_pdf_surface_stop_content_stream (cairo_pdf_surface_t *surface)
_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
surface->content_stream.active = FALSE;
if (_cairo_memory_stream_length (surface->content_stream.mem_stream) > 0) {
- group = _cairo_pdf_surface_write_memory_stream (surface,
- surface->content_stream.mem_stream,
- &surface->content_stream.resources,
- FALSE);
+ group = _cairo_pdf_surface_new_object (surface);
if (group.id == 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_pdf_surface_write_memory_stream (surface,
+ surface->content_stream.mem_stream,
+ group,
+ &surface->content_stream.resources,
+ FALSE);
status = _cairo_pdf_surface_add_group_to_content_stream (surface, group);
if (status)
return status;
@@ -1160,6 +1262,7 @@ _cairo_pdf_surface_stop_content_stream (cairo_pdf_surface_t *surface)
status = _cairo_output_stream_destroy (surface->content_stream.mem_stream);
surface->content_stream.mem_stream = NULL;
+ surface->content_stream.stream = NULL;
return status;
}
@@ -1283,20 +1386,19 @@ _cairo_pdf_surface_finish (void *abstract_surface)
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
+ _cairo_pdf_surface_clear (surface);
+ _cairo_pdf_group_resources_fini (&surface->group_stream.resources);
+ _cairo_pdf_group_resources_fini (&surface->content_stream.resources);
+
_cairo_array_fini (&surface->objects);
_cairo_array_fini (&surface->pages);
_cairo_array_fini (&surface->rgb_linear_functions);
_cairo_array_fini (&surface->alpha_linear_functions);
- _cairo_array_fini (&surface->fonts);
-
- _cairo_pdf_group_resources_fini (&surface->group_stream.resources);
- _cairo_pdf_group_resources_fini (&surface->content_stream.resources);
-
- _cairo_pdf_group_element_array_finish (&surface->knockout_group);
_cairo_array_fini (&surface->knockout_group);
-
- _cairo_pdf_group_element_array_finish (&surface->content_group);
_cairo_array_fini (&surface->content_group);
+ _cairo_array_fini (&surface->patterns);
+ _cairo_array_fini (&surface->smask_groups);
+ _cairo_array_fini (&surface->fonts);
if (surface->font_subsets) {
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
@@ -1438,6 +1540,7 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
}
*stream_ret = _cairo_pdf_surface_open_stream (surface,
+ NULL,
FALSE,
" /Type /XObject\r\n"
" /Subtype /Image\r\n"
@@ -1564,6 +1667,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
if (need_smask)
*image_ret = _cairo_pdf_surface_open_stream (surface,
+ NULL,
FALSE,
IMAGE_DICTIONARY
" /SMask %d 0 R\r\n",
@@ -1571,6 +1675,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
smask.id);
else
*image_ret = _cairo_pdf_surface_open_stream (surface,
+ NULL,
FALSE,
IMAGE_DICTIONARY,
image->width, image->height);
@@ -1649,11 +1754,6 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
if (status)
return status;
- _cairo_pdf_surface_resume_content_stream (surface);
- status = _cairo_pdf_surface_stop_content_stream (surface);
- if (status)
- return status;
-
_cairo_array_init (&group, sizeof (cairo_pdf_group_element_t));
old_group = surface->current_group;
old_width = surface->width;
@@ -1692,7 +1792,7 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
if (status)
goto CLEANUP_GROUP;
- status = _cairo_pdf_surface_open_group (surface);
+ status = _cairo_pdf_surface_open_group (surface, NULL);
if (status)
goto CLEANUP_GROUP;
@@ -1717,33 +1817,14 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
if (status)
return status;
- status = _cairo_pdf_surface_start_content_stream (surface);
- if (status)
- return status;
-
- _cairo_pdf_surface_pause_content_stream (surface);
-
return CAIRO_STATUS_SUCCESS;
}
-static void
-_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface,
- cairo_solid_pattern_t *pattern)
-{
- 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 = pattern->color.alpha;
- surface->emitted_pattern.smask.id = 0;
- surface->emitted_pattern.pattern.id = 0;
-}
-
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_pdf_pattern_t *pdf_pattern)
{
- cairo_pdf_resource_t stream;
+ cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_pdf_resource_t pattern_resource = {0}; /* squelch bogus compiler warning */
cairo_matrix_t cairo_p2d, pdf_p2d;
@@ -1754,8 +1835,6 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
int pattern_height = 0; /* squelch bogus compiler warning */
int bbox_x, bbox_y;
- _cairo_pdf_surface_pause_content_stream (surface);
-
if (_cairo_surface_is_meta (pattern->surface)) {
cairo_surface_t *meta_surface = pattern->surface;
cairo_rectangle_int16_t pattern_extents;
@@ -1876,25 +1955,25 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
- stream = _cairo_pdf_surface_open_stream (surface,
- FALSE,
- " /BBox [0 0 %d %d]\r\n"
- " /XStep %f\r\n"
- " /YStep %f\r\n"
- " /PatternType 1\r\n"
- " /TilingType 1\r\n"
- " /PaintType 1\r\n"
- " /Matrix [ %f %f %f %f %f %f ]\r\n"
- " /Resources << /XObject << /x%d %d 0 R >> >>\r\n",
- bbox_x, bbox_y,
- xstep, ystep,
- pdf_p2d.xx, pdf_p2d.yx,
- pdf_p2d.xy, pdf_p2d.yy,
- pdf_p2d.x0, pdf_p2d.y0,
- pattern_resource.id,
- pattern_resource.id);
- if (stream.id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
+ _cairo_pdf_surface_open_stream (surface,
+ &pdf_pattern->pattern_res,
+ FALSE,
+ " /PatternType 1\r\n"
+ " /BBox [0 0 %d %d]\r\n"
+ " /XStep %f\r\n"
+ " /YStep %f\r\n"
+ " /TilingType 1\r\n"
+ " /PaintType 1\r\n"
+ " /Matrix [ %f %f %f %f %f %f ]\r\n"
+ " /Resources << /XObject << /x%d %d 0 R >> >>\r\n",
+ bbox_x, bbox_y,
+ xstep, ystep,
+ pdf_p2d.xx, pdf_p2d.yx,
+ pdf_p2d.xy, pdf_p2d.yy,
+ pdf_p2d.x0, pdf_p2d.y0,
+ pattern_resource.id,
+ pattern_resource.id);
if (_cairo_surface_is_meta (pattern->surface)) {
if (extend == CAIRO_EXTEND_REFLECT) {
@@ -1927,13 +2006,6 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
if (status)
return status;
- _cairo_pdf_surface_resume_content_stream (surface);
-
- surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SURFACE;
- surface->emitted_pattern.smask.id = 0;
- surface->emitted_pattern.pattern = stream;
- surface->emitted_pattern.alpha = 1.0;
-
return CAIRO_STATUS_SUCCESS;
}
@@ -2298,13 +2370,16 @@ _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_pdf_resource_t
+static cairo_status_t
cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
- cairo_pdf_resource_t gradient_mask)
+ cairo_pdf_resource_t gstate_resource,
+ cairo_pdf_resource_t gradient_mask)
{
- cairo_pdf_resource_t xobj_resource, smask_resource, gstate_resource;
+ cairo_pdf_resource_t xobj_resource, smask_resource;
+ cairo_status_t status;
xobj_resource = _cairo_pdf_surface_open_stream (surface,
+ NULL,
surface->compress_content,
" /Type /XObject\r\n"
" /Subtype /Form\r\n"
@@ -2327,7 +2402,7 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
gradient_mask.id,
gradient_mask.id);
if (xobj_resource.id == 0)
- return xobj_resource;
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_output_stream_printf (surface->output,
"q\r\n"
@@ -2340,14 +2415,13 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
surface->width,
surface->height);
- if (_cairo_pdf_surface_close_stream (surface)) {
- smask_resource.id = 0;
- return smask_resource;
- }
+ status = _cairo_pdf_surface_close_stream (surface);
+ if (status)
+ return status;
smask_resource = _cairo_pdf_surface_new_object (surface);
if (smask_resource.id == 0)
- return smask_resource;
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
@@ -2360,9 +2434,7 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
xobj_resource.id);
/* Create GState which uses the transparency group as an SMask. */
- gstate_resource = _cairo_pdf_surface_new_object (surface);
- if (gstate_resource.id == 0)
- return gstate_resource;
+ _cairo_pdf_surface_update_object (surface, gstate_resource);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
@@ -2376,14 +2448,14 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
gstate_resource.id,
smask_resource.id);
- return gstate_resource;
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
- cairo_linear_pattern_t *pattern)
+ cairo_pdf_pattern_t *pdf_pattern)
{
- cairo_pdf_resource_t pattern_resource, smask;
+ cairo_linear_pattern_t *pattern = (cairo_linear_pattern_t *) pdf_pattern->pattern;
cairo_pdf_resource_t color_function, alpha_function;
double x1, y1, x2, y2;
double _x1, _y1, _x2, _y2;
@@ -2394,11 +2466,9 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
double first_stop, last_stop;
int repeat_begin = 0, repeat_end = 1;
- if (pattern->base.n_stops == 0)
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
+ assert (pattern->base.n_stops != 0);
- extend = cairo_pattern_get_extend (&pattern->base.base);
- _cairo_pdf_surface_pause_content_stream (surface);
+ extend = cairo_pattern_get_extend (pdf_pattern->pattern);
pat_to_pdf = pattern->base.base.matrix;
status = cairo_matrix_invert (&pat_to_pdf);
@@ -2493,10 +2563,7 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
}
}
- pattern_resource = _cairo_pdf_surface_new_object (surface);
- if (pattern_resource.id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
+ _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Type /Pattern\r\n"
@@ -2508,7 +2575,7 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
" /Coords [ %f %f %f %f ]\r\n"
" /Domain [ %f %f ]\r\n"
" /Function %d 0 R\r\n",
- pattern_resource.id,
+ pdf_pattern->pattern_res.id,
pat_to_pdf.xx, pat_to_pdf.yx,
pat_to_pdf.xy, pat_to_pdf.yy,
pat_to_pdf.x0, pat_to_pdf.y0,
@@ -2529,10 +2596,10 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
">>\r\n"
"endobj\r\n");
- if (alpha_function.id == 0) {
- surface->emitted_pattern.smask.id = 0;
- } else {
- cairo_pdf_resource_t mask_resource;
+ if (alpha_function.id != 0) {
+ cairo_pdf_resource_t mask_resource;
+
+ assert (pdf_pattern->gstate_res.id != 0);
/* Create pattern for SMask. */
mask_resource = _cairo_pdf_surface_new_object (surface);
@@ -2574,38 +2641,27 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
if (status)
return status;
- smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
- if (smask.id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- surface->emitted_pattern.smask = smask;
+ cairo_pdf_surface_emit_transparency_group (surface,
+ pdf_pattern->gstate_res,
+ mask_resource);
}
-
- surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_LINEAR;
- surface->emitted_pattern.pattern = pattern_resource;
- surface->emitted_pattern.alpha = 1.0;
-
- _cairo_pdf_surface_resume_content_stream (surface);
-
return status;
}
static cairo_status_t
_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface,
- cairo_radial_pattern_t *pattern)
+ cairo_pdf_pattern_t *pdf_pattern)
{
- cairo_pdf_resource_t pattern_resource, smask;
cairo_pdf_resource_t color_function, alpha_function;
double x1, y1, x2, y2, r1, r2;
cairo_matrix_t pat_to_pdf;
cairo_extend_t extend;
cairo_status_t status;
+ cairo_radial_pattern_t *pattern = (cairo_radial_pattern_t *) pdf_pattern->pattern;
- if (pattern->base.n_stops == 0)
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
+ assert (pattern->base.n_stops != 0);
- extend = cairo_pattern_get_extend (&pattern->base.base);
- _cairo_pdf_surface_pause_content_stream (surface);
+ extend = cairo_pattern_get_extend (pdf_pattern->pattern);
status = _cairo_pdf_surface_emit_pattern_stops (surface,
&pattern->base,
@@ -2627,9 +2683,7 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface,
y2 = _cairo_fixed_to_double (pattern->c2.y);
r2 = _cairo_fixed_to_double (pattern->r2);
- pattern_resource = _cairo_pdf_surface_new_object (surface);
- if (pattern_resource.id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
@@ -2641,7 +2695,7 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface,
" /ColorSpace /DeviceRGB\r\n"
" /Coords [ %f %f %f %f %f %f ]\r\n"
" /Function %d 0 R\r\n",
- pattern_resource.id,
+ pdf_pattern->pattern_res.id,
pat_to_pdf.xx, pat_to_pdf.yx,
pat_to_pdf.xy, pat_to_pdf.yy,
pat_to_pdf.x0, pat_to_pdf.y0,
@@ -2661,12 +2715,12 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface,
">>\r\n"
"endobj\r\n");
- if (alpha_function.id == 0) {
- surface->emitted_pattern.smask.id = 0;
- } else {
- cairo_pdf_resource_t mask_resource;
+ if (alpha_function.id != 0) {
+ cairo_pdf_resource_t mask_resource;
- /* Create pattern for SMask. */
+ assert (pdf_pattern->gstate_res.id != 0);
+
+ /* Create pattern for SMask. */
mask_resource = _cairo_pdf_surface_new_object (surface);
if (mask_resource.id == 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -2701,38 +2755,30 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface,
">>\r\n"
"endobj\r\n");
- smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
- if (smask.id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- surface->emitted_pattern.smask = smask;
+ cairo_pdf_surface_emit_transparency_group (surface,
+ pdf_pattern->gstate_res,
+ mask_resource);
}
- surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_RADIAL;
- surface->emitted_pattern.pattern = pattern_resource;
- surface->emitted_pattern.alpha = 1.0;
-
- _cairo_pdf_surface_resume_content_stream (surface);
-
- return status;
+ return status;
}
static cairo_status_t
-_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
+_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
{
- switch (pattern->type) {
+ switch (pdf_pattern->pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
- _cairo_pdf_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
- return CAIRO_STATUS_SUCCESS;
+ ASSERT_NOT_REACHED;
+ break;
case CAIRO_PATTERN_TYPE_SURFACE:
- return _cairo_pdf_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
+ return _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
case CAIRO_PATTERN_TYPE_LINEAR:
- return _cairo_pdf_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
+ return _cairo_pdf_surface_emit_linear_pattern (surface, pdf_pattern);
case CAIRO_PATTERN_TYPE_RADIAL:
- return _cairo_pdf_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
+ return _cairo_pdf_surface_emit_radial_pattern (surface, pdf_pattern);
}
ASSERT_NOT_REACHED;
@@ -2741,23 +2787,27 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *
static cairo_status_t
_cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
- cairo_bool_t is_stroke)
+ cairo_pattern_t *pattern,
+ cairo_pdf_resource_t pattern_res,
+ cairo_bool_t is_stroke)
{
cairo_status_t status;
int alpha;
- status = _cairo_pdf_surface_add_alpha (surface, surface->emitted_pattern.alpha, &alpha);
- if (status)
- return status;
+ if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
+ cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *) pattern;
+
+ status = _cairo_pdf_surface_add_alpha (surface, solid_pattern->color.alpha, &alpha);
+ if (status)
+ return status;
- 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);
+ "q %f %f %f ",
+ solid_pattern->color.red,
+ solid_pattern->color.green,
+ solid_pattern->color.blue);
- if (is_stroke)
+ if (is_stroke)
_cairo_output_stream_printf (surface->output, "RG ");
else
_cairo_output_stream_printf (surface->output, "rg ");
@@ -2766,29 +2816,37 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
"/a%d gs\r\n",
alpha);
} else {
- if (is_stroke) {
- _cairo_output_stream_printf (surface->output,
- "/Pattern CS /p%d SCN ",
- surface->emitted_pattern.pattern.id);
- } else {
- _cairo_output_stream_printf (surface->output,
- "/Pattern cs /p%d scn ",
- surface->emitted_pattern.pattern.id);
- }
- status = _cairo_pdf_surface_add_pattern (surface, surface->emitted_pattern.pattern);
+ status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
if (status)
return status;
- _cairo_output_stream_printf (surface->output,
- "/a%d gs ",
- alpha);
+ status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
+ if (status)
+ return status;
- _cairo_output_stream_printf (surface->output, "\r\n");
+ if (is_stroke) {
+ _cairo_output_stream_printf (surface->output,
+ "q /Pattern CS /p%d SCN ",
+ pattern_res.id);
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ "q /Pattern cs /p%d scn ",
+ pattern_res.id);
+ }
+ _cairo_output_stream_printf (surface->output,
+ "/a%d gs\r\n",
+ alpha);
}
return _cairo_output_stream_get_status (surface->output);
}
+static void
+_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
+{
+ _cairo_output_stream_printf (surface->output, "Q\r\n");
+}
+
static cairo_int_status_t
_cairo_pdf_surface_copy_page (void *abstract_surface)
{
@@ -2992,8 +3050,9 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
}
*stream = _cairo_pdf_surface_open_stream (surface,
- surface->compress_content,
- NULL);
+ NULL,
+ surface->compress_content,
+ NULL);
if (stream->id == 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -3588,6 +3647,7 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
}
*glyph_ret = _cairo_pdf_surface_open_stream (surface,
+ NULL,
surface->compress_content,
NULL);
if (glyph_ret->id == 0) {
@@ -3932,6 +3992,236 @@ _cairo_pdf_surface_emit_clip (cairo_pdf_surface_t *surface,
}
static cairo_status_t
+_cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
+ cairo_pdf_smask_group_t *group)
+{
+ cairo_pdf_resource_t mask_group;
+ cairo_pdf_resource_t smask;
+ cairo_pdf_smask_group_t *smask_group;
+ cairo_pdf_resource_t pattern_res, gstate_res;
+ cairo_status_t status;
+
+ /* Create mask group */
+ status = _cairo_pdf_surface_open_group (surface, NULL);
+ if (status)
+ return status;
+
+ pattern_res.id = 0;
+ gstate_res.id = 0;
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, &pattern_res, &gstate_res);
+ if (status)
+ return status;
+
+ if (gstate_res.id != 0) {
+ smask_group = _cairo_pdf_surface_create_smask_group (surface);
+ if (smask_group == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ smask_group->operation = PDF_PAINT;
+ smask_group->source = cairo_pattern_reference (group->mask);
+ smask_group->source_res = pattern_res;
+ status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
+ if (status)
+ return status;
+
+ status = _cairo_pdf_surface_add_smask (surface, gstate_res);
+ status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
+
+ _cairo_output_stream_printf (surface->output,
+ "q /s%d gs /x%d Do Q\r\n",
+ gstate_res.id,
+ smask_group->group_res.id);
+ } else {
+ status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
+ if (status)
+ return status;
+
+ _cairo_output_stream_printf (surface->output,
+ "0 0 %f %f re f\r\n",
+ surface->width, surface->height);
+
+ _cairo_pdf_surface_unselect_pattern (surface);
+ }
+
+ status = _cairo_pdf_surface_close_group (surface, &mask_group);
+ if (status)
+ return status;
+
+ /* Create source group */
+ status = _cairo_pdf_surface_open_group (surface, &group->source_res);
+ if (status)
+ return status;
+
+ pattern_res.id = 0;
+ gstate_res.id = 0;
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, &pattern_res, &gstate_res);
+ if (status)
+ return status;
+
+ if (gstate_res.id != 0) {
+ smask_group = _cairo_pdf_surface_create_smask_group (surface);
+ if (smask_group == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ smask_group->operation = PDF_PAINT;
+ smask_group->source = cairo_pattern_reference (group->source);
+ smask_group->source_res = pattern_res;
+ status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
+ if (status)
+ return status;
+
+ status = _cairo_pdf_surface_add_smask (surface, gstate_res);
+ status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
+
+ _cairo_output_stream_printf (surface->output,
+ "q /s%d gs /x%d Do Q\r\n",
+ gstate_res.id,
+ smask_group->group_res.id);
+ } else {
+ status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
+ if (status)
+ return status;
+
+ _cairo_output_stream_printf (surface->output,
+ "0 0 %f %f re f\r\n",
+ surface->width, surface->height);
+
+ _cairo_pdf_surface_unselect_pattern (surface);
+ }
+
+ status = _cairo_pdf_surface_close_group (surface, NULL);
+ if (status)
+ return status;
+
+ /* Create an smask based on the alpha component of mask_group */
+ smask = _cairo_pdf_surface_new_object (surface);
+ if (smask.id == 0)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ _cairo_output_stream_printf (surface->output,
+ "%d 0 obj\r\n"
+ "<< /Type /Mask\r\n"
+ " /S /Alpha\r\n"
+ " /G %d 0 R\r\n"
+ ">>\r\n"
+ "endobj\r\n",
+ smask.id,
+ mask_group.id);
+
+ /* Create a GState that uses the smask */
+ _cairo_pdf_surface_update_object (surface, group->group_res);
+ _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",
+ group->group_res.id,
+ smask.id);
+
+ return _cairo_output_stream_get_status (surface->output);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
+ cairo_pdf_smask_group_t *group)
+{
+ cairo_status_t status;
+
+ /* _mask is a special case that requires two groups - source
+ * and mask as well as a smask and gstate dictionary */
+ if (group->operation == PDF_MASK)
+ return _cairo_pdf_surface_write_mask_group (surface, group);
+
+ status = _cairo_pdf_surface_open_group (surface, &group->group_res);
+ if (status)
+ return status;
+
+ status = _cairo_pdf_surface_select_pattern (surface,
+ group->source,
+ group->source_res,
+ group->operation == PDF_STROKE);
+ if (status)
+ return status;
+
+ switch (group->operation) {
+ case PDF_PAINT:
+ _cairo_output_stream_printf (surface->output,
+ "0 0 %f %f re f\r\n",
+ surface->width, surface->height);
+ break;
+ case PDF_MASK:
+ ASSERT_NOT_REACHED;
+ break;
+ case PDF_FILL:
+ status = _cairo_pdf_operators_fill (&surface->pdf_operators,
+ &group->path,
+ group->fill_rule);
+ break;
+ case PDF_STROKE:
+ status = _cairo_pdf_operator_stroke (&surface->pdf_operators,
+ &group->path,
+ group->style,
+ &group->ctm,
+ &group->ctm_inverse);
+ break;
+ case PDF_SHOW_GLYPHS:
+ status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
+ group->glyphs,
+ group->num_glyphs,
+ group->scaled_font);
+ break;
+ }
+ if (status)
+ return status;
+
+ _cairo_pdf_surface_unselect_pattern (surface);
+
+ return _cairo_pdf_surface_close_group (surface, NULL);
+}
+
+static cairo_status_t
+_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
+{
+ cairo_pdf_pattern_t pattern;
+ cairo_pdf_smask_group_t *group;
+ int pattern_index, group_index;
+ cairo_status_t status;
+
+ /* Writing out PDF_MASK groups will cause additional smask groups
+ * to be appended to surface->smask_groups. Additional patterns
+ * may also be appended to surface->patterns.
+ *
+ * Writing meta surface patterns will cause additional patterns
+ * and groups to be appended.
+ */
+ pattern_index = 0;
+ group_index = 0;
+ while ((pattern_index < _cairo_array_num_elements (&surface->patterns)) ||
+ (group_index < _cairo_array_num_elements (&surface->smask_groups)))
+ {
+ for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
+ _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
+ status = _cairo_pdf_surface_write_smask_group (surface, group);
+ if (status)
+ return status;
+ }
+
+ for (; pattern_index < _cairo_array_num_elements (&surface->patterns); pattern_index++) {
+ _cairo_array_copy_element (&surface->patterns, pattern_index, &pattern);
+ status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
+ if (status)
+ return status;
+ }
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
{
cairo_status_t status;
@@ -3942,7 +4232,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
if (_cairo_array_num_elements (&surface->knockout_group) > 0)
has_fallback_images = TRUE;
- status = _cairo_pdf_surface_open_group (surface);
+ status = _cairo_pdf_surface_open_group (surface, NULL);
if (status)
return status;
@@ -3969,6 +4259,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
}
page_content = _cairo_pdf_surface_open_stream (surface,
+ NULL,
FALSE,
" /Type /XObject\r\n"
" /Subtype /Form\r\n"
@@ -4022,6 +4313,8 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
if (status)
return status;
+ _cairo_pdf_surface_write_patterns_and_smask_groups (surface);
+
return CAIRO_STATUS_SUCCESS;
}
@@ -4181,60 +4474,56 @@ _cairo_pdf_surface_paint (void *abstract_surface,
cairo_pattern_t *source)
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
cairo_status_t status;
+ cairo_pdf_smask_group_t *group;
+ cairo_pdf_resource_t pattern_res, gstate_res;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
- status = _cairo_pdf_surface_emit_pattern (surface, source);
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
-
- if (status)
- return status;
-
status = _cairo_pdf_surface_set_operator (surface, op);
if (status)
return status;
- if (surface->emitted_pattern.smask.id != 0) {
- _cairo_pdf_surface_pause_content_stream (surface);
- status = _cairo_pdf_surface_open_group (surface);
- if (status)
- return status;
- } else {
- _cairo_output_stream_printf (surface->output, "q ");
- }
-
- status = _cairo_pdf_surface_select_pattern (surface, FALSE);
+ pattern_res.id = 0;
+ gstate_res.id = 0;
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+ return CAIRO_STATUS_SUCCESS;
if (status)
return status;
- _cairo_output_stream_printf (surface->output,
- "0 0 %f %f re f\r\n",
- surface->width, surface->height);
+ if (gstate_res.id != 0) {
+ group = _cairo_pdf_surface_create_smask_group (surface);
+ if (group == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
- if (surface->emitted_pattern.smask.id != 0) {
- status = _cairo_pdf_surface_close_group (surface, &smask_group);
+ group->operation = PDF_PAINT;
+ group->source = cairo_pattern_reference (source);
+ group->source_res = pattern_res;
+ status = _cairo_pdf_surface_add_smask_group (surface, group);
if (status)
return status;
- _cairo_pdf_surface_resume_content_stream (surface);
+ status = _cairo_pdf_surface_add_smask (surface, gstate_res);
+ status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
+
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\r\n",
- surface->emitted_pattern.smask,
- smask_group.id);
- status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
- if (status)
- return status;
- status = _cairo_pdf_surface_add_xobject (surface, smask_group);
+ gstate_res.id,
+ group->group_res.id);
+ } else {
+ status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
if (status)
return status;
- } else {
- _cairo_output_stream_printf (surface->output, "Q\r\n");
+
+ _cairo_output_stream_printf (surface->output,
+ "0 0 %f %f re f\r\n",
+ surface->width, surface->height);
+
+ _cairo_pdf_surface_unselect_pattern (surface);
}
status = _cairo_output_stream_get_status (surface->output);
@@ -4251,11 +4540,7 @@ _cairo_pdf_surface_mask (void *abstract_surface,
cairo_pattern_t *mask)
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_pdf_resource_t mask_group;
- cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
- cairo_pdf_resource_t source_group;
- cairo_pdf_resource_t smask;
- cairo_pdf_resource_t gstate;
+ cairo_pdf_smask_group_t *group;
cairo_status_t status, status2;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
@@ -4278,149 +4563,32 @@ _cairo_pdf_surface_mask (void *abstract_surface,
if (status)
return status;
- /* Create mask group */
- status = _cairo_pdf_surface_emit_pattern (surface, mask);
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
+ group = _cairo_pdf_surface_create_smask_group (surface);
+ if (group == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
- if (status)
- return status;
-
- _cairo_pdf_surface_pause_content_stream (surface);
-
- status = _cairo_pdf_surface_open_group (surface);
- if (status)
- return status;
-
- status = _cairo_pdf_surface_select_pattern (surface, FALSE);
- if (status)
- return status;
-
- _cairo_output_stream_printf (surface->output,
- "0 0 %f %f re f\r\n",
- surface->width, surface->height);
- status = _cairo_pdf_surface_close_group (surface, &mask_group);
- if (status)
- return status;
-
- if (surface->emitted_pattern.smask.id != 0) {
- group = mask_group;
- status = _cairo_pdf_surface_open_group (surface);
- if (status)
- return status;
-
- _cairo_output_stream_printf (surface->output,
- "/s%d gs /x%d Do\r\n",
- surface->emitted_pattern.smask,
- group.id);
- status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
- if (status)
- return status;
- status = _cairo_pdf_surface_add_xobject (surface, group);
- if (status)
- return status;
-
- status = _cairo_pdf_surface_close_group (surface, &mask_group);
- if (status)
- return status;
- }
-
- /* Create source group */
- status = _cairo_pdf_surface_emit_pattern (surface, source);
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
-
- if (status)
- return status;
-
- _cairo_pdf_surface_pause_content_stream (surface);
-
- status = _cairo_pdf_surface_open_group (surface);
- if (status)
- return status;
-
- status = _cairo_pdf_surface_select_pattern (surface, FALSE);
- if (status)
- return status;
+ group->operation = PDF_MASK;
+ group->source = cairo_pattern_reference (source);
+ group->mask = cairo_pattern_reference (mask);
+ group->source_res = _cairo_pdf_surface_new_object (surface);
+ if (group->source_res.id == 0)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- _cairo_output_stream_printf (surface->output,
- "0 0 %f %f re f\r\n",
- surface->width, surface->height);
- status = _cairo_pdf_surface_close_group (surface, &source_group);
+ status = _cairo_pdf_surface_add_smask_group (surface, group);
if (status)
return status;
- if (surface->emitted_pattern.smask.id != 0) {
- group = source_group;
- status = _cairo_pdf_surface_open_group (surface);
- if (status)
- return status;
-
- _cairo_output_stream_printf (surface->output,
- "/s%d gs /x%d Do\r\n",
- surface->emitted_pattern.smask,
- group.id);
- status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
- if (status)
- return status;
- status = _cairo_pdf_surface_add_xobject (surface, group);
- if (status)
- return status;
-
- status =_cairo_pdf_surface_close_group (surface, &source_group);
- if (status)
- return status;
- }
-
- /* Create an smask based on the alpha component of mask_group */
- smask = _cairo_pdf_surface_new_object (surface);
- if (smask.id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _cairo_output_stream_printf (surface->output,
- "%d 0 obj\r\n"
- "<< /Type /Mask\r\n"
- " /S /Alpha\r\n"
- " /G %d 0 R\r\n"
- ">>\r\n"
- "endobj\r\n",
- smask.id,
- mask_group.id);
-
- /* Create a GState that uses the smask */
- gstate = _cairo_pdf_surface_new_object (surface);
- if (gstate.id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _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.id,
- smask.id);
+ status = _cairo_pdf_surface_add_smask (surface, group->group_res);
+ status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
- /* Select the GState then draw the source */
- _cairo_pdf_surface_resume_content_stream (surface);
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\r\n",
- gstate.id,
- source_group.id);
- status = _cairo_pdf_surface_add_smask (surface, gstate);
- if (status)
- return status;
- status = _cairo_pdf_surface_add_xobject (surface, source_group);
- if (status)
- return status;
+ group->group_res.id,
+ group->source_res.id);
return _cairo_output_stream_get_status (surface->output);
}
-
static cairo_int_status_t
_cairo_pdf_surface_stroke (void *abstract_surface,
cairo_operator_t op,
@@ -4433,60 +4601,63 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
cairo_antialias_t antialias)
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
cairo_status_t status;
+ cairo_pdf_smask_group_t *group;
+ cairo_pdf_resource_t pattern_res, gstate_res;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
- status = _cairo_pdf_surface_emit_pattern (surface, source);
+ pattern_res.id = 0;
+ gstate_res.id = 0;
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
-
+ return CAIRO_STATUS_SUCCESS;
if (status)
return status;
- if (surface->emitted_pattern.smask.id != 0) {
- _cairo_pdf_surface_pause_content_stream (surface);
- status = _cairo_pdf_surface_open_group (surface);
+ if (gstate_res.id != 0) {
+ group = _cairo_pdf_surface_create_smask_group (surface);
+ if (group == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ group->operation = PDF_STROKE;
+ group->source = cairo_pattern_reference (source);
+ group->source_res = pattern_res;
+ status = _cairo_path_fixed_init_copy (&group->path, path);
if (status)
return status;
- } else {
- _cairo_output_stream_printf (surface->output, "q ");
- }
-
- status = _cairo_pdf_surface_select_pattern (surface, TRUE);
- if (status)
- return status;
-
- status = _cairo_pdf_operator_stroke (&surface->pdf_operators,
- path,
- style,
- ctm,
- ctm_inverse);
- if (status)
- return status;
- if (surface->emitted_pattern.smask.id != 0) {
- status = _cairo_pdf_surface_close_group (surface, &smask_group);
+ group->style = style;
+ group->ctm = *ctm;
+ group->ctm_inverse = *ctm_inverse;
+ status = _cairo_pdf_surface_add_smask_group (surface, group);
if (status)
return status;
- _cairo_pdf_surface_resume_content_stream (surface);
+ status = _cairo_pdf_surface_add_smask (surface, gstate_res);
+ status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
+
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\r\n",
- surface->emitted_pattern.smask,
- smask_group.id);
- status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+ gstate_res.id,
+ group->group_res.id);
+ } else {
+ status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
if (status)
return status;
- status = _cairo_pdf_surface_add_xobject (surface, smask_group);
+
+ status = _cairo_pdf_operator_stroke (&surface->pdf_operators,
+ path,
+ style,
+ ctm,
+ ctm_inverse);
if (status)
return status;
- } else {
- _cairo_output_stream_printf (surface->output, "Q\r\n");
+
+ _cairo_pdf_surface_unselect_pattern (surface);
}
status = _cairo_output_stream_get_status (surface->output);
@@ -4506,8 +4677,9 @@ _cairo_pdf_surface_fill (void *abstract_surface,
cairo_antialias_t antialias)
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
cairo_status_t status;
+ cairo_pdf_smask_group_t *group;
+ cairo_pdf_resource_t pattern_res, gstate_res;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
@@ -4518,48 +4690,50 @@ _cairo_pdf_surface_fill (void *abstract_surface,
if (status)
return status;
- status = _cairo_pdf_surface_emit_pattern (surface, source);
+ pattern_res.id = 0;
+ gstate_res.id = 0;
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
-
+ return CAIRO_STATUS_SUCCESS;
if (status)
return status;
- if (surface->emitted_pattern.smask.id != 0) {
- _cairo_pdf_surface_pause_content_stream (surface);
- status = _cairo_pdf_surface_open_group (surface);
+ if (gstate_res.id != 0) {
+ group = _cairo_pdf_surface_create_smask_group (surface);
+ if (group == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ group->operation = PDF_FILL;
+ group->source = cairo_pattern_reference (source);
+ group->source_res = pattern_res;
+ status = _cairo_path_fixed_init_copy (&group->path, path);
if (status)
return status;
- } else {
- _cairo_output_stream_printf (surface->output, "q ");
- }
- status = _cairo_pdf_surface_select_pattern (surface, FALSE);
- if (status)
- return status;
-
- status = _cairo_pdf_operators_fill (&surface->pdf_operators, path, fill_rule);
- if (status)
- return status;
-
- if (surface->emitted_pattern.smask.id != 0) {
- status = _cairo_pdf_surface_close_group (surface, &smask_group);
+ group->fill_rule = fill_rule;
+ status = _cairo_pdf_surface_add_smask_group (surface, group);
if (status)
return status;
- _cairo_pdf_surface_resume_content_stream (surface);
+ status = _cairo_pdf_surface_add_smask (surface, gstate_res);
+ status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
+
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\r\n",
- surface->emitted_pattern.smask,
- smask_group.id);
- status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+ gstate_res.id,
+ group->group_res.id);
+ } else {
+ status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
if (status)
return status;
- status = _cairo_pdf_surface_add_xobject (surface, smask_group);
+
+ status = _cairo_pdf_operators_fill (&surface->pdf_operators,
+ path,
+ fill_rule);
if (status)
return status;
- } else {
- _cairo_output_stream_printf (surface->output, "Q\r\n");
+
+ _cairo_pdf_surface_unselect_pattern (surface);
}
status = _cairo_output_stream_get_status (surface->output);
@@ -4578,60 +4752,58 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
cairo_scaled_font_t *scaled_font)
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
cairo_status_t status;
+ cairo_pdf_smask_group_t *group;
+ cairo_pdf_resource_t pattern_res, gstate_res;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
- status = _cairo_pdf_surface_emit_pattern (surface, source);
+ pattern_res.id = 0;
+ gstate_res.id = 0;
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
-
- if (status)
- return status;
-
- if (surface->emitted_pattern.smask.id != 0) {
- _cairo_pdf_surface_pause_content_stream (surface);
- status = _cairo_pdf_surface_open_group (surface);
- if (status)
- return status;
- } else {
- _cairo_output_stream_printf (surface->output, "q ");
- }
-
- status = _cairo_pdf_surface_select_pattern (surface, FALSE);
- if (status)
- return status;
-
- status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
- glyphs,
- num_glyphs,
- scaled_font);
+ return CAIRO_STATUS_SUCCESS;
if (status)
return status;
- if (surface->emitted_pattern.smask.id != 0) {
- status = _cairo_pdf_surface_close_group (surface, &smask_group);
+ if (gstate_res.id != 0) {
+ group = _cairo_pdf_surface_create_smask_group (surface);
+ if (group == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ group->operation = PDF_SHOW_GLYPHS;
+ group->source = cairo_pattern_reference (source);
+ group->source_res = pattern_res;
+ group->glyphs = glyphs;
+ group->num_glyphs = num_glyphs;
+ group->scaled_font = cairo_scaled_font_reference (scaled_font);
+ status = _cairo_pdf_surface_add_smask_group (surface, group);
if (status)
return status;
- _cairo_pdf_surface_resume_content_stream (surface);
+ status = _cairo_pdf_surface_add_smask (surface, gstate_res);
+ status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\r\n",
- surface->emitted_pattern.smask,
- smask_group.id);
- status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+ gstate_res.id,
+ group->group_res.id);
+ } else {
+ status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
if (status)
return status;
- status = _cairo_pdf_surface_add_xobject (surface, smask_group);
+
+ status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
+ glyphs,
+ num_glyphs,
+ scaled_font);
if (status)
return status;
- } else {
- _cairo_output_stream_printf (surface->output, "Q\r\n");
+
+ _cairo_pdf_surface_unselect_pattern (surface);
}
status = _cairo_output_stream_get_status (surface->output);
commit b4e0864b960887fd71de85d514cb3e855c276080
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 20:42:15 2008 +1030
Use _cairo_pattern_create_copy() in cairo-surface.c
Use _cairo_pattern_create_copy()/cairo_pattern_destroy() instead of
_cairo_pattern_init_copy()/_cairo_pattern_fini() so the PDF backend
can reference the patterns and destroy them later.
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index e68880a..f6f26c7 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -86,7 +86,7 @@ DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
static cairo_status_t
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
cairo_surface_t *destination,
- cairo_pattern_t *pattern_out);
+ cairo_pattern_t **pattern_out);
/**
* _cairo_surface_set_error:
@@ -1395,24 +1395,24 @@ _cairo_surface_paint (cairo_surface_t *surface,
cairo_pattern_t *source)
{
cairo_status_t status;
- cairo_pattern_union_t dev_source;
+ cairo_pattern_t *dev_source;
assert (! surface->is_snapshot);
- status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+ status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
if (surface->backend->paint) {
- status = surface->backend->paint (surface, op, &dev_source.base);
+ status = surface->backend->paint (surface, op, dev_source);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto FINISH;
}
- status = _cairo_surface_fallback_paint (surface, op, &dev_source.base);
+ status = _cairo_surface_fallback_paint (surface, op, dev_source);
FINISH:
- _cairo_pattern_fini (&dev_source.base);
+ cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@@ -1424,31 +1424,31 @@ _cairo_surface_mask (cairo_surface_t *surface,
cairo_pattern_t *mask)
{
cairo_status_t status;
- cairo_pattern_union_t dev_source;
- cairo_pattern_union_t dev_mask;
+ cairo_pattern_t *dev_source;
+ cairo_pattern_t *dev_mask;
assert (! surface->is_snapshot);
- status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+ status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
goto FINISH;
- status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
+ status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask);
if (status)
goto CLEANUP_SOURCE;
if (surface->backend->mask) {
- status = surface->backend->mask (surface, op, &dev_source.base, &dev_mask.base);
+ status = surface->backend->mask (surface, op, dev_source, dev_mask);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto CLEANUP_MASK;
}
- status = _cairo_surface_fallback_mask (surface, op, &dev_source.base, &dev_mask.base);
+ status = _cairo_surface_fallback_mask (surface, op, dev_source, dev_mask);
CLEANUP_MASK:
- _cairo_pattern_fini (&dev_mask.base);
+ cairo_pattern_destroy (dev_mask);
CLEANUP_SOURCE:
- _cairo_pattern_fini (&dev_source.base);
+ cairo_pattern_destroy (dev_source);
FINISH:
return _cairo_surface_set_error (surface, status);
@@ -1473,29 +1473,29 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
cairo_status_t status;
if (surface->backend->fill_stroke) {
- cairo_pattern_union_t dev_stroke_source;
- cairo_pattern_union_t dev_fill_source;
+ cairo_pattern_t *dev_stroke_source;
+ cairo_pattern_t *dev_fill_source;
cairo_matrix_t dev_ctm = *stroke_ctm;
cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
- status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source.base);
+ status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source);
if (status)
return _cairo_surface_set_error (surface, status);
- status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source.base);
+ status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source);
if (status) {
- _cairo_pattern_fini (&dev_stroke_source.base);
+ cairo_pattern_destroy (dev_stroke_source);
return _cairo_surface_set_error (surface, status);
}
- status = surface->backend->fill_stroke (surface, fill_op, &dev_fill_source.base,
+ status = surface->backend->fill_stroke (surface, fill_op, dev_fill_source,
fill_rule, fill_tolerance, fill_antialias,
- path, stroke_op, &dev_stroke_source.base, stroke_style,
+ path, stroke_op, dev_stroke_source, stroke_style,
&dev_ctm, &dev_ctm_inverse, stroke_tolerance,
stroke_antialias);
- _cairo_pattern_fini (&dev_stroke_source.base);
- _cairo_pattern_fini (&dev_fill_source.base);
+ cairo_pattern_destroy (dev_stroke_source);
+ cairo_pattern_destroy (dev_fill_source);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return _cairo_surface_set_error (surface, status);
@@ -1527,7 +1527,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
cairo_antialias_t antialias)
{
cairo_status_t status;
- cairo_pattern_union_t dev_source;
+ cairo_pattern_t *dev_source;
cairo_path_fixed_t *dev_path = path;
cairo_path_fixed_t real_dev_path;
cairo_matrix_t dev_ctm = *ctm;
@@ -1535,12 +1535,12 @@ _cairo_surface_stroke (cairo_surface_t *surface,
assert (! surface->is_snapshot);
- status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+ status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
if (surface->backend->stroke) {
- status = surface->backend->stroke (surface, op, &dev_source.base,
+ status = surface->backend->stroke (surface, op, dev_source,
path, stroke_style,
&dev_ctm, &dev_ctm_inverse,
tolerance, antialias);
@@ -1549,7 +1549,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
goto FINISH;
}
- status = _cairo_surface_fallback_stroke (surface, op, &dev_source.base,
+ status = _cairo_surface_fallback_stroke (surface, op, dev_source,
path, stroke_style,
&dev_ctm, &dev_ctm_inverse,
tolerance, antialias);
@@ -1557,7 +1557,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
FINISH:
if (dev_path == &real_dev_path)
_cairo_path_fixed_fini (&real_dev_path);
- _cairo_pattern_fini (&dev_source.base);
+ cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@@ -1572,16 +1572,16 @@ _cairo_surface_fill (cairo_surface_t *surface,
cairo_antialias_t antialias)
{
cairo_status_t status;
- cairo_pattern_union_t dev_source;
+ cairo_pattern_t *dev_source;
assert (! surface->is_snapshot);
- status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+ status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
if (surface->backend->fill) {
- status = surface->backend->fill (surface, op, &dev_source.base,
+ status = surface->backend->fill (surface, op, dev_source,
path, fill_rule,
tolerance, antialias);
@@ -1589,12 +1589,12 @@ _cairo_surface_fill (cairo_surface_t *surface,
goto FINISH;
}
- status = _cairo_surface_fallback_fill (surface, op, &dev_source.base,
+ status = _cairo_surface_fallback_fill (surface, op, dev_source,
path, fill_rule,
tolerance, antialias);
FINISH:
- _cairo_pattern_fini (&dev_source.base);
+ cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@@ -2045,7 +2045,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
{
cairo_status_t status;
cairo_scaled_font_t *dev_scaled_font = scaled_font;
- cairo_pattern_union_t dev_source;
+ cairo_pattern_t *dev_source;
cairo_matrix_t font_matrix;
assert (! surface->is_snapshot);
@@ -2055,7 +2055,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
status = _cairo_surface_copy_pattern_for_destination (source,
surface,
- &dev_source.base);
+ &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
@@ -2080,7 +2080,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
}
status = cairo_scaled_font_status (dev_scaled_font);
if (status) {
- _cairo_pattern_fini (&dev_source.base);
+ cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@@ -2089,12 +2089,12 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->backend->show_glyphs)
- status = surface->backend->show_glyphs (surface, op, &dev_source.base,
+ status = surface->backend->show_glyphs (surface, op, dev_source,
glyphs, num_glyphs,
dev_scaled_font);
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base,
+ status = _cairo_surface_fallback_show_glyphs (surface, op, dev_source,
glyphs, num_glyphs,
dev_scaled_font);
@@ -2103,7 +2103,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
if (dev_scaled_font != scaled_font)
cairo_scaled_font_destroy (dev_scaled_font);
- _cairo_pattern_fini (&dev_source.base);
+ cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@@ -2370,11 +2370,11 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
static cairo_status_t
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
cairo_surface_t *destination,
- cairo_pattern_t *pattern_out)
+ cairo_pattern_t **pattern_out)
{
cairo_status_t status;
- status = _cairo_pattern_init_copy (pattern_out, pattern);
+ status = _cairo_pattern_create_copy (pattern_out, pattern);
if (status)
return status;
@@ -2387,7 +2387,7 @@ _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
* matrix should always be invertible. */
assert (status == CAIRO_STATUS_SUCCESS);
- _cairo_pattern_transform (pattern_out, &device_to_surface);
+ _cairo_pattern_transform (*pattern_out, &device_to_surface);
}
return CAIRO_STATUS_SUCCESS;
commit 6ead8feaf3f87e12e686092386dddcc2faa62b7f
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 20:41:43 2008 +1030
Add _cairo_pattern_create_copy()
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 488177b..f5d17dd 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -213,6 +213,34 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
}
}
+cairo_status_t
+_cairo_pattern_create_copy (cairo_pattern_t **pattern,
+ const cairo_pattern_t *other)
+{
+ if (other->status)
+ return other->status;
+
+ switch (other->type) {
+ case CAIRO_PATTERN_TYPE_SOLID:
+ *pattern = malloc (sizeof (cairo_solid_pattern_t));
+ break;
+ case CAIRO_PATTERN_TYPE_SURFACE:
+ *pattern = malloc (sizeof (cairo_surface_pattern_t));
+ break;
+ case CAIRO_PATTERN_TYPE_LINEAR:
+ *pattern = malloc (sizeof (cairo_linear_pattern_t));
+ break;
+ case CAIRO_PATTERN_TYPE_RADIAL:
+ *pattern = malloc (sizeof (cairo_radial_pattern_t));
+ break;
+ }
+ if (*pattern == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ return _cairo_pattern_init_copy (*pattern, other);
+}
+
+
void
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
const cairo_color_t *color,
diff --git a/src/cairoint.h b/src/cairoint.h
index 6d5bc2c..19513a7 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2223,6 +2223,10 @@ _cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b);
/* cairo_pattern.c */
cairo_private cairo_status_t
+_cairo_pattern_create_copy (cairo_pattern_t **pattern,
+ const cairo_pattern_t *other);
+
+cairo_private cairo_status_t
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
const cairo_pattern_t *other);
commit 26c6159b1e2f5481fb18f5f06f01063002dd6c98
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 20:36:32 2008 +1030
Move the PDF drawing operators into cairo-pdf-operators.c
By defining PostScript functions the same as the PDF drawing
operators, this code can be shared by both the PDF and PS backends.
diff --git a/src/Makefile.am b/src/Makefile.am
index e00bcfb..243dc56 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,6 +22,7 @@ endif
if CAIRO_HAS_PDF_SURFACE
libcairo_pdf_headers = cairo-pdf.h
libcairo_pdf_sources = cairo-pdf-surface.c cairo-pdf-surface-private.h \
+ cairo-pdf-operators.c cairo-pdf-operators-private.h \
cairo-deflate-stream.c
libcairo_font_subset_sources = $(font_subset_sources)
backend_pkgconfigs += cairo-pdf.pc
diff --git a/src/cairo-pdf-operators-private.h b/src/cairo-pdf-operators-private.h
new file mode 100644
index 0000000..835d395
--- /dev/null
+++ b/src/cairo-pdf-operators-private.h
@@ -0,0 +1,106 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2004 Red Hat, Inc
+ * Copyright © 2006 Red Hat, Inc
+ * Copyright © 2007 Adrian Johnson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Kristian Høgsberg <krh at redhat.com>
+ * Carl Worth <cworth at cworth.org>
+ * Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#ifndef CAIRO_PDF_OPERATORS_H
+#define CAIRO_PDF_OPERATORS_H
+
+#include "cairoint.h"
+
+typedef cairo_status_t
+(*cairo_pdf_operators_use_font_subset_t) (unsigned int font_id,
+ unsigned int subset_id,
+ void *closure);
+
+typedef struct _cairo_pdf_operators {
+ cairo_output_stream_t *stream;
+ cairo_matrix_t cairo_to_pdf;
+ cairo_scaled_font_subsets_t *font_subsets;
+ cairo_pdf_operators_use_font_subset_t use_font_subset;
+ void *use_font_subset_closure;
+} cairo_pdf_operators_t;
+
+cairo_private void
+_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
+ cairo_output_stream_t *stream,
+ cairo_matrix_t cairo_to_pdf,
+ cairo_scaled_font_subsets_t *font_subsets);
+
+cairo_private void
+_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators);
+
+cairo_private void
+_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators,
+ cairo_pdf_operators_use_font_subset_t use_font_subset,
+ void *closure);
+
+cairo_private void
+_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators,
+ cairo_output_stream_t *stream);
+
+
+cairo_private void
+_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
+ cairo_matrix_t cairo_to_pdf);
+
+cairo_private cairo_int_status_t
+_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule);
+
+cairo_private cairo_int_status_t
+_cairo_pdf_operator_stroke (cairo_pdf_operators_t *pdf_operators,
+ cairo_path_fixed_t *path,
+ cairo_stroke_style_t *style,
+ cairo_matrix_t *ctm,
+ cairo_matrix_t *ctm_inverse);
+
+cairo_private cairo_int_status_t
+_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule);
+
+cairo_private cairo_int_status_t
+_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font);
+
+#endif /* CAIRO_PDF_OPERATORS_H */
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
new file mode 100644
index 0000000..3c06e72
--- /dev/null
+++ b/src/cairo-pdf-operators.c
@@ -0,0 +1,531 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2004 Red Hat, Inc
+ * Copyright © 2006 Red Hat, Inc
+ * Copyright © 2007 Adrian Johnson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Kristian Høgsberg <krh at redhat.com>
+ * Carl Worth <cworth at cworth.org>
+ * Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#include "cairoint.h"
+#include "cairo-pdf-operators-private.h"
+#include "cairo-path-fixed-private.h"
+#include "cairo-output-stream-private.h"
+#include "cairo-scaled-font-subsets-private.h"
+
+void
+_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
+ cairo_output_stream_t *stream,
+ cairo_matrix_t cairo_to_pdf,
+ cairo_scaled_font_subsets_t *font_subsets)
+{
+ pdf_operators->stream = stream;
+ pdf_operators->cairo_to_pdf = cairo_to_pdf;
+ pdf_operators->font_subsets = font_subsets;
+ pdf_operators->use_font_subset = NULL;
+ pdf_operators->use_font_subset_closure = NULL;
+}
+
+void
+_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators)
+{
+}
+
+void
+_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators,
+ cairo_pdf_operators_use_font_subset_t use_font_subset,
+ void *closure)
+{
+ pdf_operators->use_font_subset = use_font_subset;
+ pdf_operators->use_font_subset_closure = closure;
+}
+
+void
+_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators,
+ cairo_output_stream_t *stream)
+{
+ pdf_operators->stream = stream;
+}
+
+void
+_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
+ cairo_matrix_t cairo_to_pdf)
+{
+ pdf_operators->cairo_to_pdf = cairo_to_pdf;
+}
+
+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;
+
+static cairo_status_t
+_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
+{
+ pdf_path_info_t *info = 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);
+
+ _cairo_output_stream_printf (info->output,
+ "%f %f m ", x, y);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
+{
+ pdf_path_info_t *info = 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);
+
+ _cairo_output_stream_printf (info->output,
+ "%f %f l ", x, y);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_pdf_path_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d)
+{
+ pdf_path_info_t *info = closure;
+ double bx = _cairo_fixed_to_double (b->x);
+ double by = _cairo_fixed_to_double (b->y);
+ double cx = _cairo_fixed_to_double (c->x);
+ double cy = _cairo_fixed_to_double (c->y);
+ 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);
+ cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
+ }
+
+ _cairo_output_stream_printf (info->output,
+ "%f %f %f %f %f %f c ",
+ bx, by, cx, cy, dx, dy);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_pdf_path_close_path (void *closure)
+{
+ pdf_path_info_t *info = closure;
+
+ _cairo_output_stream_printf (info->output,
+ "h\r\n");
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_int_status_t
+_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule)
+{
+ const char *pdf_operator;
+
+ if (! path->has_current_point) {
+ /* construct an empty path */
+ _cairo_output_stream_printf (pdf_operators->stream, "0 0 m ");
+ } else {
+ pdf_path_info_t info;
+ cairo_status_t status;
+
+ info.output = pdf_operators->stream;
+ info.cairo_to_pdf = &pdf_operators->cairo_to_pdf;
+ info.ctm_inverse = NULL;
+
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_pdf_path_move_to,
+ _cairo_pdf_path_line_to,
+ _cairo_pdf_path_curve_to,
+ _cairo_pdf_path_close_path,
+ &info);
+ if (status)
+ return status;
+ }
+
+ switch (fill_rule) {
+ case CAIRO_FILL_RULE_WINDING:
+ pdf_operator = "W";
+ break;
+ case CAIRO_FILL_RULE_EVEN_ODD:
+ pdf_operator = "W*";
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ }
+
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%s n\r\n",
+ pdf_operator);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static int
+_cairo_pdf_line_cap (cairo_line_cap_t cap)
+{
+ switch (cap) {
+ case CAIRO_LINE_CAP_BUTT:
+ return 0;
+ case CAIRO_LINE_CAP_ROUND:
+ return 1;
+ case CAIRO_LINE_CAP_SQUARE:
+ return 2;
+ default:
+ ASSERT_NOT_REACHED;
+ return 0;
+ }
+}
+
+static int
+_cairo_pdf_line_join (cairo_line_join_t join)
+{
+ switch (join) {
+ case CAIRO_LINE_JOIN_MITER:
+ return 0;
+ case CAIRO_LINE_JOIN_ROUND:
+ return 1;
+ case CAIRO_LINE_JOIN_BEVEL:
+ return 2;
+ default:
+ ASSERT_NOT_REACHED;
+ return 0;
+ }
+}
+
+static cairo_int_status_t
+_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
+ cairo_stroke_style_t *style)
+{
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%f w\r\n",
+ style->line_width);
+
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%d J\r\n",
+ _cairo_pdf_line_cap (style->line_cap));
+
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%d j\r\n",
+ _cairo_pdf_line_join (style->line_join));
+
+ if (style->num_dashes) {
+ unsigned int d;
+ _cairo_output_stream_printf (pdf_operators->stream, "[");
+ for (d = 0; d < style->num_dashes; d++)
+ _cairo_output_stream_printf (pdf_operators->stream, " %f", style->dash[d]);
+ _cairo_output_stream_printf (pdf_operators->stream, "] %f d\r\n",
+ style->dash_offset);
+ } else {
+ _cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\r\n");
+ }
+
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%f M ",
+ style->miter_limit);
+
+ return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+
+cairo_int_status_t
+_cairo_pdf_operator_stroke (cairo_pdf_operators_t *pdf_operators,
+ cairo_path_fixed_t *path,
+ cairo_stroke_style_t *style,
+ cairo_matrix_t *ctm,
+ cairo_matrix_t *ctm_inverse)
+{
+ pdf_path_info_t info;
+ cairo_status_t status;
+ cairo_matrix_t m;
+
+ status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style);
+ if (status)
+ return status;
+
+ info.output = pdf_operators->stream;
+ info.cairo_to_pdf = NULL;
+ info.ctm_inverse = ctm_inverse;
+
+ cairo_matrix_multiply (&m, ctm, &pdf_operators->cairo_to_pdf);
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "q %f %f %f %f %f %f cm\r\n",
+ m.xx, m.yx, m.xy, m.yy,
+ m.x0, m.y0);
+
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_pdf_path_move_to,
+ _cairo_pdf_path_line_to,
+ _cairo_pdf_path_curve_to,
+ _cairo_pdf_path_close_path,
+ &info);
+ if (status)
+ return status;
+
+ _cairo_output_stream_printf (pdf_operators->stream, "S Q\r\n");
+
+ return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+cairo_int_status_t
+_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule)
+{
+ const char *pdf_operator;
+ cairo_status_t status;
+ pdf_path_info_t info;
+
+ info.output = pdf_operators->stream;
+ info.cairo_to_pdf = &pdf_operators->cairo_to_pdf;
+ info.ctm_inverse = NULL;
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_pdf_path_move_to,
+ _cairo_pdf_path_line_to,
+ _cairo_pdf_path_curve_to,
+ _cairo_pdf_path_close_path,
+ &info);
+ if (status)
+ return status;
+
+ switch (fill_rule) {
+ case CAIRO_FILL_RULE_WINDING:
+ pdf_operator = "f";
+ break;
+ case CAIRO_FILL_RULE_EVEN_ODD:
+ pdf_operator = "f*";
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ }
+
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%s\r\n",
+ pdf_operator);
+
+ return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+#define GLYPH_POSITION_TOLERANCE 0.001
+
+cairo_int_status_t
+_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font)
+{
+ unsigned int current_subset_id = (unsigned int)-1;
+ cairo_scaled_font_subsets_glyph_t subset_glyph;
+ cairo_bool_t diagonal, in_TJ;
+ cairo_status_t status;
+ double Tlm_x = 0, Tlm_y = 0;
+ double Tm_x = 0, y;
+ int i, hex_width;
+
+ for (i = 0; i < num_glyphs; i++)
+ cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
+
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "BT\r\n");
+
+ if (scaled_font->scale.xy == 0.0 &&
+ scaled_font->scale.yx == 0.0)
+ diagonal = TRUE;
+ else
+ diagonal = FALSE;
+
+ in_TJ = FALSE;
+ for (i = 0; i < num_glyphs; i++) {
+ status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
+ scaled_font, glyphs[i].index,
+ &subset_glyph);
+ if (status)
+ return status;
+
+ if (subset_glyph.is_composite)
+ hex_width = 4;
+ else
+ hex_width = 2;
+
+ if (subset_glyph.is_scaled == FALSE) {
+ y = 0.0;
+ cairo_matrix_transform_distance (&scaled_font->scale,
+ &subset_glyph.x_advance,
+ &y);
+ }
+
+ if (subset_glyph.subset_id != current_subset_id) {
+ if (in_TJ) {
+ _cairo_output_stream_printf (pdf_operators->stream, ">] TJ\r\n");
+ in_TJ = FALSE;
+ }
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "/f-%d-%d 1 Tf\r\n",
+ subset_glyph.font_id,
+ subset_glyph.subset_id);
+ if (pdf_operators->use_font_subset) {
+ status = pdf_operators->use_font_subset (subset_glyph.font_id,
+ subset_glyph.subset_id,
+ pdf_operators->use_font_subset_closure);
+ if (status)
+ return status;
+ }
+ }
+
+ if (subset_glyph.subset_id != current_subset_id || !diagonal) {
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%f %f %f %f %f %f Tm\r\n",
+ scaled_font->scale.xx,
+ -scaled_font->scale.yx,
+ -scaled_font->scale.xy,
+ scaled_font->scale.yy,
+ glyphs[i].x,
+ glyphs[i].y);
+ current_subset_id = subset_glyph.subset_id;
+ Tlm_x = glyphs[i].x;
+ Tlm_y = glyphs[i].y;
+ Tm_x = Tlm_x;
+ }
+
+ if (diagonal) {
+ if (i < num_glyphs - 1 &&
+ fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE &&
+ fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10)
+ {
+ if (!in_TJ) {
+ if (i != 0) {
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%f %f Td\r\n",
+ (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
+ (glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
+
+ Tlm_x = glyphs[i].x;
+ Tlm_y = glyphs[i].y;
+ Tm_x = Tlm_x;
+ }
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "[<%0*x",
+ hex_width,
+ subset_glyph.subset_glyph_index);
+ Tm_x += subset_glyph.x_advance;
+ in_TJ = TRUE;
+ } else {
+ if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
+ double delta = glyphs[i].x - Tm_x;
+
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "> %f <",
+ -1000.0*delta/scaled_font->scale.xx);
+ Tm_x += delta;
+ }
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%0*x",
+ hex_width,
+ subset_glyph.subset_glyph_index);
+ Tm_x += subset_glyph.x_advance;
+ }
+ }
+ else
+ {
+ if (in_TJ) {
+ if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
+ double delta = glyphs[i].x - Tm_x;
+
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "> %f <",
+ -1000.0*delta/scaled_font->scale.xx);
+ Tm_x += delta;
+ }
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%0*x>] TJ\r\n",
+ hex_width,
+ subset_glyph.subset_glyph_index);
+ Tm_x += subset_glyph.x_advance;
+ in_TJ = FALSE;
+ } else {
+ if (i != 0) {
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%f %f Td ",
+ (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
+ (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
+ Tlm_x = glyphs[i].x;
+ Tlm_y = glyphs[i].y;
+ Tm_x = Tlm_x;
+ }
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "<%0*x> Tj ",
+ hex_width,
+ subset_glyph.subset_glyph_index);
+ Tm_x += subset_glyph.x_advance;
+ }
+ }
+ } else {
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "<%0*x> Tj\r\n",
+ hex_width,
+ subset_glyph.subset_glyph_index);
+ }
+ }
+
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "ET\r\n");
+
+ return _cairo_output_stream_get_status (pdf_operators->stream);
+}
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 28b6fd1..d4318d6 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -44,6 +44,7 @@
#include "cairo-pdf.h"
#include "cairo-surface-private.h"
+#include "cairo-pdf-operators-private.h"
typedef struct _cairo_pdf_resource {
unsigned int id;
@@ -124,7 +125,7 @@ struct _cairo_pdf_surface {
cairo_array_t *current_group;
cairo_pdf_group_resources_t *current_resources;
-
+ cairo_pdf_operators_t pdf_operators;
cairo_paginated_mode_t paginated_mode;
cairo_bool_t force_fallbacks;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 75a58d3..2e5cd2b 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -41,9 +41,9 @@
#include "cairoint.h"
#include "cairo-pdf.h"
#include "cairo-pdf-surface-private.h"
+#include "cairo-pdf-operators-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-paginated-private.h"
-#include "cairo-path-fixed-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-meta-surface-private.h"
@@ -225,6 +225,11 @@ _cairo_pdf_group_element_array_finish (cairo_array_t *array);
static void
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
+static cairo_status_t
+_cairo_pdf_surface_add_font (unsigned int font_id,
+ unsigned int subset_id,
+ void *closure);
+
static void
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
@@ -360,6 +365,14 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
surface->force_fallbacks = FALSE;
+ _cairo_pdf_operators_init (&surface->pdf_operators,
+ surface->output,
+ surface->cairo_to_pdf,
+ surface->font_subsets);
+ _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
+ _cairo_pdf_surface_add_font,
+ surface);
+
/* Document header */
_cairo_output_stream_printf (surface->output,
"%%PDF-1.4\r\n");
@@ -527,6 +540,8 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface,
pdf_surface->width = width_in_points;
pdf_surface->height = height_in_points;
cairo_matrix_init (&pdf_surface->cairo_to_pdf, 1, 0, 0, -1, 0, height_in_points);
+ _cairo_pdf_operators_set_cairo_to_pdf_matrix (&pdf_surface->pdf_operators,
+ pdf_surface->cairo_to_pdf);
status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
width_in_points,
height_in_points);
@@ -623,10 +638,11 @@ _cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface,
}
static cairo_status_t
-_cairo_pdf_surface_add_font (cairo_pdf_surface_t *surface,
- unsigned int font_id,
- unsigned int subset_id)
+_cairo_pdf_surface_add_font (unsigned int font_id,
+ unsigned int subset_id,
+ void *closure)
{
+ cairo_pdf_surface_t *surface = closure;
cairo_pdf_font_t font;
int num_fonts, i;
cairo_status_t status;
@@ -821,6 +837,7 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
assert (surface->pdf_stream.old_output == NULL);
surface->pdf_stream.old_output = surface->output;
surface->output = output;
+ _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
}
return surface->pdf_stream.self;
@@ -838,6 +855,7 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
if (surface->pdf_stream.compressed) {
status = _cairo_output_stream_destroy (surface->output);
surface->output = surface->pdf_stream.old_output;
+ _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
surface->pdf_stream.old_output = NULL;
_cairo_output_stream_printf (surface->output,
"\r\n");
@@ -938,6 +956,7 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface)
surface->group_stream.old_output = surface->output;
surface->output = surface->group_stream.stream;
+ _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
_cairo_pdf_group_resources_clear (&surface->group_stream.resources);
surface->current_resources = &surface->group_stream.resources;
surface->group_stream.is_knockout = FALSE;
@@ -980,6 +999,7 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
"\r\n");
}
surface->output = surface->group_stream.old_output;
+ _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
surface->group_stream.active = FALSE;
*group = _cairo_pdf_surface_write_memory_stream (surface,
surface->group_stream.mem_stream,
@@ -1057,6 +1077,7 @@ _cairo_pdf_surface_start_content_stream (cairo_pdf_surface_t *surface)
surface->content_stream.old_output = surface->output;
surface->output = surface->content_stream.stream;
+ _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
_cairo_pdf_group_resources_clear (&surface->content_stream.resources);
surface->current_resources = &surface->content_stream.resources;
@@ -1085,6 +1106,7 @@ _cairo_pdf_surface_pause_content_stream (cairo_pdf_surface_t *surface)
return;
surface->output = surface->content_stream.old_output;
+ _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
surface->content_stream.active = FALSE;
}
@@ -1097,6 +1119,7 @@ _cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface)
return;
surface->output = surface->content_stream.stream;
+ _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
surface->current_resources = &surface->content_stream.resources;
surface->content_stream.active = TRUE;
}
@@ -1120,6 +1143,7 @@ _cairo_pdf_surface_stop_content_stream (cairo_pdf_surface_t *surface)
"\r\n");
}
surface->output = surface->content_stream.old_output;
+ _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
surface->content_stream.active = FALSE;
if (_cairo_memory_stream_length (surface->content_stream.mem_stream) > 0) {
group = _cairo_pdf_surface_write_memory_stream (surface,
@@ -1222,6 +1246,8 @@ _cairo_pdf_surface_finish (void *abstract_surface)
"%%%%EOF\r\n",
offset);
+ _cairo_pdf_operators_fini (&surface->pdf_operators);
+
/* close any active streams still open due to fatal errors */
status2 = _cairo_pdf_surface_close_stream (surface);
if (status == CAIRO_STATUS_SUCCESS)
@@ -1637,6 +1663,8 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
surface->width = meta_extents.width;
surface->height = meta_extents.height;
cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
+ _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
+ surface->cairo_to_pdf);
status = _cairo_pdf_surface_start_content_stream (surface);
if (status)
@@ -1681,6 +1709,8 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
surface->width = old_width;
surface->height = old_height;
surface->cairo_to_pdf = old_cairo_to_pdf;
+ _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
+ surface->cairo_to_pdf);
_cairo_pdf_group_element_array_finish (&group);
_cairo_array_fini (&group);
@@ -2810,89 +2840,6 @@ _cairo_pdf_surface_get_extents (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
-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;
-
-static cairo_status_t
-_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
-{
- pdf_path_info_t *info = 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);
-
- _cairo_output_stream_printf (info->output,
- "%f %f m ", x, y);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
-{
- pdf_path_info_t *info = 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);
-
- _cairo_output_stream_printf (info->output,
- "%f %f l ", x, y);
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_path_curve_to (void *closure,
- cairo_point_t *b,
- cairo_point_t *c,
- cairo_point_t *d)
-{
- pdf_path_info_t *info = closure;
- double bx = _cairo_fixed_to_double (b->x);
- double by = _cairo_fixed_to_double (b->y);
- double cx = _cairo_fixed_to_double (c->x);
- double cy = _cairo_fixed_to_double (c->y);
- 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);
- cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
- }
-
- _cairo_output_stream_printf (info->output,
- "%f %f %f %f %f %f c ",
- bx, by, cx, cy, dx, dy);
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_path_close_path (void *closure)
-{
- pdf_path_info_t *info = closure;
-
- _cairo_output_stream_printf (info->output,
- "h\r\n");
-
- return CAIRO_STATUS_SUCCESS;
-}
-
static cairo_status_t
_cairo_pdf_surface_add_clip (cairo_pdf_surface_t *surface,
cairo_path_fixed_t *path,
@@ -3976,51 +3923,12 @@ _cairo_pdf_surface_emit_clip (cairo_pdf_surface_t *surface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule)
{
- const char *pdf_operator;
-
if (path == NULL) {
_cairo_output_stream_printf (surface->output, "Q q\r\n");
return CAIRO_STATUS_SUCCESS;
}
- if (! path->has_current_point) {
- /* construct an empty path */
- _cairo_output_stream_printf (surface->output, "0 0 m ");
- } else {
- pdf_path_info_t info;
- cairo_status_t status;
-
- 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,
- _cairo_pdf_path_move_to,
- _cairo_pdf_path_line_to,
- _cairo_pdf_path_curve_to,
- _cairo_pdf_path_close_path,
- &info);
- if (status)
- return status;
- }
-
- switch (fill_rule) {
- case CAIRO_FILL_RULE_WINDING:
- pdf_operator = "W";
- break;
- case CAIRO_FILL_RULE_EVEN_ODD:
- pdf_operator = "W*";
- break;
- default:
- ASSERT_NOT_REACHED;
- }
-
- _cairo_output_stream_printf (surface->output,
- "%s n\r\n",
- pdf_operator);
-
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
}
static cairo_status_t
@@ -4512,71 +4420,6 @@ _cairo_pdf_surface_mask (void *abstract_surface,
return _cairo_output_stream_get_status (surface->output);
}
-static int
-_cairo_pdf_line_cap (cairo_line_cap_t cap)
-{
- switch (cap) {
- case CAIRO_LINE_CAP_BUTT:
- return 0;
- case CAIRO_LINE_CAP_ROUND:
- return 1;
- case CAIRO_LINE_CAP_SQUARE:
- return 2;
- default:
- ASSERT_NOT_REACHED;
- return 0;
- }
-}
-
-static int
-_cairo_pdf_line_join (cairo_line_join_t join)
-{
- switch (join) {
- case CAIRO_LINE_JOIN_MITER:
- return 0;
- case CAIRO_LINE_JOIN_ROUND:
- return 1;
- case CAIRO_LINE_JOIN_BEVEL:
- return 2;
- default:
- ASSERT_NOT_REACHED;
- return 0;
- }
-}
-
-static cairo_status_t
-_cairo_pdf_surface_emit_stroke_style (cairo_pdf_surface_t *surface,
- cairo_stroke_style_t *style)
-{
- _cairo_output_stream_printf (surface->output,
- "%f w\r\n",
- style->line_width);
-
- _cairo_output_stream_printf (surface->output,
- "%d J\r\n",
- _cairo_pdf_line_cap (style->line_cap));
-
- _cairo_output_stream_printf (surface->output,
- "%d j\r\n",
- _cairo_pdf_line_join (style->line_join));
-
- if (style->num_dashes) {
- unsigned int d;
- _cairo_output_stream_printf (surface->output, "[");
- for (d = 0; d < style->num_dashes; d++)
- _cairo_output_stream_printf (surface->output, " %f", style->dash[d]);
- _cairo_output_stream_printf (surface->output, "] %f d\r\n",
- style->dash_offset);
- } else {
- _cairo_output_stream_printf (surface->output, "[] 0.0 d\r\n");
- }
-
- _cairo_output_stream_printf (surface->output,
- "%f M ",
- style->miter_limit);
-
- return _cairo_output_stream_get_status (surface->output);
-}
static cairo_int_status_t
_cairo_pdf_surface_stroke (void *abstract_surface,
@@ -4591,9 +4434,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_resource_t smask_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);
@@ -4620,33 +4461,14 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
if (status)
return status;
- status = _cairo_pdf_surface_emit_stroke_style (surface,
- style);
- if (status)
- 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",
- m.xx, m.yx, m.xy, m.yy,
- m.x0, m.y0);
-
- status = _cairo_path_fixed_interpret (path,
- CAIRO_DIRECTION_FORWARD,
- _cairo_pdf_path_move_to,
- _cairo_pdf_path_line_to,
- _cairo_pdf_path_curve_to,
- _cairo_pdf_path_close_path,
- &info);
+ status = _cairo_pdf_operator_stroke (&surface->pdf_operators,
+ path,
+ style,
+ ctm,
+ ctm_inverse);
if (status)
return status;
- _cairo_output_stream_printf (surface->output, "S Q\r\n");
-
if (surface->emitted_pattern.smask.id != 0) {
status = _cairo_pdf_surface_close_group (surface, &smask_group);
if (status)
@@ -4685,9 +4507,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
- const char *pdf_operator;
cairo_status_t status;
- pdf_path_info_t info;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
@@ -4718,34 +4538,10 @@ _cairo_pdf_surface_fill (void *abstract_surface,
if (status)
return status;
- 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,
- _cairo_pdf_path_move_to,
- _cairo_pdf_path_line_to,
- _cairo_pdf_path_curve_to,
- _cairo_pdf_path_close_path,
- &info);
+ status = _cairo_pdf_operators_fill (&surface->pdf_operators, path, fill_rule);
if (status)
return status;
- switch (fill_rule) {
- case CAIRO_FILL_RULE_WINDING:
- pdf_operator = "f";
- break;
- case CAIRO_FILL_RULE_EVEN_ODD:
- pdf_operator = "f*";
- break;
- default:
- ASSERT_NOT_REACHED;
- }
-
- _cairo_output_stream_printf (surface->output,
- "%s\r\n",
- pdf_operator);
-
if (surface->emitted_pattern.smask.id != 0) {
status = _cairo_pdf_surface_close_group (surface, &smask_group);
if (status)
@@ -4773,8 +4569,6 @@ _cairo_pdf_surface_fill (void *abstract_surface,
return _cairo_pdf_surface_check_content_stream_size (surface);
}
-#define GLYPH_POSITION_TOLERANCE 0.001
-
static cairo_int_status_t
_cairo_pdf_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
@@ -4785,13 +4579,7 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_resource_t smask_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;
cairo_status_t status;
- double Tlm_x = 0, Tlm_y = 0;
- double Tm_x = 0, y;
- int i, hex_width;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
@@ -4818,148 +4606,12 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
if (status)
return status;
- _cairo_output_stream_printf (surface->output,
- "BT\r\n");
-
- if (scaled_font->scale.xy == 0.0 &&
- scaled_font->scale.yx == 0.0)
- diagonal = TRUE;
- else
- diagonal = FALSE;
-
- in_TJ = FALSE;
- for (i = 0; i < num_glyphs; i++) {
- status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
- scaled_font, glyphs[i].index,
- &subset_glyph);
- if (status)
- return status;
-
- if (subset_glyph.is_composite)
- hex_width = 4;
- else
- hex_width = 2;
-
- if (subset_glyph.is_scaled == FALSE) {
- y = 0.0;
- cairo_matrix_transform_distance (&scaled_font->scale,
- &subset_glyph.x_advance,
- &y);
- }
-
- if (subset_glyph.subset_id != current_subset_id) {
- if (in_TJ) {
- _cairo_output_stream_printf (surface->output, ">] TJ\r\n");
- in_TJ = FALSE;
- }
- _cairo_output_stream_printf (surface->output,
- "/f-%d-%d 1 Tf\r\n",
- subset_glyph.font_id,
- subset_glyph.subset_id);
- status = _cairo_pdf_surface_add_font (surface,
- subset_glyph.font_id,
- subset_glyph.subset_id);
- if (status)
- return status;
- }
-
- if (subset_glyph.subset_id != current_subset_id || !diagonal) {
- _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.xy,
- scaled_font->scale.yy,
- glyphs[i].x,
- surface->height - glyphs[i].y);
- current_subset_id = subset_glyph.subset_id;
- Tlm_x = glyphs[i].x;
- Tlm_y = glyphs[i].y;
- Tm_x = Tlm_x;
- }
-
- if (diagonal) {
- if (i < num_glyphs - 1 &&
- fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE &&
- fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10)
- {
- if (!in_TJ) {
- if (i != 0) {
- _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);
-
- Tlm_x = glyphs[i].x;
- Tlm_y = glyphs[i].y;
- Tm_x = Tlm_x;
- }
- _cairo_output_stream_printf (surface->output,
- "[<%0*x",
- hex_width,
- subset_glyph.subset_glyph_index);
- Tm_x += subset_glyph.x_advance;
- in_TJ = TRUE;
- } else {
- if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
- double delta = glyphs[i].x - Tm_x;
-
- _cairo_output_stream_printf (surface->output,
- "> %f <",
- -1000.0*delta/scaled_font->scale.xx);
- Tm_x += delta;
- }
- _cairo_output_stream_printf (surface->output,
- "%0*x",
- hex_width,
- subset_glyph.subset_glyph_index);
- Tm_x += subset_glyph.x_advance;
- }
- }
- else
- {
- if (in_TJ) {
- if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
- double delta = glyphs[i].x - Tm_x;
-
- _cairo_output_stream_printf (surface->output,
- "> %f <",
- -1000.0*delta/scaled_font->scale.xx);
- Tm_x += delta;
- }
- _cairo_output_stream_printf (surface->output,
- "%0*x>] TJ\r\n",
- hex_width,
- subset_glyph.subset_glyph_index);
- Tm_x += subset_glyph.x_advance;
- in_TJ = FALSE;
- } else {
- if (i != 0) {
- _cairo_output_stream_printf (surface->output,
- "%f %f Td ",
- (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
- (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
- Tlm_x = glyphs[i].x;
- Tlm_y = glyphs[i].y;
- Tm_x = Tlm_x;
- }
- _cairo_output_stream_printf (surface->output,
- "<%0*x> Tj ",
- hex_width,
- subset_glyph.subset_glyph_index);
- Tm_x += subset_glyph.x_advance;
- }
- }
- } else {
- _cairo_output_stream_printf (surface->output,
- "<%0*x> Tj\r\n",
- hex_width,
- subset_glyph.subset_glyph_index);
- }
- }
-
- _cairo_output_stream_printf (surface->output,
- "ET\r\n");
+ status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
+ glyphs,
+ num_glyphs,
+ scaled_font);
+ if (status)
+ return status;
if (surface->emitted_pattern.smask.id != 0) {
status = _cairo_pdf_surface_close_group (surface, &smask_group);
commit a0e0aae32dfe44cca088736d10d208f328d50a34
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Mon Jan 7 20:34:55 2008 +1030
PDF: Remove the Type 3 outline glyph code
This code is never used because outline glyphs that go through the
fallback path are always embedded with Type 1 fallback. The only fonts
that are embedded as Type 3 are bitmap fonts.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 66959b3..75a58d3 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3605,60 +3605,6 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
}
static cairo_int_status_t
-_cairo_pdf_surface_emit_outline_glyph (cairo_pdf_surface_t *surface,
- cairo_scaled_font_t *scaled_font,
- unsigned long glyph_index,
- cairo_pdf_resource_t *glyph_ret)
-{
- cairo_scaled_glyph_t *scaled_glyph;
- pdf_path_info_t info;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
- status = _cairo_scaled_glyph_lookup (scaled_font,
- glyph_index,
- CAIRO_SCALED_GLYPH_INFO_METRICS|
- CAIRO_SCALED_GLYPH_INFO_PATH,
- &scaled_glyph);
- if (status)
- return status;
-
- *glyph_ret = _cairo_pdf_surface_open_stream (surface,
- surface->compress_content,
- NULL);
- if (glyph_ret->id == 0)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _cairo_output_stream_printf (surface->output,
- "0 0 %f %f %f %f d1\r\n",
- _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
- -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
- _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
- -_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,
- CAIRO_DIRECTION_FORWARD,
- _cairo_pdf_path_move_to,
- _cairo_pdf_path_line_to,
- _cairo_pdf_path_curve_to,
- _cairo_pdf_path_close_path,
- &info);
- if (status) {
- /* ignore status return as we are on the error path... */
- _cairo_pdf_surface_close_stream (surface);
- return status;
- }
-
- _cairo_output_stream_printf (surface->output,
- " f");
-
- return _cairo_pdf_surface_close_stream (surface);
-}
-
-static cairo_int_status_t
_cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
cairo_scaled_font_t *scaled_font,
unsigned long glyph_index,
@@ -3748,30 +3694,6 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
}
static cairo_status_t
-_cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface,
- cairo_scaled_font_t *scaled_font,
- unsigned long glyph_index,
- cairo_pdf_resource_t *glyph_ret,
- cairo_box_t *bbox,
- double *width)
-{
- cairo_status_t status;
-
- status = _cairo_pdf_surface_emit_outline_glyph (surface,
- scaled_font,
- glyph_index,
- glyph_ret);
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
- scaled_font,
- glyph_index,
- glyph_ret,
- bbox,
- width);
- return status;
-}
-
-static cairo_status_t
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
@@ -3798,12 +3720,12 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
}
for (i = 0; i < font_subset->num_glyphs; i++) {
- status = _cairo_pdf_surface_emit_glyph (surface,
- font_subset->scaled_font,
- font_subset->glyphs[i],
- &glyphs[i],
- &bbox,
- &widths[i]);
+ status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
+ font_subset->scaled_font,
+ font_subset->glyphs[i],
+ &glyphs[i],
+ &bbox,
+ &widths[i]);
if (status)
break;
More information about the cairo-commit
mailing list