1 #define __SP_FEFUNCNODE_CPP__
3 /** \file
4 * SVG <funcR>, <funcG>, <funcB> and <funcA> implementations.
5 */
6 /*
7 * Authors:
8 * Hugo Rodrigues <haa.rodrigues@gmail.com>
9 * Niko Kiirala <niko@kiirala.com>
10 * Felipe CorrĂȘa da Silva Sanches <felipe.sanches@gmail.com>
11 *
12 * Copyright (C) 2006, 2007, 2008 Authors
13 *
14 * Released under GNU GPL, read the file 'COPYING' for more information
15 */
17 #ifdef HAVE_CONFIG_H
18 # include "config.h"
19 #endif
21 #include <glib.h>
23 #include "attributes.h"
24 #include "document.h"
25 #include "sp-fecomponenttransfer.h"
26 #include "sp-fecomponenttransfer-funcnode.h"
27 #include "display/nr-filter-component-transfer.h"
28 #include "xml/repr.h"
29 #include "helper-fns.h"
31 #define SP_MACROS_SILENT
32 #include "macros.h"
34 /* FeFuncNode class */
36 static void sp_fefuncnode_class_init(SPFeFuncNodeClass *klass);
37 static void sp_fefuncnode_init(SPFeFuncNode *fefuncnode);
39 static void sp_fefuncnode_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
40 static void sp_fefuncnode_release(SPObject *object);
41 static void sp_fefuncnode_set(SPObject *object, unsigned int key, gchar const *value);
42 static void sp_fefuncnode_update(SPObject *object, SPCtx *ctx, guint flags);
43 static Inkscape::XML::Node *sp_fefuncnode_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
45 static SPObjectClass *feFuncNode_parent_class;
47 GType
48 sp_fefuncR_get_type()
49 {
50 static GType fefuncnode_type = 0;
52 if (!fefuncnode_type) {
53 GTypeInfo fefuncnode_info = {
54 sizeof(SPFeFuncNodeClass),
55 NULL, NULL,
56 (GClassInitFunc) sp_fefuncnode_class_init,
57 NULL, NULL,
58 sizeof(SPFeFuncNode),
59 16,
60 (GInstanceInitFunc) sp_fefuncnode_init,
61 NULL, /* value_table */
62 };
63 fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncR", &fefuncnode_info, (GTypeFlags)0);
64 }
65 return fefuncnode_type;
66 }
68 GType
69 sp_fefuncG_get_type()
70 {
71 static GType fefuncnode_type = 0;
73 if (!fefuncnode_type) {
74 GTypeInfo fefuncnode_info = {
75 sizeof(SPFeFuncNodeClass),
76 NULL, NULL,
77 (GClassInitFunc) sp_fefuncnode_class_init,
78 NULL, NULL,
79 sizeof(SPFeFuncNode),
80 16,
81 (GInstanceInitFunc) sp_fefuncnode_init,
82 NULL, /* value_table */
83 };
84 fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncG", &fefuncnode_info, (GTypeFlags)0);
85 }
86 return fefuncnode_type;
87 }
89 GType
90 sp_fefuncB_get_type()
91 {
92 static GType fefuncnode_type = 0;
94 if (!fefuncnode_type) {
95 GTypeInfo fefuncnode_info = {
96 sizeof(SPFeFuncNodeClass),
97 NULL, NULL,
98 (GClassInitFunc) sp_fefuncnode_class_init,
99 NULL, NULL,
100 sizeof(SPFeFuncNode),
101 16,
102 (GInstanceInitFunc) sp_fefuncnode_init,
103 NULL, /* value_table */
104 };
105 fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncB", &fefuncnode_info, (GTypeFlags)0);
106 }
107 return fefuncnode_type;
108 }
110 GType
111 sp_fefuncA_get_type()
112 {
113 static GType fefuncnode_type = 0;
115 if (!fefuncnode_type) {
116 GTypeInfo fefuncnode_info = {
117 sizeof(SPFeFuncNodeClass),
118 NULL, NULL,
119 (GClassInitFunc) sp_fefuncnode_class_init,
120 NULL, NULL,
121 sizeof(SPFeFuncNode),
122 16,
123 (GInstanceInitFunc) sp_fefuncnode_init,
124 NULL, /* value_table */
125 };
126 fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncA", &fefuncnode_info, (GTypeFlags)0);
127 }
128 return fefuncnode_type;
129 }
131 static void
132 sp_fefuncnode_class_init(SPFeFuncNodeClass *klass)
133 {
135 SPObjectClass *sp_object_class = (SPObjectClass *)klass;
137 feFuncNode_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass);
139 sp_object_class->build = sp_fefuncnode_build;
140 sp_object_class->release = sp_fefuncnode_release;
141 sp_object_class->write = sp_fefuncnode_write;
142 sp_object_class->set = sp_fefuncnode_set;
143 sp_object_class->update = sp_fefuncnode_update;
144 }
146 static void
147 sp_fefuncnode_init(SPFeFuncNode *fefuncnode)
148 {
149 fefuncnode->type = NR::COMPONENTTRANSFER_TYPE_IDENTITY;
150 //fefuncnode->tableValues = NULL;
151 fefuncnode->slope = 1;
152 fefuncnode->intercept = 0;
153 fefuncnode->amplitude = 1;
154 fefuncnode->exponent = 1;
155 fefuncnode->offset = 0;
156 }
158 /**
159 * Reads the Inkscape::XML::Node, and initializes SPDistantLight variables. For this to get called,
160 * our name must be associated with a repr via "sp_object_type_register". Best done through
161 * sp-object-repr.cpp's repr_name_entries array.
162 */
163 static void
164 sp_fefuncnode_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
165 {
166 if (((SPObjectClass *) feFuncNode_parent_class)->build) {
167 ((SPObjectClass *) feFuncNode_parent_class)->build(object, document, repr);
168 }
170 //Read values of key attributes from XML nodes into object.
171 sp_object_read_attr(object, "type");
172 sp_object_read_attr(object, "tableValues");
173 sp_object_read_attr(object, "slope");
174 sp_object_read_attr(object, "intercept");
175 sp_object_read_attr(object, "amplitude");
176 sp_object_read_attr(object, "exponent");
177 sp_object_read_attr(object, "offset");
180 //is this necessary?
181 sp_document_add_resource(document, "fefuncnode", object); //maybe feFuncR, fefuncG, feFuncB and fefuncA ?
182 }
184 /**
185 * Drops any allocated memory.
186 */
187 static void
188 sp_fefuncnode_release(SPObject *object)
189 {
190 //SPFeFuncNode *fefuncnode = SP_FEFUNCNODE(object);
192 if (SP_OBJECT_DOCUMENT(object)) {
193 /* Unregister ourselves */
194 sp_document_remove_resource(SP_OBJECT_DOCUMENT(object), "fefuncnode", SP_OBJECT(object));
195 }
197 //TODO: release resources here
198 }
200 static NR::FilterComponentTransferType sp_feComponenttransfer_read_type(gchar const *value){
201 if (!value) return NR::COMPONENTTRANSFER_TYPE_ERROR; //type attribute is REQUIRED.
202 switch(value[0]){
203 case 'i':
204 if (strncmp(value, "identity", 8) == 0) return NR::COMPONENTTRANSFER_TYPE_IDENTITY;
205 break;
206 case 't':
207 if (strncmp(value, "table", 5) == 0) return NR::COMPONENTTRANSFER_TYPE_TABLE;
208 break;
209 case 'd':
210 if (strncmp(value, "discrete", 8) == 0) return NR::COMPONENTTRANSFER_TYPE_DISCRETE;
211 break;
212 case 'l':
213 if (strncmp(value, "linear", 6) == 0) return NR::COMPONENTTRANSFER_TYPE_LINEAR;
214 break;
215 case 'g':
216 if (strncmp(value, "gamma", 5) == 0) return NR::COMPONENTTRANSFER_TYPE_GAMMA;
217 break;
218 }
219 return NR::COMPONENTTRANSFER_TYPE_ERROR; //type attribute is REQUIRED.
220 }
222 /**
223 * Sets a specific value in the SPFeFuncNode.
224 */
225 static void
226 sp_fefuncnode_set(SPObject *object, unsigned int key, gchar const *value)
227 {
228 SPFeFuncNode *feFuncNode = SP_FEFUNCNODE(object);
229 NR::FilterComponentTransferType type;
230 double read_num;
231 switch(key) {
232 case SP_ATTR_TYPE:
233 type = sp_feComponenttransfer_read_type(value);
234 if(type != feFuncNode->type) {
235 feFuncNode->type = type;
236 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
237 }
238 break;
239 case SP_ATTR_TABLEVALUES:
240 if (value){
241 feFuncNode->tableValues = helperfns_read_vector(value);
242 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
243 }
244 break;
245 case SP_ATTR_SLOPE:
246 read_num = helperfns_read_number(value);
247 if (read_num != feFuncNode->slope) {
248 feFuncNode->slope = read_num;
249 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
250 }
251 break;
252 case SP_ATTR_INTERCEPT:
253 read_num = helperfns_read_number(value);
254 if (read_num != feFuncNode->intercept) {
255 feFuncNode->intercept = read_num;
256 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
257 }
258 break;
259 case SP_ATTR_AMPLITUDE:
260 read_num = helperfns_read_number(value);
261 if (read_num != feFuncNode->amplitude) {
262 feFuncNode->amplitude = read_num;
263 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
264 }
265 break;
266 case SP_ATTR_EXPONENT:
267 read_num = helperfns_read_number(value);
268 if (read_num != feFuncNode->exponent) {
269 feFuncNode->exponent = read_num;
270 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
271 }
272 break;
273 case SP_ATTR_OFFSET:
274 read_num = helperfns_read_number(value);
275 if (read_num != feFuncNode->offset) {
276 feFuncNode->offset = read_num;
277 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
278 }
279 break;
280 default:
281 if (((SPObjectClass *) feFuncNode_parent_class)->set)
282 ((SPObjectClass *) feFuncNode_parent_class)->set(object, key, value);
283 break;
284 }
285 }
287 /**
288 * * Receives update notifications.
289 * */
290 static void
291 sp_fefuncnode_update(SPObject *object, SPCtx *ctx, guint flags)
292 {
293 SPFeFuncNode *feFuncNode = SP_FEFUNCNODE(object);
294 (void)feFuncNode;
296 if (flags & SP_OBJECT_MODIFIED_FLAG) {
297 /* do something to trigger redisplay, updates? */
298 //TODO
299 //sp_object_read_attr(object, "azimuth");
300 //sp_object_read_attr(object, "elevation");
301 }
303 if (((SPObjectClass *) feFuncNode_parent_class)->update) {
304 ((SPObjectClass *) feFuncNode_parent_class)->update(object, ctx, flags);
305 }
306 }
308 /**
309 * Writes its settings to an incoming repr object, if any.
310 */
311 static Inkscape::XML::Node *
312 sp_fefuncnode_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
313 {
314 SPFeFuncNode *fefuncnode = SP_FEFUNCNODE(object);
316 if (!repr) {
317 repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME
318 }
320 /*
321 TODO: I'm not sure what to do here...
323 if (fefuncnode->azimuth_set)
324 sp_repr_set_css_double(repr, "azimuth", fefuncnode->azimuth);
325 if (fefuncnode->elevation_set)
326 sp_repr_set_css_double(repr, "elevation", fefuncnode->elevation);*/
328 if (((SPObjectClass *) feFuncNode_parent_class)->write) {
329 ((SPObjectClass *) feFuncNode_parent_class)->write(object, repr, flags);
330 }
332 return repr;
333 }
335 /*
336 Local Variables:
337 mode:c++
338 c-file-style:"stroustrup"
339 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
340 indent-tabs-mode:nil
341 fill-column:99
342 End:
343 */
344 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :