index 432598b7cfe323c39f4356484a81f3aba0aa2873..96e2a92e915e53ea4bbe2ea180443419d2247ce6 100644 (file)
-#define __NR_FILTER_SLOT_CPP__
-
/*
* A container class for filter slots. Allows for simple getting and
* setting images in filter slots without having to bother with
*/
#include <assert.h>
+#include <string.h>
#include "display/nr-arena-item.h"
#include "display/nr-filter-types.h"
+#include "display/nr-filter-gaussian.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-getalpha.h"
#include "display/nr-filter-units.h"
return (int)round(a);
}
-namespace NR {
+namespace Inkscape {
+namespace Filters {
FilterSlot::FilterSlot(int slots, NRArenaItem const *item)
+ : _last_out(-1),
+ filterquality(FILTER_QUALITY_BEST),
+ 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;
- }
-
- _last_out = -1;
-
- _arena_item = item;
+ _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)
/* 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
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();
}
}
- 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) {
NRPixBlock *final_usr = get(slot_nr);
- Matrix trans = units.get_matrix_pb2display();
+ Geom::Matrix trans = units.get_matrix_pb2display();
int size = (result->area.x1 - result->area.x0)
* (result->area.y1 - result->area.y0)
memset(NR_PIXBLOCK_PX(result), 0, size);
if (fabs(trans[1]) > 1e-6 || fabs(trans[2]) > 1e-6) {
- transform_nearest(result, final_usr, trans);
+ if (filterquality == FILTER_QUALITY_BEST) {
+ NR::transform_bicubic(result, final_usr, trans);
+ } else {
+ NR::transform_nearest(result, final_usr, trans);
+ }
} else if (fabs(trans[0] - 1) > 1e-6 || fabs(trans[3] - 1) > 1e-6) {
- scale_bicubic(result, final_usr);
+ NR::scale_bicubic(result, final_usr, trans);
} else {
nr_blit_pixblock_pixblock(result, final_usr);
}
}
-void FilterSlot::set(int slot_nr, NRPixBlock *pb)
+void FilterSlot::set(int slot_nr, NRPixBlock *pb, bool takeOwnership)
{
- int index = _get_index(slot_nr);
+ /* Unnamed slot is for saving filter primitive results, when parameter
+ * 'result' is not set. Only the filter immediately after this one
+ * can access unnamed results, so we don't have to worry about overwriting
+ * previous results in filter chain. On the other hand, we may not
+ * overwrite any other image with this one, because they might be
+ * accessed later on. */
+ int index = ((slot_nr != NR_FILTER_SLOT_NOT_SET)
+ ? _get_index(slot_nr)
+ : _get_index(NR_FILTER_UNNAMED_SLOT));
assert(index >= 0);
- assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slot_number[index] == slot_nr);
+ // 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 ||_slots[index].number == slot_nr);
if (slot_nr == NR_FILTER_SOURCEGRAPHIC || slot_nr == NR_FILTER_BACKGROUNDIMAGE) {
- Matrix trans = units.get_matrix_display2pb();
+ Geom::Matrix trans = units.get_matrix_display2pb();
if (fabs(trans[1]) > 1e-6 || fabs(trans[2]) > 1e-6) {
NRPixBlock *trans_pb = new NRPixBlock;
int x0 = pb->area.x0;
trans[1] * x0 + trans[3] * y1 + trans[5],
trans[1] * x1 + trans[3] * y0 + trans[5],
trans[1] * x1 + trans[3] * y1 + trans[5]);
-
+
nr_pixblock_setup_fast(trans_pb, pb->mode,
min_x, min_y,
max_x, max_y, true);
* images are exported in horizontal stripes. One stripe
* is not too high, but can get thousands of pixels wide.
* Rotate this 45 degrees -> _huge_ image */
- g_warning("Memory allocation failed in NR::FilterSlot::set (transform)");
+ g_warning("Memory allocation failed in Inkscape::Filters::FilterSlot::set (transform)");
+ if (takeOwnership) {
+ nr_pixblock_release(pb);
+ delete pb;
+ }
return;
}
- transform_nearest(trans_pb, pb, trans);
- nr_pixblock_release(pb);
- delete pb;
+ if (filterquality == FILTER_QUALITY_BEST) {
+ NR::transform_bicubic(trans_pb, pb, trans);
+ } else {
+ NR::transform_nearest(trans_pb, pb, trans);
+ }
+ 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;
nr_pixblock_setup_fast(trans_pb, pb->mode,
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 NR::FilterSlot::set (scaling)");
+ g_warning("Memory allocation failed in Inkscape::Filters::FilterSlot::set (scaling)");
+ if (takeOwnership) {
+ nr_pixblock_release(pb);
+ delete pb;
+ }
return;
}
- scale_bicubic(trans_pb, pb);
- nr_pixblock_release(pb);
- delete pb;
+ NR::scale_bicubic(trans_pb, pb, trans);
+ 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()
slot_nr == NR_FILTER_BACKGROUNDIMAGE ||
slot_nr == NR_FILTER_BACKGROUNDALPHA ||
slot_nr == NR_FILTER_FILLPAINT ||
- slot_nr == NR_FILTER_STROKEPAINT);
+ 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 (_slot_number[seek] == NR_FILTER_SLOT_NOT_SET && seek >= 0);
- /* 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) {
this->units = units;
}
+void FilterSlot::set_quality(FilterQuality const q) {
+ filterquality = q;
+}
+
+void FilterSlot::set_blurquality(int const q) {
+ blurquality = q;
}
+int FilterSlot::get_blurquality(void) {
+ return blurquality;
+}
+
+} /* namespace Filters */
+} /* namespace Inkscape */
+
/*
Local Variables:
mode:c++
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :