static void TraverseILS2D(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; M_IndexedLineSet2D *ils2D = (M_IndexedLineSet2D *)node; Drawable *stack = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { drawable_node_del(node); return; } if (!ils2D->coord) return; ils2d_check_changes(node, stack, tr_state); switch (tr_state->traversing_mode) { case TRAVERSE_DRAW_2D: ILS2D_Draw(node, tr_state); return; #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: if (!stack->mesh) { stack->mesh = new_mesh(); mesh_new_ils(stack->mesh, ils2D->coord, &ils2D->coordIndex, ils2D->color, &ils2D->colorIndex, ils2D->colorPerVertex, 0); } if (ils2D->color) { DrawAspect2D asp; memset(&asp, 0, sizeof(DrawAspect2D)); drawable_get_aspect_2d_mpeg4(node, &asp, tr_state); visual_3d_mesh_strike(tr_state, stack->mesh, asp.pen_props.width, asp.line_scale, asp.pen_props.dash); } else { visual_3d_draw_2d(stack, tr_state); } return; #endif case TRAVERSE_PICK: vrml_drawable_pick(stack, tr_state); return; case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; /*ILS2D are NEVER filled*/ ctx->aspect.fill_color &= 0x00FFFFFF; drawable_finalize_sort(ctx, tr_state, NULL); return; default: return; } }
static void TraversePointSet2D(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; M_PointSet2D *ps2D = (M_PointSet2D *)node; Drawable *stack = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { drawable_node_del(node); return; } if (!ps2D->coord) return; pointset2d_check_changes(node, stack, tr_state); switch (tr_state->traversing_mode) { case TRAVERSE_DRAW_2D: PointSet2D_Draw(node, tr_state); return; #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: { DrawAspect2D asp; if (!stack->mesh) { stack->mesh = new_mesh(); mesh_new_ps(stack->mesh, ps2D->coord, ps2D->color); } memset(&asp, 0, sizeof(DrawAspect2D)); drawable_get_aspect_2d_mpeg4(node, &asp, tr_state); visual_3d_set_material_2d_argb(tr_state->visual, asp.fill_color); visual_3d_mesh_paint(tr_state, stack->mesh); return; } #endif case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); return; case TRAVERSE_PICK: return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; drawable_finalize_sort(ctx, tr_state, NULL); break; default: return; } }
static void TraverseArc2D(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; Drawable *stack = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { drawable_node_del(node); return; } arc2d_check_changes(node, stack, tr_state); switch (tr_state->traversing_mode) { #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: if (!stack->mesh) { stack->mesh = new_mesh(); if (gf_node_get_tag(node)==TAG_X3D_Arc2D) { mesh_get_outline(stack->mesh, stack->path); } else { mesh_from_path(stack->mesh, stack->path); } } visual_3d_draw_2d(stack, tr_state); return; #endif case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); #ifndef GPAC_DISABLE_3D gf_bbox_from_rect(&tr_state->bbox, &tr_state->bounds); #endif return; case TRAVERSE_PICK: vrml_drawable_pick(stack, tr_state); return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; drawable_finalize_sort(ctx, tr_state, NULL); return; } }
static void TraverseIndexedCurve2D(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; IndexedCurve2D ic2d; GF_TraverseState *tr_state = (GF_TraverseState *)rs; Drawable *stack = (Drawable *)gf_node_get_private(node); if (is_destroy) { drawable_node_del(node); return; } if (gf_node_dirty_get(node)) { if (!IndexedCurve2D_GetNode(node, &ic2d)) return; curve2d_check_changes((GF_Node*) &ic2d, stack, tr_state, &ic2d.index); } switch (tr_state->traversing_mode) { #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: if (!stack->mesh) { stack->mesh = new_mesh(); mesh_from_path(stack->mesh, stack->path); } visual_3d_draw_2d(stack, tr_state); return; #endif case TRAVERSE_PICK: vrml_drawable_pick(stack, tr_state); return; case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; drawable_finalize_sort(ctx, tr_state, NULL); return; } }
static void TraverseCircle(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; Drawable *stack = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { drawable_node_del(node); return; } circle_check_changes(node, stack, tr_state); switch (tr_state->traversing_mode) { #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: if (!stack->mesh) { Fixed a = ((M_Circle *) node)->radius * 2; stack->mesh = new_mesh(); mesh_new_ellipse(stack->mesh, a, a, tr_state->visual->compositor->high_speed); } visual_3d_draw_2d(stack, tr_state); return; #endif case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); return; case TRAVERSE_PICK: vrml_drawable_pick(stack, tr_state); return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; drawable_finalize_sort(ctx, tr_state, NULL); return; } }
static void TraverseDisk2D(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; Drawable *stack = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { drawable_node_del(node); return; } disk2d_check_changes(node, stack, tr_state); switch (tr_state->traversing_mode) { #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: if (!stack->mesh) { stack->mesh = new_mesh(); /*FIXME - enable it with OpenGL-ES*/ mesh_from_path(stack->mesh, stack->path); } visual_3d_draw_2d(stack, tr_state); return; #endif case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); return; case TRAVERSE_PICK: vrml_drawable_pick(stack, tr_state); return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; drawable_finalize_sort(ctx, tr_state, NULL); return; } }
static void TraverseRectangle(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; Drawable *stack = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { drawable_node_del(node); return; } rectangle_check_changes(node, stack, tr_state); switch (tr_state->traversing_mode) { case TRAVERSE_DRAW_2D: compositor_2d_draw_rectangle(tr_state); return; #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: if (!stack->mesh) { stack->mesh = new_mesh(); mesh_new_rectangle(stack->mesh, ((M_Rectangle *) node)->size, NULL, 0); } visual_3d_draw_2d(stack, tr_state); return; #endif case TRAVERSE_PICK: vrml_drawable_pick(stack, tr_state); return; case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif break; default: return; } ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; /*if rotated, object is transparent (doesn't fill bounds) and antialias must be used*/ if (tr_state->transform.m[1] || tr_state->transform.m[3]) { } else { /*if alpha or not filled, transparent*/ if (ctx->aspect.fill_color && (GF_COL_A(ctx->aspect.fill_color) != 0xFF)) { } /*if texture transparent, transparent*/ else if (ctx->aspect.fill_texture && ctx->aspect.fill_texture->transparent) { } /*TODO check matrix for alpha*/ else if (!tr_state->color_mat.identity) { } /*otherwise, not transparent*/ else { ctx->flags &= ~CTX_IS_TRANSPARENT; } /*if no line width, we skip antialiasing*/ if (!ctx->aspect.pen_props.width) ctx->flags |= CTX_NO_ANTIALIAS; } drawable_finalize_sort(ctx, tr_state, NULL); }
static void svg_drawable_traverse(GF_Node *node, void *rs, Bool is_destroy, void (*rebuild_path)(GF_Node *, Drawable *, SVGAllAttributes *), Bool is_svg_rect, Bool is_svg_path) { GF_Matrix2D backup_matrix; GF_Matrix mx_3d; DrawableContext *ctx; SVGPropertiesPointers backup_props; u32 backup_flags; Drawable *drawable = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; SVGAllAttributes all_atts; if (is_destroy) { #if USE_GF_PATH /* The path is the same as the one in the SVG node, don't delete it here */ if (is_svg_path) drawable->path = NULL; #endif drawable_node_del(node); return; } assert(tr_state->traversing_mode!=TRAVERSE_DRAW_2D); if (tr_state->traversing_mode==TRAVERSE_PICK) { svg_drawable_pick(node, drawable, tr_state); return; } /*flatten attributes and apply animations + inheritance*/ gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); if (!compositor_svg_traverse_base(node, &all_atts, (GF_TraverseState *)rs, &backup_props, &backup_flags)) return; /* Recreates the path (i.e the shape) only if the node is dirty */ if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { /*the rebuild function is responsible for cleaning the path*/ rebuild_path(node, drawable, &all_atts); gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); drawable_mark_modified(drawable, tr_state); } if (drawable->path) { if (*(tr_state->svg_props->fill_rule)==GF_PATH_FILL_ZERO_NONZERO) { if (!(drawable->path->flags & GF_PATH_FILL_ZERO_NONZERO)) { drawable->path->flags |= GF_PATH_FILL_ZERO_NONZERO; drawable_mark_modified(drawable, tr_state); } } else { if (drawable->path->flags & GF_PATH_FILL_ZERO_NONZERO) { drawable->path->flags &= ~GF_PATH_FILL_ZERO_NONZERO; drawable_mark_modified(drawable, tr_state); } } } if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) { if (! compositor_svg_is_display_off(tr_state->svg_props)) { DrawAspect2D asp; gf_path_get_bounds(drawable->path, &tr_state->bounds); if (!tr_state->ignore_strike) { memset(&asp, 0, sizeof(DrawAspect2D)); drawable_get_aspect_2d_svg(node, &asp, tr_state); if (asp.pen_props.width) { StrikeInfo2D *si = drawable_get_strikeinfo(tr_state->visual->compositor, drawable, &asp, NULL, drawable->path, 0, NULL); if (si && si->outline) { gf_path_get_bounds(si->outline, &tr_state->bounds); } } } compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, NULL); if (!tr_state->abort_bounds_traverse) gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds); gf_sc_get_nodes_bounds(node, NULL, tr_state, NULL); compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, NULL); } } else if (tr_state->traversing_mode == TRAVERSE_SORT) { /*reset our flags - this may break reuse of nodes and change-detection in dirty-rect algo */ gf_node_dirty_clear(node, 0); if (!compositor_svg_is_display_off(tr_state->svg_props) && ( *(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN) ) { compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d); ctx = drawable_init_context_svg(drawable, tr_state); if (ctx) { if (is_svg_rect) { if (ctx->aspect.fill_texture && ctx->aspect.fill_texture->transparent) {} else if (GF_COL_A(ctx->aspect.fill_color) != 0xFF) {} else if (ctx->transform.m[1] || ctx->transform.m[3]) {} else { ctx->flags &= ~CTX_IS_TRANSPARENT; if (!ctx->aspect.pen_props.width) ctx->flags |= CTX_NO_ANTIALIAS; } } if (all_atts.pathLength && all_atts.pathLength->type==SVG_NUMBER_VALUE) ctx->aspect.pen_props.path_length = all_atts.pathLength->value; #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) { if (!drawable->mesh) { drawable->mesh = new_mesh(); if (drawable->path) mesh_from_path(drawable->mesh, drawable->path); } visual_3d_draw_from_context(ctx, tr_state); ctx->drawable = NULL; } else #endif { drawable_finalize_sort(ctx, tr_state, NULL); } } compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d); } } memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); tr_state->svg_flags = backup_flags; }
static void TraverseTriangleSet2D(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; Drawable *stack = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { drawable_node_del(node); return; } triangleset2d_check_changes(node, stack, tr_state); switch (tr_state->traversing_mode) { #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: if (!stack->mesh) { SFColorRGBA col; u32 i, count, idx; GF_Vertex v1, v2, v3; X_TriangleSet2D *p = (X_TriangleSet2D *)node; stack->mesh = new_mesh(); stack->mesh->mesh_type = MESH_TRIANGLES; col.red = col.green = col.blue = 0; col.alpha = FIX_ONE; v1.color = MESH_MAKE_COL(col); v1.normal.x = v1.normal.y = 0; v1.normal.z = MESH_NORMAL_UNIT; v1.pos.z = 0; v3 = v2 = v1; count = p->vertices.count; while (count%3) count--; for (i=0; i<count; i+=3) { idx = stack->mesh->v_count; v1.pos.x = p->vertices.vals[i].x; v1.pos.y = p->vertices.vals[i].y; v2.pos.x = p->vertices.vals[i+1].x; v2.pos.y = p->vertices.vals[i+1].y; v3.pos.x = p->vertices.vals[i+2].x; v3.pos.y = p->vertices.vals[i+2].y; mesh_set_vertex_vx(stack->mesh, &v1); mesh_set_vertex_vx(stack->mesh, &v2); mesh_set_vertex_vx(stack->mesh, &v3); gf_vec_diff(v2.pos, v2.pos, v1.pos); gf_vec_diff(v3.pos, v3.pos, v1.pos); v1.pos = gf_vec_cross(v2.pos, v3.pos); if (v1.pos.z<0) { mesh_set_triangle(stack->mesh, idx, idx+2, idx+1); } else { mesh_set_triangle(stack->mesh, idx, idx+1, idx+2); } } stack->mesh->flags |= MESH_IS_2D; mesh_update_bounds(stack->mesh); } visual_3d_draw_2d(stack, tr_state); return; #endif case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); return; case TRAVERSE_PICK: vrml_drawable_pick(stack, tr_state); return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; drawable_finalize_sort(ctx, tr_state, NULL); return; } }
static void TraverseIFS2D(GF_Node *node, void *rs, Bool is_destroy) { DrawableContext *ctx; M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node; Drawable *stack = (Drawable *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { drawable_node_del(node); return; } if (!ifs2D->coord) return; ifs2d_check_changes(node, stack, tr_state); switch (tr_state->traversing_mode) { case TRAVERSE_DRAW_2D: IFS2D_Draw(node, tr_state); return; #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: { DrawAspect2D asp; if (!stack->mesh) { stack->mesh = new_mesh(); mesh_new_ifs2d(stack->mesh, node); } memset(&asp, 0, sizeof(DrawAspect2D)); drawable_get_aspect_2d_mpeg4(node, &asp, tr_state); if (ifs2D->color && !GF_COL_A(asp.fill_color) ) { /*use special func to disable outline recompute and handle recompute ourselves*/ StrikeInfo2D *si = drawable_get_strikeinfo(tr_state->visual->compositor, stack, &asp, tr_state->appear, NULL, 0, tr_state); if (!si->mesh_outline) { si->mesh_outline = new_mesh(); mesh_new_ils(si->mesh_outline, ifs2D->coord, &ifs2D->coordIndex, ifs2D->color, &ifs2D->colorIndex, ifs2D->colorPerVertex, 1); } visual_3d_mesh_strike(tr_state, si->mesh_outline, asp.pen_props.width, asp.line_scale, asp.pen_props.dash); } else { visual_3d_draw_2d_with_aspect(stack, tr_state, &asp); } return; } #endif case TRAVERSE_PICK: vrml_drawable_pick(stack, tr_state); return; case TRAVERSE_GET_BOUNDS: gf_path_get_bounds(stack->path, &tr_state->bounds); return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(stack, tr_state); if (!ctx) return; drawable_finalize_sort(ctx, tr_state, NULL); return; } }