~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/svg/svg-affine.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * SVG data parser
 
3
 *
 
4
 * Authors:
 
5
 *   Lauris Kaplinski <lauris@kaplinski.com>
 
6
 *   Raph Levien <raph@acm.org>
 
7
 *
 
8
 * Copyright (C) 1999-2002 Lauris Kaplinski
 
9
 * Copyright (C) 1999 Raph Levien
 
10
 *
 
11
 * Released under GNU GPL, read the file 'COPYING' for more information
 
12
 */
 
13
 
 
14
#ifdef HAVE_CONFIG_H
 
15
# include "config.h"
 
16
#endif
 
17
 
 
18
#include <cstring>
 
19
#include <string>
 
20
#include <cstdlib>
 
21
#include <cstdio>
 
22
#include <glib/gstrfuncs.h>
 
23
#include <libnr/nr-matrix-fns.h>
 
24
#include <libnr/nr-matrix-ops.h>
 
25
#include <2geom/transforms.h>
 
26
#include <2geom/angle.h>
 
27
#include <libnr/nr-convert2geom.h>
 
28
#include "svg.h"
 
29
#include "preferences.h"
 
30
 
 
31
#ifndef M_PI
 
32
# define M_PI 3.14159265358979323846
 
33
#endif
 
34
 
 
35
bool
 
36
sp_svg_transform_read(gchar const *str, Geom::Matrix *transform)
 
37
{
 
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 */
 
150
             while (g_ascii_isspace (str[idx])) idx++;
 
151
    }
 
152
 
 
153
    *transform = a;
 
154
    return true;
 
155
}
 
156
 
 
157
#define EQ(a,b) (fabs ((a) - (b)) < 1e-9)
 
158
 
 
159
gchar *
 
160
sp_svg_transform_write(Geom::Matrix const &transform)
 
161
{
 
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
    }
 
245
}
 
246
 
 
247
 
 
248
gchar *
 
249
sp_svg_transform_write(Geom::Matrix const *transform)
 
250
{
 
251
    return sp_svg_transform_write(*transform);
 
252
}
 
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 :