~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to src/sp-feconvolvematrix.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_FECONVOLVEMATRIX_CPP__
2
 
 
3
 
/** \file
4
 
 * SVG <feConvolveMatrix> implementation.
5
 
 *
6
 
 */
7
 
/*
8
 
 * Authors:
9
 
 *   Felipe CorrĆŖa da Silva Sanches <felipe.sanches@gmail.com>
10
 
 *   hugo Rodrigues <haa.rodrigues@gmail.com>
11
 
 *
12
 
 * Copyright (C) 2006 Hugo Rodrigues
13
 
 *
14
 
 * Released under GNU GPL, read the file 'COPYING' for more information
15
 
 */
16
 
 
17
 
#ifdef HAVE_CONFIG_H
18
 
# include "config.h"
19
 
#endif
20
 
 
21
 
#include <string.h>
22
 
 
23
 
#include <vector>
24
 
#include "attributes.h"
25
 
#include "svg/svg.h"
26
 
#include "sp-feconvolvematrix.h"
27
 
#include "helper-fns.h"
28
 
#include "xml/repr.h"
29
 
#include "display/nr-filter-convolve-matrix.h"
30
 
#include <math.h>
31
 
 
32
 
/* FeConvolveMatrix base class */
33
 
 
34
 
static void sp_feConvolveMatrix_class_init(SPFeConvolveMatrixClass *klass);
35
 
static void sp_feConvolveMatrix_init(SPFeConvolveMatrix *feConvolveMatrix);
36
 
 
37
 
static void sp_feConvolveMatrix_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
38
 
static void sp_feConvolveMatrix_release(SPObject *object);
39
 
static void sp_feConvolveMatrix_set(SPObject *object, unsigned int key, gchar const *value);
40
 
static void sp_feConvolveMatrix_update(SPObject *object, SPCtx *ctx, guint flags);
41
 
static Inkscape::XML::Node *sp_feConvolveMatrix_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
42
 
static void sp_feConvolveMatrix_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter);
43
 
 
44
 
static SPFilterPrimitiveClass *feConvolveMatrix_parent_class;
45
 
 
46
 
GType
47
 
sp_feConvolveMatrix_get_type()
48
 
{
49
 
    static GType feConvolveMatrix_type = 0;
50
 
 
51
 
    if (!feConvolveMatrix_type) {
52
 
        GTypeInfo feConvolveMatrix_info = {
53
 
            sizeof(SPFeConvolveMatrixClass),
54
 
            NULL, NULL,
55
 
            (GClassInitFunc) sp_feConvolveMatrix_class_init,
56
 
            NULL, NULL,
57
 
            sizeof(SPFeConvolveMatrix),
58
 
            16,
59
 
            (GInstanceInitFunc) sp_feConvolveMatrix_init,
60
 
            NULL,    /* value_table */
61
 
        };
62
 
        feConvolveMatrix_type = g_type_register_static(SP_TYPE_FILTER_PRIMITIVE, "SPFeConvolveMatrix", &feConvolveMatrix_info, (GTypeFlags)0);
63
 
    }
64
 
    return feConvolveMatrix_type;
65
 
}
66
 
 
67
 
static void
68
 
sp_feConvolveMatrix_class_init(SPFeConvolveMatrixClass *klass)
69
 
{
70
 
    SPObjectClass *sp_object_class = (SPObjectClass *)klass;
71
 
    SPFilterPrimitiveClass *sp_primitive_class = (SPFilterPrimitiveClass *)klass;
72
 
 
73
 
    feConvolveMatrix_parent_class = (SPFilterPrimitiveClass*)g_type_class_peek_parent(klass);
74
 
 
75
 
    sp_object_class->build = sp_feConvolveMatrix_build;
76
 
    sp_object_class->release = sp_feConvolveMatrix_release;
77
 
    sp_object_class->write = sp_feConvolveMatrix_write;
78
 
    sp_object_class->set = sp_feConvolveMatrix_set;
79
 
    sp_object_class->update = sp_feConvolveMatrix_update;
80
 
 
81
 
    sp_primitive_class->build_renderer = sp_feConvolveMatrix_build_renderer;
82
 
}
83
 
 
84
 
static void
85
 
sp_feConvolveMatrix_init(SPFeConvolveMatrix *feConvolveMatrix)
86
 
{
87
 
    //Setting default values:
88
 
    feConvolveMatrix->order.set("3 3");
89
 
    feConvolveMatrix->targetX = 1;
90
 
    feConvolveMatrix->targetY = 1;
91
 
    feConvolveMatrix->edgeMode = NR::CONVOLVEMATRIX_EDGEMODE_DUPLICATE;
92
 
    feConvolveMatrix->preserveAlpha = false;
93
 
 
94
 
    //some helper variables:
95
 
    feConvolveMatrix->targetXIsSet = false;
96
 
    feConvolveMatrix->targetYIsSet = false;
97
 
    feConvolveMatrix->kernelMatrixIsSet = false;
98
 
}
99
 
 
100
 
/**
101
 
 * Reads the Inkscape::XML::Node, and initializes SPFeConvolveMatrix variables.  For this to get called,
102
 
 * our name must be associated with a repr via "sp_object_type_register".  Best done through
103
 
 * sp-object-repr.cpp's repr_name_entries array.
104
 
 */
105
 
static void
106
 
sp_feConvolveMatrix_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
107
 
{
108
 
    if (((SPObjectClass *) feConvolveMatrix_parent_class)->build) {
109
 
        ((SPObjectClass *) feConvolveMatrix_parent_class)->build(object, document, repr);
110
 
    }
111
 
 
112
 
    /*LOAD ATTRIBUTES FROM REPR HERE*/
113
 
    sp_object_read_attr(object, "order");
114
 
    sp_object_read_attr(object, "kernelMatrix");
115
 
    sp_object_read_attr(object, "divisor");
116
 
    sp_object_read_attr(object, "bias");
117
 
    sp_object_read_attr(object, "targetX");
118
 
    sp_object_read_attr(object, "targetY");
119
 
    sp_object_read_attr(object, "edgeMode");
120
 
    sp_object_read_attr(object, "kernelUnitLength");
121
 
    sp_object_read_attr(object, "preserveAlpha");
122
 
}
123
 
 
124
 
/**
125
 
 * Drops any allocated memory.
126
 
 */
127
 
static void
128
 
sp_feConvolveMatrix_release(SPObject *object)
129
 
{
130
 
    if (((SPObjectClass *) feConvolveMatrix_parent_class)->release)
131
 
        ((SPObjectClass *) feConvolveMatrix_parent_class)->release(object);
132
 
}
133
 
 
134
 
static NR::FilterConvolveMatrixEdgeMode sp_feConvolveMatrix_read_edgeMode(gchar const *value){
135
 
    if (!value) return NR::CONVOLVEMATRIX_EDGEMODE_DUPLICATE; //duplicate is default
136
 
    switch(value[0]){
137
 
        case 'd':
138
 
            if (strncmp(value, "duplicate", 9) == 0) return NR::CONVOLVEMATRIX_EDGEMODE_DUPLICATE;
139
 
            break;
140
 
        case 'w':
141
 
            if (strncmp(value, "wrap", 4) == 0) return NR::CONVOLVEMATRIX_EDGEMODE_WRAP;
142
 
            break;
143
 
        case 'n':
144
 
            if (strncmp(value, "none", 4) == 0) return NR::CONVOLVEMATRIX_EDGEMODE_NONE;
145
 
            break;
146
 
    }
147
 
    return NR::CONVOLVEMATRIX_EDGEMODE_DUPLICATE; //duplicate is default
148
 
}
149
 
 
150
 
/**
151
 
 * Sets a specific value in the SPFeConvolveMatrix.
152
 
 */
153
 
static void
154
 
sp_feConvolveMatrix_set(SPObject *object, unsigned int key, gchar const *value)
155
 
{
156
 
    SPFeConvolveMatrix *feConvolveMatrix = SP_FECONVOLVEMATRIX(object);
157
 
    (void)feConvolveMatrix;
158
 
    double read_num;
159
 
    int read_int;
160
 
    bool read_bool;
161
 
    NR::FilterConvolveMatrixEdgeMode read_mode;
162
 
   
163
 
    switch(key) {
164
 
        /*DEAL WITH SETTING ATTRIBUTES HERE*/
165
 
        case SP_ATTR_ORDER:
166
 
            feConvolveMatrix->order.set(value);
167
 
            //From SVG spec: If <orderY> is not provided, it defaults to <orderX>.
168
 
            if (feConvolveMatrix->order.optNumIsSet() == false)
169
 
                feConvolveMatrix->order.setOptNumber(feConvolveMatrix->order.getNumber());
170
 
            if (feConvolveMatrix->targetXIsSet == false) feConvolveMatrix->targetX = (int) floor(feConvolveMatrix->order.getNumber()/2);
171
 
            if (feConvolveMatrix->targetYIsSet == false) feConvolveMatrix->targetY = (int) floor(feConvolveMatrix->order.getOptNumber()/2);
172
 
            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
173
 
            break;
174
 
        case SP_ATTR_KERNELMATRIX:
175
 
            if (value){
176
 
                feConvolveMatrix->kernelMatrixIsSet = true;
177
 
                feConvolveMatrix->kernelMatrix = helperfns_read_vector(value, (int) (feConvolveMatrix->order.getNumber() * feConvolveMatrix->order.getOptNumber()));
178
 
                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
179
 
            } else {
180
 
                g_warning("For feConvolveMatrix you MUST pass a kernelMatrix parameter!");
181
 
            }
182
 
            break;
183
 
        case SP_ATTR_DIVISOR:
184
 
            if (!value){
185
 
                read_num = 1; 
186
 
            } else {
187
 
                read_num = helperfns_read_number(value);
188
 
                if (read_num == 0) {
189
 
                    if (feConvolveMatrix->kernelMatrixIsSet){
190
 
                        g_warning("You shouldn't pass a divisor value equal to 0! Assuming the sum of all values in kernelMatrix as the default value.");
191
 
                        for (unsigned int i = 0; i< feConvolveMatrix->kernelMatrix.size(); i++)
192
 
                            read_num += feConvolveMatrix->kernelMatrix[i];
193
 
                    } else {
194
 
                        g_warning("You shouldn't pass a divisor value equal to 0! Assuming 1 as the default value.");
195
 
                        read_num = 1;
196
 
                    }
197
 
                }
198
 
            }
199
 
            if (read_num != feConvolveMatrix->divisor){
200
 
                feConvolveMatrix->divisor = read_num;
201
 
                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
202
 
            }
203
 
            break;
204
 
        case SP_ATTR_BIAS:
205
 
            read_num = 0;
206
 
            if (value) read_num = helperfns_read_number(value);
207
 
            if (read_num != feConvolveMatrix->bias){
208
 
                feConvolveMatrix->bias = read_num;
209
 
                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
210
 
            }
211
 
            break;
212
 
        case SP_ATTR_TARGETX:
213
 
            read_int = (int) helperfns_read_number(value);
214
 
            if (read_int < 0 || read_int > feConvolveMatrix->order.getNumber()){
215
 
                g_warning("targetX must be a value between 0 and orderX! Assuming orderX as default value.");
216
 
                read_int = (int) feConvolveMatrix->order.getNumber();
217
 
            }
218
 
            feConvolveMatrix->targetXIsSet = true;
219
 
            if (read_int != feConvolveMatrix->targetX){
220
 
                feConvolveMatrix->targetX = read_int;
221
 
                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
222
 
            }
223
 
            break;
224
 
        case SP_ATTR_TARGETY:
225
 
            read_int = (int) helperfns_read_number(value);
226
 
            if (read_int < 0 || read_int > feConvolveMatrix->order.getOptNumber()){
227
 
                g_warning("targetY must be a value between 0 and orderY! Assuming orderY as default value.");
228
 
                read_int = (int) feConvolveMatrix->order.getOptNumber();
229
 
            }
230
 
            feConvolveMatrix->targetYIsSet = true;
231
 
            if (read_int != feConvolveMatrix->targetY){
232
 
                feConvolveMatrix->targetY = read_int;
233
 
                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
234
 
            }
235
 
            break;
236
 
        case SP_ATTR_EDGEMODE:
237
 
            read_mode = sp_feConvolveMatrix_read_edgeMode(value);
238
 
            if (read_mode != feConvolveMatrix->edgeMode){
239
 
                feConvolveMatrix->edgeMode = read_mode;
240
 
                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
241
 
            }
242
 
            break;
243
 
        case SP_ATTR_KERNELUNITLENGTH:
244
 
            feConvolveMatrix->kernelUnitLength.set(value);
245
 
            //From SVG spec: If the <dy> value is not specified, it defaults to the same value as <dx>.
246
 
            if (feConvolveMatrix->kernelUnitLength.optNumIsSet() == false)
247
 
                feConvolveMatrix->kernelUnitLength.setOptNumber(feConvolveMatrix->kernelUnitLength.getNumber());
248
 
            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
249
 
            break;
250
 
        case SP_ATTR_PRESERVEALPHA:
251
 
            read_bool = helperfns_read_bool(value, false);
252
 
            if (read_bool != feConvolveMatrix->preserveAlpha){
253
 
                feConvolveMatrix->preserveAlpha = read_bool;
254
 
                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
255
 
            }
256
 
            break;
257
 
        default:
258
 
            if (((SPObjectClass *) feConvolveMatrix_parent_class)->set)
259
 
                ((SPObjectClass *) feConvolveMatrix_parent_class)->set(object, key, value);
260
 
            break;
261
 
    }
262
 
 
263
 
}
264
 
 
265
 
/**
266
 
 * Receives update notifications.
267
 
 */
268
 
static void
269
 
sp_feConvolveMatrix_update(SPObject *object, SPCtx *ctx, guint flags)
270
 
{
271
 
    if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
272
 
                 SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
273
 
 
274
 
        /* do something to trigger redisplay, updates? */
275
 
 
276
 
    }
277
 
 
278
 
    if (((SPObjectClass *) feConvolveMatrix_parent_class)->update) {
279
 
        ((SPObjectClass *) feConvolveMatrix_parent_class)->update(object, ctx, flags);
280
 
    }
281
 
}
282
 
 
283
 
/**
284
 
 * Writes its settings to an incoming repr object, if any.
285
 
 */
286
 
static Inkscape::XML::Node *
287
 
sp_feConvolveMatrix_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags)
288
 
{
289
 
    // Inkscape-only object, not copied during an "plain SVG" dump:
290
 
    if (flags & SP_OBJECT_WRITE_EXT) {
291
 
        if (repr) {
292
 
            // is this sane?
293
 
            //repr->mergeFrom(SP_OBJECT_REPR(object), "id");
294
 
        } else {
295
 
            repr = SP_OBJECT_REPR(object)->duplicate(doc);
296
 
        }
297
 
    }
298
 
 
299
 
    if (((SPObjectClass *) feConvolveMatrix_parent_class)->write) {
300
 
        ((SPObjectClass *) feConvolveMatrix_parent_class)->write(object, doc, repr, flags);
301
 
    }
302
 
 
303
 
    return repr;
304
 
}
305
 
 
306
 
static void sp_feConvolveMatrix_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter) {
307
 
    g_assert(primitive != NULL);
308
 
    g_assert(filter != NULL);
309
 
 
310
 
    SPFeConvolveMatrix *sp_convolve = SP_FECONVOLVEMATRIX(primitive);
311
 
 
312
 
    int primitive_n = filter->add_primitive(NR::NR_FILTER_CONVOLVEMATRIX);
313
 
    NR::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n);
314
 
    NR::FilterConvolveMatrix *nr_convolve = dynamic_cast<NR::FilterConvolveMatrix*>(nr_primitive);
315
 
    g_assert(nr_convolve != NULL);
316
 
 
317
 
    sp_filter_primitive_renderer_common(primitive, nr_primitive);
318
 
 
319
 
    nr_convolve->set_targetX(sp_convolve->targetX);
320
 
    nr_convolve->set_targetY(sp_convolve->targetY);
321
 
    nr_convolve->set_orderX( (int)sp_convolve->order.getNumber() );
322
 
    nr_convolve->set_orderY( (int)sp_convolve->order.getOptNumber() );
323
 
    nr_convolve->set_kernelMatrix(sp_convolve->kernelMatrix);
324
 
    nr_convolve->set_divisor(sp_convolve->divisor);
325
 
    nr_convolve->set_bias(sp_convolve->bias);
326
 
    nr_convolve->set_preserveAlpha(sp_convolve->preserveAlpha);
327
 
 
328
 
}
329
 
/*
330
 
  Local Variables:
331
 
  mode:c++
332
 
  c-file-style:"stroustrup"
333
 
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
334
 
  indent-tabs-mode:nil
335
 
  fill-column:99
336
 
  End:
337
 
*/
338
 
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :