~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to src/sp-symbol.cpp

  • Committer: JazzyNico
  • Date: 2011-08-29 20:25:30 UTC
  • Revision ID: nicoduf@yahoo.fr-20110829202530-6deuoz11q90usldv
Code refactoring and merging with trunk (revision 10599).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define __SP_SYMBOL_C__
2
 
 
3
1
/*
4
2
 * SVG <symbol> implementation
5
3
 *
6
4
 * Authors:
7
5
 *   Lauris Kaplinski <lauris@kaplinski.com>
 
6
 *   Abhishek Sharma
 
7
 *   Jon A. Cruz <jon@joncruz.org>
8
8
 *
9
9
 * Copyright (C) 1999-2003 Lauris Kaplinski
10
10
 *
18
18
#include <cstring>
19
19
#include <string>
20
20
 
21
 
#include "libnr/nr-matrix-fns.h"
22
 
#include "libnr/nr-matrix-ops.h"
23
21
#include <2geom/transforms.h>
24
 
#include "display/nr-arena-group.h"
 
22
#include "display/drawing-group.h"
25
23
#include "xml/repr.h"
26
24
#include "attributes.h"
27
25
#include "print.h"
39
37
static void sp_symbol_modified (SPObject *object, guint flags);
40
38
static Inkscape::XML::Node *sp_symbol_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
41
39
 
42
 
static NRArenaItem *sp_symbol_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
 
40
static Inkscape::DrawingItem *sp_symbol_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
43
41
static void sp_symbol_hide (SPItem *item, unsigned int key);
44
 
static void sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
 
42
static Geom::OptRect sp_symbol_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type);
45
43
static void sp_symbol_print (SPItem *item, SPPrintContext *ctx);
46
44
 
47
45
static SPGroupClass *parent_class;
66
64
    return type;
67
65
}
68
66
 
69
 
static void
70
 
sp_symbol_class_init (SPSymbolClass *klass)
 
67
static void sp_symbol_class_init(SPSymbolClass *klass)
71
68
{
72
 
    GObjectClass *object_class;
73
 
    SPObjectClass *sp_object_class;
74
 
    SPItemClass *sp_item_class;
75
 
 
76
 
    object_class = G_OBJECT_CLASS (klass);
77
 
    sp_object_class = (SPObjectClass *) klass;
78
 
    sp_item_class = (SPItemClass *) klass;
 
69
    SPObjectClass *sp_object_class = (SPObjectClass *) klass;
 
70
    SPItemClass *sp_item_class = (SPItemClass *) klass;
79
71
 
80
72
    parent_class = (SPGroupClass *)g_type_class_ref (SP_TYPE_GROUP);
81
73
 
93
85
    sp_item_class->print = sp_symbol_print;
94
86
}
95
87
 
96
 
static void
97
 
sp_symbol_init (SPSymbol *symbol)
 
88
static void sp_symbol_init(SPSymbol *symbol)
98
89
{
99
90
    symbol->viewBox_set = FALSE;
100
91
 
101
92
    symbol->c2p = Geom::identity();
102
93
}
103
94
 
104
 
static void
105
 
sp_symbol_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
 
95
static void sp_symbol_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
106
96
{
107
 
    SPGroup *group;
108
 
    SPSymbol *symbol;
109
 
 
110
 
    group = (SPGroup *) object;
111
 
    symbol = (SPSymbol *) object;
112
 
 
113
 
    sp_object_read_attr (object, "viewBox");
114
 
    sp_object_read_attr (object, "preserveAspectRatio");
115
 
 
116
 
    if (((SPObjectClass *) parent_class)->build)
 
97
    object->readAttr( "viewBox" );
 
98
    object->readAttr( "preserveAspectRatio" );
 
99
 
 
100
    if (((SPObjectClass *) parent_class)->build) {
117
101
        ((SPObjectClass *) parent_class)->build (object, document, repr);
 
102
    }
118
103
}
119
104
 
120
 
static void
121
 
sp_symbol_release (SPObject *object)
 
105
static void sp_symbol_release(SPObject *object)
122
106
{
123
 
    SPSymbol * symbol;
124
 
 
125
 
    symbol = (SPSymbol *) object;
126
 
 
127
 
    if (((SPObjectClass *) parent_class)->release)
 
107
    if (((SPObjectClass *) parent_class)->release) {
128
108
        ((SPObjectClass *) parent_class)->release (object);
 
109
    }
129
110
}
130
111
 
131
 
static void
132
 
sp_symbol_set (SPObject *object, unsigned int key, const gchar *value)
 
112
static void sp_symbol_set(SPObject *object, unsigned int key, const gchar *value)
133
113
{
134
 
    SPItem *item;
135
 
    SPSymbol *symbol;
136
 
 
137
 
    item = SP_ITEM (object);
138
 
    symbol = SP_SYMBOL (object);
 
114
    SPSymbol *symbol = SP_SYMBOL(object);
139
115
 
140
116
    switch (key) {
141
117
    case SP_ATTR_VIEWBOX:
155
131
            while (*eptr && ((*eptr == ',') || (*eptr == ' '))) eptr++;
156
132
            if ((width > 0) && (height > 0)) {
157
133
                /* Set viewbox */
158
 
                symbol->viewBox.x0 = x;
159
 
                symbol->viewBox.y0 = y;
160
 
                symbol->viewBox.x1 = x + width;
161
 
                symbol->viewBox.y1 = y + height;
 
134
                symbol->viewBox = Geom::Rect::from_xywh(x, y, width, height);
162
135
                symbol->viewBox_set = TRUE;
163
136
            } else {
164
137
                symbol->viewBox_set = FALSE;
235
208
    }
236
209
}
237
210
 
238
 
static void
239
 
sp_symbol_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
 
211
static void sp_symbol_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
240
212
{
241
 
    SPSymbol *symbol;
242
 
    SPGroup *group;
243
 
 
244
 
    symbol = (SPSymbol *) object;
245
 
    group = (SPGroup *) object;
246
 
 
247
 
    if (((SPObjectClass *) (parent_class))->child_added)
 
213
    if (((SPObjectClass *) (parent_class))->child_added) {
248
214
        ((SPObjectClass *) (parent_class))->child_added (object, child, ref);
 
215
    }
249
216
}
250
217
 
251
 
static void
252
 
sp_symbol_update (SPObject *object, SPCtx *ctx, guint flags)
 
218
static void sp_symbol_update(SPObject *object, SPCtx *ctx, guint flags)
253
219
{
254
 
    SPItem *item;
255
 
    SPSymbol *symbol;
256
 
    SPItemCtx *ictx, rctx;
257
 
    SPItemView *v;
258
 
 
259
 
    item = SP_ITEM (object);
260
 
    symbol = SP_SYMBOL (object);
261
 
    ictx = (SPItemCtx *) ctx;
262
 
 
263
 
    if (SP_OBJECT_IS_CLONED (object)) {
 
220
    SPSymbol *symbol = SP_SYMBOL(object);
 
221
    SPItemCtx *ictx = (SPItemCtx *) ctx;
 
222
    SPItemCtx rctx;
 
223
 
 
224
    if (object->cloned) {
264
225
        /* Cloned <symbol> is actually renderable */
265
226
 
266
227
        /* fixme: We have to set up clip here too */
270
231
 
271
232
        /* Calculate child to parent transformation */
272
233
        /* Apply parent <use> translation (set up as vewport) */
273
 
        symbol->c2p = Geom::Matrix(Geom::Translate(rctx.vp.x0, rctx.vp.y0));
 
234
        symbol->c2p = Geom::Translate(rctx.viewport.min());
274
235
 
275
236
        if (symbol->viewBox_set) {
276
237
            double x, y, width, height;
278
239
            if (symbol->aspect_align == SP_ASPECT_NONE) {
279
240
                x = 0.0;
280
241
                y = 0.0;
281
 
                width = rctx.vp.x1 - rctx.vp.x0;
282
 
                height = rctx.vp.y1 - rctx.vp.y0;
 
242
                width = rctx.viewport.width();
 
243
                height = rctx.viewport.height();
283
244
            } else {
284
245
                double scalex, scaley, scale;
285
246
                /* Things are getting interesting */
286
 
                scalex = (rctx.vp.x1 - rctx.vp.x0) / (symbol->viewBox.x1 - symbol->viewBox.x0);
287
 
                scaley = (rctx.vp.y1 - rctx.vp.y0) / (symbol->viewBox.y1 - symbol->viewBox.y0);
 
247
                scalex = rctx.viewport.width() / symbol->viewBox.width();
 
248
                scaley = rctx.viewport.height() / symbol->viewBox.height();
288
249
                scale = (symbol->aspect_clip == SP_ASPECT_MEET) ? MIN (scalex, scaley) : MAX (scalex, scaley);
289
 
                width = (symbol->viewBox.x1 - symbol->viewBox.x0) * scale;
290
 
                height = (symbol->viewBox.y1 - symbol->viewBox.y0) * scale;
 
250
                width = symbol->viewBox.width() * scale;
 
251
                height = symbol->viewBox.height() * scale;
291
252
                /* Now place viewbox to requested position */
292
253
                switch (symbol->aspect_align) {
293
254
                case SP_ASPECT_XMIN_YMIN:
295
256
                    y = 0.0;
296
257
                    break;
297
258
                case SP_ASPECT_XMID_YMIN:
298
 
                    x = 0.5 * ((rctx.vp.x1 - rctx.vp.x0) - width);
 
259
                    x = 0.5 * (rctx.viewport.width() - width);
299
260
                    y = 0.0;
300
261
                    break;
301
262
                case SP_ASPECT_XMAX_YMIN:
302
 
                    x = 1.0 * ((rctx.vp.x1 - rctx.vp.x0) - width);
 
263
                    x = 1.0 * (rctx.viewport.width() - width);
303
264
                    y = 0.0;
304
265
                    break;
305
266
                case SP_ASPECT_XMIN_YMID:
306
267
                    x = 0.0;
307
 
                    y = 0.5 * ((rctx.vp.y1 - rctx.vp.y0) - height);
 
268
                    y = 0.5 * (rctx.viewport.height() - height);
308
269
                    break;
309
270
                case SP_ASPECT_XMID_YMID:
310
 
                    x = 0.5 * ((rctx.vp.x1 - rctx.vp.x0) - width);
311
 
                    y = 0.5 * ((rctx.vp.y1 - rctx.vp.y0) - height);
 
271
                    x = 0.5 * (rctx.viewport.width() - width);
 
272
                    y = 0.5 * (rctx.viewport.height() - height);
312
273
                    break;
313
274
                case SP_ASPECT_XMAX_YMID:
314
 
                    x = 1.0 * ((rctx.vp.x1 - rctx.vp.x0) - width);
315
 
                    y = 0.5 * ((rctx.vp.y1 - rctx.vp.y0) - height);
 
275
                    x = 1.0 * (rctx.viewport.width() - width);
 
276
                    y = 0.5 * (rctx.viewport.height() - height);
316
277
                    break;
317
278
                case SP_ASPECT_XMIN_YMAX:
318
279
                    x = 0.0;
319
 
                    y = 1.0 * ((rctx.vp.y1 - rctx.vp.y0) - height);
 
280
                    y = 1.0 * (rctx.viewport.height() - height);
320
281
                    break;
321
282
                case SP_ASPECT_XMID_YMAX:
322
 
                    x = 0.5 * ((rctx.vp.x1 - rctx.vp.x0) - width);
323
 
                    y = 1.0 * ((rctx.vp.y1 - rctx.vp.y0) - height);
 
283
                    x = 0.5 * (rctx.viewport.width() - width);
 
284
                    y = 1.0 * (rctx.viewport.height() - height);
324
285
                    break;
325
286
                case SP_ASPECT_XMAX_YMAX:
326
 
                    x = 1.0 * ((rctx.vp.x1 - rctx.vp.x0) - width);
327
 
                    y = 1.0 * ((rctx.vp.y1 - rctx.vp.y0) - height);
 
287
                    x = 1.0 * (rctx.viewport.width() - width);
 
288
                    y = 1.0 * (rctx.viewport.height() - height);
328
289
                    break;
329
290
                default:
330
291
                    x = 0.0;
333
294
                }
334
295
            }
335
296
            /* Compose additional transformation from scale and position */
336
 
            Geom::Matrix q;
337
 
            q[0] = width / (symbol->viewBox.x1 - symbol->viewBox.x0);
 
297
            Geom::Affine q;
 
298
            q[0] = width / symbol->viewBox.width();
338
299
            q[1] = 0.0;
339
300
            q[2] = 0.0;
340
 
            q[3] = height / (symbol->viewBox.y1 - symbol->viewBox.y0);
341
 
            q[4] = -symbol->viewBox.x0 * q[0] + x;
342
 
            q[5] = -symbol->viewBox.y0 * q[3] + y;
 
301
            q[3] = height / symbol->viewBox.height();
 
302
            q[4] = -symbol->viewBox.left() * q[0] + x;
 
303
            q[5] = -symbol->viewBox.top() * q[3] + y;
343
304
            /* Append viewbox transformation */
344
305
            symbol->c2p = q * symbol->c2p;
345
306
        }
346
307
 
347
 
        rctx.i2doc = symbol->c2p * (Geom::Matrix)rctx.i2doc;
 
308
        rctx.i2doc = symbol->c2p * (Geom::Affine)rctx.i2doc;
348
309
 
349
310
        /* If viewBox is set initialize child viewport */
350
311
        /* Otherwise <use> has set it up already */
351
312
        if (symbol->viewBox_set) {
352
 
            rctx.vp.x0 = symbol->viewBox.x0;
353
 
            rctx.vp.y0 = symbol->viewBox.y0;
354
 
            rctx.vp.x1 = symbol->viewBox.x1;
355
 
            rctx.vp.y1 = symbol->viewBox.y1;
 
313
            rctx.viewport = symbol->viewBox;
356
314
            rctx.i2vp = Geom::identity();
357
315
        }
358
316
 
359
 
        /* And invoke parent method */
360
 
        if (((SPObjectClass *) (parent_class))->update)
 
317
        // And invoke parent method
 
318
        if (((SPObjectClass *) (parent_class))->update) {
361
319
            ((SPObjectClass *) (parent_class))->update (object, (SPCtx *) &rctx, flags);
 
320
        }
362
321
 
363
 
        /* As last step set additional transform of arena group */
364
 
        for (v = item->display; v != NULL; v = v->next) {
365
 
            nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), symbol->c2p);
 
322
        // As last step set additional transform of drawing group
 
323
        for (SPItemView *v = symbol->display; v != NULL; v = v->next) {
 
324
                Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
 
325
                g->setChildTransform(symbol->c2p);
366
326
        }
367
327
    } else {
368
 
        /* No-op */
369
 
        if (((SPObjectClass *) (parent_class))->update)
 
328
        // No-op
 
329
        if (((SPObjectClass *) (parent_class))->update) {
370
330
            ((SPObjectClass *) (parent_class))->update (object, ctx, flags);
 
331
        }
371
332
    }
372
333
}
373
334
 
374
 
static void
375
 
sp_symbol_modified (SPObject *object, guint flags)
 
335
static void sp_symbol_modified(SPObject *object, guint flags)
376
336
{
377
 
    SPSymbol *symbol;
378
 
 
379
 
    symbol = SP_SYMBOL (object);
380
 
 
381
 
    if (((SPObjectClass *) (parent_class))->modified)
 
337
    SP_SYMBOL(object);
 
338
 
 
339
    if (((SPObjectClass *) (parent_class))->modified) {
382
340
        (* ((SPObjectClass *) (parent_class))->modified) (object, flags);
 
341
    }
383
342
}
384
343
 
385
 
static Inkscape::XML::Node *
386
 
sp_symbol_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
 
344
static Inkscape::XML::Node *sp_symbol_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
387
345
{
388
 
    SPSymbol *symbol;
389
 
 
390
 
    symbol = SP_SYMBOL (object);
 
346
    SP_SYMBOL(object);
391
347
 
392
348
    if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
393
349
        repr = xml_doc->createElement("svg:symbol");
394
350
    }
395
351
 
396
 
    repr->setAttribute("viewBox", object->repr->attribute("viewBox"));
397
 
    repr->setAttribute("preserveAspectRatio", object->repr->attribute("preserveAspectRatio"));
 
352
    //XML Tree being used directly here while it shouldn't be.
 
353
    repr->setAttribute("viewBox", object->getRepr()->attribute("viewBox"));
 
354
        
 
355
    //XML Tree being used directly here while it shouldn't be.
 
356
    repr->setAttribute("preserveAspectRatio", object->getRepr()->attribute("preserveAspectRatio"));
398
357
 
399
 
    if (((SPObjectClass *) (parent_class))->write)
 
358
    if (((SPObjectClass *) (parent_class))->write) {
400
359
        ((SPObjectClass *) (parent_class))->write (object, xml_doc, repr, flags);
 
360
    }
401
361
 
402
362
    return repr;
403
363
}
404
364
 
405
 
static NRArenaItem *
406
 
sp_symbol_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags)
 
365
static Inkscape::DrawingItem *sp_symbol_show(SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags)
407
366
{
408
 
    SPSymbol *symbol;
409
 
    NRArenaItem *ai;
410
 
 
411
 
    symbol = SP_SYMBOL (item);
412
 
 
413
 
    if (SP_OBJECT_IS_CLONED (symbol)) {
414
 
        /* Cloned <symbol> is actually renderable */
 
367
    SPSymbol *symbol = SP_SYMBOL(item);
 
368
    Inkscape::DrawingItem *ai = 0;
 
369
 
 
370
    if (symbol->cloned) {
 
371
        // Cloned <symbol> is actually renderable
415
372
        if (((SPItemClass *) (parent_class))->show) {
416
 
            ai = ((SPItemClass *) (parent_class))->show (item, arena, key, flags);
417
 
            if (ai) {
418
 
                nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), symbol->c2p);
 
373
            ai = ((SPItemClass *) (parent_class))->show (item, drawing, key, flags);
 
374
            Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(ai);
 
375
            if (g) {
 
376
                g->setChildTransform(symbol->c2p);
419
377
            }
420
 
        } else {
421
 
            ai = NULL;
422
378
        }
423
 
    } else {
424
 
        ai = NULL;
425
379
    }
426
380
 
427
381
    return ai;
428
382
}
429
383
 
430
 
static void
431
 
sp_symbol_hide (SPItem *item, unsigned int key)
 
384
static void sp_symbol_hide(SPItem *item, unsigned int key)
432
385
{
433
 
    SPSymbol *symbol;
434
 
 
435
 
    symbol = SP_SYMBOL (item);
436
 
 
437
 
    if (SP_OBJECT_IS_CLONED (symbol)) {
 
386
    SPSymbol *symbol = SP_SYMBOL(item);
 
387
 
 
388
    if (symbol->cloned) {
438
389
        /* Cloned <symbol> is actually renderable */
439
 
        if (((SPItemClass *) (parent_class))->hide)
 
390
        if (((SPItemClass *) (parent_class))->hide) {
440
391
            ((SPItemClass *) (parent_class))->hide (item, key);
 
392
        }
441
393
    }
442
394
}
443
395
 
444
 
static void
445
 
sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags)
 
396
static Geom::OptRect sp_symbol_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type)
446
397
{
447
398
    SPSymbol const *symbol = SP_SYMBOL(item);
 
399
    Geom::OptRect bbox;
448
400
 
449
 
    if (SP_OBJECT_IS_CLONED (symbol)) {
450
 
        /* Cloned <symbol> is actually renderable */
 
401
    if (symbol->cloned) {
 
402
        // Cloned <symbol> is actually renderable
451
403
 
452
404
        if (((SPItemClass *) (parent_class))->bbox) {
453
 
            Geom::Matrix const a( symbol->c2p * transform );
454
 
            ((SPItemClass *) (parent_class))->bbox(item, bbox, a, flags);
 
405
            Geom::Affine const a( symbol->c2p * transform );
 
406
            bbox = ((SPItemClass *) (parent_class))->bbox(item, a, type);
455
407
        }
456
408
    }
 
409
    return bbox;
457
410
}
458
411
 
459
 
static void
460
 
sp_symbol_print (SPItem *item, SPPrintContext *ctx)
 
412
static void sp_symbol_print(SPItem *item, SPPrintContext *ctx)
461
413
{
462
414
    SPSymbol *symbol = SP_SYMBOL(item);
463
 
    if (SP_OBJECT_IS_CLONED (symbol)) {
464
 
        /* Cloned <symbol> is actually renderable */
 
415
    if (symbol->cloned) {
 
416
        // Cloned <symbol> is actually renderable
465
417
 
466
 
        sp_print_bind(ctx, &symbol->c2p, 1.0);
 
418
        sp_print_bind(ctx, symbol->c2p, 1.0);
467
419
 
468
420
        if (((SPItemClass *) (parent_class))->print) {
469
421
            ((SPItemClass *) (parent_class))->print (item, ctx);