~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/svg/svg-affine.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Ted Gould, Kees Cook
  • Date: 2009-06-24 14:00:43 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624140043-07stp20mry48hqup
Tags: 0.47~pre0-0ubuntu1
* New upstream release

[ Ted Gould ]
* debian/control: Adding libgsl0 and removing version specifics on boost

[ Kees Cook ]
* debian/watch: updated to run uupdate and mangle pre-release versions.
* Dropped patches that have been taken upstream:
  - 01_mips
  - 02-poppler-0.8.3
  - 03-chinese-inkscape
  - 05_fix_latex_patch
  - 06_gcc-4.4
  - 07_cdr2svg
  - 08_skip-bad-utf-on-pdf-import
  - 09_gtk-clist
  - 10_belarussian
  - 11_libpng
  - 12_desktop
  - 13_slider
  - 100_svg_import_improvements
  - 102_sp_pattern_painter_free
  - 103_bitmap_type_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define __SP_SVG_AFFINE_C__
2
 
 
3
1
/*
4
2
 * SVG data parser
5
3
 *
24
22
#include <glib/gstrfuncs.h>
25
23
#include <libnr/nr-matrix-fns.h>
26
24
#include <libnr/nr-matrix-ops.h>
27
 
#include <libnr/nr-matrix-translate-ops.h>
28
 
#include <libnr/nr-rotate-fns.h>
29
 
#include <libnr/nr-rotate-matrix-ops.h>
30
 
#include <libnr/nr-scale-matrix-ops.h>
31
 
#include <libnr/nr-translate-matrix-ops.h>
32
 
#include <libnr/nr-translate-rotate-ops.h>
 
25
#include <2geom/transforms.h>
 
26
#include <2geom/angle.h>
 
27
#include <libnr/nr-convert2geom.h>
33
28
#include "svg.h"
34
 
#include "prefs-utils.h"
 
29
#include "preferences.h"
35
30
 
36
31
#ifndef M_PI
37
32
# define M_PI 3.14159265358979323846
38
33
#endif
39
34
 
40
35
bool
41
 
sp_svg_transform_read(gchar const *str, NR::Matrix *transform)
 
36
sp_svg_transform_read(gchar const *str, Geom::Matrix *transform)
42
37
{
43
 
        int idx;
44
 
        char keyword[32];
45
 
        double args[6];
46
 
        int n_args;
47
 
        size_t key_len;
48
 
 
49
 
        if (str == NULL) return false;
50
 
 
51
 
        NR::Matrix a(NR::identity());
52
 
 
53
 
        idx = 0;
54
 
        while (str[idx]) {
55
 
                /* skip initial whitespace */
56
 
                while (g_ascii_isspace (str[idx])) idx++;
57
 
 
58
 
                /* parse keyword */
59
 
                for (key_len = 0; key_len < sizeof (keyword); key_len++) {
60
 
                        char c;
61
 
 
62
 
                        c = str[idx];
63
 
                        if (g_ascii_isalpha (c) || c == '-') {
64
 
                                keyword[key_len] = str[idx++];
65
 
                        } else {
66
 
                                break;
67
 
                        }
68
 
                }
69
 
                if (key_len >= sizeof (keyword)) return false;
70
 
                keyword[key_len] = '\0';
71
 
 
72
 
                /* skip whitespace */
73
 
                while (g_ascii_isspace (str[idx])) idx++;
74
 
 
75
 
                if (str[idx] != '(') return false;
76
 
                idx++;
77
 
 
78
 
                for (n_args = 0; ; n_args++) {
79
 
                        char c;
80
 
                        char *end_ptr;
81
 
 
82
 
                        /* skip whitespace */
83
 
                        while (g_ascii_isspace (str[idx])) idx++;
84
 
                        c = str[idx];
85
 
                        if (g_ascii_isdigit (c) || c == '+' || c == '-' || c == '.') {
86
 
                                if (n_args == sizeof (args) / sizeof (args[0])) return false; /* Too many args */
87
 
                                args[n_args] = g_ascii_strtod (str + idx, &end_ptr);
88
 
                                
89
 
                                //printf("took %d chars from '%s' to make %f\n",
90
 
                                //              end_ptr-(str+idx),
91
 
                                //              str+idx,
92
 
                                //              args[n_args]);
93
 
 
94
 
                                idx = end_ptr - (char *) str;
95
 
 
96
 
                                while (g_ascii_isspace (str[idx])) idx++;
97
 
 
98
 
                                /* skip optional comma */
99
 
                                if (str[idx] == ',') idx++;
100
 
                        } else if (c == ')') {
101
 
                                break;
102
 
                        } else {
103
 
                                return false;
104
 
                        }
105
 
                }
106
 
                idx++;
107
 
 
108
 
                /* ok, have parsed keyword and args, now modify the transform */
109
 
                if (!strcmp (keyword, "matrix")) {
110
 
                        if (n_args != 6) return false;
111
 
                        a = NR_MATRIX_D_FROM_DOUBLE(args) * a;
112
 
                } else if (!strcmp (keyword, "translate")) {
113
 
                        if (n_args == 1) {
114
 
                                args[1] = 0;
115
 
                        } else if (n_args != 2) {
116
 
                                return false;
117
 
                        }
118
 
                        a = NR::translate(args[0], args[1]) * a;
119
 
                } else if (!strcmp (keyword, "scale")) {
120
 
                        if (n_args == 1) {
121
 
                                args[1] = args[0];
122
 
                        } else if (n_args != 2) {
123
 
                                return false;
124
 
                        }
125
 
                        a = NR::scale(args[0], args[1]) * a;
126
 
                } else if (!strcmp (keyword, "rotate")) {
127
 
                        if (n_args != 1 && n_args != 3) {
128
 
                                return false;
129
 
                        }
130
 
                        NR::rotate const rot(rotate_degrees(args[0]));
131
 
                        if (n_args == 3) {
132
 
                                a = ( NR::translate(-args[1], -args[2])
133
 
                                      * rot
134
 
                                      * NR::translate(args[1], args[2])
135
 
                                      * a );
136
 
                        } else {
137
 
                                a = rot * a;
138
 
                        }
139
 
                } else if (!strcmp (keyword, "skewX")) {
140
 
                        if (n_args != 1) return false;
141
 
                        a = ( NR::Matrix(1, 0,
142
 
                                         tan(args[0] * M_PI / 180.0), 1,
143
 
                                         0, 0)
144
 
                              * a );
145
 
                } else if (!strcmp (keyword, "skewY")) {
146
 
                        if (n_args != 1) return false;
147
 
                        a = ( NR::Matrix(1, tan(args[0] * M_PI / 180.0),
148
 
                                         0, 1,
149
 
                                         0, 0)
150
 
                              * a );
151
 
                } else {
152
 
                        return false; /* unknown keyword */
153
 
                }
154
 
                /* Skip trailing whitespace */
 
38
    int idx;
 
39
    char keyword[32];
 
40
    double args[6];
 
41
    int n_args;
 
42
    size_t key_len;
 
43
 
 
44
    if (str == NULL) return false;
 
45
 
 
46
    Geom::Matrix a(Geom::identity());
 
47
 
 
48
    idx = 0;
 
49
    while (str[idx]) {
 
50
        /* skip initial whitespace */
 
51
        while (g_ascii_isspace (str[idx])) idx++;
 
52
 
 
53
        /* parse keyword */
 
54
        for (key_len = 0; key_len < sizeof (keyword); key_len++) {
 
55
            char c;
 
56
 
 
57
            c = str[idx];
 
58
            if (g_ascii_isalpha (c) || c == '-') {
 
59
                keyword[key_len] = str[idx++];
 
60
            } else {
 
61
                break;
 
62
            }
 
63
        }
 
64
        if (key_len >= sizeof (keyword)) return false;
 
65
        keyword[key_len] = '\0';
 
66
 
 
67
        /* skip whitespace */
 
68
        while (g_ascii_isspace (str[idx])) idx++;
 
69
 
 
70
        if (str[idx] != '(') return false;
 
71
        idx++;
 
72
 
 
73
        for (n_args = 0; ; n_args++) {
 
74
            char c;
 
75
            char *end_ptr;
 
76
 
 
77
            /* skip whitespace */
 
78
            while (g_ascii_isspace (str[idx])) idx++;
 
79
            c = str[idx];
 
80
            if (g_ascii_isdigit (c) || c == '+' || c == '-' || c == '.') {
 
81
                if (n_args == sizeof (args) / sizeof (args[0])) return false; /* Too many args */
 
82
                args[n_args] = g_ascii_strtod (str + idx, &end_ptr);
 
83
                
 
84
                //printf("took %d chars from '%s' to make %f\n",
 
85
                //              end_ptr-(str+idx),
 
86
                //              str+idx,
 
87
                //              args[n_args]);
 
88
 
 
89
                idx = end_ptr - (char *) str;
 
90
 
 
91
                while (g_ascii_isspace (str[idx])) idx++;
 
92
 
 
93
                /* skip optional comma */
 
94
                if (str[idx] == ',') idx++;
 
95
            } else if (c == ')') {
 
96
                break;
 
97
            } else {
 
98
                return false;
 
99
            }
 
100
        }
 
101
        idx++;
 
102
 
 
103
        /* ok, have parsed keyword and args, now modify the transform */
 
104
        if (!strcmp (keyword, "matrix")) {
 
105
            if (n_args != 6) return false;
 
106
            a = (*((Geom::Matrix *) &(args)[0])) * a;
 
107
        } else if (!strcmp (keyword, "translate")) {
 
108
            if (n_args == 1) {
 
109
                args[1] = 0;
 
110
            } else if (n_args != 2) {
 
111
                return false;
 
112
            }
 
113
            a = Geom::Translate(args[0], args[1]) * a;
 
114
        } else if (!strcmp (keyword, "scale")) {
 
115
            if (n_args == 1) {
 
116
                args[1] = args[0];
 
117
            } else if (n_args != 2) {
 
118
                return false;
 
119
            }
 
120
            a = Geom::Scale(args[0], args[1]) * a;
 
121
        } else if (!strcmp (keyword, "rotate")) {
 
122
            if (n_args != 1 && n_args != 3) {
 
123
                return false;
 
124
            }
 
125
            Geom::Rotate const rot(Geom::deg_to_rad(args[0]));
 
126
            if (n_args == 3) {
 
127
                a = ( Geom::Translate(-args[1], -args[2])
 
128
                      * rot
 
129
                      * Geom::Translate(args[1], args[2])
 
130
                      * Geom::Matrix(a) );
 
131
            } else {
 
132
                a = rot * a;
 
133
            }
 
134
        } else if (!strcmp (keyword, "skewX")) {
 
135
            if (n_args != 1) return false;
 
136
            a = ( Geom::Matrix(1, 0,
 
137
                     tan(args[0] * M_PI / 180.0), 1,
 
138
                     0, 0)
 
139
                  * a );
 
140
        } else if (!strcmp (keyword, "skewY")) {
 
141
            if (n_args != 1) return false;
 
142
            a = ( Geom::Matrix(1, tan(args[0] * M_PI / 180.0),
 
143
                     0, 1,
 
144
                     0, 0)
 
145
                  * a );
 
146
        } else {
 
147
            return false; /* unknown keyword */
 
148
        }
 
149
        /* Skip trailing whitespace */
155
150
             while (g_ascii_isspace (str[idx])) idx++;
156
 
        }
 
151
    }
157
152
 
158
 
        *transform = a;
159
 
        return true;
 
153
    *transform = a;
 
154
    return true;
160
155
}
161
156
 
162
157
#define EQ(a,b) (fabs ((a) - (b)) < 1e-9)
163
158
 
164
159
gchar *
165
 
sp_svg_transform_write(NR::Matrix const &transform)
 
160
sp_svg_transform_write(Geom::Matrix const &transform)
166
161
{
167
 
        NRMatrix const t(transform);
168
 
        return sp_svg_transform_write(&t);
 
162
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
 
163
 
 
164
    double e = 0.000001 * transform.descrim();
 
165
    int prec = prefs->getInt("/options/svgoutput/numericprecision", 8);
 
166
    int min_exp = prefs->getInt("/options/svgoutput/minimumexponent", -8);
 
167
 
 
168
    /* fixme: We could use t1 * t1 + t2 * t2 here instead */
 
169
    if ( Geom::are_near(transform[1], 0.0, e) && Geom::are_near (transform[2], 0.0, e)) {
 
170
        if (Geom::are_near (transform[4], 0.0, e) && Geom::are_near (transform[5], 0.0, e)) {
 
171
            if (Geom::are_near (transform[0], 1.0, e) && Geom::are_near (transform[3], 1.0, e)) {
 
172
                /* We are more or less identity */
 
173
                return NULL;
 
174
            } else {
 
175
                /* We are more or less scale */
 
176
                gchar c[256];
 
177
                unsigned p = 0;
 
178
                strcpy (c + p, "scale(");
 
179
                p += 6;
 
180
                p += sp_svg_number_write_de (c + p, transform[0], prec, min_exp);
 
181
                c[p++] = ',';
 
182
                p += sp_svg_number_write_de (c + p, transform[3], prec, min_exp);
 
183
                c[p++] = ')';
 
184
                c[p] = '\000';
 
185
                g_assert( p <= sizeof(c) );
 
186
                return g_strdup(c);
 
187
            }
 
188
        } else {
 
189
            if (Geom::are_near (transform[0], 1.0, e) && Geom::are_near (transform[3], 1.0, e)) {
 
190
                /* We are more or less translate */
 
191
                gchar c[256];
 
192
                unsigned p = 0;
 
193
                strcpy (c + p, "translate(");
 
194
                p += 10;
 
195
                p += sp_svg_number_write_de (c + p, transform[4], prec, min_exp);
 
196
                c[p++] = ',';
 
197
                p += sp_svg_number_write_de (c + p, transform[5], prec, min_exp);
 
198
                c[p++] = ')';
 
199
                c[p] = '\000';
 
200
                g_assert( p <= sizeof(c) );
 
201
                return g_strdup(c);
 
202
            } else {
 
203
                gchar c[256];
 
204
                unsigned p = 0;
 
205
                strcpy (c + p, "matrix(");
 
206
                p += 7;
 
207
                p += sp_svg_number_write_de (c + p, transform[0], prec, min_exp);
 
208
                c[p++] = ',';
 
209
                p += sp_svg_number_write_de (c + p, transform[1], prec, min_exp);
 
210
                c[p++] = ',';
 
211
                p += sp_svg_number_write_de (c + p, transform[2], prec, min_exp);
 
212
                c[p++] = ',';
 
213
                p += sp_svg_number_write_de (c + p, transform[3], prec, min_exp);
 
214
                c[p++] = ',';
 
215
                p += sp_svg_number_write_de (c + p, transform[4], prec, min_exp);
 
216
                c[p++] = ',';
 
217
                p += sp_svg_number_write_de (c + p, transform[5], prec, min_exp);
 
218
                c[p++] = ')';
 
219
                c[p] = '\000';
 
220
                g_assert( p <= sizeof(c) );
 
221
                return g_strdup(c);
 
222
            }
 
223
        }
 
224
    } else {
 
225
        gchar c[256];
 
226
        unsigned p = 0;
 
227
        strcpy (c + p, "matrix(");
 
228
        p += 7;
 
229
        p += sp_svg_number_write_de (c + p, transform[0], prec, min_exp);
 
230
        c[p++] = ',';
 
231
        p += sp_svg_number_write_de (c + p, transform[1], prec, min_exp);
 
232
        c[p++] = ',';
 
233
        p += sp_svg_number_write_de (c + p, transform[2], prec, min_exp);
 
234
        c[p++] = ',';
 
235
        p += sp_svg_number_write_de (c + p, transform[3], prec, min_exp);
 
236
        c[p++] = ',';
 
237
        p += sp_svg_number_write_de (c + p, transform[4], prec, min_exp);
 
238
        c[p++] = ',';
 
239
        p += sp_svg_number_write_de (c + p, transform[5], prec, min_exp);
 
240
        c[p++] = ')';
 
241
        c[p] = '\000';
 
242
        g_assert( p <= sizeof(c) );
 
243
        return g_strdup(c);
 
244
    }
169
245
}
170
246
 
 
247
 
171
248
gchar *
172
 
sp_svg_transform_write(NRMatrix const *transform)
 
249
sp_svg_transform_write(Geom::Matrix const *transform)
173
250
{
174
 
        double e;
175
 
 
176
 
        if (!transform) {
177
 
                return NULL;
178
 
        }
179
 
 
180
 
        e = 0.000001 * NR_MATRIX_DF_EXPANSION (transform);
181
 
        int prec = prefs_get_int_attribute("options.svgoutput", "numericprecision", 8);
182
 
        int min_exp = prefs_get_int_attribute("options.svgoutput", "minimumexponent", -8);
183
 
 
184
 
        /* fixme: We could use t1 * t1 + t2 * t2 here instead */
185
 
        if (NR_DF_TEST_CLOSE (transform->c[1], 0.0, e) && NR_DF_TEST_CLOSE (transform->c[2], 0.0, e)) {
186
 
                if (NR_DF_TEST_CLOSE (transform->c[4], 0.0, e) && NR_DF_TEST_CLOSE (transform->c[5], 0.0, e)) {
187
 
                        if (NR_DF_TEST_CLOSE (transform->c[0], 1.0, e) && NR_DF_TEST_CLOSE (transform->c[3], 1.0, e)) {
188
 
                                /* We are more or less identity */
189
 
                                return NULL;
190
 
                        } else {
191
 
                                /* We are more or less scale */
192
 
                                gchar c[256];
193
 
                                unsigned p = 0;
194
 
                                strcpy (c + p, "scale(");
195
 
                                p += 6;
196
 
                                p += sp_svg_number_write_de (c + p, transform->c[0], prec, min_exp, FALSE);
197
 
                                c[p++] = ',';
198
 
                                p += sp_svg_number_write_de (c + p, transform->c[3], prec, min_exp, FALSE);
199
 
                                c[p++] = ')';
200
 
                                c[p] = '\000';
201
 
                                g_assert( p <= sizeof(c) );
202
 
                                return g_strdup(c);
203
 
                        }
204
 
                } else {
205
 
                        if (NR_DF_TEST_CLOSE (transform->c[0], 1.0, e) && NR_DF_TEST_CLOSE (transform->c[3], 1.0, e)) {
206
 
                                /* We are more or less translate */
207
 
                                gchar c[256];
208
 
                                unsigned p = 0;
209
 
                                strcpy (c + p, "translate(");
210
 
                                p += 10;
211
 
                                p += sp_svg_number_write_de (c + p, transform->c[4], prec, min_exp, FALSE);
212
 
                                c[p++] = ',';
213
 
                                p += sp_svg_number_write_de (c + p, transform->c[5], prec, min_exp, FALSE);
214
 
                                c[p++] = ')';
215
 
                                c[p] = '\000';
216
 
                                g_assert( p <= sizeof(c) );
217
 
                                return g_strdup(c);
218
 
                        } else {
219
 
                                gchar c[256];
220
 
                                unsigned p = 0;
221
 
                                strcpy (c + p, "matrix(");
222
 
                                p += 7;
223
 
                                p += sp_svg_number_write_de (c + p, transform->c[0], prec, min_exp, FALSE);
224
 
                                c[p++] = ',';
225
 
                                p += sp_svg_number_write_de (c + p, transform->c[1], prec, min_exp, FALSE);
226
 
                                c[p++] = ',';
227
 
                                p += sp_svg_number_write_de (c + p, transform->c[2], prec, min_exp, FALSE);
228
 
                                c[p++] = ',';
229
 
                                p += sp_svg_number_write_de (c + p, transform->c[3], prec, min_exp, FALSE);
230
 
                                c[p++] = ',';
231
 
                                p += sp_svg_number_write_de (c + p, transform->c[4], prec, min_exp, FALSE);
232
 
                                c[p++] = ',';
233
 
                                p += sp_svg_number_write_de (c + p, transform->c[5], prec, min_exp, FALSE);
234
 
                                c[p++] = ')';
235
 
                                c[p] = '\000';
236
 
                                g_assert( p <= sizeof(c) );
237
 
                                return g_strdup(c);
238
 
                        }
239
 
                }
240
 
        } else {
241
 
                gchar c[256];
242
 
                unsigned p = 0;
243
 
                strcpy (c + p, "matrix(");
244
 
                p += 7;
245
 
                p += sp_svg_number_write_de (c + p, transform->c[0], prec, min_exp, FALSE);
246
 
                c[p++] = ',';
247
 
                p += sp_svg_number_write_de (c + p, transform->c[1], prec, min_exp, FALSE);
248
 
                c[p++] = ',';
249
 
                p += sp_svg_number_write_de (c + p, transform->c[2], prec, min_exp, FALSE);
250
 
                c[p++] = ',';
251
 
                p += sp_svg_number_write_de (c + p, transform->c[3], prec, min_exp, FALSE);
252
 
                c[p++] = ',';
253
 
                p += sp_svg_number_write_de (c + p, transform->c[4], prec, min_exp, FALSE);
254
 
                c[p++] = ',';
255
 
                p += sp_svg_number_write_de (c + p, transform->c[5], prec, min_exp, FALSE);
256
 
                c[p++] = ')';
257
 
                c[p] = '\000';
258
 
                g_assert( p <= sizeof(c) );
259
 
                return g_strdup(c);
260
 
        }
 
251
    return sp_svg_transform_write(*transform);
261
252
}
262
253
 
 
254
/*
 
255
  Local Variables:
 
256
  mode:c++
 
257
  c-file-style:"stroustrup"
 
258
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
259
  indent-tabs-mode:nil
 
260
  fill-column:99
 
261
  End:
 
262
*/
 
263
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :