1 /** \file
2 * SVG <funcR>, <funcG>, <funcB> and <funcA> implementations.
3 */
4 /*
5 * Authors:
6 * Hugo Rodrigues <haa.rodrigues@gmail.com>
7 * Niko Kiirala <niko@kiirala.com>
8 * Felipe CorrĂȘa da Silva Sanches <juca@members.fsf.org>
9 * Abhishek Sharma
10 *
11 * Copyright (C) 2006, 2007, 2008 Authors
12 *
13 * Released under GNU GPL, read the file 'COPYING' for more information
14 */
16 #ifdef HAVE_CONFIG_H
17 # include "config.h"
18 #endif
20 #include <glib.h>
22 #include "attributes.h"
23 #include "document.h"
24 #include "componenttransfer.h"
25 #include "componenttransfer-funcnode.h"
26 #include "display/nr-filter-component-transfer.h"
27 #include "xml/repr.h"
28 #include "helper-fns.h"
30 #define SP_MACROS_SILENT
31 #include "macros.h"
33 /* FeFuncNode class */
35 static void sp_fefuncnode_class_init(SPFeFuncNodeClass *klass);
36 static void sp_fefuncnode_init(SPFeFuncNode *fefuncnode);
38 static void sp_fefuncnode_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
39 static void sp_fefuncnode_release(SPObject *object);
40 static void sp_fefuncnode_set(SPObject *object, unsigned int key, gchar const *value);
41 static void sp_fefuncnode_update(SPObject *object, SPCtx *ctx, guint flags);
42 static Inkscape::XML::Node *sp_fefuncnode_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
44 static SPObjectClass *feFuncNode_parent_class;
46 GType
47 sp_fefuncR_get_type()
48 {
49 static GType fefuncnode_type = 0;
51 if (!fefuncnode_type) {
52 GTypeInfo fefuncnode_info = {
53 sizeof(SPFeFuncNodeClass),
54 NULL, NULL,
55 (GClassInitFunc) sp_fefuncnode_class_init,
56 NULL, NULL,
57 sizeof(SPFeFuncNode),
58 16,
59 (GInstanceInitFunc) sp_fefuncnode_init,
60 NULL, /* value_table */
61 };
62 fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncR", &fefuncnode_info, (GTypeFlags)0);
63 }
64 return fefuncnode_type;
65 }
67 GType
68 sp_fefuncG_get_type()
69 {
70 static GType fefuncnode_type = 0;
72 if (!fefuncnode_type) {
73 GTypeInfo fefuncnode_info = {
74 sizeof(SPFeFuncNodeClass),
75 NULL, NULL,
76 (GClassInitFunc) sp_fefuncnode_class_init,
77 NULL, NULL,
78 sizeof(SPFeFuncNode),
79 16,
80 (GInstanceInitFunc) sp_fefuncnode_init,
81 NULL, /* value_table */
82 };
83 fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncG", &fefuncnode_info, (GTypeFlags)0);
84 }
85 return fefuncnode_type;
86 }
88 GType
89 sp_fefuncB_get_type()
90 {
91 static GType fefuncnode_type = 0;
93 if (!fefuncnode_type) {
94 GTypeInfo fefuncnode_info = {
95 sizeof(SPFeFuncNodeClass),
96 NULL, NULL,
97 (GClassInitFunc) sp_fefuncnode_class_init,
98 NULL, NULL,
99 sizeof(SPFeFuncNode),
100 16,
101 (GInstanceInitFunc) sp_fefuncnode_init,
102 NULL, /* value_table */
103 };
104 fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncB", &fefuncnode_info, (GTypeFlags)0);
105 }
106 return fefuncnode_type;
107 }
109 GType
110 sp_fefuncA_get_type()
111 {
112 static GType fefuncnode_type = 0;
114 if (!fefuncnode_type) {
115 GTypeInfo fefuncnode_info = {
116 sizeof(SPFeFuncNodeClass),
117 NULL, NULL,
118 (GClassInitFunc) sp_fefuncnode_class_init,
119 NULL, NULL,
120 sizeof(SPFeFuncNode),
121 16,
122 (GInstanceInitFunc) sp_fefuncnode_init,
123 NULL, /* value_table */
124 };
125 fefuncnode_type = g_type_register_static(SP_TYPE_OBJECT, "SPFeFuncA", &fefuncnode_info, (GTypeFlags)0);
126 }
127 return fefuncnode_type;
128 }
130 static void
131 sp_fefuncnode_class_init(SPFeFuncNodeClass *klass)
132 {
134 SPObjectClass *sp_object_class = (SPObjectClass *)klass;
136 feFuncNode_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass);
138 sp_object_class->build = sp_fefuncnode_build;
139 sp_object_class->release = sp_fefuncnode_release;
140 sp_object_class->write = sp_fefuncnode_write;
141 sp_object_class->set = sp_fefuncnode_set;
142 sp_object_class->update = sp_fefuncnode_update;
143 }
145 static void
146 sp_fefuncnode_init(SPFeFuncNode *fefuncnode)
147 {
148 fefuncnode->type = Inkscape::Filters::COMPONENTTRANSFER_TYPE_IDENTITY;
149 //fefuncnode->tableValues = NULL;
150 fefuncnode->slope = 1;
151 fefuncnode->intercept = 0;
152 fefuncnode->amplitude = 1;
153 fefuncnode->exponent = 1;
154 fefuncnode->offset = 0;
155 }
157 /**
158 * Reads the Inkscape::XML::Node, and initializes SPDistantLight variables. For this to get called,
159 * our name must be associated with a repr via "sp_object_type_register". Best done through
160 * sp-object-repr.cpp's repr_name_entries array.
161 */
162 static void
163 sp_fefuncnode_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
164 {
165 if (((SPObjectClass *) feFuncNode_parent_class)->build) {
166 ((SPObjectClass *) feFuncNode_parent_class)->build(object, document, repr);
167 }
169 //Read values of key attributes from XML nodes into object.
170 object->readAttr( "type" );
171 object->readAttr( "tableValues" );
172 object->readAttr( "slope" );
173 object->readAttr( "intercept" );
174 object->readAttr( "amplitude" );
175 object->readAttr( "exponent" );
176 object->readAttr( "offset" );
179 //is this necessary?
180 document->addResource("fefuncnode", object); //maybe feFuncR, fefuncG, feFuncB and fefuncA ?
181 }
183 /**
184 * Drops any allocated memory.
185 */
186 static void
187 sp_fefuncnode_release(SPObject *object)
188 {
189 //SPFeFuncNode *fefuncnode = SP_FEFUNCNODE(object);
191 if (SP_OBJECT_DOCUMENT(object)) {
192 /* Unregister ourselves */
193 SP_OBJECT_DOCUMENT(object)->removeResource("fefuncnode", SP_OBJECT(object));
194 }
196 //TODO: release resources here
197 }
199 static Inkscape::Filters::FilterComponentTransferType sp_feComponenttransfer_read_type(gchar const *value){
200 if (!value) return Inkscape::Filters::COMPONENTTRANSFER_TYPE_ERROR; //type attribute is REQUIRED.
201 switch(value[0]){
202 case 'i':
203 if (strncmp(value, "identity", 8) == 0) return Inkscape::Filters::COMPONENTTRANSFER_TYPE_IDENTITY;
204 break;
205 case 't':
206 if (strncmp(value, "table", 5) == 0) return Inkscape::Filters::COMPONENTTRANSFER_TYPE_TABLE;
207 break;
208 case 'd':
209 if (strncmp(value, "discrete", 8) == 0) return Inkscape::Filters::COMPONENTTRANSFER_TYPE_DISCRETE;
210 break;
211 case 'l':
212 if (strncmp(value, "linear", 6) == 0) return Inkscape::Filters::COMPONENTTRANSFER_TYPE_LINEAR;
213 break;
214 case 'g':
215 if (strncmp(value, "gamma", 5) == 0) return Inkscape::Filters::COMPONENTTRANSFER_TYPE_GAMMA;
216 break;
217 }
218 return Inkscape::Filters::COMPONENTTRANSFER_TYPE_ERROR; //type attribute is REQUIRED.
219 }
221 /**
222 * Sets a specific value in the SPFeFuncNode.
223 */
224 static void
225 sp_fefuncnode_set(SPObject *object, unsigned int key, gchar const *value)
226 {
227 SPFeFuncNode *feFuncNode = SP_FEFUNCNODE(object);
228 Inkscape::Filters::FilterComponentTransferType type;
229 double read_num;
230 switch(key) {
231 case SP_ATTR_TYPE:
232 type = sp_feComponenttransfer_read_type(value);
233 if(type != feFuncNode->type) {
234 feFuncNode->type = type;
235 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
236 }
237 break;
238 case SP_ATTR_TABLEVALUES:
239 if (value){
240 feFuncNode->tableValues = helperfns_read_vector(value);
241 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
242 }
243 break;
244 case SP_ATTR_SLOPE:
245 read_num = value ? helperfns_read_number(value) : 1;
246 if (read_num != feFuncNode->slope) {
247 feFuncNode->slope = read_num;
248 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
249 }
250 break;
251 case SP_ATTR_INTERCEPT:
252 read_num = value ? helperfns_read_number(value) : 0;
253 if (read_num != feFuncNode->intercept) {
254 feFuncNode->intercept = read_num;
255 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
256 }
257 break;
258 case SP_ATTR_AMPLITUDE:
259 read_num = value ? helperfns_read_number(value) : 1;
260 if (read_num != feFuncNode->amplitude) {
261 feFuncNode->amplitude = read_num;
262 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
263 }
264 break;
265 case SP_ATTR_EXPONENT:
266 read_num = value ? helperfns_read_number(value) : 1;
267 if (read_num != feFuncNode->exponent) {
268 feFuncNode->exponent = read_num;
269 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
270 }
271 break;
272 case SP_ATTR_OFFSET:
273 read_num = value ? helperfns_read_number(value) : 0;
274 if (read_num != feFuncNode->offset) {
275 feFuncNode->offset = read_num;
276 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
277 }
278 break;
279 default:
280 if (((SPObjectClass *) feFuncNode_parent_class)->set)
281 ((SPObjectClass *) feFuncNode_parent_class)->set(object, key, value);
282 break;
283 }
284 }
286 /**
287 * * Receives update notifications.
288 * */
289 static void
290 sp_fefuncnode_update(SPObject *object, SPCtx *ctx, guint flags)
291 {
292 SPFeFuncNode *feFuncNode = SP_FEFUNCNODE(object);
293 (void)feFuncNode;
295 if (flags & SP_OBJECT_MODIFIED_FLAG) {
296 /* do something to trigger redisplay, updates? */
297 //TODO
298 //object->readAttr( "azimuth" );
299 //object->readAttr( "elevation" );
300 }
302 if (((SPObjectClass *) feFuncNode_parent_class)->update) {
303 ((SPObjectClass *) feFuncNode_parent_class)->update(object, ctx, flags);
304 }
305 }
307 /**
308 * Writes its settings to an incoming repr object, if any.
309 */
310 static Inkscape::XML::Node *
311 sp_fefuncnode_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags)
312 {
313 SPFeFuncNode *fefuncnode = SP_FEFUNCNODE(object);
315 if (!repr) {
316 repr = SP_OBJECT_REPR(object)->duplicate(doc);
317 }
319 (void)fefuncnode;
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, doc, 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:fileencoding=utf-8:textwidth=99 :