mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 15:48:00 +02:00
Add _cairo_pdf_operators_flush()
The optimizations planned for pdf-operators will mean that it will no longer emit complete operations on each call to fill/stroke/show_glyphs. For example a call to _show_glyphs() may not finish the text operation to allow a subsequent call to _show_glyphs() to be merged into the same text object. A flush function is required to force pdf_operators to complete the current operation before the pdf surface can emit any pdf operators.
This commit is contained in:
parent
e1bc97a7e5
commit
fd42b74a4f
4 changed files with 142 additions and 15 deletions
|
|
@ -63,7 +63,7 @@ _cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
|
|||
cairo_matrix_t *cairo_to_pdf,
|
||||
cairo_scaled_font_subsets_t *font_subsets);
|
||||
|
||||
cairo_private void
|
||||
cairo_private cairo_status_t
|
||||
_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators);
|
||||
|
||||
cairo_private void
|
||||
|
|
@ -80,6 +80,9 @@ 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_flush (cairo_pdf_operators_t *pdf_operators);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
|
|
|
|||
|
|
@ -60,9 +60,10 @@ _cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
|
|||
pdf_operators->use_font_subset_closure = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
cairo_status_t
|
||||
_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators)
|
||||
{
|
||||
return _cairo_pdf_operators_flush (pdf_operators);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -74,6 +75,10 @@ _cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf
|
|||
pdf_operators->use_font_subset_closure = closure;
|
||||
}
|
||||
|
||||
/* Change the output stream to a different stream.
|
||||
* _cairo_pdf_operators_flush() should always be called before calling
|
||||
* this function.
|
||||
*/
|
||||
void
|
||||
_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_output_stream_t *stream)
|
||||
|
|
@ -88,6 +93,23 @@ _cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operato
|
|||
pdf_operators->cairo_to_pdf = *cairo_to_pdf;
|
||||
}
|
||||
|
||||
/* Finish writing out any pending commands to the stream. This
|
||||
* function must be called by the surface before emitting anything
|
||||
* into the PDF stream.
|
||||
*
|
||||
* pdf_operators may leave the emitted PDF for some operations
|
||||
* unfinished in case subsequent operations can be merged. This
|
||||
* function will finish off any incomplete operation so the stream
|
||||
* will be in a state where the surface may emit it's own PDF
|
||||
* operations (eg changing patterns).
|
||||
*
|
||||
*/
|
||||
cairo_int_status_t
|
||||
_cairo_pdf_operators_flush (cairo_pdf_operators_t *pdf_operators)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* A word wrap stream can be used as a filter to do word wrapping on
|
||||
* top of an existing output stream. The word wrapping is quite
|
||||
* simple, using isspace to determine characters that separate
|
||||
|
|
|
|||
|
|
@ -904,6 +904,10 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
|
|||
if (! surface->pdf_stream.active)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (surface->pdf_stream.compressed) {
|
||||
status = _cairo_output_stream_destroy (surface->output);
|
||||
surface->output = surface->pdf_stream.old_output;
|
||||
|
|
@ -1045,6 +1049,10 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
|
|||
assert (surface->pdf_stream.active == FALSE);
|
||||
assert (surface->group_stream.active == TRUE);
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (surface->compress_content) {
|
||||
status = _cairo_output_stream_destroy (surface->group_stream.stream);
|
||||
surface->group_stream.stream = NULL;
|
||||
|
|
@ -1128,6 +1136,10 @@ _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
|
|||
assert (surface->pdf_stream.active == TRUE);
|
||||
assert (surface->group_stream.active == FALSE);
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output, "Q\n");
|
||||
status = _cairo_pdf_surface_close_stream (surface);
|
||||
if (status)
|
||||
|
|
@ -1193,7 +1205,10 @@ _cairo_pdf_surface_finish (void *abstract_surface)
|
|||
"%%%%EOF\n",
|
||||
offset);
|
||||
|
||||
_cairo_pdf_operators_fini (&surface->pdf_operators);
|
||||
status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
|
||||
/* pdf_operators has already been flushed when the last stream was
|
||||
* closed so we should never be writing anything here. */
|
||||
assert(status2 == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
/* close any active streams still open due to fatal errors */
|
||||
status2 = _cairo_pdf_surface_close_stream (surface);
|
||||
|
|
@ -2577,6 +2592,10 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
|
|||
cairo_bool_t is_solid_color = FALSE;
|
||||
cairo_color_t *solid_color;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
|
||||
|
||||
|
|
@ -2646,12 +2665,21 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
|
|||
return _cairo_output_stream_get_status (surface->output);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
|
||||
{
|
||||
if (surface->select_pattern_gstate_saved)
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (surface->select_pattern_gstate_saved) {
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output, "Q\n");
|
||||
}
|
||||
surface->select_pattern_gstate_saved = FALSE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -2700,8 +2728,13 @@ _cairo_pdf_surface_intersect_clip_path (void *abstract_surface,
|
|||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (path == NULL) {
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output, "Q q\n");
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -3759,7 +3792,9 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
|
|||
"0 0 %f %f re f\n",
|
||||
surface->width, surface->height);
|
||||
|
||||
_cairo_pdf_surface_unselect_pattern (surface);
|
||||
status = _cairo_pdf_surface_unselect_pattern (surface);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_pdf_surface_close_group (surface, &mask_group);
|
||||
|
|
@ -3812,7 +3847,9 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
|
|||
"0 0 %f %f re f\n",
|
||||
surface->width, surface->height);
|
||||
|
||||
_cairo_pdf_surface_unselect_pattern (surface);
|
||||
status = _cairo_pdf_surface_unselect_pattern (surface);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_pdf_surface_close_group (surface, NULL);
|
||||
|
|
@ -3910,7 +3947,10 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_pdf_surface_unselect_pattern (surface);
|
||||
status = _cairo_pdf_surface_unselect_pattern (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_surface_close_group (surface, NULL);
|
||||
|
||||
_cairo_pdf_surface_set_size_internal (surface,
|
||||
|
|
@ -4297,6 +4337,10 @@ _cairo_pdf_surface_paint (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"q /s%d gs /x%d Do Q\n",
|
||||
gstate_res.id,
|
||||
|
|
@ -4310,7 +4354,9 @@ _cairo_pdf_surface_paint (void *abstract_surface,
|
|||
"0 0 %f %f re f\n",
|
||||
surface->width, surface->height);
|
||||
|
||||
_cairo_pdf_surface_unselect_pattern (surface);
|
||||
status = _cairo_pdf_surface_unselect_pattern (surface);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return _cairo_output_stream_get_status (surface->output);
|
||||
|
|
@ -4373,6 +4419,10 @@ _cairo_pdf_surface_mask (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"q /s%d gs /x%d Do Q\n",
|
||||
group->group_res.id,
|
||||
|
|
@ -4441,6 +4491,10 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"q /s%d gs /x%d Do Q\n",
|
||||
gstate_res.id,
|
||||
|
|
@ -4458,7 +4512,9 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_pdf_surface_unselect_pattern (surface);
|
||||
status = _cairo_pdf_surface_unselect_pattern (surface);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return _cairo_output_stream_get_status (surface->output);
|
||||
|
|
@ -4525,6 +4581,10 @@ _cairo_pdf_surface_fill (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"q /s%d gs /x%d Do Q\n",
|
||||
gstate_res.id,
|
||||
|
|
@ -4540,7 +4600,9 @@ _cairo_pdf_surface_fill (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_pdf_surface_unselect_pattern (surface);
|
||||
status = _cairo_pdf_surface_unselect_pattern (surface);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return _cairo_output_stream_get_status (surface->output);
|
||||
|
|
@ -4627,7 +4689,9 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_pdf_surface_unselect_pattern (surface);
|
||||
status = _cairo_pdf_surface_unselect_pattern (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return _cairo_output_stream_get_status (surface->output);
|
||||
}
|
||||
|
|
@ -4689,6 +4753,10 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"q /s%d gs /x%d Do Q\n",
|
||||
gstate_res.id,
|
||||
|
|
@ -4705,7 +4773,9 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_pdf_surface_unselect_pattern (surface);
|
||||
status = _cairo_pdf_surface_unselect_pattern (surface);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return _cairo_output_stream_get_status (surface->output);
|
||||
|
|
|
|||
|
|
@ -1327,19 +1327,30 @@ _cairo_ps_surface_start_page (void *abstract_surface)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_int_status_t
|
||||
_cairo_ps_surface_end_page (cairo_ps_surface_t *surface)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"Q\n");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_ps_surface_show_page (void *abstract_surface)
|
||||
{
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
_cairo_ps_surface_end_page (surface);
|
||||
status = _cairo_ps_surface_end_page (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream, "showpage\n");
|
||||
|
||||
|
|
@ -2078,6 +2089,10 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
" Q\n");
|
||||
surface->content = old_content;
|
||||
|
|
@ -2835,6 +2850,10 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
|
|||
* different pattern. */
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
_cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
|
||||
|
|
@ -2875,6 +2894,7 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface,
|
|||
{
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_output_stream_t *stream = surface->stream;
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -2885,6 +2905,10 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface,
|
|||
#endif
|
||||
|
||||
if (path == NULL) {
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (stream, "Q q\n");
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -2948,6 +2972,10 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
(source->extend == CAIRO_EXTEND_NONE ||
|
||||
source->extend == CAIRO_EXTEND_PAD))
|
||||
|
|
@ -3040,6 +3068,10 @@ _cairo_ps_surface_fill (void *abstract_surface,
|
|||
(source->extend == CAIRO_EXTEND_NONE ||
|
||||
source->extend == CAIRO_EXTEND_PAD))
|
||||
{
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream, "q\n");
|
||||
|
||||
status = _cairo_pdf_operators_clip (&surface->pdf_operators,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue