Exemplo n.º 1
0
static void
_rsvg_node_text_type_children (RsvgNode * self, RsvgDrawingCtx * ctx,
                               gdouble * x, gdouble * y, gboolean * lastwasspace)
{
    guint i;

    rsvg_push_discrete_layer (ctx);
    for (i = 0; i < self->children->len; i++) {
        RsvgNode *node = g_ptr_array_index (self->children, i);
        if (!strcmp (node->type->str, "RSVG_NODE_CHARS")) {
            RsvgNodeChars *chars = (RsvgNodeChars *) node;
            GString *str = _rsvg_text_chomp (rsvg_current_state (ctx), chars->contents, lastwasspace);
            rsvg_text_render_text (ctx, str->str, x, y);
            g_string_free (str, TRUE);
        } else if (!strcmp (node->type->str, "tspan")) {
            RsvgNodeText *tspan = (RsvgNodeText *) node;
            rsvg_state_push (ctx);
            _rsvg_node_text_type_tspan (tspan, ctx, x, y, lastwasspace);
            rsvg_state_pop (ctx);
        } else if (!strcmp (node->type->str, "tref")) {
            RsvgNodeTref *tref = (RsvgNodeTref *) node;
            _rsvg_node_text_type_tref (tref, ctx, x, y, lastwasspace);
        }
    }
    rsvg_pop_discrete_layer (ctx);
}
Exemplo n.º 2
0
static int
_rsvg_node_text_length_children (RsvgNode * self, RsvgDrawingCtx * ctx,
                                 gdouble * x, gboolean * lastwasspace)
{
    guint i;
    int out = FALSE;
    for (i = 0; i < self->children->len; i++) {
        RsvgNode *node = g_ptr_array_index (self->children, i);
        rsvg_state_push (ctx);
        rsvg_state_reinherit_top (ctx, node->state, 0);
        if (!strcmp (node->type->str, "RSVG_NODE_CHARS")) {
            RsvgNodeChars *chars = (RsvgNodeChars *) node;
            GString *str = _rsvg_text_chomp (rsvg_current_state (ctx), chars->contents, lastwasspace);
            *x += rsvg_text_length_text_as_string (ctx, str->str);
            g_string_free (str, TRUE);
        } else if (!strcmp (node->type->str, "tspan")) {
            RsvgNodeText *tspan = (RsvgNodeText *) node;
            out = _rsvg_node_text_length_tspan (tspan, ctx, x, lastwasspace);
        } else if (!strcmp (node->type->str, "tref")) {
            RsvgNodeTref *tref = (RsvgNodeTref *) node;
            out = _rsvg_node_text_length_tref (tref, ctx, x, lastwasspace);
        }
        rsvg_state_pop (ctx);
        if (out)
            break;
    }
    return out;
}
Exemplo n.º 3
0
/* generic function for drawing all of the children of a particular node */
void
_rsvg_node_draw_children (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    guint i;
    if (dominate != -1) {
        rsvg_state_reinherit_top (ctx, self->state, dominate);

        rsvg_push_discrete_layer (ctx);
    }
    for (i = 0; i < self->children->len; i++) {
        rsvg_state_push (ctx);
        rsvg_node_draw (g_ptr_array_index (self->children, i), ctx, 0);
        rsvg_state_pop (ctx);
    }
    if (dominate != -1)
        rsvg_pop_discrete_layer (ctx);
}
Exemplo n.º 4
0
static int
_rsvg_node_text_length_children (RsvgNode * self, RsvgDrawingCtx * ctx,
                                 gdouble * length, gboolean * lastwasspace,
                                 gboolean usetextonly)
{
    guint i;
    int out = FALSE;
    for (i = 0; i < self->children->len; i++) {
        RsvgNode *node = g_ptr_array_index (self->children, i);
        RsvgNodeType type = RSVG_NODE_TYPE (node);

        rsvg_state_push (ctx);
        rsvg_state_reinherit_top (ctx, node->state, 0);
        if (type == RSVG_NODE_TYPE_CHARS) {
            RsvgNodeChars *chars = (RsvgNodeChars *) node;
            GString *str = _rsvg_text_chomp (rsvg_current_state (ctx), chars->contents, lastwasspace);
            *length += rsvg_text_length_text_as_string (ctx, str->str);
            g_string_free (str, TRUE);
        } else {
            if (usetextonly || type == RSVG_NODE_TYPE_TEXT_PATH) {
                out = _rsvg_node_text_length_children(node, ctx, length,
                                                      lastwasspace,
                                                      usetextonly);
            } else {
                if (type == RSVG_NODE_TYPE_TSPAN) {
                    RsvgNodeText *tspan = (RsvgNodeText *) node;
                    out = _rsvg_node_text_length_tspan (tspan, ctx, length,
                                                        lastwasspace,
                                                        usetextonly);
                } else if (type == RSVG_NODE_TYPE_TREF) {
                    RsvgNodeTref *tref = (RsvgNodeTref *) node;
                    out = _rsvg_node_text_length_tref (tref, ctx, length,
                                                       lastwasspace,
                                                       usetextonly);
                }
            }
        }
        rsvg_state_pop (ctx);
        if (out)
            break;
    }
    return out;
}
Exemplo n.º 5
0
static void
_rsvg_node_text_type_children (RsvgNode * self, RsvgDrawingCtx * ctx,
                               gdouble * x, gdouble * y, gboolean * lastwasspace,
                               gboolean usetextonly)
{
    guint i;

    rsvg_push_discrete_layer (ctx);
    for (i = 0; i < self->children->len; i++) {
        RsvgNode *node = g_ptr_array_index (self->children, i);
        RsvgNodeType type = RSVG_NODE_TYPE (node);

        if (type == RSVG_NODE_TYPE_CHARS) {
            RsvgNodeChars *chars = (RsvgNodeChars *) node;
            GString *str = _rsvg_text_chomp (rsvg_current_state (ctx), chars->contents, lastwasspace);
            rsvg_text_render_text (ctx, str->str, x, y);
            g_string_free (str, TRUE);
        } else {
            if (usetextonly) {
                _rsvg_node_text_type_children (node, ctx, x, y, lastwasspace,
                                               usetextonly);
            } else {
                if (type == RSVG_NODE_TYPE_TSPAN) {
                    RsvgNodeText *tspan = (RsvgNodeText *) node;
                    rsvg_state_push (ctx);
                    _rsvg_node_text_type_tspan (tspan, ctx, x, y, lastwasspace,
                                                usetextonly);
                    rsvg_state_pop (ctx);
                } else if (type == RSVG_NODE_TYPE_TREF) {
                    RsvgNodeTref *tref = (RsvgNodeTref *) node;
                    _rsvg_node_text_type_tref (tref, ctx, x, y, lastwasspace,
                                               usetextonly);
                } else if (type == RSVG_NODE_TYPE_TEXT_PATH) {
                    RsvgNodeTextPath *textpath = (RsvgNodeTextPath *) node;
                    _rsvg_node_text_type_text_path(textpath, ctx, x, y,
                                                   lastwasspace, usetextonly);
                }
            }
        }
    }
    rsvg_pop_discrete_layer (ctx);
}
Exemplo n.º 6
0
void
rsvg_cairo_clip (RsvgDrawingCtx * ctx, RsvgClipPath * clip, RsvgBbox * bbox)
{
    RsvgCairoClipRender *clip_render;
    RsvgCairoRender *save = RSVG_CAIRO_RENDER (ctx->render);
    cairo_t *cr;
    cairo_matrix_t affinesave;

    cr = save->cr;
    clip_render = RSVG_CAIRO_CLIP_RENDER (rsvg_cairo_clip_render_new (cr, save));
    ctx->render = &clip_render->super.super;

    /* Horribly dirty hack to have the bbox premultiplied to everything */
    if (clip->units == objectBoundingBox) {
        cairo_matrix_t bbtransform;
        cairo_matrix_init (&bbtransform,
                           bbox->rect.width,
                           0,
                           0,
                           bbox->rect.height,
                           bbox->rect.x,
                           bbox->rect.y);
        affinesave = clip->super.state->affine;
        cairo_matrix_multiply (&clip->super.state->affine, &bbtransform, &clip->super.state->affine);
    }

    rsvg_state_push (ctx);
    _rsvg_node_draw_children ((RsvgNode *) clip, ctx, 0);
    rsvg_state_pop (ctx);

    if (clip->units == objectBoundingBox)
        clip->super.state->affine = affinesave;

    g_assert (clip_render->super.cr_stack == NULL);
    g_assert (clip_render->super.bb_stack == NULL);
    g_assert (clip_render->super.surfaces_stack == NULL);

    g_free (ctx->render);
    cairo_clip (cr);
    ctx->render = &save->super;
}
/**
 * rsvg_handle_render_cairo_sub:
 * @handle: A RsvgHandle
 * @cr: A Cairo renderer
 * @id: An element's id within the SVG, or %NULL to render the whole SVG. For
 * example, if you have a layer called "layer1" that you wish to render, pass 
 * "##layer1" as the id.
 *
 * Draws a subset of a SVG to a Cairo surface
 *
 * Returns: %TRUE if drawing succeeded.
 *
 * Since: 2.14
 */
gboolean
rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
{
    RsvgDrawingCtx *draw;
    RsvgNode *drawsub = NULL;

    g_return_val_if_fail (handle != NULL, FALSE);

    if (!handle->priv->finished)
        return FALSE;

    if (id && *id)
        drawsub = rsvg_defs_lookup (handle->priv->defs, id);

    if (drawsub == NULL && id != NULL) {
	/* todo: there's no way to signal that @id doesn't exist */
	return FALSE;
    }

    draw = rsvg_cairo_new_drawing_ctx (cr, handle);
    if (!draw)
        return FALSE;

    while (drawsub != NULL) {
        draw->drawsub_stack = g_slist_prepend (draw->drawsub_stack, drawsub);
        drawsub = drawsub->parent;
    }

    rsvg_state_push (draw);
    cairo_save (cr);

    rsvg_node_draw ((RsvgNode *) handle->priv->treebase, draw, 0);

    cairo_restore (cr);
    rsvg_state_pop (draw);
    rsvg_drawing_ctx_free (draw);

    return TRUE;
}
Exemplo n.º 8
0
static void
_rsvg_node_switch_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    guint i;

    rsvg_state_reinherit_top (ctx, self->state, dominate);

    rsvg_push_discrete_layer (ctx);

    for (i = 0; i < self->children->len; i++) {
        RsvgNode *drawable = g_ptr_array_index (self->children, i);

        if (drawable->state->cond_true) {
            rsvg_state_push (ctx);
            rsvg_node_draw (g_ptr_array_index (self->children, i), ctx, 0);
            rsvg_state_pop (ctx);

            break;              /* only render the 1st one */
        }
    }

    rsvg_pop_discrete_layer (ctx);
}
Exemplo n.º 9
0
static void
rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    RsvgNodeSvg *sself;
    RsvgState *state;
    gdouble affine[6], affine_old[6], affine_new[6];
    guint i;
    double nx, ny, nw, nh;
    sself = (RsvgNodeSvg *) self;

    nx = _rsvg_css_normalize_length (&sself->x, ctx, 'h');
    ny = _rsvg_css_normalize_length (&sself->y, ctx, 'v');
    nw = _rsvg_css_normalize_length (&sself->w, ctx, 'h');
    nh = _rsvg_css_normalize_length (&sself->h, ctx, 'v');

    rsvg_state_reinherit_top (ctx, self->state, dominate);

    state = rsvg_current_state (ctx);

    for (i = 0; i < 6; i++)
        affine_old[i] = state->affine[i];

    if (sself->vbox.active) {
        double x = nx, y = ny, w = nw, h = nh;
        rsvg_preserve_aspect_ratio (sself->preserve_aspect_ratio,
                                    sself->vbox.w, sself->vbox.h, &w, &h, &x, &y);
        affine[0] = w / sself->vbox.w;
        affine[1] = 0;
        affine[2] = 0;
        affine[3] = h / sself->vbox.h;
        affine[4] = x - sself->vbox.x * w / sself->vbox.w;
        affine[5] = y - sself->vbox.y * h / sself->vbox.h;
        _rsvg_affine_multiply (state->affine, affine, state->affine);
        _rsvg_push_view_box (ctx, sself->vbox.w, sself->vbox.h);
    } else {
        affine[0] = 1;
        affine[1] = 0;
        affine[2] = 0;
        affine[3] = 1;
        affine[4] = nx;
        affine[5] = ny;
        _rsvg_affine_multiply (state->affine, affine, state->affine);
        _rsvg_push_view_box (ctx, nw, nh);
    }
    for (i = 0; i < 6; i++)
        affine_new[i] = state->affine[i];

    rsvg_push_discrete_layer (ctx);

    /* Bounding box addition must be AFTER the discrete layer push, 
       which must be AFTER the transformation happens. */
    if (!state->overflow && self->parent) {
        for (i = 0; i < 6; i++)
            state->affine[i] = affine_old[i];
        rsvg_add_clipping_rect (ctx, nx, ny, nw, nh);
        for (i = 0; i < 6; i++)
            state->affine[i] = affine_new[i];
    }

    for (i = 0; i < self->children->len; i++) {
        rsvg_state_push (ctx);
        rsvg_node_draw (g_ptr_array_index (self->children, i), ctx, 0);
        rsvg_state_pop (ctx);
    }

    rsvg_pop_discrete_layer (ctx);
    _rsvg_pop_view_box (ctx);
}
Exemplo n.º 10
0
static void
rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    RsvgNodeUse *use = (RsvgNodeUse *) self;
    RsvgNode *child;
    RsvgState *state;
    double affine[6];
    double x, y, w, h;
    x = _rsvg_css_normalize_length (&use->x, ctx, 'h');
    y = _rsvg_css_normalize_length (&use->y, ctx, 'v');
    w = _rsvg_css_normalize_length (&use->w, ctx, 'h');
    h = _rsvg_css_normalize_length (&use->h, ctx, 'v');

    rsvg_state_reinherit_top (ctx, self->state, dominate);

    child = use->link;

    /* If it can find nothing to draw... draw nothing */
    if (!child)
        return;
    else if (rsvg_node_is_ancestor (child, self))       /* or, if we're <use>'ing ourself */
        return;

    state = rsvg_current_state (ctx);
    if (strcmp (child->type->str, "symbol")) {
        _rsvg_affine_translate (affine, x, y);
        _rsvg_affine_multiply (state->affine, affine, state->affine);

        rsvg_push_discrete_layer (ctx);
        rsvg_state_push (ctx);
        rsvg_node_draw (child, ctx, 1);
        rsvg_state_pop (ctx);
        rsvg_pop_discrete_layer (ctx);
    } else {
        RsvgNodeSymbol *symbol = (RsvgNodeSymbol *) child;

        if (symbol->vbox.active) {
            rsvg_preserve_aspect_ratio
                (symbol->preserve_aspect_ratio, symbol->vbox.w, symbol->vbox.h, &w, &h, &x, &y);

            _rsvg_affine_translate (affine, x, y);
            _rsvg_affine_multiply (state->affine, affine, state->affine);
            _rsvg_affine_scale (affine, w / symbol->vbox.w, h / symbol->vbox.h);
            _rsvg_affine_multiply (state->affine, affine, state->affine);
            _rsvg_affine_translate (affine, -symbol->vbox.x, -symbol->vbox.y);
            _rsvg_affine_multiply (state->affine, affine, state->affine);

            _rsvg_push_view_box (ctx, symbol->vbox.w, symbol->vbox.h);
            rsvg_push_discrete_layer (ctx);
            if (!state->overflow || (!state->has_overflow && child->state->overflow))
                rsvg_add_clipping_rect (ctx, symbol->vbox.x, symbol->vbox.y,
                                        symbol->vbox.w, symbol->vbox.h);
        } else {
            _rsvg_affine_translate (affine, x, y);
            _rsvg_affine_multiply (state->affine, affine, state->affine);
            rsvg_push_discrete_layer (ctx);
        }

        rsvg_state_push (ctx);
        _rsvg_node_draw_children (child, ctx, 1);
        rsvg_state_pop (ctx);
        rsvg_pop_discrete_layer (ctx);
        if (symbol->vbox.active)
            _rsvg_pop_view_box (ctx);
    }

}
Exemplo n.º 11
0
void
rsvg_marker_render (RsvgMarker * self, gdouble x, gdouble y, gdouble orient, gdouble linewidth,
		    RsvgDrawingCtx * ctx)
{
    cairo_matrix_t affine, taffine;
    unsigned int i;
    gdouble rotation;
    RsvgState *state = rsvg_current_state (ctx);

    cairo_matrix_init_translate (&taffine, x, y);
    cairo_matrix_multiply (&affine, &taffine, &state->affine);

    if (self->orientAuto)
        rotation = orient;
    else
        rotation = self->orient * M_PI / 180.;

    cairo_matrix_init_rotate (&taffine, rotation);
    cairo_matrix_multiply (&affine, &taffine, &affine);

    if (self->bbox) {
        cairo_matrix_init_scale (&taffine, linewidth, linewidth);
        cairo_matrix_multiply (&affine, &taffine, &affine);
    }

    if (self->vbox.active) {

        double w, h, x, y;
        w = _rsvg_css_normalize_length (&self->width, ctx, 'h');
        h = _rsvg_css_normalize_length (&self->height, ctx, 'v');
        x = 0;
        y = 0;

        rsvg_preserve_aspect_ratio (self->preserve_aspect_ratio,
                                    self->vbox.rect.width,
                                    self->vbox.rect.height,
                                    &w, &h, &x, &y);

        x = -self->vbox.rect.x * w / self->vbox.rect.width;
        y = -self->vbox.rect.y * h / self->vbox.rect.height;

        cairo_matrix_init (&taffine,
                           w / self->vbox.rect.width,
                           0,
                           0,
                           h / self->vbox.rect.height,
                           x,
                           y);
        cairo_matrix_multiply (&affine, &taffine, &affine);
        _rsvg_push_view_box (ctx, self->vbox.rect.width, self->vbox.rect.height);
    }

    cairo_matrix_init_translate (&taffine,
                                 -_rsvg_css_normalize_length (&self->refX, ctx, 'h'),
                                 -_rsvg_css_normalize_length (&self->refY, ctx, 'v'));
    cairo_matrix_multiply (&affine, &taffine, &affine);

    rsvg_state_push (ctx);
    state = rsvg_current_state (ctx);

    rsvg_state_reinit (state);

    rsvg_state_reconstruct (state, &self->super);

    state->affine = affine;

    rsvg_push_discrete_layer (ctx);

    state = rsvg_current_state (ctx);

    if (!state->overflow) {
        if (self->vbox.active)
            rsvg_add_clipping_rect (ctx, self->vbox.rect.x, self->vbox.rect.y,
                                    self->vbox.rect.width, self->vbox.rect.height);
        else
            rsvg_add_clipping_rect (ctx, 0, 0,
                                    _rsvg_css_normalize_length (&self->width, ctx, 'h'),
                                    _rsvg_css_normalize_length (&self->height, ctx, 'v'));
    }

    for (i = 0; i < self->super.children->len; i++) {
        rsvg_state_push (ctx);

        rsvg_node_draw (g_ptr_array_index (self->super.children, i), ctx, 0);

        rsvg_state_pop (ctx);
    }
    rsvg_pop_discrete_layer (ctx);

    rsvg_state_pop (ctx);
    if (self->vbox.active)
        _rsvg_pop_view_box (ctx);
}