=== modified file 'src/display/canvas-bpath.cpp' --- src/display/canvas-bpath.cpp 2014-10-08 02:22:03 +0000 +++ src/display/canvas-bpath.cpp 2016-07-06 00:33:56 +0000 @@ -14,11 +14,14 @@ #include #include #include "desktop.h" +#include "inkscape.h" +#include "sp-namedview.h" #include "color.h" #include "display/sp-canvas-group.h" #include "display/sp-canvas-util.h" #include "display/canvas-bpath.h" +#include "display/canvas-arena.h" #include "display/curve.h" #include "display/cairo-utils.h" #include "helper/geom.h" @@ -70,8 +73,8 @@ static void sp_canvas_bpath_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCanvasBPath *cbp = SP_CANVAS_BPATH(item); - - item->canvas->requestRedraw((int)item->x1, (int)item->y1, (int)item->x2, (int)item->y2); + //Increase the box because we render the line with 2 units instead one + item->canvas->requestRedraw((int)item->x1 - 2, (int)item->y1 - 2, (int)item->x2 + 2, (int)item->y2 + 2); if (reinterpret_cast(sp_canvas_bpath_parent_class)->update) { reinterpret_cast(sp_canvas_bpath_parent_class)->update(item, affine, flags); @@ -86,10 +89,10 @@ Geom::OptRect bbox = bounds_exact_transformed(cbp->curve->get_pathvector(), affine); if (bbox) { - item->x1 = (int)bbox->min()[Geom::X] - 1; - item->y1 = (int)bbox->min()[Geom::Y] - 1; - item->x2 = (int)bbox->max()[Geom::X] + 1; - item->y2 = (int)bbox->max()[Geom::Y] + 1; + item->x1 = (int)bbox->min()[Geom::X] - 2; + item->y1 = (int)bbox->min()[Geom::Y] - 2; + item->x2 = (int)bbox->max()[Geom::X] + 2; + item->y2 = (int)bbox->max()[Geom::Y] + 2; } else { item->x1 = 0; item->y1 = 0; @@ -100,49 +103,85 @@ } static void -sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf) +sp_canvas_bpath_render_helper (SPCanvasItem *item, SPCanvasBuf *buf, cairo_t *cairogroup, guint width, bool white) { SPCanvasBPath *cbp = SP_CANVAS_BPATH (item); - Geom::Rect area = buf->rect; - - if ( !cbp->curve || - ((cbp->stroke_rgba & 0xff) == 0 && (cbp->fill_rgba & 0xff) == 0 ) || - cbp->curve->get_segment_count() < 1) - return; - - if (!buf->ct) - return; - bool dofill = ((cbp->fill_rgba & 0xff) != 0); bool dostroke = ((cbp->stroke_rgba & 0xff) != 0); - - cairo_set_tolerance(buf->ct, 0.5); - cairo_new_path(buf->ct); - - feed_pathvector_to_cairo (buf->ct, cbp->curve->get_pathvector(), cbp->affine, area, + cairo_set_tolerance(cairogroup, 0.5); + cairo_new_path(cairogroup); + feed_pathvector_to_cairo (cairogroup, cbp->curve->get_pathvector(), cbp->affine, area, /* optimized_stroke = */ !dofill, 1); + //area *= Geom::Translate(Geom::Point(-20,-10)); if (dofill) { // RGB / BGR - ink_cairo_set_source_rgba32(buf->ct, cbp->fill_rgba); - cairo_set_fill_rule(buf->ct, cbp->fill_rule == SP_WIND_RULE_EVENODD? CAIRO_FILL_RULE_EVEN_ODD + if (white) { + ink_cairo_set_source_rgba32(cairogroup, 0xffffff7f); + } else { + cairo_set_source_rgba(cairogroup, SP_RGBA32_R_F(cbp->fill_rgba), SP_RGBA32_G_F(cbp->fill_rgba), SP_RGBA32_B_F(cbp->fill_rgba), 1.0); + } + cairo_set_fill_rule(cairogroup, cbp->fill_rule == SP_WIND_RULE_EVENODD? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING); - cairo_fill_preserve(buf->ct); + cairo_fill_preserve(cairogroup); } if (dostroke) { - ink_cairo_set_source_rgba32(buf->ct, cbp->stroke_rgba); - cairo_set_line_width(buf->ct, 1); + if (white) { + ink_cairo_set_source_rgba32(cairogroup, 0xffffff7f); + } else { + cairo_set_source_rgba(cairogroup, SP_RGBA32_R_F(cbp->stroke_rgba), SP_RGBA32_G_F(cbp->stroke_rgba), SP_RGBA32_B_F(cbp->stroke_rgba), 1.0); + } + cairo_set_line_width(cairogroup, width); if (cbp->dashes[0] != 0 && cbp->dashes[1] != 0) { - cairo_set_dash (buf->ct, cbp->dashes, 2, 0); + cairo_set_dash (cairogroup, cbp->dashes, 2, 0); } - cairo_stroke(buf->ct); + cairo_stroke_preserve(cairogroup); } else { - cairo_new_path(buf->ct); + cairo_new_path(cairogroup); } } +static void +sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf) +{ + SPCanvasBPath *cbp = SP_CANVAS_BPATH (item); + + Geom::Rect area = buf->rect; + + if ( !cbp->curve || + ((cbp->stroke_rgba & 0xff) == 0 && (cbp->fill_rgba & 0xff) == 0 ) || + cbp->curve->get_segment_count() < 1) + return; + + if (!buf->ct) + return; + //render a white line down because cairo XOR create alfa instad flat color + //we give it 3 pixels for better visibility on 1 px line top fade + sp_canvas_bpath_render_helper(item, buf, buf->ct, 1, true); + //Create a isolate cairo group to perform the operations + cairo_push_group(buf->ct); + //render the line to get composition of overlaping background + sp_canvas_bpath_render_helper(item, buf, buf->ct, 3, true); + cairo_set_operator(buf->ct, CAIRO_OPERATOR_IN); + //Render the background + cairo_surface_t *background = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, (int)buf->rect.width(), (int)buf->rect.height()); + sp_canvas_arena_render_surface(SP_CANVAS_ARENA(SP_ACTIVE_DESKTOP->getDrawing()), background, area.roundOutwards()); + cairo_set_source_surface(buf->ct, background, 0, 0); + cairo_paint(buf->ct); + //Add XOR compositing + cairo_set_operator(buf->ct, CAIRO_OPERATOR_XOR); + //The line again with 1 pixel to XOR + sp_canvas_bpath_render_helper(item, buf, buf->ct, 1, false); + //Close the group + cairo_pop_group_to_source(buf->ct); + //Switch to default compositing + cairo_set_operator(buf->ct, CAIRO_OPERATOR_OVER); + cairo_paint(buf->ct); + cairo_surface_destroy(background); +} + static double sp_canvas_bpath_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item) {