static void TraverseStyleGroup(GF_Node *node, void *rs, Bool is_destroy) { Bool set = 0; StyleGroupStack *stack = (StyleGroupStack *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *) rs; if (is_destroy) { gf_free(stack); return; } if (tr_state->traversing_mode==TRAVERSE_SORT) { if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); /*flag is not set for PROTO*/ gf_node_dirty_set(node, GF_SG_CHILD_DIRTY, 0); } } StyleGroup_GetNode(node, &stack->sg); if (!tr_state->override_appearance) { set = 1; tr_state->override_appearance = stack->sg.appearance; } group_2d_traverse((GF_Node *)&stack->sg, (GroupingNode2D*)stack, tr_state); if (set) { tr_state->override_appearance = NULL; } }
static void UpdateLinearGradient(GF_TextureHandler *txh) { u32 i, *cols; Fixed a; Bool const_a; M_LinearGradient *lg = (M_LinearGradient *) txh->owner; GradientStack *st = (GradientStack *) gf_node_get_private(txh->owner); if (!txh->hwtx) txh->hwtx = txh->compositor->r2d->stencil_new(txh->compositor->r2d, GF_STENCIL_LINEAR_GRADIENT); if (!gf_node_dirty_get(txh->owner)) return; gf_node_dirty_clear(txh->owner, 0); txh->needs_refresh = 1; st->txh.transparent = 0; const_a = (lg->opacity.count == 1) ? 1 : 0; cols = (u32*)malloc(sizeof(u32) * lg->key.count); for (i=0; i<lg->key.count; i++) { a = (const_a ? lg->opacity.vals[0] : lg->opacity.vals[i]); cols[i] = GF_COL_ARGB_FIXED(a, lg->keyValue.vals[i].red, lg->keyValue.vals[i].green, lg->keyValue.vals[i].blue); if (a != FIX_ONE) txh->transparent = 1; } txh->compositor->r2d->stencil_set_gradient_interpolation(txh->hwtx, lg->key.vals, cols, lg->key.count); free(cols); txh->compositor->r2d->stencil_set_gradient_mode(txh->hwtx, (GF_GradientMode) lg->spreadMethod); }
void drawable_3d_base_traverse(GF_Node *n, void *rs, Bool is_destroy, void (*build_shape)(GF_Node*,Drawable3D *,GF_TraverseState *) ) { GF_TraverseState *tr_state = (GF_TraverseState *)rs; Drawable3D *stack = (Drawable3D*)gf_node_get_private(n); if (is_destroy) { drawable_3d_del(n); return; } if (gf_node_dirty_get(n)) { mesh_reset(stack->mesh); GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor] Rebuilding mesh %s\n", gf_node_get_class_name(n))); build_shape(n, stack, tr_state); gf_node_dirty_clear(n, 0); } switch (tr_state->traversing_mode) { case TRAVERSE_DRAW_3D: visual_3d_draw(tr_state, stack->mesh); drawable3d_check_focus_highlight(n, tr_state, &stack->mesh->bounds); break; case TRAVERSE_GET_BOUNDS: tr_state->bbox = stack->mesh->bounds; break; case TRAVERSE_PICK: visual_3d_vrml_drawable_pick(n, tr_state, stack->mesh, NULL); return; } }
/*TransformMatrix2D*/ static void TraverseTransformMatrix2D(GF_Node *node, void *rs, Bool is_destroy) { Transform2DStack *ptr = (Transform2DStack *) gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { gf_sc_check_focus_upon_destroy(node); group_2d_destroy(node, (GroupingNode2D*)ptr); gf_free(ptr); return; } if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { M_TransformMatrix2D *tr = (M_TransformMatrix2D*)node; tr_mx2d_get_matrix(node, &ptr->mat); if ((tr->mxx==FIX_ONE) && (tr->mxy==0) && (tr->tx==0) && (tr->myx==0) && (tr->myy==FIX_ONE) && (tr->ty==0) ) ptr->is_identity = 1; else ptr->is_identity = 0; ptr->is_null = ( (!ptr->mat.m[0] && !ptr->mat.m[1]) || (!ptr->mat.m[3] && !ptr->mat.m[4]) ) ? 1 : 0; gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); } traverse_transform(node, ptr, tr_state); }
static void svg_animation_smil_update(GF_Node *node, SVGlinkStack *stack, Fixed normalized_scene_time) { if (stack->init_vis_state == 3) { stack->init_vis_state = 4; gf_mo_resume(stack->resource); } else if (stack->needs_play || (gf_node_dirty_get(node) & GF_SG_SVG_XLINK_HREF_DIRTY )) { SVGAllAttributes all_atts; Double clipBegin, clipEnd; GF_MediaObject *new_res; gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); clipBegin = all_atts.clipBegin ? *all_atts.clipBegin : 0; clipEnd = all_atts.clipEnd ? *all_atts.clipEnd : -1; if (stack->needs_play) { gf_mo_play(stack->resource, clipBegin, clipEnd, 0); stack->needs_play = 0; } else { Bool primary = all_atts.gpac_useAsPrimary ? *all_atts.gpac_useAsPrimary : 1; new_res = gf_mo_load_xlink_resource(node, primary, clipBegin, clipEnd); if (new_res != stack->resource) { if (stack->resource) gf_mo_unload_xlink_resource(node, stack->resource); if (all_atts.xlink_href) all_atts.xlink_href->target = NULL; stack->resource = new_res; stack->fragment_id = NULL; stack->inline_sg = NULL; } gf_node_dirty_clear(node, 0); } } }
static void build_indexed_triangle_fan_set(GF_Node *node, Drawable3D *stack, GF_TraverseState *tr_state) { MFInt32 fanList; u32 i, nb_fans; X_IndexedTriangleFanSet *itfs = (X_IndexedTriangleFanSet *)node; gf_node_dirty_clear(node, 0); if (!itfs->coord) return; fanList.count = 0; fanList.vals = NULL; nb_fans = 0; for (i=0; i<itfs->index.count; i++) { if (itfs->index.vals[i]==-1) { if (nb_fans>=3) { u32 *out_nb; gf_sg_vrml_mf_append(&fanList, GF_SG_VRML_MFINT32, (void **) &out_nb); *out_nb = nb_fans; } nb_fans = 0; } else { nb_fans++; } } if (nb_fans>=3) { u32 *out_nb; gf_sg_vrml_mf_append(&fanList, GF_SG_VRML_MFINT32, (void **) &out_nb); *out_nb = nb_fans; } BuildTriangleFanSet(stack->mesh, itfs->coord, itfs->color, itfs->texCoord, itfs->normal, &fanList, &itfs->index, itfs->normalPerVertex, itfs->ccw, itfs->solid); gf_sg_vrml_mf_reset(&fanList, GF_SG_VRML_MFINT32); }
void compositor_extrude_text(GF_Node *node, GF_TraverseState *tr_state, GF_Mesh *mesh, MFVec3f *thespine, Fixed creaseAngle, Bool begin_cap, Bool end_cap, MFRotation *spine_ori, MFVec2f *spine_scale, Bool txAlongSpine) { u32 i, count; Fixed min_cx, min_cy, width_cx, width_cy; TextStack *st = (TextStack *) gf_node_get_private(node); /*rebuild text node*/ if (gf_node_dirty_get(node)) { ParentNode2D *parent = tr_state->parent; tr_state->parent = NULL; text_clean_paths(tr_state->visual->compositor, st); drawable_reset_path(st->graph); gf_node_dirty_clear(node, 0); build_text(st, (M_Text *)node, tr_state); tr_state->parent = parent; } min_cx = st->bounds.x; min_cy = st->bounds.y - st->bounds.height; width_cx = st->bounds.width; width_cy = st->bounds.height; mesh_reset(mesh); count = gf_list_count(st->spans); for (i=0; i<count; i++) { GF_TextSpan *span = (GF_TextSpan *)gf_list_get(st->spans, i); GF_Path *span_path = gf_font_span_create_path(span); mesh_extrude_path_ext(mesh, span_path, thespine, creaseAngle, min_cx, min_cy, width_cx, width_cy, begin_cap, end_cap, spine_ori, spine_scale, txAlongSpine); gf_path_del(span_path); } mesh_update_bounds(mesh); gf_mesh_build_aabbtree(mesh); }
static void TraverseDepthViewPoint(GF_Node *node, void *rs, Bool is_destroy) { if (!is_destroy && gf_node_dirty_get(node)) { GF_TraverseState *tr_state = (GF_TraverseState *) rs; GF_FieldInfo field; gf_node_dirty_clear(node, 0); tr_state->visual->depth_vp_position = 0; tr_state->visual->depth_vp_range = 0; #ifndef GPAC_DISABLE_3D if (!tr_state->camera) return; tr_state->camera->flags |= CAM_IS_DIRTY; #endif if (gf_node_get_field(node, 0, &field) != GF_OK) return; if (field.fieldType != GF_SG_VRML_SFBOOL) return; if ( *(SFBool *) field.far_ptr) { if (gf_node_get_field(node, 1, &field) != GF_OK) return; if (field.fieldType != GF_SG_VRML_SFFLOAT) return; tr_state->visual->depth_vp_position = *(SFFloat *) field.far_ptr; if (gf_node_get_field(node, 2, &field) != GF_OK) return; if (field.fieldType != GF_SG_VRML_SFFLOAT) return; tr_state->visual->depth_vp_range = *(SFFloat *) field.far_ptr; } #ifndef GPAC_DISABLE_3D if (tr_state->layer3d) gf_node_dirty_set(tr_state->layer3d, GF_SG_NODE_DIRTY, 0); #endif gf_sc_invalidate(tr_state->visual->compositor, NULL); } }
static void svg_sani_render_path(GF_Node *node, void *rs, Bool is_destroy) { SVG_SANI_pathElement *path = (SVG_SANI_pathElement *)node; Drawable *cs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; if (is_destroy) { svg_sani_destroy_path(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { drawable_draw(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } svg_sani_render_base(node, eff); if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { #if USE_GF_PATH cs->path = &path->d; #else drawable_reset_path(cs); gf_svg_path_build(cs->path, path->d.commands, path->d.points); #endif if (path->fill_rule==GF_PATH_FILL_ZERO_NONZERO) cs->path->flags |= GF_PATH_FILL_ZERO_NONZERO; gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_sani_DrawablePostRender(cs, (SVG_SANI_TransformableElement *)path, eff, 0, (path->pathLength.type==SVG_NUMBER_VALUE) ? path->pathLength.value : 0); }
static void svg_sani_render_line(GF_Node *node, void *rs, Bool is_destroy) { SVG_SANI_lineElement *line = (SVG_SANI_lineElement *)node; Drawable *cs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; if (is_destroy) { DestroyDrawableNode(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { drawable_draw(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } svg_sani_render_base(node, (RenderEffect2D *)rs); if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { drawable_reset_path(cs); gf_path_add_move_to(cs->path, line->x1.value, line->y1.value); gf_path_add_line_to(cs->path, line->x2.value, line->y2.value); gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_sani_DrawablePostRender(cs, (SVG_SANI_TransformableElement *)line, (RenderEffect2D *)rs, 0, 0); }
static void svg_traverse_updates(GF_Node *node, void *rs, Bool is_destroy) { /*video stack is just an extension of image stack, type-casting is OK*/ SVG_updates_stack *stack = (SVG_updates_stack*)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; SVGAllAttributes all_atts; SVGPropertiesPointers backup_props; u32 backup_flags, dirty_flags; if (is_destroy) { if (stack->resource) { if (stack->is_open) { gf_mo_set_flag(stack->resource, GF_MO_DISPLAY_REMOVE, GF_TRUE); gf_mo_stop(stack->resource); } gf_mo_unregister(node, stack->resource); } gf_free(stack); return; } if (tr_state->traversing_mode!=TRAVERSE_SORT) 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; dirty_flags = gf_node_dirty_get(node); if (dirty_flags) { stack->clipBegin = all_atts.clipBegin ? *all_atts.clipBegin : 0; stack->clipEnd = all_atts.clipEnd ? *all_atts.clipEnd : -1; if (dirty_flags & GF_SG_SVG_XLINK_HREF_DIRTY) { GF_MediaObject *new_res; MFURL url; Bool lock_timeline=GF_FALSE; url.vals = NULL; url.count = 0; if (all_atts.syncBehavior) lock_timeline = (*all_atts.syncBehavior == SMIL_SYNCBEHAVIOR_LOCKED) ? GF_TRUE : GF_FALSE; gf_term_get_mfurl_from_xlink(node, &url); new_res = gf_mo_register(node, &url, lock_timeline, GF_FALSE); gf_sg_mfurl_del(url); if (stack->resource!=new_res) { if (stack->resource) { gf_mo_stop(stack->resource); gf_mo_unregister(node, stack->resource); } stack->resource = new_res; if (stack->resource && stack->is_open) gf_mo_play(stack->resource, stack->clipBegin, stack->clipEnd, GF_FALSE); } } gf_node_dirty_clear(node, 0); } memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); tr_state->svg_flags = backup_flags; }
static void TraverseTransform2D(GF_Node *node, void *rs, Bool is_destroy) { M_Transform2D *tr = (M_Transform2D *)node; Transform2DStack *ptr = (Transform2DStack *)gf_node_get_private(node); GF_TraverseState *tr_state; if (is_destroy) { gf_sc_check_focus_upon_destroy(node); group_2d_destroy(node, (GroupingNode2D*)ptr); gf_free(ptr); return; } tr_state = (GF_TraverseState *) rs; if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { gf_mx2d_init(ptr->mat); ptr->is_identity = 1; if ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE)) { gf_mx2d_add_scale_at(&ptr->mat, tr->scale.x, tr->scale.y, 0, 0, tr->scaleOrientation); ptr->is_identity = 0; } if (tr->rotationAngle) { gf_mx2d_add_rotation(&ptr->mat, tr->center.x, tr->center.y, tr->rotationAngle); ptr->is_identity = 0; } if (tr->translation.x || tr->translation.y) { ptr->is_identity = 0; gf_mx2d_add_translation(&ptr->mat, tr->translation.x, tr->translation.y); } gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); ptr->is_null = (!tr->scale.x || !tr->scale.y) ? 1 : 0; } traverse_transform(node, ptr, tr_state); }
static void TraverseDepthGroup(GF_Node *node, void *rs, Bool is_destroy) { #ifdef GF_SR_USE_DEPTH Fixed depth_gain, depth_offset; #endif DepthGroupStack *stack = (DepthGroupStack *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *) rs; if (is_destroy) { gf_free(stack); return; } if (tr_state->traversing_mode==TRAVERSE_SORT) { if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); /*flag is not set for PROTO*/ gf_node_dirty_set(node, GF_SG_CHILD_DIRTY, 0); } } DepthGroup_GetNode(node, &stack->dg); #ifdef GF_SR_USE_DEPTH depth_gain = tr_state->depth_gain; depth_offset = tr_state->depth_offset; // new offset is multiplied by parent gain and added to parent offset tr_state->depth_offset = gf_mulfix(stack->dg.depth_offset, tr_state->depth_gain) + tr_state->depth_offset; // gain is multiplied by parent gain tr_state->depth_gain = gf_mulfix(tr_state->depth_gain, stack->dg.depth_gain); #endif #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) { GF_Matrix mx_bckup, mx; gf_mx_copy(mx_bckup, tr_state->model_matrix); gf_mx_init(mx); mx.m[14] = gf_mulfix(stack->dg.depth_offset, tr_state->visual->compositor->depth_gl_scale); gf_mx_add_matrix(&tr_state->model_matrix, &mx); group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state); gf_mx_copy(tr_state->model_matrix, mx_bckup); } else #endif { group_2d_traverse((GF_Node *)&stack->dg, (GroupingNode2D*)stack, tr_state); } #ifdef GF_SR_USE_DEPTH tr_state->depth_gain = depth_gain; tr_state->depth_offset = depth_offset; #endif }
static void RenderSwitch(GF_Node *node, void *rs, Bool is_destroy) { GF_ChildNodeItem *l; u32 i, count; Bool prev_switch; GF_ChildNodeItem *children; s32 whichChoice; GF_Node *child; SwitchStack *st = (SwitchStack *)gf_node_get_private(node); RenderEffect2D *eff; eff = (RenderEffect2D *)rs; if (is_destroy) { free(st); return; } if (gf_node_get_name(node)) { node = node; } /*WARNING: X3D/MPEG4 NOT COMPATIBLE*/ if (gf_node_get_tag(node)==TAG_MPEG4_Switch) { children = ((M_Switch *)node)->choice; whichChoice = ((M_Switch *)node)->whichChoice; } else { children = ((X_Switch *)node)->children; whichChoice = ((X_Switch *)node)->whichChoice; } count = gf_node_list_get_count(children); prev_switch = eff->trav_flags; /*check changes in choice field*/ if ((gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) || (st->last_switch != whichChoice) ) { eff->trav_flags |= GF_SR_TRAV_SWITCHED_OFF; i=0; l = children; while (l) { // if ((s32) i!=whichChoice) gf_node_render(l->node, eff); if ((s32) i == st->last_switch) gf_node_render(l->node, eff); l = l->next; i++; } eff->trav_flags &= ~GF_SR_TRAV_SWITCHED_OFF; st->last_switch = whichChoice; } gf_node_dirty_clear(node, 0); /*no need to check for sensors since a sensor is active for the whole parent group, that is for switch itself CSQ: switch cannot be used to switch sensors, too bad...*/ eff->trav_flags = prev_switch; if (whichChoice>=0) { child = (GF_Node*)gf_node_list_get_child(children, whichChoice); gf_node_render(child, eff); } }
static void TraverseOrderedGroup(GF_Node *node, void *rs, Bool is_destroy) { u32 i, count; struct og_pos *priorities; Bool invalidate_backup; OrderedGroupStack *stack = (OrderedGroupStack *) gf_node_get_private(node); M_OrderedGroup *og = (M_OrderedGroup *) node; GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { gf_sc_check_focus_upon_destroy(node); group_2d_destroy(node, (GroupingNode2D*)stack); if (stack->positions) gf_free(stack->positions); gf_free(stack); return; } if (!og->order.count || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) { gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); group_2d_traverse(node, (GroupingNode2D*)stack, tr_state); return; } invalidate_backup = tr_state->invalidate_all; /*check whether the OrderedGroup node has changed*/ if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { if (stack->positions) gf_free(stack->positions); count = gf_node_list_get_count(og->children); priorities = (struct og_pos*)gf_malloc(sizeof(struct og_pos)*count); for (i=0; i<count; i++) { priorities[i].position = i; priorities[i].priority = (i<og->order.count) ? og->order.vals[i] : 0; } qsort(priorities, count, sizeof(struct og_pos), compare_priority); stack->positions = (u32*)gf_malloc(sizeof(u32) * count); for (i=0; i<count; i++) stack->positions[i] = priorities[i].position; gf_free(priorities); tr_state->invalidate_all = 1; gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); } group_2d_traverse_with_order(node, (GroupingNode2D*)stack, tr_state, stack->positions); tr_state->invalidate_all = invalidate_backup; }
static void ellipse_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { if (gf_node_dirty_get(node)) { drawable_reset_path(stack); gf_path_add_ellipse(stack->path, 0, 0, ((M_Ellipse *) node)->radius.x*2, ((M_Ellipse *) node)->radius.y*2); gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); } }
static void circle_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { if (gf_node_dirty_get(node)) { Fixed a = ((M_Circle *) node)->radius * 2; drawable_reset_path(stack); gf_path_add_ellipse(stack->path, 0, 0, a, a); gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); } }
static void rectangle_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { /*if modified update node - we don't update for other traversing mode in order not to mess up the dirty rect tracking (otherwise we would miss geometry changes with same bounds)*/ if (gf_node_dirty_get(node)) { drawable_reset_path(stack); gf_path_add_rect_center(stack->path, 0, 0, ((M_Rectangle *) node)->size.x, ((M_Rectangle *) node)->size.y); gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); } }
static void disk2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { if (gf_node_dirty_get(node)) { Fixed a = ((X_Disk2D *) node)->outerRadius * 2; drawable_reset_path(stack); gf_path_add_ellipse(stack->path, 0, 0, a, a); a = ((X_Disk2D *) node)->innerRadius * 2; if (a) gf_path_add_ellipse(stack->path, 0, 0, a, a); gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); } }
/*ColorTransform*/ static void TraverseColorTransform(GF_Node *node, void *rs, Bool is_destroy) { Bool c_changed; M_ColorTransform *tr = (M_ColorTransform *)node; ColorTransformStack *ptr = (ColorTransformStack *)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *) rs; Bool prev_inv; if (is_destroy) { gf_sc_check_focus_upon_destroy(node); group_2d_destroy(node, (GroupingNode2D*)ptr); gf_free(ptr); return; } if (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) { group_2d_traverse(node, (GroupingNode2D *) ptr, tr_state); return; } prev_inv = tr_state->invalidate_all; c_changed = 0; if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { gf_cmx_set(&ptr->cmat, tr->mrr , tr->mrg, tr->mrb, tr->mra, tr->tr, tr->mgr , tr->mgg, tr->mgb, tr->mga, tr->tg, tr->mbr, tr->mbg, tr->mbb, tr->mba, tr->tb, tr->mar, tr->mag, tr->mab, tr->maa, tr->ta); c_changed = 1; gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); } if ((tr_state->traversing_mode==TRAVERSE_SORT) && !tr->maa && !tr->mar && !tr->mag && !tr->mab && !tr->ta) return; /*if modified redraw all nodes*/ if (c_changed) tr_state->invalidate_all = 1; /*note we don't clear dirty flag, this is done in traversing*/ if (ptr->cmat.identity) { group_2d_traverse(node, (GroupingNode2D *) ptr, tr_state); } else { GF_ColorMatrix gf_cmx_bck; gf_cmx_copy(&gf_cmx_bck, &tr_state->color_mat); gf_cmx_multiply(&tr_state->color_mat, &ptr->cmat); group_2d_traverse(node, (GroupingNode2D *) ptr, tr_state); /*restore traversing state*/ gf_cmx_copy(&tr_state->color_mat, &gf_cmx_bck); } tr_state->invalidate_all = prev_inv; }
static void arc2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { if (gf_node_dirty_get(node)) { drawable_reset_path(stack); if (gf_node_get_tag(node)==TAG_X3D_Arc2D) { X_Arc2D *a = (X_Arc2D *) node; gf_path_add_arc(stack->path, a->radius, a->startAngle, a->endAngle, 0); } else { X_ArcClose2D *a = (X_ArcClose2D *) node; gf_path_add_arc(stack->path, a->radius, a->startAngle, a->endAngle, !stricmp(a->closureType.buffer, "PIE") ? 2 : 1); } gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); } }
static void text_check_changes(GF_Node *node, TextStack *stack, GF_TraverseState *tr_state) { if (gf_node_dirty_get(node) || tr_state->visual->compositor->reset_fonts) { text_clean_paths(tr_state->visual->compositor, stack); build_text(stack, (M_Text*)node, tr_state); gf_node_dirty_clear(node, 0); drawable_mark_modified(stack->graph, tr_state); } if (tr_state->visual->compositor->edited_text && (tr_state->visual->compositor->focus_node==node)) { drawable_mark_modified(stack->graph, tr_state); tr_state->visual->has_text_edit = 1; if (!stack->bounds.width) stack->bounds.width = INT2FIX(1)/100; if (!stack->bounds.height) stack->bounds.height = INT2FIX(1)/100; } }
static void polyline2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { if (gf_node_dirty_get(node)) { u32 i; X_Polyline2D *a = (X_Polyline2D *) node; drawable_reset_path(stack); for (i=0; i<a->lineSegments.count; i++) { if (i) { gf_path_add_line_to(stack->path, a->lineSegments.vals[i].x, a->lineSegments.vals[i].y); } else { gf_path_add_move_to(stack->path, a->lineSegments.vals[i].x, a->lineSegments.vals[i].y); } } gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); } }
static void triangleset2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { if (gf_node_dirty_get(node)) { u32 i, count; X_TriangleSet2D *p = (X_TriangleSet2D *)node; drawable_reset_path(stack); count = p->vertices.count; while (count%3) count--; for (i=0; i<count; i+=3) { gf_path_add_move_to(stack->path, p->vertices.vals[i].x, p->vertices.vals[i].y); gf_path_add_line_to(stack->path, p->vertices.vals[i+1].x, p->vertices.vals[i+1].y); gf_path_add_line_to(stack->path, p->vertices.vals[i+2].x, p->vertices.vals[i+2].y); gf_path_close(stack->path); } gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); } }
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); } }
static void UpdateRadialGradient(GF_TextureHandler *txh) { u32 i; M_RadialGradient *rg = (M_RadialGradient*) txh->owner; GradientStack *st = (GradientStack *) gf_node_get_private(txh->owner); if (!txh->hwtx) txh->hwtx = txh->compositor->r2d->stencil_new(txh->compositor->r2d, GF_STENCIL_RADIAL_GRADIENT); if (!gf_node_dirty_get(txh->owner)) return; gf_node_dirty_clear(txh->owner, 0); txh->needs_refresh = 1; st->txh.transparent = 0; for (i=0; i<rg->opacity.count; i++) { if (rg->opacity.vals[i] != FIX_ONE) { st->txh.transparent = 1; break; } } }
static void svg_sani_render_polygon(GF_Node *node, void *rs, Bool is_destroy) { SVG_SANI_polygonElement *polygon = (SVG_SANI_polygonElement *)node; Drawable *cs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; if (is_destroy) { DestroyDrawableNode(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { drawable_draw(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } svg_sani_render_base(node, (RenderEffect2D *)rs); if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { u32 i; u32 nbPoints = gf_list_count(polygon->points); drawable_reset_path(cs); if (nbPoints) { SVG_Point *p = (SVG_Point *)gf_list_get(polygon->points, 0); gf_path_add_move_to(cs->path, p->x, p->y); for (i = 1; i < nbPoints; i++) { p = (SVG_Point *)gf_list_get(polygon->points, i); gf_path_add_line_to(cs->path, p->x, p->y); } gf_path_close(cs->path); } else { gf_path_add_move_to(cs->path, 0, 0); } gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_sani_DrawablePostRender(cs, (SVG_SANI_TransformableElement *)polygon, (RenderEffect2D *)rs, 0, 0); }
static void pointset2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { u32 i; Fixed w, h; M_Coordinate2D *coord; if (!gf_node_dirty_get(node)) return; coord = (M_Coordinate2D *) ((M_PointSet2D *)node)->coord; drawable_reset_path(stack); get_point_size(&tr_state->transform, &w, &h); /*for PS2D don't add to avoid too much antialiasing, just try to fill the given pixel*/ for (i=0; i < coord->point.count; i++) gf_path_add_rect(stack->path, coord->point.vals[i].x, coord->point.vals[i].y, w, h); stack->path->flags |= GF_PATH_FILL_ZERO_NONZERO; gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); }
static void ils2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state) { u32 i; Bool started; SFVec2f *pts; M_IndexedLineSet2D *ils2D; M_Coordinate2D *coord; if (! gf_node_dirty_get(node)) return; drawable_reset_path(stack); gf_node_dirty_clear(node, 0); drawable_mark_modified(stack, tr_state); ils2D = (M_IndexedLineSet2D *)node; coord = (M_Coordinate2D *)ils2D->coord; pts = coord->point.vals; if (ils2D->coordIndex.count > 0) { started = 0; for (i=0; i < ils2D->coordIndex.count; i++) { /*NO close on ILS2D*/ if (ils2D->coordIndex.vals[i] == -1) { started = 0; } else if (!started) { started = 1; gf_path_add_move_to(stack->path, pts[ils2D->coordIndex.vals[i]].x, pts[ils2D->coordIndex.vals[i]].y); } else { gf_path_add_line_to(stack->path, pts[ils2D->coordIndex.vals[i]].x, pts[ils2D->coordIndex.vals[i]].y); } } } else if (coord->point.count) { gf_path_add_move_to(stack->path, pts[0].x, pts[0].y); for (i=1; i < coord->point.count; i++) { gf_path_add_line_to(stack->path, pts[i].x, pts[i].y); } } stack->path->flags |= GF_PATH_FILL_ZERO_NONZERO; }
static void TraverseAnchor(GF_Node *node, void *rs, Bool is_destroy) { AnchorStack *st = (AnchorStack *) gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { mpeg4_sensor_deleted(node, &st->hdl); gf_sc_check_focus_upon_destroy(node); if (st->sensors) gf_list_del(st->sensors); gf_free(st); return; } if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { MFURL *url = NULL; switch (gf_node_get_tag(node)) { case TAG_MPEG4_Anchor: url = & ((M_Anchor *)node)->url; break; #ifndef GPAC_DISABLE_X3D case TAG_X3D_Anchor: url = & ((X_Anchor *)node)->url; break; #endif } st->enabled = 0; if (url && url->count && url->vals[0].url && strlen(url->vals[0].url) ) st->enabled = 1; if (!tr_state->visual->compositor->user->EventProc) { st->enabled = 0; } gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); } group_2d_traverse(node, (GroupingNode2D*)st, tr_state); }