rsvg-defs.c 3.91 KB
Newer Older
1 2
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 sts=4 expandtab: */
3 4 5 6 7 8
/* 
   rsvg-defs.c: Manage SVG defs and references.
 
   Copyright (C) 2000 Eazel, Inc.
  
   This program is free software; you can redistribute it and/or
9
   modify it under the terms of the GNU Library General Public License as
10 11 12 13 14 15
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
   Library General Public License for more details.
17
  
18
   You should have received a copy of the GNU Library General Public
19 20 21 22 23 24 25
   License along with this program; if not, write to the
   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
  
   Author: Raph Levien <raph@artofcode.com>
*/

26
#include "config.h"
27
#include "rsvg-private.h"
28
#include "rsvg-defs.h"
29
#include "rsvg-styles.h"
30
#include "rsvg-io.h"
31

32
#include <glib.h>
33

34
struct _RsvgDefs {
35 36
    GHashTable *hash;
    GHashTable *externs;
37
    RsvgHandle *ctx;
38 39
};

40
RsvgDefs *
41
rsvg_defs_new (RsvgHandle *handle)
42
{
43
    RsvgDefs *result = g_new0 (RsvgDefs, 1);
44

45
    result->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) rsvg_node_unref);
46 47
    result->externs =
        g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref);
48
    result->ctx = handle; /* no need to take a ref here */
49 50

    return result;
51 52
}

53
static int
54
rsvg_defs_load_extern (const RsvgDefs * defs, const char *name)
55
{
56 57
    RsvgHandle *handle;
    gchar *filename, *base_uri;
58
    char *data;
59
    gsize data_len;
60
    gboolean rv;
61

62
    filename = _rsvg_io_get_file_path (name, rsvg_handle_get_base_uri (defs->ctx));
63

64
    data = _rsvg_handle_acquire_data (defs->ctx, name, NULL, &data_len, NULL);
65

66
    if (data) {
67 68 69 70 71 72
        handle = rsvg_handle_new ();

        base_uri = rsvg_get_base_uri_from_filename (filename);
        rsvg_handle_set_base_uri (handle, base_uri);
        g_free (base_uri);

73
        rv = rsvg_handle_write (handle, (guchar *) data, data_len, NULL);
74 75
        rv = rsvg_handle_close (handle, NULL) && rv;
        if (rv) {
76 77 78
            g_hash_table_insert (defs->externs, g_strdup (name), handle);
        }

79
        g_free (data);
80 81 82 83
    }

    g_free (filename);
    return 0;
84 85
}

86
static RsvgNode *
87
rsvg_defs_extern_lookup (const RsvgDefs * defs, const char *filename, const char *name)
88
{
89 90 91 92 93 94 95 96 97
    RsvgHandle *file;
    file = (RsvgHandle *) g_hash_table_lookup (defs->externs, filename);
    if (file == NULL) {
        if (rsvg_defs_load_extern (defs, filename))
            return NULL;
        file = (RsvgHandle *) g_hash_table_lookup (defs->externs, filename);
    }

    if (file != NULL)
98
        return g_hash_table_lookup (file->priv->defs->hash, name);
99 100
    else
        return NULL;
101 102
}

103
RsvgNode *
104
rsvg_defs_lookup (const RsvgDefs * defs, const char *name)
105
{
106 107 108 109 110 111
    char *hashpos;
    hashpos = g_strrstr (name, "#");
    if (!hashpos) {
        return NULL;
    }
    if (hashpos == name) {
112
        return g_hash_table_lookup (defs->hash, name + 1);
113 114 115 116 117 118 119 120
    } else {
        gchar **splitbits;
        RsvgNode *toreturn;
        splitbits = g_strsplit (name, "#", 2);
        toreturn = rsvg_defs_extern_lookup (defs, splitbits[0], splitbits[1]);
        g_strfreev (splitbits);
        return toreturn;
    }
121 122
}

Caleb Michael Moore's avatar
Caleb Michael Moore committed
123
void
124
rsvg_defs_register_node_by_id (RsvgDefs *defs, const char *id, RsvgNode *node)
Caleb Michael Moore's avatar
Caleb Michael Moore committed
125
{
126 127 128 129 130
    g_assert (defs != NULL);
    g_assert (id != NULL);
    g_assert (node != NULL);

    if (g_hash_table_lookup (defs->hash, id))
131 132
        return;

133
    g_hash_table_insert (defs->hash, g_strdup (id), rsvg_node_ref (node));
Caleb Michael Moore's avatar
Caleb Michael Moore committed
134 135
}

136
void
137
rsvg_defs_free (RsvgDefs * defs)
138
{
139
    g_hash_table_destroy (defs->hash);
140
    defs->hash = NULL;
141

142
    g_hash_table_destroy (defs->externs);
143
    defs->externs = NULL;
Caleb Michael Moore's avatar
Caleb Michael Moore committed
144

145
    g_free (defs);
146
}
147