From: Jasper van de Gronde
Date: Wed, 4 Aug 2010 12:51:48 +0000 (+0200)
Subject: Fix to background handling that avoids both duplication and aliasing as much as possible.
X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=9bf80f42b0d99fc1bff5461a563d9fa2b5f81082;p=inkscape.git
Fix to background handling that avoids both duplication and aliasing as much as possible.
---
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index b80df7273..3b8dceb93 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -323,8 +323,11 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
item->state);
#ifdef NR_ARENA_ITEM_VERBOSE
- printf ("Invoke render %p: %d %d - %d %d\n", item, area->x0, area->y0,
- area->x1, area->y1);
+ g_message ("Invoke render %p on %p: %d %d - %d %d, %d %d - %d %d", item, pb,
+ area->x0, area->y0,
+ area->x1, area->y1,
+ item->drawbox.x0, item->drawbox.y0,
+ item->drawbox.x1, item->drawbox.y1);
#endif
/* If we are invisible, just return successfully */
@@ -415,8 +418,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
/* Determine, whether we need temporary buffer */
if (item->clip || item->mask
|| ((item->opacity != 255) && !item->render_opacity)
- || (item->filter && filter) || item->background_new
- || (item->parent && item->parent->background_pb)) {
+ || (item->filter && filter) || item->background_new) {
/* Setup and render item buffer */
NRPixBlock ipb;
@@ -432,8 +434,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
/* If background access is used, save the pixblock address.
* This address is set to NULL at the end of this block */
- if (item->background_new ||
- (item->parent && item->parent->background_pb)) {
+ if (item->background_new) {
item->background_pb = &ipb;
}
@@ -859,29 +860,15 @@ nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect &bbox)
/** Returns a background image for use with filter effects. */
NRPixBlock *
-nr_arena_item_get_background (NRArenaItem const *item, int depth)
+nr_arena_item_get_background (NRArenaItem const *item)
{
- NRPixBlock *pb;
- if (!item->background_pb)
- return NULL;
if (item->background_new) {
- pb = new NRPixBlock ();
- nr_pixblock_setup_fast (pb, item->background_pb->mode,
- item->background_pb->area.x0,
- item->background_pb->area.y0,
- item->background_pb->area.x1,
- item->background_pb->area.y1, true);
- if (pb->size != NR_PIXBLOCK_SIZE_TINY && pb->data.px == NULL) // allocation failed
- return NULL;
+ return item->background_pb;
} else if (item->parent) {
- pb = nr_arena_item_get_background (item->parent, depth + 1);
- } else
+ return nr_arena_item_get_background (item->parent);
+ } else {
return NULL;
-
- if (depth > 0)
- nr_blit_pixblock_pixblock (pb, item->background_pb);
-
- return pb;
+ }
}
/* Helpers */
diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h
index 2faa7d2d0..e92fb1313 100644
--- a/src/display/nr-arena-item.h
+++ b/src/display/nr-arena-item.h
@@ -181,7 +181,7 @@ void nr_arena_item_set_mask (NRArenaItem *item, NRArenaItem *mask);
void nr_arena_item_set_order (NRArenaItem *item, int order);
void nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect &bbox);
-NRPixBlock *nr_arena_item_get_background (NRArenaItem const *item, int depth = 0);
+NRPixBlock *nr_arena_item_get_background (NRArenaItem const *item);
/* Helpers */
diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp
index 7df9ab979..354b31b4d 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -70,26 +70,22 @@ FilterSlot::FilterSlot(int slots, NRArenaItem const *item)
blurquality(BLUR_QUALITY_BEST),
_arena_item(item)
{
- _slot_count = ((slots > 0) ? slots : 2);
- _slot = new NRPixBlock*[_slot_count];
- _slot_number = new int[_slot_count];
-
- for (int i = 0 ; i < _slot_count ; i++) {
- _slot[i] = NULL;
- _slot_number[i] = NR_FILTER_SLOT_NOT_SET;
- }
+ _slots.reserve((slots > 0) ? slots : 2);
}
FilterSlot::~FilterSlot()
{
- for (int i = 0 ; i < _slot_count ; i++) {
- if (_slot[i]) {
- nr_pixblock_release(_slot[i]);
- delete _slot[i];
+ for (unsigned int i = 0 ; i < _slots.size() ; i++) {
+ if (_slots[i].owned) {
+ nr_pixblock_release(_slots[i].pb);
+ delete _slots[i].pb;
}
}
- delete[] _slot;
- delete[] _slot_number;
+}
+
+FilterSlot::slot_entry_t::~slot_entry_t()
+{
+ // It's a bad idea to destruct pixblocks here, as this will also be called upon resizing _slots
}
NRPixBlock *FilterSlot::get(int slot_nr)
@@ -99,7 +95,7 @@ NRPixBlock *FilterSlot::get(int slot_nr)
/* If we didn't have the specified image, but we could create it
* from the other information we have, let's do that */
- if (_slot[index] == NULL
+ if (_slots[index].pb == NULL
&& (slot_nr == NR_FILTER_SOURCEALPHA
|| slot_nr == NR_FILTER_BACKGROUNDIMAGE
|| slot_nr == NR_FILTER_BACKGROUNDALPHA
@@ -112,7 +108,7 @@ NRPixBlock *FilterSlot::get(int slot_nr)
pb = nr_arena_item_get_background(_arena_item);
if (pb) {
pb->empty = false;
- this->set(NR_FILTER_BACKGROUNDIMAGE, pb);
+ this->set(NR_FILTER_BACKGROUNDIMAGE, pb, false);
} else {
NRPixBlock *source = this->get(NR_FILTER_SOURCEGRAPHIC);
pb = new NRPixBlock();
@@ -145,12 +141,12 @@ NRPixBlock *FilterSlot::get(int slot_nr)
}
}
- if (_slot[index]) {
- _slot[index]->empty = false;
+ if (_slots[index].pb) {
+ _slots[index].pb->empty = false;
}
- assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slot_number[index] == slot_nr);
- return _slot[index];
+ assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slots[index].number == slot_nr);
+ return _slots[index].pb;
}
void FilterSlot::get_final(int slot_nr, NRPixBlock *result) {
@@ -175,7 +171,7 @@ void FilterSlot::get_final(int slot_nr, NRPixBlock *result) {
}
}
-void FilterSlot::set(int slot_nr, NRPixBlock *pb)
+void FilterSlot::set(int slot_nr, NRPixBlock *pb, bool takeOwnership)
{
/* Unnamed slot is for saving filter primitive results, when parameter
* 'result' is not set. Only the filter immediately after this one
@@ -189,7 +185,7 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb)
assert(index >= 0);
// Unnamed slot is only for Inkscape::Filters::FilterSlot internal use.
assert(slot_nr != NR_FILTER_UNNAMED_SLOT);
- assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slot_number[index] == slot_nr);
+ assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slots[index].number == slot_nr);
if (slot_nr == NR_FILTER_SOURCEGRAPHIC || slot_nr == NR_FILTER_BACKGROUNDIMAGE) {
Geom::Matrix trans = units.get_matrix_display2pb();
@@ -225,6 +221,10 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb)
* is not too high, but can get thousands of pixels wide.
* Rotate this 45 degrees -> _huge_ image */
g_warning("Memory allocation failed in Inkscape::Filters::FilterSlot::set (transform)");
+ if (takeOwnership) {
+ nr_pixblock_release(pb);
+ delete pb;
+ }
return;
}
if (filterquality == FILTER_QUALITY_BEST) {
@@ -232,8 +232,11 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb)
} else {
NR::transform_nearest(trans_pb, pb, trans);
}
- nr_pixblock_release(pb);
- delete pb;
+ if (takeOwnership) {
+ nr_pixblock_release(pb);
+ delete pb;
+ }
+ takeOwnership = true;
pb = trans_pb;
} else if (fabs(trans[0] - 1) > 1e-6 || fabs(trans[3] - 1) > 1e-6) {
NRPixBlock *trans_pb = new NRPixBlock;
@@ -255,31 +258,34 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb)
min_x, min_y, max_x, max_y, true);
if (trans_pb->size != NR_PIXBLOCK_SIZE_TINY && trans_pb->data.px == NULL) {
g_warning("Memory allocation failed in Inkscape::Filters::FilterSlot::set (scaling)");
+ if (takeOwnership) {
+ nr_pixblock_release(pb);
+ delete pb;
+ }
return;
}
NR::scale_bicubic(trans_pb, pb, trans);
- nr_pixblock_release(pb);
- delete pb;
+ if (takeOwnership) {
+ nr_pixblock_release(pb);
+ delete pb;
+ }
+ takeOwnership = true;
pb = trans_pb;
}
}
- if(_slot[index]) {
- nr_pixblock_release(_slot[index]);
- delete _slot[index];
+ if(_slots[index].owned) {
+ nr_pixblock_release(_slots[index].pb);
+ delete _slots[index].pb;
}
- _slot[index] = pb;
+ _slots[index].pb = pb;
+ _slots[index].owned = takeOwnership;
_last_out = index;
}
int FilterSlot::get_slot_count()
{
- int seek = _slot_count;
- do {
- seek--;
- } while (!_slot[seek] && _slot_number[seek] == NR_FILTER_SLOT_NOT_SET);
-
- return seek + 1;
+ return _slots.size();
}
NRArenaItem const* FilterSlot::get_arenaitem()
@@ -299,47 +305,22 @@ int FilterSlot::_get_index(int slot_nr)
slot_nr == NR_FILTER_STROKEPAINT ||
slot_nr == NR_FILTER_UNNAMED_SLOT);
- int index = -1;
if (slot_nr == NR_FILTER_SLOT_NOT_SET) {
return _last_out;
}
+
/* Search, if the slot already exists */
- for (int i = 0 ; i < _slot_count ; i++) {
- if (_slot_number[i] == slot_nr) {
- index = i;
- break;
+ for (int i = 0 ; i < (int)_slots.size() ; i++) {
+ if (_slots[i].number == slot_nr) {
+ return i;
}
}
/* If the slot doesn't already exist, create it */
- if (index == -1) {
- int seek = _slot_count;
- do {
- seek--;
- } while ((seek >= 0) && (_slot_number[seek] == NR_FILTER_SLOT_NOT_SET));
- /* If there is no space for more slots, create more space */
- if (seek == _slot_count - 1) {
- NRPixBlock **new_slot = new NRPixBlock*[_slot_count * 2];
- int *new_number = new int[_slot_count * 2];
- for (int i = 0 ; i < _slot_count ; i++) {
- new_slot[i] = _slot[i];
- new_number[i] = _slot_number[i];
- }
- for (int i = _slot_count ; i < _slot_count * 2 ; i++) {
- new_slot[i] = NULL;
- new_number[i] = NR_FILTER_SLOT_NOT_SET;
- }
- delete[] _slot;
- delete[] _slot_number;
- _slot = new_slot;
- _slot_number = new_number;
- _slot_count *= 2;
- }
- /* Now that there is space, create the slot */
- _slot_number[seek + 1] = slot_nr;
- index = seek + 1;
- }
- return index;
+ slot_entry_t entry;
+ entry.number = slot_nr;
+ _slots.push_back(entry);
+ return (int)_slots.size()-1;
}
void FilterSlot::set_units(FilterUnits const &units) {
diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h
index 8d7a82d2d..a12d75a26 100644
--- a/src/display/nr-filter-slot.h
+++ b/src/display/nr-filter-slot.h
@@ -17,6 +17,7 @@
#include "libnr/nr-pixblock.h"
#include "display/nr-filter-types.h"
#include "display/nr-filter-units.h"
+#include
struct NRArenaItem;
@@ -59,11 +60,11 @@ public:
* If there was a pixblock already assigned with this slot,
* that pixblock is destroyed.
* Pixblocks passed to this function should be considered
- * managed by this FilterSlot object.
+ * managed by this FilterSlot object if takeOwnership==true.
* Pixblocks passed to this function should be reserved with
- * c++ -style new-operator.
+ * c++ -style new-operator (if managed by FilterSlot).
*/
- void set(int slot, NRPixBlock *pb);
+ void set(int slot, NRPixBlock *pb, bool takeOwnership=true);
/** Returns the number of slots in use. */
int get_slot_count();
@@ -84,9 +85,14 @@ public:
int get_blurquality(void);
private:
- NRPixBlock **_slot;
- int *_slot_number;
- int _slot_count;
+ struct slot_entry_t {
+ NRPixBlock* pb;
+ int number;
+ bool owned;
+ slot_entry_t() : pb(0), number(NR_FILTER_SLOT_NOT_SET), owned(false) {}
+ ~slot_entry_t();
+ };
+ std::vector _slots;
int _last_out;