static void PointSet2D_Draw(GF_Node *node, GF_TraverseState *tr_state) { GF_Path *path; Fixed alpha, w, h; u32 i; SFColor col; DrawableContext *ctx = tr_state->ctx; M_PointSet2D *ps2D = (M_PointSet2D *)node; M_Coordinate2D *coord = (M_Coordinate2D*) ps2D->coord; M_Color *color = (M_Color *) ps2D->color; /*never outline PS2D*/ ctx->flags |= CTX_PATH_STROKE; if (!color || color->color.count<coord->point.count) { /*no texturing*/ visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state); return; } get_point_size(&ctx->transform, &w, &h); path = gf_path_new(); alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255; for (i = 0; i < coord->point.count; i++) { col = color->color.vals[i]; ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); gf_path_add_rect_center(path, coord->point.vals[i].x, coord->point.vals[i].y, w, h); visual_2d_draw_path(tr_state->visual, path, ctx, NULL, NULL, tr_state); gf_path_reset(path); ctx->flags &= ~CTX_PATH_FILLED; } gf_path_del(path); }
static void compositor_2d_draw_rectangle(GF_TraverseState *tr_state) { DrawableContext *ctx = tr_state->ctx; if (ctx->aspect.fill_texture && ctx->aspect.fill_texture->data #ifndef GPAC_DISABLE_3D && !tr_state->visual->compositor->hybrid_opengl #endif ) { Bool res; /*get image size WITHOUT line size or antialias margin*/ if ( !(ctx->flags & CTX_NO_ANTIALIAS) ) { GF_Rect orig_unclip; GF_IRect orig_clip; orig_unclip = ctx->bi->unclip; orig_clip = ctx->bi->clip; gf_path_get_bounds(ctx->drawable->path, &ctx->bi->unclip); gf_mx2d_apply_rect(&ctx->transform, &ctx->bi->unclip); ctx->bi->clip = gf_rect_pixelize(&ctx->bi->unclip); gf_irect_intersect(&ctx->bi->clip, &orig_clip); res = tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx, NULL); /*strike path*/ ctx->bi->unclip = orig_unclip; ctx->bi->clip = orig_clip; if (res) { ctx->flags |= CTX_PATH_FILLED; visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state); } } else { res = tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx, NULL); } /*if failure retry with raster*/ if (res) return; } visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state); visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state); }
void visual_2d_texture_path(GF_VisualManager *visual, GF_Path *path, struct _drawable_context *ctx, GF_TraverseState *tr_state) { #ifdef SKIP_DRAW return; #endif if (!visual->is_attached || (ctx->flags & CTX_PATH_FILLED) || !ctx->aspect.fill_texture || visual->compositor->is_hidden) return; /*this is ambiguous in the spec, what if the material is filled and the texture is transparent ? let's draw, it's nicer */ #if 0 if (GF_COL_A(ctx->aspect.fill_color) && ctx->aspect.fill_texture->transparent) { visual_2d_draw_path(visual, path, ctx, NULL, NULL); ctx->flags &= ~CTX_PATH_FILLED; } #endif visual_2d_texture_path_extended(visual, path, NULL, ctx, NULL, NULL, tr_state); }
static void fs_traverse(GF_Node *node, void *rs, Bool is_destroy) { u32 i; DrawableContext *ctx; FSStack *st = (FSStack *) gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState*)rs; if (is_destroy) { clean_paths(st); drawable_del(st->drawable); gf_list_del(st->items); gf_free(st); return; } /*check for geometry change*/ if (gf_node_dirty_get(node)) { gf_node_dirty_clear(node, 0); /*build*/ clean_paths(st); build_shape(st, node); } switch (tr_state->traversing_mode) { case TRAVERSE_DRAW_2D: ctx = tr_state->ctx; for (i=0; i<gf_list_count(st->items); i++) { FSItem *item = gf_list_get(st->items, i); ctx->flags &= ~(CTX_PATH_FILLED | CTX_PATH_STROKE); memset(&ctx->aspect, 0, sizeof(DrawAspect2D)); if (item->fill_col) { ctx->aspect.fill_color = item->fill_col; } if (item->width) { ctx->aspect.line_color = item->line_col; ctx->aspect.pen_props.width = item->width; } visual_2d_draw_path(tr_state->visual, item->path, ctx, NULL, NULL, tr_state); } return; #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: ctx = tr_state->ctx; for (i=0; i<gf_list_count(st->items); i++) { FSItem *item = gf_list_get(st->items, i); memset(&ctx->aspect, 0, sizeof(DrawAspect2D)); if (item->fill_col) { ctx->aspect.fill_color = item->fill_col; } if (item->width) { ctx->aspect.line_color = item->line_col; ctx->aspect.pen_props.width = item->width; } if (!item->mesh) { item->mesh = new_mesh(); mesh_from_path(item->mesh, item->path); } st->drawable->mesh = item->mesh; visual_3d_draw_2d_with_aspect(st->drawable, tr_state, &ctx->aspect); st->drawable->mesh = NULL; } return; #endif case TRAVERSE_PICK: /*todo*/ return; case TRAVERSE_GET_BOUNDS: tr_state->bounds = st->bounds; return; case TRAVERSE_SORT: #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif /*finalize*/ ctx = drawable_init_context_mpeg4(st->drawable, tr_state); if (!ctx) return; /*force width to max width used for clipper compute*/ if (st->max_width) { ctx->aspect.pen_props.width = st->max_width; } drawable_finalize_sort(ctx, tr_state, &st->bounds); break; } }
static void ILS2D_Draw(GF_Node *node, GF_TraverseState *tr_state) { GF_Path *path; SFVec2f *pts; SFColor col; Fixed alpha; u32 i, count, col_ind, ind, end_at; u32 linear[2], *colors; SFVec2f start, end; u32 j, num_col; GF_STENCIL grad; GF_Raster2D *raster; DrawableContext *ctx = tr_state->ctx; M_IndexedLineSet2D *ils2D = (M_IndexedLineSet2D *)node; M_Coordinate2D *coord = (M_Coordinate2D*) ils2D->coord; M_Color *color = (M_Color *) ils2D->color; end.x = end.y = 0; if (!coord->point.count) return; if (! ils2D->color) { /*no texturing*/ visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state); return; } alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255; pts = coord->point.vals; if (!ils2D->colorPerVertex || (color->color.count<2) ) { count = 0; end_at = ils2D->coordIndex.count; if (!end_at) end_at = coord->point.count; ind = ils2D->coordIndex.count ? ils2D->coordIndex.vals[0] : 0; i=1; path = gf_path_new(); gf_path_add_move_to(path, pts[ind].x, pts[ind].y); for (; i<=end_at; i++) { if ((i==end_at) || (ils2D->coordIndex.count && ils2D->coordIndex.vals[i] == -1)) { /*draw current*/ col_ind = (ils2D->colorIndex.count && (ils2D->colorIndex.vals[count]>=0) ) ? (u32) ils2D->colorIndex.vals[count] : count; if (col_ind>=color->color.count) col_ind=color->color.count-1; col = color->color.vals[col_ind]; ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); visual_2d_draw_path(tr_state->visual, path, ctx, NULL, NULL, tr_state); i++; if (i>=end_at) break; gf_path_reset(path); ind = (ils2D->coordIndex.count && (ils2D->coordIndex.vals[i]>=0)) ? (u32) ils2D->coordIndex.vals[i] : i; gf_path_add_move_to(path, pts[ind].x, pts[ind].y); if (ils2D->coordIndex.count) count++; continue; } else { ind = (ils2D->coordIndex.count && (ils2D->coordIndex.vals[i]>=0) ) ? (u32) ils2D->coordIndex.vals[i] : i; gf_path_add_line_to(path, pts[ind].x, pts[ind].y); } } gf_path_del(path); return; } raster = NULL; end_at = ils2D->coordIndex.count; if (!end_at) end_at = coord->point.count; count = 0; col_ind = 0; ind = 0; i=0; path = gf_path_new(); while (1) { gf_path_reset(path); ind = (ils2D->coordIndex.count && (ils2D->coordIndex.vals[i]>=0)) ? (u32) ils2D->coordIndex.vals[i] : i; start = pts[ind]; num_col = 1; i++; gf_path_add_move_to(path, start.x, start.y); if (ils2D->coordIndex.count) { while (ils2D->coordIndex.vals[i] != -1) { end = pts[ils2D->coordIndex.vals[i]]; gf_path_add_line_to(path, end.x, end.y); i++; num_col++; if (i >= ils2D->coordIndex.count) break; } } else { while (i<end_at) { end = pts[i]; gf_path_add_line_to(path, end.x, end.y); i++; num_col++; } } raster = tr_state->visual->compositor->rasterizer; /*use linear gradient*/ if (num_col==2) { Fixed pos[2]; grad = raster->stencil_new(raster, GF_STENCIL_LINEAR_GRADIENT); if (ils2D->colorIndex.count) { col = color->color.vals[ils2D->colorIndex.vals[col_ind]]; linear[0] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); col = color->color.vals[ils2D->colorIndex.vals[col_ind+1]]; linear[1] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); } else if (ils2D->coordIndex.count) { col = color->color.vals[ils2D->coordIndex.vals[col_ind]]; linear[0] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); col = color->color.vals[ils2D->coordIndex.vals[col_ind+1]]; linear[1] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); } else { col = color->color.vals[col_ind]; linear[0] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); col = color->color.vals[col_ind+1]; linear[1] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); } pos[0] = 0; pos[1] = FIX_ONE; raster->stencil_set_linear_gradient(grad, start.x, start.y, end.x, end.y); raster->stencil_set_gradient_interpolation(grad, pos, linear, 2); } else { grad = raster->stencil_new(raster, GF_STENCIL_VERTEX_GRADIENT); if (grad) { raster->stencil_set_vertex_path(grad, path); colors = (u32*)gf_malloc(sizeof(u32) * num_col); for (j=0; j<num_col; j++) { if (ils2D->colorIndex.count>0) { col = color->color.vals[ils2D->colorIndex.vals[col_ind+j]]; } else if (ils2D->coordIndex.count) { col = color->color.vals[ils2D->coordIndex.vals[col_ind+j]]; } else { col = color->color.vals[col_ind+j]; } colors[j] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); } raster->stencil_set_vertex_colors(grad, colors, num_col); gf_free(colors); } } raster->stencil_set_matrix(grad, &ctx->transform); visual_2d_draw_path(tr_state->visual, path, ctx, NULL, grad, tr_state); if (grad) raster->stencil_delete(grad); i ++; col_ind += num_col + 1; if (i >= ils2D->coordIndex.count) break; ctx->flags &= ~CTX_PATH_STROKE; } gf_path_del(path); }
static void IFS2D_Draw(GF_Node *node, GF_TraverseState *tr_state) { u32 i, count, ci_count; u32 j, ind_col, num_col; SFVec2f center, end; SFColor col_cen; GF_STENCIL grad; u32 *colors; GF_Path *path; SFVec2f start; SFVec2f *pts; SFColor col; Fixed alpha; GF_Raster2D *raster; DrawableContext *ctx = tr_state->ctx; M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node; M_Coordinate2D *coord = (M_Coordinate2D*) ifs2D->coord; M_Color *color = (M_Color *) ifs2D->color; col.red = col.green = col.blue = 0; /*simple case, no color specified*/ if (!ifs2D->color) { visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state); visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state); return; } /*if default face use first color*/ ci_count = ifs2D->coordIndex.count; pts = coord->point.vals; if (ci_count == 0) { col = (ifs2D->colorIndex.count > 0) ? color->color.vals[ifs2D->colorIndex.vals[0]] : color->color.vals[0]; alpha = INT2FIX(GF_COL_A(ctx->aspect.fill_color)) / 255; if (!alpha || !ctx->aspect.pen_props.width) { alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255; ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); } else { ctx->aspect.fill_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); } visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state); visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state); return; } /*we have color per faces so we need N path :(*/ if (! ifs2D->colorPerVertex) { path = gf_path_new(); count = 0; i = 0; while (1) { gf_path_reset(path); start = pts[ifs2D->coordIndex.vals[i]]; gf_path_add_move_to(path, start.x, start.y); i++; while (ifs2D->coordIndex.vals[i] != -1) { start = pts[ifs2D->coordIndex.vals[i]]; gf_path_add_line_to(path, start.x, start.y); i++; if (i >= ci_count) break; } /*close in ALL cases because even if the start/end points are the same the line join needs to be present*/ gf_path_close(path); col = (ifs2D->colorIndex.count > 0) ? color->color.vals[ifs2D->colorIndex.vals[count]] : color->color.vals[count]; alpha = INT2FIX(GF_COL_A(ctx->aspect.fill_color)) / 255; if (!alpha) { alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255; ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); } else { ctx->aspect.fill_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); } visual_2d_texture_path(tr_state->visual, path, ctx, tr_state); visual_2d_draw_path(tr_state->visual, path, ctx, NULL, NULL, tr_state); count++; i++; if (i >= ci_count) break; ctx->flags &= ~CTX_PATH_FILLED; ctx->flags &= ~CTX_PATH_STROKE; } gf_path_del(path); return; } /*final case, color per vertex means gradient fill/strike*/ raster = tr_state->visual->compositor->rasterizer; grad = raster->stencil_new(raster, GF_STENCIL_VERTEX_GRADIENT); /*not supported, fill default*/ if (!grad) { visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state); visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state); return; } path = gf_path_new(); ind_col = 0; i = 0; while (1) { gf_path_reset(path); start = pts[ifs2D->coordIndex.vals[i]]; center = start; gf_path_add_move_to(path, start.x, start.y); num_col = 1; i+=1; while (ifs2D->coordIndex.vals[i] != -1) { end = pts[ifs2D->coordIndex.vals[i]]; gf_path_add_line_to(path, end.x, end.y); i++; center.x += end.x; center.y += end.y; num_col ++; if (i >= ci_count) break; } gf_path_close(path); num_col++; alpha = INT2FIX(GF_COL_A(ctx->aspect.fill_color) ) / 255; colors = (u32*)gf_malloc(sizeof(u32) * num_col); col_cen.blue = col_cen.red = col_cen.green = 0; for (j=0; j<num_col-1; j++) { if (ifs2D->colorIndex.count > ind_col + j) { col = color->color.vals[ifs2D->colorIndex.vals[ind_col + j]]; } else if (ci_count > ind_col + j) { col = color->color.vals[ifs2D->coordIndex.vals[ind_col + j]]; } colors[j] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue); col_cen.blue += col.blue; col_cen.green += col.green; col_cen.red += col.red; } colors[num_col-1] = colors[0]; if (ifs2D->colorIndex.count > ind_col) { col = color->color.vals[ifs2D->colorIndex.vals[ind_col]]; } else if (ci_count > ind_col) { col = color->color.vals[ifs2D->coordIndex.vals[ind_col]]; } col_cen.blue += col.blue; col_cen.green += col.green; col_cen.red += col.red; raster->stencil_set_vertex_path(grad, path); raster->stencil_set_vertex_colors(grad, colors, num_col); gf_free(colors); col_cen.blue /= num_col; col_cen.green /= num_col; col_cen.red /= num_col; center.x /= num_col; center.y /= num_col; raster->stencil_set_vertex_center(grad, center.x, center.y, GF_COL_ARGB_FIXED(alpha, col_cen.red, col_cen.green, col_cen.blue) ); raster->stencil_set_matrix(grad, &ctx->transform); /*draw*/ visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, grad, grad, tr_state); raster->stencil_delete(grad); //goto next point i++; ind_col += num_col + 1; if (i >= ci_count) break; grad = raster->stencil_new(raster, GF_STENCIL_VERTEX_GRADIENT); ctx->flags &= ~CTX_PATH_FILLED; ctx->flags &= ~CTX_PATH_STROKE; } gf_path_del(path); }