static void SVG_Draw_bitmap(GF_TraverseState *tr_state) { DrawableContext *ctx = tr_state->ctx; if (!tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx, NULL)) { visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state); } }
static void layer3d_draw_2d(GF_Node *node, GF_TraverseState *tr_state) { DrawableContext *ctx = tr_state->ctx; if (tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx, NULL)) return; visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state); }
void group_cache_draw(GroupCache *cache, GF_TraverseState *tr_state) { GF_TextureHandler *old_txh = tr_state->ctx->aspect.fill_texture; /*switch the texture to our offscreen cache*/ tr_state->ctx->aspect.fill_texture = &cache->txh; if (! tr_state->visual->DrawBitmap(tr_state->visual, tr_state, tr_state->ctx, NULL)) { visual_2d_texture_path(tr_state->visual, cache->drawable->path, tr_state->ctx, tr_state); } tr_state->ctx->aspect.fill_texture = old_txh; }
static void DrawBackground2D_2D(DrawableContext *ctx, GF_TraverseState *tr_state) { Background2DStack *stack; if (!ctx || !ctx->drawable || !ctx->drawable->node) return; stack = (Background2DStack *) gf_node_get_private(ctx->drawable->node); if (!ctx->bi->clip.width || !ctx->bi->clip.height) return; stack->flags &= ~CTX_PATH_FILLED; if (back_use_texture((M_Background2D *)ctx->drawable->node)) { if (!tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx, NULL)) { /*set target rect*/ gf_path_reset(stack->drawable->path); gf_path_add_rect_center(stack->drawable->path, ctx->bi->unclip.x + ctx->bi->unclip.width/2, ctx->bi->unclip.y - ctx->bi->unclip.height/2, ctx->bi->unclip.width, ctx->bi->unclip.height); /*draw texture*/ visual_2d_texture_path(tr_state->visual, stack->drawable->path, ctx, tr_state); } stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY); } else { /*direct drawing, draw without clippers */ if (tr_state->immediate_draw) { /*directly clear with specified color*/ tr_state->visual->ClearSurface(tr_state->visual, &ctx->bi->clip, ctx->aspect.fill_color); } else { u32 i; GF_IRect clip; for (i=0; i<tr_state->visual->to_redraw.count; i++) { /*there's an opaque region above, don't draw*/ #ifdef TRACK_OPAQUE_REGIONS if (tr_state->visual->draw_node_index<tr_state->visual->to_redraw.opaque_node_index[i]) continue; #endif clip = ctx->bi->clip; gf_irect_intersect(&clip, &tr_state->visual->to_redraw.list[i]); if (clip.width && clip.height) { tr_state->visual->ClearSurface(tr_state->visual, &clip, ctx->aspect.fill_color); } } } stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY); } tr_state->visual->has_modif = 1; }
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); }
static void svg_traverse_filter(GF_Node *node, void *rs, Bool is_destroy) { GF_TraverseState *tr_state = (GF_TraverseState *)rs; GF_FilterStack *st = gf_node_get_private(node); if (is_destroy) { drawable_del(st->drawable); if (st->data) gf_free(st->data); st->txh.data = NULL; gf_sc_texture_release(&st->txh); gf_sc_texture_destroy(&st->txh); gf_free(st); return; } if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) { if (! tr_state->visual->DrawBitmap(tr_state->visual, tr_state, tr_state->ctx, NULL)) { visual_2d_texture_path(tr_state->visual, st->drawable->path, tr_state->ctx, tr_state); } } }
void group_cache_draw(GroupCache *cache, GF_TraverseState *tr_state) { GF_TextureHandler *old_txh = tr_state->ctx->aspect.fill_texture; /*switch the texture to our offscreen cache*/ tr_state->ctx->aspect.fill_texture = &cache->txh; #ifndef GPAC_DISABLE_3D if (tr_state->traversing_mode == TRAVERSE_DRAW_3D) { if (!cache->drawable->mesh) { cache->drawable->mesh = new_mesh(); } mesh_from_path(cache->drawable->mesh, cache->drawable->path); visual_3d_draw_2d(cache->drawable, tr_state); return; } #endif if (! tr_state->visual->DrawBitmap(tr_state->visual, tr_state, tr_state->ctx, NULL)) { visual_2d_texture_path(tr_state->visual, cache->drawable->path, tr_state->ctx, tr_state); } tr_state->ctx->aspect.fill_texture = old_txh; }
static void DrawBackground2D_2D(DrawableContext *ctx, GF_TraverseState *tr_state) { Bool clear_all = GF_TRUE; u32 color; Bool use_texture; Bool is_offscreen = GF_FALSE; Background2DStack *stack; if (!ctx || !ctx->drawable || !ctx->drawable->node) return; stack = (Background2DStack *) gf_node_get_private(ctx->drawable->node); if (!ctx->bi->clip.width || !ctx->bi->clip.height) return; stack->flags &= ~CTX_PATH_FILLED; color = ctx->aspect.fill_color; use_texture = back_use_texture((M_Background2D *)ctx->drawable->node); if (!use_texture && !tr_state->visual->is_attached) { use_texture = 1; stack->txh.data = stack->col_tx; stack->txh.width = 2; stack->txh.height = 2; stack->txh.stride = 6; stack->txh.pixelformat = GF_PIXEL_RGB_24; } if (use_texture) { if (!tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx)) { /*set target rect*/ gf_path_reset(stack->drawable->path); gf_path_add_rect_center(stack->drawable->path, ctx->bi->unclip.x + ctx->bi->unclip.width/2, ctx->bi->unclip.y - ctx->bi->unclip.height/2, ctx->bi->unclip.width, ctx->bi->unclip.height); /*draw texture*/ visual_2d_texture_path(tr_state->visual, stack->drawable->path, ctx, tr_state); } //a quick hack, if texture not ready return (we don't have direct notification of this through the above functions #ifndef GPAC_DISABLE_3D if (tr_state->visual->compositor->hybrid_opengl && !stack->txh.tx_io) return; #endif stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY); tr_state->visual->has_modif = 1; #ifndef GPAC_DISABLE_3D //in opengl auto mode we still have to clear the canvas if (!tr_state->immediate_draw && !tr_state->visual->offscreen && tr_state->visual->compositor->hybrid_opengl) { clear_all = GF_FALSE; is_offscreen = GF_TRUE; color &= 0x00FFFFFF; } else #endif return; } #ifndef GPAC_DISABLE_3D if (ctx->flags & CTX_BACKROUND_NOT_LAYER) { if (clear_all && !tr_state->visual->offscreen && tr_state->visual->compositor->hybrid_opengl) { compositor_2d_hybgl_clear_surface(tr_state->visual, NULL, color, GF_FALSE); is_offscreen = GF_TRUE; color &= 0x00FFFFFF; //we may need to clear the canvas for immediate mode } } else { is_offscreen = GF_TRUE; } #endif /*direct drawing, draw without clippers */ if (tr_state->immediate_draw ) { /*directly clear with specified color*/ if (clear_all) tr_state->visual->ClearSurface(tr_state->visual, &ctx->bi->clip, color, is_offscreen); } else { u32 i; GF_IRect clip; for (i=0; i<tr_state->visual->to_redraw.count; i++) { /*there's an opaque region above, don't draw*/ #ifdef TRACK_OPAQUE_REGIONS if (tr_state->visual->draw_node_index < tr_state->visual->to_redraw.list[i].opaque_node_index) continue; #endif clip = ctx->bi->clip; gf_irect_intersect(&clip, &tr_state->visual->to_redraw.list[i].rect); if (clip.width && clip.height) { tr_state->visual->ClearSurface(tr_state->visual, &clip, color, is_offscreen); } } } stack->flags &= ~(CTX_APP_DIRTY | CTX_TEXTURE_DIRTY); tr_state->visual->has_modif = 1; }
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); }