~centralelyon2010/inkscape/imagelinks2

1 by mental
moving trunk for module inkscape
1
/** \file
2
 * SVG \<svg\> implementation.
3
 */
4
/*
5
 * Authors:
6
 *   Lauris Kaplinski <lauris@kaplinski.com>
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
7
 *   Jon A. Cruz <jon@joncruz.org>
8
 *   Abhishek Sharma
1 by mental
moving trunk for module inkscape
9
 *
10
 * Copyright (C) 1999-2002 Lauris Kaplinski
11
 * Copyright (C) 2000-2001 Ximian, Inc.
12
 *
13
 * Released under GNU GPL, read the file 'COPYING' for more information
14
 */
15
4629 by bryce
Applying fixes for gcc 4.3 build issues (closes LP: #169115)
16
#ifdef HAVE_CONFIG_H
17
# include "config.h"
18
#endif
19
20
#include <cstring>
21
#include <string>
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
22
#include <2geom/transforms.h>
1 by mental
moving trunk for module inkscape
23
24
#include "svg/svg.h"
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
25
#include "display/drawing-group.h"
1 by mental
moving trunk for module inkscape
26
#include "attributes.h"
27
#include "print.h"
28
#include "document.h"
29
#include "sp-defs.h"
30
#include "sp-root.h"
31
#include <xml/repr.h>
32
#include "svg/stringstream.h"
7123 by tweenk
Improved version reporting. Add SVN revision and custom status to
33
#include "inkscape-version.h"
1 by mental
moving trunk for module inkscape
34
35
class SPDesktop;
36
37
static void sp_root_class_init(SPRootClass *klass);
38
static void sp_root_init(SPRoot *root);
39
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
40
static void sp_root_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
1 by mental
moving trunk for module inkscape
41
static void sp_root_release(SPObject *object);
42
static void sp_root_set(SPObject *object, unsigned int key, gchar const *value);
43
static void sp_root_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref);
44
static void sp_root_remove_child(SPObject *object, Inkscape::XML::Node *child);
45
static void sp_root_update(SPObject *object, SPCtx *ctx, guint flags);
46
static void sp_root_modified(SPObject *object, guint flags);
5884 by mental
plumb XML::Documents in everywhere
47
static Inkscape::XML::Node *sp_root_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
1 by mental
moving trunk for module inkscape
48
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
49
static Inkscape::DrawingItem *sp_root_show(SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
1 by mental
moving trunk for module inkscape
50
static void sp_root_print(SPItem *item, SPPrintContext *ctx);
51
52
static SPGroupClass *parent_class;
53
54
/**
55
 * Returns the type info of sp_root, including its class sizes and initialization routines.
56
 */
57
GType
58
sp_root_get_type(void)
59
{
60
    static GType type = 0;
61
    if (!type) {
62
        GTypeInfo info = {
63
            sizeof(SPRootClass),
64
            NULL, NULL,
65
            (GClassInitFunc) sp_root_class_init,
66
            NULL, NULL,
67
            sizeof(SPRoot),
68
            16,
69
            (GInstanceInitFunc) sp_root_init,
70
            NULL,   /* value_table */
71
        };
72
        type = g_type_register_static(SP_TYPE_GROUP, "SPRoot", &info, (GTypeFlags)0);
73
    }
74
    return type;
75
}
76
77
/**
78
 * Initializes an SPRootClass object by setting its class and parent class objects, and registering
79
 * function pointers (i.e.\ gobject-style virtual functions) for various operations.
80
 */
81
static void
82
sp_root_class_init(SPRootClass *klass)
83
{
84
    GObjectClass *object_class;
85
    SPObjectClass *sp_object_class;
86
    SPItemClass *sp_item_class;
87
88
    object_class = G_OBJECT_CLASS(klass);
89
    sp_object_class = (SPObjectClass *) klass;
90
    sp_item_class = (SPItemClass *) klass;
91
92
    parent_class = (SPGroupClass *)g_type_class_ref(SP_TYPE_GROUP);
93
94
    sp_object_class->build = sp_root_build;
95
    sp_object_class->release = sp_root_release;
96
    sp_object_class->set = sp_root_set;
97
    sp_object_class->child_added = sp_root_child_added;
98
    sp_object_class->remove_child = sp_root_remove_child;
99
    sp_object_class->update = sp_root_update;
100
    sp_object_class->modified = sp_root_modified;
101
    sp_object_class->write = sp_root_write;
102
103
    sp_item_class->show = sp_root_show;
104
    sp_item_class->print = sp_root_print;
105
}
106
107
/**
108
 * Initializes an SPRoot object by setting its default parameter values.
109
 */
110
static void
111
sp_root_init(SPRoot *root)
112
{
113
    static Inkscape::Version const zero_version(0, 0);
114
115
    sp_version_from_string(SVG_VERSION, &root->original.svg);
8029 by joncruz
Removed sodipodi:version
116
    root->version.svg = zero_version;
117
    root->original.svg = zero_version;
118
    root->version.inkscape = zero_version;
119
    root->original.inkscape = zero_version;
1 by mental
moving trunk for module inkscape
120
121
    root->x.unset();
122
    root->y.unset();
123
    root->width.unset(SVGLength::PERCENT, 1.0, 1.0);
124
    root->height.unset(SVGLength::PERCENT, 1.0, 1.0);
125
126
    root->viewBox_set = FALSE;
127
6839 by cilix42
Next roud of NR ==> Geom conversion
128
    root->c2p.setIdentity();
1 by mental
moving trunk for module inkscape
129
130
    root->defs = NULL;
131
}
132
133
/**
134
 * Fills in the data for an SPObject from its Inkscape::XML::Node object.
135
 * It fills in data such as version, x, y, width, height, etc.
136
 * It then calls the object's parent class object's build function.
137
 */
138
static void
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
139
sp_root_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
1 by mental
moving trunk for module inkscape
140
{
141
    SPGroup *group = (SPGroup *) object;
142
    SPRoot *root = (SPRoot *) object;
143
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
144
    //XML Tree being used directly here while it shouldn't be.
145
    if ( !object->getRepr()->attribute("version") ) {
8029 by joncruz
Removed sodipodi:version
146
        repr->setAttribute("version", SVG_VERSION);
147
    }
8028 by joncruz
Correct handling of version and set to 1.1 for default. Fixes bug #168180.
148
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
149
    object->readAttr( "version" );
150
    object->readAttr( "inkscape:version" );
1 by mental
moving trunk for module inkscape
151
    /* It is important to parse these here, so objects will have viewport build-time */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
152
    object->readAttr( "x" );
153
    object->readAttr( "y" );
154
    object->readAttr( "width" );
155
    object->readAttr( "height" );
156
    object->readAttr( "viewBox" );
157
    object->readAttr( "preserveAspectRatio" );
158
    object->readAttr( "onload" );
1 by mental
moving trunk for module inkscape
159
160
    if (((SPObjectClass *) parent_class)->build)
161
        (* ((SPObjectClass *) parent_class)->build) (object, document, repr);
162
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
163
    // Search for first <defs> node
164
    for (SPObject *o = group->firstChild() ; o ; o = o->getNext() ) {
1 by mental
moving trunk for module inkscape
165
        if (SP_IS_DEFS(o)) {
166
            root->defs = SP_DEFS(o);
167
            break;
168
        }
169
    }
170
171
    // clear transform, if any was read in - SVG does not allow transform= on <svg>
7032 by verbalshadow
More NR ==> Geom changes
172
    SP_ITEM(object)->transform = Geom::identity();
1 by mental
moving trunk for module inkscape
173
}
174
175
/**
176
 * This is a destructor routine for SPRoot objects.  It de-references any \<def\> items and calls
177
 * the parent class destructor.
178
 */
179
static void
180
sp_root_release(SPObject *object)
181
{
182
    SPRoot *root = (SPRoot *) object;
183
    root->defs = NULL;
184
185
    if (((SPObjectClass *) parent_class)->release)
186
        ((SPObjectClass *) parent_class)->release(object);
187
}
188
189
/**
190
 * Sets the attribute given by key for SPRoot objects to the value specified by value.
191
 */
192
static void
193
sp_root_set(SPObject *object, unsigned int key, gchar const *value)
194
{
195
    SPRoot *root = SP_ROOT(object);
196
197
    switch (key) {
198
        case SP_ATTR_VERSION:
199
            if (!sp_version_from_string(value, &root->version.svg)) {
200
                root->version.svg = root->original.svg;
201
            }
202
            break;
203
        case SP_ATTR_INKSCAPE_VERSION:
204
            if (!sp_version_from_string(value, &root->version.inkscape)) {
205
                root->version.inkscape = root->original.inkscape;
206
            }
207
            break;
208
        case SP_ATTR_X:
209
            if (!root->x.readAbsolute(value)) {
210
                /* fixme: em, ex, % are probably valid, but require special treatment (Lauris) */
211
                root->x.unset();
212
            }
213
            /* fixme: I am almost sure these do not require viewport flag (Lauris) */
214
            object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG);
215
            break;
216
        case SP_ATTR_Y:
217
            if (!root->y.readAbsolute(value)) {
218
                /* fixme: em, ex, % are probably valid, but require special treatment (Lauris) */
219
                root->y.unset();
220
            }
221
            /* fixme: I am almost sure these do not require viewport flag (Lauris) */
222
            object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG);
223
            break;
224
        case SP_ATTR_WIDTH:
225
            if (!root->width.readAbsolute(value) || !(root->width.computed > 0.0)) {
226
                /* fixme: em, ex, % are probably valid, but require special treatment (Lauris) */
227
                root->width.unset(SVGLength::PERCENT, 1.0, 1.0);
228
            }
229
            object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG);
230
            break;
231
        case SP_ATTR_HEIGHT:
232
            if (!root->height.readAbsolute(value) || !(root->height.computed > 0.0)) {
233
                /* fixme: em, ex, % are probably valid, but require special treatment (Lauris) */
234
                root->height.unset(SVGLength::PERCENT, 1.0, 1.0);
235
            }
236
            object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG);
237
            break;
238
        case SP_ATTR_VIEWBOX:
239
            if (value) {
240
                double x, y, width, height;
241
                char *eptr;
242
                /* fixme: We have to take original item affine into account */
243
                /* fixme: Think (Lauris) */
244
                eptr = (gchar *) value;
245
                x = g_ascii_strtod(eptr, &eptr);
246
                while (*eptr && ((*eptr == ',') || (*eptr == ' '))) eptr++;
247
                y = g_ascii_strtod(eptr, &eptr);
248
                while (*eptr && ((*eptr == ',') || (*eptr == ' '))) eptr++;
249
                width = g_ascii_strtod(eptr, &eptr);
250
                while (*eptr && ((*eptr == ',') || (*eptr == ' '))) eptr++;
251
                height = g_ascii_strtod(eptr, &eptr);
252
                while (*eptr && ((*eptr == ',') || (*eptr == ' '))) eptr++;
253
                if ((width > 0) && (height > 0)) {
254
                    /* Set viewbox */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
255
                    root->viewBox = Geom::Rect::from_xywh(x, y, width, height);
1 by mental
moving trunk for module inkscape
256
                    root->viewBox_set = TRUE;
257
                } else {
258
                    root->viewBox_set = FALSE;
259
                }
260
            } else {
261
                root->viewBox_set = FALSE;
262
            }
263
            object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG);
264
            break;
265
        case SP_ATTR_PRESERVEASPECTRATIO:
266
            /* Do setup before, so we can use break to escape */
267
            root->aspect_set = FALSE;
268
            root->aspect_align = SP_ASPECT_XMID_YMID;
269
            root->aspect_clip = SP_ASPECT_MEET;
270
            object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG);
271
            if (value) {
272
                int len;
273
                gchar c[256];
274
                gchar const *p, *e;
275
                unsigned int align, clip;
276
                p = value;
277
                while (*p && *p == 32) p += 1;
278
                if (!*p) break;
279
                e = p;
280
                while (*e && *e != 32) e += 1;
281
                len = e - p;
282
                if (len > 8) break;
283
                memcpy(c, value, len);
284
                c[len] = 0;
285
                /* Now the actual part */
286
                if (!strcmp(c, "none")) {
287
                    align = SP_ASPECT_NONE;
288
                } else if (!strcmp(c, "xMinYMin")) {
289
                    align = SP_ASPECT_XMIN_YMIN;
290
                } else if (!strcmp(c, "xMidYMin")) {
291
                    align = SP_ASPECT_XMID_YMIN;
292
                } else if (!strcmp(c, "xMaxYMin")) {
293
                    align = SP_ASPECT_XMAX_YMIN;
294
                } else if (!strcmp(c, "xMinYMid")) {
295
                    align = SP_ASPECT_XMIN_YMID;
296
                } else if (!strcmp(c, "xMidYMid")) {
297
                    align = SP_ASPECT_XMID_YMID;
6990 by speleo3
typo in xMaxYMid
298
                } else if (!strcmp(c, "xMaxYMid")) {
1 by mental
moving trunk for module inkscape
299
                    align = SP_ASPECT_XMAX_YMID;
300
                } else if (!strcmp(c, "xMinYMax")) {
301
                    align = SP_ASPECT_XMIN_YMAX;
302
                } else if (!strcmp(c, "xMidYMax")) {
303
                    align = SP_ASPECT_XMID_YMAX;
304
                } else if (!strcmp(c, "xMaxYMax")) {
305
                    align = SP_ASPECT_XMAX_YMAX;
306
                } else {
307
                    break;
308
                }
309
                clip = SP_ASPECT_MEET;
310
                while (*e && *e == 32) e += 1;
6988 by speleo3
bug #166885 (preserveAspectRatio="none" misinterpreted)
311
                if (*e) {
1 by mental
moving trunk for module inkscape
312
                    if (!strcmp(e, "meet")) {
313
                        clip = SP_ASPECT_MEET;
314
                    } else if (!strcmp(e, "slice")) {
315
                        clip = SP_ASPECT_SLICE;
316
                    } else {
317
                        break;
318
                    }
319
                }
320
                root->aspect_set = TRUE;
321
                root->aspect_align = align;
322
                root->aspect_clip = clip;
323
            }
324
            break;
6391 by JucaBlues
initial handling of <script> tag
325
        case SP_ATTR_ONLOAD:
326
            root->onload = (char *) value;
327
            break;
1 by mental
moving trunk for module inkscape
328
        default:
329
            /* Pass the set event to the parent */
330
            if (((SPObjectClass *) parent_class)->set) {
331
                ((SPObjectClass *) parent_class)->set(object, key, value);
332
            }
333
            break;
334
    }
335
}
336
337
/**
338
 * This routine is for adding a child SVG object to an SPRoot object.
339
 * The SPRoot object is taken to be an SPGroup.
340
 */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
341
static void sp_root_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
1 by mental
moving trunk for module inkscape
342
{
343
    SPRoot *root = (SPRoot *) object;
344
    SPGroup *group = (SPGroup *) object;
345
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
346
    if (((SPObjectClass *) (parent_class))->child_added) {
1 by mental
moving trunk for module inkscape
347
        (* ((SPObjectClass *) (parent_class))->child_added)(object, child, ref);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
348
    }
1 by mental
moving trunk for module inkscape
349
350
    SPObject *co = object->document->getObjectByRepr(child);
2355 by buliabyak
fix 1654495: a comment repr node has no spobject, so we must weaken the asserts
351
    g_assert (co != NULL || !strcmp("comment", child->name())); // comment repr node has no object
1 by mental
moving trunk for module inkscape
352
2355 by buliabyak
fix 1654495: a comment repr node has no spobject, so we must weaken the asserts
353
    if (co && SP_IS_DEFS(co)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
354
        // We search for first <defs> node - it is not beautiful, but works
355
        for (SPObject *c = group->firstChild() ; c ; c = c->getNext() ) {
1 by mental
moving trunk for module inkscape
356
            if (SP_IS_DEFS(c)) {
357
                root->defs = SP_DEFS(c);
358
                break;
359
            }
360
        }
361
    }
362
}
363
364
/**
365
 * Removes the given child from this SPRoot object.
366
 */
367
static void sp_root_remove_child(SPObject *object, Inkscape::XML::Node *child)
368
{
369
    SPRoot *root = (SPRoot *) object;
370
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
371
    if ( root->defs && (root->defs->getRepr() == child) ) {
372
        SPObject *iter = 0;
373
        // We search for first remaining <defs> node - it is not beautiful, but works
374
        for ( iter = object->firstChild() ; iter ; iter = iter->getNext() ) {
1 by mental
moving trunk for module inkscape
375
            if ( SP_IS_DEFS(iter) && (SPDefs *)iter != root->defs ) {
376
                root->defs = (SPDefs *)iter;
377
                break;
378
            }
379
        }
380
        if (!iter) {
381
            /* we should probably create a new <defs> here? */
382
            root->defs = NULL;
383
        }
384
    }
385
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
386
    if (((SPObjectClass *) (parent_class))->remove_child) {
1 by mental
moving trunk for module inkscape
387
        (* ((SPObjectClass *) (parent_class))->remove_child)(object, child);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
388
    }
1 by mental
moving trunk for module inkscape
389
}
390
391
/**
392
 * This callback routine updates the SPRoot object when its attributes have been changed.
393
 */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
394
static void sp_root_update(SPObject *object, SPCtx *ctx, guint flags)
1 by mental
moving trunk for module inkscape
395
{
396
    SPRoot *root = SP_ROOT(object);
397
    SPItemCtx *ictx = (SPItemCtx *) ctx;
398
399
    /* fixme: This will be invoked too often (Lauris) */
400
    /* fixme: We should calculate only if parent viewport has changed (Lauris) */
401
    /* If position is specified as percentage, calculate actual values */
402
    if (root->x.unit == SVGLength::PERCENT) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
403
        root->x.computed = root->x.value * ictx->viewport.width();
1 by mental
moving trunk for module inkscape
404
    }
405
    if (root->y.unit == SVGLength::PERCENT) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
406
        root->y.computed = root->y.value * ictx->viewport.height();
1 by mental
moving trunk for module inkscape
407
    }
408
    if (root->width.unit == SVGLength::PERCENT) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
409
        root->width.computed = root->width.value * ictx->viewport.width();
1 by mental
moving trunk for module inkscape
410
    }
411
    if (root->height.unit == SVGLength::PERCENT) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
412
        root->height.computed = root->height.value * ictx->viewport.height();
1 by mental
moving trunk for module inkscape
413
    }
414
415
    /* Create copy of item context */
416
    SPItemCtx rctx = *ictx;
417
418
    /* Calculate child to parent transformation */
6839 by cilix42
Next roud of NR ==> Geom conversion
419
    root->c2p.setIdentity();
1 by mental
moving trunk for module inkscape
420
421
    if (object->parent) {
422
        /*
423
         * fixme: I am not sure whether setting x and y does or does not
424
         * fixme: translate the content of inner SVG.
425
         * fixme: Still applying translation and setting viewport to width and
426
         * fixme: height seems natural, as this makes the inner svg element
427
         * fixme: self-contained. The spec is vague here.
428
         */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
429
        root->c2p = Geom::Affine(Geom::Translate(root->x.computed,
6839 by cilix42
Next roud of NR ==> Geom conversion
430
                                                 root->y.computed));
1 by mental
moving trunk for module inkscape
431
    }
432
433
    if (root->viewBox_set) {
434
        double x, y, width, height;
435
        /* Determine actual viewbox in viewport coordinates */
436
        if (root->aspect_align == SP_ASPECT_NONE) {
437
            x = 0.0;
438
            y = 0.0;
439
            width = root->width.computed;
440
            height = root->height.computed;
441
        } else {
442
            double scalex, scaley, scale;
443
            /* Things are getting interesting */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
444
            scalex = root->width.computed / root->viewBox.width();
445
            scaley = root->height.computed / root->viewBox.height();
1 by mental
moving trunk for module inkscape
446
            scale = (root->aspect_clip == SP_ASPECT_MEET) ? MIN(scalex, scaley) : MAX(scalex, scaley);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
447
            width = root->viewBox.width() * scale;
448
            height = root->viewBox.height() * scale;
1 by mental
moving trunk for module inkscape
449
            /* Now place viewbox to requested position */
450
            /* todo: Use an array lookup to find the 0.0/0.5/1.0 coefficients,
451
               as is done for dialogs/align.cpp. */
452
            switch (root->aspect_align) {
453
                case SP_ASPECT_XMIN_YMIN:
454
                    x = 0.0;
455
                    y = 0.0;
456
                    break;
457
                case SP_ASPECT_XMID_YMIN:
458
                    x = 0.5 * (root->width.computed - width);
459
                    y = 0.0;
460
                    break;
461
                case SP_ASPECT_XMAX_YMIN:
462
                    x = 1.0 * (root->width.computed - width);
463
                    y = 0.0;
464
                    break;
465
                case SP_ASPECT_XMIN_YMID:
466
                    x = 0.0;
467
                    y = 0.5 * (root->height.computed - height);
468
                    break;
469
                case SP_ASPECT_XMID_YMID:
470
                    x = 0.5 * (root->width.computed - width);
471
                    y = 0.5 * (root->height.computed - height);
472
                    break;
473
                case SP_ASPECT_XMAX_YMID:
474
                    x = 1.0 * (root->width.computed - width);
475
                    y = 0.5 * (root->height.computed - height);
476
                    break;
477
                case SP_ASPECT_XMIN_YMAX:
478
                    x = 0.0;
479
                    y = 1.0 * (root->height.computed - height);
480
                    break;
481
                case SP_ASPECT_XMID_YMAX:
482
                    x = 0.5 * (root->width.computed - width);
483
                    y = 1.0 * (root->height.computed - height);
484
                    break;
485
                case SP_ASPECT_XMAX_YMAX:
486
                    x = 1.0 * (root->width.computed - width);
487
                    y = 1.0 * (root->height.computed - height);
488
                    break;
489
                default:
490
                    x = 0.0;
491
                    y = 0.0;
492
                    break;
493
            }
494
        }
495
496
        /* Compose additional transformation from scale and position */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
497
        Geom::Scale const viewBox_length( root->viewBox.dimensions() );
6839 by cilix42
Next roud of NR ==> Geom conversion
498
        Geom::Scale const new_length(width, height);
1 by mental
moving trunk for module inkscape
499
500
        /* Append viewbox transformation */
501
        /* TODO: The below looks suspicious to me (pjrm): I wonder whether the RHS
502
           expression should have c2p at the beginning rather than at the end.  Test it. */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
503
        root->c2p = Geom::Translate(-root->viewBox.min()) * ( new_length * viewBox_length.inverse() ) * Geom::Translate(x, y) * root->c2p;
1 by mental
moving trunk for module inkscape
504
    }
505
506
    rctx.i2doc = root->c2p * rctx.i2doc;
507
508
    /* Initialize child viewport */
509
    if (root->viewBox_set) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
510
        rctx.viewport = root->viewBox;
1 by mental
moving trunk for module inkscape
511
    } else {
512
        /* fixme: I wonder whether this logic is correct (Lauris) */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
513
        Geom::Point minp(0,0);
1 by mental
moving trunk for module inkscape
514
        if (object->parent) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
515
            minp = Geom::Point(root->x.computed, root->y.computed);
1 by mental
moving trunk for module inkscape
516
        }
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
517
        rctx.viewport = Geom::Rect::from_xywh(minp[Geom::X], minp[Geom::Y], root->width.computed, root->height.computed);
1 by mental
moving trunk for module inkscape
518
    }
519
7032 by verbalshadow
More NR ==> Geom changes
520
    rctx.i2vp = Geom::identity();
1 by mental
moving trunk for module inkscape
521
522
    /* And invoke parent method */
523
    if (((SPObjectClass *) (parent_class))->update)
524
        ((SPObjectClass *) (parent_class))->update(object, (SPCtx *) &rctx, flags);
525
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
526
    /* As last step set additional transform of drawing group */
527
    for (SPItemView *v = root->display; v != NULL; v = v->next) {
528
        Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
529
        g->setChildTransform(root->c2p);
1 by mental
moving trunk for module inkscape
530
    }
531
}
532
533
/**
534
 * Calls the <tt>modified</tt> routine of the SPRoot object's parent class.
535
 * Also, if the viewport has been modified, it sets the document size to the new
536
 * height and width.
537
 */
538
static void
539
sp_root_modified(SPObject *object, guint flags)
540
{
541
    SPRoot *root = SP_ROOT(object);
542
543
    if (((SPObjectClass *) (parent_class))->modified)
544
        (* ((SPObjectClass *) (parent_class))->modified)(object, flags);
545
546
    /* fixme: (Lauris) */
547
    if (!object->parent && (flags & SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
548
        root->document->emitResizedSignal(root->width.computed, root->height.computed);
1 by mental
moving trunk for module inkscape
549
    }
550
}
551
552
/**
553
 * Writes the object into the repr object, then calls the parent's write routine.
554
 */
555
static Inkscape::XML::Node *
5884 by mental
plumb XML::Documents in everywhere
556
sp_root_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
1 by mental
moving trunk for module inkscape
557
{
558
    SPRoot *root = SP_ROOT(object);
559
560
    if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
2253 by mental
start switching sp_repr_new* over to XML::Document::create*, and rename create methods to match DOM
561
        repr = xml_doc->createElement("svg:svg");
1 by mental
moving trunk for module inkscape
562
    }
563
564
    if (flags & SP_OBJECT_WRITE_EXT) {
7123 by tweenk
Improved version reporting. Add SVN revision and custom status to
565
        repr->setAttribute("inkscape:version", Inkscape::version_string);
1 by mental
moving trunk for module inkscape
566
    }
567
8028 by joncruz
Correct handling of version and set to 1.1 for default. Fixes bug #168180.
568
    if ( !repr->attribute("version") ) {
569
        repr->setAttribute("version", sp_version_to_string(root->version.svg));
570
    }
1 by mental
moving trunk for module inkscape
571
572
    if (fabs(root->x.computed) > 1e-9)
573
        sp_repr_set_svg_double(repr, "x", root->x.computed);
574
    if (fabs(root->y.computed) > 1e-9)
575
        sp_repr_set_svg_double(repr, "y", root->y.computed);
576
577
    /* Unlike all other SPObject, here we want to preserve absolute units too (and only here,
578
     * according to the recommendation in http://www.w3.org/TR/SVG11/coords.html#Units).
579
     */
580
    repr->setAttribute("width", sp_svg_length_write_with_units(root->width).c_str());
581
    repr->setAttribute("height", sp_svg_length_write_with_units(root->height).c_str());
582
583
    if (root->viewBox_set) {
584
        Inkscape::SVGOStringStream os;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
585
        os << root->viewBox.left() << " " << root->viewBox.top() << " "
586
           << root->viewBox.width() << " " << root->viewBox.height();
1 by mental
moving trunk for module inkscape
587
        repr->setAttribute("viewBox", os.str().c_str());
149 by rwst
bulk trailing spaces removal. consistency through MD5 of binary
588
    }
1 by mental
moving trunk for module inkscape
589
590
    if (((SPObjectClass *) (parent_class))->write)
5884 by mental
plumb XML::Documents in everywhere
591
        ((SPObjectClass *) (parent_class))->write(object, xml_doc, repr, flags);
1 by mental
moving trunk for module inkscape
592
593
    return repr;
594
}
595
596
/**
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
597
 * Displays the SPRoot item on the drawing.
1 by mental
moving trunk for module inkscape
598
 */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
599
static Inkscape::DrawingItem *
600
sp_root_show(SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags)
1 by mental
moving trunk for module inkscape
601
{
602
    SPRoot *root = SP_ROOT(item);
603
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
604
    Inkscape::DrawingItem *ai;
1 by mental
moving trunk for module inkscape
605
    if (((SPItemClass *) (parent_class))->show) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
606
        ai = ((SPItemClass *) (parent_class))->show(item, drawing, key, flags);
1 by mental
moving trunk for module inkscape
607
        if (ai) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
608
            Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(ai);
609
            g->setChildTransform(root->c2p);
1 by mental
moving trunk for module inkscape
610
        }
611
    } else {
612
        ai = NULL;
613
    }
614
615
    return ai;
616
}
617
618
/**
619
 * Virtual print callback.
620
 */
621
static void
622
sp_root_print(SPItem *item, SPPrintContext *ctx)
623
{
624
    SPRoot *root = SP_ROOT(item);
625
626
    sp_print_bind(ctx, root->c2p, 1.0);
627
628
    if (((SPItemClass *) (parent_class))->print) {
629
        ((SPItemClass *) (parent_class))->print(item, ctx);
630
    }
631
632
    sp_print_release(ctx);
633
}
634
635
636
/*
637
  Local Variables:
638
  mode:c++
639
  c-file-style:"stroustrup"
640
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
641
  indent-tabs-mode:nil
642
  fill-column:99
643
  End:
644
*/
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
645
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :