Code

Patch from Jean-René Reinhard: support for feDiffuseLighting and
authorkiirala <kiirala@users.sourceforge.net>
Fri, 20 Jul 2007 19:50:41 +0000 (19:50 +0000)
committerkiirala <kiirala@users.sourceforge.net>
Fri, 20 Jul 2007 19:50:41 +0000 (19:50 +0000)
feSpecularLighting filter primitives

25 files changed:
src/Makefile_insert
src/attributes.cpp
src/attributes.h
src/display/Makefile_insert
src/display/nr-3dutils.cpp [new file with mode: 0644]
src/display/nr-3dutils.h [new file with mode: 0644]
src/display/nr-filter-diffuselighting.cpp [new file with mode: 0644]
src/display/nr-filter-diffuselighting.h [new file with mode: 0644]
src/display/nr-filter-specularlighting.cpp [new file with mode: 0644]
src/display/nr-filter-specularlighting.h [new file with mode: 0644]
src/display/nr-filter.cpp
src/display/nr-light-types.h [new file with mode: 0644]
src/display/nr-light.cpp [new file with mode: 0644]
src/display/nr-light.h [new file with mode: 0644]
src/sp-fediffuselighting.cpp
src/sp-fediffuselighting.h
src/sp-fedistantlight.cpp [new file with mode: 0644]
src/sp-fedistantlight.h [new file with mode: 0644]
src/sp-fepointlight.cpp [new file with mode: 0644]
src/sp-fepointlight.h [new file with mode: 0644]
src/sp-fespecularlighting.cpp
src/sp-fespecularlighting.h
src/sp-fespotlight.cpp [new file with mode: 0644]
src/sp-fespotlight.h [new file with mode: 0644]
src/sp-object-repr.cpp

index 1371039c15bf472251d1a2f6c311d541edd446c8..548a4933491ffcfcd19c7eab85e3fbc9e9ddcbe1 100644 (file)
@@ -166,6 +166,7 @@ libinkpre_a_SOURCES =       \
        sp-fediffuselighting-fns.h      \
        sp-fedisplacementmap.cpp sp-fedisplacementmap.h \
        sp-fedisplacementmap-fns.h      \
+       sp-fedistantlight.cpp sp-fedistantlight.h \
        sp-feflood.cpp sp-feflood.h     \
        sp-feflood-fns.h        \
        sp-feimage.cpp sp-feimage.h     \
@@ -176,8 +177,10 @@ libinkpre_a_SOURCES =      \
        sp-femorphology-fns.h   \
        sp-feoffset.cpp sp-feoffset.h   \
        sp-feoffset-fns.h       \
+       sp-fepointlight.cpp sp-fepointlight.h \
        sp-fespecularlighting.cpp sp-fespecularlighting.h       \
        sp-fespecularlighting-fns.h     \
+       sp-fespotlight.cpp sp-fespotlight.h \
        sp-fetile.cpp sp-fetile.h       \
        sp-fetile-fns.h \
        sp-feturbulence.cpp sp-feturbulence.h   \
index 968e3863373a74a5f2f7772cff593f76aabc3b10..025f1991bf78bef9bf6a6a9b9d41c4d56474fca3 100644 (file)
@@ -213,6 +213,16 @@ static SPStyleProp const props[] = {
     {SP_ATTR_XCHANNELSELECTOR, "xChannelSelector"},
     {SP_ATTR_YCHANNELSELECTOR, "yChannelSelector"},
     //{SP_ATTR_IN2, "in2"},
+    /*feDistantLight*/
+    {SP_ATTR_AZIMUTH, "azimuth"},
+    {SP_ATTR_ELEVATION, "elevation"},
+    /*fePointLight*/
+    {SP_ATTR_Z, "z"},
+    /*feSpotLight*/
+    {SP_ATTR_POINTSATX, "pointsAtX"},
+    {SP_ATTR_POINTSATY, "pointsAtY"},
+    {SP_ATTR_POINTSATZ, "pointsAtZ"},
+    {SP_ATTR_LIMITINGCONEANGLE, "limitingConeAngle"},
     /*feFlood*/
     {SP_ATTR_FLOODCOLOR, "flood-color"},
     {SP_ATTR_FLOODOPACITY, "flood-opacity"},
index 9e658f562d4b2bfd6a0a0682898d659601a0a13b..c7f1fb71edce1d8ad0156885a425fa861f414e52 100644 (file)
@@ -213,6 +213,16 @@ enum SPAttributeEnum {
     SP_ATTR_XCHANNELSELECTOR,
     SP_ATTR_YCHANNELSELECTOR,
     //SP_ATTR_IN2,
+    /*feDistantLight*/
+    SP_ATTR_AZIMUTH,
+    SP_ATTR_ELEVATION,
+    /*fePointLight*/
+    SP_ATTR_Z,
+    /*feSpotLight*/
+    SP_ATTR_POINTSATX,
+    SP_ATTR_POINTSATY,
+    SP_ATTR_POINTSATZ,
+    SP_ATTR_LIMITINGCONEANGLE,
     /*feFlood*/
     SP_ATTR_FLOODCOLOR,
     SP_ATTR_FLOODOPACITY,
index 1a4c01011af4648086e5c68d2363f8d87baa42e4..bc6fb33369744069c54cc5abd89e63dd2db0b1f2 100644 (file)
@@ -15,6 +15,8 @@ display/canvas-arena.$(OBJEXT): helper/sp-marshal.h
 display/sp-canvas.$(OBJEXT): helper/sp-marshal.h
 
 display_libspdisplay_a_SOURCES = \
+       display/nr-3dutils.h \
+       display/nr-3dutils.cpp \
        display/nr-arena-forward.h      \
        display/nr-arena.cpp    \
        display/nr-arena.h      \
@@ -71,8 +73,12 @@ display_libspdisplay_a_SOURCES = \
        display/nr-filter-gaussian.h    \
        display/nr-filter-blend.cpp     \
        display/nr-filter-blend.h       \
+       display/nr-filter-diffuselighting.cpp     \
+       display/nr-filter-diffuselighting.h       \
        display/nr-filter-offset.cpp    \
        display/nr-filter-offset.h      \
+       display/nr-filter-specularlighting.cpp     \
+       display/nr-filter-specularlighting.h       \
        display/nr-filter-composite.h   \
        display/nr-filter-composite.cpp \
        display/nr-filter-slot.cpp      \
@@ -86,7 +92,10 @@ display_libspdisplay_a_SOURCES = \
        display/pixblock-transform.cpp  \
        display/pixblock-transform.h    \
        display/inkscape-cairo.cpp      \
-       display/inkscape-cairo.h
+       display/inkscape-cairo.h                \
+       display/nr-light.h                              \
+       display/nr-light.cpp                    \
+       display/nr-light-types.h
 
 display_bezier_utils_test_SOURCES = display/bezier-utils-test.cpp
 display_bezier_utils_test_LDADD = libnr/libnr.a -lglib-2.0
diff --git a/src/display/nr-3dutils.cpp b/src/display/nr-3dutils.cpp
new file mode 100644 (file)
index 0000000..c8171cc
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * 3D utils.
+ * 
+ * Authors:
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib/gmessages.h>
+
+#include "libnr/nr-pixblock.h"
+#include "libnr/nr-matrix.h"
+#include "display/nr-3dutils.h"
+#include <cmath>
+
+namespace NR {
+
+#define BEGIN 0 // TOP or LEFT
+#define MIDDLE 1
+#define END 2 // BOTTOM or RIGHT
+
+#define START(v) ((v)==BEGIN? 1 : 0)
+#define FINISH(v) ((v)==END? 1 : 2)
+    
+signed char K_X[3][3][3][3] = {
+    //K_X[TOP]
+    {
+        //K_X[TOP][LEFT]
+        {
+            { 0,  0,  0},
+            { 0, -2,  2},
+            { 0, -1,  1}
+        },
+        { 
+            { 0,  0,  0},
+            {-2,  0,  2},
+            {-1,  0,  1}
+        },   
+        { 
+            { 0,  0,  0},
+            {-2,  2,  0},
+            {-1,  1,  0}
+        }
+    },
+    //K_X[MIDDLE]
+    {
+        //K_X[MIDDLE][LEFT]
+        {
+            { 0, -1,  1},
+            { 0, -2,  2},
+            { 0, -1,  1}
+        },
+        { 
+            {-1,  0,  1},
+            {-2,  0,  2},
+            {-1,  0,  1}
+        },   
+        { 
+            {-1,  1,  0},
+            {-2,  2,  0},
+            {-1,  1,  0}
+        }
+    },
+    //K_X[BOTTOM]
+    {
+        //K_X[BOTTOM][LEFT]
+        {
+            { 0, -1,  1},
+            { 0, -2,  2},
+            { 0,  0,  0}
+        },
+        { 
+            {-1,  0,  1},
+            {-2,  0,  2},
+            { 0,  0,  0}
+        },   
+        { 
+            {-1,  1,  0},
+            {-2,  2,  0},
+            { 0,  0,  0}
+        }
+    }
+};
+
+//K_Y is obtained by transposing K_X globally and each of its components
+
+gdouble FACTOR_X[3][3] = {
+    {2./3, 1./3, 2./3},
+    {1./2, 1./4, 1./2},
+    {2./3, 1./3, 2./3}
+};
+
+//FACTOR_Y is obtained by transposing FACTOR_X
+
+inline
+int get_carac(int i, int len, int delta) {
+    if (i < delta)
+        return BEGIN;
+    else if (i > len - 1 - delta)
+        return END;
+    else
+        return MIDDLE;
+}
+    
+//assumes in is RGBA
+//should be made more resistant
+void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j, int dx, int dy) {
+    int w = in->area.x1 - in->area.x0;
+    int h = in->area.y1 - in->area.y0;
+    int k, l, alpha_idx, alpha_idx_y;
+    int x_carac, y_carac;
+    gdouble alpha;
+    gdouble accu_x;
+    gdouble accu_y;
+    unsigned char *data = NR_PIXBLOCK_PX (in);
+    g_assert(in->mode == NR_PIXBLOCK_MODE_R8G8B8A8P);
+    x_carac = get_carac(j, w, dx); //LEFT, MIDDLE or RIGHT
+    y_carac = get_carac(i, h, dy); //TOP, MIDDLE or BOTTOM
+    alpha_idx = 4*(i*w + j);
+    accu_x = 0;
+    accu_y = 0;
+    for (k = START(y_carac); k <= FINISH(y_carac); k++) {
+        alpha_idx_y = alpha_idx + 4*(k-1)*dy*w;
+        for (l = START(x_carac); l <= FINISH(x_carac); l++) {
+            alpha = (data + alpha_idx_y + 4*dx*(l-1))[3];
+            accu_x += K_X[y_carac][x_carac][k][l] * alpha / 255;
+            accu_y += K_X[x_carac][y_carac][l][k] * alpha / 255;
+        }
+    }
+    N[X_3D] = -1 * ss * FACTOR_X[y_carac][x_carac] * accu_x / dx;
+    N[Y_3D] = -1 * ss * FACTOR_X[x_carac][y_carac] * accu_y / dy;
+    N[Z_3D] = 1; 
+    normalize_vector(N);
+    //std::cout << "(" << N[X_3D] << ", " << N[Y_3D] << ", " << N[Z_3D] << ")" << std::endl;
+}
+
+void convert_coord(gdouble &x, gdouble &y, gdouble &z, Matrix const &trans) {
+    Point p = Point(x, y);
+    p *= trans;
+    x = p[X];
+    y = p[Y];
+    z *= trans[0];
+}
+
+gdouble norm(const Fvector &v) {
+    return sqrt(v[X_3D]*v[X_3D] + v[Y_3D]*v[Y_3D] + v[Z_3D]*v[Z_3D]); 
+}
+
+void normalize_vector(Fvector &v) {
+    int i, j;
+    gdouble nv = norm(v);
+    //TODO test nv == 0
+    for (j = 0; j < 3; j++) {
+        v[j] /= nv;
+    }
+} 
+
+gdouble scalar_product(const Fvector &a, const Fvector &b) {
+    return  a[X_3D] * b[X_3D] +
+            a[Y_3D] * b[Y_3D] +
+            a[Z_3D] * b[Z_3D];
+}
+
+void normalized_sum(Fvector &r, const Fvector &a, const Fvector &b) {
+    r[X_3D] = a[X_3D] + b[X_3D];
+    r[Y_3D] = a[Y_3D] + b[Y_3D];
+    r[Z_3D] = a[Z_3D] + b[Z_3D];
+    normalize_vector(r);
+}
+
+}/* namespace NR */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-3dutils.h b/src/display/nr-3dutils.h
new file mode 100644 (file)
index 0000000..4baa9cc
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef __NR_3DUTILS_H__
+#define __NR_3DUTILS_H__
+
+/*
+ * 3D utils. Definition of gdouble vectors of dimension 3 and of some basic
+ * functions.
+ *
+ * Authors:
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gdk/gdktypes.h>
+
+struct NRPixBlock;
+
+namespace NR {
+
+struct Matrix;
+
+#define X_3D 0
+#define Y_3D 1
+#define Z_3D 2
+
+/**
+ * a type of 3 gdouble components vectors
+ */
+typedef gdouble Fvector[3];
+
+/**
+ * The eye vector
+ */
+const static Fvector EYE_VECTOR = {0, 0, 1};
+
+/**
+ * returns the euclidian norm of the vector v
+ *
+ * \param v a reference to a vector with double components
+ * \return the euclidian norm of v
+ */
+gdouble norm(const Fvector &v);
+
+/**
+ * Normalizes a vector
+ *
+ * \param v a reference to a vector to normalize
+ */
+void normalize_vector(Fvector &v);
+
+/**
+ * Computes the scalar product between two Fvectors
+ *
+ * \param a a Fvector reference
+ * \param b a Fvector reference
+ * \return the scalar product of a and b
+ */
+gdouble scalar_product(const Fvector &a, const Fvector &b);
+
+/**
+ * Computes the normalized sum of two Fvectors
+ *
+ * \param r a Fvector reference where we store the result
+ * \param a a Fvector reference
+ * \param b a Fvector reference
+ */
+void normalized_sum(Fvector &r, const Fvector &a, const Fvector &b);
+
+/**
+ * Computes the unit suface normal vector of surface given by "in" at (i, j)
+ * and store it into N. "in" is a (NRPixBlock *) in mode RGBA but only the alpha
+ * channel is considered as a bump map. ss is the altitude when for the alpha
+ * value 255. dx and dy are the deltas used to compute in our discrete setting
+ *
+ * \param N a reference to a Fvector in which we store the unit surface normal
+ * \param ss the surface scale
+ * \param in a NRPixBlock * whose alpha channel codes the surface
+ * \param i the x coordinate of the point at which we compute the normal
+ * \param j the y coordinate of the point at which we compute the normal
+ * \param dx the delta used in the x coordinate
+ * \param dy the delta used in the y coordinate
+ */
+void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j, int dx, int dy);
+
+/**
+ * Applies the transformation matrix to (x, y, z). This function assumes that
+ * trans[0] = trans[3]. x and y are transformed according to trans, z is
+ * multiplied by trans[0].
+ *
+ * \param x a reference to a x coordinate
+ * \param y a reference to a y coordinate
+ * \param z a reference to a z coordinate
+ * \param z a reference to a transformation matrix
+ */
+void convert_coord(gdouble &x, gdouble &y, gdouble &z, Matrix const &trans);
+
+} /* namespace NR */
+
+#endif /* __NR_3DUTILS_H__ */
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-filter-diffuselighting.cpp b/src/display/nr-filter-diffuselighting.cpp
new file mode 100644 (file)
index 0000000..736055f
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * feDiffuseLighting renderer
+ *
+ * Authors:
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib/gmessages.h>
+
+#include "display/nr-3dutils.h"
+#include "display/nr-arena-item.h"
+#include "display/nr-filter-diffuselighting.h"
+#include "display/nr-filter-getalpha.h"
+#include "display/nr-filter-slot.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"
+#include "round.h"
+
+namespace NR {
+
+FilterDiffuseLighting::FilterDiffuseLighting() 
+{
+    light_type = NO_LIGHT;
+    diffuseConstant = 1;
+    surfaceScale = 1;
+    lighting_color = 0xffffffff;
+}
+
+FilterPrimitive * FilterDiffuseLighting::create() {
+    return new FilterDiffuseLighting();
+}
+
+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, Matrix const &trans) {
+    NRPixBlock *in = filter_get_alpha(slot.get(_input));
+    NRPixBlock *out = new NRPixBlock;
+
+    int w = in->area.x1 - in->area.x0;
+    int h = in->area.y1 - in->area.y0;
+    int x0 = in->area.x0;
+    int y0 = in->area.y0;
+    int i, j;
+    //As long as FilterRes and kernel unit is not supported we hardcode the
+    //default value
+    int dx = 1; //TODO setup
+    int dy = 1; //TODO setup
+    //surface scale
+    //TODO for the time being, assumes userSpaceOnUse
+    gdouble ss = surfaceScale * trans[0];
+    gdouble kd = diffuseConstant; //diffuse lighting constant
+
+    Fvector L, N, LC;
+    gdouble inter;
+
+    nr_pixblock_setup_fast(out, in->mode,
+            in->area.x0, in->area.y0, in->area.x1, in->area.y1,
+            true);
+    unsigned char *data_i = NR_PIXBLOCK_PX (in);
+    unsigned char *data_o = NR_PIXBLOCK_PX (out);
+    //No light, nothing to do
+    switch (light_type) {
+        case DISTANT_LIGHT:  
+            //the light vector is constant
+            {
+            DistantLight *dl = new DistantLight(light.distant, lighting_color);
+            dl->light_vector(L);
+            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);
+
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = 255;
+            }
+            out->empty = FALSE;
+            delete dl;
+            }
+            break;
+        case POINT_LIGHT:
+            {
+            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
+            //finish the work
+            for (i = 0, j = 0; i < w*h; i++) {
+                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);
+
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = 255;
+            }
+            out->empty = FALSE;
+            delete pl;
+            }
+            break;
+        case SPOT_LIGHT:
+            {
+            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
+            //finish the work
+            for (i = 0, j = 0; i < w*h; i++) {
+                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);
+                
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = 255;
+            }
+            out->empty = FALSE;
+            delete sl;
+            }
+            break;
+        //else unknown light source, doing nothing
+        case NO_LIGHT:
+        default:
+            {
+            if (light_type != NO_LIGHT)
+                g_warning("unknown light source %d", light_type);
+            for (i = 0; i < w*h; i++) {
+                data_o[4*i+3] = 255;
+            }
+            out->empty = false;
+            }
+    }
+        
+    //finishing
+    slot.set(_output, out);
+    delete in;
+    return 0;
+}
+
+} /* namespace NR */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-filter-diffuselighting.h b/src/display/nr-filter-diffuselighting.h
new file mode 100644 (file)
index 0000000..486b81a
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __NR_FILTER_DIFFUSELIGHTING_H__
+#define __NR_FILTER_DIFFUSELIGHTING_H__
+
+/*
+ * feDiffuseLighting renderer
+ *
+ * Authors:
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ * 
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gdk/gdktypes.h>
+#include "display/nr-light-types.h"
+#include "display/nr-filter-primitive.h"
+#include "display/nr-filter-slot.h"
+#include "libnr/nr-matrix.h"
+#include "sp-fedistantlight.h"
+#include "sp-fepointlight.h"
+#include "sp-fespotlight.h"
+#include "color.h"
+
+namespace NR {
+    
+class FilterDiffuseLighting : public FilterPrimitive {
+public:
+    union {
+        SPFeDistantLight *distant;
+        SPFePointLight *point;
+        SPFeSpotLight *spot;
+    } light;
+    LightType light_type;
+    gdouble diffuseConstant;
+    gdouble surfaceScale;
+    guint32 lighting_color;
+    
+    FilterDiffuseLighting();
+    static FilterPrimitive *create();
+    virtual ~FilterDiffuseLighting();
+    virtual int render(FilterSlot &slot, Matrix const &trans);
+
+private:
+};
+
+} /* namespace NR */
+
+#endif /* __NR_FILTER_DIFFUSELIGHTING_H__ */
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-filter-specularlighting.cpp b/src/display/nr-filter-specularlighting.cpp
new file mode 100644 (file)
index 0000000..117df28
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * feSpecularLighting renderer
+ *
+ * Authors:
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib/gmessages.h>
+#include <cmath>
+
+#include "display/nr-3dutils.h"
+#include "display/nr-arena-item.h"
+#include "display/nr-filter-specularlighting.h"
+#include "display/nr-filter-getalpha.h"
+#include "display/nr-filter-slot.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"
+#include "round.h"
+
+namespace NR {
+
+FilterSpecularLighting::FilterSpecularLighting() 
+{
+    light_type = NO_LIGHT;
+    specularConstant = 1;
+    specularExponent = 1;
+    surfaceScale = 1;
+    lighting_color = 0xffffffff;
+}
+
+FilterPrimitive * FilterSpecularLighting::create() {
+    return new FilterSpecularLighting();
+}
+
+FilterSpecularLighting::~FilterSpecularLighting()
+{}
+
+//Investigating Phong Lighting model we should not take N.H but
+//R.E which equals to 2*N.H^2 - 1
+#define COMPUTE_INTER(inter, H, N, ks, speculaExponent) \
+do {\
+    gdouble scal = scalar_product((N), (H));\
+    scal = 2 * scal * scal - 1;\
+    if (scal <= 0)\
+        (inter) = 0;\
+    else\
+        (inter) = (ks) * std::pow(scal, (specularExponent));\
+}while(0)
+
+int FilterSpecularLighting::render(FilterSlot &slot, Matrix const &trans) {
+    NRPixBlock *in = filter_get_alpha(slot.get(_input));
+    NRPixBlock *out = new NRPixBlock;
+
+    //Fvector *L = NULL; //vector to the light
+    
+    int w = in->area.x1 - in->area.x0;
+    int h = in->area.y1 - in->area.y0;
+    int x0 = in->area.x0;
+    int y0 = in->area.y0;
+    int i, j;
+    //As long as FilterRes and kernel unit is not supported we hardcode the
+    //default value
+    int dx = 1; //TODO setup
+    int dy = 1; //TODO setup
+    //surface scale
+    //TODO for the time being, assumes userSpaceOnUse
+    gdouble ss = surfaceScale * trans[0];
+    gdouble ks = specularConstant; //diffuse lighting constant
+    Fvector L, N, LC, H;
+    gdouble inter;
+    
+    nr_pixblock_setup_fast(out, in->mode,
+            in->area.x0, in->area.y0, in->area.x1, in->area.y1,
+            true);
+    unsigned char *data_i = NR_PIXBLOCK_PX (in);
+    unsigned char *data_o = NR_PIXBLOCK_PX (out);
+    //No light, nothing to do
+    switch (light_type) {
+        case DISTANT_LIGHT:  
+            //the light vector is constant
+            {
+            DistantLight *dl = new DistantLight(light.distant, lighting_color);
+            dl->light_vector(L);
+            dl->light_components(LC);
+            normalized_sum(H, L, EYE_VECTOR);
+            //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, H, ks, specularExponent);
+
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
+            }
+            out->empty = FALSE;
+            delete dl;
+            }
+            break;
+        case POINT_LIGHT:
+            {
+            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
+            //finish the work
+            for (i = 0, j = 0; i < w*h; i++) {
+                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);
+                normalized_sum(H, L, EYE_VECTOR);
+                COMPUTE_INTER(inter, N, H, ks, specularExponent);
+                
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
+            }
+            out->empty = FALSE;
+            delete pl;
+            }
+            break;
+        case SPOT_LIGHT:
+            {
+            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
+            //finish the work
+            for (i = 0, j = 0; i < w*h; i++) {
+                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);
+                normalized_sum(H, L, EYE_VECTOR);
+                COMPUTE_INTER(inter, N, H, ks, specularExponent);
+                
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
+            }
+            out->empty = FALSE;
+            delete sl;
+            }
+            break;
+        //else unknown light source, doing nothing
+        case NO_LIGHT:
+        default:
+            {
+            if (light_type != NO_LIGHT)
+                g_warning("unknown light source %d", light_type);
+            out->empty = false;
+            }
+    }
+        
+    //finishing
+    slot.set(_output, out);
+    delete in;
+    return 0;
+}
+
+} /* namespace NR */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-filter-specularlighting.h b/src/display/nr-filter-specularlighting.h
new file mode 100644 (file)
index 0000000..a9b3429
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __NR_FILTER_SPECULARLIGHTING_H__
+#define __NR_FILTER_SPECULARLIGHTING_H__
+
+/*
+ * feSpecularLighting renderer
+ *
+ * Authors:
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ * 
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gdk/gdktypes.h>
+#include "display/nr-light-types.h"
+#include "display/nr-filter-primitive.h"
+#include "display/nr-filter-slot.h"
+#include "libnr/nr-matrix.h"
+#include "sp-fedistantlight.h"
+#include "sp-fepointlight.h"
+#include "sp-fespotlight.h"
+#include "color.h"
+
+namespace NR {
+    
+class FilterSpecularLighting : public FilterPrimitive {
+public:
+    union {
+        SPFeDistantLight *distant;
+        SPFePointLight *point;
+        SPFeSpotLight *spot;
+    } light;
+    LightType light_type;
+    gdouble surfaceScale;
+    gdouble specularConstant;
+    gdouble specularExponent;
+    guint32 lighting_color;
+    
+    FilterSpecularLighting();
+    static FilterPrimitive *create();
+    virtual ~FilterSpecularLighting();
+    virtual int render(FilterSlot &slot, Matrix const &trans);
+
+private:
+};
+
+} /* namespace NR */
+
+#endif /* __NR_FILTER_SPECULARLIGHTING_H__ */
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 61571f43bde80a5321bc764be81c6f532b253b45..8a22778a130566eaa57233496c5b2e7429f27fc1 100644 (file)
@@ -25,6 +25,8 @@
 #include "display/nr-filter-blend.h"
 #include "display/nr-filter-offset.h"
 #include "display/nr-filter-composite.h"
+#include "display/nr-filter-diffuselighting.h"
+#include "display/nr-filter-specularlighting.h"
 
 #include "display/nr-arena-item.h"
 #include "libnr/nr-pixblock.h"
@@ -313,7 +315,7 @@ void Filter::_create_constructor_table()
     _constructor[NR_FILTER_COMPONENTTRANSFER] = NULL;
     _constructor[NR_FILTER_COMPOSITE] = &FilterComposite::create;
     _constructor[NR_FILTER_CONVOLVEMATRIX] = NULL;
-    _constructor[NR_FILTER_DIFFUSELIGHTING] = NULL;
+    _constructor[NR_FILTER_DIFFUSELIGHTING] = &FilterDiffuseLighting::create;
     _constructor[NR_FILTER_DISPLACEMENTMAP] = NULL;
     _constructor[NR_FILTER_FLOOD] = NULL;
     _constructor[NR_FILTER_GAUSSIANBLUR] = &FilterGaussian::create;
@@ -321,7 +323,7 @@ void Filter::_create_constructor_table()
     _constructor[NR_FILTER_MERGE] = NULL;
     _constructor[NR_FILTER_MORPHOLOGY] = NULL;
     _constructor[NR_FILTER_OFFSET] = &FilterOffset::create;
-    _constructor[NR_FILTER_SPECULARLIGHTING] = NULL;
+    _constructor[NR_FILTER_SPECULARLIGHTING] = &FilterSpecularLighting::create;
     _constructor[NR_FILTER_TILE] = NULL;
     _constructor[NR_FILTER_TURBULENCE] = NULL;
     created = true;
diff --git a/src/display/nr-light-types.h b/src/display/nr-light-types.h
new file mode 100644 (file)
index 0000000..8786546
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __NR_LIGHT_TYPES_H__
+#define __NR_LIGHT_TYPES_H__
+
+namespace NR {
+
+enum LightType{
+    NO_LIGHT = 0,
+    DISTANT_LIGHT,
+    POINT_LIGHT,
+    SPOT_LIGHT
+};
+
+} /* namespace NR */
+
+#endif // __NR_LIGHT_TYPES_H__
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-light.cpp b/src/display/nr-light.cpp
new file mode 100644 (file)
index 0000000..c2e6f1f
--- /dev/null
@@ -0,0 +1,119 @@
+#define __NR_LIGHT_CPP__
+
+/*
+ * Light rendering helpers
+ *
+ * Author:
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2006 Jean-Rene Reinhard
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <cmath>
+
+#include "libnr/nr-pixops.h"
+#include "display/nr-light.h"
+#include "display/nr-3dutils.h"
+#include "sp-fedistantlight.h"
+#include "sp-fepointlight.h"
+#include "sp-fespotlight.h"
+
+namespace NR {
+   
+DistantLight::DistantLight(SPFeDistantLight *light, guint32 lighting_color) {
+    color = lighting_color;
+    azimuth = M_PI / 180 * light->azimuth;
+    elevation = M_PI / 180 * light->elevation;
+}
+
+DistantLight::~DistantLight() {}
+
+void DistantLight::light_vector(Fvector &v) {
+    v[X_3D] = std::cos(azimuth)*std::cos(elevation);
+    v[Y_3D] = std::sin(azimuth)*std::cos(elevation);
+    v[Z_3D] = std::sin(elevation);
+} 
+
+void DistantLight::light_components(Fvector &lc) {
+    lc[LIGHT_RED] = NR_RGBA32_R(color);
+    lc[LIGHT_GREEN] = NR_RGBA32_G(color);
+    lc[LIGHT_BLUE] = NR_RGBA32_B(color);
+}
+
+PointLight::PointLight(SPFePointLight *light, guint32 lighting_color, const Matrix &trans) {
+    color = lighting_color;
+    l_x = light->x;
+    l_y = light->y;
+    l_z = light->z;
+    convert_coord(l_x, l_y, l_z, trans);
+}
+
+PointLight::~PointLight() {}
+
+void PointLight::light_vector(Fvector &v, gdouble x, gdouble y, gdouble z) {
+    v[X_3D] = l_x - x;
+    v[Y_3D] = l_y - y;
+    v[Z_3D] = l_z - z;
+    normalize_vector(v);
+} 
+
+void PointLight::light_components(Fvector &lc) {
+    lc[LIGHT_RED] = NR_RGBA32_R(color);
+    lc[LIGHT_GREEN] = NR_RGBA32_G(color);
+    lc[LIGHT_BLUE] = NR_RGBA32_B(color);
+}
+
+SpotLight::SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Matrix &trans) {
+    gdouble p_x, p_y, p_z;
+    color = lighting_color;
+    l_x = light->x;
+    l_y = light->y;
+    l_z = light->z;
+    p_x = light->pointsAtX;
+    p_y = light->pointsAtY;
+    p_z = light->pointsAtZ;
+    cos_lca = std::cos(M_PI / 180 * light->limitingConeAngle);
+    speExp = light->specularExponent;
+    convert_coord(l_x, l_y, l_z, trans);
+    convert_coord(p_x, p_y, p_z, trans);
+    S[X_3D] = p_x - l_x;
+    S[Y_3D] = p_y - l_y;
+    S[Z_3D] = p_z - l_z;
+    normalize_vector(S);
+    
+}
+
+SpotLight::~SpotLight() {}
+
+void SpotLight::light_vector(Fvector &v, gdouble x, gdouble y, gdouble z) {
+    v[X_3D] = l_x - x;
+    v[Y_3D] = l_y - y;
+    v[Z_3D] = l_z - z;
+    normalize_vector(v);
+} 
+
+void SpotLight::light_components(Fvector &lc, const Fvector &L) {
+    gdouble spmod = (-1) * scalar_product(L, S);
+    if (spmod <= cos_lca)
+        spmod = 0;
+    else
+        spmod = std::pow(spmod, speExp);
+    lc[LIGHT_RED] = spmod * NR_RGBA32_R(color);
+    lc[LIGHT_GREEN] = spmod * NR_RGBA32_G(color);
+    lc[LIGHT_BLUE] = spmod * NR_RGBA32_B(color);
+}
+
+} /* namespace NR */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-light.h b/src/display/nr-light.h
new file mode 100644 (file)
index 0000000..61c3c39
--- /dev/null
@@ -0,0 +1,160 @@
+#ifndef __NR_LIGHT_H__
+#define __NR_LIGHT_H__
+/** \file
+ * These classes provide tools to compute interesting objects relative to light
+ * sources. Each class provides a constructor converting information contained
+ * in a sp light object into information useful in the current setting, a
+ * method to get the light vector (at a given point) and a method to get the 
+ * light color components (at a given point).
+ */
+
+#include <gdk/gdktypes.h>
+#include "display/nr-3dutils.h"
+#include "display/nr-light-types.h"
+
+struct SPFeDistantLight;
+struct SPFePointLight;
+struct SPFeSpotLight;
+
+namespace NR {
+
+struct Matrix;
+
+enum LightComponent {
+    LIGHT_RED = 0,
+    LIGHT_GREEN,
+    LIGHT_BLUE
+};
+
+class DistantLight {
+    public:
+        /**
+         * Constructor
+         *
+         * \param light the sp light object
+         * \param lighting_color the lighting_color used
+         */
+        DistantLight(SPFeDistantLight *light, guint32 lighting_color);
+        ~DistantLight();
+        
+        /**
+         * Computes the light vector of the distant light
+         *
+         * \param v a Fvector referece where we store the result
+         */
+        void light_vector(Fvector &v);
+        
+        /**
+         * Computes the light components of the distant light
+         *
+         * \param lc a Fvector referece where we store the result, X=R, Y=G, Z=B
+         */
+        void light_components(Fvector &lc);
+
+    private:
+        guint32 color;
+        gdouble azimuth; //azimuth in rad
+        gdouble elevation; //elevation in rad
+};
+
+class PointLight {
+    public:
+        /**
+         * Constructor
+         *
+         * \param light the sp light object
+         * \param lighting_color the lighting_color used
+         * \param trans the transformation between absolute coordinate (those
+         * employed in the sp light object) and current coordinate (those
+         * employed in the rendering)
+         */
+        PointLight(SPFePointLight *light, guint32 lighting_color, const Matrix &trans);
+        ~PointLight();
+        /**
+         * Computes the light vector of the distant light at point (x,y,z).
+         * x, y and z are given in the arena_item coordinate, they are used as
+         * is
+         *
+         * \param v a Fvector referece where we store the result
+         * \param x x coordinate of the current point
+         * \param y y coordinate of the current point
+         * \param z z coordinate of the current point
+         */
+        void light_vector(Fvector &v, gdouble x, gdouble y, gdouble z);
+        
+        /**
+         * Computes the light components of the distant light
+         *
+         * \param lc a Fvector referece where we store the result, X=R, Y=G, Z=B
+         */
+        void light_components(Fvector &lc);
+
+    private:
+        guint32 color;
+        //light position coordinates in render setting
+        gdouble l_x;
+        gdouble l_y;
+        gdouble l_z;
+};
+
+class SpotLight {
+    public:
+        /**
+         * Constructor
+         *
+         * \param light the sp light object
+         * \param lighting_color the lighting_color used
+         * \param trans the transformation between absolute coordinate (those
+         * employed in the sp light object) and current coordinate (those
+         * employed in the rendering)
+         */
+        SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Matrix &trans);
+        ~SpotLight();
+
+        /**
+         * Computes the light vector of the distant light at point (x,y,z).
+         * x, y and z are given in the arena_item coordinate, they are used as
+         * is
+         *
+         * \param v a Fvector referece where we store the result
+         * \param x x coordinate of the current point
+         * \param y y coordinate of the current point
+         * \param z z coordinate of the current point
+         */
+        void light_vector(Fvector &v, gdouble x, gdouble y, gdouble z);
+
+        /**
+         * Computes the light components of the distant light at the current
+         * point. We only need the light vector to compute theses
+         *
+         * \param lc a Fvector referece where we store the result, X=R, Y=G, Z=B
+         * \param L the light vector of the current point
+         */
+        void light_components(Fvector &lc, const Fvector &L);
+
+    private:
+        guint32 color;
+        //light position coordinates in render setting
+        gdouble l_x;
+        gdouble l_y;
+        gdouble l_z;
+        gdouble cos_lca; //cos of the limiting cone angle
+        gdouble speExp; //specular exponent;
+        Fvector S; //unit vector from light position in the direction
+                   //the spot point at
+};
+
+
+} /* namespace NR */
+
+#endif // __NR_LIGHT_H__
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index d48c02c96d0978014c42a7a8cd5a7101f24a9649..543c16e8b03834536dabee69118a449baaefad58 100644 (file)
@@ -7,8 +7,10 @@
 /*
  * Authors:
  *   hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
  *
  * Copyright (C) 2006 Hugo Rodrigues
+ *               2007 authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
 #include "attributes.h"
 #include "svg/svg.h"
+#include "sp-object.h"
+#include "svg/svg-color.h"
 #include "sp-fediffuselighting.h"
 #include "xml/repr.h"
-
+#include "display/nr-filter-diffuselighting.h"
 
 /* FeDiffuseLighting base class */
 
@@ -32,7 +36,18 @@ static void sp_feDiffuseLighting_build(SPObject *object, SPDocument *document, I
 static void sp_feDiffuseLighting_release(SPObject *object);
 static void sp_feDiffuseLighting_set(SPObject *object, unsigned int key, gchar const *value);
 static void sp_feDiffuseLighting_update(SPObject *object, SPCtx *ctx, guint flags);
+//we assume that svg:feDiffuseLighting can have any number of children
+//only the first one is considered as the light source of the filter
+//TODO is that right?
+//if not modify child_added and remove_child to raise errors
+static void sp_feDiffuseLighting_child_added(SPObject *object,
+                                    Inkscape::XML::Node *child,
+                                    Inkscape::XML::Node *ref);
+static void sp_feDiffuseLighting_remove_child(SPObject *object, Inkscape::XML::Node *child);
+static void sp_feDiffuseLighting_order_changed(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref);
 static Inkscape::XML::Node *sp_feDiffuseLighting_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+static void sp_feDiffuseLighting_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter);
+static void sp_feDiffuseLighting_children_modified(SPFeDiffuseLighting *sp_diffuselighting);
 
 static SPFilterPrimitiveClass *feDiffuseLighting_parent_class;
 
@@ -61,7 +76,7 @@ static void
 sp_feDiffuseLighting_class_init(SPFeDiffuseLightingClass *klass)
 {
     SPObjectClass *sp_object_class = (SPObjectClass *)klass;
-
+    SPFilterPrimitiveClass *sp_primitive_class = (SPFilterPrimitiveClass *)klass;
     feDiffuseLighting_parent_class = (SPFilterPrimitiveClass*)g_type_class_peek_parent(klass);
 
     sp_object_class->build = sp_feDiffuseLighting_build;
@@ -69,11 +84,21 @@ sp_feDiffuseLighting_class_init(SPFeDiffuseLightingClass *klass)
     sp_object_class->write = sp_feDiffuseLighting_write;
     sp_object_class->set = sp_feDiffuseLighting_set;
     sp_object_class->update = sp_feDiffuseLighting_update;
+    sp_object_class->child_added = sp_feDiffuseLighting_child_added;
+    sp_object_class->remove_child = sp_feDiffuseLighting_remove_child;
+    sp_object_class->order_changed = sp_feDiffuseLighting_order_changed;
+
+    sp_primitive_class->build_renderer = sp_feDiffuseLighting_build_renderer;
 }
 
 static void
 sp_feDiffuseLighting_init(SPFeDiffuseLighting *feDiffuseLighting)
 {
+    feDiffuseLighting->surfaceScale = 1;
+    feDiffuseLighting->diffuseConstant = 1;
+    feDiffuseLighting->lighting_color = 0xffffffff;
+    //TODO kernelUnit
+    feDiffuseLighting->renderer = NULL;
 }
 
 /**
@@ -89,6 +114,11 @@ sp_feDiffuseLighting_build(SPObject *object, SPDocument *document, Inkscape::XML
     }
 
     /*LOAD ATTRIBUTES FROM REPR HERE*/
+    sp_object_read_attr(object, "surfaceScale");
+    sp_object_read_attr(object, "diffuseConstant");
+    sp_object_read_attr(object, "kernelUnitLength");
+    sp_object_read_attr(object, "lighting-color");
+    
 }
 
 /**
@@ -108,10 +138,40 @@ static void
 sp_feDiffuseLighting_set(SPObject *object, unsigned int key, gchar const *value)
 {
     SPFeDiffuseLighting *feDiffuseLighting = SP_FEDIFFUSELIGHTING(object);
-    (void)feDiffuseLighting;
-
+    
     switch(key) {
        /*DEAL WITH SETTING ATTRIBUTES HERE*/
+//TODO test forbidden values
+        case SP_ATTR_SURFACESCALE:
+            feDiffuseLighting->surfaceScale = g_ascii_strtod(value, NULL);
+            if (feDiffuseLighting->renderer) {
+                feDiffuseLighting->renderer->surfaceScale = feDiffuseLighting->surfaceScale;
+            }
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_DIFFUSECONSTANT:
+            feDiffuseLighting->diffuseConstant = g_ascii_strtod(value, NULL);
+            if (feDiffuseLighting->renderer) {
+                feDiffuseLighting->renderer->diffuseConstant = feDiffuseLighting->diffuseConstant;
+            }
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_KERNELUNITLENGTH:
+            //TODO kernelUnit
+            //feDiffuseLighting->kernelUnitLength.set(value);
+            /*TODOif (feDiffuseLighting->renderer) {
+                feDiffuseLighting->renderer->surfaceScale = feDiffuseLighting->renderer;
+            }
+            */
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_PROP_LIGHTING_COLOR:
+            feDiffuseLighting->lighting_color = sp_svg_read_color(value, 0xffffffff);
+            if (feDiffuseLighting->renderer) {
+                feDiffuseLighting->renderer->lighting_color = feDiffuseLighting->lighting_color;
+            }
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
         default:
             if (((SPObjectClass *) feDiffuseLighting_parent_class)->set)
                 ((SPObjectClass *) feDiffuseLighting_parent_class)->set(object, key, value);
@@ -126,11 +186,11 @@ sp_feDiffuseLighting_set(SPObject *object, unsigned int key, gchar const *value)
 static void
 sp_feDiffuseLighting_update(SPObject *object, SPCtx *ctx, guint flags)
 {
-    if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
-                 SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
-
-        /* do something to trigger redisplay, updates? */
-
+    if (flags & (SP_OBJECT_MODIFIED_FLAG)) {
+        sp_object_read_attr(object, "surfaceScale");
+        sp_object_read_attr(object, "diffuseConstant");
+        sp_object_read_attr(object, "kernelUnit");
+        sp_object_read_attr(object, "lighting-color");
     }
 
     if (((SPObjectClass *) feDiffuseLighting_parent_class)->update) {
@@ -144,16 +204,24 @@ sp_feDiffuseLighting_update(SPObject *object, SPCtx *ctx, guint flags)
 static Inkscape::XML::Node *
 sp_feDiffuseLighting_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
 {
+    SPFeDiffuseLighting *fediffuselighting = SP_FEDIFFUSELIGHTING(object);
+    
     // Inkscape-only object, not copied during an "plain SVG" dump:
     if (flags & SP_OBJECT_WRITE_EXT) {
         if (repr) {
             // is this sane?
-            repr->mergeFrom(SP_OBJECT_REPR(object), "id");
+            //repr->mergeFrom(SP_OBJECT_REPR(object), "id");
         } else {
             repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
         }
     }
 
+    sp_repr_set_css_double(repr, "surfaceScale", fediffuselighting->surfaceScale);
+    sp_repr_set_css_double(repr, "diffuseConstant", fediffuselighting->diffuseConstant);
+   /*TODO kernelUnits */ 
+    gchar c[64];
+    sp_svg_write_color(c, 64, fediffuselighting->lighting_color);
+    repr->setAttribute("lighting-color", c);
     if (((SPObjectClass *) feDiffuseLighting_parent_class)->write) {
         ((SPObjectClass *) feDiffuseLighting_parent_class)->write(object, repr, flags);
     }
@@ -161,6 +229,103 @@ sp_feDiffuseLighting_write(SPObject *object, Inkscape::XML::Node *repr, guint fl
     return repr;
 }
 
+/**
+ * Callback for child_added event.
+ */
+static void
+sp_feDiffuseLighting_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
+{
+    SPFeDiffuseLighting *f = SP_FEDIFFUSELIGHTING(object);
+
+    if (((SPObjectClass *) feDiffuseLighting_parent_class)->child_added)
+        (* ((SPObjectClass *) feDiffuseLighting_parent_class)->child_added)(object, child, ref);
+
+    sp_feDiffuseLighting_children_modified(f);
+    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+}
+            
+
+/**
+ * Callback for remove_child event.
+ */
+static void
+sp_feDiffuseLighting_remove_child(SPObject *object, Inkscape::XML::Node *child)
+{   
+    SPFeDiffuseLighting *f = SP_FEDIFFUSELIGHTING(object);
+
+    if (((SPObjectClass *) feDiffuseLighting_parent_class)->remove_child)
+        (* ((SPObjectClass *) feDiffuseLighting_parent_class)->remove_child)(object, child);   
+
+    sp_feDiffuseLighting_children_modified(f);
+    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+}
+
+static void
+sp_feDiffuseLighting_order_changed (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref)
+{
+    SPFeDiffuseLighting *f = SP_FEDIFFUSELIGHTING(object);
+    if (((SPObjectClass *) (feDiffuseLighting_parent_class))->order_changed)
+        (* ((SPObjectClass *) (feDiffuseLighting_parent_class))->order_changed) (object, child, old_ref, new_ref);
+
+    sp_feDiffuseLighting_children_modified(f);
+    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+}
+
+static void sp_feDiffuseLighting_children_modified(SPFeDiffuseLighting *sp_diffuselighting)
+{
+   if (sp_diffuselighting->renderer) {
+        sp_diffuselighting->renderer->light_type = NR::NO_LIGHT;
+        if (SP_IS_FEDISTANTLIGHT(sp_diffuselighting->children)) {
+            sp_diffuselighting->renderer->light_type = NR::DISTANT_LIGHT;
+            sp_diffuselighting->renderer->light.distant = SP_FEDISTANTLIGHT(sp_diffuselighting->children);
+        }
+        if (SP_IS_FEPOINTLIGHT(sp_diffuselighting->children)) {
+            sp_diffuselighting->renderer->light_type = NR::POINT_LIGHT;
+            sp_diffuselighting->renderer->light.point = SP_FEPOINTLIGHT(sp_diffuselighting->children);
+        }
+        if (SP_IS_FESPOTLIGHT(sp_diffuselighting->children)) {
+            sp_diffuselighting->renderer->light_type = NR::SPOT_LIGHT;
+            sp_diffuselighting->renderer->light.spot = SP_FESPOTLIGHT(sp_diffuselighting->children);
+        }
+   }
+}
+
+static void sp_feDiffuseLighting_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter) {
+    g_assert(primitive != NULL);
+    g_assert(filter != NULL);
+
+    SPFeDiffuseLighting *sp_diffuselighting = SP_FEDIFFUSELIGHTING(primitive);
+
+    int primitive_n = filter->add_primitive(NR::NR_FILTER_DIFFUSELIGHTING);
+    NR::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n);
+    NR::FilterDiffuseLighting *nr_diffuselighting = dynamic_cast<NR::FilterDiffuseLighting*>(nr_primitive);
+    g_assert(nr_diffuselighting != NULL);
+
+    sp_diffuselighting->renderer = nr_diffuselighting;
+    sp_filter_primitive_renderer_common(primitive, nr_primitive);
+
+    nr_diffuselighting->diffuseConstant = sp_diffuselighting->diffuseConstant;
+    nr_diffuselighting->surfaceScale = sp_diffuselighting->surfaceScale;
+    nr_diffuselighting->lighting_color = sp_diffuselighting->lighting_color;
+    //We assume there is at most one child
+    nr_diffuselighting->light_type = NR::NO_LIGHT;
+    if (SP_IS_FEDISTANTLIGHT(primitive->children)) {
+        nr_diffuselighting->light_type = NR::DISTANT_LIGHT;
+        nr_diffuselighting->light.distant = SP_FEDISTANTLIGHT(primitive->children);
+    }
+    if (SP_IS_FEPOINTLIGHT(primitive->children)) {
+        nr_diffuselighting->light_type = NR::POINT_LIGHT;
+        nr_diffuselighting->light.point = SP_FEPOINTLIGHT(primitive->children);
+    }
+    if (SP_IS_FESPOTLIGHT(primitive->children)) {
+        nr_diffuselighting->light_type = NR::SPOT_LIGHT;
+        nr_diffuselighting->light.spot = SP_FESPOTLIGHT(primitive->children);
+    }
+        
+    //nr_offset->set_dx(sp_offset->dx);
+    //nr_offset->set_dy(sp_offset->dy);
+}
+
 
 /*
   Local Variables:
index c937c2dd862c5f9a865dca42acbad78d1d25b697..15988b306663251bcf9d9fe2d87efe694de7dd32 100644 (file)
@@ -7,8 +7,10 @@
 /*
  * Authors:
  *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
  *
  * Copyright (C) 2006 Hugo Rodrigues
+ *               2007 authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 #include "sp-filter.h"
 #include "sp-fediffuselighting-fns.h"
 
+namespace NR {
+class FilterDiffuseLighting;
+}
+
 /* FeDiffuseLighting base class */
 class SPFeDiffuseLightingClass;
 
 struct SPFeDiffuseLighting : public SPFilterPrimitive {
     /** DIFFUSELIGHTING ATTRIBUTES HERE */
-    
+    gfloat surfaceScale;
+    gfloat diffuseConstant;
+    NumberOptNumber kernelUnitLength;
+    guint32 lighting_color;
+
+    NR::FilterDiffuseLighting *renderer;
 };
 
 struct SPFeDiffuseLightingClass {
diff --git a/src/sp-fedistantlight.cpp b/src/sp-fedistantlight.cpp
new file mode 100644 (file)
index 0000000..2b9ef8f
--- /dev/null
@@ -0,0 +1,209 @@
+#define __SP_FEDISTANTLIGHT_CPP__
+
+/** \file
+ * SVG <fedistantlight> implementation.
+ */
+/*
+ * Authors:
+ *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2006,2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include "attributes.h"
+#include "document.h"
+#include "sp-fedistantlight.h"
+#include "sp-fediffuselighting-fns.h"
+#include "sp-fespecularlighting-fns.h"
+#include "xml/repr.h"
+
+#define SP_MACROS_SILENT
+#include "macros.h"
+
+/* FeDistantLight class */
+
+static void sp_fedistantlight_class_init(SPFeDistantLightClass *klass);
+static void sp_fedistantlight_init(SPFeDistantLight *fedistantlight);
+
+static void sp_fedistantlight_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
+static void sp_fedistantlight_release(SPObject *object);
+static void sp_fedistantlight_set(SPObject *object, unsigned int key, gchar const *value);
+static void sp_fedistantlight_update(SPObject *object, SPCtx *ctx, guint flags);
+static Inkscape::XML::Node *sp_fedistantlight_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+
+static SPObjectClass *feDistantLight_parent_class;
+
+GType
+sp_fedistantlight_get_type()
+{
+    static GType fedistantlight_type = 0;
+
+    if (!fedistantlight_type) {
+        GTypeInfo fedistantlight_info = {
+            sizeof(SPFeDistantLightClass),
+            NULL, NULL,
+            (GClassInitFunc) sp_fedistantlight_class_init,
+            NULL, NULL,
+            sizeof(SPFeDistantLight),
+            16,
+            (GInstanceInitFunc) sp_fedistantlight_init,
+            NULL,    /* value_table */
+        };
+        fedistantlight_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeDistantLight", &fedistantlight_info, (GTypeFlags)0);
+    }
+    return fedistantlight_type;
+}
+
+static void
+sp_fedistantlight_class_init(SPFeDistantLightClass *klass)
+{
+
+    SPObjectClass *sp_object_class = (SPObjectClass *)klass;
+
+    feDistantLight_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass);
+
+    sp_object_class->build = sp_fedistantlight_build;
+    sp_object_class->release = sp_fedistantlight_release;
+    sp_object_class->write = sp_fedistantlight_write;
+    sp_object_class->set = sp_fedistantlight_set;
+    sp_object_class->update = sp_fedistantlight_update;
+}
+
+static void
+sp_fedistantlight_init(SPFeDistantLight *fedistantlight)
+{
+    fedistantlight->azimuth = 0;
+    fedistantlight->elevation = 0;
+}
+
+/**
+ * Reads the Inkscape::XML::Node, and initializes SPDistantLight variables.  For this to get called,
+ * our name must be associated with a repr via "sp_object_type_register".  Best done through
+ * sp-object-repr.cpp's repr_name_entries array.
+ */
+static void
+sp_fedistantlight_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
+{
+    if (((SPObjectClass *) feDistantLight_parent_class)->build) {
+        ((SPObjectClass *) feDistantLight_parent_class)->build(object, document, repr);
+    }
+
+    //Read values of key attributes from XML nodes into object.
+    sp_object_read_attr(object, "azimuth");
+    sp_object_read_attr(object, "elevation");
+
+//is this necessary?
+    sp_document_add_resource(document, "fedistantlight", object);
+}
+
+/**
+ * Drops any allocated memory.
+ */
+static void
+sp_fedistantlight_release(SPObject *object)
+{
+    //SPFeDistantLight *fedistantlight = SP_FEDISTANTLIGHT(object);
+
+    if (SP_OBJECT_DOCUMENT(object)) {
+        /* Unregister ourselves */
+        sp_document_remove_resource(SP_OBJECT_DOCUMENT(object), "fedistantlight", SP_OBJECT(object));
+    }
+
+//TODO: release resources here
+}
+
+/**
+ * Sets a specific value in the SPFeDistantLight.
+ */
+static void
+sp_fedistantlight_set(SPObject *object, unsigned int key, gchar const *value)
+{
+    SPFeDistantLight *fedistantlight = SP_FEDISTANTLIGHT(object);
+
+    switch (key) {
+    case SP_ATTR_AZIMUTH:
+        fedistantlight->azimuth = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_ELEVATION:
+        fedistantlight->elevation = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    default:
+        // See if any parents need this value. 
+        if (((SPObjectClass *) feDistantLight_parent_class)->set) {
+            ((SPObjectClass *) feDistantLight_parent_class)->set(object, key, value);
+        }
+        break;
+    }
+}
+
+/**
+ *  * Receives update notifications.
+ *   */
+static void
+sp_fedistantlight_update(SPObject *object, SPCtx *ctx, guint flags)
+{
+    SPFeDistantLight *feDistantLight = SP_FEDISTANTLIGHT(object);
+
+    if (flags & SP_OBJECT_MODIFIED_FLAG) {
+        /* do something to trigger redisplay, updates? */
+        sp_object_read_attr(object, "azimuth");
+        sp_object_read_attr(object, "elevation");
+    }
+    
+    if (((SPObjectClass *) feDistantLight_parent_class)->update) {
+        ((SPObjectClass *) feDistantLight_parent_class)->update(object, ctx, flags);
+    }
+}
+
+/**
+ * Writes its settings to an incoming repr object, if any.
+ */
+static Inkscape::XML::Node *
+sp_fedistantlight_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
+{
+    SPFeDistantLight *fedistantlight = SP_FEDISTANTLIGHT(object);
+
+    if (!repr) {
+        repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
+    }
+
+    sp_repr_set_css_double(repr, "azimuth", fedistantlight->azimuth);
+    sp_repr_set_css_double(repr, "elevation", fedistantlight->elevation);
+    
+    if (((SPObjectClass *) feDistantLight_parent_class)->write) {
+        ((SPObjectClass *) feDistantLight_parent_class)->write(object, repr, flags);
+    }
+
+    return repr;
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/sp-fedistantlight.h b/src/sp-fedistantlight.h
new file mode 100644 (file)
index 0000000..32a63f6
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef SP_FEDISTANTLIGHT_H_SEEN
+#define SP_FEDISTANTLIGHT_H_SEEN
+
+/** \file
+ * SVG <filter> implementation, see sp-filter.cpp.
+ */
+/*
+ * Authors:
+ *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2006,2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "sp-object.h"
+
+#define SP_TYPE_FEDISTANTLIGHT (sp_fedistantlight_get_type())
+#define SP_FEDISTANTLIGHT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEDISTANTLIGHT, SPFeDistantLight))
+#define SP_FEDISTANTLIGHT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEDISTANTLIGHT, SPFeDistantLightClass))
+#define SP_IS_FEDISTANTLIGHT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEDISTANTLIGHT))
+#define SP_IS_FEDISTANTLIGHT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEDISTANTLIGHT))
+
+/* Distant light class */
+
+
+class SPFeDistantLight;
+class SPFeDistantLightClass;
+
+struct SPFeDistantLight : public SPObject {
+
+    /** azimuth attribute */
+    gfloat azimuth;
+    /** elevation attribute */
+    gfloat elevation;
+
+    //other fields
+};
+
+struct SPFeDistantLightClass {
+    SPObjectClass parent_class;
+};
+
+GType
+sp_fedistantlight_get_type();
+#endif /* !SP_FEDISTANTLIGHT_H_SEEN */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/sp-fepointlight.cpp b/src/sp-fepointlight.cpp
new file mode 100644 (file)
index 0000000..9d912da
--- /dev/null
@@ -0,0 +1,221 @@
+#define __SP_FEPOINTLIGHT_CPP__
+
+/** \file
+ * SVG <fepointlight> implementation.
+ */
+/*
+ * Authors:
+ *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2006,2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include "attributes.h"
+#include "document.h"
+#include "sp-fepointlight.h"
+#include "sp-fediffuselighting-fns.h"
+#include "sp-fespecularlighting-fns.h"
+#include "xml/repr.h"
+
+#define SP_MACROS_SILENT
+#include "macros.h"
+
+/* FePointLight class */
+
+static void sp_fepointlight_class_init(SPFePointLightClass *klass);
+static void sp_fepointlight_init(SPFePointLight *fepointlight);
+
+static void sp_fepointlight_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
+static void sp_fepointlight_release(SPObject *object);
+static void sp_fepointlight_set(SPObject *object, unsigned int key, gchar const *value);
+static void sp_fepointlight_update(SPObject *object, SPCtx *ctx, guint flags);
+static Inkscape::XML::Node *sp_fepointlight_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+
+static SPObjectClass *fePointLight_parent_class;
+
+GType
+sp_fepointlight_get_type()
+{
+    static GType fepointlight_type = 0;
+
+    if (!fepointlight_type) {
+        GTypeInfo fepointlight_info = {
+            sizeof(SPFePointLightClass),
+            NULL, NULL,
+            (GClassInitFunc) sp_fepointlight_class_init,
+            NULL, NULL,
+            sizeof(SPFePointLight),
+            16,
+            (GInstanceInitFunc) sp_fepointlight_init,
+            NULL,    /* value_table */
+        };
+        fepointlight_type = g_type_register_static(SP_TYPE_OBJECT, "SPFePointLight", &fepointlight_info, (GTypeFlags)0);
+    }
+    return fepointlight_type;
+}
+
+static void
+sp_fepointlight_class_init(SPFePointLightClass *klass)
+{
+
+    SPObjectClass *sp_object_class = (SPObjectClass *)klass;
+
+    fePointLight_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass);
+
+    sp_object_class->build = sp_fepointlight_build;
+    sp_object_class->release = sp_fepointlight_release;
+    sp_object_class->write = sp_fepointlight_write;
+    sp_object_class->set = sp_fepointlight_set;
+    sp_object_class->update = sp_fepointlight_update;
+}
+
+static void
+sp_fepointlight_init(SPFePointLight *fepointlight)
+{
+    fepointlight->x = 0;
+    fepointlight->y = 0;
+    fepointlight->z = 0;
+}
+
+/**
+ * Reads the Inkscape::XML::Node, and initializes SPPointLight variables.  For this to get called,
+ * our name must be associated with a repr via "sp_object_type_register".  Best done through
+ * sp-object-repr.cpp's repr_name_entries array.
+ */
+static void
+sp_fepointlight_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
+{
+    if (((SPObjectClass *) fePointLight_parent_class)->build) {
+        ((SPObjectClass *) fePointLight_parent_class)->build(object, document, repr);
+    }
+
+    //Read values of key attributes from XML nodes into object.
+    sp_object_read_attr(object, "x");
+    sp_object_read_attr(object, "y");
+    sp_object_read_attr(object, "z");
+
+//is this necessary?
+    sp_document_add_resource(document, "fepointlight", object);
+}
+
+/**
+ * Drops any allocated memory.
+ */
+static void
+sp_fepointlight_release(SPObject *object)
+{
+    //SPFePointLight *fepointlight = SP_FEPOINTLIGHT(object);
+
+    if (SP_OBJECT_DOCUMENT(object)) {
+        /* Unregister ourselves */
+        sp_document_remove_resource(SP_OBJECT_DOCUMENT(object), "fepointlight", SP_OBJECT(object));
+    }
+
+//TODO: release resources here
+}
+
+/**
+ * Sets a specific value in the SPFePointLight.
+ */
+static void
+sp_fepointlight_set(SPObject *object, unsigned int key, gchar const *value)
+{
+    SPFePointLight *fepointlight = SP_FEPOINTLIGHT(object);
+
+    switch (key) {
+    case SP_ATTR_X:
+        fepointlight->x = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_Y:
+        fepointlight->y = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_Z:
+        fepointlight->z = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    default:
+        // See if any parents need this value. 
+        if (((SPObjectClass *) fePointLight_parent_class)->set) {
+            ((SPObjectClass *) fePointLight_parent_class)->set(object, key, value);
+        }
+        break;
+    }
+}
+
+/**
+ *  * Receives update notifications.
+ *   */
+static void
+sp_fepointlight_update(SPObject *object, SPCtx *ctx, guint flags)
+{
+    SPFePointLight *fePointLight = SP_FEPOINTLIGHT(object);
+
+    if (flags & SP_OBJECT_MODIFIED_FLAG) {
+        /* do something to trigger redisplay, updates? */
+        sp_object_read_attr(object, "x");
+        sp_object_read_attr(object, "y");
+        sp_object_read_attr(object, "z");
+    }
+    
+    if (((SPObjectClass *) fePointLight_parent_class)->update) {
+        ((SPObjectClass *) fePointLight_parent_class)->update(object, ctx, flags);
+    }
+}
+
+/**
+ * Writes its settings to an incoming repr object, if any.
+ */
+static Inkscape::XML::Node *
+sp_fepointlight_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
+{
+    SPFePointLight *fepointlight = SP_FEPOINTLIGHT(object);
+
+    if (!repr) {
+        repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
+    }
+
+    sp_repr_set_css_double(repr, "x", fepointlight->x);
+    sp_repr_set_css_double(repr, "y", fepointlight->y);
+    sp_repr_set_css_double(repr, "z", fepointlight->z);
+    
+    if (((SPObjectClass *) fePointLight_parent_class)->write) {
+        ((SPObjectClass *) fePointLight_parent_class)->write(object, repr, flags);
+    }
+
+    return repr;
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/sp-fepointlight.h b/src/sp-fepointlight.h
new file mode 100644 (file)
index 0000000..88d3998
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef SP_FEPOINTLIGHT_H_SEEN
+#define SP_FEPOINTLIGHT_H_SEEN
+
+/** \file
+ * SVG <filter> implementation, see sp-filter.cpp.
+ */
+/*
+ * Authors:
+ *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2006,2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "sp-object.h"
+
+#define SP_TYPE_FEPOINTLIGHT (sp_fepointlight_get_type())
+#define SP_FEPOINTLIGHT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEPOINTLIGHT, SPFePointLight))
+#define SP_FEPOINTLIGHT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEPOINTLIGHT, SPFePointLightClass))
+#define SP_IS_FEPOINTLIGHT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEPOINTLIGHT))
+#define SP_IS_FEPOINTLIGHT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEPOINTLIGHT))
+
+/* Distant light class */
+
+
+class SPFePointLight;
+class SPFePointLightClass;
+
+struct SPFePointLight : public SPObject {
+
+    /** x coordinate of the light source */
+    gfloat x; 
+    /** y coordinate of the light source */
+    gfloat y; 
+    /** z coordinate of the light source */
+    gfloat z; 
+
+    //other fields
+};
+
+struct SPFePointLightClass {
+    SPObjectClass parent_class;
+};
+
+GType
+sp_fepointlight_get_type();
+#endif /* !SP_FEPOINTLIGHT_H_SEEN */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index cc9837041b0df00f353938cfc565a05b7803b0e7..85f2aa862a6fba9cc4238a13501641d1f8faa046 100644 (file)
@@ -7,8 +7,10 @@
 /*
  * Authors:
  *   hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
  *
  * Copyright (C) 2006 Hugo Rodrigues
+ *               2007 authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
 #include "attributes.h"
 #include "svg/svg.h"
+#include "sp-object.h"
+#include "svg/svg-color.h"
 #include "sp-fespecularlighting.h"
 #include "xml/repr.h"
-
+#include "display/nr-filter-specularlighting.h"
 
 /* FeSpecularLighting base class */
 
@@ -32,7 +36,18 @@ static void sp_feSpecularLighting_build(SPObject *object, SPDocument *document,
 static void sp_feSpecularLighting_release(SPObject *object);
 static void sp_feSpecularLighting_set(SPObject *object, unsigned int key, gchar const *value);
 static void sp_feSpecularLighting_update(SPObject *object, SPCtx *ctx, guint flags);
+//we assume that svg:feSpecularLighting can have any number of children
+//only the first one is considered as the light source of the filter
+//TODO is that right?
+//if not modify child_added and remove_child to raise errors
+static void sp_feSpecularLighting_child_added(SPObject *object,
+                                    Inkscape::XML::Node *child,
+                                    Inkscape::XML::Node *ref);
+static void sp_feSpecularLighting_remove_child(SPObject *object, Inkscape::XML::Node *child);
+static void sp_feSpecularLighting_order_changed(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref);
 static Inkscape::XML::Node *sp_feSpecularLighting_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+static void sp_feSpecularLighting_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter);
+static void sp_feSpecularLighting_children_modified(SPFeSpecularLighting *sp_specularlighting);
 
 static SPFilterPrimitiveClass *feSpecularLighting_parent_class;
 
@@ -61,7 +76,7 @@ static void
 sp_feSpecularLighting_class_init(SPFeSpecularLightingClass *klass)
 {
     SPObjectClass *sp_object_class = (SPObjectClass *)klass;
-
+    SPFilterPrimitiveClass *sp_primitive_class = (SPFilterPrimitiveClass *)klass;
     feSpecularLighting_parent_class = (SPFilterPrimitiveClass*)g_type_class_peek_parent(klass);
 
     sp_object_class->build = sp_feSpecularLighting_build;
@@ -69,11 +84,22 @@ sp_feSpecularLighting_class_init(SPFeSpecularLightingClass *klass)
     sp_object_class->write = sp_feSpecularLighting_write;
     sp_object_class->set = sp_feSpecularLighting_set;
     sp_object_class->update = sp_feSpecularLighting_update;
+    sp_object_class->child_added = sp_feSpecularLighting_child_added;
+    sp_object_class->remove_child = sp_feSpecularLighting_remove_child;
+    sp_object_class->order_changed = sp_feSpecularLighting_order_changed;
+
+    sp_primitive_class->build_renderer = sp_feSpecularLighting_build_renderer;
 }
 
 static void
 sp_feSpecularLighting_init(SPFeSpecularLighting *feSpecularLighting)
 {
+    feSpecularLighting->surfaceScale = 1;
+    feSpecularLighting->specularConstant = 1;
+    feSpecularLighting->specularExponent = 1;
+    feSpecularLighting->lighting_color = 0xffffffff;
+    //TODO kernelUnit
+    feSpecularLighting->renderer = NULL;
 }
 
 /**
@@ -89,6 +115,12 @@ sp_feSpecularLighting_build(SPObject *object, SPDocument *document, Inkscape::XM
     }
 
     /*LOAD ATTRIBUTES FROM REPR HERE*/
+    sp_object_read_attr(object, "surfaceScale");
+    sp_object_read_attr(object, "specularConstant");
+    sp_object_read_attr(object, "specularExponent");
+    sp_object_read_attr(object, "kernelUnitLength");
+    sp_object_read_attr(object, "lighting-color");
+    
 }
 
 /**
@@ -108,10 +140,47 @@ static void
 sp_feSpecularLighting_set(SPObject *object, unsigned int key, gchar const *value)
 {
     SPFeSpecularLighting *feSpecularLighting = SP_FESPECULARLIGHTING(object);
-    (void)feSpecularLighting;
-
+    
     switch(key) {
        /*DEAL WITH SETTING ATTRIBUTES HERE*/
+//TODO test forbidden values
+        case SP_ATTR_SURFACESCALE:
+            feSpecularLighting->surfaceScale = g_ascii_strtod(value, NULL);
+            if (feSpecularLighting->renderer) {
+                feSpecularLighting->renderer->surfaceScale = feSpecularLighting->surfaceScale;
+            }
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_SPECULARCONSTANT:
+            feSpecularLighting->specularConstant = g_ascii_strtod(value, NULL);
+            if (feSpecularLighting->renderer) {
+                feSpecularLighting->renderer->specularConstant = feSpecularLighting->specularConstant;
+            }
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_SPECULAREXPONENT:
+            feSpecularLighting->specularExponent = g_ascii_strtod(value, NULL);
+            if (feSpecularLighting->renderer) {
+                feSpecularLighting->renderer->specularExponent = feSpecularLighting->specularExponent;
+            }
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_KERNELUNITLENGTH:
+            //TODO kernelUnit
+            //feSpecularLighting->kernelUnitLength.set(value);
+            /*TODOif (feSpecularLighting->renderer) {
+                feSpecularLighting->renderer->surfaceScale = feSpecularLighting->renderer;
+            }
+            */
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_PROP_LIGHTING_COLOR:
+            feSpecularLighting->lighting_color = sp_svg_read_color(value, 0xffffffff);
+            if (feSpecularLighting->renderer) {
+                feSpecularLighting->renderer->lighting_color = feSpecularLighting->lighting_color;
+            }
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
         default:
             if (((SPObjectClass *) feSpecularLighting_parent_class)->set)
                 ((SPObjectClass *) feSpecularLighting_parent_class)->set(object, key, value);
@@ -126,11 +195,12 @@ sp_feSpecularLighting_set(SPObject *object, unsigned int key, gchar const *value
 static void
 sp_feSpecularLighting_update(SPObject *object, SPCtx *ctx, guint flags)
 {
-    if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
-                 SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
-
-        /* do something to trigger redisplay, updates? */
-
+    if (flags & (SP_OBJECT_MODIFIED_FLAG)) {
+        sp_object_read_attr(object, "surfaceScale");
+        sp_object_read_attr(object, "specularConstant");
+        sp_object_read_attr(object, "specularExponent");
+        sp_object_read_attr(object, "kernelUnitLength");
+        sp_object_read_attr(object, "lighting-color");
     }
 
     if (((SPObjectClass *) feSpecularLighting_parent_class)->update) {
@@ -144,16 +214,25 @@ sp_feSpecularLighting_update(SPObject *object, SPCtx *ctx, guint flags)
 static Inkscape::XML::Node *
 sp_feSpecularLighting_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
 {
+    SPFeSpecularLighting *fespecularlighting = SP_FESPECULARLIGHTING(object);
+    
     // Inkscape-only object, not copied during an "plain SVG" dump:
     if (flags & SP_OBJECT_WRITE_EXT) {
         if (repr) {
             // is this sane?
-            repr->mergeFrom(SP_OBJECT_REPR(object), "id");
+            //repr->mergeFrom(SP_OBJECT_REPR(object), "id");
         } else {
             repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
         }
     }
 
+    sp_repr_set_css_double(repr, "surfaceScale", fespecularlighting->surfaceScale);
+    sp_repr_set_css_double(repr, "specularConstant", fespecularlighting->specularConstant);
+    sp_repr_set_css_double(repr, "specularExponent", fespecularlighting->specularExponent);
+   /*TODO kernelUnits */ 
+    gchar c[64];
+    sp_svg_write_color(c, 64, fespecularlighting->lighting_color);
+    repr->setAttribute("lighting-color", c);
     if (((SPObjectClass *) feSpecularLighting_parent_class)->write) {
         ((SPObjectClass *) feSpecularLighting_parent_class)->write(object, repr, flags);
     }
@@ -161,6 +240,104 @@ sp_feSpecularLighting_write(SPObject *object, Inkscape::XML::Node *repr, guint f
     return repr;
 }
 
+/**
+ * Callback for child_added event.
+ */
+static void
+sp_feSpecularLighting_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
+{
+    SPFeSpecularLighting *f = SP_FESPECULARLIGHTING(object);
+
+    if (((SPObjectClass *) feSpecularLighting_parent_class)->child_added)
+        (* ((SPObjectClass *) feSpecularLighting_parent_class)->child_added)(object, child, ref);
+
+    sp_feSpecularLighting_children_modified(f);
+    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+}
+            
+
+/**
+ * Callback for remove_child event.
+ */
+static void
+sp_feSpecularLighting_remove_child(SPObject *object, Inkscape::XML::Node *child)
+{   
+    SPFeSpecularLighting *f = SP_FESPECULARLIGHTING(object);
+
+    if (((SPObjectClass *) feSpecularLighting_parent_class)->remove_child)
+        (* ((SPObjectClass *) feSpecularLighting_parent_class)->remove_child)(object, child);   
+
+    sp_feSpecularLighting_children_modified(f);
+    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+}
+
+static void
+sp_feSpecularLighting_order_changed (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref)
+{
+    SPFeSpecularLighting *f = SP_FESPECULARLIGHTING(object);
+    if (((SPObjectClass *) (feSpecularLighting_parent_class))->order_changed)
+        (* ((SPObjectClass *) (feSpecularLighting_parent_class))->order_changed) (object, child, old_ref, new_ref);
+
+    sp_feSpecularLighting_children_modified(f);
+    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+}
+
+static void sp_feSpecularLighting_children_modified(SPFeSpecularLighting *sp_specularlighting)
+{
+   if (sp_specularlighting->renderer) {
+        sp_specularlighting->renderer->light_type = NR::NO_LIGHT;
+        if (SP_IS_FEDISTANTLIGHT(sp_specularlighting->children)) {
+            sp_specularlighting->renderer->light_type = NR::DISTANT_LIGHT;
+            sp_specularlighting->renderer->light.distant = SP_FEDISTANTLIGHT(sp_specularlighting->children);
+        }
+        if (SP_IS_FEPOINTLIGHT(sp_specularlighting->children)) {
+            sp_specularlighting->renderer->light_type = NR::POINT_LIGHT;
+            sp_specularlighting->renderer->light.point = SP_FEPOINTLIGHT(sp_specularlighting->children);
+        }
+        if (SP_IS_FESPOTLIGHT(sp_specularlighting->children)) {
+            sp_specularlighting->renderer->light_type = NR::SPOT_LIGHT;
+            sp_specularlighting->renderer->light.spot = SP_FESPOTLIGHT(sp_specularlighting->children);
+        }
+   }
+}
+
+static void sp_feSpecularLighting_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter) {
+    g_assert(primitive != NULL);
+    g_assert(filter != NULL);
+
+    SPFeSpecularLighting *sp_specularlighting = SP_FESPECULARLIGHTING(primitive);
+
+    int primitive_n = filter->add_primitive(NR::NR_FILTER_SPECULARLIGHTING);
+    NR::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n);
+    NR::FilterSpecularLighting *nr_specularlighting = dynamic_cast<NR::FilterSpecularLighting*>(nr_primitive);
+    g_assert(nr_specularlighting != NULL);
+
+    sp_specularlighting->renderer = nr_specularlighting;
+    sp_filter_primitive_renderer_common(primitive, nr_primitive);
+
+    nr_specularlighting->specularConstant = sp_specularlighting->specularConstant;
+    nr_specularlighting->specularExponent = sp_specularlighting->specularExponent;
+    nr_specularlighting->surfaceScale = sp_specularlighting->surfaceScale;
+    nr_specularlighting->lighting_color = sp_specularlighting->lighting_color;
+    //We assume there is at most one child
+    nr_specularlighting->light_type = NR::NO_LIGHT;
+    if (SP_IS_FEDISTANTLIGHT(primitive->children)) {
+        nr_specularlighting->light_type = NR::DISTANT_LIGHT;
+        nr_specularlighting->light.distant = SP_FEDISTANTLIGHT(primitive->children);
+    }
+    if (SP_IS_FEPOINTLIGHT(primitive->children)) {
+        nr_specularlighting->light_type = NR::POINT_LIGHT;
+        nr_specularlighting->light.point = SP_FEPOINTLIGHT(primitive->children);
+    }
+    if (SP_IS_FESPOTLIGHT(primitive->children)) {
+        nr_specularlighting->light_type = NR::SPOT_LIGHT;
+        nr_specularlighting->light.spot = SP_FESPOTLIGHT(primitive->children);
+    }
+        
+    //nr_offset->set_dx(sp_offset->dx);
+    //nr_offset->set_dy(sp_offset->dy);
+}
+
 
 /*
   Local Variables:
index 3c0887f157f46c829dccf675646b472bb1e79810..9aa38b53e807fcc07e11233b755fb43becfca9bc 100644 (file)
@@ -7,8 +7,10 @@
 /*
  * Authors:
  *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
  *
  * Copyright (C) 2006 Hugo Rodrigues
+ *               2007 authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 #include "sp-filter.h"
 #include "sp-fespecularlighting-fns.h"
 
+namespace NR {
+class FilterSpecularLighting;
+}
+
 /* FeSpecularLighting base class */
 class SPFeSpecularLightingClass;
 
 struct SPFeSpecularLighting : public SPFilterPrimitive {
     /** SPECULARLIGHTING ATTRIBUTES HERE */
-    
+    gfloat surfaceScale;
+    gfloat specularConstant;
+    gfloat specularExponent;
+    NumberOptNumber kernelUnitLength;
+    guint32 lighting_color;
+
+    NR::FilterSpecularLighting *renderer;
 };
 
 struct SPFeSpecularLightingClass {
diff --git a/src/sp-fespotlight.cpp b/src/sp-fespotlight.cpp
new file mode 100644 (file)
index 0000000..d5ae530
--- /dev/null
@@ -0,0 +1,281 @@
+#define __SP_FESPOTLIGHT_CPP__
+
+/** \file
+ * SVG <fespotlight> implementation.
+ */
+/*
+ * Authors:
+ *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2006,2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include "attributes.h"
+#include "document.h"
+#include "sp-fespotlight.h"
+#include "sp-fediffuselighting-fns.h"
+#include "sp-fespecularlighting-fns.h"
+#include "xml/repr.h"
+
+#define SP_MACROS_SILENT
+#include "macros.h"
+
+/* FeSpotLight class */
+
+static void sp_fespotlight_class_init(SPFeSpotLightClass *klass);
+static void sp_fespotlight_init(SPFeSpotLight *fespotlight);
+
+static void sp_fespotlight_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
+static void sp_fespotlight_release(SPObject *object);
+static void sp_fespotlight_set(SPObject *object, unsigned int key, gchar const *value);
+static void sp_fespotlight_update(SPObject *object, SPCtx *ctx, guint flags);
+static Inkscape::XML::Node *sp_fespotlight_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+
+static SPObjectClass *feSpotLight_parent_class;
+
+GType
+sp_fespotlight_get_type()
+{
+    static GType fespotlight_type = 0;
+
+    if (!fespotlight_type) {
+        GTypeInfo fespotlight_info = {
+            sizeof(SPFeSpotLightClass),
+            NULL, NULL,
+            (GClassInitFunc) sp_fespotlight_class_init,
+            NULL, NULL,
+            sizeof(SPFeSpotLight),
+            16,
+            (GInstanceInitFunc) sp_fespotlight_init,
+            NULL,    /* value_table */
+        };
+        fespotlight_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeSpotLight", &fespotlight_info, (GTypeFlags)0);
+    }
+    return fespotlight_type;
+}
+
+static void
+sp_fespotlight_class_init(SPFeSpotLightClass *klass)
+{
+
+    SPObjectClass *sp_object_class = (SPObjectClass *)klass;
+
+    feSpotLight_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass);
+
+    sp_object_class->build = sp_fespotlight_build;
+    sp_object_class->release = sp_fespotlight_release;
+    sp_object_class->write = sp_fespotlight_write;
+    sp_object_class->set = sp_fespotlight_set;
+    sp_object_class->update = sp_fespotlight_update;
+}
+
+static void
+sp_fespotlight_init(SPFeSpotLight *fespotlight)
+{
+    fespotlight->x = 0;
+    fespotlight->y = 0;
+    fespotlight->z = 0;
+    fespotlight->pointsAtX = 0;
+    fespotlight->pointsAtY = 0;
+    fespotlight->pointsAtZ = 0;
+    fespotlight->specularExponent = 1;
+    fespotlight->limitingConeAngle = 90;
+}
+
+/**
+ * Reads the Inkscape::XML::Node, and initializes SPPointLight variables.  For this to get called,
+ * our name must be associated with a repr via "sp_object_type_register".  Best done through
+ * sp-object-repr.cpp's repr_name_entries array.
+ */
+static void
+sp_fespotlight_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
+{
+    if (((SPObjectClass *) feSpotLight_parent_class)->build) {
+        ((SPObjectClass *) feSpotLight_parent_class)->build(object, document, repr);
+    }
+
+    //Read values of key attributes from XML nodes into object.
+    sp_object_read_attr(object, "x");
+    sp_object_read_attr(object, "y");
+    sp_object_read_attr(object, "z");
+    sp_object_read_attr(object, "pointsAtX");
+    sp_object_read_attr(object, "pointsAtY");
+    sp_object_read_attr(object, "pointsAtZ");
+    sp_object_read_attr(object, "specularExponent");
+    sp_object_read_attr(object, "limitingConeAngle");
+
+//is this necessary?
+    sp_document_add_resource(document, "fespotlight", object);
+}
+
+/**
+ * Drops any allocated memory.
+ */
+static void
+sp_fespotlight_release(SPObject *object)
+{
+    //SPFeSpotLight *fespotlight = SP_FESPOTLIGHT(object);
+
+    if (SP_OBJECT_DOCUMENT(object)) {
+        /* Unregister ourselves */
+        sp_document_remove_resource(SP_OBJECT_DOCUMENT(object), "fespotlight", SP_OBJECT(object));
+    }
+
+//TODO: release resources here
+}
+
+/**
+ * Sets a specific value in the SPFeSpotLight.
+ */
+static void
+sp_fespotlight_set(SPObject *object, unsigned int key, gchar const *value)
+{
+    SPFeSpotLight *fespotlight = SP_FESPOTLIGHT(object);
+
+    switch (key) {
+    case SP_ATTR_X:
+        fespotlight->x = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_Y:
+        fespotlight->y = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_Z:
+        fespotlight->z = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_POINTSATX:
+        fespotlight->pointsAtX = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_POINTSATY:
+        fespotlight->pointsAtY = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_POINTSATZ:
+        fespotlight->pointsAtZ = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_SPECULAREXPONENT:
+        fespotlight->specularExponent = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    case SP_ATTR_LIMITINGCONEANGLE:
+        fespotlight->limitingConeAngle = g_ascii_strtod(value, NULL);
+        if (object->parent &&
+                (SP_IS_FEDIFFUSELIGHTING(object->parent) ||
+                 SP_IS_FESPECULARLIGHTING(object->parent))) {
+            object->parent->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+        break;
+    default:
+        // See if any parents need this value. 
+        if (((SPObjectClass *) feSpotLight_parent_class)->set) {
+            ((SPObjectClass *) feSpotLight_parent_class)->set(object, key, value);
+        }
+        break;
+    }
+}
+
+/**
+ *  * Receives update notifications.
+ *   */
+static void
+sp_fespotlight_update(SPObject *object, SPCtx *ctx, guint flags)
+{
+    SPFeSpotLight *feSpotLight = SP_FESPOTLIGHT(object);
+
+    if (flags & SP_OBJECT_MODIFIED_FLAG) {
+        /* do something to trigger redisplay, updates? */
+        sp_object_read_attr(object, "x");
+        sp_object_read_attr(object, "y");
+        sp_object_read_attr(object, "z");
+        sp_object_read_attr(object, "pointsAtX");
+        sp_object_read_attr(object, "pointsAtY");
+        sp_object_read_attr(object, "pointsAtZ");
+        sp_object_read_attr(object, "specularExponent");
+        sp_object_read_attr(object, "limitingConeAngle");
+    }
+    
+    if (((SPObjectClass *) feSpotLight_parent_class)->update) {
+        ((SPObjectClass *) feSpotLight_parent_class)->update(object, ctx, flags);
+    }
+}
+
+/**
+ * Writes its settings to an incoming repr object, if any.
+ */
+static Inkscape::XML::Node *
+sp_fespotlight_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
+{
+    SPFeSpotLight *fespotlight = SP_FESPOTLIGHT(object);
+
+    if (!repr) {
+        repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
+    }
+
+    sp_repr_set_css_double(repr, "x", fespotlight->x);
+    sp_repr_set_css_double(repr, "y", fespotlight->y);
+    sp_repr_set_css_double(repr, "z", fespotlight->z);
+    sp_repr_set_css_double(repr, "pointsAtX", fespotlight->pointsAtX);
+    sp_repr_set_css_double(repr, "pointsAtY", fespotlight->pointsAtY);
+    sp_repr_set_css_double(repr, "pointsAtZ", fespotlight->pointsAtZ);
+    sp_repr_set_css_double(repr, "specularExponent", fespotlight->specularExponent);
+    sp_repr_set_css_double(repr, "limitingConeAngle", fespotlight->limitingConeAngle);
+    
+    if (((SPObjectClass *) feSpotLight_parent_class)->write) {
+        ((SPObjectClass *) feSpotLight_parent_class)->write(object, repr, flags);
+    }
+
+    return repr;
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/sp-fespotlight.h b/src/sp-fespotlight.h
new file mode 100644 (file)
index 0000000..d0b0425
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef SP_FESPOTLIGHT_H_SEEN
+#define SP_FESPOTLIGHT_H_SEEN
+
+/** \file
+ * SVG <filter> implementation, see sp-filter.cpp.
+ */
+/*
+ * Authors:
+ *   Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Niko Kiirala <niko@kiirala.com>
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2006,2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "sp-object.h"
+
+#define SP_TYPE_FESPOTLIGHT (sp_fespotlight_get_type())
+#define SP_FESPOTLIGHT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FESPOTLIGHT, SPFeSpotLight))
+#define SP_FESPOTLIGHT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FESPOTLIGHT, SPFeSpotLightClass))
+#define SP_IS_FESPOTLIGHT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FESPOTLIGHT))
+#define SP_IS_FESPOTLIGHT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FESPOTLIGHT))
+
+/* Distant light class */
+
+
+class SPFeSpotLight;
+class SPFeSpotLightClass;
+
+struct SPFeSpotLight : public SPObject {
+
+    /** x coordinate of the light source */
+    gfloat x; 
+    /** y coordinate of the light source */
+    gfloat y; 
+    /** z coordinate of the light source */
+    gfloat z; 
+    /** x coordinate of the point the source is pointing at */
+    gfloat pointsAtX;
+    /** y coordinate of the point the source is pointing at */
+    gfloat pointsAtY;
+    /** z coordinate of the point the source is pointing at */
+    gfloat pointsAtZ;
+    /** specular exponent (focus of the light) */
+    gfloat specularExponent;
+    /** limiting cone angle */
+    gfloat limitingConeAngle;
+    //other fields
+};
+
+struct SPFeSpotLightClass {
+    SPObjectClass parent_class;
+};
+
+GType
+sp_fespotlight_get_type();
+#endif /* !SP_FESPOTLIGHT_H_SEEN */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index a4b47ca220c13c017567334e3593246ccd76e9aa..4e417e29434a6902864276e64584dbe8987df9c0 100644 (file)
 #include "sp-fecomposite.h"
 #include "sp-feconvolvematrix.h"
 #include "sp-fediffuselighting.h"
+#include "sp-fedistantlight.h"
 #include "sp-fedisplacementmap.h"
 #include "sp-feflood.h"
 #include "sp-feimage.h"
 #include "sp-femerge.h"
 #include "sp-femorphology.h"
 #include "sp-feoffset.h"
+#include "sp-fepointlight.h"
 #include "sp-fespecularlighting.h"
+#include "sp-fespotlight.h"
 #include "sp-fetile.h"
 #include "sp-feturbulence.h"
 
@@ -137,6 +140,7 @@ populate_dtables()
         { "svg:feComposite", SP_TYPE_FECOMPOSITE },
         { "svg:feConvolveMatrix", SP_TYPE_FECONVOLVEMATRIX },
         { "svg:feDiffuseLighting", SP_TYPE_FEDIFFUSELIGHTING },
+        { "svg:feDistantLight", SP_TYPE_FEDISTANTLIGHT },
         { "svg:feDisplacementMap", SP_TYPE_FEDISPLACEMENTMAP },
         { "svg:feFlood", SP_TYPE_FEFLOOD },
         { "svg:feGaussianBlur", SP_TYPE_GAUSSIANBLUR },
@@ -144,7 +148,9 @@ populate_dtables()
         { "svg:feMerge", SP_TYPE_FEMERGE },
         { "svg:feMorphology", SP_TYPE_FEMORPHOLOGY },
         { "svg:feOffset", SP_TYPE_FEOFFSET },
+        { "svg:fePointLight", SP_TYPE_FEPOINTLIGHT },
         { "svg:feSpecularLighting", SP_TYPE_FESPECULARLIGHTING },
+        { "svg:feSpotLight", SP_TYPE_FESPOTLIGHT },
         { "svg:feTile", SP_TYPE_FETILE },
         { "svg:feTurbulence", SP_TYPE_FETURBULENCE },
         { "svg:image", SP_TYPE_IMAGE },