~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to src/filters/specularlighting.cpp

  • Committer: Ted Gould
  • Date: 2008-11-21 05:24:08 UTC
  • Revision ID: ted@canonical.com-20081121052408-tilucis2pjrrpzxx
MergeĀ fromĀ fe-moved

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define __SP_FESPECULARLIGHTING_CPP__
 
2
 
 
3
/** \file
 
4
 * SVG <feSpecularLighting> implementation.
 
5
 *
 
6
 */
 
7
/*
 
8
 * Authors:
 
9
 *   hugo Rodrigues <haa.rodrigues@gmail.com>
 
10
 *   Jean-Rene Reinhard <jr@komite.net>
 
11
 *
 
12
 * Copyright (C) 2006 Hugo Rodrigues
 
13
 *               2007 authors
 
14
 *
 
15
 * Released under GNU GPL, read the file 'COPYING' for more information
 
16
 */
 
17
 
 
18
#ifdef HAVE_CONFIG_H
 
19
# include "config.h"
 
20
#endif
 
21
 
 
22
#include "attributes.h"
 
23
#include "svg/svg.h"
 
24
#include "sp-object.h"
 
25
#include "svg/svg-color.h"
 
26
#include "specularlighting.h"
 
27
#include "xml/repr.h"
 
28
#include "display/nr-filter-specularlighting.h"
 
29
 
 
30
/* FeSpecularLighting base class */
 
31
 
 
32
static void sp_feSpecularLighting_class_init(SPFeSpecularLightingClass *klass);
 
33
static void sp_feSpecularLighting_init(SPFeSpecularLighting *feSpecularLighting);
 
34
 
 
35
static void sp_feSpecularLighting_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
 
36
static void sp_feSpecularLighting_release(SPObject *object);
 
37
static void sp_feSpecularLighting_set(SPObject *object, unsigned int key, gchar const *value);
 
38
static void sp_feSpecularLighting_update(SPObject *object, SPCtx *ctx, guint flags);
 
39
//we assume that svg:feSpecularLighting can have any number of children
 
40
//only the first one is considered as the light source of the filter
 
41
//TODO is that right?
 
42
//if not modify child_added and remove_child to raise errors
 
43
static void sp_feSpecularLighting_child_added(SPObject *object,
 
44
                                    Inkscape::XML::Node *child,
 
45
                                    Inkscape::XML::Node *ref);
 
46
static void sp_feSpecularLighting_remove_child(SPObject *object, Inkscape::XML::Node *child);
 
47
static void sp_feSpecularLighting_order_changed(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref);
 
48
static Inkscape::XML::Node *sp_feSpecularLighting_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
 
49
static void sp_feSpecularLighting_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter);
 
50
static void sp_feSpecularLighting_children_modified(SPFeSpecularLighting *sp_specularlighting);
 
51
 
 
52
static SPFilterPrimitiveClass *feSpecularLighting_parent_class;
 
53
 
 
54
GType
 
55
sp_feSpecularLighting_get_type()
 
56
{
 
57
    static GType feSpecularLighting_type = 0;
 
58
 
 
59
    if (!feSpecularLighting_type) {
 
60
        GTypeInfo feSpecularLighting_info = {
 
61
            sizeof(SPFeSpecularLightingClass),
 
62
            NULL, NULL,
 
63
            (GClassInitFunc) sp_feSpecularLighting_class_init,
 
64
            NULL, NULL,
 
65
            sizeof(SPFeSpecularLighting),
 
66
            16,
 
67
            (GInstanceInitFunc) sp_feSpecularLighting_init,
 
68
            NULL,    /* value_table */
 
69
        };
 
70
        feSpecularLighting_type = g_type_register_static(SP_TYPE_FILTER_PRIMITIVE, "SPFeSpecularLighting", &feSpecularLighting_info, (GTypeFlags)0);
 
71
    }
 
72
    return feSpecularLighting_type;
 
73
}
 
74
 
 
75
static void
 
76
sp_feSpecularLighting_class_init(SPFeSpecularLightingClass *klass)
 
77
{
 
78
    SPObjectClass *sp_object_class = (SPObjectClass *)klass;
 
79
    SPFilterPrimitiveClass *sp_primitive_class = (SPFilterPrimitiveClass *)klass;
 
80
    feSpecularLighting_parent_class = (SPFilterPrimitiveClass*)g_type_class_peek_parent(klass);
 
81
 
 
82
    sp_object_class->build = sp_feSpecularLighting_build;
 
83
    sp_object_class->release = sp_feSpecularLighting_release;
 
84
    sp_object_class->write = sp_feSpecularLighting_write;
 
85
    sp_object_class->set = sp_feSpecularLighting_set;
 
86
    sp_object_class->update = sp_feSpecularLighting_update;
 
87
    sp_object_class->child_added = sp_feSpecularLighting_child_added;
 
88
    sp_object_class->remove_child = sp_feSpecularLighting_remove_child;
 
89
    sp_object_class->order_changed = sp_feSpecularLighting_order_changed;
 
90
 
 
91
    sp_primitive_class->build_renderer = sp_feSpecularLighting_build_renderer;
 
92
}
 
93
 
 
94
static void
 
95
sp_feSpecularLighting_init(SPFeSpecularLighting *feSpecularLighting)
 
96
{
 
97
    feSpecularLighting->surfaceScale = 1;
 
98
    feSpecularLighting->specularConstant = 1;
 
99
    feSpecularLighting->specularExponent = 1;
 
100
    feSpecularLighting->lighting_color = 0xffffffff;
 
101
    //TODO kernelUnit
 
102
    feSpecularLighting->renderer = NULL;
 
103
    
 
104
    feSpecularLighting->surfaceScale_set = FALSE;
 
105
    feSpecularLighting->specularConstant_set = FALSE;
 
106
    feSpecularLighting->specularExponent_set = FALSE;
 
107
    feSpecularLighting->lighting_color_set = FALSE;
 
108
}
 
109
 
 
110
/**
 
111
 * Reads the Inkscape::XML::Node, and initializes SPFeSpecularLighting variables.  For this to get called,
 
112
 * our name must be associated with a repr via "sp_object_type_register".  Best done through
 
113
 * sp-object-repr.cpp's repr_name_entries array.
 
114
 */
 
115
static void
 
116
sp_feSpecularLighting_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
 
117
{
 
118
    if (((SPObjectClass *) feSpecularLighting_parent_class)->build) {
 
119
        ((SPObjectClass *) feSpecularLighting_parent_class)->build(object, document, repr);
 
120
    }
 
121
 
 
122
    /*LOAD ATTRIBUTES FROM REPR HERE*/
 
123
    sp_object_read_attr(object, "surfaceScale");
 
124
    sp_object_read_attr(object, "specularConstant");
 
125
    sp_object_read_attr(object, "specularExponent");
 
126
    sp_object_read_attr(object, "kernelUnitLength");
 
127
    sp_object_read_attr(object, "lighting-color");
 
128
    
 
129
}
 
130
 
 
131
/**
 
132
 * Drops any allocated memory.
 
133
 */
 
134
static void
 
135
sp_feSpecularLighting_release(SPObject *object)
 
136
{
 
137
    if (((SPObjectClass *) feSpecularLighting_parent_class)->release)
 
138
        ((SPObjectClass *) feSpecularLighting_parent_class)->release(object);
 
139
}
 
140
 
 
141
/**
 
142
 * Sets a specific value in the SPFeSpecularLighting.
 
143
 */
 
144
static void
 
145
sp_feSpecularLighting_set(SPObject *object, unsigned int key, gchar const *value)
 
146
{
 
147
    SPFeSpecularLighting *feSpecularLighting = SP_FESPECULARLIGHTING(object);
 
148
    gchar const *cend_ptr = NULL;
 
149
    gchar *end_ptr = NULL;
 
150
    switch(key) {
 
151
        /*DEAL WITH SETTING ATTRIBUTES HERE*/
 
152
//TODO test forbidden values
 
153
        case SP_ATTR_SURFACESCALE:
 
154
            end_ptr = NULL;
 
155
            if (value) {
 
156
                feSpecularLighting->surfaceScale = g_ascii_strtod(value, &end_ptr);
 
157
                if (end_ptr) {
 
158
                    feSpecularLighting->surfaceScale_set = TRUE;
 
159
                } else {
 
160
                    g_warning("feSpecularLighting: surfaceScale should be a number ... defaulting to 1");
 
161
                }
 
162
 
 
163
            }
 
164
            //if the attribute is not set or has an unreadable value
 
165
            if (!value || !end_ptr) {
 
166
                feSpecularLighting->surfaceScale = 1;
 
167
                feSpecularLighting->surfaceScale_set = FALSE;
 
168
            }
 
169
            if (feSpecularLighting->renderer) {
 
170
                feSpecularLighting->renderer->surfaceScale = feSpecularLighting->surfaceScale;
 
171
            }
 
172
            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
173
            break;
 
174
        case SP_ATTR_SPECULARCONSTANT:
 
175
            end_ptr = NULL;
 
176
            if (value) {
 
177
                feSpecularLighting->specularConstant = g_ascii_strtod(value, &end_ptr);
 
178
                if (end_ptr && feSpecularLighting->specularConstant >= 0) {
 
179
                    feSpecularLighting->specularConstant_set = TRUE;
 
180
                } else {
 
181
                    end_ptr = NULL;
 
182
                    g_warning("feSpecularLighting: specularConstant should be a positive number ... defaulting to 1");
 
183
                }
 
184
            }
 
185
            if (!value || !end_ptr) {
 
186
                feSpecularLighting->specularConstant = 1;
 
187
                feSpecularLighting->specularConstant_set = FALSE;
 
188
            }
 
189
            if (feSpecularLighting->renderer) {
 
190
                feSpecularLighting->renderer->specularConstant = feSpecularLighting->specularConstant;
 
191
            }
 
192
            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
193
            break;
 
194
        case SP_ATTR_SPECULAREXPONENT:
 
195
            end_ptr = NULL;
 
196
            if (value) {
 
197
                feSpecularLighting->specularExponent = g_ascii_strtod(value, &end_ptr);
 
198
                if (feSpecularLighting->specularExponent >= 1 && feSpecularLighting->specularExponent <= 128) {
 
199
                    feSpecularLighting->specularExponent_set = TRUE;
 
200
                } else {
 
201
                    end_ptr = NULL;
 
202
                    g_warning("feSpecularLighting: specularExponent should be a number in range [1, 128] ... defaulting to 1");
 
203
                }
 
204
            } 
 
205
            if (!value || !end_ptr) {
 
206
                feSpecularLighting->specularExponent = 1;
 
207
                feSpecularLighting->specularExponent_set = FALSE;
 
208
            }
 
209
            if (feSpecularLighting->renderer) {
 
210
                feSpecularLighting->renderer->specularExponent = feSpecularLighting->specularExponent;
 
211
            }
 
212
            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
213
            break;
 
214
        case SP_ATTR_KERNELUNITLENGTH:
 
215
            //TODO kernelUnit
 
216
            //feSpecularLighting->kernelUnitLength.set(value);
 
217
            /*TODOif (feSpecularLighting->renderer) {
 
218
                feSpecularLighting->renderer->surfaceScale = feSpecularLighting->renderer;
 
219
            }
 
220
            */
 
221
            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
222
            break;
 
223
        case SP_PROP_LIGHTING_COLOR:
 
224
            cend_ptr = NULL;
 
225
            feSpecularLighting->lighting_color = sp_svg_read_color(value, &cend_ptr, 0xffffffff);
 
226
            //if a value was read
 
227
            if (cend_ptr) {
 
228
                feSpecularLighting->lighting_color_set = TRUE;
 
229
            } else {
 
230
                //lighting_color already contains the default value
 
231
                feSpecularLighting->lighting_color_set = FALSE;
 
232
            }
 
233
            if (feSpecularLighting->renderer) {
 
234
                feSpecularLighting->renderer->lighting_color = feSpecularLighting->lighting_color;
 
235
            }
 
236
            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
237
            break;
 
238
        default:
 
239
            if (((SPObjectClass *) feSpecularLighting_parent_class)->set)
 
240
                ((SPObjectClass *) feSpecularLighting_parent_class)->set(object, key, value);
 
241
            break;
 
242
    }
 
243
 
 
244
}
 
245
 
 
246
/**
 
247
 * Receives update notifications.
 
248
 */
 
249
static void
 
250
sp_feSpecularLighting_update(SPObject *object, SPCtx *ctx, guint flags)
 
251
{
 
252
    if (flags & (SP_OBJECT_MODIFIED_FLAG)) {
 
253
        sp_object_read_attr(object, "surfaceScale");
 
254
        sp_object_read_attr(object, "specularConstant");
 
255
        sp_object_read_attr(object, "specularExponent");
 
256
        sp_object_read_attr(object, "kernelUnitLength");
 
257
        sp_object_read_attr(object, "lighting-color");
 
258
    }
 
259
 
 
260
    if (((SPObjectClass *) feSpecularLighting_parent_class)->update) {
 
261
        ((SPObjectClass *) feSpecularLighting_parent_class)->update(object, ctx, flags);
 
262
    }
 
263
}
 
264
 
 
265
/**
 
266
 * Writes its settings to an incoming repr object, if any.
 
267
 */
 
268
static Inkscape::XML::Node *
 
269
sp_feSpecularLighting_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags)
 
270
{
 
271
    SPFeSpecularLighting *fespecularlighting = SP_FESPECULARLIGHTING(object);
 
272
    
 
273
    // Inkscape-only object, not copied during an "plain SVG" dump:
 
274
    if (flags & SP_OBJECT_WRITE_EXT) {
 
275
        if (repr) {
 
276
            // is this sane?
 
277
            //repr->mergeFrom(SP_OBJECT_REPR(object), "id");
 
278
        } else {
 
279
            repr = SP_OBJECT_REPR(object)->duplicate(doc);
 
280
        }
 
281
    }
 
282
    if (fespecularlighting->surfaceScale_set)
 
283
        sp_repr_set_css_double(repr, "surfaceScale", fespecularlighting->surfaceScale);
 
284
    if (fespecularlighting->specularConstant_set)
 
285
        sp_repr_set_css_double(repr, "specularConstant", fespecularlighting->specularConstant);
 
286
    if (fespecularlighting->specularExponent_set)
 
287
        sp_repr_set_css_double(repr, "specularExponent", fespecularlighting->specularExponent);
 
288
   /*TODO kernelUnits */ 
 
289
    if (fespecularlighting->lighting_color_set) {
 
290
        gchar c[64];
 
291
        sp_svg_write_color(c, sizeof(c), fespecularlighting->lighting_color);
 
292
        repr->setAttribute("lighting-color", c);
 
293
    }
 
294
    if (((SPObjectClass *) feSpecularLighting_parent_class)->write) {
 
295
        ((SPObjectClass *) feSpecularLighting_parent_class)->write(object, doc, repr, flags);
 
296
    }
 
297
 
 
298
    return repr;
 
299
}
 
300
 
 
301
/**
 
302
 * Callback for child_added event.
 
303
 */
 
304
static void
 
305
sp_feSpecularLighting_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
 
306
{
 
307
    SPFeSpecularLighting *f = SP_FESPECULARLIGHTING(object);
 
308
 
 
309
    if (((SPObjectClass *) feSpecularLighting_parent_class)->child_added)
 
310
        (* ((SPObjectClass *) feSpecularLighting_parent_class)->child_added)(object, child, ref);
 
311
 
 
312
    sp_feSpecularLighting_children_modified(f);
 
313
    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
314
}
 
315
            
 
316
 
 
317
/**
 
318
 * Callback for remove_child event.
 
319
 */
 
320
static void
 
321
sp_feSpecularLighting_remove_child(SPObject *object, Inkscape::XML::Node *child)
 
322
{   
 
323
    SPFeSpecularLighting *f = SP_FESPECULARLIGHTING(object);
 
324
 
 
325
    if (((SPObjectClass *) feSpecularLighting_parent_class)->remove_child)
 
326
        (* ((SPObjectClass *) feSpecularLighting_parent_class)->remove_child)(object, child);   
 
327
 
 
328
    sp_feSpecularLighting_children_modified(f);
 
329
    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
330
}
 
331
 
 
332
static void
 
333
sp_feSpecularLighting_order_changed (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref)
 
334
{
 
335
    SPFeSpecularLighting *f = SP_FESPECULARLIGHTING(object);
 
336
    if (((SPObjectClass *) (feSpecularLighting_parent_class))->order_changed)
 
337
        (* ((SPObjectClass *) (feSpecularLighting_parent_class))->order_changed) (object, child, old_ref, new_ref);
 
338
 
 
339
    sp_feSpecularLighting_children_modified(f);
 
340
    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
341
}
 
342
 
 
343
static void sp_feSpecularLighting_children_modified(SPFeSpecularLighting *sp_specularlighting)
 
344
{
 
345
   if (sp_specularlighting->renderer) {
 
346
        sp_specularlighting->renderer->light_type = NR::NO_LIGHT;
 
347
        if (SP_IS_FEDISTANTLIGHT(sp_specularlighting->children)) {
 
348
            sp_specularlighting->renderer->light_type = NR::DISTANT_LIGHT;
 
349
            sp_specularlighting->renderer->light.distant = SP_FEDISTANTLIGHT(sp_specularlighting->children);
 
350
        }
 
351
        if (SP_IS_FEPOINTLIGHT(sp_specularlighting->children)) {
 
352
            sp_specularlighting->renderer->light_type = NR::POINT_LIGHT;
 
353
            sp_specularlighting->renderer->light.point = SP_FEPOINTLIGHT(sp_specularlighting->children);
 
354
        }
 
355
        if (SP_IS_FESPOTLIGHT(sp_specularlighting->children)) {
 
356
            sp_specularlighting->renderer->light_type = NR::SPOT_LIGHT;
 
357
            sp_specularlighting->renderer->light.spot = SP_FESPOTLIGHT(sp_specularlighting->children);
 
358
        }
 
359
   }
 
360
}
 
361
 
 
362
static void sp_feSpecularLighting_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter) {
 
363
    g_assert(primitive != NULL);
 
364
    g_assert(filter != NULL);
 
365
 
 
366
    SPFeSpecularLighting *sp_specularlighting = SP_FESPECULARLIGHTING(primitive);
 
367
 
 
368
    int primitive_n = filter->add_primitive(NR::NR_FILTER_SPECULARLIGHTING);
 
369
    NR::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n);
 
370
    NR::FilterSpecularLighting *nr_specularlighting = dynamic_cast<NR::FilterSpecularLighting*>(nr_primitive);
 
371
    g_assert(nr_specularlighting != NULL);
 
372
 
 
373
    sp_specularlighting->renderer = nr_specularlighting;
 
374
    sp_filter_primitive_renderer_common(primitive, nr_primitive);
 
375
 
 
376
    nr_specularlighting->specularConstant = sp_specularlighting->specularConstant;
 
377
    nr_specularlighting->specularExponent = sp_specularlighting->specularExponent;
 
378
    nr_specularlighting->surfaceScale = sp_specularlighting->surfaceScale;
 
379
    nr_specularlighting->lighting_color = sp_specularlighting->lighting_color;
 
380
    //We assume there is at most one child
 
381
    nr_specularlighting->light_type = NR::NO_LIGHT;
 
382
    if (SP_IS_FEDISTANTLIGHT(primitive->children)) {
 
383
        nr_specularlighting->light_type = NR::DISTANT_LIGHT;
 
384
        nr_specularlighting->light.distant = SP_FEDISTANTLIGHT(primitive->children);
 
385
    }
 
386
    if (SP_IS_FEPOINTLIGHT(primitive->children)) {
 
387
        nr_specularlighting->light_type = NR::POINT_LIGHT;
 
388
        nr_specularlighting->light.point = SP_FEPOINTLIGHT(primitive->children);
 
389
    }
 
390
    if (SP_IS_FESPOTLIGHT(primitive->children)) {
 
391
        nr_specularlighting->light_type = NR::SPOT_LIGHT;
 
392
        nr_specularlighting->light.spot = SP_FESPOTLIGHT(primitive->children);
 
393
    }
 
394
        
 
395
    //nr_offset->set_dx(sp_offset->dx);
 
396
    //nr_offset->set_dy(sp_offset->dy);
 
397
}
 
398
 
 
399
 
 
400
/*
 
401
  Local Variables:
 
402
  mode:c++
 
403
  c-file-style:"stroustrup"
 
404
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
405
  indent-tabs-mode:nil
 
406
  fill-column:99
 
407
  End:
 
408
*/
 
409
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :