From 59ecedf4447c67295802a5bdc31fd05a6981bace Mon Sep 17 00:00:00 2001 From: James Bursa Date: Fri, 13 Jul 2007 03:53:14 +0000 Subject: Primitive SVG render (rect, text). svn path=/trunk/netsurf/; revision=3405 --- image/svg.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ image/svg.h | 33 +++++++++ 2 files changed, 255 insertions(+) create mode 100644 image/svg.c create mode 100644 image/svg.h (limited to 'image') diff --git a/image/svg.c b/image/svg.c new file mode 100644 index 000000000..378b6d97e --- /dev/null +++ b/image/svg.c @@ -0,0 +1,222 @@ +/* + * This file is part of NetSurf, http://netsurf-browser.org/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2007 James Bursa + */ + +/** \file + * Content for image/svg (implementation). + */ + +#include +#include +#include +#include +#include +#include +#include +#include "utils/config.h" +#include "content/content.h" +#include "desktop/plotters.h" +#include "image/svg.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" + + +static bool svg_redraw_svg(xmlNode *svg, int x, int y); +static bool svg_redraw_rect(xmlNode *rect, int x, int y); +static bool svg_redraw_text(xmlNode *text, int x, int y); + + +/** + * Create a CONTENT_SVG. + */ + +bool svg_create(struct content *c, const char *params[]) +{ + c->data.svg.doc = 0; + c->data.svg.svg = 0; + + return true; +} + + +/** + * Convert a CONTENT_SVG for display. + */ + +bool svg_convert(struct content *c, int w, int h) +{ + xmlDoc *document; + xmlNode *svg; + union content_msg_data msg_data; + + /* parse XML to tree */ + document = xmlReadMemory(c->source_data, c->source_size, + c->url, 0, XML_PARSE_NONET | XML_PARSE_COMPACT); + if (!document) { + LOG(("xmlReadMemory failed")); + msg_data.error = messages_get("ParsingFail"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + c->data.svg.doc = document; + + xmlDebugDumpDocument(stderr, document); + + /* find root element */ + for (svg = document->children; + svg && svg->type != XML_ELEMENT_NODE; + svg = svg->next) + continue; + if (!svg) { + LOG(("no element in svg")); + msg_data.error = "no element in svg"; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + if (strcmp(svg->name, "svg") != 0) { + LOG(("root element is not svg")); + msg_data.error = "root element is not svg"; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + c->data.svg.svg = svg; + + /* get graphic dimensions */ + xmlChar *width = xmlGetProp(svg, "width"); + if (width) { + c->width = atoi(width); + xmlFree(width); + } else { + c->width = 100; + } + + xmlChar *height = xmlGetProp(svg, "height"); + if (height) { + c->height = atoi(height); + xmlFree(height); + } else { + c->height = 100; + } + + /*c->title = malloc(100); + if (c->title) + snprintf(c->title, 100, messages_get("svgTitle"), + width, height, c->source_size);*/ + //c->size += ?; + c->status = CONTENT_STATUS_DONE; + return true; +} + + +/** + * Redraw a CONTENT_SVG. + */ + +bool svg_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, + float scale, unsigned long background_colour) +{ + assert(c->data.svg.svg); + + return svg_redraw_svg(c->data.svg.svg, x, y); +} + + +/** + * Redraw a element node. + */ + +bool svg_redraw_svg(xmlNode *svg, int x, int y) +{ + for (xmlNode *child = svg->children; child; child = child->next) { + bool ok = true; + + if (child->type == XML_ELEMENT_NODE) { + if (strcmp(child->name, "svg") == 0) + ok = svg_redraw_svg(child, x, y); + else if (strcmp(child->name, "g") == 0) + ok = svg_redraw_svg(child, x, y); + else if (strcmp(child->name, "rect") == 0) + ok = svg_redraw_rect(child, x, y); + else if (strcmp(child->name, "text") == 0) + ok = svg_redraw_text(child, x, y); + } + + if (!ok) + return false; + } + + return true; +} + + +/** + * Redraw a element node. + */ + +bool svg_redraw_rect(xmlNode *rect, int x, int y) +{ + int width = 0, height = 0; + + for (xmlAttr *attr = rect->properties; attr; attr = attr->next) { + if (strcmp(attr->name, "x") == 0) + x += atoi(attr->children->content); + else if (strcmp(attr->name, "y") == 0) + y += atoi(attr->children->content); + else if (strcmp(attr->name, "width") == 0) + width = atoi(attr->children->content); + else if (strcmp(attr->name, "height") == 0) + height = atoi(attr->children->content); + } + + return plot.rectangle(x, y, width, height, 5, 0x000000, false, false); +} + + +/** + * Redraw a or element node. + */ + +bool svg_redraw_text(xmlNode *text, int x, int y) +{ + for (xmlAttr *attr = text->properties; attr; attr = attr->next) { + if (strcmp(attr->name, "x") == 0) + x += atoi(attr->children->content); + else if (strcmp(attr->name, "y") == 0) + y += atoi(attr->children->content); + } + + for (xmlNode *child = text->children; child; child = child->next) { + bool ok = true; + + if (child->type == XML_TEXT_NODE) { + ok = plot.text(x, y, &css_base_style, + child->content, strlen(child->content), + 0xffffff, 0x000000); + } else if (child->type == XML_ELEMENT_NODE && + strcmp(child->name, "tspan") == 0) { + ok = svg_redraw_text(child, x, y); + } + + if (!ok) + return false; + } + + return true; +} + + +/** + * Destroy a CONTENT_SVG and free all resources it owns. + */ + +void svg_destroy(struct content *c) +{ + if (c->data.svg.doc) + xmlFreeDoc(c->data.svg.doc); +} diff --git a/image/svg.h b/image/svg.h new file mode 100644 index 000000000..d33fdbe41 --- /dev/null +++ b/image/svg.h @@ -0,0 +1,33 @@ +/* + * This file is part of NetSurf, http://netsurf-browser.org/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2007 James Bursa + */ + +/** \file + * Content for image/svg (interface). + */ + +#ifndef _NETSURF_IMAGE_SVG_H_ +#define _NETSURF_IMAGE_SVG_H_ + +#include +#include + +struct content; + +struct content_svg_data { + xmlDoc *doc; + xmlNode *svg; +}; + +bool svg_create(struct content *c, const char *params[]); +bool svg_convert(struct content *c, int width, int height); +void svg_destroy(struct content *c); +bool svg_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, + float scale, unsigned long background_colour); + +#endif -- cgit v1.2.3