summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNiko Kiirala <niko@kiirala.com>2006-07-26 17:31:16 +0000
committerkiirala <kiirala@users.sourceforge.net>2006-07-26 17:31:16 +0000
commitb3d7086c26844d050d5d13d48831c072a7814251 (patch)
treef1fff89cf832d20eb781a8e8200cfa7026b8454e /src
parentusage (diff)
downloadinkscape-b3d7086c26844d050d5d13d48831c072a7814251.tar.gz
inkscape-b3d7086c26844d050d5d13d48831c072a7814251.zip
Added renderer support for accessing background image from filters
(bzr r1485)
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-arena-group.cpp5
-rw-r--r--src/display/nr-arena-item.cpp40
-rw-r--r--src/display/nr-arena-item.h6
-rw-r--r--src/display/nr-filter-gaussian.cpp14
-rw-r--r--src/display/nr-filter-primitive.cpp2
-rw-r--r--src/display/nr-filter-slot.cpp60
-rw-r--r--src/display/nr-filter-slot.h18
-rw-r--r--src/display/nr-filter.cpp2
8 files changed, 116 insertions, 31 deletions
diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp
index 9657715ea..b4cc3930b 100644
--- a/src/display/nr-arena-group.cpp
+++ b/src/display/nr-arena-group.cpp
@@ -196,6 +196,11 @@ void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
if (style && style->filter.set && style->filter.filter) {
group->filter = new NR::Filter();
}
+
+ if (style && style->enable_background.set
+ && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
+ group->background_new = true;
+ }
}
static unsigned int
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index 57413ef22..7e03c51dd 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -97,6 +97,8 @@ nr_arena_item_init (NRArenaItem *item)
item->px = NULL;
item->data = NULL;
item->filter = NULL;
+ item->background_pb = NULL;
+ item->background_new = false;
}
static void
@@ -552,11 +554,21 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area,
#endif
} else {
/* Determine, whether we need temporary buffer */
- if (item->clip || item->mask || ((item->opacity != 255) && !item->render_opacity && item->arena->rendermode != RENDERMODE_OUTLINE) || item->filter) {
+ if (item->clip || item->mask
+ || ((item->opacity != 255) && !item->render_opacity && item->arena->rendermode != RENDERMODE_OUTLINE)
+ || item->filter || item->background_new
+ || (item->parent && item->parent->background_pb) )
+ {
NRPixBlock ipb, mpb;
/* Setup and render item buffer */
nr_pixblock_setup_fast (&ipb, NR_PIXBLOCK_MODE_R8G8B8A8P, carea.x0, carea.y0, carea.x1, carea.y1, TRUE);
+ /* 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)) {
+ item->background_pb = &ipb;
+ }
ipb.visible_area = pb->visible_area;
state = NR_ARENA_ITEM_VIRTUAL (item, render) (item, &carea, &ipb, flags);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
@@ -568,7 +580,7 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area,
}
ipb.empty = FALSE;
- /* Run filtering test, if a filter is set for this object */
+ /* Run filtering, if a filter is set for this object */
if(item->filter) {
item->filter->render(item, &ipb);
}
@@ -656,6 +668,8 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area,
/* Compose rendering pixblock int destination */
nr_blit_pixblock_pixblock_mask (dpb, &ipb, &mpb);
nr_pixblock_release (&mpb);
+ /* This pointer wouldn't be valid outside this block, so clear it */
+ item->background_pb = NULL;
} else {
/* Opacity only */
nr_blit_pixblock_pixblock_alpha (dpb, &ipb, item->opacity);
@@ -920,6 +934,28 @@ nr_arena_item_set_order (NRArenaItem *item, int order)
nr_arena_item_set_child_position (item->parent, item, ref);
}
+/** Returns a background image for use with filter effects. */
+NRPixBlock *nr_arena_item_get_background (NRArenaItem const *item, int depth)
+{
+ 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);
+ } else if (item->parent) {
+ pb = nr_arena_item_get_background(item->parent, depth + 1);
+ } else return NULL;
+
+ if (depth > 0)
+ nr_blit_pixblock_pixblock(pb, item->background_pb);
+
+ return pb;
+}
+
/* Helpers */
NRArenaItem *
diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h
index d38e44929..52408d154 100644
--- a/src/display/nr-arena-item.h
+++ b/src/display/nr-arena-item.h
@@ -115,6 +115,10 @@ struct NRArenaItem : public NRObject {
/* Current Transformation Matrix */
NR::Matrix ctm;
+ /* These hold background buffer state for filter rendering */
+ NRPixBlock *background_pb;
+ bool background_new;
+
void init(NRArena *arena) {
this->arena = arena;
}
@@ -180,6 +184,8 @@ void nr_arena_item_set_clip (NRArenaItem *item, NRArenaItem *clip);
void nr_arena_item_set_mask (NRArenaItem *item, NRArenaItem *mask);
void nr_arena_item_set_order (NRArenaItem *item, int order);
+NRPixBlock *nr_arena_item_get_background (NRArenaItem const *item, int depth = 0);
+
/* Helpers */
NRArenaItem *nr_arena_item_attach (NRArenaItem *parent, NRArenaItem *child, NRArenaItem *prev, NRArenaItem *next);
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp
index ad94bd0da..e2edcd0b8 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -27,7 +27,7 @@ namespace NR {
FilterGaussian::FilterGaussian()
{
- _deviation_x = _deviation_y = prefs_get_double_attribute("options.filtertest", "value", 0.0);
+ _deviation_x = _deviation_y = prefs_get_double_attribute("options.filtertest", "value", 1.0);
}
FilterPrimitive *FilterGaussian::create()
@@ -142,10 +142,16 @@ int FilterGaussian::render(FilterSlot &slot, Matrix const &trans)
/* in holds the input pixblock */
NRPixBlock *in = slot.get(_input);
- /* If to either direction, the standard deviation is zero, a transparent
- * black image should be returned */
- if (_deviation_x <= 0 || _deviation_y <= 0) {
+ /* If to either direction, the standard deviation is zero or
+ * input image is not defined,
+ * a transparent black image should be returned. */
+ if (_deviation_x <= 0 || _deviation_y <= 0 || in == NULL) {
NRPixBlock *out = new NRPixBlock;
+ if (in == NULL) {
+ // A bit guessing here, but source graphic is likely to be of
+ // right size
+ in = slot.get(NR_FILTER_SOURCEGRAPHIC);
+ }
nr_pixblock_setup_fast(out, in->mode, in->area.x0, in->area.y0,
in->area.x1, in->area.y1, true);
out->empty = false;
diff --git a/src/display/nr-filter-primitive.cpp b/src/display/nr-filter-primitive.cpp
index 9ea721d3b..890cb96fe 100644
--- a/src/display/nr-filter-primitive.cpp
+++ b/src/display/nr-filter-primitive.cpp
@@ -57,7 +57,7 @@ void FilterPrimitive::set_input(int slot) {
}
void FilterPrimitive::set_input(int input, int slot) {
- if (slot == 0) _input = slot;
+ if (input == 0) _input = slot;
}
void FilterPrimitive::set_output(int slot) {
diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp
index 6072e7993..3a2895ec6 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -14,15 +14,17 @@
*/
#include <assert.h>
+
+#include "display/nr-arena-item.h"
#include "libnr/nr-pixblock.h"
#include "display/nr-filter-types.h"
#include "display/nr-filter-slot.h"
namespace NR {
-FilterSlot::FilterSlot()
+FilterSlot::FilterSlot(int slots, NRArenaItem const *item)
{
- _slot_count = 2;
+ _slot_count = ((slots > 0) ? slots : 2);
_slot = new NRPixBlock*[_slot_count];
_slot_number = new int[_slot_count];
@@ -32,20 +34,8 @@ FilterSlot::FilterSlot()
}
_last_out = -1;
-}
-
-FilterSlot::FilterSlot(int slots)
-{
- _slot_count = slots;
- _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;
}
FilterSlot::~FilterSlot()
@@ -64,6 +54,40 @@ NRPixBlock *FilterSlot::get(int slot_nr)
{
int index = _get_index(slot_nr);
assert(index >= 0);
+
+ /* 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
+ && (slot_nr == NR_FILTER_SOURCEALPHA
+ || slot_nr == NR_FILTER_BACKGROUNDIMAGE
+ || slot_nr == NR_FILTER_BACKGROUNDALPHA
+ || slot_nr == NR_FILTER_FILLPAINT
+ || slot_nr == NR_FILTER_SOURCEPAINT))
+ {
+ /* If needed, fetch background */
+ if (slot_nr == NR_FILTER_BACKGROUNDIMAGE
+ || slot_nr == NR_FILTER_BACKGROUNDALPHA)
+ {
+ NRPixBlock *pb;
+ pb = nr_arena_item_get_background(_arena_item);
+ this->set(NR_FILTER_BACKGROUNDIMAGE, pb);
+ }
+ /* If only a alpha channel is needed, strip it from full image */
+ if (slot_nr == NR_FILTER_SOURCEALPHA) {
+ // TODO
+ }
+ if (slot_nr == NR_FILTER_BACKGROUNDALPHA) {
+ // TODO
+ }
+ /* When a paint is needed, fetch it from arena item */
+ if (slot_nr == NR_FILTER_FILLPAINT) {
+ // TODO
+ }
+ if (slot_nr == NR_FILTER_SOURCEPAINT) {
+ // TODO
+ }
+ }
+
assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slot_number[index] == slot_nr);
return _slot[index];
}
@@ -120,7 +144,7 @@ int FilterSlot::_get_index(int slot_nr)
int seek = _slot_count;
do {
seek--;
- } while (_slot[seek] == NULL);
+ } while (_slot[seek] == NULL && 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];
@@ -130,8 +154,8 @@ int FilterSlot::_get_index(int slot_nr)
new_number[i] = _slot_number[i];
}
for (int i = _slot_count ; i < _slot_count * 2 ; i++) {
- _slot[i] = NULL;
- _slot_number[i] = NR_FILTER_SLOT_NOT_SET;
+ new_slot[i] = NULL;
+ new_number[i] = NR_FILTER_SLOT_NOT_SET;
}
delete[] _slot;
delete[] _slot_number;
diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h
index 13ce1afe2..09190a9b0 100644
--- a/src/display/nr-filter-slot.h
+++ b/src/display/nr-filter-slot.h
@@ -16,14 +16,20 @@
#include "libnr/nr-pixblock.h"
+struct NRArenaItem;
+
namespace NR {
class FilterSlot {
public:
- /** Creates a new FilterSlot object, with two slots. */
- FilterSlot();
- /** Creates a new FilterSlot object, with specified amount of slots */
- FilterSlot(int slots);
+ /** Creates a new FilterSlot object.
+ * First parameter specifies the amount of slots this SilterSlot
+ * should reserve beforehand. If a negative number is given,
+ * two slots will be reserved.
+ * Second parameter specifies the arena item, which should be used
+ * for background accesses from filters.
+ */
+ FilterSlot(int slots, NRArenaItem const *item);
/** Destroys the FilterSlot object and all its contents */
~FilterSlot();
@@ -58,7 +64,9 @@ private:
int _last_out;
- /** Returns the table index of given slot. If that slot dows not exist,
+ NRArenaItem const *_arena_item;
+
+ /** Returns the table index of given slot. If that slot does not exist,
* it is created. Table index can be used to read the correct
* pixblock from _slot */
int _get_index(int slot);
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index db1e9d8db..bda64c50c 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -84,7 +84,7 @@ Filter::~Filter()
int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
{
Matrix trans = *item->ctm;
- FilterSlot slot(_slot_count);
+ FilterSlot slot(_slot_count, item);
NRPixBlock *in = new NRPixBlock;
// First, if filter resolution is not set to automatic, we should