/** * Creates a projective matrix that maps a quadrangle to a quadrangle */ EAPI Eina_Bool enesim_matrix_quad_quad_map(Enesim_Matrix *m, const Enesim_Quad *src, const Enesim_Quad *dst) { Enesim_Matrix tmp; /* TODO check that both are actually quadrangles */ if (!enesim_matrix_quad_square_map(m, src)) return EINA_FALSE; if (!enesim_matrix_square_quad_map(&tmp, dst)) return EINA_FALSE; enesim_matrix_compose(&tmp, m, m); return EINA_TRUE; }
/*----------------------------------------------------------------------------* * Element interface * *----------------------------------------------------------------------------*/ static Eina_Bool _egueb_svg_renderable_process(Egueb_Svg_Element *e) { Egueb_Svg_Renderable *thiz; Egueb_Svg_Renderable_Class *klass; Egueb_Svg_Clip_Path clip_path = EGUEB_SVG_CLIP_PATH_INIT; Egueb_Svg_Matrix m; Egueb_Svg_Painter *painter; Egueb_Dom_Node *relative; Egueb_Dom_Node *doc; Egueb_Dom_Node *topmost; Enesim_Renderer *ren = NULL; thiz = EGUEB_SVG_RENDERABLE(e); klass = EGUEB_SVG_RENDERABLE_CLASS_GET(e); /* set the new transformation */ relative = egueb_svg_element_geometry_relative_get(EGUEB_DOM_NODE(e)); if (relative) { Egueb_Svg_Element *e_parent; e_parent = EGUEB_SVG_ELEMENT(relative); egueb_dom_attr_final_get(thiz->transform, &m); enesim_matrix_compose(&e_parent->transform, &m, &e->transform); egueb_dom_node_unref(relative); } /* TODO in case there is no relative, set our own transform */ DBG_ELEMENT(EGUEB_DOM_NODE(e), "New transformation %" ENESIM_MATRIX_FORMAT, ENESIM_MATRIX_ARGS(&e->transform)); /* first process the renderable itself */ if (klass->process) { if (!klass->process(thiz)) { WARN_ELEMENT(EGUEB_DOM_NODE(e), "Process failed"); return EINA_FALSE; } } /* propagate the presentation attributes */ /* resolve the painter based on the presentation attributes */ painter = egueb_svg_painter_ref(thiz->painter); if (!painter) { doc = egueb_dom_node_owner_document_get(EGUEB_DOM_NODE(e)); if (!doc) { WARN_ELEMENT(EGUEB_DOM_NODE(e), "No document available"); return EINA_FALSE; } topmost = egueb_dom_document_document_element_get(doc); egueb_dom_node_unref(doc); /* The only special case is the topmost svg element */ if (topmost == EGUEB_DOM_NODE(e)) { painter = egueb_svg_renderable_class_painter_get(EGUEB_DOM_NODE(e)); if (!painter) { WARN_ELEMENT(EGUEB_DOM_NODE(e), "Topmost element does not have a painter"); egueb_dom_node_unref(topmost); } egueb_dom_node_unref(topmost); } else { egueb_dom_node_unref(topmost); WARN_ELEMENT(EGUEB_DOM_NODE(e), "No painter available"); } } if (painter) { if (!egueb_svg_painter_resolve(painter, e)) { WARN_ELEMENT(EGUEB_DOM_NODE(e), "Painter resolving failed"); egueb_svg_painter_unref(painter); return EINA_FALSE; } /* finally call the renderer propagate implementation */ if (klass->painter_apply) klass->painter_apply(thiz, painter); egueb_svg_painter_unref(painter); } /* now resolve the clip path */ egueb_svg_element_clip_path_final_get(EGUEB_DOM_NODE(e), &clip_path); egueb_svg_element_clip_path_resolve(EGUEB_DOM_NODE(e), &clip_path, &thiz->clip_path_last, &thiz->clip_path); egueb_svg_clip_path_reset(&clip_path); if (thiz->clip_path) egueb_svg_reference_clip_path_renderer_get(thiz->clip_path, &ren); /* set the correct renderer on the proxy */ if (ren) { DBG_ELEMENT(EGUEB_DOM_NODE(e), "Clip path: %s", enesim_renderer_name_get(ren)); } else { if (klass->renderer_get) ren = klass->renderer_get(thiz); if (!ren) { WARN_ELEMENT(EGUEB_DOM_NODE(e), "No renderer found"); return EINA_FALSE; } else { DBG_ELEMENT(EGUEB_DOM_NODE(e), "Renderer: %s", enesim_renderer_name_get(ren)); } } enesim_renderer_proxy_proxied_set(thiz->proxy, ren); _egueb_svg_renderable_check_new_bounds(thiz); return EINA_TRUE; }
/*----------------------------------------------------------------------------* * Gradient interface * *----------------------------------------------------------------------------*/ static Eina_Bool _egueb_svg_reference_gradient_linear_process( Egueb_Svg_Reference_Gradient *g) { Egueb_Svg_Reference_Gradient_Linear *thiz; Egueb_Svg_Reference *r; Egueb_Svg_Length x1, y1, x2, y2; Egueb_Svg_Referenceable_Units units; Egueb_Dom_Node *doc = NULL; Enesim_Matrix m, transform; double gx1, gy1, gx2, gy2; DBG("Processing a linear gradient reference"); /* get the final attributes */ r = EGUEB_SVG_REFERENCE(g); egueb_svg_element_linear_gradient_deep_x1_get(r->referenceable, &x1); egueb_svg_element_linear_gradient_deep_y1_get(r->referenceable, &y1); egueb_svg_element_linear_gradient_deep_x2_get(r->referenceable, &x2); egueb_svg_element_linear_gradient_deep_y2_get(r->referenceable, &y2); egueb_svg_gradient_deep_units_get(r->referenceable, &units); egueb_svg_gradient_deep_transform_get(r->referenceable, &transform); if (units == EGUEB_SVG_REFERENCEABLE_UNITS_OBJECT_BOUNDING_BOX) { Enesim_Rectangle bounds; Egueb_Svg_Element *e_referencer; e_referencer = EGUEB_SVG_ELEMENT(r->referencer); /* check that the coordinates shold be set with (0,0) -> (1, 1) */ gx1 = egueb_svg_coord_final_get(&x1, 1, 1); gy1 = egueb_svg_coord_final_get(&y1, 1, 1); gx2 = egueb_svg_coord_final_get(&x2, 1, 1); gy2 = egueb_svg_coord_final_get(&y2, 1, 1); egueb_svg_renderable_bounds_get(r->referencer, &bounds); enesim_matrix_values_set(&m, bounds.w, 0, bounds.x, 0, bounds.h, bounds.y, 0, 0, 1); DBG("Using the object bounding box %" ENESIM_RECTANGLE_FORMAT, ENESIM_RECTANGLE_ARGS(&bounds)); /* transform the bounds using the context matrix */ enesim_matrix_compose(&e_referencer->transform, &m, &m); } else { Egueb_Dom_Node *g_relative; Egueb_Svg_Element *ge_relative; double font_size; DBG("Using the user space on use"); doc = egueb_dom_node_owner_document_get(r->referencer); if (!doc) { WARN("No document set"); return EINA_FALSE; } font_size = egueb_svg_document_font_size_get(doc); egueb_dom_node_unref(doc); g_relative = egueb_svg_element_geometry_relative_get(r->referencer); if (!g_relative) { WARN("No relative geometry"); return EINA_FALSE; } ge_relative = EGUEB_SVG_ELEMENT(g_relative); /* use the user space coordiantes */ gx1 = egueb_svg_coord_final_get(&x1, ge_relative->viewbox.w, font_size); gy1 = egueb_svg_coord_final_get(&y1, ge_relative->viewbox.h, font_size); gx2 = egueb_svg_coord_final_get(&x2, ge_relative->viewbox.w, font_size); gy2 = egueb_svg_coord_final_get(&y2, ge_relative->viewbox.h, font_size); m = ge_relative->transform; egueb_dom_node_unref(g_relative); } /* Apply the gradient transform */ if (enesim_matrix_type_get(&transform) != ENESIM_MATRIX_TYPE_IDENTITY) enesim_matrix_compose(&m, &transform, &m); /* set the renderer properties */ thiz = EGUEB_SVG_REFERENCE_GRADIENT_LINEAR(r); enesim_renderer_transformation_set(thiz->r, &m); enesim_renderer_gradient_linear_x0_set(thiz->r, gx1); enesim_renderer_gradient_linear_y0_set(thiz->r, gy1); enesim_renderer_gradient_linear_x1_set(thiz->r, gx2); enesim_renderer_gradient_linear_y1_set(thiz->r, gy2); DBG("Coordinates x1 = %g, y1 = %g, x2 = %g, y2 = %g", gx1, gy1, gx2, gy2); DBG("Transformation %" ENESIM_MATRIX_FORMAT, ENESIM_MATRIX_ARGS(&m)); return EINA_TRUE; }