summaryrefslogtreecommitdiffstats
path: root/src/display
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-06-22 21:36:47 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2010-06-22 21:36:47 +0000
commit917de2bab458d51b4149a1b794cbb1b6b9562171 (patch)
tree9abd6fe6497b8b0965bb85caf4b4456ff2099989 /src/display
parent* [INTL:sk] Slovak translation update (diff)
downloadinkscape-917de2bab458d51b4149a1b794cbb1b6b9562171.tar.gz
inkscape-917de2bab458d51b4149a1b794cbb1b6b9562171.zip
Initial Cairo rendering commit: solid shapes, gradients, opacity and patterns
(bzr r9508.1.1)
Diffstat (limited to 'src/display')
-rw-r--r--src/display/canvas-arena.cpp25
-rw-r--r--src/display/canvas-bpath.cpp22
-rw-r--r--src/display/inkscape-cairo.cpp35
-rw-r--r--src/display/inkscape-cairo.h5
-rw-r--r--src/display/nr-arena-item.cpp13
-rw-r--r--src/display/nr-arena-shape.cpp259
-rw-r--r--src/display/nr-arena-shape.h3
-rw-r--r--src/display/sodipodi-ctrl.cpp283
-rw-r--r--src/display/sodipodi-ctrl.h2
-rw-r--r--src/display/sodipodi-ctrlrect.cpp35
-rw-r--r--src/display/sp-canvas-util.cpp29
-rw-r--r--src/display/sp-canvas-util.h5
-rw-r--r--src/display/sp-canvas.cpp53
-rw-r--r--src/display/sp-canvas.h14
-rw-r--r--src/display/sp-ctrlline.cpp6
15 files changed, 433 insertions, 356 deletions
diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp
index 733f9a513..86d902be2 100644
--- a/src/display/canvas-arena.cpp
+++ b/src/display/canvas-arena.cpp
@@ -190,6 +190,7 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
gint bw, bh;
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
+ SPCanvas *canvas = item->canvas;
nr_arena_item_invoke_update (arena->root, NULL, &arena->gc,
NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER,
@@ -209,19 +210,31 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
area.x1 = buf->rect.x1;
area.y1 = buf->rect.y1;
+ sp_canvas_prepare_buffer(buf);
+
nr_pixblock_setup_extern (&cb, NR_PIXBLOCK_MODE_R8G8B8A8P, area.x0, area.y0, area.x1, area.y1,
buf->buf,
buf->buf_rowstride,
FALSE, FALSE);
cb.visible_area = buf->visible_rect;
- cairo_t *ct = nr_create_cairo_context (&area, &cb);
- nr_arena_item_invoke_render (ct, arena->root, &area, &cb, 0);
+ //cairo_t *ct = nr_create_cairo_context (&area, &cb);
+
+ cairo_save(buf->ct);
+ //cairo_translate(buf->ct, area.x0 - canvas->x0, area.y0 - canvas->y0);
+ nr_arena_item_invoke_render (buf->ct, arena->root, &area, &cb, 0);
+ cairo_restore(buf->ct);
+
+ //cairo_surface_t *cst = cairo_get_target(ct);
+
+ //cairo_save(buf->ct);
+ //cairo_set_source_surface(buf->ct, cst, 0, 0);
+ //cairo_paint(buf->ct);
+ //cairo_restore(buf->ct);
- cairo_surface_t *cst = cairo_get_target(ct);
- cairo_destroy (ct);
- cairo_surface_finish (cst);
- cairo_surface_destroy (cst);
+ //cairo_destroy (ct);
+ //cairo_surface_finish (cst);
+ //cairo_surface_destroy (cst);
nr_pixblock_release (&cb);
}
diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp
index c47806615..5726fef02 100644
--- a/src/display/canvas-bpath.cpp
+++ b/src/display/canvas-bpath.cpp
@@ -149,8 +149,6 @@ sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf)
{
SPCanvasBPath *cbp = SP_CANVAS_BPATH (item);
- sp_canvas_prepare_buffer(buf);
-
Geom::Rect area (Geom::Point(buf->rect.x0, buf->rect.y0), Geom::Point(buf->rect.x1, buf->rect.y1));
if ( !cbp->curve ||
@@ -164,33 +162,29 @@ sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf)
bool dofill = ((cbp->fill_rgba & 0xff) != 0);
bool dostroke = ((cbp->stroke_rgba & 0xff) != 0);
- cairo_set_tolerance(buf->ct, 1.25); // low quality, but good enough for canvas items
+ cairo_set_tolerance(buf->ct, 0.5);
cairo_new_path(buf->ct);
- if (!dofill)
- feed_pathvector_to_cairo (buf->ct, cbp->curve->get_pathvector(), cbp->affine, area, true, 1);
- else
- feed_pathvector_to_cairo (buf->ct, cbp->curve->get_pathvector(), cbp->affine, area, false, 1);
+ feed_pathvector_to_cairo (buf->ct, cbp->curve->get_pathvector(), cbp->affine, area,
+ /* optimized_stroke = */ !dofill, 1);
if (dofill) {
// RGB / BGR
- cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(cbp->fill_rgba), SP_RGBA32_G_F(cbp->fill_rgba), SP_RGBA32_R_F(cbp->fill_rgba), SP_RGBA32_A_F(cbp->fill_rgba));
+ 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
: CAIRO_FILL_RULE_WINDING);
- if (dostroke)
- cairo_fill_preserve(buf->ct);
- else
- cairo_fill(buf->ct);
+ cairo_fill_preserve(buf->ct);
}
if (dostroke) {
- // RGB / BGR
- cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(cbp->stroke_rgba), SP_RGBA32_G_F(cbp->stroke_rgba), SP_RGBA32_R_F(cbp->stroke_rgba), SP_RGBA32_A_F(cbp->stroke_rgba));
+ ink_cairo_set_source_rgba32(buf->ct, cbp->stroke_rgba);
cairo_set_line_width(buf->ct, 1);
if (cbp->dashes[0] != 0 && cbp->dashes[1] != 0) {
cairo_set_dash (buf->ct, cbp->dashes, 2, 0);
}
cairo_stroke(buf->ct);
+ } else {
+ cairo_new_path(buf->ct);
}
}
diff --git a/src/display/inkscape-cairo.cpp b/src/display/inkscape-cairo.cpp
index a3e550fc5..fa5a7cfe2 100644
--- a/src/display/inkscape-cairo.cpp
+++ b/src/display/inkscape-cairo.cpp
@@ -53,12 +53,14 @@ nr_create_cairo_context_for_data (NRRectL *area, NRRectL *buf_area, unsigned cha
return ct;
}
+#if 0
/** Creates a cairo context to render to the given SPCanvasBuf on the given area */
cairo_t *
nr_create_cairo_context_canvasbuf (NRRectL */*area*/, SPCanvasBuf *b)
{
return nr_create_cairo_context_for_data (&(b->rect), &(b->rect), b->buf, b->buf_rowstride);
}
+#endif
/** Creates a cairo context to render to the given NRPixBlock on the given area */
@@ -236,6 +238,39 @@ feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv)
}
}
+void
+ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba)
+{
+ cairo_set_source_rgba(ct, SP_RGBA32_R_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_B_F(rgba), SP_RGBA32_A_F(rgba));
+}
+
+static void
+ink_cairo_convert_matrix(cairo_matrix_t &cm, Geom::Matrix const &m)
+{
+ cm.xx = m[0];
+ cm.xy = m[2];
+ cm.x0 = m[4];
+ cm.yx = m[1];
+ cm.yy = m[3];
+ cm.y0 = m[5];
+}
+
+void
+ink_cairo_transform(cairo_t *ct, Geom::Matrix const &m)
+{
+ cairo_matrix_t cm;
+ ink_cairo_convert_matrix(cm, m);
+ cairo_transform(ct, &cm);
+}
+
+void
+ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Matrix const &m)
+{
+ cairo_matrix_t cm;
+ ink_cairo_convert_matrix(cm, m);
+ cairo_pattern_set_matrix(cp, &cm);
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/display/inkscape-cairo.h b/src/display/inkscape-cairo.h
index cb4d474a6..74dc10995 100644
--- a/src/display/inkscape-cairo.h
+++ b/src/display/inkscape-cairo.h
@@ -19,11 +19,14 @@
struct NRPixBlock;
class SPCanvasBuf;
-cairo_t *nr_create_cairo_context_canvasbuf (NRRectL *area, SPCanvasBuf *b);
cairo_t *nr_create_cairo_context (NRRectL *area, NRPixBlock *pb);
void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width);
void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv);
+void ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba);
+void ink_cairo_transform(cairo_t *ct, Geom::Matrix const &m);
+void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Matrix const &m);
+
#endif
/*
Local Variables:
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index b80df7273..d101a9e54 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -369,6 +369,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
return item->state | NR_ARENA_ITEM_STATE_RENDER;
}
+#if 0
NRPixBlock cpb;
if (item->px) {
/* Has cache pixblock, render this and return */
@@ -386,9 +387,9 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
pb->empty = FALSE;
return item->state | NR_ARENA_ITEM_STATE_RENDER;
}
-
+#endif
NRPixBlock *dpb = pb;
-
+#if 0
/* Setup cache if we can */
if ((!(flags & NR_ARENA_ITEM_RENDER_NO_CACHE)) &&
(carea.x0 <= item->drawbox.x0) && (carea.y0 <= item->drawbox.y0) &&
@@ -411,12 +412,14 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
// Set nocache flag for downstream rendering
flags |= NR_ARENA_ITEM_RENDER_NO_CACHE;
}
+#endif
/* Determine, whether we need temporary buffer */
- if (item->clip || item->mask
+/* if (item->clip || item->mask
|| ((item->opacity != 255) && !item->render_opacity)
|| (item->filter && filter) || item->background_new
- || (item->parent && item->parent->background_pb)) {
+ || (item->parent && item->parent->background_pb))*/
+ if (0) {
/* Setup and render item buffer */
NRPixBlock ipb;
@@ -575,7 +578,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
item->background_pb = NULL;
} else {
/* Just render */
- unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, dpb, flags);
+ unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, const_cast<NRRectL*>(area), dpb, flags);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
/* Clean up and return error */
if (dpb != pb)
diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp
index a3b295a4e..9ec8f1100 100644
--- a/src/display/nr-arena-shape.cpp
+++ b/src/display/nr-arena-shape.cpp
@@ -145,6 +145,8 @@ nr_arena_shape_finalize(NRObject *object)
if (shape->cached_stroke) delete shape->cached_stroke;
if (shape->fill_painter) sp_painter_free(shape->fill_painter);
if (shape->stroke_painter) sp_painter_free(shape->stroke_painter);
+ if (shape->fill_pattern) cairo_pattern_destroy(shape->fill_pattern);
+ if (shape->stroke_pattern) cairo_pattern_destroy(shape->stroke_pattern);
if (shape->style) sp_style_unref(shape->style);
if (shape->curve) shape->curve->unref();
@@ -317,13 +319,15 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
delete shape->stroke_shp;
shape->stroke_shp = NULL;
}
- if (shape->fill_painter) {
- sp_painter_free(shape->fill_painter);
- shape->fill_painter = NULL;
+
+ // clear Cairo patterns to force update
+ if (shape->fill_pattern) {
+ cairo_pattern_destroy(shape->fill_pattern);
+ shape->fill_pattern = NULL;
}
- if (shape->stroke_painter) {
- sp_painter_free(shape->stroke_painter);
- shape->stroke_painter = NULL;
+ if (shape->stroke_pattern) {
+ cairo_pattern_destroy(shape->stroke_pattern);
+ shape->stroke_pattern = NULL;
}
if (!shape->curve ||
@@ -366,31 +370,10 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
item->bbox.x1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[0][1]));
item->bbox.y1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[1][1]));
- item->render_opacity = TRUE;
- if ( shape->_fill.paint.type() == NRArenaShape::Paint::SERVER ) {
- if (gc && gc->parent) {
- shape->fill_painter = sp_paint_server_painter_new(shape->_fill.paint.server(),
- gc->transform, gc->parent->transform,
- &shape->paintbox);
- }
- item->render_opacity = FALSE;
- }
- if ( shape->_stroke.paint.type() == NRArenaShape::Paint::SERVER ) {
- if (gc && gc->parent) {
- shape->stroke_painter = sp_paint_server_painter_new(shape->_stroke.paint.server(),
- gc->transform, gc->parent->transform,
- &shape->paintbox);
- }
- item->render_opacity = FALSE;
- }
- if ( (shape->_fill.paint.type() != NRArenaShape::Paint::NONE &&
- shape->_stroke.paint.type() != NRArenaShape::Paint::NONE)
- || (shape->markers)
- )
- {
- // don't merge item opacity with paint opacity if there is a stroke on the fill, or markers on stroke
- item->render_opacity = FALSE;
- }
+ // to render opacity, use Cairo groups
+ item->render_opacity = FALSE;
+
+ // update patterns when rendering
if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
@@ -745,92 +728,6 @@ cairo_arena_shape_render_outline(cairo_t *ct, NRArenaItem *item, Geom::OptRect a
return item->state;
}
-// cairo stroke rendering (flat color only so far!):
-// works on canvas, but wrongs the colors in nonpremul buffers: icons and png export
-// (need to switch them to premul before this can be enabled)
-void
-cairo_arena_shape_render_stroke(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
- SPStyle const *style = shape->style;
-
- float const scale = shape->ctm.descrim();
-
- if (fabs(shape->_stroke.width * scale) < 0.01)
- return;
-
- cairo_t *ct = nr_create_cairo_context (area, pb);
-
- if (!ct)
- return;
-
- guint32 rgba;
- if ( item->render_opacity ) {
- rgba = shape->_stroke.paint.color().toRGBA32( shape->_stroke.opacity *
- SP_SCALE24_TO_FLOAT(style->opacity.value) );
- } else {
- rgba = shape->_stroke.paint.color().toRGBA32( shape->_stroke.opacity );
- }
-
- // FIXME: we use RGBA buffers but cairo writes BGRA (on i386), so we must cheat
- // by setting color channels in the "wrong" order
- cairo_set_source_rgba(ct, SP_RGBA32_B_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_R_F(rgba), SP_RGBA32_A_F(rgba));
-
- float style_width = MAX(0.125, shape->_stroke.width * scale);
- cairo_set_line_width(ct, style_width);
-
- switch (shape->_stroke.cap) {
- case NRArenaShape::BUTT_CAP:
- cairo_set_line_cap(ct, CAIRO_LINE_CAP_BUTT);
- break;
- case NRArenaShape::ROUND_CAP:
- cairo_set_line_cap(ct, CAIRO_LINE_CAP_ROUND);
- break;
- case NRArenaShape::SQUARE_CAP:
- cairo_set_line_cap(ct, CAIRO_LINE_CAP_SQUARE);
- break;
- }
- switch (shape->_stroke.join) {
- case NRArenaShape::MITRE_JOIN:
- cairo_set_line_join(ct, CAIRO_LINE_JOIN_MITER);
- break;
- case NRArenaShape::ROUND_JOIN:
- cairo_set_line_join(ct, CAIRO_LINE_JOIN_ROUND);
- break;
- case NRArenaShape::BEVEL_JOIN:
- cairo_set_line_join(ct, CAIRO_LINE_JOIN_BEVEL);
- break;
- }
-
- cairo_set_miter_limit (ct, style->stroke_miterlimit.value);
-
- if (style->stroke_dash.n_dash) {
- NRVpathDash dash;
- dash.offset = style->stroke_dash.offset * scale;
- dash.n_dash = style->stroke_dash.n_dash;
- dash.dash = g_new(double, dash.n_dash);
- for (int i = 0; i < dash.n_dash; i++) {
- dash.dash[i] = style->stroke_dash.dash[i] * scale;
- }
- cairo_set_dash (ct, dash.dash, dash.n_dash, dash.offset);
- g_free(dash.dash);
- }
-
- cairo_set_tolerance(ct, 0.1);
- cairo_new_path(ct);
-
- feed_pathvector_to_cairo (ct, shape->curve->get_pathvector(), shape->ctm, to_2geom(area->upgrade()), true, style_width);
-
- cairo_stroke(ct);
-
- cairo_surface_t *cst = cairo_get_target(ct);
- cairo_destroy (ct);
- cairo_surface_finish (cst);
- cairo_surface_destroy (cst);
-
- pb->empty = FALSE;
-}
-
/**
* Renders the item. Markers are just composed into the parent buffer.
*/
@@ -841,9 +738,10 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
if (!shape->curve) return item->state;
if (!shape->style) return item->state;
+ if (!ct) return item->state;
bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
- bool print_colors_preview = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW);
+ //bool print_colors_preview = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW);
if (outline) { // cairo outline rendering
@@ -875,6 +773,121 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
SPStyle const *style = shape->style;
+ // set up context and feed path
+ float opacity = SP_SCALE24_TO_FLOAT(shape->style->opacity.value);
+ bool needs_opacity = ((1.0 - opacity) >= 1e-3);
+
+ cairo_save(ct);
+ //cairo_new_path(ct); // we assume the context is clean
+ cairo_translate(ct, -area->x0, -area->y0);
+ ink_cairo_transform(ct, shape->ctm);
+
+ // update fill and stroke paints.
+ // this cannot be done during nr_arena_shape_update, because we need a Cairo context
+ // to use groups for svg:pattern
+ if (!shape->fill_pattern) {
+ switch (shape->_fill.paint.type()) {
+ case NRArenaShape::Paint::SERVER: {
+ SPPaintServer *ps = shape->_fill.paint.server();
+ shape->fill_pattern = sp_paint_server_create_pattern(ps, ct, &shape->paintbox, shape->_fill.opacity);
+ } break;
+ case NRArenaShape::Paint::COLOR: {
+ SPColor const &c = shape->_fill.paint.color();
+ shape->fill_pattern = cairo_pattern_create_rgba(
+ c.v.c[0], c.v.c[1], c.v.c[2], shape->_fill.opacity);
+ } break;
+ default: break;
+ }
+ }
+
+ if (!shape->stroke_pattern) {
+ switch (shape->_stroke.paint.type()) {
+ case NRArenaShape::Paint::SERVER: {
+ SPPaintServer *ps = shape->_stroke.paint.server();
+ shape->stroke_pattern = sp_paint_server_create_pattern(ps, ct, &shape->paintbox, shape->_stroke.opacity);
+ } break;
+ case NRArenaShape::Paint::COLOR: {
+ SPColor const &c = shape->_stroke.paint.color();
+ shape->stroke_pattern = cairo_pattern_create_rgba(
+ c.v.c[0], c.v.c[1], c.v.c[2], shape->_stroke.opacity);
+ } break;
+ default: break;
+ }
+ }
+
+ if (shape->fill_pattern || shape->stroke_pattern) {
+
+ if (needs_opacity) {
+ cairo_push_group(ct);
+ }
+
+ // TODO: remove segments outside of bbox when no dashes present
+ feed_pathvector_to_cairo(ct, shape->curve->get_pathvector());
+
+ if (shape->fill_pattern) {
+ switch (shape->_fill.rule) {
+ case NRArenaShape::EVEN_ODD:
+ cairo_set_fill_rule(ct, CAIRO_FILL_RULE_EVEN_ODD);
+ break;
+ default:
+ cairo_set_fill_rule(ct, CAIRO_FILL_RULE_WINDING);
+ break;
+ }
+ cairo_set_source(ct, shape->fill_pattern);
+ cairo_fill_preserve(ct);
+ }
+
+ if (shape->stroke_pattern) {
+ // float style_width = shape->_stroke.width * scale;
+ cairo_set_line_width(ct, shape->_stroke.width);
+
+ // stroke caps
+ switch (shape->_stroke.cap) {
+ case NRArenaShape::BUTT_CAP:
+ cairo_set_line_cap(ct, CAIRO_LINE_CAP_BUTT);
+ break;
+ case NRArenaShape::ROUND_CAP:
+ cairo_set_line_cap(ct, CAIRO_LINE_CAP_ROUND);
+ break;
+ case NRArenaShape::SQUARE_CAP:
+ cairo_set_line_cap(ct, CAIRO_LINE_CAP_SQUARE);
+ break;
+ }
+ // stroke join
+ switch (shape->_stroke.join) {
+ case NRArenaShape::MITRE_JOIN:
+ cairo_set_line_join(ct, CAIRO_LINE_JOIN_MITER);
+ break;
+ case NRArenaShape::ROUND_JOIN:
+ cairo_set_line_join(ct, CAIRO_LINE_JOIN_ROUND);
+ break;
+ case NRArenaShape::BEVEL_JOIN:
+ cairo_set_line_join(ct, CAIRO_LINE_JOIN_BEVEL);
+ break;
+ }
+
+ // miter limit
+ cairo_set_miter_limit (ct, style->stroke_miterlimit.value);
+
+ // dashes
+ if (style->stroke_dash.n_dash) {
+ cairo_set_dash (ct, style->stroke_dash.dash, style->stroke_dash.n_dash,
+ style->stroke_dash.offset);
+ }
+ cairo_set_source(ct, shape->stroke_pattern);
+ cairo_stroke_preserve(ct);
+ }
+ cairo_new_path(ct); // clear path
+
+ if (needs_opacity) {
+ cairo_pop_group_to_source(ct);
+ cairo_paint_with_alpha(ct, opacity);
+ }
+ } // has fill or stroke pattern
+
+ cairo_restore(ct);
+
+/*
if (shape->fill_shp) {
NRPixBlock m;
guint32 rgba;
@@ -917,10 +930,11 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
nr_pixblock_release(&m);
}
- if (shape->stroke_shp && shape->_stroke.paint.type() == NRArenaShape::Paint::COLOR) {
+ if (shape->_stroke.paint.type() == NRArenaShape::Paint::COLOR) {
- // cairo_arena_shape_render_stroke(item, area, pb);
+
+
guint32 rgba;
NRPixBlock m;
@@ -951,6 +965,7 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
pb->empty = FALSE;
nr_pixblock_release(&m);
+
} else if (shape->stroke_shp && shape->_stroke.paint.type() == NRArenaShape::Paint::SERVER) {
@@ -973,8 +988,8 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
}
nr_pixblock_release(&m);
- }
-
+ }
+*/
} // non-cairo non-outline branch
/* Render markers into parent buffer */
diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h
index 455757806..a88129286 100644
--- a/src/display/nr-arena-shape.h
+++ b/src/display/nr-arena-shape.h
@@ -115,6 +115,9 @@ struct NRArenaShape : public NRArenaItem {
/* State data */
Geom::Matrix ctm;
+ cairo_pattern_t *fill_pattern;
+ cairo_pattern_t *stroke_pattern;
+
SPPainter *fill_painter;
SPPainter *stroke_painter;
// the 2 cached polygons, for rasterizations uses
diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp
index caa5fa697..c85fb586b 100644
--- a/src/display/sodipodi-ctrl.cpp
+++ b/src/display/sodipodi-ctrl.cpp
@@ -13,6 +13,7 @@
#include "display-forward.h"
#include "sodipodi-ctrl.h"
#include "libnr/nr-pixops.h"
+#include "display/inkscape-cairo.h"
enum {
ARG_0,
@@ -176,11 +177,14 @@ sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
sp_canvas_item_request_update (item);
break;
- case ARG_FILL_COLOR:
- ctrl->fill_color = GTK_VALUE_INT (*arg);
+ case ARG_FILL_COLOR: {
+ // treat colors with zero alpha as opaque
+ guint32 fill = GTK_VALUE_INT (*arg);
+ fill = ((fill & 0xff) == 0 && fill) ? fill | 0xff : fill;
+ ctrl->fill_color = fill;
ctrl->build = FALSE;
sp_canvas_item_request_update (item);
- break;
+ } break;
case ARG_STROKED:
ctrl->stroked = GTK_VALUE_BOOL (*arg);
@@ -188,11 +192,14 @@ sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
sp_canvas_item_request_update (item);
break;
- case ARG_STROKE_COLOR:
- ctrl->stroke_color = GTK_VALUE_INT (*arg);
+ case ARG_STROKE_COLOR: {
+ // treat colors with zero alpha as opaque
+ guint32 stroke = GTK_VALUE_INT (*arg);
+ stroke = ((stroke & 0xff) == 0 && stroke) ? stroke | 0xff : stroke;
+ ctrl->stroke_color = stroke;
ctrl->build = FALSE;
sp_canvas_item_request_update (item);
- break;
+ } break;
case ARG_PIXBUF:
pixbuf = (GdkPixbuf*)(GTK_VALUE_POINTER (*arg));
@@ -298,11 +305,11 @@ sp_ctrl_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item)
static void
sp_ctrl_build_cache (SPCtrl *ctrl)
{
- guchar * p, *q;
- gint size, x, y, z, s, a, side, c;
- guint8 fr, fg, fb, fa, sr, sg, sb, sa;
+ //guchar * p, *q;
+ //int size, x, y, z, s, a, side, c;
+ //guint8 fr, fg, fb, fa, sr, sg, sb, sa;
- if (ctrl->filled) {
+ /*if (ctrl->filled) {
fr = (ctrl->fill_color >> 24) & 0xff;
fg = (ctrl->fill_color >> 16) & 0xff;
fb = (ctrl->fill_color >> 8) & 0xff;
@@ -317,147 +324,85 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
sa = (ctrl->stroke_color) & 0xff;
} else {
sr = fr; sg = fg; sb = fb; sa = fa;
- }
+ }*/
+ int w, h; // for clarity; w and h are always odd
+ w = h = (ctrl->span * 2 +1);
+ int c = ctrl->span ;
- side = (ctrl->span * 2 +1);
- c = ctrl->span ;
- size = (side) * (side) * 4;
- if (side < 2) return;
+ if (ctrl->cache) {
+ cairo_surface_finish(ctrl->cache);
+ cairo_surface_destroy(ctrl->cache);
+ }
+ ctrl->cache = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
+ cairo_t *cr = cairo_create(ctrl->cache);
- if (ctrl->cache)
- g_free (ctrl->cache);
- ctrl->cache = (guchar*)g_malloc (size);
+ bool supress_fill = false;
+ bool supress_paint = false;
switch (ctrl->shape) {
case SP_CTRL_SHAPE_SQUARE:
- p = ctrl->cache;
- for (x=0; x < side; x++) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
- }
- for (y = 2; y < side; y++) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
- for (x=2; x < side; x++) {
- *p++ = fr; *p++ = fg; *p++ = fb; *p++ = fa;
- }
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
- }
- for (x=0; x < side; x++) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
- }
+ cairo_rectangle(cr, 0, 0, w, h);
ctrl->build = TRUE;
break;
case SP_CTRL_SHAPE_DIAMOND:
- p = ctrl->cache;
- for (y = 0; y < side; y++) {
- z = abs (c - y);
- for (x = 0; x < z; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
- }
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;
- for (; x < side - z -1; x++) {
- *p++ = fr; *p++ = fg; *p++ = fb; *p++ = fa;
- }
- if (z != c) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;
- }
- for (; x < side; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
- }
- }
+ cairo_move_to(cr, c, 0); // c stands for "center" - it is half of the width / height
+ cairo_line_to(cr, w, c);
+ cairo_line_to(cr, c, h);
+ cairo_line_to(cr, 0, c);
+ cairo_close_path(cr);
+ ctrl->build = TRUE;
break;
case SP_CTRL_SHAPE_CIRCLE:
- p = ctrl->cache;
- q = p + size -1;
- s = -1;
- for (y = 0; y <= c ; y++) {
- a = abs (c - y);
- z = (gint)(0.0 + sqrt ((c+.4)*(c+.4) - a*a));
- x = 0;
- while (x < c-z) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
- *q-- = 0x00; *q-- = 0x00; *q-- = 0x00; *q-- = 0x00;
- x++;
- }
- do {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
- *q-- = sa; *q-- = sb; *q-- = sg; *q-- = sr;
- x++;
- } while (x < c-s);
- while (x < MIN(c+s+1, c+z)) {
- *p++ = fr; *p++ = fg; *p++ = fb; *p++ = fa;
- *q-- = fa; *q-- = fb; *q-- = fg; *q-- = fr;
- x++;
- }
- do {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
- *q-- = sa; *q-- = sb; *q-- = sg; *q-- = sr;
- x++;
- } while (x <= c+z);
- while (x < side) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
- *q-- = 0x00; *q-- = 0x00; *q-- = 0x00; *q-- = 0x00;
- x++;
- }
- s = z;
- }
+ cairo_arc(cr, 0.5+c, 0.5+c, c, 0, 2*M_PI);
+ cairo_close_path(cr);
ctrl->build = TRUE;
break;
case SP_CTRL_SHAPE_CROSS:
- p = ctrl->cache;
- for (y = 0; y < side; y++) {
- z = abs (c - y);
- for (x = 0; x < c-z; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
- }
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;
- for (; x < c + z; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
- }
- if (z != 0) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;
- }
- for (; x < side; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
- }
- }
+ cairo_move_to(cr, 0.5+c, 0); // top stroke
+ cairo_line_to(cr, 0.5+c, c);
+ cairo_move_to(cr, w, 0.5+c); // right stroke
+ cairo_line_to(cr, w, c+1);
+ cairo_move_to(cr, 0.5+c, h); // bottom stroke
+ cairo_line_to(cr, 0.5+c, c+1);
+ cairo_move_to(cr, 0, 0.5+c); // left stroke
+ cairo_line_to(cr, c, 0.5+c);
+ supress_fill = true;
ctrl->build = TRUE;
break;
case SP_CTRL_SHAPE_BITMAP:
if (ctrl->pixbuf) {
- unsigned char *px;
- unsigned int rs;
- px = gdk_pixbuf_get_pixels (ctrl->pixbuf);
- rs = gdk_pixbuf_get_rowstride (ctrl->pixbuf);
- for (y = 0; y < side; y++){
- unsigned char *s, *d;
- s = px + y * rs;
- d = ctrl->cache + 4 * side * y;
- for (x = 0; x < side; x++) {
- if (s[3] < 0x80) {
- d[0] = 0x00;
- d[1] = 0x00;
- d[2] = 0x00;
- d[3] = 0x00;
- } else if (s[0] < 0x80) {
- d[0] = sr;
- d[1] = sg;
- d[2] = sb;
- d[3] = sa;
+ gdk_cairo_set_source_pixbuf(cr, ctrl->pixbuf, 0, 0);
+ cairo_paint(cr);
+ cairo_surface_flush(ctrl->cache);
+
+ // TODO lame!!! find a way to do this without direct pixel manipulation.
+ int stride = cairo_image_surface_get_stride(ctrl->cache);
+ guint32 *px = reinterpret_cast<guint32*>(cairo_image_surface_get_data(ctrl->cache));
+
+ // fix byte order. fill_color is 0xrrggbbaa, cairo needs 0xaarrggbb.
+ // both quantities are native-endian, so it should be portable.
+ guint32 fill = ctrl->fill_color;
+ guint32 stroke = ctrl->stroke_color;
+ fill = ((fill & 0xff) << 24) | ((fill & 0xffffff00) >> 8);
+ stroke = ((stroke & 0xff) << 24) | ((stroke & 0xffffff00) >> 8);
+
+ for (int i = 0; i < h; ++i) {
+ for (int j = 0; j < w; ++j) {
+ int index = i * stride / 4 + j;
+ if (px[index] & 0xff000000) {
+ px[index] = px[index] ? stroke : fill;
} else {
- d[0] = fr;
- d[1] = fg;
- d[2] = fb;
- d[3] = fa;
+ px[index] = 0;
}
- s += 4;
- d += 4;
}
}
+ cairo_surface_mark_dirty(ctrl->cache);
+ supress_paint = true;
} else {
g_print ("control has no pixmap\n");
}
@@ -466,19 +411,9 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
case SP_CTRL_SHAPE_IMAGE:
if (ctrl->pixbuf) {
- guint r = gdk_pixbuf_get_rowstride (ctrl->pixbuf);
- guchar * pix;
- q = gdk_pixbuf_get_pixels (ctrl->pixbuf);
- p = ctrl->cache;
- for (y = 0; y < side; y++){
- pix = q + (y * r);
- for (x = 0; x < side; x++) {
- *p++ = *pix++;
- *p++ = *pix++;
- *p++ = *pix++;
- *p++ = *pix++;
- }
- }
+ gdk_cairo_set_source_pixbuf(cr, ctrl->pixbuf, 0, 0);
+ cairo_paint(cr);
+ supress_paint = true;
} else {
g_print ("control has no pixmap\n");
}
@@ -489,6 +424,20 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
break;
}
+ if (ctrl->build && !supress_paint) {
+ if (ctrl->filled && !supress_fill) {
+ ink_cairo_set_source_rgba32(cr, ctrl->fill_color);
+ cairo_fill_preserve(cr);
+ }
+ if (ctrl->stroked) {
+ ink_cairo_set_source_rgba32(cr, ctrl->stroke_color);
+ cairo_set_line_width(cr, 2);
+ cairo_clip_preserve(cr);
+ cairo_stroke(cr);
+ }
+ }
+
+ cairo_destroy(cr);
}
// composite background, foreground, alpha for xor mode
@@ -499,29 +448,74 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
static void
sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf)
{
- gint y0, y1, y, x0,x1,x;
- guchar *p, *q, a;
+ //gint y0, y1, y, x0,x1,x;
+ //guchar *p, *q, a;
SPCtrl *ctrl = SP_CTRL (item);
if (!ctrl->defined) return;
if ((!ctrl->filled) && (!ctrl->stroked)) return;
- sp_canvas_prepare_buffer (buf);
-
// the control-image is rendered into ctrl->cache
if (!ctrl->build) {
sp_ctrl_build_cache (ctrl);
}
+ cairo_set_source_surface(buf->ct, ctrl->cache,
+ ctrl->box.x0 - buf->rect.x0, ctrl->box.y0 - buf->rect.y0);
+ cairo_paint(buf->ct);
+
+ /*
+ double x0 = ctrl->box.x0;
+ double y0 = ctrl->box.y0;
+ double w = ctrl->box.x1 - ctrl->box.x0 + 1;
+ double h = ctrl->box.y1 - ctrl->box.y0 + 1;
+ //guint32 fill = ctrl->fill_color;
+ //fill = (fill & 0xff == 0 && fill) ? fill | 0xff : fill;
+
+
+ switch (ctrl->shape) {
+ case SP_CTRL_SHAPE_SQUARE:
+ cairo_rectangle(buf->ct, x0, y0, w, h);
+ break;
+ case SP_CTRL_SHAPE_DIAMOND:
+ cairo_move_to(buf->ct, x0 + w/2, y0);
+ cairo_line_to(buf->ct, x0 + w, y0 + h/2);
+ cairo_line_to(buf->ct, x0 + w/2, y0 + h);
+ cairo_line_to(buf->ct, x0, y0 + h/2);
+ cairo_close_path(buf->ct);
+ break;
+ //case SP_CTRL_SHAPE_CIRCLE:
+ default:
+ cairo_arc(buf->ct, x0 + w/2, y0 + h/2, w/2, 0, 2*M_PI);
+ cairo_close_path(buf->ct);
+ break;
+ }
+
+ //if (ctrl->mode == SP_CTRL_MODE_XOR) {
+ // cairo_set_operator(buf->ct, CAIRO_OPERATOR_XOR);
+ //}
+ if (ctrl->filled) {
+ ink_cairo_set_source_rgba32(buf->ct, ctrl->fill_color);
+ cairo_fill_preserve(buf->ct);
+ }
+ if (ctrl->stroked) {
+ ink_cairo_set_source_rgba32(buf->ct, ctrl->stroke_color);
+ cairo_set_line_width(buf->ct, 2);
+ cairo_clip_preserve(buf->ct);
+ cairo_stroke_preserve(buf->ct);
+ }
+
+ cairo_new_path(buf->ct);
+ cairo_restore(buf->ct);*/
+
+ #if 0
// then we render from ctrl->cache
y0 = MAX (ctrl->box.y0, buf->rect.y0);
y1 = MIN (ctrl->box.y1, buf->rect.y1 - 1);
x0 = MAX (ctrl->box.x0, buf->rect.x0);
x1 = MIN (ctrl->box.x1, buf->rect.x1 - 1);
- bool colormode;
-
for (y = y0; y <= y1; y++) {
p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 4;
q = ctrl->cache + ((y - ctrl->box.y0) * (ctrl->span*2+1) + (x0 - ctrl->box.x0)) * 4;
@@ -548,6 +542,7 @@ sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf)
}
}
}
+ #endif
ctrl->shown = TRUE;
}
diff --git a/src/display/sodipodi-ctrl.h b/src/display/sodipodi-ctrl.h
index 859735e4f..ed4db27fe 100644
--- a/src/display/sodipodi-ctrl.h
+++ b/src/display/sodipodi-ctrl.h
@@ -50,7 +50,7 @@ struct SPCtrl : public SPCanvasItem{
bool _moved;
NRRectL box; /* NB! x1 & y1 are included */
- guchar *cache;
+ cairo_surface_t *cache;
GdkPixbuf * pixbuf;
void moveto(Geom::Point const p);
diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp
index dcd6dc0a6..09bfde6fb 100644
--- a/src/display/sodipodi-ctrlrect.cpp
+++ b/src/display/sodipodi-ctrlrect.cpp
@@ -18,7 +18,7 @@
#include "display-forward.h"
#include "sp-canvas-util.h"
#include "sodipodi-ctrlrect.h"
-#include "libnr/nr-pixops.h"
+#include "display/inkscape-cairo.h"
/*
* Currently we do not have point method, as it should always be painted
@@ -84,7 +84,7 @@ static void sp_ctrlrect_destroy(GtkObject *object)
(* GTK_OBJECT_CLASS(parent_class)->destroy)(object);
}
}
-
+#if 0
/* FIXME: use definitions from somewhere else */
#define RGBA_R(v) ((v) >> 24)
#define RGBA_G(v) (((v) >> 16) & 0xff)
@@ -154,6 +154,7 @@ static void sp_ctrlrect_area(SPCanvasBuf *buf, gint xs, gint ys, gint xe, gint y
}
}
}
+#endif
static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf)
{
@@ -189,13 +190,38 @@ void CtrlRect::init()
void CtrlRect::render(SPCanvasBuf *buf)
{
+ static double const dashes[2] = {4.0, 4.0};
+
if ((_area.x0 != 0 || _area.x1 != 0 || _area.y0 != 0 || _area.y1 != 0) &&
(_area.x0 < buf->rect.x1) &&
(_area.y0 < buf->rect.y1) &&
((_area.x1 + _shadow_size) >= buf->rect.x0) &&
- ((_area.y1 + _shadow_size) >= buf->rect.y0)) {
- sp_canvas_prepare_buffer(buf);
+ ((_area.y1 + _shadow_size) >= buf->rect.y0))
+ {
+ cairo_save(buf->ct);
+ cairo_translate(buf->ct, -buf->rect.x0, -buf->rect.y0);
+ cairo_set_line_width(buf->ct, 1);
+ if (_dashed) cairo_set_dash(buf->ct, dashes, 2, 0);
+ cairo_rectangle(buf->ct, 0.5 + _area.x0, 0.5 + _area.y0,
+ _area.x1 - _area.x0, _area.y1 - _area.y0);
+ if (_has_fill) {
+ ink_cairo_set_source_rgba32(buf->ct, _fill_color);
+ cairo_fill_preserve(buf->ct);
+ }
+ ink_cairo_set_source_rgba32(buf->ct, _border_color);
+ cairo_stroke(buf->ct);
+
+ if (_shadow_size > 0) {
+ ink_cairo_set_source_rgba32(buf->ct, _shadow_color);
+ cairo_rectangle(buf->ct, 1 + _area.x1, _area.y0 + _shadow_size,
+ _shadow_size, _area.y1 - _area.y0 + 1); // right shadow
+ cairo_rectangle(buf->ct, _area.x0 + _shadow_size, 1 + _area.y1,
+ _area.x1 - _area.x0 - _shadow_size + 1, _shadow_size);
+ cairo_fill(buf->ct);
+ }
+ cairo_restore(buf->ct);
+#if 0
/* Top */
sp_ctrlrect_hline(buf, _area.y0, _area.x0, _area.x1, _border_color, _dashed);
/* Bottom */
@@ -217,6 +243,7 @@ void CtrlRect::render(SPCanvasBuf *buf)
sp_ctrlrect_area(buf, _area.x0 + 1, _area.y0 + 1,
_area.x1 - 1, _area.y1 - 1, _fill_color);
}
+#endif
}
}
diff --git a/src/display/sp-canvas-util.cpp b/src/display/sp-canvas-util.cpp
index a23b157df..970fea0e5 100644
--- a/src/display/sp-canvas-util.cpp
+++ b/src/display/sp-canvas-util.cpp
@@ -43,36 +43,11 @@ void
sp_canvas_prepare_buffer (SPCanvasBuf *buf)
{
if (buf->is_empty) {
- sp_canvas_clear_buffer(buf);
- buf->is_empty = false;
- }
-}
-
-void
-sp_canvas_clear_buffer (SPCanvasBuf *buf)
-{
- unsigned char r, g, b;
-
- r = (buf->bg_color >> 16) & 0xff;
- g = (buf->bg_color >> 8) & 0xff;
- b = buf->bg_color & 0xff;
-
- if ((r != g) || (r != b)) {
- int x, y;
- for (y = buf->rect.y0; y < buf->rect.y1; y++) {
- unsigned char *p;
- p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride;
- for (x = buf->rect.x0; x < buf->rect.x1; x++) {
- *p++ = r;
- *p++ = g;
- *p++ = b;
- }
- }
- } else {
int y;
for (y = buf->rect.y0; y < buf->rect.y1; y++) {
- memset (buf->buf + (y - buf->rect.y0) * buf->buf_rowstride, r, 4 * (buf->rect.x1 - buf->rect.x0));
+ memset (buf->buf + (y - buf->rect.y0) * buf->buf_rowstride, 0, 4 * (buf->rect.x1 - buf->rect.x0));
}
+ buf->is_empty = false;
}
}
diff --git a/src/display/sp-canvas-util.h b/src/display/sp-canvas-util.h
index 4708126e5..e86eeba20 100644
--- a/src/display/sp-canvas-util.h
+++ b/src/display/sp-canvas-util.h
@@ -21,11 +21,6 @@ void sp_canvas_update_bbox (SPCanvasItem *item, int x1, int y1, int x2, int y2);
void sp_canvas_item_reset_bounds (SPCanvasItem *item);
void sp_canvas_prepare_buffer (SPCanvasBuf *buf);
-/* fill buffer with background color */
-
-void
-sp_canvas_clear_buffer (SPCanvasBuf * buf);
-
/* get i2p (item to parent) affine transformation as general 6-element array */
Geom::Matrix sp_canvas_item_i2p_affine (SPCanvasItem * item);
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index c6778c8c5..29a5cd740 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -1649,18 +1649,32 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1,
buf.visible_rect.y0 = draw_y1;
buf.visible_rect.x1 = draw_x2;
buf.visible_rect.y1 = draw_y2;
- GdkColor *color = &widget->style->bg[GTK_STATE_NORMAL];
- buf.bg_color = (((color->red & 0xff00) << 8)
- | (color->green & 0xff00)
- | (color->blue >> 8));
buf.is_empty = true;
-
- buf.ct = nr_create_cairo_context_canvasbuf (&(buf.visible_rect), &buf);
+ //buf.bg_color = &widget->style->bg[GTK_STATE_NORMAL];
+ //buf.ct = nr_create_cairo_context_canvasbuf (&(buf.visible_rect), &buf);
+ buf.ct = gdk_cairo_create(widget->window);
+
+ // fix coordinates, clip all drawing to the tile and clear the background
+ // TODO: the translation is done to remain compatible with legacy code.
+ // Fix the code so it doesn't refer to buf.rect and remove the translation.
+ cairo_translate(buf.ct, x0 - canvas->x0, y0 - canvas->y0); // ?
+ cairo_rectangle(buf.ct, 0, 0, x1 - x0, y1 - y0);
+ //cairo_set_line_width(buf.ct, 3);
+ //cairo_set_source_rgba(buf.ct, 1.0, 0.0, 0.0, 0.1);
+ //cairo_stroke_preserve(buf.ct);
+ cairo_clip(buf.ct);
+
+ gdk_cairo_set_source_color(buf.ct, &widget->style->bg[GTK_STATE_NORMAL]);
+ cairo_set_operator(buf.ct, CAIRO_OPERATOR_SOURCE);
+ //cairo_rectangle(buf.ct, 0, 0, x1 - x0, y1 - y0);
+ cairo_paint(buf.ct);
+ cairo_set_operator(buf.ct, CAIRO_OPERATOR_OVER);
if (canvas->root->flags & SP_CANVAS_ITEM_VISIBLE) {
SP_CANVAS_ITEM_GET_CLASS (canvas->root)->render (canvas->root, &buf);
}
+#if 0
#if ENABLE_LCMS
cmsHTRANSFORM transf = 0;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -1702,22 +1716,22 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1,
// use gdk_draw_rgb_image_dithalign, for unfortunately gdk can only handle 24 bpp, which cairo
// cannot handle at all. Still, this way is currently faster even despite the blit with squeeze.
-///#define CANVAS_OUTPUT_VIA_CAIRO
+//#define CANVAS_OUTPUT_VIA_CAIRO
#ifdef CANVAS_OUTPUT_VIA_CAIRO
- buf.cst = cairo_image_surface_create_for_data (
+ cairo_surface_t *cst = cairo_image_surface_create_for_data (
buf.buf,
CAIRO_FORMAT_ARGB32, // unpacked, i.e. 32 bits! one byte is unused
x1 - x0, y1 - y0,
buf.buf_rowstride
);
cairo_t *window_ct = gdk_cairo_create(SP_CANVAS_WINDOW (canvas));
- cairo_set_source_surface (window_ct, buf.cst, x0 - canvas->x0, y0 - canvas->y0);
+ cairo_set_source_surface (window_ct, cst, x0 - canvas->x0, y0 - canvas->y0);
cairo_paint (window_ct);
cairo_destroy (window_ct);
- cairo_surface_finish (buf.cst);
- cairo_surface_destroy (buf.cst);
+ cairo_surface_finish (cst);
+ cairo_surface_destroy (cst);
#else
@@ -1746,11 +1760,12 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1,
nr_pixblock_release (&b4);
#endif
}
+#endif
- cairo_surface_t *cst = cairo_get_target(buf.ct);
+ //cairo_surface_t *cst = cairo_get_target(buf.ct);
cairo_destroy (buf.ct);
- cairo_surface_finish (cst);
- cairo_surface_destroy (cst);
+ //cairo_surface_finish (cst);
+ //cairo_surface_destroy (cst);
if (canvas->rendermode != Inkscape::RENDERMODE_OUTLINE) {
nr_pixelstore_256K_free (buf.buf);
@@ -1816,11 +1831,21 @@ sp_canvas_paint_rect_internal (PaintRectSetup const *setup, NRRectL this_rect)
if (bw * bh < setup->max_pixels) {
// We are small enough
+ GdkRectangle r;
+ r.x = this_rect.x0 - setup->canvas->x0;
+ r.y = this_rect.y0 - setup->canvas->y0;
+ r.width = this_rect.x1 - this_rect.x0;
+ r.height = this_rect.y1 - this_rect.y0;
+
+ GdkWindow *window = GTK_WIDGET(setup->canvas)->window;
+ gdk_window_begin_paint_rect(window, &r);
+
sp_canvas_paint_single_buffer (setup->canvas,
this_rect.x0, this_rect.y0,
this_rect.x1, this_rect.y1,
setup->big_rect.x0, setup->big_rect.y0,
setup->big_rect.x1, setup->big_rect.y1, bw);
+ gdk_window_end_paint(window);
return 1;
}
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index a2af080ef..6a2ee074e 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -52,18 +52,16 @@ enum {
};
/**
- * The canvas buf contains the actual pixels.
+ * Structure used when rendering canvas items.
*/
-struct SPCanvasBuf{
- guchar *buf;
- int buf_rowstride;
+struct SPCanvasBuf {
+ cairo_t *ct;
NRRectL rect;
NRRectL visible_rect;
- /// Background color, given as 0xrrggbb
- guint32 bg_color;
- // If empty, ignore contents of buffer and use a solid area of bg_color
+
+ unsigned char *buf;
+ int buf_rowstride;
bool is_empty;
- cairo_t *ct;
};
/**
diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp
index 033c8d1f8..043736d94 100644
--- a/src/display/sp-ctrlline.cpp
+++ b/src/display/sp-ctrlline.cpp
@@ -106,11 +106,7 @@ sp_ctrlline_render (SPCanvasItem *item, SPCanvasBuf *buf)
if (cl->s == cl->e)
return;
- sp_canvas_prepare_buffer (buf);
-
- guint32 rgba = cl->rgba;
- cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_R_F(rgba), SP_RGBA32_A_F(rgba));
-
+ ink_cairo_set_source_rgba32(buf->ct, cl->rgba);
cairo_set_line_width(buf->ct, 1);
cairo_new_path(buf->ct);