GF_EXPORT GF_Path *gf_path_get_flatten(GF_Path *gp) { GF_Path *ngp; Fixed fineness; u32 i, *countour; GF_Point2D *pt; if (!gp || !gp->n_points) return NULL; if (gp->flags & GF_PATH_FLATTENED) return gf_path_clone(gp); /*avoid too high precision */ fineness = MAX(FIX_ONE - gp->fineness, FIX_ONE / 100); ngp = gf_path_new(); pt = &gp->points[0]; gf_path_add_move_to_vec(ngp, pt); countour = gp->contours; for (i=1; i<gp->n_points; ) { switch (gp->tags[i]) { case GF_PATH_CURVE_ON: case GF_PATH_CLOSE: pt = &gp->points[i]; if (*countour == i-1) { gf_path_add_move_to_vec(ngp, pt); countour++; } else { gf_path_add_line_to_vec(ngp, pt); } if (gp->tags[i]==GF_PATH_CLOSE) gf_path_close(ngp); i++; break; case GF_PATH_CURVE_CONIC: { GF_Point2D *ctl, *end, c1, c2; ctl = &gp->points[i]; end = &gp->points[i+1]; c1.x = pt->x + 2*(ctl->x - pt->x)/3; c1.y = pt->y + 2*(ctl->y - pt->y)/3; c2.x = c1.x + (end->x - pt->x) / 3; c2.y = c1.y + (end->y - pt->y) / 3; gf_subdivide_cubic(ngp, pt->x, pt->y, c1.x, c1.y, c2.x, c2.y, end->x, end->y, fineness); pt = end; if (gp->tags[i+1]==GF_PATH_CLOSE) gf_path_close(ngp); i+=2; } break; case GF_PATH_CURVE_CUBIC: gf_subdivide_cubic(ngp, pt->x, pt->y, gp->points[i].x, gp->points[i].y, gp->points[i+1].x, gp->points[i+1].y, gp->points[i+2].x, gp->points[i+2].y, fineness); pt = &gp->points[i+2]; if (gp->tags[i+2]==GF_PATH_CLOSE) gf_path_close(ngp); i+=3; break; } } if (gp->flags & GF_PATH_FILL_ZERO_NONZERO) ngp->flags |= GF_PATH_FILL_ZERO_NONZERO; ngp->flags |= (GF_PATH_BBOX_DIRTY | GF_PATH_FLATTENED); return ngp; }
static void ifs2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { u32 i; SFVec2f *pts; u32 ci_count, c_count; Bool started; M_IndexedFaceSet2D *ifs2D; M_Coordinate2D *coord; if (! gf_node_dirty_get(node)) return; ifs2D = (M_IndexedFaceSet2D *)node; coord = (M_Coordinate2D *)ifs2D->coord; drawable_reset_path(stack); gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); c_count = coord->point.count; ci_count = ifs2D->coordIndex.count; pts = coord->point.vals; if (ci_count > 0) { started = 0; for (i=0; i < ci_count; i++) { if (ifs2D->coordIndex.vals[i] == -1) { gf_path_close(stack->path); started = 0; } else if (!started) { started = 1; gf_path_add_move_to_vec(stack->path, &pts[ifs2D->coordIndex.vals[i]]); } else { gf_path_add_line_to_vec(stack->path, &pts[ifs2D->coordIndex.vals[i]]); } } if (started) gf_path_close(stack->path); } else if (c_count) { gf_path_add_move_to_vec(stack->path, &pts[0]); for (i=1; i < c_count; i++) { gf_path_add_line_to_vec(stack->path, &pts[i]); } gf_path_close(stack->path); } }