diff options
Diffstat (limited to 'src/extension/internal/cairo-render-context.cpp')
| -rw-r--r-- | src/extension/internal/cairo-render-context.cpp | 113 |
1 files changed, 85 insertions, 28 deletions
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index c3e416184..5d8b0e076 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -130,14 +130,12 @@ CairoRenderContext::CairoRenderContext(CairoRenderer *parent) : _clip_mode(CLIP_MODE_MASK), _omittext_state(EMPTY) { - font_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, font_data_free); } CairoRenderContext::~CairoRenderContext(void) { - if(font_table != NULL) { - g_hash_table_remove_all(font_table); - } + for (std::map<gpointer, cairo_font_face_t *>::const_iterator iter = font_table.begin(); iter != font_table.end(); ++iter) + font_data_free(iter->second); if (_cr) cairo_destroy(_cr); if (_surface) cairo_surface_destroy(_surface); @@ -1182,7 +1180,7 @@ CairoRenderContext::_createHatchPainter(SPPaintServer const *const paintserver, std::vector<SPHatchPath *> children(evil->hatchPaths()); for (int i = 0; i < overflow_steps; i++) { - for (std::vector<SPHatchPath *>::iterator iter = children.begin(); iter != children.end(); iter++) { + for (std::vector<SPHatchPath *>::iterator iter = children.begin(); iter != children.end(); ++iter) { SPHatchPath *path = *iter; _renderer->renderHatchPath(pattern_ctx, *path, dkey); } @@ -1247,11 +1245,12 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain Geom::Point c (rg->cx.computed, rg->cy.computed); Geom::Point f (rg->fx.computed, rg->fy.computed); double r = rg->r.computed; + double fr = rg->fr.computed; if (pbox && SP_GRADIENT(rg)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) apply_bbox2user = true; // create radial gradient pattern - pattern = cairo_pattern_create_radial(f[Geom::X], f[Geom::Y], 0, c[Geom::X], c[Geom::Y], r); + pattern = cairo_pattern_create_radial(f[Geom::X], f[Geom::Y], fr, c[Geom::X], c[Geom::Y], r); // add stops for (gint i = 0; unsigned(i) < rg->vector.stops.size(); i++) { @@ -1454,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 ); @@ -1477,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; @@ -1493,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); @@ -1510,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) @@ -1643,9 +1656,11 @@ 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 = (cairo_font_face_t *)g_hash_table_lookup(font_table, fonthash); + cairo_font_face_t *font_face = NULL; + if(font_table.find(fonthash)!=font_table.end()) + font_face = font_table[fonthash]; FcPattern *fc_pattern = NULL; @@ -1660,7 +1675,7 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const &font_ma if(font_face == NULL) { font_face = cairo_win32_font_face_create_for_logfontw(&lfw); - g_hash_table_insert(font_table, fonthash, font_face); + font_table[fonthash] = font_face; } # endif #else @@ -1669,7 +1684,7 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const &font_ma fc_pattern = fc_font->font_pattern; if(font_face == NULL) { font_face = cairo_ft_font_face_create_for_pattern(fc_pattern); - g_hash_table_insert(font_table, fonthash, font_face); + font_table[fonthash] = font_face; } # endif #endif @@ -1677,8 +1692,8 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const &font_ma cairo_save(_cr); cairo_set_font_face(_cr, font_face); - if (fc_pattern && FcPatternGetDouble(fc_pattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch) - size = 12.0; + //if (fc_pattern && FcPatternGetDouble(fc_pattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch) + // size = 12.0; // set the given font matrix cairo_matrix_t matrix; @@ -1698,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); |
