예제 #1
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;
}
예제 #2
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);
    }

}