Implement PDF fill-stroke

This commit is contained in:
Adrian Johnson 2008-02-17 16:45:15 +10:30
parent 1e7fa4b9f5
commit 2dfe32a0ff
4 changed files with 164 additions and 2 deletions

View file

@ -744,7 +744,12 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
cairo_command_t *stroke_command;
stroke_command = (i < num_elements - 1) ? elements[i + 1] : NULL;
if (stroke_command != NULL &&
type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL)
{
if (stroke_command->header.region != region)
stroke_command = NULL;
}
if (stroke_command != NULL &&
stroke_command->header.type == CAIRO_COMMAND_STROKE &&
_cairo_path_fixed_is_equal (dev_path, _cairo_command_get_path (stroke_command))) {
@ -778,6 +783,14 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
stroke_command->stroke.tolerance * tolerance_multiplier,
stroke_command->stroke.antialias);
i++;
if (type == CAIRO_META_CREATE_REGIONS) {
if (status == CAIRO_STATUS_SUCCESS) {
stroke_command->header.region = CAIRO_META_REGION_NATIVE;
} else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
stroke_command->header.region = CAIRO_META_REGION_IMAGE_FALLBACK;
status = CAIRO_STATUS_SUCCESS;
}
}
} else
status = _cairo_surface_fill (target,
command->fill.op,

View file

@ -97,6 +97,14 @@ _cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule);
cairo_int_status_t
_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
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_private cairo_int_status_t
_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
cairo_glyph_t *glyphs,

View file

@ -3,7 +3,7 @@
*
* 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
@ -612,6 +612,55 @@ _cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
return _cairo_output_stream_get_status (pdf_operators->stream);
}
cairo_int_status_t
_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
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)
{
const char *pdf_operator;
cairo_status_t status;
cairo_matrix_t m;
status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;
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_pdf_operators_emit_path (pdf_operators,
path,
ctm_inverse,
style->line_cap);
if (status)
return status;
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
pdf_operator = "B";
break;
case CAIRO_FILL_RULE_EVEN_ODD:
pdf_operator = "B*";
break;
default:
ASSERT_NOT_REACHED;
}
_cairo_output_stream_printf (pdf_operators->stream,
"%s Q\r\n",
pdf_operator);
return _cairo_output_stream_get_status (pdf_operators->stream);
}
#define GLYPH_POSITION_TOLERANCE 0.001
cairo_int_status_t

View file

@ -4455,6 +4455,97 @@ _cairo_pdf_surface_fill (void *abstract_surface,
return _cairo_output_stream_get_status (surface->output);
}
static cairo_int_status_t
_cairo_pdf_surface_fill_stroke (void *abstract_surface,
cairo_operator_t fill_op,
cairo_pattern_t *fill_source,
cairo_fill_rule_t fill_rule,
double fill_tolerance,
cairo_antialias_t fill_antialias,
cairo_path_fixed_t *path,
cairo_operator_t stroke_op,
cairo_pattern_t *stroke_source,
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *stroke_ctm,
cairo_matrix_t *stroke_ctm_inverse,
double stroke_tolerance,
cairo_antialias_t stroke_antialias)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_status_t status;
cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
/* During analysis we return unsupported and let the _fill and
* _stroke functions that are on the fallback path do the analysis
* for us. During render we may still encounter unsupported
* combinations of fill/stroke patterns. However we can return
* unsupported anytime to let the _fill and _stroke functions take
* over.
*/
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Fill-stroke with patterns requiring an SMask are not currently
* implemented. Non opaque stroke patterns are not supported
* because the PDF fill-stroke operator does not blend a
* transparent stroke with the fill.
*/
if (fill_source->type == CAIRO_PATTERN_TYPE_LINEAR ||
fill_source->type == CAIRO_PATTERN_TYPE_RADIAL)
{
if (!_cairo_pattern_is_opaque (fill_source))
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (!_cairo_pattern_is_opaque (stroke_source))
return CAIRO_INT_STATUS_UNSUPPORTED;
fill_pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
&fill_pattern_res,
&gstate_res);
if (status)
return status;
assert (gstate_res.id == 0);
stroke_pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface,
stroke_source,
&stroke_pattern_res,
&gstate_res);
if (status)
return status;
assert (gstate_res.id == 0);
/* As PDF has separate graphics state for fill and stroke we can
* select both at the same time */
status = _cairo_pdf_surface_select_pattern (surface, fill_source,
fill_pattern_res, FALSE);
if (status)
return status;
status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
stroke_pattern_res, TRUE);
if (status)
return status;
status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
path,
fill_rule,
stroke_style,
stroke_ctm,
stroke_ctm_inverse);
if (status)
return status;
_cairo_pdf_surface_unselect_pattern (surface);
return _cairo_output_stream_get_status (surface->output);
}
static cairo_int_status_t
_cairo_pdf_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
@ -4572,6 +4663,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
NULL, /* is_compatible */
NULL, /* reset */
_cairo_pdf_surface_fill_stroke,
};
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {