~ubuntu-branches/debian/experimental/inkscape/experimental

« back to all changes in this revision

Viewing changes to src/sp-feconvolvematrix.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-09-09 23:29:02 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080909232902-c50iujhk1w79u8e7
Tags: 0.46-2.1
* Non-maintainer upload.
* Add upstream patch fixing a crash in the open dialog
  in the zh_CN.utf8 locale. Closes: #487623.
  Thanks to Luca Bruno for the patch.

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::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("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::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(NULL); // FIXME
 
296
        }
 
297
    }
 
298
 
 
299
    if (((SPObjectClass *) feConvolveMatrix_parent_class)->write) {
 
300
        ((SPObjectClass *) feConvolveMatrix_parent_class)->write(object, 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 :