summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-07-07 16:41:53 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2010-07-07 16:41:53 +0000
commitb986b0fb26a23899a51e564ef07880a0166680cc (patch)
treec1b53cbeaecca62d602ba1ecb15ea11d148c8f86 /src
parentRemove some cruft (diff)
downloadinkscape-b986b0fb26a23899a51e564ef07880a0166680cc.tar.gz
inkscape-b986b0fb26a23899a51e564ef07880a0166680cc.zip
Smaller intermediate rendering regions
(bzr r9508.1.11)
Diffstat (limited to 'src')
-rw-r--r--src/display/cairo-utils.cpp2
-rw-r--r--src/display/nr-arena-image.cpp4
-rw-r--r--src/display/nr-arena-item.cpp61
-rw-r--r--src/display/nr-filter.cpp2
-rw-r--r--src/display/nr-filter.h3
5 files changed, 52 insertions, 20 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index 7bfdd7dd7..8aaf838ed 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -413,7 +413,7 @@ convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int stride)
* using it with GTK will result in corrupted drawings.
*/
void
-convert_pixbuf_normal_to_argb32_mutant(GdkPixbuf *pb)
+convert_pixbuf_normal_to_argb32(GdkPixbuf *pb)
{
convert_pixels_pixbuf_to_argb32(
gdk_pixbuf_get_pixels(pb),
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
index 9f883a77c..f198b176b 100644
--- a/src/display/nr-arena-image.cpp
+++ b/src/display/nr-arena-image.cpp
@@ -203,9 +203,7 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
} else { // outline; draw a rect instead
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
guint32 rgba = prefs->getInt("/options/wireframecolors/images", 0xff0000ff);
- // 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));
+ ink_cairo_set_source_rgba32(ct, rgba);
cairo_set_line_width(ct, 0.5);
cairo_new_path(ct);
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index 08fbe1f1c..338940fb6 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -335,6 +335,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
if (!item->visible)
return item->state | NR_ARENA_ITEM_STATE_RENDER;
+ // carea is the bounding box for intermediate rendering.
NRRectL carea;
nr_rect_l_intersect (&carea, area, &item->drawbox);
if (nr_rect_l_test_empty(carea))
@@ -564,27 +565,46 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
// clipping and masks
unsigned int state;
- Cairo::Context cct(ct);
+
+ cairo_t *this_ct = ct;
+ NRRectL *this_area = const_cast<NRRectL*>(area);
+
+ bool needs_intermediate_rendering = false;
+ bool &nir = needs_intermediate_rendering;
+
+ // this item needs an intermediate rendering if:
+ nir |= (item->mask != NULL); // 1. it has a mask
+ nir |= (item->filter != NULL && filter); // 2. it has a filter
+
+ if (needs_intermediate_rendering) {
+ cairo_surface_t *intermediate = cairo_surface_create_similar(
+ cairo_get_target(ct), CAIRO_CONTENT_COLOR_ALPHA,
+ carea.x1 - carea.x0, carea.y1 - carea.y0);
+ this_ct = cairo_create(intermediate);
+ this_area = &carea;
+ cairo_surface_destroy(intermediate); // the surface will be held in memory by this_ct
+ }
+
+ Cairo::Context cct(this_ct);
Cairo::RefPtr<Cairo::Pattern> mask;
- CairoSave clipsave(ct); // RAII for save / restore
- CairoGroup maskgroup(ct); // RAII for push_group / pop_group
- CairoGroup drawgroup(ct);
+ CairoSave clipsave(this_ct); // RAII for save / restore
+ CairoGroup maskgroup(this_ct); // RAII for push_group / pop_group
+ CairoGroup drawgroup(this_ct);
- if (item->clip) {
+ if (item->clip && !(item->filter && filter)) {
clipsave.save();
- state = nr_arena_item_invoke_clip(ct, item->clip, const_cast<NRRectL*>(area));
+ state = nr_arena_item_invoke_clip(this_ct, item->clip, this_area);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
}
-
cct.clip();
}
if (item->mask) {
maskgroup.push_with_content(CAIRO_CONTENT_ALPHA);
- state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, const_cast<NRRectL*>(area), pb, flags);
+ state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (this_ct, item->mask, this_area, pb, flags);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
@@ -592,18 +612,31 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
mask = maskgroup.popmm();
}
- if (mask) {
+ /*if (mask) {
drawgroup.push();
- }
- state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, const_cast<NRRectL*>(area), pb, flags);
+ }*/
+ state = NR_ARENA_ITEM_VIRTUAL (item, render) (this_ct, item, this_area, pb, flags);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
/* Clean up and return error */
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
}
- if (mask) {
- drawgroup.pop_to_source();
- cct.mask(mask);
+ if (needs_intermediate_rendering) {
+ cairo_surface_t *intermediate = cairo_get_target(this_ct);
+ cairo_set_source_surface(ct, intermediate, carea.x0 - area->x0, carea.y0 - area->y0);
+ if (mask) {
+ // bring mask into the coordinate system of ct
+ cairo_pattern_t *cmask = mask->cobj();
+ cairo_matrix_t m;
+ cairo_pattern_get_matrix(cmask, &m);
+ cairo_matrix_translate(&m, area->x0 - carea.x0, area->y0 - carea.y0);
+ cairo_pattern_set_matrix(cmask, &m);
+ cairo_mask(ct, cmask);
+ } else {
+ cairo_paint(ct);
+ }
+ cairo_set_source_rgba(ct,0,0,0,0);
+ cairo_destroy(this_ct);
}
return item->state | NR_ARENA_ITEM_STATE_RENDER;
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index 3b19ff69b..24079be4e 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -129,7 +129,7 @@ Filter::~Filter()
}
-int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
+int Filter::render(NRArenaItem const *item, NRPixBlock *pb, cairo_t *ct)
{
if (!_primitive[0]) {
// TODO: Should clear the input buffer instead of just returning
diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h
index 318e1030f..08d0254d1 100644
--- a/src/display/nr-filter.h
+++ b/src/display/nr-filter.h
@@ -13,6 +13,7 @@
*/
//#include "display/nr-arena-item.h"
+#include <cairo.h>
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-types.h"
#include "libnr/nr-pixblock.h"
@@ -29,7 +30,7 @@ namespace Filters {
class Filter : public Inkscape::GC::Managed<> {
public:
- int render(NRArenaItem const *item, NRPixBlock *pb);
+ int render(NRArenaItem const *item, NRPixBlock *pb, cairo_t *ct);
/**
* Creates a new filter primitive under this filter object.