1 /* libsvg-cairo - Render SVG documents using the cairo library
2  *
3  * Copyright � 2002 University of Southern California
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Author: Carl D. Worth <cworth@isi.edu>
20  */
21 
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "svg-cairo-internal.h"
26 
27 svg_cairo_status_t
_svg_cairo_state_create(svg_cairo_state_t ** state)28 _svg_cairo_state_create (svg_cairo_state_t **state)
29 {
30     *state = malloc (sizeof (svg_cairo_state_t));
31     if (*state == NULL)
32 	return SVG_CAIRO_STATUS_NO_MEMORY;
33 
34     _svg_cairo_state_init (*state);
35 
36     return SVG_CAIRO_STATUS_SUCCESS;
37 }
38 
39 svg_cairo_status_t
_svg_cairo_state_init(svg_cairo_state_t * state)40 _svg_cairo_state_init (svg_cairo_state_t *state)
41 {
42     /* trust libsvg to set all of these to reasonable defaults:
43     state->fill_paint;
44     state->stroke_paint;
45     state->fill_opacity;
46     state->stroke_opacity;
47     */
48     state->child_surface = NULL;
49     state->saved_cr = NULL;
50 
51     state->font_family = strdup (SVG_CAIRO_FONT_FAMILY_DEFAULT);
52     if (state->font_family == NULL)
53 	return SVG_CAIRO_STATUS_NO_MEMORY;
54 
55     state->font_size = 1.0;
56     state->font_style = SVG_FONT_STYLE_NORMAL;
57     state->font_weight = 400;
58     state->font_dirty = 1;
59 
60     state->dash = NULL;
61     state->num_dashes = 0;
62     state->dash_offset = 0;
63 
64     state->opacity = 1.0;
65 
66     state->bbox = 0;
67 
68     state->text_anchor = SVG_TEXT_ANCHOR_START;
69 
70     state->next = NULL;
71 
72     return SVG_CAIRO_STATUS_SUCCESS;
73 }
74 
75 svg_cairo_status_t
_svg_cairo_state_init_copy(svg_cairo_state_t * state,const svg_cairo_state_t * other)76 _svg_cairo_state_init_copy (svg_cairo_state_t *state, const svg_cairo_state_t *other)
77 {
78     _svg_cairo_state_deinit (state);
79 
80     if (other == NULL)
81 	return _svg_cairo_state_init (state);
82 
83     *state = *other;
84 
85     /* We don't need our own child_surface or saved cr at this point. */
86     state->child_surface = NULL;
87     state->saved_cr = NULL;
88 
89     if (other->font_family)
90 	state->font_family = strdup ((char *) other->font_family);
91 
92     state->viewport_width = other->viewport_width;
93     state->viewport_height = other->viewport_height;
94 
95     if (other->dash) {
96 	state->dash = malloc (state->num_dashes * sizeof(double));
97 	if (state->dash == NULL)
98 	    return SVG_CAIRO_STATUS_NO_MEMORY;
99 	memcpy (state->dash, other->dash, state->num_dashes * sizeof(double));
100     }
101 
102     return SVG_CAIRO_STATUS_SUCCESS;
103 }
104 
105 svg_cairo_status_t
_svg_cairo_state_deinit(svg_cairo_state_t * state)106 _svg_cairo_state_deinit (svg_cairo_state_t *state)
107 {
108     if (state->child_surface) {
109 	cairo_surface_destroy(state->child_surface);
110 	state->child_surface = NULL;
111     }
112 
113     if (state->saved_cr) {
114 	cairo_destroy(state->saved_cr);
115 	state->saved_cr = NULL;
116     }
117 
118     if (state->font_family) {
119 	free (state->font_family);
120 	state->font_family = NULL;
121     }
122 
123     if (state->dash) {
124 	free (state->dash);
125 	state->dash = NULL;
126     }
127 
128     state->next = NULL;
129 
130     return SVG_CAIRO_STATUS_SUCCESS;
131 }
132 
133 svg_cairo_status_t
_svg_cairo_state_destroy(svg_cairo_state_t * state)134 _svg_cairo_state_destroy (svg_cairo_state_t *state)
135 {
136     _svg_cairo_state_deinit (state);
137 
138     free (state);
139 
140     return SVG_CAIRO_STATUS_SUCCESS;
141 }
142 
143 svg_cairo_state_t *
_svg_cairo_state_push(svg_cairo_state_t * state)144 _svg_cairo_state_push (svg_cairo_state_t *state)
145 {
146     svg_cairo_state_t *new;
147 
148     _svg_cairo_state_create (&new);
149     if (new == NULL)
150 	return NULL;
151 
152     _svg_cairo_state_init_copy (new, state);
153 
154     new->next = state;
155 
156     return new;
157 }
158 
159 svg_cairo_state_t *
_svg_cairo_state_pop(svg_cairo_state_t * state)160 _svg_cairo_state_pop (svg_cairo_state_t *state)
161 {
162     svg_cairo_state_t *next;
163 
164     if (state == NULL)
165 	return NULL;
166 
167     next = state->next;
168 
169     _svg_cairo_state_destroy (state);
170 
171     return next;
172 }
173