Code

And now gradients should be (almost) perfect... The gradient vector is set up to...
[inkscape.git] / src / display / nr-filter-diffuselighting.cpp
index 500a275afd7fb800931cd73b910530ca2c995fe9..bf5b97fb1310787039e99cfa002ddb66c0e48f32 100644 (file)
 #include "display/nr-filter-diffuselighting.h"
 #include "display/nr-filter-getalpha.h"
 #include "display/nr-filter-slot.h"
+#include "display/nr-filter-units.h"
 #include "display/nr-filter-utils.h"
 #include "display/nr-light.h"
 #include "libnr/nr-blit.h"
 #include "libnr/nr-pixblock.h"
-#include "libnr/nr-matrix.h"
 #include "libnr/nr-rect-l.h"
 #include "color.h"
 
-namespace NR {
+namespace Inkscape {
+namespace Filters {
 
 FilterDiffuseLighting::FilterDiffuseLighting() 
 {
@@ -42,15 +43,13 @@ FilterPrimitive * FilterDiffuseLighting::create() {
 FilterDiffuseLighting::~FilterDiffuseLighting()
 {}
 
-#define COMPUTE_INTER(inter, N, L, kd) \
-do {\
-    (inter) = (kd) * scalar_product((N), (L)); \
-    if ((inter) < 0) (inter) = 0; \
-}while(0)
-
+int FilterDiffuseLighting::render(FilterSlot &slot, FilterUnits const &units) {
+    NRPixBlock *in = slot.get(_input);
+    if (!in) {
+        g_warning("Missing source image for feDiffuseLighting (in=%d)", _input);
+        return 1;
+    }
 
-int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
-    NRPixBlock *in = filter_get_alpha(slot.get(_input));
     NRPixBlock *out = new NRPixBlock;
 
     int w = in->area.x1 - in->area.x0;
@@ -63,11 +62,11 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
     int dx = 1; //TODO setup
     int dy = 1; //TODO setup
     //surface scale
-    //TODO for the time being, assumes userSpaceOnUse
+    Geom::Matrix trans = units.get_matrix_primitiveunits2pb();
     gdouble ss = surfaceScale * trans[0];
     gdouble kd = diffuseConstant; //diffuse lighting constant
 
-    Fvector L, N, LC;
+    NR::Fvector L, N, LC;
     gdouble inter;
 
     nr_pixblock_setup_fast(out, in->mode,
@@ -85,8 +84,8 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
             dl->light_components(LC);
             //finish the work
             for (i = 0, j = 0; i < w*h; i++) {
-                compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
-                COMPUTE_INTER(inter, N, L, kd);
+                NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
+                inter = kd * NR::scalar_product(N, L);
 
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
@@ -102,17 +101,17 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
             PointLight *pl = new PointLight(light.point, lighting_color, trans);
             pl->light_components(LC);
         //TODO we need a reference to the filter to determine primitiveUnits
-        //slot._arena_item->filter seems to be ok on simple examples
-        //for now assume userSpaceOnUse
         //if objectBoundingBox is used, use a different matrix for light_vector
+        // UPDATE: trans is now correct matrix from primitiveUnits to
+        // pixblock coordinates
             //finish the work
             for (i = 0, j = 0; i < w*h; i++) {
-                compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
+                NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
                 pl->light_vector(L,
                         i % w + x0,
                         i / w + y0,
                         ss * (double) data_i[4*i+3]/ 255);
-                COMPUTE_INTER(inter, N, L, kd);
+                inter = kd * NR::scalar_product(N, L);
 
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
@@ -127,18 +126,18 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
             {
             SpotLight *sl = new SpotLight(light.spot, lighting_color, trans);
         //TODO we need a reference to the filter to determine primitiveUnits
-        //slot._arena_item->filter seems to be ok on simple examples
-        //for now assume userSpaceOnUse
         //if objectBoundingBox is used, use a different matrix for light_vector
+        // UPDATE: trans is now correct matrix from primitiveUnits to
+        // pixblock coordinates
             //finish the work
             for (i = 0, j = 0; i < w*h; i++) {
-                compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
+                NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
                 sl->light_vector(L,
                     i % w + x0,
                     i / w + y0,
                     ss * (double) data_i[4*i+3]/ 255);
                 sl->light_components(LC, L);
-                COMPUTE_INTER(inter, N, L, kd);
+                inter = kd * NR::scalar_product(N, L);
                 
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
@@ -164,12 +163,17 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
         
     //finishing
     slot.set(_output, out);
-    nr_pixblock_release(in);
-    delete in;
+    //nr_pixblock_release(in);
+    //delete in;
     return 0;
 }
 
-} /* namespace NR */
+FilterTraits FilterDiffuseLighting::get_input_traits() {
+    return TRAIT_PARALLER;
+}
+
+} /* namespace Filters */
+} /* namespace Inkscape */
 
 /*
   Local Variables: