NetSurf
svg.c
Go to the documentation of this file.
1/*
2 * Copyright 2007-2008 James Bursa <bursa@users.sourceforge.net>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf 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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * implementation of content for image/svg using libsvgtiny.
22 */
23
24#include <assert.h>
25#include <limits.h>
26#include <string.h>
27#include <stdlib.h>
28
29#include <svgtiny.h>
30
31#include "utils/messages.h"
32#include "utils/utils.h"
33#include "utils/nsurl.h"
34#include "netsurf/plotters.h"
35#include "netsurf/content.h"
38
39#include "image/svg.h"
40
41typedef struct svg_content {
42 struct content base;
43
44 struct svgtiny_diagram *diagram;
45
49
50
51
53{
54 c->diagram = svgtiny_create();
55 if (c->diagram == NULL)
56 goto no_memory;
57
58 c->current_width = INT_MAX;
59 c->current_height = INT_MAX;
60
61 return NSERROR_OK;
62
63no_memory:
65 return NSERROR_NOMEM;
66}
67
68
69/**
70 * Create a CONTENT_SVG.
71 */
72
73static nserror svg_create(const content_handler *handler,
74 lwc_string *imime_type, const struct http_parameter *params,
75 struct llcache_handle *llcache, const char *fallback_charset,
76 bool quirks, struct content **c)
77{
78 svg_content *svg;
79 nserror error;
80
81 svg = calloc(1, sizeof(svg_content));
82 if (svg == NULL)
83 return NSERROR_NOMEM;
84
85 error = content__init(&svg->base, handler, imime_type, params,
86 llcache, fallback_charset, quirks);
87 if (error != NSERROR_OK) {
88 free(svg);
89 return error;
90 }
91
92 error = svg_create_svg_data(svg);
93 if (error != NSERROR_OK) {
94 free(svg);
95 return error;
96 }
97
98 *c = (struct content *) svg;
99
100 return NSERROR_OK;
101}
102
103
104
105/**
106 * Convert a CONTENT_SVG for display.
107 */
108
109static bool svg_convert(struct content *c)
110{
111 /*c->title = malloc(100);
112 if (c->title)
113 snprintf(c->title, 100, messages_get("svgTitle"),
114 width, height, c->source_size);*/
115 //c->size += ?;
118 /* Done: update status bar */
119 content_set_status(c, "");
120
121 return true;
122}
123
124/**
125 * Reformat a CONTENT_SVG.
126 */
127
128static void svg_reformat(struct content *c, int width, int height)
129{
130 svg_content *svg = (svg_content *) c;
131 const uint8_t *source_data;
132 size_t source_size;
133
134 assert(svg->diagram);
135
136 /* Avoid reformats to same width/height as we already reformatted to */
137 if (width != svg->current_width || height != svg->current_height) {
138 source_data = content__get_source_data(c, &source_size);
139
140 svgtiny_parse(svg->diagram,
141 (const char *)source_data,
142 source_size,
144 width,
145 height);
146
147 svg->current_width = width;
148 svg->current_height = height;
149 }
150
151 c->width = svg->diagram->width;
152 c->height = svg->diagram->height;
153}
154
155
156/**
157 * Redraw a CONTENT_SVG.
158 */
159
160static bool
162 int x,
163 int y,
164 int width,
165 int height,
166 const struct rect *clip,
167 const struct redraw_context *ctx,
168 float scale,
169 colour background_colour)
170{
171 svg_content *svg = (svg_content *) c;
172 float transform[6];
173 struct svgtiny_diagram *diagram = svg->diagram;
174 int px, py;
175 unsigned int i;
177 plot_style_t pstyle;
178 nserror res;
179
180 assert(diagram);
181
182 transform[0] = (float) width / (float) c->width;
183 transform[1] = 0;
184 transform[2] = 0;
185 transform[3] = (float) height / (float) c->height;
186 transform[4] = x;
187 transform[5] = y;
188
189#define BGR(c) ((c) == svgtiny_TRANSPARENT ? NS_TRANSPARENT : \
190 ((svgtiny_RED((c))) | \
191 (svgtiny_GREEN((c)) << 8) | \
192 (svgtiny_BLUE((c)) << 16)))
193
194 for (i = 0; i != diagram->shape_count; i++) {
195 if (diagram->shape[i].path) {
197 diagram->shape[i].stroke_width);
198 pstyle.stroke_colour = BGR(diagram->shape[i].stroke);
199 pstyle.fill_colour = BGR(diagram->shape[i].fill);
200 res = ctx->plot->path(ctx,
201 &pstyle,
202 diagram->shape[i].path,
203 diagram->shape[i].path_length,
204 transform);
205 if (res != NSERROR_OK) {
206 return false;
207 }
208
209 } else if (diagram->shape[i].text) {
210 px = transform[0] * diagram->shape[i].text_x +
211 transform[2] * diagram->shape[i].text_y +
212 transform[4];
213 py = transform[1] * diagram->shape[i].text_x +
214 transform[3] * diagram->shape[i].text_y +
215 transform[5];
216
217 fstyle.background = 0xffffff;
218 fstyle.foreground = 0x000000;
219 fstyle.size = (8 * PLOT_STYLE_SCALE) * scale;
220
221 res = ctx->plot->text(ctx,
222 &fstyle,
223 px, py,
224 diagram->shape[i].text,
225 strlen(diagram->shape[i].text));
226 if (res != NSERROR_OK) {
227 return false;
228 }
229 }
230 }
231
232#undef BGR
233
234 return true;
235}
236
237
238/**
239 * Redraw a CONTENT_SVG.
240 */
241
242static bool svg_redraw(struct content *c, struct content_redraw_data *data,
243 const struct rect *clip, const struct redraw_context *ctx)
244{
245 int x = data->x;
246 int y = data->y;
247
248 if ((data->width <= 0) && (data->height <= 0)) {
249 /* No point trying to plot SVG if it does not occupy a valid
250 * area */
251 return true;
252 }
253
254 if ((data->repeat_x == false) && (data->repeat_y == false)) {
255 /* Simple case: SVG is not tiled */
256 return svg_redraw_internal(c, x, y,
257 data->width, data->height,
258 clip, ctx, data->scale,
259 data->background_colour);
260 } else {
261 /* Tiled redraw required. SVG repeats to extents of clip
262 * rectangle, in x, y or both directions */
263 int x0, y0, x1, y1;
264
265 /* Find the redraw boundaries to loop within */
266 x0 = x;
267 if (data->repeat_x) {
268 for (; x0 > clip->x0; x0 -= data->width);
269 x1 = clip->x1;
270 } else {
271 x1 = x + 1;
272 }
273 y0 = y;
274 if (data->repeat_y) {
275 for (; y0 > clip->y0; y0 -= data->height);
276 y1 = clip->y1;
277 } else {
278 y1 = y + 1;
279 }
280
281 /* Repeatedly plot the SVG across the area */
282 for (y = y0; y < y1; y += data->height) {
283 for (x = x0; x < x1; x += data->width) {
284 if (!svg_redraw_internal(c, x, y,
285 data->width, data->height,
286 clip, ctx, data->scale,
287 data->background_colour)) {
288 return false;
289 }
290 }
291 }
292 }
293
294 return true;
295}
296
297
298/**
299 * Destroy a CONTENT_SVG and free all resources it owns.
300 */
301
302static void svg_destroy(struct content *c)
303{
304 svg_content *svg = (svg_content *) c;
305
306 if (svg->diagram != NULL)
307 svgtiny_free(svg->diagram);
308}
309
310
311static nserror svg_clone(const struct content *old, struct content **newc)
312{
313 svg_content *svg;
314 nserror error;
315
316 svg = calloc(1, sizeof(svg_content));
317 if (svg == NULL)
318 return NSERROR_NOMEM;
319
320 error = content__clone(old, &svg->base);
321 if (error != NSERROR_OK) {
322 content_destroy(&svg->base);
323 return error;
324 }
325
326 /* Simply replay create/convert */
327 error = svg_create_svg_data(svg);
328 if (error != NSERROR_OK) {
329 content_destroy(&svg->base);
330 return error;
331 }
332
333 if (old->status == CONTENT_STATUS_READY ||
334 old->status == CONTENT_STATUS_DONE) {
335 if (svg_convert(&svg->base) == false) {
336 content_destroy(&svg->base);
338 }
339 }
340
341 *newc = (struct content *) svg;
342
343 return NSERROR_OK;
344}
345
347{
348 return CONTENT_IMAGE;
349}
350
353 .data_complete = svg_convert,
354 .reformat = svg_reformat,
355 .destroy = svg_destroy,
356 .redraw = svg_redraw,
357 .clone = svg_clone,
358 .type = svg_content_type,
359 .no_share = true
360};
361
362static const char *svg_types[] = {
363 "image/svg",
364 "image/svg+xml"
365};
366
367
void content_destroy(struct content *c)
Destroy and free a content.
Definition: content.c:354
void content_set_done(struct content *c)
Put a content in status CONTENT_STATUS_DONE.
Definition: content.c:299
nserror content__init(struct content *c, const content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, llcache_handle *llcache, const char *fallback_charset, bool quirks)
Definition: content.c:190
nsurl * content_get_url(struct content *c)
Retrieve URL associated with content.
Definition: content.c:1051
const uint8_t * content__get_source_data(struct content *c, size_t *size)
Retrieve source of content.
Definition: content.c:1216
nserror content__clone(const struct content *c, struct content *nc)
Clone a content's data members.
Definition: content.c:1382
void content_set_ready(struct content *c)
Put a content in status CONTENT_STATUS_READY and unlock the content.
Definition: content.c:285
void content_set_status(struct content *c, const char *status_message)
Updates content with new status.
Definition: content.c:270
void content_broadcast_error(struct content *c, nserror errorcode, const char *msg)
Send an error message to all users.
Definition: content.c:769
Protected interface to Content handling.
@ CONTENT_STATUS_READY
Some parts of content still being loaded, but can be displayed.
Definition: content_type.h:92
@ CONTENT_STATUS_DONE
Content has completed all processing.
Definition: content_type.h:95
content_type
The type of a content.
Definition: content_type.h:53
@ CONTENT_IMAGE
All images.
Definition: content_type.h:67
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_CLONE_FAILED
Failed to clone handle.
Definition: errors.h:37
@ NSERROR_OK
No error.
Definition: errors.h:30
Public content interface.
Target independent plotting interface.
static struct llcache_s * llcache
low level cache state
Definition: llcache.c:267
Localised message support (interface).
NetSurf URL handling (interface).
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
plot_font_style_t const *const plot_style_font
Definition: plot_style.c:165
#define plot_style_int_to_fixed(v)
Definition: plot_style.h:51
#define PLOT_STYLE_SCALE
Scaling factor for plot styles.
Definition: plot_style.h:45
int width
Definition: gui.c:166
int height
Definition: gui.c:167
Interface to utility string handling.
Content operation function table.
nserror(* create)(const struct content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, struct llcache_handle *llcache, const char *fallback_charset, bool quirks, struct content **c)
parameters to content redraw
Definition: content.h:40
int height
vertical dimension
Definition: content.h:48
bool repeat_y
whether content is tiled in y direction
Definition: content.h:59
bool repeat_x
whether content is tiled in x direction
Definition: content.h:58
int y
coordinate for top-left of redraw
Definition: content.h:42
int x
coordinate for top-left of redraw
Definition: content.h:41
colour background_colour
The background colour.
Definition: content.h:51
int width
dimensions to render content at (for scaling contents with intrinsic dimensions)
Definition: content.h:47
float scale
Scale for redraw (for scaling contents without intrinsic dimensions)
Definition: content.h:56
Content which corresponds to a single URL.
int height
Height dimension, if applicable.
int width
Width dimension, if applicable.
content_status status
Current status.
Representation of an HTTP parameter.
Definition: parameter.c:31
Handle to low-level cache object.
Definition: llcache.c:76
Font style for plotting.
Definition: plot_style.h:111
colour foreground
Colour of text.
Definition: plot_style.h:123
plot_style_fixed size
Font size, in pt.
Definition: plot_style.h:119
colour background
Background colour to blend to, if appropriate.
Definition: plot_style.h:122
Plot style for stroke/fill plotters.
Definition: plot_style.h:76
colour fill_colour
Colour of fill.
Definition: plot_style.h:81
plot_style_fixed stroke_width
Width of stroke, in pixels.
Definition: plot_style.h:78
colour stroke_colour
Colour of stroke.
Definition: plot_style.h:79
nserror(* text)(const struct redraw_context *ctx, const plot_font_style_t *fstyle, int x, int y, const char *text, size_t length)
Text plotting.
Definition: plotters.h:278
nserror(* path)(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plotters.h:226
Rectangle coordinates.
Definition: types.h:40
Redraw context.
Definition: plotters.h:51
const struct plotter_table * plot
Current plot operation table.
Definition: plotters.h:73
struct svgtiny_diagram * diagram
Definition: svg.c:44
struct content base
Definition: svg.c:42
int current_height
Definition: svg.c:47
int current_width
Definition: svg.c:46
static void svg_destroy(struct content *c)
Destroy a CONTENT_SVG and free all resources it owns.
Definition: svg.c:302
struct svg_content svg_content
static const char * svg_types[]
Definition: svg.c:362
static bool svg_convert(struct content *c)
Convert a CONTENT_SVG for display.
Definition: svg.c:109
CONTENT_FACTORY_REGISTER_TYPES(svg, svg_types, svg_content_handler)
#define BGR(c)
static bool svg_redraw(struct content *c, struct content_redraw_data *data, const struct rect *clip, const struct redraw_context *ctx)
Redraw a CONTENT_SVG.
Definition: svg.c:242
static void svg_reformat(struct content *c, int width, int height)
Reformat a CONTENT_SVG.
Definition: svg.c:128
static nserror svg_create_svg_data(svg_content *c)
Definition: svg.c:52
static nserror svg_clone(const struct content *old, struct content **newc)
Definition: svg.c:311
static const content_handler svg_content_handler
Definition: svg.c:351
static nserror svg_create(const content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, struct llcache_handle *llcache, const char *fallback_charset, bool quirks, struct content **c)
Create a CONTENT_SVG.
Definition: svg.c:73
static content_type svg_content_type(void)
Definition: svg.c:346
static bool svg_redraw_internal(struct content *c, int x, int y, int width, int height, const struct rect *clip, const struct redraw_context *ctx, float scale, colour background_colour)
Redraw a CONTENT_SVG.
Definition: svg.c:161
Content for image/svg (interface).
uint32_t colour
Colour type: XBGR.
Definition: types.h:35
Interface to a number of general purpose functionality.
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357