diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2010-07-07 16:41:53 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2010-07-07 16:41:53 +0000 |
| commit | b986b0fb26a23899a51e564ef07880a0166680cc (patch) | |
| tree | c1b53cbeaecca62d602ba1ecb15ea11d148c8f86 /src | |
| parent | Remove some cruft (diff) | |
| download | inkscape-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.cpp | 2 | ||||
| -rw-r--r-- | src/display/nr-arena-image.cpp | 4 | ||||
| -rw-r--r-- | src/display/nr-arena-item.cpp | 61 | ||||
| -rw-r--r-- | src/display/nr-filter.cpp | 2 | ||||
| -rw-r--r-- | src/display/nr-filter.h | 3 |
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. |
