~ubuntu-branches/ubuntu/raring/librsvg/raring-proposed

« back to all changes in this revision

Viewing changes to rsvg-base.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl
  • Date: 2012-03-27 01:47:52 UTC
  • mfrom: (1.1.32) (36 experimental)
  • mto: This revision was merged to the branch mainline in revision 37.
  • Revision ID: package-import@ubuntu.com-20120327014752-c9vmipiww40cnip7
Tags: 2.36.0-1
* New upstream release.
* Update debian/copyright using the machine-readable copyright format 1.0.
* Bump Standards-Version to 3.9.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include "rsvg-shapes.h"
34
34
#include "rsvg-structure.h"
35
35
#include "rsvg-image.h"
 
36
#include "rsvg-io.h"
36
37
#include "rsvg-text.h"
37
38
#include "rsvg-filter.h"
38
39
#include "rsvg-mask.h"
43
44
#include <libxml/parser.h>
44
45
#include <libxml/parserInternals.h>
45
46
 
 
47
#include <gio/gio.h>
 
48
 
46
49
#include <math.h>
47
50
#include <string.h>
48
51
#include <stdarg.h>
49
52
 
50
 
#ifdef HAVE_GSF
51
 
#include <gsf/gsf-input-gzip.h>
52
 
#include <gsf/gsf-input-memory.h>
53
 
#include <gsf/gsf-output-memory.h>
54
 
#include <gsf/gsf-utils.h>
55
 
#endif
56
 
 
57
 
#include "rsvg-bpath-util.h"
58
53
#include "rsvg-path.h"
59
54
#include "rsvg-paint-server.h"
60
55
#include "rsvg-xml.h"
64
59
 */
65
60
#define RSVG_DEFAULT_DPI_X 90.0
66
61
#define RSVG_DEFAULT_DPI_Y 90.0
 
62
 
 
63
G_GNUC_INTERNAL
67
64
double rsvg_internal_dpi_x = RSVG_DEFAULT_DPI_X;
 
65
G_GNUC_INTERNAL
68
66
double rsvg_internal_dpi_y = RSVG_DEFAULT_DPI_Y;
69
67
 
70
68
static xmlSAXHandler rsvgSAXHandlerStruct;
80
78
    RsvgSaxHandlerDefs *parent;
81
79
    RsvgHandle *ctx;
82
80
    GString *style;
 
81
    gboolean is_text_css;
83
82
} RsvgSaxHandlerStyle;
84
83
 
 
84
typedef struct {
 
85
    RsvgSaxHandler super;
 
86
    RsvgHandle *ctx;
 
87
    const char *name;
 
88
    GString *string;
 
89
    GString **stringptr;
 
90
} RsvgSaxHandlerExtra;
 
91
 
85
92
/* hide this fact from the general public */
86
 
typedef RsvgSaxHandlerDefs RsvgSaxHandlerTitle;
87
 
typedef RsvgSaxHandlerDefs RsvgSaxHandlerDesc;
88
 
typedef RsvgSaxHandlerDefs RsvgSaxHandlerMetadata;
 
93
typedef RsvgSaxHandlerExtra RsvgSaxHandlerTitle;
 
94
typedef RsvgSaxHandlerExtra RsvgSaxHandlerDesc;
 
95
typedef RsvgSaxHandlerExtra RsvgSaxHandlerMetadata;
89
96
 
90
97
static void
91
98
rsvg_style_handler_free (RsvgSaxHandler * self)
93
100
    RsvgSaxHandlerStyle *z = (RsvgSaxHandlerStyle *) self;
94
101
    RsvgHandle *ctx = z->ctx;
95
102
 
96
 
    rsvg_parse_cssbuffer (ctx, z->style->str, z->style->len);
 
103
    if (z->is_text_css)
 
104
        rsvg_parse_cssbuffer (ctx, z->style->str, z->style->len);
97
105
 
98
106
    g_string_free (z->style, TRUE);
99
107
    g_free (z);
127
135
}
128
136
 
129
137
static void
130
 
rsvg_start_style (RsvgHandle * ctx, RsvgPropertyBag * atts)
 
138
rsvg_start_style (RsvgHandle * ctx, RsvgPropertyBag *atts)
131
139
{
132
140
    RsvgSaxHandlerStyle *handler = g_new0 (RsvgSaxHandlerStyle, 1);
 
141
    const char *type;
 
142
 
 
143
    type = rsvg_property_bag_lookup (atts, "type");
133
144
 
134
145
    handler->super.free = rsvg_style_handler_free;
135
146
    handler->super.characters = rsvg_style_handler_characters;
138
149
    handler->ctx = ctx;
139
150
 
140
151
    handler->style = g_string_new (NULL);
 
152
    handler->is_text_css = type && g_ascii_strcasecmp (type, "text/css") == 0;
141
153
 
142
154
    handler->parent = (RsvgSaxHandlerDefs *) ctx->priv->handler;
143
155
    ctx->priv->handler = &handler->super;
280
292
    }
281
293
}
282
294
 
 
295
/* extra (title, desc, metadata) */
 
296
 
 
297
static void
 
298
rsvg_extra_handler_free (RsvgSaxHandler * self)
 
299
{
 
300
    RsvgSaxHandlerExtra *z = (RsvgSaxHandlerExtra *) self;
 
301
 
 
302
    if (z->stringptr) {
 
303
        if (*z->stringptr)
 
304
            g_string_free (*z->stringptr, TRUE);
 
305
        *z->stringptr = z->string;
 
306
    } else if (z->string) {
 
307
        g_string_free (z->string, TRUE);
 
308
    }
 
309
 
 
310
    g_free (self);
 
311
}
 
312
 
 
313
static void
 
314
rsvg_extra_handler_characters (RsvgSaxHandler * self, const char *ch, int len)
 
315
{
 
316
    RsvgSaxHandlerExtra *z = (RsvgSaxHandlerExtra *) self;
 
317
    RsvgHandle *ctx = z->ctx;
 
318
 
 
319
    /* This isn't quite the correct behavior - in theory, any graphics
 
320
       element may contain a title, desc, or metadata element */
 
321
 
 
322
    if (!z->string)
 
323
        return;
 
324
 
 
325
    if (!ch || !len)
 
326
        return;
 
327
 
 
328
    if (!g_utf8_validate ((char *) ch, len, NULL)) {
 
329
        char *utf8;
 
330
        utf8 = rsvg_make_valid_utf8 ((char *) ch, len);
 
331
        g_string_append (z->string, utf8);
 
332
        g_free (utf8);
 
333
    } else {
 
334
        g_string_append_len (z->string, (char *) ch, len);
 
335
    }
 
336
}
 
337
 
 
338
static void
 
339
rsvg_extra_handler_start (RsvgSaxHandler * self, const char *name, RsvgPropertyBag * atts)
 
340
{
 
341
}
 
342
 
 
343
static void
 
344
rsvg_extra_handler_end (RsvgSaxHandler * self, const char *name)
 
345
{
 
346
    RsvgSaxHandlerExtra *z = (RsvgSaxHandlerExtra *) self;
 
347
    RsvgHandle *ctx = z->ctx;
 
348
 
 
349
    if (!strcmp (name, z->name)) {
 
350
        if (ctx->priv->handler != NULL) {
 
351
            ctx->priv->handler->free (ctx->priv->handler);
 
352
            ctx->priv->handler = NULL;
 
353
        }
 
354
    }
 
355
}
 
356
 
 
357
static RsvgSaxHandlerExtra *
 
358
rsvg_start_extra (RsvgHandle * ctx,
 
359
                  const char *name,
 
360
                  GString **stringptr)
 
361
{
 
362
    RsvgSaxHandlerExtra *handler = g_new0 (RsvgSaxHandlerExtra, 1);
 
363
    RsvgNode *treebase = ctx->priv->treebase;
 
364
    RsvgNode *currentnode = ctx->priv->currentnode;
 
365
    gboolean do_care;
 
366
 
 
367
    /* only parse <extra> for the <svg> node.
 
368
     * This isn't quite the correct behavior - any graphics
 
369
     * element may contain a <extra> element.
 
370
     */
 
371
    do_care = treebase != NULL && treebase == currentnode;
 
372
 
 
373
    handler->super.free = rsvg_extra_handler_free;
 
374
    handler->super.characters = rsvg_extra_handler_characters;
 
375
    handler->super.start_element = rsvg_extra_handler_start;
 
376
    handler->super.end_element = rsvg_extra_handler_end;
 
377
    handler->ctx = ctx;
 
378
    handler->name = name; /* interned */
 
379
    handler->string = do_care ? g_string_new (NULL) : NULL;
 
380
    handler->stringptr = do_care ? stringptr : NULL;
 
381
 
 
382
    ctx->priv->handler = &handler->super;
 
383
 
 
384
    return handler;
 
385
}
 
386
 
283
387
/* start desc */
284
388
 
285
389
static void
286
 
rsvg_desc_handler_free (RsvgSaxHandler * self)
287
 
{
288
 
    g_free (self);
289
 
}
290
 
 
291
 
static void
292
 
rsvg_desc_handler_characters (RsvgSaxHandler * self, const char *ch, int len)
293
 
{
294
 
    RsvgSaxHandlerDesc *z = (RsvgSaxHandlerDesc *) self;
295
 
    RsvgHandle *ctx = z->ctx;
296
 
 
297
 
    /* This isn't quite the correct behavior - in theory, any graphics
298
 
       element may contain a title or desc element */
299
 
 
300
 
    if (!ch || !len)
301
 
        return;
302
 
 
303
 
    if (!g_utf8_validate ((char *) ch, len, NULL)) {
304
 
        char *utf8;
305
 
        utf8 = rsvg_make_valid_utf8 ((char *) ch, len);
306
 
        g_string_append (ctx->priv->desc, utf8);
307
 
        g_free (utf8);
308
 
    } else {
309
 
        g_string_append_len (ctx->priv->desc, (char *) ch, len);
310
 
    }
311
 
}
312
 
 
313
 
static void
314
 
rsvg_desc_handler_start (RsvgSaxHandler * self, const char *name, RsvgPropertyBag * atts)
315
 
{
316
 
}
317
 
 
318
 
static void
319
 
rsvg_desc_handler_end (RsvgSaxHandler * self, const char *name)
320
 
{
321
 
    RsvgSaxHandlerDesc *z = (RsvgSaxHandlerDesc *) self;
322
 
    RsvgHandle *ctx = z->ctx;
323
 
 
324
 
    if (!strcmp (name, "desc")) {
325
 
        if (ctx->priv->handler != NULL) {
326
 
            ctx->priv->handler->free (ctx->priv->handler);
327
 
            ctx->priv->handler = NULL;
328
 
        }
329
 
    }
330
 
}
331
 
 
332
 
static void
333
 
rsvg_start_desc (RsvgHandle * ctx, RsvgPropertyBag * atts)
334
 
{
335
 
    RsvgSaxHandlerDesc *handler = g_new0 (RsvgSaxHandlerDesc, 1);
336
 
 
337
 
    handler->super.free = rsvg_desc_handler_free;
338
 
    handler->super.characters = rsvg_desc_handler_characters;
339
 
    handler->super.start_element = rsvg_desc_handler_start;
340
 
    handler->super.end_element = rsvg_desc_handler_end;
341
 
    handler->ctx = ctx;
342
 
 
343
 
    ctx->priv->desc = g_string_new (NULL);
344
 
    ctx->priv->handler = &handler->super;
 
390
rsvg_start_desc (RsvgHandle * ctx)
 
391
{
 
392
    rsvg_start_extra (ctx, "desc", &ctx->priv->desc);
345
393
}
346
394
 
347
395
/* end desc */
349
397
/* start title */
350
398
 
351
399
static void
352
 
rsvg_title_handler_free (RsvgSaxHandler * self)
353
 
{
354
 
    g_free (self);
355
 
}
356
 
 
357
 
static void
358
 
rsvg_title_handler_characters (RsvgSaxHandler * self, const char *ch, int len)
359
 
{
360
 
    RsvgSaxHandlerTitle *z = (RsvgSaxHandlerTitle *) self;
361
 
    RsvgHandle *ctx = z->ctx;
362
 
 
363
 
    /* This isn't quite the correct behavior - in theory, any graphics
364
 
       element may contain a title or desc element */
365
 
 
366
 
    if (!ch || !len)
367
 
        return;
368
 
 
369
 
    if (!g_utf8_validate ((char *) ch, len, NULL)) {
370
 
        char *utf8;
371
 
        utf8 = rsvg_make_valid_utf8 ((char *) ch, len);
372
 
        g_string_append (ctx->priv->title, utf8);
373
 
        g_free (utf8);
374
 
    } else {
375
 
        g_string_append_len (ctx->priv->title, (char *) ch, len);
376
 
    }
377
 
}
378
 
 
379
 
static void
380
 
rsvg_title_handler_start (RsvgSaxHandler * self, const char *name, RsvgPropertyBag * atts)
381
 
{
382
 
}
383
 
 
384
 
static void
385
 
rsvg_title_handler_end (RsvgSaxHandler * self, const char *name)
386
 
{
387
 
    RsvgSaxHandlerTitle *z = (RsvgSaxHandlerTitle *) self;
388
 
    RsvgHandle *ctx = z->ctx;
389
 
 
390
 
    if (!strcmp (name, "title")) {
391
 
        if (ctx->priv->handler != NULL) {
392
 
            ctx->priv->handler->free (ctx->priv->handler);
393
 
            ctx->priv->handler = NULL;
394
 
        }
395
 
    }
396
 
}
397
 
 
398
 
static void
399
 
rsvg_start_title (RsvgHandle * ctx, RsvgPropertyBag * atts)
400
 
{
401
 
    RsvgSaxHandlerTitle *handler = g_new0 (RsvgSaxHandlerTitle, 1);
402
 
 
403
 
    handler->super.free = rsvg_title_handler_free;
404
 
    handler->super.characters = rsvg_title_handler_characters;
405
 
    handler->super.start_element = rsvg_title_handler_start;
406
 
    handler->super.end_element = rsvg_title_handler_end;
407
 
    handler->ctx = ctx;
408
 
 
409
 
    ctx->priv->title = g_string_new (NULL);
410
 
    ctx->priv->handler = &handler->super;
 
400
rsvg_start_title (RsvgHandle * ctx)
 
401
{
 
402
    rsvg_start_extra (ctx, "title", &ctx->priv->title);
411
403
}
412
404
 
413
405
/* end title */
415
407
/* start metadata */
416
408
 
417
409
static void
418
 
rsvg_metadata_handler_free (RsvgSaxHandler * self)
419
 
{
420
 
    g_free (self);
421
 
}
422
 
 
423
 
static void
424
 
rsvg_metadata_handler_characters (RsvgSaxHandler * self, const char *ch, int len)
425
 
{
426
 
    RsvgSaxHandlerDesc *z = (RsvgSaxHandlerDesc *) self;
427
 
    RsvgHandle *ctx = z->ctx;
428
 
 
429
 
    /* This isn't quite the correct behavior - in theory, any graphics
430
 
       element may contain a metadata or desc element */
431
 
 
432
 
    if (!ch || !len)
433
 
        return;
434
 
 
435
 
    if (!g_utf8_validate ((char *) ch, len, NULL)) {
436
 
        char *utf8;
437
 
        utf8 = rsvg_make_valid_utf8 ((char *) ch, len);
438
 
        g_string_append (ctx->priv->metadata, utf8);
439
 
        g_free (utf8);
440
 
    } else {
441
 
        g_string_append_len (ctx->priv->metadata, (char *) ch, len);
442
 
    }
443
 
}
444
 
 
445
 
static void
446
410
rsvg_metadata_props_enumerate (const char *key, const char *value, gpointer user_data)
447
411
{
448
412
    GString *metadata = (GString *) user_data;
455
419
    RsvgSaxHandlerMetadata *z = (RsvgSaxHandlerMetadata *) self;
456
420
    RsvgHandle *ctx = z->ctx;
457
421
 
458
 
    g_string_append_printf (ctx->priv->metadata, "<%s ", name);
459
 
    rsvg_property_bag_enumerate (atts, rsvg_metadata_props_enumerate, ctx->priv->metadata);
460
 
    g_string_append (ctx->priv->metadata, ">\n");
 
422
    rsvg_extra_handler_start (self, name, atts);
 
423
 
 
424
    if (!z->string)
 
425
        return;
 
426
 
 
427
    g_string_append_printf (z->string, "<%s ", name);
 
428
    rsvg_property_bag_enumerate (atts, rsvg_metadata_props_enumerate, z->string);
 
429
    g_string_append (z->string, ">\n");
461
430
}
462
431
 
463
432
static void
466
435
    RsvgSaxHandlerMetadata *z = (RsvgSaxHandlerMetadata *) self;
467
436
    RsvgHandle *ctx = z->ctx;
468
437
 
469
 
    if (!strcmp (name, "metadata")) {
470
 
        if (ctx->priv->handler != NULL) {
471
 
            ctx->priv->handler->free (ctx->priv->handler);
472
 
            ctx->priv->handler = NULL;
473
 
        }
474
 
    } else
475
 
        g_string_append_printf (ctx->priv->metadata, "</%s>\n", name);
 
438
    if (strcmp (name, z->name) != 0) {
 
439
        if (z->string)
 
440
            g_string_append_printf (z->string, "</%s>\n", name);
 
441
    } else {
 
442
        rsvg_extra_handler_end (self, name);
 
443
    }
476
444
}
477
445
 
478
446
static void
479
 
rsvg_start_metadata (RsvgHandle * ctx, RsvgPropertyBag * atts)
 
447
rsvg_start_metadata (RsvgHandle * ctx)
480
448
{
481
 
    RsvgSaxHandlerMetadata *handler = g_new0 (RsvgSaxHandlerMetadata, 1);
 
449
    RsvgSaxHandlerMetadata *handler = rsvg_start_extra (ctx, "metadata", &ctx->priv->metadata);
482
450
 
483
 
    handler->super.free = rsvg_metadata_handler_free;
484
 
    handler->super.characters = rsvg_metadata_handler_characters;
485
451
    handler->super.start_element = rsvg_metadata_handler_start;
486
452
    handler->super.end_element = rsvg_metadata_handler_end;
487
 
    handler->ctx = ctx;
488
 
 
489
 
    ctx->priv->metadata = g_string_new (NULL);
490
 
    ctx->priv->handler = &handler->super;
491
453
}
492
454
 
493
455
/* end metadata */
566
528
rsvg_start_xinclude (RsvgHandle * ctx, RsvgPropertyBag * atts)
567
529
{
568
530
    RsvgSaxHandlerXinclude *handler;
569
 
    GByteArray *data;
570
 
    const char *href;
 
531
    const char *href, *parse;
571
532
    gboolean success = FALSE;
572
533
 
573
534
    href = rsvg_property_bag_lookup (atts, "href");
574
 
    if (href) {
575
 
        data = _rsvg_acquire_xlink_href_resource (href, rsvg_handle_get_base_uri (ctx), NULL);
576
 
        if (data) {
577
 
            const char *parse;
578
 
 
579
 
            parse = rsvg_property_bag_lookup (atts, "parse");
580
 
            if (parse && !strcmp (parse, "text")) {
581
 
                const char *encoding;
582
 
                char *text_data;
583
 
                gsize text_data_len;
584
 
                gboolean text_data_needs_free = FALSE;
585
 
 
586
 
                encoding = rsvg_property_bag_lookup (atts, "encoding");
587
 
                if (encoding) {
588
 
                    text_data =
589
 
                        g_convert ((const char *) data->data, data->len, "utf-8", encoding, NULL,
 
535
    if (href == NULL)
 
536
        goto fallback;
 
537
 
 
538
    parse = rsvg_property_bag_lookup (atts, "parse");
 
539
    if (parse && !strcmp (parse, "text")) {
 
540
        guint8 *data;
 
541
        gsize data_len;
 
542
        const char *encoding;
 
543
 
 
544
        data = _rsvg_handle_acquire_data (ctx, href, NULL, &data_len, NULL);
 
545
        if (data == NULL)
 
546
            goto fallback;
 
547
 
 
548
        encoding = rsvg_property_bag_lookup (atts, "encoding");
 
549
        if (encoding && g_ascii_strcasecmp (encoding, "UTF-8") != 0) {
 
550
            char *text_data;
 
551
            gsize text_data_len;
 
552
 
 
553
            text_data = g_convert (data, data_len, "utf-8", encoding, NULL,
590
554
                                   &text_data_len, NULL);
591
 
                    text_data_needs_free = TRUE;
592
 
                } else {
593
 
                    text_data = (char *) data->data;
594
 
                    text_data_len = data->len;
595
 
                }
596
 
 
597
 
                rsvg_characters_impl (ctx, (const xmlChar *) text_data, text_data_len);
598
 
 
599
 
                if (text_data_needs_free)
600
 
                    g_free (text_data);
601
 
            } else {
602
 
                /* xml */
603
 
                xmlDocPtr xml_doc;
604
 
                xmlParserCtxtPtr xml_parser;
605
 
                int result;
606
 
 
607
 
                xml_parser = xmlCreatePushParserCtxt (&rsvgSAXHandlerStruct, ctx, NULL, 0, NULL);
608
 
                result = xmlParseChunk (xml_parser, (char *) data->data, data->len, 0);
609
 
                result = xmlParseChunk (xml_parser, "", 0, TRUE);
610
 
 
611
 
                xml_doc = xml_parser->myDoc;
612
 
                xmlFreeParserCtxt (xml_parser);
613
 
                xmlFreeDoc (xml_doc);
614
 
            }
615
 
 
616
 
            g_byte_array_free (data, TRUE);
617
 
            success = TRUE;
618
 
        }
 
555
            g_free (data);
 
556
 
 
557
            data = text_data;
 
558
            data_len = text_data_len;
 
559
        }
 
560
 
 
561
        rsvg_characters_impl (ctx, (const xmlChar *) data, data_len);
 
562
 
 
563
        g_free (data);
 
564
    } else {
 
565
        /* xml */
 
566
        GInputStream *stream;
 
567
        GError *err = NULL;
 
568
        xmlDocPtr xml_doc;
 
569
        xmlParserCtxtPtr xml_parser;
 
570
        xmlParserInputBufferPtr buffer;
 
571
        xmlParserInputPtr input;
 
572
        int result;
 
573
 
 
574
        stream = _rsvg_handle_acquire_stream (ctx, href, NULL, NULL);
 
575
        if (stream == NULL)
 
576
            goto fallback;
 
577
 
 
578
        xml_parser = xmlCreatePushParserCtxt (&rsvgSAXHandlerStruct, ctx, NULL, 0, NULL);
 
579
 
 
580
        buffer = _rsvg_xml_input_buffer_new_from_stream (stream, NULL /* cancellable */, XML_CHAR_ENCODING_NONE, &err);
 
581
        g_object_unref (stream);
 
582
 
 
583
        input = xmlNewIOInputStream (xml_parser, buffer /* adopts */, XML_CHAR_ENCODING_NONE);
 
584
 
 
585
        if (xmlPushInput (xml_parser, input) < 0) {
 
586
            g_clear_error (&err);
 
587
            xmlFreeInputStream (input);
 
588
            xmlFreeParserCtxt (xml_parser);
 
589
            goto fallback;
 
590
        }
 
591
 
 
592
        (void) xmlParseDocument (xml_parser);
 
593
 
 
594
        xml_doc = xml_parser->myDoc;
 
595
        xmlFreeParserCtxt (xml_parser);
 
596
        if (xml_doc)
 
597
            xmlFreeDoc (xml_doc);
 
598
 
 
599
        g_clear_error (&err);
619
600
    }
620
601
 
 
602
    success = TRUE;
 
603
 
 
604
  fallback:
 
605
 
621
606
    /* needed to handle xi:fallback */
622
607
    handler = g_new0 (RsvgSaxHandlerXinclude, 1);
623
608
 
655
640
        if (!strcmp ((const char *) name, "style"))
656
641
            rsvg_start_style (ctx, bag);
657
642
        else if (!strcmp ((const char *) name, "title"))
658
 
            rsvg_start_title (ctx, bag);
 
643
            rsvg_start_title (ctx);
659
644
        else if (!strcmp ((const char *) name, "desc"))
660
 
            rsvg_start_desc (ctx, bag);
 
645
            rsvg_start_desc (ctx);
661
646
        else if (!strcmp ((const char *) name, "metadata"))
662
 
            rsvg_start_metadata (ctx, bag);
 
647
            rsvg_start_metadata (ctx);
663
648
        else if (!strcmp ((const char *) name, "include"))      /* xi:include */
664
649
            rsvg_start_xinclude (ctx, bag);
665
650
        else
753
738
                if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CHARS) {
754
739
                    self = (RsvgNodeChars*)node;
755
740
                }
 
741
                else if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_TSPAN) {
 
742
                    self = NULL;
 
743
                }
756
744
            }
757
745
 
758
746
            if (self != NULL) {
790
778
    rsvg_characters_impl (ctx, ch, len);
791
779
}
792
780
 
793
 
#if LIBXML_VERSION >= 20621
794
 
#define RSVG_ENABLE_ENTITIES
795
 
#elif defined(__GNUC__)
796
 
#warning "libxml version less than 2.6.22. XML entities won't work"
797
 
#endif
798
 
 
799
 
#ifdef RSVG_ENABLE_ENTITIES
800
 
 
801
781
static xmlEntityPtr
802
782
rsvg_get_entity (void *data, const xmlChar * name)
803
783
{
816
796
    RsvgHandle *ctx = (RsvgHandle *) data;
817
797
    GHashTable *entities = ctx->priv->entities;
818
798
    xmlEntityPtr entity;
819
 
#if LIBXML_VERSION >= 20700
820
799
    xmlChar *resolvedSystemId = NULL, *resolvedPublicId = NULL;
821
800
 
822
801
    if (systemId)
825
804
        resolvedPublicId = xmlBuildRelativeURI (publicId, (xmlChar*) rsvg_handle_get_base_uri (ctx));
826
805
 
827
806
    if (type == XML_EXTERNAL_PARAMETER_ENTITY && !content) {
828
 
      GByteArray *arr = NULL;
829
 
 
830
 
      if (systemId)
831
 
        arr = _rsvg_acquire_xlink_href_resource ((const char *) systemId,
832
 
                                                 rsvg_handle_get_base_uri (ctx), NULL);
833
 
      else if (publicId)
834
 
        arr = _rsvg_acquire_xlink_href_resource ((const char *) publicId,
835
 
                                                 rsvg_handle_get_base_uri (ctx), NULL);
836
 
      if (arr) {
837
 
        content = xmlCharStrndup ((const char*)arr->data, arr->len);
838
 
        g_byte_array_free(arr, TRUE);
839
 
      }
 
807
        guint8 *entity_data;
 
808
        gsize entity_data_len;
 
809
 
 
810
        if (systemId)
 
811
            entity_data = _rsvg_handle_acquire_data (ctx,
 
812
                                                     (const char *) systemId,
 
813
                                                     NULL,
 
814
                                                     &entity_data_len,
 
815
                                                     NULL);
 
816
        else if (publicId)
 
817
            entity_data = _rsvg_handle_acquire_data (ctx,
 
818
                                                     (const char *) publicId,
 
819
                                                     NULL,
 
820
                                                     &entity_data_len,
 
821
                                                     NULL);
 
822
        else
 
823
            entity_data = NULL;
 
824
 
 
825
        if (entity_data) {
 
826
            content = xmlCharStrndup (entity_data, entity_data_len);
 
827
            g_free (entity_data);
 
828
        }
840
829
    }
841
 
      
 
830
 
842
831
    entity = xmlNewEntity(NULL, name, type, resolvedPublicId, resolvedSystemId, content);
843
832
 
844
833
    xmlFree(resolvedPublicId);
845
834
    xmlFree(resolvedSystemId);
846
835
 
847
836
    g_hash_table_insert (entities, g_strdup ((const char*) name), entity);
848
 
#else
849
 
    xmlChar *dupname;
850
 
 
851
 
    entity = xmlMalloc (sizeof (xmlEntity));
852
 
    memset (entity, 0, sizeof (xmlEntity));
853
 
    entity->type = XML_ENTITY_DECL;
854
 
    dupname = (xmlChar *) xmlMemStrdup ((const char *) name);
855
 
    entity->name = dupname;
856
 
 
857
 
    entity->etype = type;
858
 
    if (content) {
859
 
        entity->content = (xmlChar *) xmlMemStrdup ((const char *) content);
860
 
        entity->length = strlen ((const char *) content);
861
 
    } else if (systemId || publicId) {
862
 
        GByteArray *data = NULL;
863
 
 
864
 
        if (systemId)
865
 
            data =
866
 
                _rsvg_acquire_xlink_href_resource ((const char *) systemId,
867
 
                                                   rsvg_handle_get_base_uri (ctx), NULL);
868
 
        else if (publicId)
869
 
            data =
870
 
                _rsvg_acquire_xlink_href_resource ((const char *) publicId,
871
 
                                                   rsvg_handle_get_base_uri (ctx), NULL);
872
 
 
873
 
        if (data) {
874
 
            entity->SystemID = (xmlChar *) xmlMemStrdup ((const char *) systemId);
875
 
            entity->ExternalID = (xmlChar *) xmlMemStrdup ((const char *) publicId);
876
 
            entity->content = (xmlChar *) xmlMemStrdup ((const char *) data->data);
877
 
            entity->length = data->len;
878
 
 
879
 
            /* fool libxml2 into supporting SYSTEM and PUBLIC entities */
880
 
            entity->etype = XML_INTERNAL_GENERAL_ENTITY;
881
 
 
882
 
            g_byte_array_free (data, TRUE);
883
 
        }
884
 
    }
885
 
 
886
 
    g_hash_table_insert (entities, dupname, entity);
887
 
#endif
888
837
}
889
838
 
890
839
static void
907
856
    return entity;
908
857
}
909
858
 
910
 
#endif
911
 
 
912
859
static void
913
860
rsvg_error_cb (void *data, const char *msg, ...)
914
861
{
932
879
        char **xml_atts;
933
880
 
934
881
        xml_atts = rsvg_css_parse_xml_attribute_string ((const char *) data);
935
 
        atts = rsvg_property_bag_new ((const char **) xml_atts);
936
882
 
937
 
        if (atts) {
 
883
        if (xml_atts) {
938
884
            const char *value;
939
885
 
 
886
            atts = rsvg_property_bag_new ((const char **) xml_atts);
940
887
            value = rsvg_property_bag_lookup (atts, "alternate");
941
 
            if (!value || (strcmp (value, "no") != 0)) {
 
888
            if (!value || !value[0] || (strcmp (value, "no") != 0)) {
942
889
                value = rsvg_property_bag_lookup (atts, "type");
943
890
                if (value && strcmp (value, "text/css") == 0) {
944
891
                    value = rsvg_property_bag_lookup (atts, "href");
945
 
                    if (value) {
946
 
                        GByteArray *style;
 
892
                    if (value && value[0]) {
 
893
                        guint8 *style_data;
 
894
                        gsize style_data_len;
 
895
                        char *mime_type = NULL;
947
896
 
948
 
                        style =
949
 
                            _rsvg_acquire_xlink_href_resource (value,
950
 
                                                               rsvg_handle_get_base_uri (handle),
951
 
                                                               NULL);
952
 
                        if (style) {
953
 
                            rsvg_parse_cssbuffer (handle, (char *) style->data, style->len);
954
 
                            g_byte_array_free (style, TRUE);
 
897
                        style_data = _rsvg_handle_acquire_data (handle,
 
898
                                                                value,
 
899
                                                                &mime_type,
 
900
                                                                &style_data_len,
 
901
                                                                NULL);
 
902
                        if (style_data && 
 
903
                            mime_type &&
 
904
                            strcmp (mime_type, "text/css") == 0) {
 
905
                            rsvg_parse_cssbuffer (handle, (char *) style_data, style_data_len);
955
906
                        }
 
907
 
 
908
                        g_free (mime_type);
 
909
                        g_free (style_data);
956
910
                    }
957
911
                }
958
912
            }
959
913
 
 
914
            rsvg_property_bag_free (atts);
960
915
            g_strfreev (xml_atts);
961
 
            rsvg_property_bag_free (atts);
962
916
        }
963
917
    }
964
918
}
971
925
 
972
926
        memset (&rsvgSAXHandlerStruct, 0, sizeof (rsvgSAXHandlerStruct));
973
927
 
974
 
#ifdef RSVG_ENABLE_ENTITIES
975
928
        rsvgSAXHandlerStruct.getEntity = rsvg_get_entity;
976
929
        rsvgSAXHandlerStruct.entityDecl = rsvg_entity_decl;
977
930
        rsvgSAXHandlerStruct.unparsedEntityDecl = rsvg_unparsed_entity_decl;
978
931
        rsvgSAXHandlerStruct.getParameterEntity = rsvg_get_parameter_entity;
979
 
#endif
980
932
        rsvgSAXHandlerStruct.characters = rsvg_characters;
981
933
        rsvgSAXHandlerStruct.error = rsvg_error_cb;
982
934
        rsvgSAXHandlerStruct.cdataBlock = rsvg_characters;
1068
1020
        if (handle->priv->base_uri)
1069
1021
            g_free (handle->priv->base_uri);
1070
1022
        handle->priv->base_uri = uri;
1071
 
        rsvg_defs_set_base_uri (handle->priv->defs, handle->priv->base_uri);
1072
1023
    }
1073
1024
}
1074
1025
 
1098
1049
    if (priv->base_gfile)
1099
1050
        g_object_unref (priv->base_gfile);
1100
1051
    priv->base_gfile = base_file;
1101
 
    
 
1052
 
1102
1053
    g_free (priv->base_uri);
1103
1054
    priv->base_uri = g_file_get_uri (base_file);
1104
 
 
1105
 
    rsvg_defs_set_base_uri (priv->defs, priv->base_uri);
1106
1055
}
1107
1056
 
1108
1057
/**
1259
1208
 * Returns: The SVG's title
1260
1209
 *
1261
1210
 * Since: 2.9
 
1211
 *
 
1212
 * Deprecated: 2.36
1262
1213
 */
1263
1214
const char *
1264
1215
rsvg_handle_get_metadata (RsvgHandle * handle)
1281
1232
 * Returns: The SVG's title
1282
1233
 *
1283
1234
 * Since: 2.4
 
1235
 *
 
1236
 * Deprecated: 2.36
1284
1237
 */
1285
1238
const char *
1286
1239
rsvg_handle_get_title (RsvgHandle * handle)
1303
1256
 * Returns: The SVG's description
1304
1257
 *
1305
1258
 * Since: 2.4
 
1259
 *
 
1260
 * Deprecated: 2.36
1306
1261
 */
1307
1262
const char *
1308
1263
rsvg_handle_get_desc (RsvgHandle * handle)
1359
1314
    cairo_t *cr;
1360
1315
    cairo_surface_t *target;
1361
1316
    RsvgDrawingCtx *draw;
1362
 
    RsvgCairoRender *render;
1363
1317
    RsvgNodeSvg *root = NULL;
1364
1318
    RsvgNode *sself = NULL;
1365
1319
    RsvgBbox bbox;
1388
1342
    if (!root)
1389
1343
        return FALSE;
1390
1344
 
1391
 
    bbox.x = bbox.y = 0;
1392
 
    bbox.w = bbox.h = 1;
 
1345
    bbox.rect.x = bbox.rect.y = 0;
 
1346
    bbox.rect.width = bbox.rect.height = 1;
1393
1347
 
1394
1348
    if (!id && (root->w.factor == 'p' || root->h.factor == 'p')
1395
1349
            && !root->vbox.active)
1420
1374
        cairo_save (cr);
1421
1375
 
1422
1376
        rsvg_node_draw ((RsvgNode *) handle->priv->treebase, draw, 0);
1423
 
        render = (RsvgCairoRender *) draw->render;
1424
 
 
1425
 
        bbox.x = render->bbox.x;
1426
 
        bbox.y = render->bbox.y;
1427
 
        bbox.w = render->bbox.w;
1428
 
        bbox.h = render->bbox.h;
 
1377
        bbox = RSVG_CAIRO_RENDER (draw->render)->bbox;
1429
1378
 
1430
1379
        cairo_restore (cr);
1431
1380
        rsvg_state_pop (draw);
1433
1382
        cairo_destroy (cr);
1434
1383
        cairo_surface_destroy (target);
1435
1384
 
1436
 
        dimension_data->width = bbox.w;
1437
 
        dimension_data->height = bbox.h;
 
1385
        dimension_data->width = bbox.rect.width;
 
1386
        dimension_data->height = bbox.rect.height;
1438
1387
    } else {
1439
 
        bbox.w = root->vbox.w;
1440
 
        bbox.h = root->vbox.h;
 
1388
        bbox.rect.width = root->vbox.rect.width;
 
1389
        bbox.rect.height = root->vbox.rect.height;
1441
1390
 
1442
1391
        dimension_data->width = (int) (_rsvg_css_hand_normalize_length (&root->w, handle->priv->dpi_x,
1443
 
                                       bbox.w + bbox.x * 2, 12) + 0.5);
 
1392
                                       bbox.rect.width + bbox.rect.x * 2, 12) + 0.5);
1444
1393
        dimension_data->height = (int) (_rsvg_css_hand_normalize_length (&root->h, handle->priv->dpi_y,
1445
 
                                         bbox.h + bbox.y * 2,
 
1394
                                         bbox.rect.height + bbox.rect.y * 2,
1446
1395
                                         12) + 0.5);
1447
1396
    }
1448
1397
    
1523
1472
    cairo_save (cr);
1524
1473
 
1525
1474
    rsvg_node_draw ((RsvgNode *) handle->priv->treebase, draw, 0);
1526
 
    bbox.x = ((RsvgCairoRender *) draw->render)->bbox.x;
1527
 
    bbox.y = ((RsvgCairoRender *) draw->render)->bbox.y;
1528
 
    bbox.w = ((RsvgCairoRender *) draw->render)->bbox.w;
1529
 
    bbox.h = ((RsvgCairoRender *) draw->render)->bbox.h;
 
1475
    bbox = RSVG_CAIRO_RENDER (draw->render)->bbox;
1530
1476
 
1531
1477
    cairo_restore (cr);
1532
1478
    rsvg_state_pop (draw);
1533
1479
    rsvg_drawing_ctx_free (draw);
1534
1480
 
1535
 
    position_data->x = bbox.x;
1536
 
    position_data->y = bbox.y;
1537
 
    dimension_data.width = bbox.w;
1538
 
    dimension_data.height = bbox.h;
 
1481
    position_data->x = bbox.rect.x;
 
1482
    position_data->y = bbox.rect.y;
 
1483
    dimension_data.width = bbox.rect.width;
 
1484
    dimension_data.height = bbox.rect.height;
1539
1485
 
1540
1486
    dimension_data.em = dimension_data.width;
1541
1487
    dimension_data.ex = dimension_data.height;
1725
1671
        /* test for GZ marker. todo: store the first 2 bytes in the odd circumstance that someone calls
1726
1672
         * write() in 1 byte increments */
1727
1673
        if ((count >= 2) && (buf[0] == (guchar) 0x1f) && (buf[1] == (guchar) 0x8b)) {
1728
 
#if GLIB_CHECK_VERSION (2, 24, 0)
1729
1674
            priv->data_input_stream = g_memory_input_stream_new ();
1730
 
#elif defined (HAVE_GSF)
1731
 
            priv->gzipped_data = GSF_OUTPUT (gsf_output_memory_new ());
1732
 
#else
1733
 
            g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1734
 
                                 "GZip compressed SVG not supported");
1735
 
            return FALSE;
1736
 
#endif
1737
1675
        }
1738
1676
    }
1739
1677
 
1740
 
#if GLIB_CHECK_VERSION (2, 24, 0)
1741
1678
    if (priv->data_input_stream) {
1742
1679
        g_memory_input_stream_add_data ((GMemoryInputStream *) priv->data_input_stream,
1743
1680
                                        g_memdup (buf, count), count, (GDestroyNotify) g_free);
1744
1681
        return TRUE;
1745
1682
    }
1746
 
#elif defined (HAVE_GSF)
1747
 
    if (priv->gzipped_data)
1748
 
        return gsf_output_write (handle->priv->gzipped_data, count, buf);
1749
 
#endif
1750
1683
 
1751
1684
    return rsvg_handle_write_impl (handle, buf, count, error);
1752
1685
}
1773
1706
    if (priv->is_closed)
1774
1707
          return TRUE;
1775
1708
 
1776
 
#if GLIB_CHECK_VERSION (2, 24, 0)
1777
1709
    if (priv->data_input_stream) {
1778
1710
        GConverter *converter;
1779
1711
        GInputStream *stream;
1790
1722
 
1791
1723
        return ret;
1792
1724
    }
1793
 
#elif defined(HAVE_GSF)
1794
 
    if (priv->gzipped_data) {
1795
 
        GsfInput *gzip;
1796
 
        const guchar *bytes;
1797
 
        gsize size;
1798
 
        gsize remaining;
1799
 
 
1800
 
        bytes = gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (priv->gzipped_data));
1801
 
        size = gsf_output_size (priv->gzipped_data);
1802
 
 
1803
 
        gzip =
1804
 
            GSF_INPUT (gsf_input_gzip_new
1805
 
                       (GSF_INPUT (gsf_input_memory_new (bytes, size, FALSE)), error));
1806
 
        remaining = gsf_input_remaining (gzip);
1807
 
        while ((size = MIN (remaining, 1024)) > 0) {
1808
 
            guint8 const *buf;
1809
 
 
1810
 
            /* write to parent */
1811
 
            buf = gsf_input_read (gzip, size, NULL);
1812
 
            if (!buf) {
1813
 
                /* an error occured, so bail */
1814
 
                g_warning (_("rsvg_gz_handle_close_impl: gsf_input_read returned NULL"));
1815
 
                break;
1816
 
            }
1817
 
 
1818
 
            rsvg_handle_write_impl (handle, buf, size, error);
1819
 
            /* if we didn't manage to lower remaining number of bytes,
1820
 
             * something is wrong, and we should avoid an endless loop */
1821
 
            if (remaining == ((gsize) gsf_input_remaining (gzip))) {
1822
 
                g_warning (_
1823
 
                           ("rsvg_gz_handle_close_impl: write_impl didn't lower the input_remaining count"));
1824
 
                break;
1825
 
            }
1826
 
            remaining = gsf_input_remaining (gzip);
1827
 
        }
1828
 
        g_object_unref (gzip);
1829
 
 
1830
 
        /* close parent */
1831
 
        gsf_output_close (priv->gzipped_data);
1832
 
        g_object_unref (priv->gzipped_data);
1833
 
        priv->gzipped_data = NULL;
1834
 
    }
1835
 
#endif /* GIO >= 2.24.0 */
1836
1725
 
1837
1726
    return rsvg_handle_close_impl (handle, error);
1838
1727
}
1868
1757
    int result;
1869
1758
    xmlDocPtr doc;
1870
1759
    GError *err = NULL;
 
1760
    gboolean res = FALSE;
1871
1761
 
1872
1762
    g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
1873
1763
    g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
1877
1767
    priv = handle->priv;
1878
1768
 
1879
1769
    priv->error = &err;
 
1770
    priv->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1880
1771
    if (priv->ctxt == NULL) {
1881
1772
        priv->ctxt = xmlCreatePushParserCtxt (&rsvgSAXHandlerStruct, handle, NULL, 0,
1882
1773
                                              rsvg_handle_get_base_uri (handle));
1890
1781
 
1891
1782
    buffer = _rsvg_xml_input_buffer_new_from_stream (stream, cancellable, XML_CHAR_ENCODING_NONE, &err);
1892
1783
    input = xmlNewIOInputStream (priv->ctxt, buffer, XML_CHAR_ENCODING_NONE);
1893
 
#if LIBXML_VERSION >= 20700
 
1784
 
1894
1785
    if (xmlPushInput (priv->ctxt, input) < 0) {
1895
1786
        rsvg_set_error (error, priv->ctxt);
1896
1787
        xmlFreeInputStream (input);
1897
 
        return FALSE;
 
1788
        goto out;
1898
1789
    }
1899
 
#else
1900
 
    xmlPushInput (priv->ctxt, input);
1901
 
#endif
1902
1790
 
1903
1791
    result = xmlParseDocument (priv->ctxt);
1904
1792
    if (result != 0) {
1907
1795
        else
1908
1796
            rsvg_set_error (error, handle->priv->ctxt);
1909
1797
 
1910
 
        return FALSE;
 
1798
        goto out;
1911
1799
    }
1912
1800
 
1913
 
    priv->error = NULL;
1914
 
 
1915
1801
    if (err != NULL) {
1916
1802
        g_propagate_error (error, err);
1917
 
        return FALSE;
 
1803
        goto out;
1918
1804
    }
1919
1805
 
1920
1806
    doc = priv->ctxt->myDoc;
1926
1812
    rsvg_defs_resolve_all (priv->defs);
1927
1813
    priv->finished = TRUE;
1928
1814
 
1929
 
    return TRUE;
 
1815
    res = TRUE;
 
1816
 
 
1817
  out:
 
1818
 
 
1819
    priv->error = NULL;
 
1820
    g_clear_object (&priv->cancellable);
 
1821
 
 
1822
    return res;
1930
1823
}
1931
1824
 
1932
1825
/**
2004
1897
    g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2005
1898
    g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2006
1899
 
2007
 
    handle = rsvg_handle_new ();
 
1900
    handle = rsvg_handle_new_with_flags (flags);
2008
1901
 
2009
1902
    if (base_file)
2010
1903
        rsvg_handle_set_base_gfile (handle, base_file);
2022
1915
 *
2023
1916
 * Initializes librsvg
2024
1917
 * Since: 2.9
 
1918
 * Deprecated: 2.36: Use g_type_init()
2025
1919
 **/
2026
1920
void
2027
1921
rsvg_init (void)
2028
1922
{
2029
1923
    g_type_init ();
2030
 
 
2031
 
#ifdef HAVE_GSF
2032
 
    gsf_init ();
2033
 
#endif
2034
 
 
2035
 
    xmlInitParser ();
2036
1924
}
2037
1925
 
2038
1926
/**
2039
1927
 * rsvg_term:
2040
1928
 *
2041
 
 * De-initializes librsvg
 
1929
 * This function does nothing.
 
1930
 *
2042
1931
 * Since: 2.9
 
1932
 * Deprecated: 2.36
2043
1933
 **/
2044
1934
void
2045
1935
rsvg_term (void)
2046
1936
{
2047
 
#ifdef HAVE_GSF
2048
 
    gsf_shutdown ();
2049
 
#endif
 
1937
}
2050
1938
 
 
1939
/**
 
1940
 * rsvg_cleanup:
 
1941
 *
 
1942
 * This function should not be called from normal programs.
 
1943
 * See xmlCleanupParser() for more information.
 
1944
 *
 
1945
 * Since: 2.36
 
1946
 **/
 
1947
void
 
1948
rsvg_cleanup (void)
 
1949
{
2051
1950
    xmlCleanupParser ();
2052
1951
}
2053
1952
 
2070
1969
}
2071
1970
 
2072
1971
void
2073
 
rsvg_render_path (RsvgDrawingCtx * ctx, const char *d)
 
1972
rsvg_render_path (RsvgDrawingCtx * ctx, const cairo_path_t *path)
2074
1973
{
2075
 
    /* todo: store and use the bpath higher up */
2076
 
    RsvgBpathDef *bpath_def;
2077
 
 
2078
 
    bpath_def = rsvg_parse_path (d);
2079
 
    rsvg_bpath_def_art_finish (bpath_def);
2080
 
 
2081
 
    ctx->render->render_path (ctx, bpath_def);
2082
 
    rsvg_render_markers (bpath_def, ctx);
2083
 
 
2084
 
    rsvg_bpath_def_free (bpath_def);
 
1974
    ctx->render->render_path (ctx, path);
 
1975
    rsvg_render_markers (ctx, path);
2085
1976
}
2086
1977
 
2087
1978
void
2088
 
rsvg_render_image (RsvgDrawingCtx * ctx, GdkPixbuf * pb, double x, double y, double w, double h)
 
1979
rsvg_render_surface (RsvgDrawingCtx * ctx, cairo_surface_t *surface, double x, double y, double w, double h)
2089
1980
{
2090
 
    ctx->render->render_image (ctx, pb, x, y, w, h);
 
1981
    /* surface must be a cairo image surface */
 
1982
    g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE);
 
1983
 
 
1984
    ctx->render->render_surface (ctx, surface, x, y, w, h);
2091
1985
}
2092
1986
 
2093
1987
void
2096
1990
    ctx->render->add_clipping_rect (ctx, x, y, w, h);
2097
1991
}
2098
1992
 
2099
 
GdkPixbuf *
2100
 
rsvg_get_image_of_node (RsvgDrawingCtx * ctx, RsvgNode * drawable, double w, double h)
 
1993
cairo_surface_t *
 
1994
rsvg_get_surface_of_node (RsvgDrawingCtx * ctx, RsvgNode * drawable, double w, double h)
2101
1995
{
2102
 
    return ctx->render->get_image_of_node (ctx, drawable, w, h);
 
1996
    return ctx->render->get_surface_of_node (ctx, drawable, w, h);
2103
1997
}
2104
1998
 
2105
1999
void
2109
2003
}
2110
2004
 
2111
2005
void
2112
 
rsvg_bbox_init (RsvgBbox * self, double *affine)
 
2006
rsvg_bbox_init (RsvgBbox * self, cairo_matrix_t *affine)
2113
2007
{
2114
 
    int i;
2115
2008
    self->virgin = 1;
2116
 
    for (i = 0; i < 6; i++)
2117
 
        self->affine[i] = affine[i];
 
2009
    self->affine = *affine;
2118
2010
}
2119
2011
 
2120
2012
void
2121
2013
rsvg_bbox_insert (RsvgBbox * dst, RsvgBbox * src)
2122
2014
{
2123
 
    double affine[6];
 
2015
    cairo_matrix_t affine;
2124
2016
    double xmin, ymin;
2125
2017
    double xmax, ymax;
2126
2018
    int i;
2129
2021
        return;
2130
2022
 
2131
2023
    if (!dst->virgin) {
2132
 
        xmin = dst->x, ymin = dst->y;
2133
 
        xmax = dst->x + dst->w, ymax = dst->y + dst->h;
 
2024
        xmin = dst->rect.x, ymin = dst->rect.y;
 
2025
        xmax = dst->rect.x + dst->rect.width, ymax = dst->rect.y + dst->rect.height;
2134
2026
    } else {
2135
2027
        xmin = ymin = xmax = ymax = 0;
2136
2028
    }
2137
2029
 
2138
 
    _rsvg_affine_invert (affine, dst->affine);
2139
 
    _rsvg_affine_multiply (affine, src->affine, affine);
 
2030
    affine = dst->affine;
 
2031
    if (cairo_matrix_invert (&affine) != CAIRO_STATUS_SUCCESS)
 
2032
      return; //FIXMEchpe correct??
 
2033
 
 
2034
    cairo_matrix_multiply (&affine, &src->affine, &affine);
2140
2035
 
2141
2036
    for (i = 0; i < 4; i++) {
2142
2037
        double rx, ry, x, y;
2143
 
        rx = src->x + src->w * (double) (i % 2);
2144
 
        ry = src->y + src->h * (double) (i / 2);
2145
 
        x = affine[0] * rx + affine[2] * ry + affine[4];
2146
 
        y = affine[1] * rx + affine[3] * ry + affine[5];
 
2038
        rx = src->rect.x + src->rect.width * (double) (i % 2);
 
2039
        ry = src->rect.y + src->rect.height * (double) (i / 2);
 
2040
        x = affine.xx * rx + affine.xy * ry + affine.x0;
 
2041
        y = affine.yx * rx + affine.yy * ry + affine.y0;
2147
2042
        if (dst->virgin) {
2148
2043
            xmin = xmax = x;
2149
2044
            ymin = ymax = y;
2159
2054
                ymax = y;
2160
2055
        }
2161
2056
    }
2162
 
    dst->x = xmin;
2163
 
    dst->y = ymin;
2164
 
    dst->w = xmax - xmin;
2165
 
    dst->h = ymax - ymin;
 
2057
    dst->rect.x = xmin;
 
2058
    dst->rect.y = ymin;
 
2059
    dst->rect.width = xmax - xmin;
 
2060
    dst->rect.height = ymax - ymin;
2166
2061
}
2167
2062
 
2168
2063
void
2169
2064
rsvg_bbox_clip (RsvgBbox * dst, RsvgBbox * src)
2170
2065
{
2171
 
    double affine[6];
 
2066
    cairo_matrix_t affine;
2172
2067
        double xmin, ymin;
2173
2068
        double xmax, ymax;
2174
2069
    int i;
2177
2072
        return;
2178
2073
 
2179
2074
        if (!dst->virgin) {
2180
 
        xmin = dst->x + dst->w, ymin = dst->y + dst->h;
2181
 
        xmax = dst->x, ymax = dst->y;
 
2075
        xmin = dst->rect.x + dst->rect.width, ymin = dst->rect.y + dst->rect.height;
 
2076
        xmax = dst->rect.x, ymax = dst->rect.y;
2182
2077
    } else {
2183
2078
        xmin = ymin = xmax = ymax = 0;
2184
2079
    }
2185
2080
 
2186
 
    _rsvg_affine_invert (affine, dst->affine);
2187
 
    _rsvg_affine_multiply (affine, src->affine, affine);
 
2081
    affine = dst->affine;
 
2082
    if (cairo_matrix_invert (&affine) != CAIRO_STATUS_SUCCESS)
 
2083
      return;
 
2084
 
 
2085
    cairo_matrix_multiply (&affine, &src->affine, &affine);
2188
2086
 
2189
2087
    for (i = 0; i < 4; i++) {
2190
2088
        double rx, ry, x, y;
2191
 
        rx = src->x + src->w * (double) (i % 2);
2192
 
        ry = src->y + src->h * (double) (i / 2);
2193
 
        x = affine[0] * rx + affine[2] * ry + affine[4];
2194
 
        y = affine[1] * rx + affine[3] * ry + affine[5];
 
2089
        rx = src->rect.x + src->rect.width * (double) (i % 2);
 
2090
        ry = src->rect.y + src->rect.height * (double) (i / 2);
 
2091
        x = affine.xx * rx + affine.xy * ry + affine.x0;
 
2092
        y = affine.yx * rx + affine.yy * ry + affine.y0;
2195
2093
        if (dst->virgin) {
2196
2094
            xmin = xmax = x;
2197
2095
            ymin = ymax = y;
2208
2106
        }
2209
2107
    }
2210
2108
 
2211
 
    if (xmin < dst->x)
2212
 
        xmin = dst->x;
2213
 
    if (ymin < dst->y)
2214
 
        ymin = dst->y;
2215
 
    if (xmax > dst->x + dst->w)
2216
 
        xmax = dst->x + dst->w;
2217
 
    if (ymax > dst->y + dst->h)
2218
 
        ymax = dst->y + dst->h;
 
2109
    if (xmin < dst->rect.x)
 
2110
        xmin = dst->rect.x;
 
2111
    if (ymin < dst->rect.y)
 
2112
        ymin = dst->rect.y;
 
2113
    if (xmax > dst->rect.x + dst->rect.width)
 
2114
        xmax = dst->rect.x + dst->rect.width;
 
2115
    if (ymax > dst->rect.y + dst->rect.height)
 
2116
        ymax = dst->rect.y + dst->rect.height;
2219
2117
 
2220
 
    dst->x = xmin;
2221
 
    dst->w = xmax - xmin;
2222
 
    dst->y = ymin;
2223
 
    dst->h = ymax - ymin;
 
2118
    dst->rect.x = xmin;
 
2119
    dst->rect.width = xmax - xmin;
 
2120
    dst->rect.y = ymin;
 
2121
    dst->rect.height = ymax - ymin;
2224
2122
}
2225
2123
 
2226
2124
void
2229
2127
    RsvgViewBox *vb = g_new (RsvgViewBox, 1);
2230
2128
    *vb = ctx->vb;
2231
2129
    ctx->vb_stack = g_slist_prepend (ctx->vb_stack, vb);
2232
 
    ctx->vb.w = w;
2233
 
    ctx->vb.h = h;
 
2130
    ctx->vb.rect.width = w;
 
2131
    ctx->vb.rect.height = h;
2234
2132
}
2235
2133
 
2236
2134
void
2246
2144
{
2247
2145
    g_set_error (error, RSVG_ERROR, 0, _("%s: assertion `%s' failed"), pretty_function, expression);
2248
2146
}
 
2147
 
 
2148
static gboolean
 
2149
_rsvg_handle_allow_load (RsvgHandle *handle,
 
2150
                         const char *uri,
 
2151
                         GError **error)
 
2152
{
 
2153
    RsvgLoadPolicy policy = handle->priv->load_policy;
 
2154
 
 
2155
    if (policy == RSVG_LOAD_POLICY_ALL_PERMISSIVE)
 
2156
        return TRUE;
 
2157
 
 
2158
    return TRUE;
 
2159
}
 
2160
 
 
2161
guint8* 
 
2162
_rsvg_handle_acquire_data (RsvgHandle *handle,
 
2163
                           const char *uri,
 
2164
                           char **content_type,
 
2165
                           gsize *len,
 
2166
                           GError **error)
 
2167
{
 
2168
    if (!_rsvg_handle_allow_load (handle, uri, error))
 
2169
        return NULL;
 
2170
 
 
2171
    return _rsvg_io_acquire_data (uri, 
 
2172
                                  rsvg_handle_get_base_uri (handle), 
 
2173
                                  content_type, 
 
2174
                                  len, 
 
2175
                                  handle->priv->cancellable,
 
2176
                                  error);
 
2177
}
 
2178
 
 
2179
GInputStream *
 
2180
_rsvg_handle_acquire_stream (RsvgHandle *handle,
 
2181
                             const char *uri,
 
2182
                             char **content_type,
 
2183
                             GError **error)
 
2184
{
 
2185
    if (!_rsvg_handle_allow_load (handle, uri, error))
 
2186
        return NULL;
 
2187
 
 
2188
    return _rsvg_io_acquire_stream (uri, 
 
2189
                                    rsvg_handle_get_base_uri (handle), 
 
2190
                                    content_type, 
 
2191
                                    handle->priv->cancellable,
 
2192
                                    error);
 
2193
}