rsvg-paint-server.c 5.43 KB
Newer Older
1 2
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 sts=4 expandtab: */
3
/*
4
   rsvg-paint-server.c: Implement the SVG paint server abstraction.
5

6
   Copyright (C) 2000 Eazel, Inc.
7

8
   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
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.
12

13 14 15
   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
   License along with this program; if not, write to the
   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
22

23 24 25
   Author: Raph Levien <raph@artofcode.com>
*/

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

32
#include <glib.h>
33
#include <string.h>
34 35
#include <math.h>

36 37 38
#include "rsvg-css.h"

static RsvgPaintServer *
39
rsvg_paint_server_solid (guint32 argb)
40
{
41
    RsvgPaintServer *result = g_new0 (RsvgPaintServer, 1);
42 43 44

    result->refcnt = 1;
    result->type = RSVG_PAINT_SERVER_SOLID;
45
    result->core.color = g_new0 (RsvgSolidColor, 1);
46 47
    result->core.color->argb = argb;
    result->core.color->currentcolor = FALSE;
48 49

    return result;
50 51 52
}

static RsvgPaintServer *
53
rsvg_paint_server_solid_current_color (void)
54
{
55
    RsvgPaintServer *result = g_new0 (RsvgPaintServer, 1);
56 57 58

    result->refcnt = 1;
    result->type = RSVG_PAINT_SERVER_SOLID;
59
    result->core.color = g_new0 (RsvgSolidColor, 1);
60
    result->core.color->currentcolor = TRUE;
61 62

    return result;
63 64 65
}

static RsvgPaintServer *
66
rsvg_paint_server_iri (char *iri, gboolean has_alternate, RsvgSolidColor alternate)
67
{
68
    RsvgPaintServer *result = g_new0 (RsvgPaintServer, 1);
69 70

    result->refcnt = 1;
71
    result->type = RSVG_PAINT_SERVER_IRI;
72 73 74 75
    result->core.iri = g_new0 (RsvgPaintServerIri, 1);
    result->core.iri->iri_str = iri;
    result->core.iri->has_alternate = has_alternate;
    result->core.iri->alternate = alternate;
76 77

    return result;
78 79
}

80 81 82
static gboolean
parse_current_color_or_argb (const char *str, RsvgSolidColor *dest)
{
83 84
    if (!strcmp (str, "none")) {
        dest->currentcolor = FALSE;
85
        dest->argb = 0;
86
        return FALSE;
87
    } else {
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
        RsvgCssColorSpec spec;

        spec = rsvg_css_parse_color (str, ALLOW_INHERIT_NO, ALLOW_CURRENT_COLOR_YES);
        switch (spec.kind) {
        case RSVG_CSS_COLOR_SPEC_CURRENT_COLOR:
            dest->currentcolor = TRUE;
            dest->argb = 0;
            return TRUE;

        case RSVG_CSS_COLOR_SPEC_ARGB:
            dest->currentcolor = FALSE;
            dest->argb = spec.argb;
            return TRUE;

        case RSVG_CSS_COLOR_PARSE_ERROR:
            dest->currentcolor = FALSE;
            dest->argb = 0;
            return FALSE;

        default:
            g_assert_not_reached ();
            return FALSE;
        }
111 112 113
    }
}

114
/**
115
 * rsvg_paint_server_parse:
116 117 118 119 120
 * @str: The SVG paint specification string to parse.
 *
 * Parses the paint specification @str, creating a new paint server
 * object.
 *
121 122
 * Return value: (nullable): The newly created paint server, or %NULL
 *   on error.
123 124
 **/
RsvgPaintServer *
125
rsvg_paint_server_parse (gboolean *inherit, const char *str)
126
{
127
    char *name;
128 129
    const char *rest;

130
    if (inherit != NULL)
131 132
        *inherit = TRUE;

133
    if (str == NULL || !strcmp (str, "none"))
134 135
        return NULL;

136
    name = rsvg_get_url_string (str, &rest);
137
    if (name) {
138 139 140 141 142 143 144 145 146 147
        RsvgSolidColor alternate;
        gboolean has_alternate;

        while (*rest && g_ascii_isspace (*rest)) {
            rest++;
        }

        has_alternate = parse_current_color_or_argb (rest, &alternate);

        return rsvg_paint_server_iri (name, has_alternate, alternate);
148
    } else {
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
        RsvgCssColorSpec spec;

        spec = rsvg_css_parse_color (str, ALLOW_INHERIT_YES, ALLOW_CURRENT_COLOR_YES);
        switch (spec.kind) {
        case RSVG_CSS_COLOR_SPEC_INHERIT:
            /* FIXME: this is incorrect; we should inherit the paint server */
            if (inherit != NULL)
                *inherit = FALSE;
            return rsvg_paint_server_solid (0);

        case RSVG_CSS_COLOR_SPEC_CURRENT_COLOR:
            return rsvg_paint_server_solid_current_color ();

        case RSVG_CSS_COLOR_SPEC_ARGB:
            return rsvg_paint_server_solid (spec.argb);

        case RSVG_CSS_COLOR_PARSE_ERROR:
            return NULL;

        default:
            g_assert_not_reached ();
            return NULL;
        }
172
    }
173 174 175
}

/**
176
 * rsvg_paint_server_ref:
177
 * @ps: The paint server object to reference.
178 179
 *
 * Reference a paint server object.
180 181
 **/
void
182
rsvg_paint_server_ref (RsvgPaintServer * ps)
183
{
184 185 186
    if (ps == NULL)
        return;
    ps->refcnt++;
187 188 189
}

/**
190
 * rsvg_paint_server_unref:
191
 * @ps: The paint server object to unreference.
192 193
 *
 * Unreference a paint server object.
194 195
 **/
void
196
rsvg_paint_server_unref (RsvgPaintServer * ps)
197
{
198 199 200 201
    if (ps == NULL)
        return;
    if (--ps->refcnt == 0) {
        if (ps->type == RSVG_PAINT_SERVER_SOLID)
202
            g_free (ps->core.color);
203 204
        else if (ps->type == RSVG_PAINT_SERVER_IRI) {
            g_free (ps->core.iri->iri_str);
205
            g_free (ps->core.iri);
206
        }
207 208
        g_free (ps);
    }
209
}