📄 geometry_stacks.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / 2D rendering module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "stacks2d.h"#include "visualsurface2d.h"/* Shape */static void RenderShape(GF_Node *node, void *rs, Bool is_destroy){ RenderEffect2D *eff; M_Shape *shape = (M_Shape *) node; if (is_destroy ) return; gf_node_dirty_clear(node, 0); if (!shape->geometry) return; eff = (RenderEffect2D *)rs; if (eff->trav_flags & GF_SR_TRAV_SWITCHED_OFF) return; eff->appear = (GF_Node *) shape->appearance; gf_node_render((GF_Node *) shape->geometry, eff); eff->appear = NULL;}void R2D_InitShape(Render2D *sr, GF_Node *node){ gf_node_set_callback_function(node, RenderShape);}static void RenderCircle(GF_Node *node, void *rs, Bool is_destroy){ DrawableContext *ctx; 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; } if (gf_node_dirty_get(node)) { drawable_reset_path(cs); gf_path_add_ellipse(cs->path, 0, 0, ((M_Circle *) node)->radius * 2, ((M_Circle *) node)->radius * 2); gf_node_dirty_clear(node, 0); cs->flags |= DRAWABLE_HAS_CHANGED; } ctx = drawable_init_context(cs, eff); if (!ctx) return; drawable_finalize_render(ctx, eff, NULL);}void R2D_InitCircle(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, RenderCircle);}static void RenderEllipse(GF_Node *node, void *rs, Bool is_destroy){ DrawableContext *ctx; 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; } if (gf_node_dirty_get(node)) { drawable_reset_path(cs); gf_path_add_ellipse(cs->path, 0, 0, ((M_Ellipse *) node)->radius.x, ((M_Ellipse *) node)->radius.y); gf_node_dirty_clear(node, 0); cs->flags |= DRAWABLE_HAS_CHANGED; } ctx = drawable_init_context(cs, eff); if (!ctx) return; drawable_finalize_render(ctx, eff, NULL);}void R2D_InitEllipse(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, RenderEllipse);}static Bool txtrans_identity(GF_Node *appear){ if (!appear || !((M_Appearance*)appear)->textureTransform) return 1; /*we could optimize, but let's assume that if a transform is used, it is not identity...*/ return 0;}void R2D_DrawRectangle(RenderEffect2D *eff){ DrawableContext *ctx = eff->ctx; if (!ctx->h_texture || !ctx->h_texture->stream || ctx->transform.m[1] || ctx->transform.m[3] || !txtrans_identity(ctx->appear) ) { VS2D_TexturePath(eff->surface, ctx->drawable->path, ctx); VS2D_DrawPath(eff->surface, ctx->drawable->path, ctx, NULL, NULL); } else { GF_Rect unclip; GF_IRect clip, unclip_pix; u8 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); /*get image size WITHOUT line size*/ gf_path_get_bounds(ctx->drawable->path, &unclip); gf_mx2d_apply_rect(&ctx->transform, &unclip); unclip_pix = clip = gf_rect_pixelize(&unclip); gf_irect_intersect(&clip, &ctx->bi->clip); /*direct rendering, render without clippers */ if (eff->surface->render->top_effect->trav_flags & TF_RENDER_DIRECT) { eff->surface->DrawBitmap(eff->surface, ctx->h_texture, &clip, &unclip, alpha, NULL, ctx->col_mat); } /*render bitmap for all dirty rects*/ else { u32 i; GF_IRect a_clip; for (i=0; i<eff->surface->to_redraw.count; i++) { /*there's an opaque region above, don't draw*/#ifdef TRACK_OPAQUE_REGIONS if (eff->surface->draw_node_index < eff->surface->to_redraw.opaque_node_index[i]) continue;#endif a_clip = clip; gf_irect_intersect(&a_clip, &eff->surface->to_redraw.list[i]); if (a_clip.width && a_clip.height) { eff->surface->DrawBitmap(eff->surface, ctx->h_texture, &a_clip, &unclip, alpha, NULL, ctx->col_mat); } } } ctx->flags |= CTX_PATH_FILLED; VS2D_DrawPath(eff->surface, ctx->drawable->path, ctx, NULL, NULL); }}static void RenderRectangle(GF_Node *node, void *reff, Bool is_destroy){ DrawableContext *ctx; Drawable *rs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)reff; if (is_destroy) { DestroyDrawableNode(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { R2D_DrawRectangle(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } if (gf_node_dirty_get(node)) { drawable_reset_path(rs); gf_path_add_rect_center(rs->path, 0, 0, ((M_Rectangle *) node)->size.x, ((M_Rectangle *) node)->size.y); gf_node_dirty_clear(node, 0); rs->flags |= DRAWABLE_HAS_CHANGED; } ctx = drawable_init_context(rs, eff); if (!ctx) return; /*if alpha or not filled, transparent*/ if (GF_COL_A(ctx->aspect.fill_color) != 0xFF) { } /*if texture transparent, transparent*/ else if (ctx->h_texture && ctx->h_texture->transparent) { } /*if rotated, transparent (doesn't fill bounds)*/ else if (ctx->transform.m[1] || ctx->transform.m[3]) { } /*TODO check matrix for alpha*/ else if (!eff->color_mat.identity) { } /*otherwsie, not transparent*/ else { ctx->flags &= ~CTX_IS_TRANSPARENT; } drawable_finalize_render(ctx, eff, NULL);}void R2D_InitRectangle(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, RenderRectangle);}//#define CHECK_VALID_C2D(nbPts) if (cur_index+nbPts>=pt_count) { gd->path_reset(cs->path); return; }#define CHECK_VALID_C2D(nbPts)static void build_curve2D(Drawable *cs, M_Curve2D *c2D){ SFVec2f orig, ct_orig, ct_end, end; u32 cur_index, i, remain, type_count, pt_count; SFVec2f *pts; M_Coordinate2D *coord = (M_Coordinate2D *)c2D->point; pts = coord->point.vals; if (!pts) return; cur_index = c2D->type.count ? 1 : 0; /*if the first type is a moveTo skip initial moveTo*/ i=0; i=0; if (cur_index) { while (c2D->type.vals[i]==0) i++; } ct_orig = orig = pts[i]; gf_path_add_move_to(cs->path, orig.x, orig.y); pt_count = coord->point.count; type_count = c2D->type.count; for (; i<type_count; i++) { switch (c2D->type.vals[i]) { /*moveTo, 1 point*/ case 0: CHECK_VALID_C2D(0); orig = pts[cur_index]; if (i) gf_path_add_move_to(cs->path, orig.x, orig.y); cur_index += 1; break; /*lineTo, 1 point*/ case 1: CHECK_VALID_C2D(0); end = pts[cur_index]; gf_path_add_line_to(cs->path, end.x, end.y); orig = end; cur_index += 1; break; /*curveTo, 3 points*/ case 2: CHECK_VALID_C2D(2); ct_orig = pts[cur_index]; ct_end = pts[cur_index+1]; end = pts[cur_index+2]; gf_path_add_cubic_to(cs->path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y); cur_index += 3; ct_orig = ct_end; orig = end; break; /*nextCurveTo, 2 points (cf spec)*/ case 3: CHECK_VALID_C2D(1); ct_orig.x = 2*orig.x - ct_orig.x; ct_orig.y = 2*orig.y - ct_orig.y; ct_end = pts[cur_index]; end = pts[cur_index+1]; gf_path_add_cubic_to(cs->path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y); cur_index += 2; ct_orig = ct_end; orig = end; break; /*all XCurve2D specific*/ /*CW and CCW ArcTo*/ case 4: case 5: CHECK_VALID_C2D(2); ct_orig = pts[cur_index]; ct_end = pts[cur_index+1]; end = pts[cur_index+2]; gf_path_add_arc_to(cs->path, end.x, end.y, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, (c2D->type.vals[i]==5) ? 1 : 0); cur_index += 3; ct_orig = ct_end; orig = end; break; /*ClosePath*/ case 6: gf_path_close(cs->path); break; /*quadratic CurveTo, 2 points*/ case 7: CHECK_VALID_C2D(1); ct_end = pts[cur_index]; end = pts[cur_index+1]; gf_path_add_quadratic_to(cs->path, ct_end.x, ct_end.y, end.x, end.y); cur_index += 2; ct_orig = ct_end; orig = end; break; } } /*what's left is an N-bezier spline*/ if (pt_count > cur_index) { /*first moveto*/ if (!cur_index) cur_index++; remain = pt_count - cur_index; if (remain>1) gf_path_add_bezier(cs->path, &pts[cur_index], remain); }}static void RenderCurve2D(GF_Node *node, void *rs, Bool is_destroy){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -