static Bool composite2d_draw_bitmap(GF_VisualManager *visual, GF_TraverseState *tr_state, struct _drawable_context *ctx, GF_ColorKey *col_key) { u8 alpha = 0xFF; GF_VideoSurface offscreen_dst, video_src; GF_Window src_wnd, dst_wnd; Bool use_blit, has_scale; CompositeTextureStack *st; if (visual->compositor->disable_composite_blit) return 0; if (!ctx->aspect.fill_texture) return 1; if (ctx->transform.m[0]<0) return 0; if (ctx->transform.m[4]<0) { if (!(ctx->flags & CTX_FLIPED_COORDS)) return 0; } else { if (ctx->flags & CTX_FLIPED_COORDS) return 0; } if (ctx->transform.m[1] || ctx->transform.m[3]) return 0; #ifndef GPAC_DISABLE_VRML if ((ctx->flags & CTX_HAS_APPEARANCE) && ctx->appear && ((M_Appearance*)ctx->appear)->textureTransform) return 0; #endif alpha = GF_COL_A(ctx->aspect.fill_color); /*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/ if (!alpha) alpha = GF_COL_A(ctx->aspect.line_color); if (!alpha) return 1; st = (CompositeTextureStack *) gf_node_get_private(visual->offscreen); if (!compositor_texture_rectangles(visual, ctx->aspect.fill_texture, &ctx->bi->clip, &ctx->bi->unclip, &src_wnd, &dst_wnd, &use_blit, &has_scale)) return 1; memset(&video_src, 0, sizeof(GF_VideoSurface)); video_src.height = ctx->aspect.fill_texture->height; video_src.width = ctx->aspect.fill_texture->width; video_src.pitch_x = 0; video_src.pitch_y = ctx->aspect.fill_texture->stride; video_src.pixel_format = ctx->aspect.fill_texture->pixelformat; #ifdef GF_SR_USE_DEPTH if (ctx->aspect.fill_texture->pixelformat==GF_PIXEL_YUVD) video_src.pixel_format = GF_PIXEL_YV12; #endif video_src.video_buffer = ctx->aspect.fill_texture->data; memset(&offscreen_dst, 0, sizeof(GF_VideoSurface)); offscreen_dst.width = st->txh.width; offscreen_dst.height = st->txh.height; offscreen_dst.pitch_y = st->txh.stride; offscreen_dst.pixel_format = st->txh.pixelformat; offscreen_dst.video_buffer = st->txh.data; gf_stretch_bits(&offscreen_dst, &video_src, &dst_wnd, &src_wnd, alpha, 0, col_key, ctx->col_mat); return 1; }
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); }
void VS2D_TexturePathText(VisualSurface2D *surf, DrawableContext *txt_ctx, GF_Path *path, GF_Rect *object_bounds, GF_HWTEXTURE hwtx, GF_Rect *gf_sr_texture_bounds) { Fixed sS, sT; GF_Matrix2D gf_mx2d_txt; GF_Rect rc, orig_rc; u8 alpha, r, g, b; GF_ColorMatrix cmat; GF_Raster2D *r2d = surf->render->compositor->r2d; VS2D_SetOptions(surf->render, surf->the_surface, 0, 1); /*get original bounds*/ orig_rc = *object_bounds; rc = *gf_sr_texture_bounds; /*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/ sS = gf_divfix(orig_rc.width, rc.width); sT = gf_divfix(orig_rc.height, rc.height); gf_mx2d_init(gf_mx2d_txt); gf_mx2d_add_scale(&gf_mx2d_txt, sS, sT); /*move to bottom-left corner of bounds */ gf_mx2d_add_translation(&gf_mx2d_txt, (orig_rc.x), (orig_rc.y - orig_rc.height)); /*move to final coordinate system*/ gf_mx2d_add_matrix(&gf_mx2d_txt, &txt_ctx->transform); /*set path transform, except for background2D node which is directly build in the final coord system*/ r2d->stencil_set_matrix(hwtx, &gf_mx2d_txt); alpha = GF_COL_A(txt_ctx->aspect.fill_color); r = GF_COL_R(txt_ctx->aspect.fill_color); g = GF_COL_G(txt_ctx->aspect.fill_color); b = GF_COL_B(txt_ctx->aspect.fill_color); /*if col do a cxmatrix*/ if (!r && !g && !b) { r2d->stencil_set_texture_alpha(hwtx, alpha); } else { r2d->stencil_set_texture_alpha(hwtx, 0xFF); memset(cmat.m, 0, sizeof(Fixed) * 20); cmat.m[4] = INT2FIX(r)/255; cmat.m[9] = INT2FIX(g)/255; cmat.m[14] = INT2FIX(b)/255; cmat.m[18] = INT2FIX(alpha)/255; cmat.identity = 0; r2d->stencil_set_color_matrix(hwtx, &cmat); } r2d->surface_set_matrix(surf->the_surface, &txt_ctx->transform); /*push path*/ r2d->surface_set_path(surf->the_surface, path); VS2D_DoFill(surf, txt_ctx, hwtx); r2d->surface_set_path(surf->the_surface, NULL); txt_ctx->flags |= CTX_PATH_FILLED; }
/** * function DirectFBVid_DrawRectangle * - using hardware accelerator to fill a rectangle **/ static void DirectFBVid_DrawRectangle(GF_VideoOutput *driv, u32 x, u32 y, u32 width, u32 height, GF_Color color) { u8 r = GF_COL_R(color); u8 g = GF_COL_G(color); u8 b = GF_COL_B(color); u8 a = GF_COL_A(color); DirectFBVID(); DirectFBVid_DrawRectangleWrapper(ctx, x, y, width, height, r, g, b, a); }
static void visual_2d_draw_gradient(GF_VisualManager *visual, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_TraverseState *tr_state, GF_Matrix2D *ext_mx, GF_Rect *orig_bounds) { GF_Rect rc; GF_STENCIL stencil; GF_Matrix2D g_mat; GF_Raster2D *raster = visual->compositor->rasterizer; if (!txh) txh = ctx->aspect.fill_texture; gf_path_get_bounds(path, &rc); if (!rc.width || !rc.height || !txh->tx_io) return; if (orig_bounds) { txh->compute_gradient_matrix(txh, orig_bounds, &g_mat, 0); } else { txh->compute_gradient_matrix(txh, &rc, &g_mat, 0); } stencil = gf_sc_texture_get_stencil(txh); if (!stencil) return; #ifndef GPAC_DISABLE_VRML if (ctx->flags & CTX_HAS_APPEARANCE) { GF_Matrix2D txt_mat; visual_2d_get_texture_transform(ctx->appear, txh, &txt_mat, (txh == ctx->aspect.fill_texture) ? 0 : 1, INT2FIX(txh->width), INT2FIX(txh->height)); gf_mx2d_add_matrix(&g_mat, &txt_mat); } #endif /*move to bottom-left corner of bounds */ if (ext_mx) gf_mx2d_add_matrix(&g_mat, ext_mx); if (orig_bounds) gf_mx2d_add_translation(&g_mat, (orig_bounds->x), (orig_bounds->y - orig_bounds->height)); gf_mx2d_add_matrix(&g_mat, &ctx->transform); raster->stencil_set_matrix(stencil, &g_mat); raster->stencil_set_color_matrix(stencil, ctx->col_mat); /*MPEG-4/VRML context or no fill info*/ if (ctx->flags & CTX_HAS_APPEARANCE || !ctx->aspect.fill_color) raster->stencil_set_alpha(stencil, 0xFF); else raster->stencil_set_alpha(stencil, GF_COL_A(ctx->aspect.fill_color) ); raster->surface_set_matrix(visual->raster_surface, &ctx->transform); txh->flags |= GF_SR_TEXTURE_USED; raster->surface_set_path(visual->raster_surface, path); visual_2d_fill_path(visual, ctx, stencil, tr_state, 0); raster->surface_set_path(visual->raster_surface, NULL); ctx->flags |= CTX_PATH_FILLED; }
static void c2d_gl_fill_rect(void *cbk, u32 x, u32 y, u32 width, u32 height, GF_Color color) { #if defined(GPAC_USE_OGL_ES) GLfloat line[8]; line[0] = FIX2FLT(x); line[1] = FIX2FLT(y); line[2] = FIX2FLT(x+width); line[3] = FIX2FLT(y); line[4] = FIX2FLT(x+width); line[5] = FIX2FLT(y+height); line[6] = FIX2FLT(x); line[7] = FIX2FLT(y+height); glEnable(GL_BLEND); glColor4ub(GF_COL_R(color), GF_COL_G(color), GF_COL_B(color), GF_COL_A(color)); glVertexPointer(4, GL_FLOAT, 0, line); glEnableClientState(GL_VERTEX_ARRAY); glDrawArrays(GL_TRIANGLE_FAN, 0, 2); glDisableClientState(GL_VERTEX_ARRAY); glDisable(GL_BLEND); #else glEnable(GL_BLEND); glColor4ub(GF_COL_R(color), GF_COL_G(color), GF_COL_B(color), GF_COL_A(color)); glBegin(GL_TRIANGLES); glVertex2i(x,y); glVertex2i(x+width,y); glVertex2i(x+width,y+height); glEnd(); glBegin(GL_TRIANGLES); glVertex2i(x,y); glVertex2i(x+width,y+height); glVertex2i(x,y+height); glEnd(); glDisable(GL_BLEND); #endif }
void text_draw_2d(GF_Node *node, GF_TraverseState *tr_state) { Bool force_texture; u32 hl_color; TextStack *st = (TextStack *) gf_node_get_private((GF_Node *) node); if (!GF_COL_A(tr_state->ctx->aspect.fill_color) && !tr_state->ctx->aspect.pen_props.width) return; text_get_draw_opt(node, st, &force_texture, &hl_color, &tr_state->ctx->aspect); tr_state->text_parent = node; gf_font_spans_draw_2d(st->spans, tr_state, hl_color, force_texture, &st->bounds); tr_state->text_parent = NULL; }
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); }
void VS2D_TexturePath(VisualSurface2D *surf, GF_Path *path, struct _drawable_context *ctx) { #ifdef SKIP_DRAW return; #endif if (!surf->the_surface || (ctx->flags & CTX_PATH_FILLED) || !ctx->h_texture || surf->render->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->h_texture->transparent) { VS2D_DrawPath(surf, path, ctx, NULL, NULL); ctx->flags &= ~CTX_PATH_FILLED; } #endif VS2D_TexturePathIntern(surf, path, NULL, ctx); }
static void svg_sani_DrawablePostRender(Drawable *cs, SVG_SANI_TransformableElement *elt, RenderEffect2D *eff, Bool rectangular, Fixed path_length) { GF_FieldInfo info; GF_Matrix2D backup_matrix; DrawableContext *ctx; if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) { gf_node_get_field_by_name(cs->node, "display", &info); if (*(SVG_Display *)info.far_ptr == SVG_DISPLAY_NONE) gf_path_get_bounds(cs->path, &eff->bounds); return; } gf_node_get_field_by_name(cs->node, "display", &info); if (*(SVG_Display *)info.far_ptr == SVG_DISPLAY_NONE) return; gf_node_get_field_by_name(cs->node, "visibility", &info); if (*(SVG_Visibility *)info.far_ptr == SVG_VISIBILITY_HIDDEN) return; gf_svg_sani_apply_local_transformation(eff, (GF_Node *)elt, &backup_matrix); gf_node_get_field_by_name(cs->node, "fill-rule", &info); if (*(SVG_FillRule *)info.far_ptr == SVG_FILLRULE_NONZERO) cs->path->flags |= GF_PATH_FILL_ZERO_NONZERO; else cs->path->flags &= ~GF_PATH_FILL_ZERO_NONZERO; ctx = svg_sani_drawable_init_context(cs, eff); if (ctx) { if (rectangular) { if (ctx->h_texture && ctx->h_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 (path_length) ctx->aspect.pen_props.path_length = path_length; drawable_finalize_render(ctx, eff, NULL); } gf_svg_sani_restore_parent_transformation(eff, &backup_matrix); }
Bool c2d_gl_draw_bitmap(GF_VisualManager *visual, GF_TraverseState *tr_state, DrawableContext *ctx, GF_ColorKey *col_key) { u8 alpha = GF_COL_A(ctx->aspect.fill_color); if (ctx->transform.m[1] || ctx->transform.m[3]) return 0; visual_3d_set_state(visual, V3D_STATE_LIGHT, 0); visual_3d_enable_antialias(visual, 0); if (alpha && (alpha != 0xFF)) { visual_3d_set_material_2d_argb(visual, ctx->aspect.fill_color); gf_sc_texture_set_blend_mode(ctx->aspect.fill_texture, TX_MODULATE); } else if (gf_sc_texture_is_transparent(ctx->aspect.fill_texture)) { gf_sc_texture_set_blend_mode(ctx->aspect.fill_texture, TX_REPLACE); } else { visual_3d_set_state(visual, V3D_STATE_BLEND, 0); } /*ignore texture transform for bitmap*/ tr_state->mesh_num_textures = gf_sc_texture_enable(ctx->aspect.fill_texture, tr_state->appear ? ((M_Appearance *)tr_state->appear)->textureTransform : NULL); if (tr_state->mesh_num_textures) { SFVec2f size, orig; GF_Mesh *mesh; size.x = ctx->bi->unclip.width; size.y = ctx->bi->unclip.height; orig.x = ctx->bi->unclip.x + INT2FIX(visual->compositor->vp_width)/2; orig.y = INT2FIX(visual->compositor->vp_height)/2 - ctx->bi->unclip.y + ctx->bi->unclip.height; mesh = new_mesh(); mesh_new_rectangle(mesh, size, &orig, 1); visual_3d_mesh_paint(tr_state, mesh); mesh_free(mesh); gf_sc_texture_disable(ctx->aspect.fill_texture); tr_state->mesh_num_textures = 0; return 1; } return 0; }
static void Text_Traverse(GF_Node *n, void *rs, Bool is_destroy) { DrawableContext *ctx; M_Text *txt = (M_Text *) n; TextStack *st = (TextStack *) gf_node_get_private(n); GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { text_clean_paths(gf_sc_get_compositor(n), st); drawable_del(st->graph); gf_list_del(st->spans); gf_free(st); return; } if (!txt->string.count) return; if (tr_state->text_split_mode) { gf_node_dirty_clear(n, 0); text_clean_paths(tr_state->visual->compositor, st); build_text_split(st, txt, tr_state); return; } text_check_changes(n, st, tr_state); switch (tr_state->traversing_mode) { case TRAVERSE_DRAW_2D: text_draw_2d(n, tr_state); return; #ifndef GPAC_DISABLE_3D case TRAVERSE_DRAW_3D: text_draw_3d(tr_state, n, st); return; #endif case TRAVERSE_PICK: tr_state->text_parent = n; gf_font_spans_pick(n, st->spans, tr_state, &st->bounds, 0, NULL); tr_state->text_parent = NULL; return; case TRAVERSE_GET_BOUNDS: tr_state->bounds = st->bounds; return; case TRAVERSE_GET_TEXT: tr_state->text_parent = n; gf_font_spans_get_selection(n, st->spans, tr_state); tr_state->text_parent = NULL; return; case TRAVERSE_SORT: break; default: return; } #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) return; #endif ctx = drawable_init_context_mpeg4(st->graph, tr_state); if (!ctx) return; ctx->sub_path_index = tr_state->text_split_idx; ctx->flags |= CTX_IS_TEXT; if (!GF_COL_A(ctx->aspect.fill_color)) { /*override line join*/ ctx->aspect.pen_props.join = GF_LINE_JOIN_MITER; ctx->aspect.pen_props.cap = GF_LINE_CAP_FLAT; } /*if text selection mode, we must force redraw of the entire text span because we don't if glyphs have been (un)selected*/ if (!tr_state->immediate_draw && /*text selection on*/ (tr_state->visual->compositor->text_selection /*text sel release*/ || (tr_state->visual->compositor->store_text_state==GF_SC_TSEL_RELEASED)) ) { GF_TextSpan *span; u32 i = 0; Bool unselect = (tr_state->visual->compositor->store_text_state==GF_SC_TSEL_RELEASED) ? 1 : 0; while ((span = gf_list_enum(st->spans, &i))) { if (span->flags & GF_TEXT_SPAN_SELECTED) { if (unselect) span->flags &= ~GF_TEXT_SPAN_SELECTED; ctx->flags |= CTX_APP_DIRTY; } } } if (ctx->sub_path_index) { GF_TextSpan *span = (GF_TextSpan *)gf_list_get(st->spans, ctx->sub_path_index-1); if (span) drawable_finalize_sort(ctx, tr_state, &span->bounds); } else { drawable_finalize_sort(ctx, tr_state, &st->bounds); } }
void visual_2d_texture_path_text(GF_VisualManager *visual, DrawableContext *txt_ctx, GF_Path *path, GF_Rect *object_bounds, GF_TextureHandler *txh, GF_TraverseState *tr_state) { GF_STENCIL stencil; Fixed sS, sT; GF_Matrix2D gf_mx2d_txt; GF_Rect orig_rc; u8 alpha, r, g, b; GF_ColorMatrix cmat; GF_Raster2D *raster; if (! visual->CheckAttached(visual) ) return; raster = visual->compositor->rasterizer; stencil = gf_sc_texture_get_stencil(txh); if (!stencil) return; visual_2d_set_options(visual->compositor, visual->raster_surface, 0, 1); /*get original bounds*/ orig_rc = *object_bounds; /*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/ sS = gf_divfix(orig_rc.width, INT2FIX(txh->width)); sT = gf_divfix(orig_rc.height, INT2FIX(txh->height)); gf_mx2d_init(gf_mx2d_txt); gf_mx2d_add_scale(&gf_mx2d_txt, sS, sT); /*move to bottom-left corner of bounds */ gf_mx2d_add_translation(&gf_mx2d_txt, (orig_rc.x), (orig_rc.y - orig_rc.height)); /*move to final coordinate system*/ gf_mx2d_add_matrix(&gf_mx2d_txt, &txt_ctx->transform); /*set path transform, except for background2D node which is directly build in the final coord system*/ raster->stencil_set_matrix(stencil, &gf_mx2d_txt); alpha = GF_COL_A(txt_ctx->aspect.fill_color); r = GF_COL_R(txt_ctx->aspect.fill_color); g = GF_COL_G(txt_ctx->aspect.fill_color); b = GF_COL_B(txt_ctx->aspect.fill_color); /*if col do a cxmatrix*/ if (!r && !g && !b) { raster->stencil_set_alpha(stencil, alpha); } else { raster->stencil_set_alpha(stencil, 0xFF); memset(cmat.m, 0, sizeof(Fixed) * 20); cmat.m[4] = INT2FIX(r)/255; cmat.m[9] = INT2FIX(g)/255; cmat.m[14] = INT2FIX(b)/255; cmat.m[18] = INT2FIX(alpha)/255; cmat.identity = 0; raster->stencil_set_color_matrix(stencil, &cmat); } raster->surface_set_matrix(visual->raster_surface, &txt_ctx->transform); txh->flags |= GF_SR_TEXTURE_USED; /*push path*/ raster->surface_set_path(visual->raster_surface, path); visual_2d_fill_path(visual, txt_ctx, stencil, tr_state, 0); raster->surface_set_path(visual->raster_surface, NULL); txt_ctx->flags |= CTX_PATH_FILLED; }
void visual_2d_flush_hybgl_canvas(GF_VisualManager *visual, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_TraverseState *tr_state) { Bool line_texture = GF_FALSE; u32 i; u32 prev_color; Bool transparent, had_flush = 0; u32 nb_obj_left_on_canvas = visual->nb_objects_on_canvas_since_last_ogl_flush; u8 alpha; if (! visual->hybgl_drawn.count) return; //we have drawn things on the canvas before this object, flush canvas to GPU if (txh && (txh==ctx->aspect.line_texture)) { line_texture = GF_TRUE; alpha = GF_COL_A(ctx->aspect.line_color); prev_color = ctx->aspect.line_color; ctx->aspect.line_texture = NULL; ctx->aspect.line_color = 0; } else { alpha = GF_COL_A(ctx->aspect.fill_color); if (!alpha) alpha = GF_COL_A(ctx->aspect.line_color); prev_color = ctx->aspect.fill_color; ctx->aspect.fill_texture = NULL; ctx->aspect.fill_color = 0; } transparent = txh ? (txh->transparent || (alpha!=0xFF)) : GF_TRUE; //clear wherever we have overlap for (i=0; i<visual->hybgl_drawn.count; i++) { GF_IRect rc = ctx->bi->clip; gf_irect_intersect(&ctx->bi->clip, &visual->hybgl_drawn.list[i].rect); if (ctx->bi->clip.width && ctx->bi->clip.height) { //if something behind this, flush canvas to gpu if (transparent) { if (!had_flush) { //flush the complete area below this object, regardless of intersections compositor_2d_hybgl_flush_video(visual->compositor, tr_state->immediate_draw ? NULL : &rc); had_flush = 1; } //if object was not completely in the flush region we will need to flush the canvas if (gf_irect_inside(&rc, &visual->hybgl_drawn.list[i].rect)) { assert(nb_obj_left_on_canvas); nb_obj_left_on_canvas--; } } //erase all part of the canvas below us if (txh) { visual_2d_draw_path_extended(visual, ctx->drawable->path, ctx, NULL, NULL, tr_state, NULL, NULL, GF_TRUE); } else { visual->compositor->rasterizer->surface_clear(visual->raster_surface, &ctx->bi->clip, 0); } } ctx->bi->clip = rc; } if (line_texture) { ctx->aspect.line_color = prev_color; ctx->aspect.line_texture = txh; } else { ctx->aspect.fill_color = prev_color; ctx->aspect.fill_texture = txh; } if (had_flush) { visual->nb_objects_on_canvas_since_last_ogl_flush = nb_obj_left_on_canvas; } }
static Bool setup_grey_callback(EVGSurface *surf) { u32 col, a; Bool use_const = 1; if (surf->sten->type == GF_STENCIL_SOLID) { col = surf->fill_col = ((EVG_Brush *)surf->sten)->color; a = GF_COL_A(surf->fill_col); } else { col = a = 0; use_const = 0; } if (surf->raster_cbk) { if (use_const) { if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_user_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_user_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_user_fill_var; } return 1; } switch (surf->pixelFormat) { case GF_PIXEL_ARGB: if (use_const) { if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgra_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgra_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgra_fill_var; } break; case GF_PIXEL_RGBA: if (use_const) { if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgba_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgba_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgba_fill_var; } break; case GF_PIXEL_RGB_32: if (use_const) { if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgrx_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgrx_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgrx_fill_var; } break; case GF_PIXEL_BGR_32: if (use_const) { if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgbx_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgbx_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgbx_fill_var; } break; case GF_PIXEL_RGB_24: if (use_const) { if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgb_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgb_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgb_fill_var; } break; case GF_PIXEL_BGR_24: if (use_const) { if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgr_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgr_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgr_fill_var; } break; case GF_PIXEL_RGB_565: if (use_const) { surf->fill_565 = GF_COL_TO_565(col); if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_565_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_565_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_565_fill_var; assert(surf->sten->fill_run); } break; #ifdef GF_RGB_444_SUPORT if (use_const) { surf->fill_444 = GF_COL_TO_444(col); if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_444_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_444_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_444_fill_var; } break; #endif #ifdef GF_RGB_555_SUPORT case GF_PIXEL_RGB_555: if (use_const) { surf->fill_555 = GF_COL_TO_555(col); if (!a) return 0; if (a!=0xFF) { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_555_fill_const_a; } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_555_fill_const; } } else { surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_555_fill_var; } break; #endif } return 1; }
void compositor_3d_draw_bitmap(Drawable *stack, DrawAspect2D *asp, GF_TraverseState *tr_state, Fixed width, Fixed height, Fixed bmp_scale_x, Fixed bmp_scale_y) { u8 alpha; GF_TextureHandler *txh; GF_Compositor *compositor = tr_state->visual->compositor; if (!asp->fill_texture) return; txh = asp->fill_texture; if (!txh || !txh->tx_io || !txh->width || !txh->height) return; if (((txh->pixelformat==GF_PIXEL_RGBD) || (txh->pixelformat==GF_PIXEL_YUVD))) { if (compositor->depth_gl_type) { if (txh->data && gf_sc_texture_convert(txh) ) visual_3d_point_sprite(tr_state->visual, stack, txh, tr_state); return; } } alpha = GF_COL_A(asp->fill_color); /*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/ if (!alpha) alpha = GF_COL_A(asp->line_color); visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, GF_FALSE); visual_3d_enable_antialias(tr_state->visual, GF_FALSE); if (alpha && (alpha != 0xFF)) { visual_3d_set_material_2d_argb(tr_state->visual, GF_COL_ARGB(alpha, 0xFF, 0xFF, 0xFF)); gf_sc_texture_set_blend_mode(txh, TX_MODULATE); } else if (gf_sc_texture_is_transparent(txh)) { gf_sc_texture_set_blend_mode(txh, TX_REPLACE); } else { visual_3d_set_state(tr_state->visual, V3D_STATE_BLEND, GF_FALSE); } /*ignore texture transform for bitmap*/ tr_state->mesh_num_textures = gf_sc_texture_enable(txh, NULL); if (tr_state->mesh_num_textures) { /*we must check the w & h passed are correct because of bitmap node initialization*/ if (width && height) { if (!stack->mesh) { SFVec2f size; size.x = width; size.y = height; stack->mesh = new_mesh(); mesh_new_rectangle(stack->mesh, size, NULL, GF_FALSE); } } if (stack->mesh) { #ifdef GF_SR_USE_DEPTH if (tr_state->depth_offset) { GF_Matrix mx; Fixed offset; Fixed disp_depth = (compositor->display_depth<0) ? INT2FIX(tr_state->visual->height) : INT2FIX(compositor->display_depth); if (disp_depth) { GF_Matrix bck_mx; if (!tr_state->pixel_metrics) disp_depth = gf_divfix(disp_depth, tr_state->min_hsize); gf_mx_init(mx); /*add recalibration by the scene*/ offset = tr_state->depth_offset; if (tr_state->visual->depth_vp_range) { offset = gf_divfix(offset, tr_state->visual->depth_vp_range/2); } gf_mx_add_translation(&mx, 0, 0, gf_mulfix(offset, disp_depth/2) ); gf_mx_copy(bck_mx, tr_state->model_matrix); gf_mx_add_matrix(&tr_state->model_matrix, &mx); visual_3d_mesh_paint(tr_state, stack->mesh); gf_mx_copy(tr_state->model_matrix, bck_mx); } else { visual_3d_mesh_paint(tr_state, stack->mesh); } } else #endif visual_3d_mesh_paint(tr_state, stack->mesh); } gf_sc_texture_disable(txh); tr_state->mesh_num_textures = 0; } }
void visual_2d_texture_path_extended(GF_VisualManager *visual, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_Rect *orig_bounds, GF_Matrix2D *ext_mx, GF_TraverseState *tr_state) { Fixed sS, sT; u32 tx_tile; GF_STENCIL tx_raster; GF_Matrix2D mx_texture; GF_Rect orig_rc; GF_Raster2D *raster; if (! visual->CheckAttached(visual) ) return; raster = visual->compositor->rasterizer; if (!txh) txh = ctx->aspect.fill_texture; if (!txh) return; if (!txh->tx_io) { gf_node_dirty_set(txh->owner, 0, 1); txh->needs_refresh=1; return; } /*this is gradient draw*/ if (txh->compute_gradient_matrix) { visual_2d_draw_gradient(visual, path, txh, ctx, tr_state, ext_mx, orig_bounds); return; } #ifndef GPAC_DISABLE_3D if (visual->compositor->hybrid_opengl) { visual_2d_texture_path_opengl_auto(visual, path, txh, ctx, orig_bounds, ext_mx, tr_state); return; } #endif if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) { GF_Window src, dst; visual_2d_fill_path(visual, ctx, NULL, tr_state, 0); /*if texture not ready, update the size before computing output rectangles */ if (!txh->width || !txh->height) { gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped); /*in case the node is an MPEG-4 bitmap, force stack rebuild at next frame */ gf_node_dirty_set(ctx->drawable->node, GF_SG_NODE_DIRTY, 1); } if (compositor_texture_rectangles(visual, txh, &ctx->bi->clip, &ctx->bi->unclip, &src, &dst, NULL, NULL)) { if (txh->stream && gf_mo_set_position(txh->stream, &src, &dst)) { gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped); /*force dirty flag to get called again*/ gf_node_dirty_set(ctx->drawable->node, GF_SG_NODE_DIRTY, 1); gf_sc_next_frame_state(visual->compositor, GF_SC_DRAW_FRAME); } } return; } if (!gf_sc_texture_push_image(txh, 0, 1)) return; tx_raster = gf_sc_texture_get_stencil(txh); /*setup quality even for background (since quality concerns images)*/ visual_2d_set_options(visual->compositor, visual->raster_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS); /*get original bounds*/ if (orig_bounds) { orig_rc = *orig_bounds; } else { gf_path_get_bounds(path, &orig_rc); } /*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/ sS = orig_rc.width / txh->width; sT = orig_rc.height / txh->height; gf_mx2d_init(mx_texture); gf_mx2d_add_scale(&mx_texture, sS, sT); #ifndef GPAC_DISABLE_VRML /*apply texture transform*/ if (ctx->flags & CTX_HAS_APPEARANCE) { GF_Matrix2D tex_trans; visual_2d_get_texture_transform(ctx->appear, txh, &tex_trans, (txh == ctx->aspect.fill_texture) ? 0 : 1, txh->width * sS, txh->height * sT); gf_mx2d_add_matrix(&mx_texture, &tex_trans); } #endif /*move to bottom-left corner of bounds */ gf_mx2d_add_translation(&mx_texture, (orig_rc.x), (orig_rc.y - orig_rc.height)); if (ext_mx) gf_mx2d_add_matrix(&mx_texture, ext_mx); /*move to final coordinate system (except background which is built directly in final coord system)*/ if (!(ctx->flags & CTX_IS_BACKGROUND) ) gf_mx2d_add_matrix(&mx_texture, &ctx->transform); /*set path transform*/ raster->stencil_set_matrix(tx_raster, &mx_texture); tx_tile = 0; if (txh->flags & GF_SR_TEXTURE_REPEAT_S) tx_tile |= GF_TEXTURE_REPEAT_S; if (txh->flags & GF_SR_TEXTURE_REPEAT_T) tx_tile |= GF_TEXTURE_REPEAT_T; if (ctx->flags & CTX_FLIPED_COORDS) tx_tile |= GF_TEXTURE_FLIP; raster->stencil_set_tiling(tx_raster, (GF_TextureTiling) tx_tile); if (!(ctx->flags & CTX_IS_BACKGROUND) ) { u8 a = GF_COL_A(ctx->aspect.fill_color); if (!a) a = GF_COL_A(ctx->aspect.line_color); /*texture alpha scale is the original material transparency, NOT the one after color transform*/ raster->stencil_set_alpha(tx_raster, a ); raster->stencil_set_color_matrix(tx_raster, ctx->col_mat); raster->surface_set_matrix(visual->raster_surface, &ctx->transform); } else { raster->surface_set_matrix(visual->raster_surface, NULL); } txh->flags |= GF_SR_TEXTURE_USED; /*push path & draw*/ raster->surface_set_path(visual->raster_surface, path); visual_2d_fill_path(visual, ctx, tx_raster, tr_state, 0); raster->surface_set_path(visual->raster_surface, NULL); ctx->flags |= CTX_PATH_FILLED; }
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; }
void visual_2d_draw_path_extended(GF_VisualManager *visual, GF_Path *path, DrawableContext *ctx, GF_STENCIL brush, GF_STENCIL pen, GF_TraverseState *tr_state, GF_Rect *orig_bounds, GF_Matrix2D *ext_mx, Bool is_erase) { Bool dofill, dostrike; GF_Raster2D *raster = visual->compositor->rasterizer; #ifdef SKIP_DRAW return; #endif if (! visual->CheckAttached(visual) ) return; if ((ctx->flags & CTX_PATH_FILLED) && (ctx->flags & CTX_PATH_STROKE) ) { if (visual->compositor->draw_bvol) draw_clipper(visual, ctx); return; } if (! (ctx->flags & CTX_IS_BACKGROUND) ) visual_2d_set_options(visual->compositor, visual->raster_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS); dofill = dostrike = 0; if (!(ctx->flags & CTX_PATH_FILLED) && (is_erase || GF_COL_A(ctx->aspect.fill_color)) ) { dofill = 1; if (!brush) { brush = visual->raster_brush; raster->stencil_set_brush_color(brush, ctx->aspect.fill_color); } } /*compute width based on transform and top_level transform*/ if (!(ctx->flags & CTX_PATH_STROKE) && ctx->aspect.pen_props.width) { dostrike = 1; } else if (!dofill) { return; } /*set path transform, except for background2D node which is directly build in the final coord system*/ raster->surface_set_matrix(visual->raster_surface, (ctx->flags & CTX_IS_BACKGROUND) ? NULL : &ctx->transform); /*fill path*/ if (dofill) { #if ADAPTATION_SIZE if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) { raster->surface_clear(visual->raster_surface, &ctx->bi->clip, ctx->aspect.fill_color); } else #endif { /*push path*/ raster->surface_set_path(visual->raster_surface, path); visual_2d_fill_path(visual, ctx, brush, tr_state, is_erase); raster->surface_set_path(visual->raster_surface, NULL); } } if (dostrike) { #if ADAPTATION_SIZE if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) { } else #endif { StrikeInfo2D *si; if (!pen) { pen = visual->raster_brush; raster->stencil_set_brush_color(pen, ctx->aspect.line_color); } si = drawable_get_strikeinfo(visual->compositor, ctx->drawable, &ctx->aspect, ctx->appear, path, ctx->flags, NULL); if (si && si->outline) { if (ctx->aspect.line_texture) { visual_2d_texture_path_extended(visual, si->outline, ctx->aspect.line_texture, ctx, orig_bounds, ext_mx, tr_state); } else { raster->surface_set_path(visual->raster_surface, si->outline); visual_2d_fill_path(visual, ctx, pen, tr_state, 0); } /*that's ugly, but we cannot cache path outline for IFS2D/ILS2D*/ if (path && !(ctx->flags & CTX_IS_TEXT) && (path!=ctx->drawable->path) ) { gf_path_del(si->outline); si->outline = NULL; } } // drawable_reset_path_outline(ctx->drawable); } } if (visual->compositor->draw_bvol) draw_clipper(visual, ctx); }
Bool group_cache_compute_stats(GF_Node *node, GroupingNode2D *group, GF_TraverseState *tr_state, DrawableContext *first_child, Bool skip_first_child) { GF_Rect group_bounds; DrawableContext *ctx; u32 nb_segments, nb_objects; u32 alpha_pixels, opaque_pixels, area_world; u32 video_cache_max_size, cache_size, prev_cache_size; u32 i; GF_RectArray ra; /*compute stats*/ nb_objects = 0; nb_segments = 0; alpha_pixels = opaque_pixels = 0; prev_cache_size = group->cached_size; /*reset bounds*/ group_bounds.width = group_bounds.height = 0; video_cache_max_size = tr_state->visual->compositor->video_cache_max_size; /*never cache root node - this should be refined*/ if (gf_node_get_parent(node, 0) == NULL) goto group_reject; if (!group->traverse_time) goto group_reject; ra_init(&ra); ctx = first_child; if (!first_child) ctx = tr_state->visual->context; if (skip_first_child) ctx = ctx->next; /*compute properties for the sub display list*/ while (ctx && ctx->drawable) { //Fixed area; u32 alpha_comp; /*get area and compute alpha/opaque coverage*/ alpha_comp = GF_COL_A(ctx->aspect.fill_color); /*add to group area*/ gf_rect_union(&group_bounds, &ctx->bi->unclip); nb_objects++; /*no alpha*/ if ((alpha_comp==0xFF) /*no transparent texture*/ && (!ctx->aspect.fill_texture || !ctx->aspect.fill_texture->transparent) ) { ra_union_rect(&ra, &ctx->bi->clip); } nb_segments += ctx->drawable->path->n_points; ctx = ctx->next; } if ( /*TEST 1: discard visually empty groups*/ (!group_bounds.width || !group_bounds.height) || /*TEST 2: discard small groups*/ (nb_objects<MIN_OBJECTS_IN_CACHE) || /*TEST 3: low complexity group*/ (nb_segments && (nb_segments<10)) ) { ra_del(&ra); goto group_reject; } ra_refresh(&ra); opaque_pixels = 0; for (i=0; i<ra.count; i++) { opaque_pixels += ra.list[i].width * ra.list[i].height; } ra_del(&ra); /*get coverage in world coords*/ area_world = FIX2INT(group_bounds.width) * FIX2INT(group_bounds.height); /*TEST 4: discard low coverage groups in world coords (plenty of space wasted) we consider that this % of the area is actually drawn - this is of course wrong, we would need to compute each path coverage in local coords then get the ratio */ if (10*opaque_pixels < 7*area_world) goto group_reject; /*the memory size allocated for the cache - cache is drawn in final coordinate system !!*/ group_bounds.width = tr_state->visual->compositor->cache_scale * group_bounds.width / 100; group_bounds.height = tr_state->visual->compositor->cache_scale * group_bounds.height / 100; cache_size = FIX2INT(group_bounds.width) * FIX2INT(group_bounds.height) * 4 /* pixelFormat is ARGB*/; /*TEST 5: cache is less than 10x10 pixels: discard*/ if (cache_size < 400) goto group_reject; /*TEST 6: cache is larger than our allowed memory: discard*/ if (cache_size>=video_cache_max_size) { tr_state->cache_too_small = 1; goto group_reject; } /*compute the delta value for measuring the group importance for later discard (avg_time - Tcache) / (size_cache - drawable_gain) */ group->priority = INT2FIX(nb_objects*1024*group->traverse_time) / cache_size / group->nb_stats_frame; /*OK, group is a good candidate for caching*/ group->nb_objects = nb_objects; group->cached_size = cache_size; /*we're moving from non-cached to cached*/ if (!(group->flags & GROUP_IS_CACHABLE)) { group->flags |= GROUP_IS_CACHABLE; tr_state->visual->compositor->draw_next_frame = 1; /*insert the candidate and then update the list in order*/ group_cache_insert_entry(node, group, tr_state); /*keep track of this cache object for later removal*/ gf_list_add(tr_state->visual->compositor->cached_groups_queue, group); GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Turning cache on during stat pass for node %s - %d kb used in all caches\n", gf_node_get_log_name(node), tr_state->visual->compositor->video_cache_current_size )); } /*update memory occupation*/ else { tr_state->visual->compositor->video_cache_current_size -= prev_cache_size; tr_state->visual->compositor->video_cache_current_size += group->cached_size; if (group->cache) group->cache->force_recompute = 1; } return 1; group_reject: group->nb_objects = nb_objects; if ((group->flags & GROUP_IS_CACHABLE) || group->cache) { group->flags &= ~GROUP_IS_CACHABLE; if (group->cache) { group_cache_del(group->cache); group->cache = NULL; group->flags &= ~GROUP_IS_CACHED; } gf_list_del_item(tr_state->visual->compositor->cached_groups, group); tr_state->visual->compositor->video_cache_current_size -= cache_size; } #if 0 GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] REJECT %s\tObjects: %d\tSlope: %g\tBytes: %d\tTime: %d\n", gf_node_get_log_name(node), group->nb_objects, FIX2FLT(group->priority), group->cached_size, group->traverse_time )); GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Status (B): Max: %d\tUsed: %d\tNb Groups: %d\n", tr_state->visual->compositor->video_cache_max_size, tr_state->visual->compositor->video_cache_current_size, gf_list_count(tr_state->visual->compositor->cached_groups) )); #endif return 0; }
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); }
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); }
void VS2D_TexturePathIntern(VisualSurface2D *surf, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx) { Fixed sS, sT; u32 tx_tile; GF_Matrix2D gf_mx2d_txt, gf_sr_texture_transform; GF_Rect rc, orig_rc; GF_Raster2D *r2d = surf->render->compositor->r2d; if (!txh) txh = ctx->h_texture; if (!txh || !txh->hwtx) return; /*this is gradient draw*/ if (txh->compute_gradient_matrix) { VS2D_DrawGradient(surf, path, txh, ctx); return; } /*setup quality even for background (since quality concerns images)*/ VS2D_SetOptions(surf->render, surf->the_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS); /*get original bounds*/ gf_path_get_bounds(path, &orig_rc); /*get active texture window in pixels*/ rc.width = INT2FIX(txh->width); rc.height = INT2FIX(txh->height); /*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/ sS = orig_rc.width / txh->width; sT = orig_rc.height / txh->height; gf_mx2d_init(gf_mx2d_txt); gf_mx2d_add_scale(&gf_mx2d_txt, sS, sT); /*apply texture transform*/ get_gf_sr_texture_transform(ctx->appear, txh, &gf_sr_texture_transform, (txh == ctx->h_texture) ? 0 : 1, txh->width * sS, txh->height * sT); gf_mx2d_add_matrix(&gf_mx2d_txt, &gf_sr_texture_transform); /*move to bottom-left corner of bounds */ gf_mx2d_add_translation(&gf_mx2d_txt, (orig_rc.x), (orig_rc.y - orig_rc.height)); /*move to final coordinate system (except background which is built directly in final coord system)*/ if (!(ctx->flags & CTX_IS_BACKGROUND) ) gf_mx2d_add_matrix(&gf_mx2d_txt, &ctx->transform); /*set path transform, except for background2D node which is directly build in the final coord system*/ r2d->stencil_set_matrix(txh->hwtx, &gf_mx2d_txt); tx_tile = 0; if (txh->flags & GF_SR_TEXTURE_REPEAT_S) tx_tile |= GF_TEXTURE_REPEAT_S; if (txh->flags & GF_SR_TEXTURE_REPEAT_T) tx_tile |= GF_TEXTURE_REPEAT_T; r2d->stencil_set_tiling(txh->hwtx, (GF_TextureTiling) tx_tile); if (!(ctx->flags & CTX_IS_BACKGROUND) ) { u8 a = GF_COL_A(ctx->aspect.fill_color); if (!a) a = GF_COL_A(ctx->aspect.line_color); /*texture alpha scale is the original material transparency, NOT the one after color transform*/ r2d->stencil_set_texture_alpha(txh->hwtx, a ); r2d->stencil_set_color_matrix(txh->hwtx, ctx->col_mat); r2d->surface_set_matrix(surf->the_surface, &ctx->transform); } else { r2d->surface_set_matrix(surf->the_surface, NULL); } /*push path & draw*/ r2d->surface_set_path(surf->the_surface, path); VS2D_DoFill(surf, ctx, txh->hwtx); r2d->surface_set_path(surf->the_surface, NULL); ctx->flags |= CTX_PATH_FILLED; }
void compositor_3d_draw_bitmap(Drawable *stack, DrawAspect2D *asp, GF_TraverseState *tr_state, Fixed width, Fixed height, Fixed bmp_scale_x, Fixed bmp_scale_y) { u8 alpha; #if !defined(GPAC_USE_OGL_ES) && !defined(GPAC_USE_TINYGL) Fixed x, y; Fixed sx, sy; char *data; u32 format; #endif GF_TextureHandler *txh; GF_Compositor *compositor = tr_state->visual->compositor; Bool use_texture = !compositor->bitmap_use_pixels; if (!asp->fill_texture) return; txh = asp->fill_texture; if (!txh || !txh->tx_io || !txh->width || !txh->height) return; if (((txh->pixelformat==GF_PIXEL_RGBD) || (txh->pixelformat==GF_PIXEL_YUVD))) { if (compositor->depth_gl_type) { if (txh->data && gf_sc_texture_convert(txh) ) visual_3d_point_sprite(tr_state->visual, stack, txh, tr_state); return; } else { use_texture = 1; } } alpha = GF_COL_A(asp->fill_color); /*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/ if (!alpha) alpha = GF_COL_A(asp->line_color); /*texture is available in hw, use it - if blending, force using texture*/ if (!gf_sc_texture_needs_reload(txh) || (alpha != 0xFF) || use_texture #ifdef GF_SR_USE_DEPTH || tr_state->depth_offset #endif ) { visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, 0); visual_3d_enable_antialias(tr_state->visual, 0); if (alpha && (alpha != 0xFF)) { visual_3d_set_material_2d_argb(tr_state->visual, GF_COL_ARGB(alpha, 0xFF, 0xFF, 0xFF)); gf_sc_texture_set_blend_mode(txh, TX_MODULATE); } else if (gf_sc_texture_is_transparent(txh)) { gf_sc_texture_set_blend_mode(txh, TX_REPLACE); } else { visual_3d_set_state(tr_state->visual, V3D_STATE_BLEND, 0); } /*ignore texture transform for bitmap*/ tr_state->mesh_num_textures = gf_sc_texture_enable(txh, NULL); if (tr_state->mesh_num_textures) { /*we must check the w & h passed are correct because of bitmap node initialization*/ if (width && height) { if (!stack->mesh) { SFVec2f size; size.x = width; size.y = height; stack->mesh = new_mesh(); mesh_new_rectangle(stack->mesh, size, NULL, 0); } } if (stack->mesh) { #ifdef GF_SR_USE_DEPTH if (tr_state->depth_offset) { GF_Matrix mx; Fixed offset; Fixed disp_depth = (compositor->display_depth<0) ? INT2FIX(tr_state->visual->height) : INT2FIX(compositor->display_depth); if (disp_depth) { if (!tr_state->pixel_metrics) disp_depth = gf_divfix(disp_depth, tr_state->min_hsize); gf_mx_init(mx); /*add recalibration by the scene*/ offset = tr_state->depth_offset; if (tr_state->visual->depth_vp_range) { offset = gf_divfix(offset, tr_state->visual->depth_vp_range/2); } gf_mx_add_translation(&mx, 0, 0, gf_mulfix(offset, disp_depth/2) ); visual_3d_matrix_push(tr_state->visual); visual_3d_matrix_add(tr_state->visual, mx.m); visual_3d_mesh_paint(tr_state, stack->mesh); visual_3d_matrix_pop(tr_state->visual); } else { visual_3d_mesh_paint(tr_state, stack->mesh); } } else #endif visual_3d_mesh_paint(tr_state, stack->mesh); } gf_sc_texture_disable(txh); tr_state->mesh_num_textures = 0; return; } } /*otherwise use glDrawPixels*/ #if !defined(GPAC_USE_OGL_ES) && !defined(GPAC_USE_TINYGL) data = gf_sc_texture_get_data(txh, &format); if (!data) return; x = INT2FIX(txh->width) / -2; y = INT2FIX(txh->height) / 2; { Fixed g[16]; sx = bmp_scale_x; if (sx<0) sx = FIX_ONE; sy = bmp_scale_y; if (sy<0) sy = FIX_ONE; #ifndef GPAC_DISABLE_VRML compositor_adjust_scale(txh->owner, &sx, &sy); #endif /*add top level scale if any*/ sx = gf_mulfix(sx, compositor->scale_x); sy = gf_mulfix(sy, compositor->scale_y); /*get & apply current transform scale*/ visual_3d_matrix_get(tr_state->visual, V3D_MATRIX_MODELVIEW, g); if (g[0]<0) g[0] *= -FIX_ONE; if (g[5]<0) g[5] *= -FIX_ONE; sx = gf_mulfix(sx, g[0]); sy = gf_mulfix(sy, g[5]); x = gf_mulfix(x, sx); y = gf_mulfix(y, sy); } visual_3d_draw_image(tr_state->visual, x, y, txh->width, txh->height, format, data, sx, sy); #endif }
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); }
void VS2D_DrawPath(VisualSurface2D *surf, GF_Path *path, DrawableContext *ctx, GF_STENCIL brush, GF_STENCIL pen) { Bool dofill, dostrike; GF_Raster2D *r2d = surf->render->compositor->r2d; #ifdef SKIP_DRAW return; #endif assert(surf->the_surface); if ((ctx->flags & CTX_PATH_FILLED) && (ctx->flags & CTX_PATH_STROKE) ) { if (surf->render->compositor->draw_bvol) draw_clipper(surf, ctx); return; } if (! (ctx->flags & CTX_IS_BACKGROUND) ) VS2D_SetOptions(surf->render, surf->the_surface, ctx->flags & CTX_IS_TEXT, 0); dofill = dostrike = 0; if (!(ctx->flags & CTX_PATH_FILLED) && GF_COL_A(ctx->aspect.fill_color) ) { dofill = 1; if (!brush) { brush = surf->the_brush; r2d->stencil_set_brush_color(brush, ctx->aspect.fill_color); } } /*compute width based on transform and top_level transform*/ if (!(ctx->flags & CTX_PATH_STROKE) && ctx->aspect.pen_props.width) { dostrike = 1; if (!pen) { pen = surf->the_pen; r2d->stencil_set_brush_color(pen, ctx->aspect.line_color); } } else if (!dofill) { return; } /*set path transform, except for background2D node which is directly build in the final coord system*/ r2d->surface_set_matrix(surf->the_surface, (ctx->flags & CTX_IS_BACKGROUND) ? NULL : &ctx->transform); /*fill path*/ if (dofill) { #if ADAPTATION_SIZE if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) { r2d->surface_clear(surf->the_surface, &ctx->bi->clip, ctx->aspect.fill_color); } else #endif { /*push path*/ r2d->surface_set_path(surf->the_surface, path); VS2D_DoFill(surf, ctx, brush); r2d->surface_set_path(surf->the_surface, NULL); } } if (dostrike) { #if ADAPTATION_SIZE if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) { } else #endif { StrikeInfo2D *si = drawctx_get_strikeinfo(surf->render, ctx, path); if (si && si->outline) { if (ctx->aspect.line_texture) { VS2D_TexturePathIntern(surf, si->outline, ctx->aspect.line_texture, ctx); } else { r2d->surface_set_path(surf->the_surface, si->outline); VS2D_DoFill(surf, ctx, pen); } /*that's ugly, but we cannot cache path outline for IFS2D/ILS2D*/ if (path && !(ctx->flags & CTX_IS_TEXT) && (path!=ctx->drawable->path) ) { gf_path_del(si->outline); si->outline = NULL; } } } } if (surf->render->compositor->draw_bvol) draw_clipper(surf, ctx); }
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; } }