Beispiel #1
0
static void
rsvg_node_image_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    RsvgNodeImage *z = (RsvgNodeImage *) self;
    unsigned int aspect_ratio = z->preserve_aspect_ratio;
    gdouble x, y, w, h;
    cairo_surface_t *surface = z->surface;

    if (surface == NULL)
        return;

    x = _rsvg_css_normalize_length (&z->x, ctx, 'h');
    y = _rsvg_css_normalize_length (&z->y, ctx, 'v');
    w = _rsvg_css_normalize_length (&z->w, ctx, 'h');
    h = _rsvg_css_normalize_length (&z->h, ctx, 'v');

    rsvg_state_reinherit_top (ctx, z->super.state, dominate);

    rsvg_push_discrete_layer (ctx);

    if (!rsvg_current_state (ctx)->overflow && (aspect_ratio & RSVG_ASPECT_RATIO_SLICE)) {
        rsvg_add_clipping_rect (ctx, x, y, w, h);
    }

    rsvg_preserve_aspect_ratio (aspect_ratio, 
                                (double) cairo_image_surface_get_width (surface),
                                (double) cairo_image_surface_get_height (surface), 
                                &w, &h, &x, &y);

    rsvg_render_surface (ctx, surface, x, y, w, h);

    rsvg_pop_discrete_layer (ctx);
}
Beispiel #2
0
static void
_rsvg_node_line_draw (RsvgNode * overself, RsvgDrawingCtx * ctx, int dominate)
{
    cairo_path_t *path;
    RsvgPathBuilder builder;
    RsvgNodeLine *self = (RsvgNodeLine *) overself;
    double x1, y1, x2, y2;

    rsvg_path_builder_init (&builder, 4);

    x1 = _rsvg_css_normalize_length (&self->x1, ctx, 'h');
    y1 = _rsvg_css_normalize_length (&self->y1, ctx, 'v');
    x2 = _rsvg_css_normalize_length (&self->x2, ctx, 'h');
    y2 = _rsvg_css_normalize_length (&self->y2, ctx, 'v');

    rsvg_path_builder_move_to (&builder, x1, y1);
    rsvg_path_builder_line_to (&builder, x2, y2);

    path = rsvg_path_builder_finish (&builder);

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

    rsvg_render_path (ctx, path);
    rsvg_cairo_path_destroy (path);
}
Beispiel #3
0
static void
_rsvg_node_text_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    double x, y;
    gboolean lastwasspace = TRUE;
    RsvgNodeText *text = (RsvgNodeText *) self;
    rsvg_state_reinherit_top (ctx, self->state, dominate);

    x = _rsvg_css_normalize_length (&text->x, ctx, 'h');
    y = _rsvg_css_normalize_length (&text->y, ctx, 'v');
    x += _rsvg_css_normalize_length (&text->dx, ctx, 'h');
    y += _rsvg_css_normalize_length (&text->dy, ctx, 'v');

    if (rsvg_current_state (ctx)->text_anchor != TEXT_ANCHOR_START) {
        double length = 0;
        _rsvg_node_text_length_children (self, ctx, &length, &lastwasspace);
        if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_END)
            x -= length;
        if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
            x -= length / 2;
    }

    lastwasspace = TRUE;
    _rsvg_node_text_type_children (self, ctx, &x, &y, &lastwasspace);
}
Beispiel #4
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;
}
Beispiel #5
0
static void
rsvg_node_path_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    RsvgNodePath *path = (RsvgNodePath *) self;

    if (!path->path)
        return;

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

    rsvg_render_path (ctx, path->path);
}
Beispiel #6
0
static void
_rsvg_node_poly_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    RsvgNodePoly *poly = (RsvgNodePoly *) self;

    if (poly->path == NULL)
        return;

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

    rsvg_render_path (ctx, poly->path);
}
Beispiel #7
0
static void
_rsvg_node_ellipse_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    RsvgNodeEllipse *ellipse = (RsvgNodeEllipse *) self;
    cairo_path_t *path;
    double cx, cy, rx, ry;
    RsvgPathBuilder builder;

    cx = _rsvg_css_normalize_length (&ellipse->cx, ctx, 'h');
    cy = _rsvg_css_normalize_length (&ellipse->cy, ctx, 'v');
    rx = _rsvg_css_normalize_length (&ellipse->rx, ctx, 'h');
    ry = _rsvg_css_normalize_length (&ellipse->ry, ctx, 'v');

    if (rx <= 0 || ry <= 0)
        return;

    /* approximate an ellipse using 4 bezier curves */

    rsvg_path_builder_init (&builder, 19);

    rsvg_path_builder_move_to (&builder, cx + rx, cy);

    rsvg_path_builder_curve_to (&builder,
                                cx + rx, cy - RSVG_ARC_MAGIC * ry,
                                cx + RSVG_ARC_MAGIC * rx, cy - ry,
                                cx, cy - ry);

    rsvg_path_builder_curve_to (&builder,
                                cx - RSVG_ARC_MAGIC * rx, cy - ry,
                                cx - rx, cy - RSVG_ARC_MAGIC * ry,
                                cx - rx, cy);

    rsvg_path_builder_curve_to (&builder,
                                cx - rx, cy + RSVG_ARC_MAGIC * ry,
                                cx - RSVG_ARC_MAGIC * rx, cy + ry,
                                cx, cy + ry);

    rsvg_path_builder_curve_to (&builder,
                                cx + RSVG_ARC_MAGIC * rx, cy + ry,
                                cx + rx, cy + RSVG_ARC_MAGIC * ry,
                                cx + rx, cy);

    rsvg_path_builder_close_path (&builder);

    path = rsvg_path_builder_finish (&builder);

    rsvg_state_reinherit_top (ctx, self->state, dominate);
    rsvg_render_path (ctx, path);
    rsvg_cairo_path_destroy (path);
}
Beispiel #8
0
static void
_rsvg_node_circle_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    cairo_path_t *path;
    RsvgNodeCircle *circle = (RsvgNodeCircle *) self;
    double cx, cy, r;
    RsvgPathBuilder builder;

    cx = _rsvg_css_normalize_length (&circle->cx, ctx, 'h');
    cy = _rsvg_css_normalize_length (&circle->cy, ctx, 'v');
    r = _rsvg_css_normalize_length (&circle->r, ctx, 'o');

    if (r <= 0)
        return;

    /* approximate a circle using 4 bezier curves */

    rsvg_path_builder_init (&builder, 19);

    rsvg_path_builder_move_to (&builder, cx + r, cy);

    rsvg_path_builder_curve_to (&builder,
                                cx + r, cy + r * RSVG_ARC_MAGIC,
                                cx + r * RSVG_ARC_MAGIC, cy + r,
                                cx, cy + r);

    rsvg_path_builder_curve_to (&builder,
                                cx - r * RSVG_ARC_MAGIC, cy + r,
                                cx - r, cy + r * RSVG_ARC_MAGIC,
                                cx - r, cy);

    rsvg_path_builder_curve_to (&builder,
                                cx - r, cy - r * RSVG_ARC_MAGIC,
                                cx - r * RSVG_ARC_MAGIC, cy - r,
                                cx, cy - r);

    rsvg_path_builder_curve_to (&builder,
                                cx + r * RSVG_ARC_MAGIC, cy - r,
                                cx + r, cy - r * RSVG_ARC_MAGIC,
                                cx + r, cy);

    rsvg_path_builder_close_path (&builder);

    path = rsvg_path_builder_finish (&builder);

    rsvg_state_reinherit_top (ctx, self->state, dominate);
    rsvg_render_path (ctx, path);
    rsvg_cairo_path_destroy (path);
}
Beispiel #9
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);
}
Beispiel #10
0
static void
_rsvg_node_text_type_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
                            gdouble * x, gdouble * y, gboolean * lastwasspace,
                            gboolean usetextonly)
{
    double dx, dy, length = 0;
    rsvg_state_reinherit_top (ctx, self->super.state, 0);

    dx = _rsvg_css_normalize_length (&self->dx, ctx, 'h');
    dy = _rsvg_css_normalize_length (&self->dy, ctx, 'v');

    if (rsvg_current_state (ctx)->text_anchor != TEXT_ANCHOR_START) {
        gboolean lws = *lastwasspace;
        _rsvg_node_text_length_children (&self->super, ctx, &length, &lws,
                                         usetextonly);
        if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
            length /= 2;
    }

    if (self->x.factor != 'n') {
        *x = _rsvg_css_normalize_length (&self->x, ctx, 'h');
        if (!PANGO_GRAVITY_IS_VERTICAL (rsvg_current_state (ctx)->text_gravity)) {
            *x -= length;
            if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
                dx /= 2;
            if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_END)
                dx = 0;
        }
    }
    *x += dx;

    if (self->y.factor != 'n') {
        *y = _rsvg_css_normalize_length (&self->y, ctx, 'v');
        if (PANGO_GRAVITY_IS_VERTICAL (rsvg_current_state (ctx)->text_gravity)) {
            *y -= length;
            if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
                dy /= 2;
            if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_END)
                dy = 0;
        }
    }
    *y += dy;
    _rsvg_node_text_type_children (&self->super, ctx, x, y, lastwasspace,
                                   usetextonly);
}
Beispiel #11
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;
}
Beispiel #12
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);
}
Beispiel #13
0
static void
_rsvg_node_text_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    double x, y, dx, dy, length = 0;
    gboolean lastwasspace = TRUE;
    RsvgNodeText *text = (RsvgNodeText *) self;
    rsvg_state_reinherit_top (ctx, self->state, dominate);

    x = _rsvg_css_normalize_length (&text->x, ctx, 'h');
    y = _rsvg_css_normalize_length (&text->y, ctx, 'v');
    dx = _rsvg_css_normalize_length (&text->dx, ctx, 'h');
    dy = _rsvg_css_normalize_length (&text->dy, ctx, 'v');

    if (rsvg_current_state (ctx)->text_anchor != TEXT_ANCHOR_START) {
        _rsvg_node_text_length_children (self, ctx, &length, &lastwasspace, FALSE);
        if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
            length /= 2;
    }
    if (PANGO_GRAVITY_IS_VERTICAL (rsvg_current_state (ctx)->text_gravity)) {
        y -= length;
        if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
            dy /= 2;
        if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_END)
            dy = 0;
    } else {
        x -= length;
        if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
            dx /= 2;
        if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_END)
            dx = 0;
    }
    x += dx;
    y += dy;

    lastwasspace = TRUE;
    _rsvg_node_text_type_children (self, ctx, &x, &y, &lastwasspace, FALSE);
}
Beispiel #14
0
static void
_rsvg_node_text_type_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
                            gdouble * x, gdouble * y, gboolean * lastwasspace)
{
    rsvg_state_reinherit_top (ctx, self->super.state, 0);

    if (self->x.factor != 'n') {
        *x = _rsvg_css_normalize_length (&self->x, ctx, 'h');
        if (rsvg_current_state (ctx)->text_anchor != TEXT_ANCHOR_START) {
            double length = 0;
            gboolean lws = *lastwasspace;
            _rsvg_node_text_length_children (&self->super, ctx, &length, &lws);
            if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_END)
                *x -= length;
            if (rsvg_current_state (ctx)->text_anchor == TEXT_ANCHOR_MIDDLE)
                *x -= length / 2;
        }
    }
    if (self->y.factor != 'n')
        *y = _rsvg_css_normalize_length (&self->y, ctx, 'v');
    *x += _rsvg_css_normalize_length (&self->dx, ctx, 'h');
    *y += _rsvg_css_normalize_length (&self->dy, ctx, 'v');
    _rsvg_node_text_type_children (&self->super, ctx, x, y, lastwasspace);
}
Beispiel #15
0
static void
_rsvg_node_rect_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
    double x, y, w, h, rx, ry;
    double half_w, half_h;
    RsvgPathBuilder builder;
    cairo_path_t *path;
    RsvgNodeRect *rect = (RsvgNodeRect *) self;

    x = _rsvg_css_normalize_length (&rect->x, ctx, 'h');
    y = _rsvg_css_normalize_length (&rect->y, ctx, 'v');

    /* FIXME: negative w/h/rx/ry is an error, per http://www.w3.org/TR/SVG11/shapes.html#RectElement
     * For now we'll just take the absolute value.
     */
    w = fabs (_rsvg_css_normalize_length (&rect->w, ctx, 'h'));
    h = fabs (_rsvg_css_normalize_length (&rect->h, ctx, 'v'));
    rx = fabs (_rsvg_css_normalize_length (&rect->rx, ctx, 'h'));
    ry = fabs (_rsvg_css_normalize_length (&rect->ry, ctx, 'v'));

    if (w == 0. || h == 0.)
        return;

    if (rect->got_rx)
        rx = rx;
    else
        rx = ry;

    if (rect->got_ry)
        ry = ry;
    else
        ry = rx;

    half_w = w / 2;
    half_h = h / 2;

    if (rx > half_w)
        rx = half_w;

    if (ry > half_h)
        ry = half_h;

    if (rx == 0)
        ry = 0;
    else if (ry == 0)
        rx = 0;

    if (rx == 0) {
        /* Easy case, no rounded corners */

        rsvg_path_builder_init (&builder, 11);

        rsvg_path_builder_move_to (&builder, x, y);
        rsvg_path_builder_line_to (&builder, x + w, y);
        rsvg_path_builder_line_to (&builder, x + w, y + h);
        rsvg_path_builder_line_to (&builder, x, y + h);
        rsvg_path_builder_line_to (&builder, x, y);
        rsvg_path_builder_close_path (&builder);
    } else {
        double top_x1, top_x2, top_y;
        double bottom_x1, bottom_x2, bottom_y;
        double left_x, left_y1, left_y2;
        double right_x, right_y1, right_y2;

        /* Hard case, rounded corners
         *
         *      (top_x1, top_y)                   (top_x2, top_y)
         *     *--------------------------------*
         *    /                                  \
         *   * (left_x, left_y1)                  * (right_x, right_y1)
         *   |                                    |
         *   |                                    |
         *   |                                    |
         *   |                                    |
         *   |                                    |
         *   |                                    |
         *   |                                    |
         *   |                                    |
         *   |                                    |
         *   * (left_x, left_y2)                  * (right_x, right_y2)
         *    \                                  /
         *     *--------------------------------*
         *      (bottom_x1, bottom_y)            (bottom_x2, bottom_y)
         */

        top_x1 = x + rx;
        top_x2 = x + w - rx;
        top_y  = y;

        bottom_x1 = top_x1;
        bottom_x2 = top_x2;
        bottom_y  = y + h;

        left_x = x;
        left_y1 = y + ry;
        left_y2 = y + h - ry;

        right_x = x + w;
        right_y1 = left_y1;
        right_y2 = left_y2;

        rsvg_path_builder_init (&builder, 32); /* an estimate; the arc segments may grow the array anyway */

        rsvg_path_builder_move_to (&builder, top_x1, top_y);
        rsvg_path_builder_line_to (&builder, top_x2, top_y);

        rsvg_path_builder_arc (&builder,
                               top_x2, top_y,
                               rx, ry, 0, FALSE, TRUE,
                               right_x, right_y1);

        rsvg_path_builder_line_to (&builder, right_x, right_y2);

        rsvg_path_builder_arc (&builder,
                               right_x, right_y2,
                               rx, ry, 0, FALSE, TRUE,
                               bottom_x2, bottom_y);

        rsvg_path_builder_line_to (&builder, bottom_x1, bottom_y);

        rsvg_path_builder_arc (&builder,
                               bottom_x1, bottom_y,
                               rx, ry, 0, FALSE, TRUE,
                               left_x, left_y2);

        rsvg_path_builder_line_to (&builder, left_x, left_y1);

        rsvg_path_builder_arc (&builder,
                               left_x, left_y1,
                               rx, ry, 0, FALSE, TRUE,
                               top_x1, top_y);

        rsvg_path_builder_close_path (&builder);
    }

    path = rsvg_path_builder_finish (&builder);

    rsvg_state_reinherit_top (ctx, self->state, dominate);
    rsvg_render_path (ctx, path);
    rsvg_cairo_path_destroy (path);
}
Beispiel #16
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);
    }

}
Beispiel #17
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);
}