GF_Err evg_surface_set_path(GF_SURFACE _this, GF_Path *gp) { #ifndef INLINE_POINT_CONVERSION u32 i; GF_Point2D pt; #endif EVGSurface *surf = (EVGSurface *)_this; if (!surf) return GF_BAD_PARAM; if (!gp || !gp->n_points) { surf->ftoutline.n_points = 0; surf->ftoutline.n_contours = 0; return GF_OK; } gf_path_flatten(gp); surf->ftoutline.n_points = gp->n_points; surf->ftoutline.n_contours = gp->n_contours; surf->ftoutline.tags = gp->tags; surf->ftoutline.contours = (s32*) gp->contours; /*store path bounds for gradient/textures*/ gf_path_get_bounds(gp, &surf->path_bounds); /*invert Y (ft uses min Y)*/ surf->path_bounds.y -= surf->path_bounds.height; surf->ftoutline.flags = 0; if (gp->flags & GF_PATH_FILL_ZERO_NONZERO) surf->ftoutline.flags = GF_PATH_FILL_ZERO_NONZERO; #ifdef INLINE_POINT_CONVERSION surf->ftoutline.n_points = gp->n_points; surf->ftoutline.points = gp->points; surf->ftparams.mx = &surf->mat; #else if (surf->pointlen < gp->n_points) { surf->points = gf_realloc(surf->points, sizeof(EVG_Vector) * gp->n_points); if (surf->points == NULL) { surf->pointlen = 0; return GF_OUT_OF_MEM; } surf->pointlen = gp->n_points; } surf->ftoutline.points = surf->points; for (i=0; i<gp->n_points; i++) { pt = gp->points[i]; gf_mx2d_apply_point(&surf->mat, &pt); #ifdef GPAC_FIXED_POINT surf->points[i].x = pt.x; surf->points[i].y = pt.y; #else /*move to 16.16 representation*/ surf->points[i].x = (u32) (pt.x * 0x10000L); surf->points[i].y = (u32) (pt.y * 0x10000L); #endif } #endif return GF_OK; }
static void TraversePlanarExtrusion(GF_Node *node, void *rs, Bool is_destroy) { PlanarExtrusion plane_ext; Drawable *stack_2d; u32 i, j, k; MFVec3f spine_vec; SFVec3f d; Fixed spine_len; GF_Rect bounds; GF_Path *geo, *spine; GF_TraverseState *tr_state = (GF_TraverseState *)rs; Drawable3D *stack = (Drawable3D *)gf_node_get_private(node); if (is_destroy) { drawable_3d_del(node); return; } if (!PlanarExtrusion_GetNode(node, &plane_ext)) return; if (!plane_ext.geometry || !plane_ext.spine) return; if (gf_node_dirty_get(node)) { u32 cur, nb_pts; u32 mode = tr_state->traversing_mode; geo = spine = NULL; tr_state->traversing_mode = TRAVERSE_GET_BOUNDS; gf_node_traverse(plane_ext.geometry, tr_state); gf_node_traverse(plane_ext.spine, tr_state); tr_state->traversing_mode = mode; switch (gf_node_get_tag(plane_ext.geometry) ) { case TAG_MPEG4_Circle: case TAG_MPEG4_Ellipse: case TAG_MPEG4_Rectangle: case TAG_MPEG4_Curve2D: case TAG_MPEG4_XCurve2D: case TAG_MPEG4_IndexedFaceSet2D: case TAG_MPEG4_IndexedLineSet2D: stack_2d = (Drawable*)gf_node_get_private(plane_ext.geometry); if (stack_2d) geo = stack_2d->path; break; default: return; } switch (gf_node_get_tag(plane_ext.spine) ) { case TAG_MPEG4_Circle: case TAG_MPEG4_Ellipse: case TAG_MPEG4_Rectangle: case TAG_MPEG4_Curve2D: case TAG_MPEG4_XCurve2D: case TAG_MPEG4_IndexedFaceSet2D: case TAG_MPEG4_IndexedLineSet2D: stack_2d = (Drawable*)gf_node_get_private(plane_ext.spine); if (stack_2d) spine = stack_2d->path; break; default: return; } if (!geo || !spine) return; mesh_reset(stack->mesh); gf_path_flatten(spine); gf_path_get_bounds(spine, &bounds); gf_path_flatten(geo); gf_path_get_bounds(geo, &bounds); cur = 0; for (i=0; i<spine->n_contours; i++) { nb_pts = 1 + spine->contours[i] - cur; spine_vec.vals = NULL; gf_sg_vrml_mf_alloc(&spine_vec, GF_SG_VRML_MFVEC3F, nb_pts); spine_len = 0; for (j=cur; j<nb_pts; j++) { spine_vec.vals[j].x = spine->points[j].x; spine_vec.vals[j].y = spine->points[j].y; spine_vec.vals[j].z = 0; if (j) { gf_vec_diff(d, spine_vec.vals[j], spine_vec.vals[j-1]); spine_len += gf_vec_len(d); } } cur += nb_pts; if (!plane_ext.orientation->count && !plane_ext.scale->count) { mesh_extrude_path_ext(stack->mesh, geo, &spine_vec, plane_ext.creaseAngle, bounds.x, bounds.y-bounds.height, bounds.width, bounds.height, plane_ext.beginCap, plane_ext.endCap, NULL, NULL, plane_ext.txAlongSpine); } /*interpolate orientation and scale along subpath line*/ else { MFRotation ori; MFVec2f scale; Fixed cur_len, frac; ori.vals = NULL; gf_sg_vrml_mf_alloc(&ori, GF_SG_VRML_MFROTATION, nb_pts); scale.vals = NULL; gf_sg_vrml_mf_alloc(&scale, GF_SG_VRML_MFVEC2F, nb_pts); cur_len = 0; if (!plane_ext.orientation->count) ori.vals[0].y = FIX_ONE; if (!plane_ext.scale->count) scale.vals[0].x = scale.vals[0].y = FIX_ONE; for (j=0; j<nb_pts; j++) { if (j) { gf_vec_diff(d, spine_vec.vals[j], spine_vec.vals[j-1]); cur_len += gf_vec_len(d); ori.vals[j] = ori.vals[j-1]; scale.vals[j] = scale.vals[j-1]; } if (plane_ext.orientation->count && (plane_ext.orientation->count == plane_ext.orientationKeys->count)) { frac = gf_divfix(cur_len , spine_len); if (frac < plane_ext.orientationKeys->vals[0]) ori.vals[j] = plane_ext.orientation->vals[0]; else if (frac >= plane_ext.orientationKeys->vals[plane_ext.orientationKeys->count-1]) ori.vals[j] = plane_ext.orientation->vals[plane_ext.orientationKeys->count-1]; else { for (k=1; k<plane_ext.orientationKeys->count; k++) { Fixed kDiff = plane_ext.orientationKeys->vals[k] - plane_ext.orientationKeys->vals[k-1]; if (!kDiff) continue; if (frac < plane_ext.orientationKeys->vals[k-1]) continue; if (frac > plane_ext.orientationKeys->vals[k]) continue; frac = gf_divfix(frac - plane_ext.orientationKeys->vals[k-1], kDiff); break; } ori.vals[j] = gf_sg_sfrotation_interpolate(plane_ext.orientation->vals[k-1], plane_ext.orientation->vals[k], frac); } } if (plane_ext.scale->count == plane_ext.scaleKeys->count) { frac = gf_divfix(cur_len , spine_len); if (frac <= plane_ext.scaleKeys->vals[0]) scale.vals[j] = plane_ext.scale->vals[0]; else if (frac >= plane_ext.scaleKeys->vals[plane_ext.scaleKeys->count-1]) scale.vals[j] = plane_ext.scale->vals[plane_ext.scale->count-1]; else { for (k=1; k<plane_ext.scaleKeys->count; k++) { Fixed kDiff = plane_ext.scaleKeys->vals[k] - plane_ext.scaleKeys->vals[k-1]; if (!kDiff) continue; if (frac < plane_ext.scaleKeys->vals[k-1]) continue; if (frac > plane_ext.scaleKeys->vals[k]) continue; frac = gf_divfix(frac - plane_ext.scaleKeys->vals[k-1], kDiff); break; } scale.vals[j].x = gf_mulfix(plane_ext.scale->vals[k].x - plane_ext.scale->vals[k-1].x, frac) + plane_ext.scale->vals[k-1].x; scale.vals[j].y = gf_mulfix(plane_ext.scale->vals[k].y - plane_ext.scale->vals[k-1].y, frac) + plane_ext.scale->vals[k-1].y; } } } mesh_extrude_path_ext(stack->mesh, geo, &spine_vec, plane_ext.creaseAngle, bounds.x, bounds.y-bounds.height, bounds.width, bounds.height, plane_ext.beginCap, plane_ext.endCap, &ori, &scale, plane_ext.txAlongSpine); gf_sg_vrml_mf_reset(&ori, GF_SG_VRML_MFROTATION); gf_sg_vrml_mf_reset(&scale, GF_SG_VRML_MFVEC2F); } gf_sg_vrml_mf_reset(&spine_vec, GF_SG_VRML_MFVEC3F); } mesh_update_bounds(stack->mesh); gf_mesh_build_aabbtree(stack->mesh); } if (tr_state->traversing_mode==TRAVERSE_DRAW_3D) { visual_3d_draw(tr_state, stack->mesh); } else if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) { tr_state->bbox = stack->mesh->bounds; } }