summaryrefslogtreecommitdiff
path: root/image/rsvg.c
diff options
context:
space:
mode:
Diffstat (limited to 'image/rsvg.c')
-rw-r--r--image/rsvg.c189
1 files changed, 167 insertions, 22 deletions
diff --git a/image/rsvg.c b/image/rsvg.c
index cf3d5cea6..26370de57 100644
--- a/image/rsvg.c
+++ b/image/rsvg.c
@@ -32,6 +32,7 @@
#include <stdbool.h>
#include <assert.h>
+#include <string.h>
#include <sys/types.h>
#include <librsvg/rsvg.h>
@@ -46,33 +47,151 @@
#include "utils/messages.h"
#include "utils/talloc.h"
+typedef struct rsvg_content {
+ struct content base;
+
+ RsvgHandle *rsvgh; /**< Context handle for RSVG renderer */
+ cairo_surface_t *cs; /**< The surface built inside a nsbitmap */
+ cairo_t *ct; /**< Cairo drawing context */
+ struct bitmap *bitmap; /**< Created NetSurf bitmap */
+} rsvg_content;
+
+static nserror rsvg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror rsvg_create_svg_data(rsvg_content *c);
+static bool rsvg_process_data(struct content *c, const char *data,
+ unsigned int size);
+static bool rsvg_convert(struct content *c);
+static void rsvg_destroy(struct content *c);
+static bool rsvg_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror rsvg_clone(const struct content *old, struct content **newc);
+static content_type rsvg_content_type(lwc_string *mime_type);
+
static inline void rsvg_argb_to_abgr(uint8_t *pixels,
int width, int height, size_t rowstride);
-bool rsvg_create(struct content *c, const struct http_parameter *params)
+static const content_handler rsvg_content_handler = {
+ rsvg_create,
+ rsvg_process_data,
+ rsvg_convert,
+ NULL,
+ rsvg_destroy,
+ NULL,
+ NULL,
+ NULL,
+ rsvg_redraw,
+ NULL,
+ NULL,
+ NULL,
+ rsvg_clone,
+ NULL,
+ rsvg_content_type,
+ false
+};
+
+static const char *rsvg_types[] = {
+ "image/svg",
+ "image/svg+xml"
+};
+
+static lwc_string *rsvg_mime_types[NOF_ELEMENTS(rsvg_types)];
+
+nserror nsrsvg_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(rsvg_mime_types); i++) {
+ lerror = lwc_intern_string(rsvg_types[i],
+ strlen(rsvg_types[i]),
+ &rsvg_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(rsvg_mime_types[i],
+ &rsvg_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsrsvg_fini();
+
+ return error;
+}
+
+void nsrsvg_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(rsvg_mime_types); i++) {
+ if (rsvg_mime_types[i] != NULL)
+ lwc_string_unref(rsvg_mime_types[i]);
+ }
+}
+
+nserror rsvg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ rsvg_content *svg;
+ nserror error;
+
+ svg = talloc_zero(0, rsvg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&svg->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ error = rsvg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ *c = (struct content *) svg;
+
+ return NSERROR_OK;
+}
+
+nserror rsvg_create_svg_data(rsvg_content *c)
{
- struct content_rsvg_data *d = &c->data.rsvg;
union content_msg_data msg_data;
- d->rsvgh = NULL;
- d->cs = NULL;
- d->ct = NULL;
- d->bitmap = NULL;
+ c->rsvgh = NULL;
+ c->cs = NULL;
+ c->ct = NULL;
+ c->bitmap = NULL;
- if ((d->rsvgh = rsvg_handle_new()) == NULL) {
+ if ((c->rsvgh = rsvg_handle_new()) == NULL) {
LOG(("rsvg_handle_new() returned NULL."));
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- return true;
+ return NSERROR_OK;
}
bool rsvg_process_data(struct content *c, const char *data,
unsigned int size)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ rsvg_content *d = (rsvg_content *) c;
union content_msg_data msg_data;
GError *err = NULL;
@@ -118,7 +237,7 @@ static inline void rsvg_argb_to_abgr(uint8_t *pixels,
bool rsvg_convert(struct content *c)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ rsvg_content *d = (rsvg_content *) c;
union content_msg_data msg_data;
RsvgDimensionData rsvgsize;
GError *err = NULL;
@@ -191,7 +310,7 @@ bool rsvg_redraw(struct content *c, int x, int y,
void rsvg_destroy(struct content *c)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ rsvg_content *d = (rsvg_content *) c;
if (d->bitmap != NULL) bitmap_destroy(d->bitmap);
if (d->rsvgh != NULL) rsvg_handle_free(d->rsvgh);
@@ -201,28 +320,54 @@ void rsvg_destroy(struct content *c)
return;
}
-bool rsvg_clone(const struct content *old, struct content *new_content)
+nserror rsvg_clone(const struct content *old, struct content **newc)
{
+ rsvg_content *svg;
+ nserror error;
const char *data;
unsigned long size;
+ svg = talloc_zero(0, rsvg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &svg->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
+
/* Simply replay create/process/convert */
- if (rsvg_create(new_content, NULL) == false)
- return false;
+ error = rsvg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
- data = content__get_source_data(new_content, &size);
+ data = content__get_source_data(&svg->base, &size);
if (size > 0) {
- if (rsvg_process_data(new_content, data, size) == false)
- return false;
+ if (rsvg_process_data(&svg->base, data, size) == false) {
+ content_destroy(&svg->base);
+ return NSERROR_NOMEM;
+ }
}
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (rsvg_convert(new_content) == false)
- return false;
+ if (rsvg_convert(&svg->base) == false) {
+ content_destroy(&svg->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) svg;
+
+ return NSERROR_OK;
+}
+
+content_type rsvg_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
}
#endif /* WITH_RSVG */