summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2016-03-08 14:10:38 +0000
committertavmjong-free <tavmjong@free.fr>2016-03-08 14:10:38 +0000
commitcd166baa1470b0ca83973f76fabea9a935163344 (patch)
tree4ab24c7edd578c261602f19e347f1a67d3847c83 /src
parentTranslations. PO template updated. (diff)
downloadinkscape-cd166baa1470b0ca83973f76fabea9a935163344.tar.gz
inkscape-cd166baa1470b0ca83973f76fabea9a935163344.zip
Add PDF/PS output support for 'paint-order' property.
(bzr r14696)
Diffstat (limited to 'src')
-rw-r--r--src/extension/internal/cairo-render-context.cpp90
-rw-r--r--src/extension/internal/cairo-render-context.h9
-rw-r--r--src/extension/internal/cairo-renderer.cpp30
3 files changed, 110 insertions, 19 deletions
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index f811f00ad..5d8b0e076 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -1453,8 +1453,11 @@ CairoRenderContext::_prepareRenderText()
}
}
+/* We need CairoPaintOrder as markers are rendered in a separate step and may be rendered
+ * inbetween fill and stroke.
+ */
bool
-CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle const *style, Geom::OptRect const &pbox)
+CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle const *style, Geom::OptRect const &pbox, CairoPaintOrder order)
{
g_assert( _is_valid );
@@ -1476,9 +1479,10 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con
return true;
}
- bool no_fill = style->fill.isNone() || style->fill_opacity.value == 0;
+ bool no_fill = style->fill.isNone() || style->fill_opacity.value == 0 ||
+ order == STROKE_ONLY;
bool no_stroke = style->stroke.isNone() || style->stroke_width.computed < 1e-9 ||
- style->stroke_opacity.value == 0;
+ style->stroke_opacity.value == 0 || order == FILL_ONLY;
if (no_fill && no_stroke)
return true;
@@ -1492,14 +1496,17 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con
pushLayer();
if (!no_fill) {
- _setFillStyle(style, pbox);
- setPathVector(pathv);
-
if (style->fill_rule.computed == SP_WIND_RULE_EVENODD) {
cairo_set_fill_rule(_cr, CAIRO_FILL_RULE_EVEN_ODD);
} else {
cairo_set_fill_rule(_cr, CAIRO_FILL_RULE_WINDING);
}
+ }
+
+ setPathVector(pathv);
+
+ if (!no_fill && (order == STROKE_OVER_FILL || order == FILL_ONLY)) {
+ _setFillStyle(style, pbox);
if (no_stroke)
cairo_fill(_cr);
@@ -1509,10 +1516,17 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con
if (!no_stroke) {
_setStrokeStyle(style, pbox);
- if (no_fill)
- setPathVector(pathv);
- cairo_stroke(_cr);
+ if (no_fill || order == STROKE_OVER_FILL)
+ cairo_stroke(_cr);
+ else
+ cairo_stroke_preserve(_cr);
+ }
+
+ if (!no_fill && order == FILL_OVER_STROKE) {
+ _setFillStyle(style, pbox);
+
+ cairo_fill(_cr);
}
if (need_layer)
@@ -1642,7 +1656,7 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const &font_ma
return true;
// create a cairo_font_face from PangoFont
- double size = style->font_size.computed; /// \fixme why is this variable never used?
+ // double size = style->font_size.computed; /// \fixme why is this variable never used?
gpointer fonthash = (gpointer)font;
cairo_font_face_t *font_face = NULL;
if(font_table.find(fonthash)!=font_table.end())
@@ -1699,30 +1713,72 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const &font_ma
_showGlyphs(_cr, font, glyphtext, TRUE);
}
} else {
- bool fill = false, stroke = false, have_path = false;
+
+ bool fill = false;
if (style->fill.isColor() || style->fill.isPaintserver()) {
fill = true;
}
+ bool stroke = false;
if (style->stroke.isColor() || style->stroke.isPaintserver()) {
stroke = true;
}
- if (fill) {
+
+ // Text never has markers
+ bool stroke_over_fill = true;
+ if ( (style->paint_order.layer[0] == SP_CSS_PAINT_ORDER_STROKE &&
+ style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_FILL) ||
+
+ (style->paint_order.layer[0] == SP_CSS_PAINT_ORDER_STROKE &&
+ style->paint_order.layer[2] == SP_CSS_PAINT_ORDER_FILL) ||
+
+ (style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_STROKE &&
+ style->paint_order.layer[2] == SP_CSS_PAINT_ORDER_FILL) ) {
+ stroke_over_fill = false;
+ }
+
+ bool have_path = false;
+ if (fill && stroke_over_fill) {
_setFillStyle(style, Geom::OptRect());
if (_is_texttopath) {
_showGlyphs(_cr, font, glyphtext, true);
- have_path = true;
- if (stroke) cairo_fill_preserve(_cr);
- else cairo_fill(_cr);
+ if (stroke) {
+ cairo_fill_preserve(_cr);
+ have_path = true;
+ } else {
+ cairo_fill(_cr);
+ }
} else {
_showGlyphs(_cr, font, glyphtext, false);
}
}
+
if (stroke) {
_setStrokeStyle(style, Geom::OptRect());
- if (!have_path) _showGlyphs(_cr, font, glyphtext, true);
- cairo_stroke(_cr);
+ if (!have_path) {
+ _showGlyphs(_cr, font, glyphtext, true);
+ }
+ if (fill && _is_texttopath && !stroke_over_fill) {
+ cairo_stroke_preserve(_cr);
+ have_path = true;
+ } else {
+ cairo_stroke(_cr);
+ }
+ }
+
+ if (fill && !stroke_over_fill) {
+ _setFillStyle(style, Geom::OptRect());
+ if (_is_texttopath) {
+ if (!have_path) {
+ // Could happen if both 'stroke' and 'stroke_over_fill' are false
+ _showGlyphs(_cr, font, glyphtext, true);
+ }
+ cairo_fill(_cr);
+ } else {
+ _showGlyphs(_cr, font, glyphtext, false);
+ }
}
+
}
cairo_restore(_cr);
diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h
index b3ab3655a..dfa6084d1 100644
--- a/src/extension/internal/cairo-render-context.h
+++ b/src/extension/internal/cairo-render-context.h
@@ -148,7 +148,14 @@ public:
void addClippingRect(double x, double y, double width, double height);
/* Rendering methods */
- bool renderPathVector(Geom::PathVector const &pathv, SPStyle const *style, Geom::OptRect const &pbox);
+ enum CairoPaintOrder {
+ STROKE_OVER_FILL,
+ FILL_OVER_STROKE,
+ FILL_ONLY,
+ STROKE_ONLY
+ };
+
+ bool renderPathVector(Geom::PathVector const &pathv, SPStyle const *style, Geom::OptRect const &pbox, CairoPaintOrder order = STROKE_OVER_FILL);
bool renderImage(Inkscape::Pixbuf *pb,
Geom::Affine const &image_transform, SPStyle const *style);
bool renderGlyphtext(PangoFont *font, Geom::Affine const &font_matrix,
diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp
index a4561fd11..5dc20ab06 100644
--- a/src/extension/internal/cairo-renderer.cpp
+++ b/src/extension/internal/cairo-renderer.cpp
@@ -194,7 +194,20 @@ static void sp_shape_render(SPShape *shape, CairoRenderContext *ctx)
return;
}
- ctx->renderPathVector(pathv, style, pbox);
+ if (style->paint_order.layer[0] == SP_CSS_PAINT_ORDER_NORMAL ||
+ (style->paint_order.layer[0] == SP_CSS_PAINT_ORDER_FILL &&
+ style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_STROKE)) {
+ ctx->renderPathVector(pathv, style, pbox, CairoRenderContext::STROKE_OVER_FILL);
+ } else if (style->paint_order.layer[0] == SP_CSS_PAINT_ORDER_STROKE &&
+ style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_FILL ) {
+ ctx->renderPathVector(pathv, style, pbox, CairoRenderContext::FILL_OVER_STROKE);
+ } else if (style->paint_order.layer[0] == SP_CSS_PAINT_ORDER_STROKE &&
+ style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_MARKER ) {
+ ctx->renderPathVector(pathv, style, pbox, CairoRenderContext::STROKE_ONLY);
+ } else if (style->paint_order.layer[0] == SP_CSS_PAINT_ORDER_FILL &&
+ style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_MARKER ) {
+ ctx->renderPathVector(pathv, style, pbox, CairoRenderContext::FILL_ONLY);
+ }
// START marker
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
@@ -287,6 +300,21 @@ static void sp_shape_render(SPShape *shape, CairoRenderContext *ctx)
sp_shape_render_invoke_marker_rendering(marker, tr, style, ctx);
}
}
+
+ if (style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_FILL &&
+ style->paint_order.layer[2] == SP_CSS_PAINT_ORDER_STROKE) {
+ ctx->renderPathVector(pathv, style, pbox, CairoRenderContext::STROKE_OVER_FILL);
+ } else if (style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_STROKE &&
+ style->paint_order.layer[2] == SP_CSS_PAINT_ORDER_FILL ) {
+ ctx->renderPathVector(pathv, style, pbox, CairoRenderContext::FILL_OVER_STROKE);
+ } else if (style->paint_order.layer[2] == SP_CSS_PAINT_ORDER_STROKE &&
+ style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_MARKER ) {
+ ctx->renderPathVector(pathv, style, pbox, CairoRenderContext::STROKE_ONLY);
+ } else if (style->paint_order.layer[2] == SP_CSS_PAINT_ORDER_FILL &&
+ style->paint_order.layer[1] == SP_CSS_PAINT_ORDER_MARKER ) {
+ ctx->renderPathVector(pathv, style, pbox, CairoRenderContext::FILL_ONLY);
+ }
+
}
static void sp_group_render(SPGroup *group, CairoRenderContext *ctx)