📄 visualsurface2d.h
字号:
/* * 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. * */#ifndef VISUALSURFACE2D_H_#define VISUALSURFACE2D_H_#include "render2d.h"#include "drawable.h"static GFINLINE Bool gf_irect_overlaps(GF_IRect *rc1, GF_IRect *rc2){ if (! rc2->height || !rc2->width || !rc1->height || !rc1->width) return 0; if (rc2->x+rc2->width<=rc1->x) return 0; if (rc2->x>=rc1->x+rc1->width) return 0; if (rc2->y-rc2->height>=rc1->y) return 0; if (rc2->y<=rc1->y-rc1->height) return 0; return 1;}/*adds @rc2 to @rc1 - the new @rc1 contains the old @rc1 and @rc2*/static GFINLINE void gf_irect_union(GF_IRect *rc1, GF_IRect *rc2) { if (!rc1->width || !rc1->height) {*rc1=*rc2; return;} if (rc2->x < rc1->x) { rc1->width += rc1->x - rc2->x; rc1->x = rc2->x; } if (rc2->x + rc2->width > rc1->x+rc1->width) rc1->width = rc2->x + rc2->width - rc1->x; if (rc2->y > rc1->y) { rc1->height += rc2->y - rc1->y; rc1->y = rc2->y; } if (rc2->y - rc2->height < rc1->y - rc1->height) rc1->height = rc1->y - rc2->y + rc2->height;}/*makes @rc empty*/#define gf_rect_reset(rc) { (rc)->x = (rc)->y = (rc)->width = (rc)->height = 0; }/*is @rc empty*/#define gf_rect_is_empty(rc) ( ((rc).width && (rc).height) ? 0 : 1 )/*@rc1 equales @rc2*/#define gf_rect_equal(rc1, rc2) ((rc1.width == rc2.width) && (rc1.height == rc2.height) && (rc1.x == rc2.x) && (rc1.y == rc2.y)) /*intersects @rc1 with @rc2 - the new @rc1 is the intersection*/static GFINLINE void gf_irect_intersect(GF_IRect *rc1, GF_IRect *rc2){ if (! gf_irect_overlaps(rc1, rc2)) { gf_rect_reset(rc1); return; } if (rc2->x > rc1->x) { rc1->width -= rc2->x - rc1->x; rc1->x = rc2->x; } if (rc2->x + rc2->width < rc1->x + rc1->width) { rc1->width = rc2->width + rc2->x - rc1->x; } if (rc2->y < rc1->y) { rc1->height -= rc1->y - rc2->y; rc1->y = rc2->y; } if (rc2->y - rc2->height > rc1->y - rc1->height) { rc1->height = rc1->y - rc2->y + rc2->height; } }/*@rc2 fully contained in @rc1*/static GFINLINE Bool gf_irect_inside(GF_IRect *rc1, GF_IRect *rc2) { if (!rc1->width || !rc1->height) return 0; if ( (rc1->x <= rc2->x) && (rc1->y >= rc2->y) && (rc1->x + rc1->width >= rc2->x + rc2->width) && (rc1->y - rc1->height <= rc2->y - rc2->height) ) return 1; return 0;}static GFINLINE GF_Rect gf_rect_ft(GF_IRect *rc){ GF_Rect rcft; rcft.x = INT2FIX(rc->x); rcft.y = INT2FIX(rc->y); rcft.width = INT2FIX(rc->width); rcft.height = INT2FIX(rc->height); return rcft;}/*@x, y in @rc*/static GFINLINE Bool gf_point_in_rect(GF_IRect *_rc, Fixed x, Fixed y) { GF_Rect rc = gf_rect_ft(_rc); if ( (x >= rc.x) && (y <= rc.y) && (x <= rc.x + rc.width) && (y >= rc.y - rc.height) ) return 1; return 0;}//#define TRACK_OPAQUE_REGIONS/*ra_: rectangle array macros to speed dirty rects*/#define RA_DEFAULT_STEP 10typedef struct{ GF_IRect *list; u32 count, alloc;#ifdef TRACK_OPAQUE_REGIONS /*list of nodes covering (no transparency) each rect, or 0 otherwise.*/ u32 *opaque_node_index;#endif} GF_RectArray;#ifdef TRACK_OPAQUE_REGIONS/*inits structure - called as a constructor*/#define ra_init(ra) { (ra)->count = 0; (ra)->alloc = 1; (ra)->list = (GF_IRect*)malloc(sizeof(GF_IRect)); (ra)->opaque_node_index = NULL;}/*deletes structure - called as a destructor*/#define ra_del(ra) { free((ra)->list); if ((ra)->opaque_node_index) free((ra)->opaque_node_index); }#else#define ra_init(ra) { (ra)->count = 0; (ra)->alloc = 1; (ra)->list = (GF_IRect*)malloc(sizeof(GF_IRect));}/*deletes structure - called as a destructor*/#define ra_del(ra) { free((ra)->list); }#endif/*adds rect to list - expand if needed*/#define ra_add(ra, rc) { \ if ((ra)->count==(ra)->alloc) { (ra)->alloc += RA_DEFAULT_STEP; (ra)->list = (GF_IRect*)realloc((ra)->list, sizeof(GF_IRect) * (ra)->alloc); } \ (ra)->list[(ra)->count] = *rc; (ra)->count++; }/*clears list*/#define ra_clear(ra) { (ra)->count = 0; }/*is list empty*/#define ra_is_empty(ra) (!((ra)->count))/*adds rectangle to the list performing union test*/static GFINLINE void ra_union_rect(GF_RectArray *ra, GF_IRect *rc) { u32 i; for (i=0; i<ra->count; i++) { if (gf_irect_overlaps(&ra->list[i], rc)) { gf_irect_union(&ra->list[i], rc); return; } } ra_add(ra, rc); }/*merges all rects in ra2 into ra1*/static GFINLINE void ra_merge(GF_RectArray *ra1, GF_RectArray *ra2) { u32 i; for (i=0; i<ra2->count; i++) { ra_union_rect(ra1, &ra2->list[i]); }}/*refreshes the content of the array to have only non-overlapping rects*/static GFINLINE void ra_refresh(GF_RectArray *ra){ u32 i, j, k; for (i=0; i<ra->count; i++) { for (j=i+1; j<ra->count; j++) { if (gf_irect_overlaps(&ra->list[i], &ra->list[j])) { gf_irect_union(&ra->list[i], &ra->list[j]); /*remove rect*/ k = ra->count - j - 1; if (k) memmove(&ra->list[j], & ra->list[j+1], sizeof(GF_IRect)*k); ra->count--; ra_refresh(ra); return; } } }}struct _drawable_store{ struct _drawable *drawable; struct _drawable_store *next;};typedef struct _visual_surface_2D { Render2D *render; /*the one and only dirty rect collector*/ GF_RectArray to_redraw;#ifdef TRACK_OPAQUE_REGIONS u32 draw_node_index;#endif /*static list of context*/ struct _drawable_context *context, *cur_context; /*keeps track of nodes drawn last frame*/ struct _drawable_store *prev_nodes, *last_prev_entry; /*background and viewport stacks*/ GF_List *back_stack; GF_List *view_stack; /*top-level transform (active viewport, user zoom and pan) */ GF_Matrix2D top_transform; /*pixel area of surface in BIFS coords - eg surface to fill with background*/ GF_IRect surf_rect; /*top clipper (may be different than surf_rect when a viewport is active)*/ GF_IRect top_clipper; Bool last_had_back; Bool has_sensors; /*signals that the surface is attached to buffer/device/stencil*/ Bool is_attached; /*size in pixels*/ u32 width, height; Bool center_coords; /*this is set by the video renderer or the composite texture object */ /*gets access to graphics handle*/ GF_Err (*GetSurfaceAccess)(struct _visual_surface_2D *); /*release graphics handle*/ void (*ReleaseSurfaceAccess)(struct _visual_surface_2D *); /*draws specified texture as flat bitmap*/ void (*DrawBitmap)(struct _visual_surface_2D *, struct _gf_sr_texture_handler *, GF_IRect *clip, GF_Rect *unclip, u8 alpha, u32 *col_key, GF_ColorMatrix *cmat); Bool (*SupportsFormat)(struct _visual_surface_2D *surf, u32 pixel_format); /*composite texture renderer if any*/ struct _composite_2D *composite; GF_SURFACE the_surface; GF_STENCIL the_brush; GF_STENCIL the_pen;} VisualSurface2D;/*constructor/destructor*/VisualSurface2D *NewVisualSurface2D();void DeleteVisualSurface2D(VisualSurface2D *);/*gets a drawable context on this surface*/struct _drawable_context *VS2D_GetDrawableContext(VisualSurface2D *surf);/*remove last drawable context*/void VS2D_RemoveLastContext(VisualSurface2D *surf);/*signal the given drawable is being deleted*/void VS2D_DrawableDeleted(VisualSurface2D *surf, Drawable *node);/*inits rendering cycle - called at each cycle start regardless of rendering mode*/GF_Err VS2D_InitDraw(VisualSurface2D *surf, RenderEffect2D *eff);/*terminates rendering cycle - called at each cycle end regardless of rendering modeif rendering is indirect, actual drawing is performed here. Returns 1 if the surface has been modified*/Bool VS2D_TerminateDraw(VisualSurface2D *surf, RenderEffect2D *eff);/*register context sensors for later picking*/void VS2D_RegisterSensor(VisualSurface2D *surf, DrawableContext *ctx);/*locates drawable context under the given point for VRML-based scene (that is for nodes with sensors attached)Note: this also locate context in composite textures*/DrawableContext *VS2D_PickSensitiveNode(VisualSurface2D *surf, Fixed X, Fixed Y);/*same as above but doesn't check for any sensor & co*/DrawableContext *VS2D_PickContext(VisualSurface2D *surf, Fixed x, Fixed y);/*clear given rect or all surface if no rect specified - clear color depends on surface type - 0 for compositesurfaces, renderer clear color otherwiseBackColor is non 0 for background node only*/void VS2D_Clear(VisualSurface2D *, GF_IRect *clear, u32 BackColor);/*texture the path with the given context info*/void VS2D_TexturePath(VisualSurface2D *, GF_Path *path, DrawableContext *ctx);/*draw the path (fill and strike) - if brushes are NULL they are created if needed based on the context aspectDrawPath shall always be called after TexturePath*/void VS2D_DrawPath(VisualSurface2D *, GF_Path *path, DrawableContext *ctx, GF_STENCIL brush, GF_STENCIL pen);/*special texturing extension for text, using a given path (text rectangle) and texture (rendered text)*/void VS2D_TexturePathText(VisualSurface2D *surf, DrawableContext *txt_ctx, GF_Path *path, GF_Rect *object_bounds, GF_HWTEXTURE hwtx, GF_Rect *gf_sr_texture_bounds);/*inits graphics surface handler for subsequent draw*/GF_Err VS2D_InitSurface(VisualSurface2D *surf);/*releases graphics surface handler */void VS2D_TerminateSurface(VisualSurface2D *surf);/*destroys graphics driver objects used by the surface*/void VS2D_ResetGraphics(VisualSurface2D *surf);/* this is to use carefully: picks a node based on the PREVIOUS frame state (no traversing)*/GF_Node *VS2D_PickNode(VisualSurface2D *surf, Fixed x, Fixed y);/*fill given rect with given color with given ctx transform and clipper (used for text hilighting only)if rc is NULL, fills object bounds*/void VS2D_FillRect(VisualSurface2D *surf, DrawableContext *ctx, GF_Rect *rc, u32 color, u32 strike_color);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -