Commit 6df53732 authored by Benjamin Otte's avatar Benjamin Otte

marker: Resolve lazily

And that concludes our rework of reference cylce detection. All code
that references other objects via IRIs will now call rsvg_acquire_node()
which itself avoids giving out the same node a second time until
rsvg_release_node() has been called.

This also means that rsvg_defs_lookup() is only used in two places now:
(1) by rsvg_acquire_node()
(2) by public API that allows operating on objects by id.
parent 9fc56102
......@@ -99,15 +99,23 @@ rsvg_new_marker (void)
return &marker->super;
}
void
rsvg_marker_render (RsvgMarker * self, gdouble xpos, gdouble ypos, gdouble orient, gdouble linewidth,
static void
rsvg_marker_render (const char * marker_name, gdouble xpos, gdouble ypos, gdouble orient, gdouble linewidth,
RsvgDrawingCtx * ctx)
{
RsvgMarker *self;
cairo_matrix_t affine, taffine;
unsigned int i;
gdouble rotation;
RsvgState *state = rsvg_current_state (ctx);
self = (RsvgMarker *) rsvg_acquire_node (ctx, marker_name);
if (self == NULL || RSVG_NODE_TYPE (&self->super) != RSVG_NODE_TYPE_MARKER)
{
rsvg_release_node (ctx, &self->super);
return;
}
cairo_matrix_init_translate (&taffine, xpos, ypos);
cairo_matrix_multiply (&affine, &taffine, &state->affine);
......@@ -191,23 +199,8 @@ rsvg_marker_render (RsvgMarker * self, gdouble xpos, gdouble ypos, gdouble orien
rsvg_state_pop (ctx);
if (self->vbox.active)
_rsvg_pop_view_box (ctx);
}
RsvgNode *
rsvg_marker_parse (const RsvgDefs * defs, const char *str)
{
char *name;
name = rsvg_get_url_string (str);
if (name) {
RsvgNode *val;
val = rsvg_defs_lookup (defs, name);
g_free (name);
if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_MARKER)
return val;
}
return NULL;
rsvg_release_node (ctx, (RsvgNode *) self);
}
void
......@@ -220,18 +213,18 @@ rsvg_render_markers (RsvgDrawingCtx * ctx,
cairo_path_data_type_t code, nextcode;
RsvgState *state;
RsvgMarker *startmarker;
RsvgMarker *middlemarker;
RsvgMarker *endmarker;
const char *startmarker;
const char *middlemarker;
const char *endmarker;
cairo_path_data_t *data, *nextdata, *end;
cairo_path_data_t nextp;
state = rsvg_current_state (ctx);
linewidth = _rsvg_css_normalize_length (&state->stroke_width, ctx, 'o');
startmarker = (RsvgMarker *) state->startMarker;
middlemarker = (RsvgMarker *) state->middleMarker;
endmarker = (RsvgMarker *) state->endMarker;
startmarker = state->startMarker;
middlemarker = state->middleMarker;
endmarker = state->endMarker;
if (linewidth == 0)
return;
......
......@@ -45,11 +45,6 @@ struct _RsvgMarker {
G_GNUC_INTERNAL
RsvgNode *rsvg_new_marker (void);
G_GNUC_INTERNAL
void rsvg_marker_render (RsvgMarker * self, gdouble xpos, gdouble ypos,
gdouble orient, gdouble linewidth, RsvgDrawingCtx * ctx);
G_GNUC_INTERNAL
RsvgNode *rsvg_marker_parse (const RsvgDefs * defs, const char *str);
G_GNUC_INTERNAL
void rsvg_render_markers (RsvgDrawingCtx *ctx, const cairo_path_t *path);
G_END_DECLS
......
......@@ -226,6 +226,9 @@ rsvg_state_clone (RsvgState * dst, const RsvgState * src)
dst->clip_path = g_strdup (src->clip_path);
dst->font_family = g_strdup (src->font_family);
dst->lang = g_strdup (src->lang);
dst->startMarker = g_strdup (src->startMarker);
dst->middleMarker = g_strdup (src->middleMarker);
dst->endMarker = g_strdup (src->endMarker);
rsvg_paint_server_ref (dst->fill);
rsvg_paint_server_ref (dst->stroke);
......@@ -315,16 +318,22 @@ rsvg_state_inherit_run (RsvgState * dst, const RsvgState * src,
dst->text_anchor = src->text_anchor;
if (function (dst->has_letter_spacing, src->has_letter_spacing))
dst->letter_spacing = src->letter_spacing;
if (function (dst->has_startMarker, src->has_startMarker))
dst->startMarker = src->startMarker;
if (function (dst->has_middleMarker, src->has_middleMarker))
dst->middleMarker = src->middleMarker;
if (function (dst->has_endMarker, src->has_endMarker))
dst->endMarker = src->endMarker;
if (function (dst->has_shape_rendering_type, src->has_shape_rendering_type))
dst->shape_rendering_type = src->shape_rendering_type;
if (function (dst->has_text_rendering_type, src->has_text_rendering_type))
dst->text_rendering_type = src->text_rendering_type;
if (function (dst->has_startMarker, src->has_startMarker)) {
g_free (dst->startMarker);
dst->startMarker = g_strdup (src->startMarker);
}
if (function (dst->has_middleMarker, src->has_middleMarker)) {
g_free (dst->middleMarker);
dst->middleMarker = g_strdup (src->middleMarker);
}
if (function (dst->has_endMarker, src->has_endMarker)) {
g_free (dst->endMarker);
dst->endMarker = g_strdup (src->endMarker);
}
if (function (dst->has_shape_rendering_type, src->has_shape_rendering_type))
dst->shape_rendering_type = src->shape_rendering_type;
if (function (dst->has_text_rendering_type, src->has_text_rendering_type))
dst->text_rendering_type = src->text_rendering_type;
if (function (dst->has_font_family, src->has_font_family)) {
g_free (dst->font_family); /* font_family is always set to something */
......@@ -455,6 +464,9 @@ rsvg_state_finalize (RsvgState * state)
g_free (state->clip_path);
g_free (state->font_family);
g_free (state->lang);
g_free (state->startMarker);
g_free (state->middleMarker);
g_free (state->endMarker);
rsvg_paint_server_unref (state->fill);
rsvg_paint_server_unref (state->stroke);
......@@ -773,13 +785,16 @@ rsvg_parse_style_pair (RsvgHandle * ctx,
state->stop_opacity = rsvg_css_parse_opacity (value);
}
} else if (g_str_equal (name, "marker-start")) {
state->startMarker = rsvg_marker_parse (ctx->priv->defs, value);
g_free (state->startMarker);
state->startMarker = rsvg_get_url_string (value);
state->has_startMarker = TRUE;
} else if (g_str_equal (name, "marker-mid")) {
state->middleMarker = rsvg_marker_parse (ctx->priv->defs, value);
g_free (state->middleMarker);
state->middleMarker = rsvg_get_url_string (value);
state->has_middleMarker = TRUE;
} else if (g_str_equal (name, "marker-end")) {
state->endMarker = rsvg_marker_parse (ctx->priv->defs, value);
g_free (state->endMarker);
state->endMarker = rsvg_get_url_string (value);
state->has_endMarker = TRUE;
} else if (g_str_equal (name, "stroke-miterlimit")) {
state->has_miter_limit = TRUE;
......
......@@ -167,9 +167,9 @@ struct _RsvgState {
guchar flood_opacity;
gboolean has_flood_opacity;
RsvgNode *startMarker;
RsvgNode *middleMarker;
RsvgNode *endMarker;
char *startMarker;
char *middleMarker;
char *endMarker;
gboolean has_startMarker;
gboolean has_middleMarker;
gboolean has_endMarker;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment