summaryrefslogtreecommitdiff
path: root/rsvg-shapes.c
diff options
context:
space:
mode:
authorCaleb Michael Moore <cmoore@src.gnome.org>2005-02-11 13:38:17 +0000
committerCaleb Michael Moore <cmoore@src.gnome.org>2005-02-11 13:38:17 +0000
commit7072c08c2c0e054fef272927fcb0b62ce6c7108d (patch)
treef4e97f9fa75710e10450595465c51344119980ba /rsvg-shapes.c
parenteaf07a88aab2f65bb217cf6a8aaeeaef81fdb6d8 (diff)
downloadlibrsvg-7072c08c2c0e054fef272927fcb0b62ce6c7108d.tar.gz
split the behemoth rsvg-shapes.c into bite size meaty chunks
Diffstat (limited to 'rsvg-shapes.c')
-rw-r--r--rsvg-shapes.c2103
1 files changed, 33 insertions, 2070 deletions
diff --git a/rsvg-shapes.c b/rsvg-shapes.c
index 4b0c77f7..0da7e6cf 100644
--- a/rsvg-shapes.c
+++ b/rsvg-shapes.c
@@ -20,7 +20,34 @@
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
- Author: Raph Levien <raph@artofcode.com>
+ Authors: Raph Levien <raph@artofcode.com>,
+ Dom Lachowicz <cinamod@hotmail.com>,
+ Caleb Moore <c.moore@student.unsw.edu.au>
+*//* vim: set sw=4: -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ rsvg-shapes.c: Draw SVG shapes
+
+ Copyright (C) 2000 Eazel, Inc.
+ Copyright (C) 2002 Dom Lachowicz <cinamod@hotmail.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Raph Levien <raph@artofcode.com>,
+ Dom Lachowicz <cinamod@hotmail.com>,
+ Caleb Moore <c.moore@student.unsw.edu.au>
*/
#include <string.h>
#include <math.h>
@@ -31,22 +58,15 @@
#include "rsvg-styles.h"
#include "rsvg-shapes.h"
#include "rsvg-css.h"
-#include "rsvg-bpath-util.h"
-#include "rsvg-path.h"
#include "rsvg-defs.h"
#include "rsvg-filter.h"
#include "rsvg-mask.h"
+#include "rsvg-image.h"
+#include "rsvg-art-draw.h"
-#include <libart_lgpl/art_affine.h>
-#include <libart_lgpl/art_vpath_bpath.h>
-#include <libart_lgpl/art_render_svp.h>
-#include <libart_lgpl/art_svp_vpath.h>
#include <libart_lgpl/art_svp_intersect.h>
#include <libart_lgpl/art_svp_ops.h>
-#include <libart_lgpl/art_svp_vpath.h>
-#include <libart_lgpl/art_rgb_affine.h>
-#include <libart_lgpl/art_rgb_rgba_affine.h>
-#include <libart_lgpl/art_rgb_svp.h>
+#include <libart_lgpl/art_affine.h>
/* 4/3 * (1-cos 45ƒ)/sin 45ƒ = 4/3 * sqrt(2) - 1 */
#define RSVG_ARC_MAGIC ((double) 0.5522847498)
@@ -55,504 +75,6 @@
#define M_PI 3.14159265358979323846
#endif /* M_PI */
-/**
- * rsvg_close_vpath: Close a vector path.
- * @src: Source vector path.
- *
- * Closes any open subpaths in the vector path.
- *
- * Return value: Closed vector path, allocated with g_new.
- **/
-static ArtVpath *
-rsvg_close_vpath (const ArtVpath *src)
-{
- ArtVpath *result;
- int n_result, n_result_max;
- int src_ix;
- double beg_x, beg_y;
- gboolean open;
-
- n_result = 0;
- n_result_max = 16;
- result = g_new (ArtVpath, n_result_max);
-
- beg_x = 0;
- beg_y = 0;
- open = FALSE;
-
- for (src_ix = 0; src[src_ix].code != ART_END; src_ix++)
- {
- if (n_result == n_result_max)
- result = g_renew (ArtVpath, result, n_result_max <<= 1);
- result[n_result].code = src[src_ix].code == ART_MOVETO_OPEN ?
- ART_MOVETO : src[src_ix].code;
- result[n_result].x = src[src_ix].x;
- result[n_result].y = src[src_ix].y;
- n_result++;
- if (src[src_ix].code == ART_MOVETO_OPEN)
- {
- beg_x = src[src_ix].x;
- beg_y = src[src_ix].y;
- open = TRUE;
- }
- else if (src[src_ix + 1].code != ART_LINETO)
- {
- if (open && (beg_x != src[src_ix].x || beg_y != src[src_ix].y))
- {
- if (n_result == n_result_max)
- result = g_renew (ArtVpath, result, n_result_max <<= 1);
- result[n_result].code = ART_LINETO;
- result[n_result].x = beg_x;
- result[n_result].y = beg_y;
- n_result++;
- }
- open = FALSE;
- }
- }
- if (n_result == n_result_max)
- result = g_renew (ArtVpath, result, n_result_max <<= 1);
- result[n_result].code = ART_END;
- result[n_result].x = 0.0;
- result[n_result].y = 0.0;
- return result;
-}
-
-/* calculates how big an svp is */
-struct _RsvgFRect
-{
- double x0;
- double y0;
- double x1;
- double y1;
-};
-typedef struct _RsvgFRect RsvgFRect;
-
-static RsvgFRect
-rsvg_calculate_svp_bounds (const ArtSVP *svp, double * useraffine)
-{
- int i, j;
- float x, y;
- double affine[6];
- float bigx, littlex, bigy, littley, assignedonce;
- RsvgFRect output;
-
- art_affine_invert(affine, useraffine);
- bigx = littlex = bigy = littley = assignedonce = 0;
-
- for (i = 0; i < svp->n_segs; i++)
- for (j = 0; j < svp->segs[i].n_points; j++)
- {
- x = svp->segs[i].points[j].x * affine[0] +
- svp->segs[i].points[j].y * affine[2] +
- affine[4];
- y = svp->segs[i].points[j].x * affine[1] +
- svp->segs[i].points[j].y * affine[3] +
- affine[5];
- if (!assignedonce)
- {
- bigx = x;
- littlex = x;
- bigy = y;
- littley = y;
- assignedonce = 1;
- }
- if (x > bigx)
- bigx = x;
- if (x < littlex)
- littlex = x;
- if (y > bigy)
- bigy = y;
- if (y < littley)
- littley = y;
- }
- output.x0 = littlex;
- output.y0 = littley;
- output.x1 = bigx;
- output.y1 = bigy;
- return output;
-}
-
-static ArtIRect rsvg_frect_pixelspaceise(RsvgFRect input, double * affine)
-{
- ArtIRect temprect;
- int i, j, basex, basey;
- int assignedonce = 0;
- float x, y;
-
- for (i = 0; i < 2; i++)
- for (j = 0; j < 2; j++)
- {
- x = i ? input.x0 : input.x1;
- y = j ? input.y0 : input.y1;
- basex = affine[0] * x + affine[2] * y + affine[4];
- basey = affine[1] * x + affine[3] * y + affine[5];
- if (assignedonce)
- {
- temprect.x0 = MIN(basex, temprect.x0);
- temprect.y0 = MIN(basey, temprect.y0);
- temprect.x1 = MAX(basex, temprect.x1);
- temprect.y1 = MAX(basey, temprect.y1);
- }
- else
- {
- temprect.x1 = temprect.x0 = basex;
- temprect.y1 = temprect.y0 = basey;
- assignedonce = 1;
- }
- }
- return temprect;
-}
-
-/**
- * rsvg_render_svp: Render an SVP.
- * @ctx: Context in which to render.
- * @svp: SVP to render.
- * @ps: Paint server for rendering.
- * @opacity: Opacity as 0..0xff.
- *
- * Renders the SVP over the pixbuf in @ctx.
- **/
-static void
-rsvg_render_svp (DrawingCtx *ctx, ArtSVP *svp,
- RsvgPaintServer *ps, int opacity)
-{
- GdkPixbuf *pixbuf;
- ArtRender *render;
- gboolean has_alpha;
- RsvgFRect temprect;
- ArtIRect temptemprect;
- RsvgPSCtx gradctx;
- RsvgState *state;
- int i;
-
- rsvg_state_clip_path_assure(ctx);
-
- pixbuf = ctx->pixbuf;
- if (pixbuf == NULL)
- {
- /* FIXME: What warning/GError here? */
- return;
- }
-
- state = rsvg_state_current(ctx);
-
- has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
-
- render = art_render_new (0, 0,
- gdk_pixbuf_get_width (pixbuf),
- gdk_pixbuf_get_height (pixbuf),
- gdk_pixbuf_get_pixels (pixbuf),
- gdk_pixbuf_get_rowstride (pixbuf),
- gdk_pixbuf_get_n_channels (pixbuf) -
- (has_alpha ? 1 : 0),
- gdk_pixbuf_get_bits_per_sample (pixbuf),
- has_alpha ? ART_ALPHA_SEPARATE : ART_ALPHA_NONE,
- NULL);
-
- temprect = rsvg_calculate_svp_bounds(svp, state->affine);
-
- if (state->clippath != NULL)
- {
- ArtSVP * svpx;
- svpx = art_svp_intersect(svp, state->clippath);
- svp = svpx;
- }
-
- art_render_svp (render, svp);
- art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
-
- temptemprect = rsvg_frect_pixelspaceise(temprect, state->affine);
- art_irect_union(&ctx->bbox, &ctx->bbox, &temptemprect);
-
- gradctx.x0 = temprect.x0;
- gradctx.y0 = temprect.y0;
- gradctx.x1 = temprect.x1;
- gradctx.y1 = temprect.y1;
- gradctx.ctx = ctx;
-
- for (i = 0; i < 6; i++)
- gradctx.affine[i] = state->affine[i];
-
- gradctx.color = state->current_color;
- rsvg_render_paint_server (render, ps, &gradctx);
- art_render_invoke (render);
-
- if (state->clippath != NULL) /*we don't need svpx any more*/
- art_free(svp);
-}
-
-static ArtSVP *
-rsvg_render_filling (RsvgState *state, const ArtVpath *vpath)
-{
- ArtVpath *closed_vpath;
- ArtSVP *svp2, *svp;
- ArtSvpWriter *swr;
-
- closed_vpath = rsvg_close_vpath (vpath);
- svp = art_svp_from_vpath (closed_vpath);
- g_free (closed_vpath);
-
- if (state->fill_rule == FILL_RULE_EVENODD)
- swr = art_svp_writer_rewind_new (ART_WIND_RULE_ODDEVEN);
- else /* state->fill_rule == FILL_RULE_NONZERO */
- swr = art_svp_writer_rewind_new (ART_WIND_RULE_NONZERO);
-
- art_svp_intersector (svp, swr);
-
- svp2 = art_svp_writer_rewind_reap (swr);
- art_svp_free (svp);
-
- return svp2;
-}
-
-static ArtSVP *
-rsvg_render_outline (RsvgState *state, ArtVpath *vpath)
-{
- ArtSVP * output;
-
- /* todo: libart doesn't yet implement anamorphic scaling of strokes */
- double stroke_width = state->stroke_width *
- art_affine_expansion (state->affine);
-
- if (stroke_width < 0.25)
- stroke_width = 0.25;
-
- /* if the path is dashed, stroke it */
- if (state->dash.n_dash > 0)
- {
- ArtVpath * dashed_vpath = art_vpath_dash (vpath, &state->dash);
- vpath = dashed_vpath;
- }
-
- output = art_svp_vpath_stroke (vpath, state->join, state->cap,
- stroke_width, state->miter_limit, 0.25);
-
- if (state->dash.n_dash > 0)
- art_free (vpath);
- return output;
-}
-
-static void
-rsvg_render_bpath (DrawingCtx *ctx, const ArtBpath *bpath)
-{
- RsvgState *state;
- ArtBpath *affine_bpath;
- ArtVpath *vpath;
- ArtSVP *svp;
- GdkPixbuf *pixbuf;
- gboolean need_tmpbuf;
- int opacity;
- int tmp;
-
- pixbuf = ctx->pixbuf;
- if (pixbuf == NULL)
- {
- /* FIXME: What warning/GError here? */
- return;
- }
-
- state = rsvg_state_current (ctx);
-
- /* todo: handle visibility stuff earlier for performance benefits
- * handles all path based shapes. will handle text and images separately
- */
- if (!state->visible || !state->cond_true)
- return;
-
- affine_bpath = art_bpath_affine_transform (bpath,
- state->affine);
-
- vpath = art_bez_path_to_vec (affine_bpath, 0.25);
- art_free (affine_bpath);
-
- need_tmpbuf = ((state->fill != NULL) && (state->stroke != NULL) &&
- state->opacity != 0xff) || rsvg_needs_discrete_layer(state);
-
- if (need_tmpbuf)
- rsvg_push_discrete_layer (ctx);
-
- if (state->fill != NULL)
- {
-
- opacity = state->fill_opacity;
- if (!need_tmpbuf && state->opacity != 0xff)
- {
- tmp = opacity * state->opacity + 0x80;
- opacity = (tmp + (tmp >> 8)) >> 8;
- }
- svp = rsvg_render_filling(state, vpath);
- rsvg_render_svp (ctx, svp, state->fill, opacity);
- art_svp_free (svp);
- }
-
- if (state->stroke != NULL)
- {
- opacity = state->stroke_opacity;
- if (!need_tmpbuf && state->opacity != 0xff)
- {
- tmp = opacity * state->opacity + 0x80;
- opacity = (tmp + (tmp >> 8)) >> 8;
- }
- svp = rsvg_render_outline(state, vpath);
- rsvg_render_svp (ctx, svp, state->stroke, opacity);
- art_svp_free (svp);
- }
-
- if (need_tmpbuf)
- rsvg_pop_discrete_layer (ctx);
-
- art_free (vpath);
-}
-
-static ArtSVP *
-rsvg_render_bpath_into_svp (DrawingCtx *ctx, const ArtBpath *bpath)
-{
- RsvgState *state;
- ArtBpath *affine_bpath;
- ArtVpath *vpath;
- ArtSVP *svp;
-
- state = rsvg_state_current (ctx);
-
- affine_bpath = art_bpath_affine_transform (bpath,
- state->affine);
-
- vpath = art_bez_path_to_vec (affine_bpath, 0.25);
- art_free (affine_bpath);
- state->fill_rule = state->clip_rule;
-
- svp = rsvg_render_filling(state, vpath);
-
- art_free (vpath);
- return svp;
-}
-
-static void
-rsvg_render_markers(RsvgBpathDef * bpath_def, DrawingCtx *ctx)
-{
- int i;
-
- double x, y;
- double lastx, lasty;
- double nextx, nexty;
- double linewidth;
-
- RsvgState * state;
- RsvgMarker * startmarker;
- RsvgMarker * middlemarker;
- RsvgMarker * endmarker;
-
- state = rsvg_state_current(ctx);
-
- linewidth = state->stroke_width;
- startmarker = (RsvgMarker *)state->startMarker;
- middlemarker = (RsvgMarker *)state->middleMarker;
- endmarker = (RsvgMarker *)state->endMarker;
-
- if (!startmarker && !middlemarker && !endmarker)
- return;
-
- x = 0;
- y = 0;
- nextx = state->affine[0] * bpath_def->bpath[0].x3 +
- state->affine[2] * bpath_def->bpath[0].y3 + state->affine[4];
- nexty = state->affine[1] * bpath_def->bpath[0].x3 +
- state->affine[3] * bpath_def->bpath[0].y3 + state->affine[5];
-
- for (i = 0; i < bpath_def->n_bpath - 1; i++)
- {
- lastx = x;
- lasty = y;
- x = nextx;
- y = nexty;
- nextx = state->affine[0] * bpath_def->bpath[i + 1].x3 +
- state->affine[2] * bpath_def->bpath[i + 1].y3 + state->affine[4];
- nexty = state->affine[1] * bpath_def->bpath[i + 1].x3 +
- state->affine[3] * bpath_def->bpath[i + 1].y3 + state->affine[5];
-
-
- if(bpath_def->bpath[i + 1].code == ART_MOVETO ||
- bpath_def->bpath[i + 1].code == ART_MOVETO_OPEN ||
- bpath_def->bpath[i + 1].code == ART_END)
- {
- if (endmarker)
- rsvg_marker_render (endmarker, x, y, atan2(y - lasty, x - lastx), linewidth, ctx);
- }
- else if (bpath_def->bpath[i].code == ART_MOVETO || bpath_def->bpath[i].code == ART_MOVETO_OPEN)
- {
- if (startmarker)
- rsvg_marker_render (startmarker, x, y, atan2(nexty - y, nextx - x), linewidth, ctx);
- }
- else
- {
- if (middlemarker)
- {
- double xdifin, ydifin, xdifout, ydifout, intot, outtot, angle;
-
- xdifin = x - lastx;
- ydifin = y - lasty;
- xdifout = nextx - x;
- ydifout = nexty - y;
-
- intot = sqrt(xdifin * xdifin + ydifin * ydifin);
- outtot = sqrt(xdifout * xdifout + ydifout * ydifout);
-
- xdifin /= intot;
- ydifin /= intot;
- xdifout /= outtot;
- ydifout /= outtot;
-
- angle = atan2((ydifin + ydifout) / 2, (xdifin + xdifout) / 2);
- rsvg_marker_render (middlemarker, x, y, angle, linewidth, ctx);
- }
- }
- }
-}
-
-void
-rsvg_render_path(DrawingCtx *ctx, const char *d)
-{
- RsvgBpathDef *bpath_def;
-
- bpath_def = rsvg_parse_path (d);
- rsvg_bpath_def_art_finish (bpath_def);
-
- rsvg_render_bpath (ctx, bpath_def->bpath);
-
- rsvg_render_markers(bpath_def, ctx);
-
- rsvg_bpath_def_free (bpath_def);
-}
-
-ArtSVP *
-rsvg_render_path_as_svp(DrawingCtx *ctx, const char *d)
-{
- RsvgBpathDef *bpath_def;
- ArtSVP * output;
-
- bpath_def = rsvg_parse_path (d);
- rsvg_bpath_def_art_finish (bpath_def);
-
- output = rsvg_render_bpath_into_svp (ctx, bpath_def->bpath);
-
- rsvg_bpath_def_free (bpath_def);
- return output;
-}
-
-void
-rsvg_defs_drawable_draw (RsvgDefsDrawable * self, DrawingCtx *ctx,
- int dominate)
-{
- self->draw(self, ctx, dominate);
-}
-
-ArtSVP *
-rsvg_defs_drawable_draw_as_svp (RsvgDefsDrawable * self, DrawingCtx *ctx,
- int dominate)
-{
- return self->draw_as_svp(self, ctx, dominate);
-}
-
static void
rsvg_defs_drawable_path_free (RsvgDefVal *self)
{
@@ -563,7 +85,7 @@ rsvg_defs_drawable_path_free (RsvgDefVal *self)
}
static void
-rsvg_defs_drawable_path_draw (RsvgDefsDrawable * self, DrawingCtx *ctx,
+rsvg_defs_drawable_path_draw (RsvgDefsDrawable * self, RsvgDrawingCtx *ctx,
int dominate)
{
RsvgDefsDrawablePath *path = (RsvgDefsDrawablePath*)self;
@@ -575,7 +97,7 @@ rsvg_defs_drawable_path_draw (RsvgDefsDrawable * self, DrawingCtx *ctx,
}
static ArtSVP *
-rsvg_defs_drawable_path_draw_as_svp (RsvgDefsDrawable * self, DrawingCtx *ctx,
+rsvg_defs_drawable_path_draw_as_svp (RsvgDefsDrawable * self, RsvgDrawingCtx *ctx,
int dominate)
{
RsvgDefsDrawablePath *path = (RsvgDefsDrawablePath*)self;
@@ -586,239 +108,6 @@ rsvg_defs_drawable_path_draw_as_svp (RsvgDefsDrawable * self, DrawingCtx *ctx,
}
-static void
-rsvg_defs_drawable_group_free (RsvgDefVal *self)
-{
- RsvgDefsDrawableGroup *z = (RsvgDefsDrawableGroup *)self;
- rsvg_state_finalize (&z->super.state);
- g_ptr_array_free(z->children, TRUE);
- g_free (z);
-}
-
-static void
-rsvg_defs_drawable_group_draw (RsvgDefsDrawable * self, DrawingCtx *ctx,
- int dominate)
-{
- RsvgDefsDrawableGroup *group = (RsvgDefsDrawableGroup*)self;
- guint i;
-
- rsvg_state_reinherit_top(ctx, &self->state, dominate);
-
- rsvg_push_discrete_layer (ctx);
-
- for (i = 0; i < group->children->len; i++)
- {
- rsvg_state_push(ctx);
-
- rsvg_defs_drawable_draw (g_ptr_array_index(group->children, i),
- ctx, 0);
-
- rsvg_state_pop(ctx);
- }
-
- rsvg_pop_discrete_layer (ctx);
-}
-
-static ArtSVP *
-rsvg_defs_drawable_group_draw_as_svp (RsvgDefsDrawable * self, DrawingCtx *ctx,
- int dominate)
-{
- RsvgDefsDrawableGroup *group = (RsvgDefsDrawableGroup*)self;
- guint i;
- ArtSVP *svp1, *svp2, *svp3;
-
- svp1 = NULL;
-
- rsvg_state_reinherit_top(ctx, &self->state, dominate);
-
- for (i = 0; i < group->children->len; i++)
- {
- rsvg_state_push(ctx);
-
- svp2 = rsvg_defs_drawable_draw_as_svp (g_ptr_array_index(group->children, i),
- ctx, 0);
- if (svp1 != NULL)
- {
- svp3 = art_svp_union(svp2, svp1);
- art_free(svp1);
- svp1 = svp3;
- }
- else
- svp1 = svp2;
-
- rsvg_state_pop(ctx);
- }
- return svp1;
-}
-
-static void
-rsvg_defs_drawable_use_free (RsvgDefVal *self)
-{
- RsvgDefsDrawableUse *z = (RsvgDefsDrawableUse *)self;
- rsvg_state_finalize (&z->super.state);
- g_free (z);
-}
-
-static RsvgDefsDrawable *
-rsvg_defs_drawable_use_resolve(RsvgDefsDrawableUse * self, DrawingCtx *ctx, double * affine_out)
-{
- double affine[6];
- double x, y, width, height;
- x = self->x;
- y = self->y;
- width = self->w;
- height = self->h;
-
- RsvgDefVal * parent = rsvg_defs_lookup (ctx->defs, self->href->str);
- if (parent != NULL)
- switch(parent->type)
- {
- case RSVG_DEF_PATH:
- {
-
- art_affine_translate(affine, x, y);
- art_affine_multiply(affine_out, affine, affine_out);
- return (RsvgDefsDrawable *)parent;
- }
- case RSVG_DEF_SYMBOL:
- {
- RsvgDefsDrawable *drawable =
- (RsvgDefsDrawable*)parent;
- RsvgDefsDrawableSymbol *symbol =
- (RsvgDefsDrawableSymbol*)parent;
-
- if (symbol->has_vbox){
- rsvg_preserve_aspect_ratio
- (symbol->preserve_aspect_ratio,
- symbol->width, symbol->height,
- &width, &height, &x, &y);
- art_affine_translate(affine, x, y);
- art_affine_multiply(affine_out, affine, affine_out);
-
- art_affine_scale(affine, width / symbol->width,
- height / symbol->height);
- art_affine_multiply(affine_out, affine, affine_out);
- art_affine_translate(affine, -symbol->x,
- -symbol->y);
- art_affine_multiply(affine_out, affine, affine_out);
- }
- else {
- art_affine_translate(affine, x, y);
- art_affine_multiply(affine_out, affine, affine_out);
- }
-
- return drawable;
- }
- default:
- break;
- }
- return NULL;
-}
-
-static void
-rsvg_defs_drawable_use_draw (RsvgDefsDrawable * self, DrawingCtx *ctx,
- int dominate)
-{
- RsvgState *state = rsvg_state_current (ctx);
- RsvgDefsDrawableUse *use = (RsvgDefsDrawableUse*)self;
- RsvgDefsDrawable * child;
-
- rsvg_state_reinherit_top(ctx, &self->state, dominate);
-
- child = rsvg_defs_drawable_use_resolve(use, ctx, rsvg_state_current(ctx)->affine);
-
- if (state->opacity != 0xff || rsvg_needs_discrete_layer(state))
- rsvg_push_discrete_layer (ctx);
- rsvg_state_push(ctx);
-
- rsvg_defs_drawable_draw (child, ctx, 1);
-
- rsvg_state_pop(ctx);
-
- if (state->opacity != 0xff || rsvg_needs_discrete_layer(state))
- rsvg_pop_discrete_layer (ctx);
-}
-
-static ArtSVP *
-rsvg_defs_drawable_use_draw_as_svp (RsvgDefsDrawable * self, DrawingCtx *ctx,
- int dominate)
-{
- RsvgDefsDrawableUse *use = (RsvgDefsDrawableUse*)self;
- ArtSVP * svp;
- RsvgDefsDrawable * child;
-
- child = rsvg_defs_drawable_use_resolve(use, ctx, rsvg_state_current(ctx)->affine);
-
- rsvg_state_reinherit_top(ctx, &self->state, dominate);
-
- rsvg_state_push(ctx);
-
- svp = rsvg_defs_drawable_draw_as_svp (child, ctx, 1);
-
- rsvg_state_pop(ctx);
-
- return svp;
-}
-
-void
-rsvg_defs_drawable_group_pack (RsvgDefsDrawableGroup *self, RsvgDefsDrawable *child)
-{
- if (self == NULL)
- return;
- g_ptr_array_add(self->children, child);
-}
-
-RsvgDefsDrawable *
-rsvg_push_part_def_group (RsvgHandle *ctx, const char * id,
- RsvgState tempstate)
-{
- RsvgDefsDrawableGroup *group;
-
- group = g_new (RsvgDefsDrawableGroup, 1);
- group->children = g_ptr_array_new();
- group->super.state = tempstate;
-
- group->super.super.type = RSVG_DEF_PATH;
- group->super.super.free = rsvg_defs_drawable_group_free;
- group->super.draw = rsvg_defs_drawable_group_draw;
- group->super.draw_as_svp = rsvg_defs_drawable_group_draw_as_svp;
-
- rsvg_defs_set (ctx->defs, id, &group->super.super);
-
- group->super.parent = (RsvgDefsDrawable *)ctx->current_defs_group;
-
- ctx->current_defs_group = group;
-
- return &group->super;
-}
-
-RsvgDefsDrawable *
-rsvg_push_def_group (RsvgHandle *ctx, const char * id,
- RsvgState state)
-{
- RsvgDefsDrawable * group;
-
- group = rsvg_push_part_def_group (ctx, id, state);
-
- if (group->parent != NULL)
- rsvg_defs_drawable_group_pack((RsvgDefsDrawableGroup *)group->parent,
- group);
-
- return group;
-}
-
-void
-rsvg_pop_def_group (RsvgHandle *ctx)
-{
- RsvgDefsDrawableGroup * group;
-
- group = (RsvgDefsDrawableGroup *)ctx->current_defs_group;
- if (group == NULL)
- return;
- ctx->current_defs_group = group->super.parent;
-
-}
-
void
rsvg_handle_path (RsvgHandle *ctx, const char * d, const char * id, RsvgState state)
{
@@ -1348,1329 +637,3 @@ rsvg_start_ellipse (RsvgHandle *ctx, RsvgPropertyBag *atts)
rsvg_handle_path (ctx, d->str, id, state);
g_string_free (d, TRUE);
}
-
-static const char s_UTF8_B64Alphabet[64] = {
- 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, /* A-Z */
- 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, /* a-z */
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, /* 0-9 */
- 0x2b, /* + */
- 0x2f /* / */
-};
-static const char utf8_b64_pad = 0x3d;
-
-static gboolean b64_decode_char (char c, int * b64)
-{
- if ((c >= 0x41) && (c <= 0x5a))
- {
- *b64 = c - 0x41;
- return TRUE;
- }
- if ((c >= 0x61) && (c <= 0x7a))
- {
- *b64 = c - (0x61 - 26);
- return TRUE;
- }
- if ((c >= 0x30) && (c <= 0x39))
- {
- *b64 = c + (52 - 0x30);
- return TRUE;
- }
- if (c == 0x2b)
- {
- *b64 = 62;
- return TRUE;
- }
- if (c == 0x2f)
- {
- *b64 = 63;
- return TRUE;
- }
- return FALSE;
-}
-
-static gboolean utf8_base64_decode(guchar ** binptr, size_t * binlen, const char * b64ptr, size_t b64len)
-{
- gboolean decoded = TRUE;
- gboolean padding = FALSE;
-
- int i = 0;
- glong ucs4_len, j;
-
- unsigned char byte1 = 0;
- unsigned char byte2;
-
- gunichar ucs4, * ucs4_str;
-
- if (b64len == 0)
- return TRUE;
-
- if ((binptr == 0) || (b64ptr == 0))
- return FALSE;
-
- ucs4_str = g_utf8_to_ucs4_fast(b64ptr, b64len, &ucs4_len);
-
- for(j = 0; j < ucs4_len; j++)
- {
- ucs4 = ucs4_str[j];
- if ((ucs4 & 0x7f) == ucs4)
- {
- int b64;
- char c = (char)(ucs4);
-
- if (b64_decode_char (c, &b64))
- {
- if (padding || (*binlen == 0))
- {
- decoded = FALSE;
- break;
- }
-
- switch (i)
- {
- case 0:
- byte1 = (unsigned char)(b64) << 2;
- i++;
- break;
- case 1:
- byte2 = (unsigned char)(b64);
- byte1 |= byte2 >> 4;
- *(*binptr)++ = (char)(byte1);
- (*binlen)--;
- byte1 = (byte2 & 0x0f) << 4;
- i++;
- break;
- case 2:
- byte2 = (unsigned char)(b64);
- byte1 |= byte2 >> 2;
- *(*binptr)++ = (char)(byte1);
- (*binlen)--;
- byte1 = (byte2 & 0x03) << 6;
- i++;
- break;
- default:
- byte1 |= (unsigned char)(b64);
- *(*binptr)++ = (char)(byte1);
- (*binlen)--;
- i = 0;
- break;
- }
-
- if (!decoded)
- break;
-
- continue;
- }
- else if (c == utf8_b64_pad)
- {
- switch (i)
- {
- case 0:
- case 1:
- decoded = FALSE;
- break;
- case 2:
- if (*binlen == 0)
- decoded = FALSE;
- else
- {
- *(*binptr)++ = (char)(byte1);
- (*binlen)--;
- padding = TRUE;
- }
- i++;
- break;
- default:
- if (!padding)
- {
- if (*binlen == 0)
- decoded = FALSE;
- else
- {
- *(*binptr)++ = (char)(byte1);
- (*binlen)--;
- padding = TRUE;
- }
- }
- i = 0;
- break;
- }
- if (!decoded)
- break;
-
- continue;
- }
- }
- if (g_unichar_isspace (ucs4))
- continue;
-
- decoded = FALSE;
- break;
- }
-
- g_free(ucs4_str);
- return decoded;
-}
-
-static GByteArray *
-rsvg_acquire_base64_resource (const char *data,
- GError **error)
-{
- GByteArray * array;
-
- guchar *bufptr;
- size_t buffer_len, buffer_max_len, data_len;
-
- g_return_val_if_fail (data != NULL, NULL);
-
- while (*data) if (*data++ == ',') break;
-
- data_len = strlen(data);
-
- buffer_max_len = ((data_len >> 2) + 1) * 3;
- buffer_len = buffer_max_len;
-
- array = g_byte_array_sized_new (buffer_max_len);
- bufptr = array->data;
-
- if(!utf8_base64_decode(&bufptr, &buffer_len, data, data_len)) {
- g_byte_array_free (array, TRUE);
- return NULL;
- }
-
- array->len = buffer_max_len - buffer_len;
-
- return array;
-}
-
-gchar *
-rsvg_get_file_path (const gchar * filename, const gchar *basedir)
-{
- gchar *absolute_filename;
-
- if (g_path_is_absolute(filename)) {
- absolute_filename = g_strdup (filename);
- } else {
- gchar *tmpcdir;
-
- if (basedir)
- tmpcdir = g_path_get_dirname (basedir);
- else
- tmpcdir = g_get_current_dir ();
-
- absolute_filename = g_build_filename (tmpcdir, filename, NULL);
- g_free(tmpcdir);
- }
-
- return absolute_filename;
-}
-
-static GByteArray *
-rsvg_acquire_file_resource (const char *filename,
- const char *base_uri,
- GError **error)
-{
- GByteArray *array;
- gchar *path;
-
- guchar buffer [4096];
- int length;
- FILE *f;
-
- g_return_val_if_fail (filename != NULL, NULL);
-
- path = rsvg_get_file_path (filename, base_uri);
- f = fopen (path, "rb");
- g_free (path);
-
- if (!f) {
- g_set_error (error,
- G_FILE_ERROR,
- g_file_error_from_errno (errno),
- _("Failed to open file '%s': %s"),
- filename, g_strerror (errno));
- return NULL;
- }
-
- /* TODO: an optimization is to use the file's size */
- array = g_byte_array_new ();
-
- while (!feof (f)) {
- length = fread (buffer, 1, sizeof (buffer), f);
- if (length > 0)
- if (g_byte_array_append (array, buffer, length) == NULL) {
- fclose (f);
- g_byte_array_free (array, TRUE);
- return NULL;
- }
- }
-
- fclose (f);
-
- return array;
-}
-
-#ifdef HAVE_GNOME_VFS
-
-#include <libgnomevfs/gnome-vfs.h>
-
-static GByteArray *
-rsvg_acquire_vfs_resource (const char *filename,
- const char *base_uri,
- GError **error)
-{
- GByteArray *array;
-
- guchar buffer [4096];
- GnomeVFSFileSize length;
- GnomeVFSHandle *f = NULL;
- GnomeVFSResult res;
-
- g_return_val_if_fail (filename != NULL, NULL);
- g_return_val_if_fail (gnome_vfs_initialized (), NULL);
-
- res = gnome_vfs_open (&f, filename, GNOME_VFS_OPEN_READ);
-
- if (res != GNOME_VFS_OK) {
- if (base_uri) {
- GnomeVFSURI * base = gnome_vfs_uri_new (base_uri);
- if (base) {
- GnomeVFSURI * uri = gnome_vfs_uri_resolve_relative (base, filename);
- if (uri) {
- res = gnome_vfs_open_uri (&f, uri, GNOME_VFS_OPEN_READ);
- gnome_vfs_uri_unref (uri);
- }
-
- gnome_vfs_uri_unref (base);
- }
- }
- }
-
- if (res != GNOME_VFS_OK) {
- g_set_error (error, rsvg_error_quark (), (gint) res,
- gnome_vfs_result_to_string (res));
- return NULL;
- }
-
- /* TODO: an optimization is to use the file's size */
- array = g_byte_array_new ();
-
- while (TRUE) {
- res = gnome_vfs_read (f, buffer, sizeof (buffer), &length);
- if (res == GNOME_VFS_OK && length > 0) {
- if (g_byte_array_append (array, buffer, length) == NULL) {
- gnome_vfs_close (f);
- g_byte_array_free (array, TRUE);
- return NULL;
- }
- } else {
- break;
- }
- }
-
- gnome_vfs_close (f);
-
- return array;
-}
-
-#endif
-
-GByteArray *
-_rsvg_acquire_xlink_href_resource (const char *href,
- const char *base_uri,
- GError **err)
-{
- GByteArray * arr = NULL;
-
- if(!strncmp(href, "data:", 5))
- arr = rsvg_acquire_base64_resource (href, err);
-
- if(!arr)
- arr = rsvg_acquire_file_resource (href, base_uri, err);
-
-#ifdef HAVE_GNOME_VFS
- if(!arr)
- arr = rsvg_acquire_vfs_resource (href, base_uri, err);
-#else
-
- if(!arr)
- arr = rsvg_acquire_file_resource (href, base_uri, err);
-
-#endif
-
- return arr;
-}
-
-GdkPixbuf *
-rsvg_pixbuf_new_from_href (const char *href,
- const char *base_uri,
- GError **error)
-{
- GByteArray * arr;
-
- arr = _rsvg_acquire_xlink_href_resource (href, base_uri, error);
- if (arr) {
- GdkPixbufLoader *loader;
- GdkPixbuf * pixbuf = NULL;
- int res;
-
- loader = gdk_pixbuf_loader_new ();
-
- res = gdk_pixbuf_loader_write (loader, arr->data, arr->len, error);
- g_byte_array_free (arr, TRUE);
-
- if (!res) {
- gdk_pixbuf_loader_close (loader, NULL);
- g_object_unref (loader);
- return NULL;
- }
-
- if (!gdk_pixbuf_loader_close (loader, error)) {
- g_object_unref (loader);
- return NULL;
- }
-
- pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
-
- if (!pixbuf) {
- g_object_unref (loader);
- g_set_error (error,
- GDK_PIXBUF_ERROR,
- GDK_PIXBUF_ERROR_FAILED,
- _("Failed to load image '%s': reason not known, probably a corrupt image file"),
- href);
- return NULL;
- }
-
- g_object_ref (pixbuf);
-
- g_object_unref (loader);
-
- return pixbuf;
- }
-
- return NULL;
-}
-
-void
-rsvg_affine_image(GdkPixbuf *img, GdkPixbuf *intermediate,
- double * affine, double w, double h)
-{
- gdouble tmp_affine[6];
- gdouble inv_affine[6];
- gdouble raw_inv_affine[6];
- gint intstride;
- gint basestride;
- gint basex, basey;
- gdouble fbasex, fbasey;
- gdouble rawx, rawy;
- guchar * intpix;
- guchar * basepix;
- gint i, j, k, basebpp, ii, jj;
- gboolean has_alpha;
- gdouble pixsum[4];
- gboolean xrunnoff, yrunnoff;
- gint iwidth, iheight;
- gint width, height;
-
- width = gdk_pixbuf_get_width (img);
- height = gdk_pixbuf_get_height (img);
- iwidth = gdk_pixbuf_get_width (intermediate);
- iheight = gdk_pixbuf_get_height (intermediate);
-
- has_alpha = gdk_pixbuf_get_has_alpha (img);
-
- basestride = gdk_pixbuf_get_rowstride (img);
- intstride = gdk_pixbuf_get_rowstride (intermediate);
- basepix = gdk_pixbuf_get_pixels (img);
- intpix = gdk_pixbuf_get_pixels (intermediate);
- basebpp = has_alpha ? 4 : 3;
-
- art_affine_invert(raw_inv_affine, affine);
-
- /*scale to w and h*/
- tmp_affine[0] = (double)w;
- tmp_affine[3] = (double)h;
- tmp_affine[1] = tmp_affine[2] = tmp_affine[4] = tmp_affine[5] = 0;
- art_affine_multiply(tmp_affine, tmp_affine, affine);
-
- art_affine_invert(inv_affine, tmp_affine);
-
-
- /*apply the transformation*/
- for (i = 0; i < iwidth; i++)
- for (j = 0; j < iheight; j++)
- {
- fbasex = (inv_affine[0] * (double)i + inv_affine[2] * (double)j +
- inv_affine[4]) * (double)width;
- fbasey = (inv_affine[1] * (double)i + inv_affine[3] * (double)j +
- inv_affine[5]) * (double)height;
- basex = floor(fbasex);
- basey = floor(fbasey);
- rawx = raw_inv_affine[0] * i + raw_inv_affine[2] * j +
- raw_inv_affine[4];
- rawy = raw_inv_affine[1] * i + raw_inv_affine[3] * j +
- raw_inv_affine[5];
- if (rawx < 0 || rawy < 0 || rawx >= w ||
- rawy >= h || basex < 0 || basey < 0
- || basex >= width || basey >= height)
- {
- for (k = 0; k < 4; k++)
- intpix[i * 4 + j * intstride + k] = 0;
- }
- else
- {
- if (basex < 0 || basex + 1 >= width)
- xrunnoff = TRUE;
- else
- xrunnoff = FALSE;
- if (basey < 0 || basey + 1 >= height)
- yrunnoff = TRUE;
- else
- yrunnoff = FALSE;
- for (k = 0; k < basebpp; k++)
- pixsum[k] = 0;
- for (ii = 0; ii < 2; ii++)
- for (jj = 0; jj < 2; jj++)
- {
- if (basex + ii < 0 || basey + jj< 0
- || basex + ii >= width || basey + jj >= height)
- ;
- else
- {
- for (k = 0; k < basebpp; k++)
- {
- pixsum[k] +=
- (double)basepix[basebpp * (basex + ii) + (basey + jj) * basestride + k]
- * (xrunnoff ? 1 : fabs(fbasex - (double)(basex + (1 - ii))))
- * (yrunnoff ? 1 : fabs(fbasey - (double)(basey + (1 - jj))));
- }
- }
- }
- for (k = 0; k < basebpp; k++)
- intpix[i * 4 + j * intstride + k] = pixsum[k];
- if (!has_alpha)
- intpix[i * 4 + j * intstride + 3] = 255;
- }
-
- }
-}
-
-void rsvg_clip_image(GdkPixbuf *intermediate, ArtSVP *path);
-
-void
-rsvg_clip_image(GdkPixbuf *intermediate, ArtSVP *path)
-{
- gint intstride;
- gint basestride;
- guchar * intpix;
- guchar * basepix;
- gint i, j;
- gint width, height;
- GdkPixbuf * base;
-
- width = gdk_pixbuf_get_width (intermediate);
- height = gdk_pixbuf_get_height (intermediate);
-
- intstride = gdk_pixbuf_get_rowstride (intermediate);
- intpix = gdk_pixbuf_get_pixels (intermediate);
-
- base = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8,
- width, height);
- basestride = gdk_pixbuf_get_rowstride (base);
- basepix = gdk_pixbuf_get_pixels (base);
-
- art_rgb_svp_aa(path, 0, 0, width, height, 0xFFFFFF, 0x000000, basepix, basestride, NULL);
-
- for (i = 0; i < width; i++)
- for (j = 0; j < height; j++)
- {
- intpix[i * 4 + j * intstride + 3] = intpix[i * 4 + j * intstride + 3] *
- basepix[i * 3 + j * basestride] / 255;
- }
-}
-
-void
-rsvg_preserve_aspect_ratio(unsigned int aspect_ratio, double width,
- double height, double * w, double * h,
- double * x, double * y)
-{
- double neww, newh;
- if (aspect_ratio)
- {
- neww = *w;
- newh = *h;
- if (height * *w >
- width * *h != (aspect_ratio & RSVG_ASPECT_RATIO_SLICE))
- {
- neww = width * *h
- / height;
- }
- else
- {
- newh = height * *w
- / width;
- }
-
- if (aspect_ratio & RSVG_ASPECT_RATIO_XMIN_YMIN ||
- aspect_ratio & RSVG_ASPECT_RATIO_XMIN_YMID ||
- aspect_ratio & RSVG_ASPECT_RATIO_XMIN_YMAX)
- {}
- else if (aspect_ratio & RSVG_ASPECT_RATIO_XMID_YMIN ||
- aspect_ratio & RSVG_ASPECT_RATIO_XMID_YMID ||
- aspect_ratio & RSVG_ASPECT_RATIO_XMID_YMAX)
- *x -= (neww - *w) / 2;
- else
- *x -= neww - *w;
-
- if (aspect_ratio & RSVG_ASPECT_RATIO_XMIN_YMIN ||
- aspect_ratio & RSVG_ASPECT_RATIO_XMID_YMIN ||
- aspect_ratio & RSVG_ASPECT_RATIO_XMAX_YMIN)
- {}
- else if (aspect_ratio & RSVG_ASPECT_RATIO_XMIN_YMID ||
- aspect_ratio & RSVG_ASPECT_RATIO_XMID_YMID ||
- aspect_ratio & RSVG_ASPECT_RATIO_XMAX_YMID)
- *y -= (newh - *h) / 2;
- else
- *y -= newh - *h;
-
- *w = neww;
- *h = newh;
- }
-}
-
-static void
-rsvg_defs_drawable_image_free (RsvgDefVal * self)
-{
- RsvgDefsDrawableImage *z = (RsvgDefsDrawableImage *)self;
- rsvg_state_finalize (&z->super.state);
- g_object_unref (G_OBJECT (z->img));
- g_free (z);
-}
-
-static void
-rsvg_defs_drawable_image_draw (RsvgDefsDrawable * self, DrawingCtx *ctx,
- int dominate)
-{
- RsvgDefsDrawableImage *z = (RsvgDefsDrawableImage *)self;
- double x = z->x, y = z->y, w = z->w, h = z->h;
- unsigned int aspect_ratio = z->preserve_aspect_ratio;
- ArtIRect temprect;
- GdkPixbuf *img = z->img;
- int i, j;
- double tmp_affine[6];
- double tmp_tmp_affine[6];
- RsvgState *state = rsvg_state_current(ctx);
- GdkPixbuf *intermediate;
- double basex, basey;
- ArtSVP * temppath;
-
- rsvg_state_reinherit_top(ctx, &self->state, dominate);
-
- for (i = 0; i < 6; i++)
- tmp_affine[i] = state->affine[i];
-
- if (!z->overflow && (aspect_ratio & RSVG_ASPECT_RATIO_SLICE)){
- temppath = rsvg_rect_clip_path(x, y, w, h, ctx);
- state->clip_path_loaded = TRUE;
- state->clippath = rsvg_clip_path_merge(temppath,
- state->clippath, 'i');
- }
-
- rsvg_preserve_aspect_ratio(aspect_ratio, (double)gdk_pixbuf_get_width(img),
- (double)gdk_pixbuf_get_height(img), &w, &h,
- &x, &y);
-
- /*translate to x and y*/
- tmp_tmp_affine[0] = tmp_tmp_affine[3] = 1;
- tmp_tmp_affine[1] = tmp_tmp_affine[2] = 0;
- tmp_tmp_affine[4] = x;
- tmp_tmp_affine[5] = y;
-
- art_affine_multiply(tmp_affine, tmp_tmp_affine, tmp_affine);
-
- intermediate = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1, 8,
- gdk_pixbuf_get_width (ctx->pixbuf),
- gdk_pixbuf_get_height (ctx->pixbuf));
-
- if (!intermediate)
- {
- g_object_unref (G_OBJECT (img));
- return;
- }
-
- rsvg_affine_image(img, intermediate, tmp_affine, w, h);
-
- rsvg_push_discrete_layer(ctx);
-
- if (state->clippath)
- {
- rsvg_clip_image(intermediate, state->clippath);
- }
-
- /*slap it down*/
- rsvg_alpha_blt (intermediate, 0, 0,
- gdk_pixbuf_get_width (intermediate),
- gdk_pixbuf_get_height (intermediate),
- ctx->pixbuf,
- 0, 0);
-
- temprect.x0 = gdk_pixbuf_get_width (intermediate);
- temprect.y0 = gdk_pixbuf_get_height (intermediate);
- temprect.x1 = 0;
- temprect.y1 = 0;
-
- for (i = 0; i < 2; i++)
- for (j = 0; j < 2; j++)
- {
- basex = tmp_affine[0] * w * i + tmp_affine[2] * h * j + tmp_affine[4];
- basey = tmp_affine[1] * w * i + tmp_affine[3] * h * j + tmp_affine[5];
- temprect.x0 = MIN(basex, temprect.x0);
- temprect.y0 = MIN(basey, temprect.y0);
- temprect.x1 = MAX(basex, temprect.x1);
- temprect.y1 = MAX(basey, temprect.y1);
- }
-
- art_irect_union(&ctx->bbox, &ctx->bbox, &temprect);
- rsvg_pop_discrete_layer(ctx);
-
- g_object_unref (G_OBJECT (intermediate));
-}
-
-void
-rsvg_start_image (RsvgHandle *ctx, RsvgPropertyBag *atts)
-{
- double x = 0., y = 0., w = -1., h = -1., font_size;
- const char * href = NULL;
- const char * klazz = NULL, * id = NULL, *value;
- int aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
- GdkPixbuf *img;
- GError *err = NULL;
- RsvgState state;
- RsvgDefsDrawableImage *image;
- gboolean overflow = FALSE;
- rsvg_state_init(&state);
- font_size = rsvg_state_current_font_size(ctx);
-
- if (rsvg_property_bag_size (atts))
- {
- if ((value = rsvg_property_bag_lookup (atts, "x")))
- x = rsvg_css_parse_normalized_length (value, ctx->dpi_x, (gdouble)ctx->width, font_size);
- if ((value = rsvg_property_bag_lookup (atts, "y")))
- y = rsvg_css_parse_normalized_length (value, ctx->dpi_y, (gdouble)ctx->height, font_size);
- if ((value = rsvg_property_bag_lookup (atts, "width")))
- w = rsvg_css_parse_normalized_length (value, ctx->dpi_x, (gdouble)ctx->width, font_size);
- if ((value = rsvg_property_bag_lookup (atts, "height")))
- h = rsvg_css_parse_normalized_length (value, ctx->dpi_y, (gdouble)ctx->height, font_size);
- /* path is used by some older adobe illustrator versions */
- if ((value = rsvg_property_bag_lookup (atts, "path")) || (value = rsvg_property_bag_lookup (atts, "xlink:href")))
- href = value;
- if ((value = rsvg_property_bag_lookup (atts, "class")))
- klazz = value;
- if ((value = rsvg_property_bag_lookup (atts, "id")))
- id = value;
- if ((value = rsvg_property_bag_lookup (atts, "preserveAspectRatio")))
- aspect_ratio = rsvg_css_parse_aspect_ratio (value);
- if ((value = rsvg_property_bag_lookup (atts, "overflow")))
- overflow = rsvg_css_parse_overflow(value);
-
- rsvg_parse_style_attrs (ctx, &state, "image", klazz, id, atts);
- }
-
- if (!href || w <= 0. || h <= 0.)
- return;
-
- /*hmm, passing the error thingie into the next thing makes it screw up when using vfs*/
- img = rsvg_pixbuf_new_from_href (href, rsvg_handle_get_base_uri (ctx), NULL);
-
- if (!img)
- {
- if (err)
- {
- g_warning (_("Couldn't load image: %s\n"), err->message);
- g_error_free (err);
- }
- return;
- }
-
- image = g_new (RsvgDefsDrawableImage, 1);
- image->img = img;
- image->preserve_aspect_ratio = aspect_ratio;
- image->x = x;
- image->y = y;
- image->w = w;
- image->h = h;
- image->overflow = overflow;
- image->super.state = state;
- image->super.super.type = RSVG_DEF_PATH;
- image->super.super.free = rsvg_defs_drawable_image_free;
- image->super.draw = rsvg_defs_drawable_image_draw;
- rsvg_defs_set (ctx->defs, id, &image->super.super);
-
- image->super.parent = (RsvgDefsDrawable *)ctx->current_defs_group;
- if (image->super.parent != NULL)
- rsvg_defs_drawable_group_pack((RsvgDefsDrawableGroup *)image->super.parent,
- &image->super);
-
-}
-
-void
-rsvg_start_use (RsvgHandle *ctx, RsvgPropertyBag *atts)
-{
- const char * klazz = NULL, *id = NULL, *xlink_href = NULL, *value;
- double x = 0, y = 0, width = 0, height = 0, font_size;
- gboolean got_width = FALSE, got_height = FALSE;
- RsvgState state;
- rsvg_state_init(&state);
- font_size = rsvg_state_current_font_size(ctx);
-
- if (rsvg_property_bag_size(atts))
- {
- if ((value = rsvg_property_bag_lookup (atts, "x")))
- x = rsvg_css_parse_normalized_length (value, ctx->dpi_x, (gdouble)ctx->width, font_size);
- if ((value = rsvg_property_bag_lookup (atts, "y")))
- y = rsvg_css_parse_normalized_length (value, ctx->dpi_y, (gdouble)ctx->height, font_size);
- if ((value = rsvg_property_bag_lookup (atts, "width"))) {
- width = rsvg_css_parse_normalized_length (value, ctx->dpi_x, (gdouble)ctx->height, font_size);
- got_width = TRUE;
- }
- if ((value = rsvg_property_bag_lookup (atts, "height"))) {
- height = rsvg_css_parse_normalized_length (value, ctx->dpi_y, (gdouble)ctx->height, font_size);
- got_height = TRUE;
- }
- if ((value = rsvg_property_bag_lookup (atts, "class")))
- klazz = value;
- if ((value = rsvg_property_bag_lookup (atts, "id")))
- id = value;
- if ((value = rsvg_property_bag_lookup (atts, "xlink:href")))
- xlink_href = value;
- }
- if (!xlink_href)
- return;
-
- rsvg_parse_style_attrs (ctx, &state, "use", klazz, id, atts);
-
- /* < 0 is an error, 0 disables rendering. TODO: handle positive values correctly */
- if (got_width || got_height)
- if (width <= 0. || height <= 0.)
- return;
-
- RsvgDefsDrawableUse * use;
- use = g_new (RsvgDefsDrawableUse, 1);
- use->super.state = state;
- use->super.super.type = RSVG_DEF_PATH;
- use->super.super.free = rsvg_defs_drawable_use_free;
- use->super.draw = rsvg_defs_drawable_use_draw;
- use->super.draw_as_svp = rsvg_defs_drawable_use_draw_as_svp;
- use->x = x;
- use->y = y;
- use->w = width;
- use->h = height;
- use->href = g_string_new(xlink_href);
- rsvg_defs_set (ctx->defs, id, &use->super.super);
-
- use->super.parent = (RsvgDefsDrawable *)ctx->current_defs_group;
- if (use->super.parent != NULL)
- rsvg_defs_drawable_group_pack((RsvgDefsDrawableGroup *)use->super.parent,
- &use->super);
-}
-
-static void
-rsvg_defs_drawable_symbol_free (RsvgDefVal *self)
-{
- RsvgDefsDrawableGroup *z = (RsvgDefsDrawableGroup *)self;
- rsvg_state_finalize (&z->super.state);
- g_ptr_array_free(z->children, TRUE);
- g_free (z);
-}
-
-static void
-rsvg_defs_drawable_symbol_draw (RsvgDefsDrawable * self, DrawingCtx *ctx,
- int dominate)
-{
- RsvgDefsDrawableSymbol * sself;
- RsvgState *state;
- ArtSVP * temppath = NULL;
- RsvgDefsDrawableGroup *group = (RsvgDefsDrawableGroup*)self;
- guint i;
- sself = (RsvgDefsDrawableSymbol *)self;
-
- rsvg_state_reinherit_top(ctx, &self->state, dominate);
-
- rsvg_push_discrete_layer (ctx);
-
- state = rsvg_state_current (ctx);
-
- if (!sself->overflow){
- temppath = rsvg_rect_clip_path(sself->x,
- sself->y,
- sself->width,
- sself->height,
- ctx);
- state->clip_path_loaded = TRUE;
- state->clippath = rsvg_clip_path_merge(temppath,
- state->clippath, 'i');
- }
-
- for (i = 0; i < group->children->len; i++)
- {
- rsvg_state_push(ctx);
-
- rsvg_defs_drawable_draw (g_ptr_array_index(group->children, i),
- ctx, 0);
-
- rsvg_state_pop(ctx);
- }
-
- rsvg_pop_discrete_layer (ctx);
-}
-
-
-void
-rsvg_start_symbol(RsvgHandle *ctx, RsvgPropertyBag *atts)
-{
- RsvgDefsDrawableSymbol *symbol;
- RsvgDefsDrawableGroup *group;
- RsvgState state;
- const char * klazz = NULL, *id = NULL, *value;
-
- rsvg_state_init(&state);
- symbol = g_new (RsvgDefsDrawableSymbol, 1);
- group = &symbol->super;
- symbol->has_vbox = 0;
- symbol->overflow = 0;
- symbol->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
-
- if (rsvg_property_bag_size(atts))
- {
- if ((value = rsvg_property_bag_lookup (atts, "class")))
- klazz = value;
- if ((value = rsvg_property_bag_lookup (atts, "id")))
- id = value;
- if ((value = rsvg_property_bag_lookup (atts, "viewBox")))
- {
- symbol->has_vbox = rsvg_css_parse_vbox (value,
- &symbol->x,
- &symbol->y,
- &symbol->width,
- &symbol->height);
- if (symbol->has_vbox)
- {
- ctx->width = symbol->width;
- ctx->height = symbol->height;
- }
- }
- if ((value = rsvg_property_bag_lookup (atts, "preserveAspectRatio")))
- symbol->preserve_aspect_ratio = rsvg_css_parse_aspect_ratio (value);
- if ((value = rsvg_property_bag_lookup (atts, "overflow")))
- symbol->overflow = rsvg_css_parse_overflow(value);
- }
-
- rsvg_parse_style_attrs (ctx, &state, "symbol", klazz, id, atts);
- group->children = g_ptr_array_new();
- group->super.state = state;
- group->super.super.type = RSVG_DEF_SYMBOL;
- group->super.super.free = rsvg_defs_drawable_symbol_free;
- group->super.draw = rsvg_defs_drawable_symbol_draw;
- group->super.draw_as_svp = rsvg_defs_drawable_group_draw_as_svp;
-
- rsvg_defs_set (ctx->defs, id, &group->super.super);
-
- group->super.parent = (RsvgDefsDrawable *)ctx->current_defs_group;
-
- ctx->current_defs_group = group;
-}
-
-static void
-rsvg_marker_free(RsvgDefVal* self)
-{
- RsvgMarker *marker;
- marker = (RsvgMarker *)self;
- g_free(self);
-}
-
-void
-rsvg_start_marker (RsvgHandle *ctx, RsvgPropertyBag *atts)
-{
- const char *klazz = NULL, *id = NULL, *value;
- RsvgMarker *marker;
- double font_size;
- double x = 0., y = 0., w = 0., h = 0.;
- double vbx = 0., vby = 0., vbw = 1., vbh = 1.;
- gboolean obj_bbox = TRUE;
- RsvgState state;
- gboolean got_x, got_y, got_bbox, got_vbox, got_width, got_height;
- got_x = got_y = got_bbox = got_vbox = got_width = got_height = FALSE;
-
- font_size = rsvg_state_current_font_size (ctx);
- marker = g_new (RsvgMarker, 1);
-
- rsvg_state_init(&state);
-
- marker->orient = 0;
- marker->orientAuto = FALSE;
- marker->overflow = FALSE;
- marker->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
-
- if (rsvg_property_bag_size (atts))
- {
- if ((value = rsvg_property_bag_lookup (atts, "id")))
- id = value;
- if ((value = rsvg_property_bag_lookup (atts, "class")))
- klazz = value;
- if ((value = rsvg_property_bag_lookup (atts, "viewBox")))
- {
- got_vbox = rsvg_css_parse_vbox (value, &vbx, &vby,
- &vbw, &vbh);
- }
- if ((value = rsvg_property_bag_lookup (atts, "refX"))) {
- x = rsvg_css_parse_normalized_length (value, ctx->dpi_x, 1, font_size);
- got_x = TRUE;
- }
- if ((value = rsvg_property_bag_lookup (atts, "refY"))) {
- y = rsvg_css_parse_normalized_length (value, ctx->dpi_y, 1, font_size);
- got_y = TRUE;
- }
- if ((value = rsvg_property_bag_lookup (atts, "markerWidth"))) {
- w = rsvg_css_parse_normalized_length (value, ctx->dpi_x, 1, font_size);
- got_width = TRUE;
- }
- if ((value = rsvg_property_bag_lookup (atts, "markerHeight"))) {
- h = rsvg_css_parse_normalized_length (value, ctx->dpi_y, 1, font_size);
- got_height = TRUE;
- }
- if ((value = rsvg_property_bag_lookup (atts, "orient"))) {
- if (!strcmp (value, "auto"))
- marker->orientAuto = TRUE;
- else
- marker->orient = rsvg_css_parse_angle(value);
- }
- if ((value = rsvg_property_bag_lookup (atts, "markerUnits"))) {
- if (!strcmp (value, "userSpaceOnUse"))
- obj_bbox = FALSE;
- else
- obj_bbox = TRUE;
- got_bbox = TRUE;
- }
- if ((value = rsvg_property_bag_lookup (atts, "preserveAspectRatio")))
- marker->preserve_aspect_ratio = rsvg_css_parse_aspect_ratio (value);
- if ((value = rsvg_property_bag_lookup (atts, "overflow")))
- marker->overflow = rsvg_css_parse_overflow(value);
- }
-
- if (got_x)
- marker->refX = x;
- else
- marker->refX = 0;
-
- if (got_y)
- marker->refY = y;
- else
- marker->refY = 0;
-
- if (got_width)
- marker->width = w;
- else
- marker->width = 1;
-
- if (got_height)
- marker->height = h;
- else
- marker->height = 1;
-
- if (got_bbox)
- marker->bbox = obj_bbox;
- else
- marker->bbox = TRUE;
-
- if (got_vbox)
- {
- marker->vbx = vbx;
- marker->vby = vby;
- marker->vbw = vbw;
- marker->vbh = vbh;
- marker->vbox = TRUE;
- ctx->width = vbw;
- ctx->height = vbh;
- }
- else
- marker->vbox = FALSE;
-
- /* set up the defval stuff */
- marker->super.type = RSVG_DEF_MARKER;
-
- marker->contents = (RsvgDefsDrawable *)rsvg_push_part_def_group(ctx, NULL, state);
-
- rsvg_state_init (&marker->contents->state);
- marker->super.free = rsvg_marker_free;
-
- rsvg_defs_set (ctx->defs, id, &marker->super);
-}
-
-void
-rsvg_marker_render (RsvgMarker *self, gdouble x, gdouble y, gdouble orient, gdouble linewidth, DrawingCtx *ctx)
-{
- gdouble affine[6];
- gdouble taffine[6];
- int i;
- gdouble rotation;
- RsvgState * state = rsvg_state_current(ctx);
-
- if (self->bbox) {
- art_affine_scale(affine,linewidth * state->affine[0],
- linewidth * state->affine[3]);
- } else {
- for (i = 0; i < 6; i++)
- affine[i] = state->affine[i];
- }
-
- if (self->vbox) {
-
- double w, h, x, y;
- w = self->width;
- h = self->height;
- x = 0;
- y = 0;
-
- rsvg_preserve_aspect_ratio(self->preserve_aspect_ratio,
- self->vbw, self->vbh,
- &w, &h, &x, &y);
-
- x -= self->vbx / self->vbw;
- y -= self->vby / self->vbh;
-
- taffine[0] = w / self->vbw;
- taffine[1] = 0.;
- taffine[2] = 0.;
- taffine[3] = h / self->vbh;
- taffine[4] = x;
- taffine[5] = y;
- art_affine_multiply(affine, taffine, affine);
- }
-
- art_affine_translate(taffine, -self->refX, -self->refY);
-
- art_affine_multiply(affine, taffine, affine);
-
- if (self->orientAuto)
- rotation = orient * 180. / M_PI;
- else
- rotation = self->orient;
-
- art_affine_rotate(taffine, rotation);
-
- art_affine_multiply(affine, affine, taffine);
-
- art_affine_translate(taffine, x, y);
-
- art_affine_multiply(affine, affine, taffine);
-
- /*don't inherit anything from the current context*/
- rsvg_state_finalize(state);
- rsvg_state_init(state);
- rsvg_state_reassemble((RsvgDefsDrawable *)self->contents, state);
-
- rsvg_state_push(ctx);
- state = rsvg_state_current(ctx);
-
- for (i = 0; i < 6; i++)
- {
- state->affine[i] = affine[i];
- }
-
- rsvg_defs_drawable_draw (self->contents, ctx, 3);
-
- rsvg_state_pop(ctx);
-}
-
-RsvgDefVal *
-rsvg_marker_parse (const RsvgDefs * defs, const char *str)
-{
- if (!strncmp (str, "url(", 4))
- {
- const char *p = str + 4;
- int ix;
- char *name;
- RsvgDefVal *val;
-
- while (g_ascii_isspace (*p))
- p++;
-
- for (ix = 0; p[ix]; ix++)
- if (p[ix] == ')')
- break;
-
- if (p[ix] == ')')
- {
- name = g_strndup (p, ix);
- val = rsvg_defs_lookup (defs, name);
- g_free (name);
-
- if (val && val->type == RSVG_DEF_MARKER)
- return (RsvgDefVal *) val;
- }
- }
- return NULL;
-}
-
-static void
-rsvg_defs_drawable_svg_draw (RsvgDefsDrawable * self, DrawingCtx *ctx,
- int dominate)
-{
- RsvgDefsDrawableSvg * sself;
- RsvgState *state;
- ArtSVP * temppath = NULL;
- RsvgDefsDrawableGroup *group = (RsvgDefsDrawableGroup*)self;
- guint i;
- sself = (RsvgDefsDrawableSvg *)self;
-
- if (!sself->overflow)
- temppath = rsvg_rect_clip_path(sself->x,
- sself->y,
- sself->w,
- sself->h,
- ctx);
-
- rsvg_state_reinherit_top(ctx, &self->state, dominate);
-
- rsvg_push_discrete_layer (ctx);
-
- state = rsvg_state_current (ctx);
- if (temppath != NULL){
- state->clip_path_loaded = TRUE;
- state->clippath = rsvg_clip_path_merge(temppath,
- state->clippath, 'i');
- }
-
- for (i = 0; i < group->children->len; i++)
- {
- rsvg_state_push(ctx);
-
- rsvg_defs_drawable_draw (g_ptr_array_index(group->children, i),
- ctx, 0);
-
- rsvg_state_pop(ctx);
- }
-
- rsvg_pop_discrete_layer (ctx);
-}
-
-static void
-rsvg_defs_drawable_svg_free (RsvgDefVal *self)
-{
- RsvgDefsDrawableGroup *z = (RsvgDefsDrawableGroup *)self;
- rsvg_state_finalize (&z->super.state);
- g_ptr_array_free(z->children, TRUE);
- g_free (z);
-}
-
-void
-rsvg_start_sub_svg (RsvgHandle *ctx, RsvgPropertyBag *atts)
-{
- int width = -1, height = -1, x = -1, y = -1, i;
- double affine[6];
- const char * id, *value;
- double vbox_x = 0, vbox_y = 0, vbox_w = 0, vbox_h = 0;
- gboolean has_vbox = FALSE, overflow = 0;
- id = NULL;
- RsvgDefsDrawableSvg * svg;
- RsvgDefsDrawableGroup * group;
- RsvgState state;
- rsvg_state_init(&state);
-
- if (rsvg_property_bag_size (atts))
- {
- if ((value = rsvg_property_bag_lookup (atts, "viewBox")))
- {
- has_vbox = rsvg_css_parse_vbox (value, &vbox_x, &vbox_y,
- &vbox_w, &vbox_h);
- }
- if ((value = rsvg_property_bag_lookup (atts, "width")))
- width = rsvg_css_parse_normalized_length (value, ctx->dpi_x, ctx->width, 1);
- if ((value = rsvg_property_bag_lookup (atts, "height")))
- height = rsvg_css_parse_normalized_length (value, ctx->dpi_y, ctx->height, 1);
- if ((value = rsvg_property_bag_lookup (atts, "x")))
- x = rsvg_css_parse_normalized_length (value, ctx->dpi_x, ctx->width, 1);
- if ((value = rsvg_property_bag_lookup (atts, "y")))
- y = rsvg_css_parse_normalized_length (value, ctx->dpi_y, ctx->height, 1);
- if ((value = rsvg_property_bag_lookup (atts, "id")))
- id = value;
- if ((value = rsvg_property_bag_lookup (atts, "overflow")))
- overflow = rsvg_css_parse_overflow(value);
- }
-
- if (has_vbox)
- {
- affine[0] = width / vbox_w;
- affine[1] = 0;
- affine[2] = 0;
- affine[3] = height / vbox_h;
- affine[4] = x - vbox_x * width / vbox_w;
- affine[5] = y - vbox_y * height / vbox_h;
- for (i = 0; i < 6; i++)
- state.personal_affine[i] = affine[i];
- art_affine_multiply(state.affine, affine,
- state.affine);
- ctx->width = vbox_w;
- ctx->height = vbox_h;
- }
- else
- {
- affine[0] = 1;
- affine[1] = 0;
- affine[2] = 0;
- affine[3] = 1;
- affine[4] = x;
- affine[5] = y;
- for (i = 0; i < 6; i++)
- state.personal_affine[i] = affine[i];
- art_affine_multiply(state.affine, affine,
- state.affine);
- }
-
- svg = g_new (RsvgDefsDrawableSvg, 1);
- group = &svg->super;
- svg->has_vbox = has_vbox;
- svg->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
-
- svg->x = x; svg->y = y; svg->w = width; svg->h = height;
- svg->vbx = vbox_x; svg->vby = vbox_y; svg->vbw = vbox_w; svg->vbh = vbox_h;
- svg->overflow = overflow;
-
- group->children = g_ptr_array_new();
- group->super.state = state;
-
- group->super.super.type = RSVG_DEF_PATH;
- group->super.super.free = rsvg_defs_drawable_svg_free;
- group->super.draw = rsvg_defs_drawable_svg_draw;
- group->super.draw_as_svp = rsvg_defs_drawable_group_draw_as_svp;
-
- rsvg_defs_set (ctx->defs, id, &group->super.super);
-
- group->super.parent = (RsvgDefsDrawable *)ctx->current_defs_group;
-
- ctx->current_defs_group = group;
-
- if (group->super.parent != NULL)
- rsvg_defs_drawable_group_pack((RsvgDefsDrawableGroup *)group->super.parent,
- &group->super);
-
- ctx->nest_level++;
-}
-
-void
-rsvg_state_reassemble(RsvgDefsDrawable * self, RsvgState * state)
-{
- RsvgState store;
- if (self == NULL)
- {
- return;
- }
- rsvg_state_reassemble(self->parent, state);
-
- rsvg_state_clone (&store, &self->state);
- rsvg_state_reinherit(&store, state);
- rsvg_state_finalize(state);
- *state = store;
-}