Code

Added renderer support for accessing background image from filters
authorkiirala <kiirala@users.sourceforge.net>
Wed, 26 Jul 2006 17:31:16 +0000 (17:31 +0000)
committerkiirala <kiirala@users.sourceforge.net>
Wed, 26 Jul 2006 17:31:16 +0000 (17:31 +0000)
src/display/nr-arena-group.cpp
src/display/nr-arena-item.cpp
src/display/nr-arena-item.h
src/display/nr-filter-gaussian.cpp
src/display/nr-filter-primitive.cpp
src/display/nr-filter-slot.cpp
src/display/nr-filter-slot.h
src/display/nr-filter.cpp

index 9657715ea72a874c8b7303952429e590e63eaac9..b4cc3930b1a5ad4807ee79bf040065c976801a35 100644 (file)
@@ -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
index 57413ef227740b750e756026a2429c061726b3b6..7e03c51dd2cf10506c738fe52d698255485e0163 100644 (file)
@@ -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 *
index d38e44929269d10ee78d139052b68e363b4f7c49..52408d1547f09892879ad9aa28e652e191c37f89 100644 (file)
@@ -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);
index ad94bd0da875f73cbb9f13d54b323bab4db58e73..e2edcd0b843d7f45f295a91f6c1bc2686d049061 100644 (file)
@@ -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;
index 9ea721d3beb44ad3313abba7b3fc5adea2c1d12a..890cb96fe7ad81399c9c7a0422a24272373fc7a1 100644 (file)
@@ -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) {
index 6072e7993b30891f126ff230aafcc073b172434c..3a2895ec61d45485a489ce330a2a31da7df77f1c 100644 (file)
  */
 
 #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;
index 13ce1afe20fff919619db5fc2b9d8ac4d2f97826..09190a9b0a105502d76df79a27d76aaea9f26dfc 100644 (file)
 
 #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);
index db1e9d8db596df27c093c8ce74d83e165534365f..bda64c50ce232068fee2c966dd6dbb19738e6e4e 100644 (file)
@@ -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