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); } }
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); }
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); }