1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2000-2012
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / Scene Compositor sub-project
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 
27 #ifndef DRAWABLE_H
28 #define DRAWABLE_H
29 
30 #include <gpac/internal/compositor_dev.h>
31 
32 
33 typedef struct _drawable Drawable;
34 typedef struct _drawable_context DrawableContext;
35 
36 typedef struct _bound_info
37 {
38 	/*cliped bounds in pixels - needed to track static objects with animated cliping*/
39 	GF_IRect clip;
40 	/*uncliped bounds - needed to track moving objects fully contained in visual and for image bliting*/
41 	GF_Rect unclip;
42 	/* extra_check:
43 		for MPEG-4: pointer to appearance node (due to DEF/USE) in order to detect same bounds and appearance node change
44 		for SVG: currently not used, should be needed for <use>
45 	*/
46 	void *extra_check;
47 
48 	/**/
49 	struct _bound_info *next;
50 } BoundInfo;
51 
52 typedef struct _dirty_rect_info
53 {
54 	/*the visual manager for which we're storing the bounds of this node*/
55 	GF_VisualManager *visual;
56 	/*the current location of the node on the visual manager collected during traverse step*/
57 	struct _bound_info *current_bounds;
58 	/*the location of the node on the visual manager at the previous frame*/
59 	struct _bound_info *previous_bounds;
60 
61 	/**/
62 	struct _dirty_rect_info *next;
63 } DRInfo;
64 
65 enum {
66 	/*user defined flags*/
67 
68 	/*if flag set, the node callback function will be used to draw the node. Otherwise,
69 	high-level draw operations on the drawable & drawable context will be used*/
70 	DRAWABLE_USE_TRAVERSE_DRAW = 1,
71 
72 	/*bounds tracker flags, INTERNAL TO RENDERER */
73 
74 	/*flag set by drawable_mark_modified during a TRAVERSE_SORT pass when geometry's node has been modified. This forces clearing of the node
75 	and skips bounds checking.
76 	Flag is cleared by the compositor*/
77 	DRAWABLE_HAS_CHANGED = 1<<1,
78 	/*same flag as above except set when picking/getting bounds out of the main scene traversal routine (user event, script)*/
79 	DRAWABLE_HAS_CHANGED_IN_LAST_TRAVERSE = 1<<2,
80 
81 	/*flag set if node has been drawn for the current visual manager*/
82 	DRAWABLE_DRAWN_ON_VISUAL = 1<<3,
83 	/*set if node is registered in previous node drawn list of the current visual manager
84 	the flag is only set during a visual_draw_frame pass*/
85 	DRAWABLE_REGISTERED_WITH_VISUAL = 1<<4,
86 
87 	/*drawable is an overlay surface*/
88 	DRAWABLE_IS_OVERLAY = 1<<5,
89 
90 	/*drawable has a cache texture*/
91 	DRAWABLE_IS_CACHED = 1<<6,
92 
93 	/*drawable has been initialized for hybrid GL mode - used to perform the initial clear of the overlay graphics*/
94 	DRAWABLE_HYBGL_INIT = 1<<7,
95 };
96 
97 struct _drawable
98 {
99 #ifndef GPAC_DISABLE_3D
100 	/*3D object for drawable if needed - NOT ALLOCATED BY DEFAULT
101 	DO NOT CHANGE THE LOCATION IN THE STRUCTURE, IT SHALL BE FIRST TO BE TYPECASTED TO
102 	A Drawable3D when drawing OpenGL*/
103 	GF_Mesh *mesh;
104 #endif
105 	/*set of drawable flags*/
106 	u32 flags;
107 
108 	/*node owning the drawable*/
109 	GF_Node *node;
110 
111 	/*bounds collector*/
112 	struct _dirty_rect_info *dri;
113 
114 	/*graphic path - !! CREATED BY DEFAULT !! */
115 	GF_Path *path;
116 	/*cached outlines*/
117 	struct _strikeinfo2d *outline;
118 };
119 
120 /*construction destruction*/
121 Drawable *drawable_new();
122 void drawable_del(Drawable *dr);
123 void drawable_del_ex(Drawable *dr, GF_Compositor *compositor);
124 
125 /*cleans up the drawable attached to the node*/
126 void drawable_node_del(GF_Node *node);
127 
128 
129 /*
130 decide whether drawing is needed or not based on visual settings and parent node - must be called
131 at the end of each TRAVERSE_SORT of drawable nodes
132 if orig_bounds is NULL, function uses the bounds of the drawable's path
133 */
134 void drawable_finalize_sort(DrawableContext *ctx, GF_TraverseState *tr_state, GF_Rect *orig_bounds);
135 /*same as drawable_finalize_sort but skips focus check*/
136 void drawable_finalize_sort_ex(DrawableContext *ctx, GF_TraverseState *tr_state, GF_Rect *orig_bounds, Bool skip_focus);
137 
138 /*base constructor for geometry objects that work without overloading the drawable stuff*/
139 Drawable *drawable_stack_new(GF_Compositor *compositor, GF_Node *node);
140 /*reset all paths (main path and any outline) of the stack*/
141 void drawable_reset_path(Drawable *st);
142 /*reset all paths outlines (only) of the stack*/
143 void drawable_reset_path_outline(Drawable *st);
144 
145 /*mark the drawable as modified - this shall be caleed whenever the node geometry is rebuilt
146 in order to signal this change to the bounds tracker algorithm*/
147 void drawable_mark_modified(Drawable *st, GF_TraverseState *tr_state);
148 
149 /*checks if the current object is the focused one, and insert the focus drawable at the current pos*/
150 void drawable_check_focus_highlight(GF_Node *node, GF_TraverseState *tr_state, GF_Rect *orig_bounds);
151 
152 /*reset the highlight state (bounds) if associated with the current node. This is automatically called
153 whenever reseting a drawable but must be called when a grouping node is modified*/
154 void drawable_reset_group_highlight(GF_TraverseState *tr_state, GF_Node *n);
155 
156 /*move current bounds to previous bounds for given target visual manager - called BEFORE updating the visual manager
157 returns 1 if nod was draw last frame on this visual manager, 0 otherwise*/
158 Bool drawable_flush_bounds(Drawable *node, GF_VisualManager *on_visual, u32 mode2d);
159 
160 /*
161 	return 1 if same bound is found in previous list (and remove it from the list)
162 	return 0 otherwise
163 */
164 Bool drawable_has_same_bounds(DrawableContext *ctx, GF_VisualManager *visual);
165 
166 /*
167 	return any previous bounds related to the same visual manager in @rc if any
168 	if nothing found return 0
169 */
170 Bool drawable_get_previous_bound(Drawable *node, GF_IRect *rc, GF_VisualManager *visual);
171 
172 /*reset bounds array (current and previous) on the given visual manager*/
173 void drawable_reset_bounds(Drawable *dr, GF_VisualManager *visual);
174 /*setup clip/uncli pointers for the drawable context*/
175 void drawable_check_bounds(DrawableContext *ctx, GF_VisualManager *visual);
176 
177 /*the focus drawable routine of the focus object*/
178 void drawable_traverse_focus(GF_Node *node, void *rs, Bool is_destroy);
179 
180 struct _draw_aspect_2d
181 {
182 	/*including alpha*/
183 	GF_Color fill_color, line_color;
184 	Fixed line_scale;
185 	GF_PenSettings pen_props;
186 	/*texture fill handler*/
187 	struct _gf_sc_texture_handler *fill_texture;
188 	/*texture stroke handler*/
189 	struct _gf_sc_texture_handler *line_texture;
190 };
191 
192 /*fills the 2D drawing properties according to the traversing state - MPEG4/X3D only*/
193 u32 drawable_get_aspect_2d_mpeg4(GF_Node *node, DrawAspect2D *asp, GF_TraverseState *tr_state);
194 /*fills the 2D drawing properties according to the traversing state - SVG only*/
195 Bool drawable_get_aspect_2d_svg(GF_Node *node, DrawAspect2D *asp, GF_TraverseState *tr_state);
196 
197 
198 enum
199 {
200 	/*set whenever appearance changed*/
201 	CTX_APP_DIRTY = 1,
202 	/*set whenever texture data changed*/
203 	CTX_TEXTURE_DIRTY = 1<<1,
204 
205 	/*set when context is an MPEG-4/VRML node*/
206 	CTX_HAS_APPEARANCE = 1<<2,
207 	/*set if node completely fits its bounds (flat rect and bitmap) then non transparent*/
208 	CTX_IS_TRANSPARENT = 1<<3,
209 	/*set if node is text data*/
210 	CTX_IS_TEXT = 1<<4,
211 	/*set if node is background*/
212 	CTX_IS_BACKGROUND = 1<<5,
213 	/*turn antialiasing off when drawing*/
214 	CTX_NO_ANTIALIAS = 1<<6,
215 	/*indicates path has been textured, in which case FILL is skiped*/
216 	CTX_PATH_FILLED = 1<<7,
217 	/*indicates path outline has been textured, in which case STRIKE is skiped*/
218 	CTX_PATH_STROKE = 1<<8,
219 	/*indicates SVG path outline geometry has been modified*/
220 	CTX_SVG_OUTLINE_GEOMETRY_DIRTY = 1<<9,
221 	/*indicates the context is in a flip coord state (used for image and text flip)*/
222 	CTX_FLIPED_COORDS = 1<<10,
223 	//flag set in opengl auto mode to indicate that the corresponding area should not be cleared but still redrawn (this means an opaque texture is used)
224 	CTX_HYBOGL_NO_CLEAR = 1<<11,
225 	//flag set in opengl auto mode to indicate that the corresponding area should not be cleared but still redrawn (this means an opaque texture is used)
226 	CTX_BACKROUND_NOT_LAYER = 1<<12,
227 	CTX_BACKROUND_NO_CLEAR= 1<<13,
228 };
229 
230 #define CTX_3DTYPE_MASK 0x7800
231 
232 #define CTX_REDRAW_MASK	0x00000003
233 
234 struct _drawable_context
235 {
236 	/*next context allocated, or NULL*/
237 	struct _drawable_context *next;
238 
239 	/*any of the above flags*/
240 	u16 flags;
241 	/*only used by text when splitting strings into chars / substrings*/
242 	s16 sub_path_index;
243 
244 	/*drawable using this context*/
245 	Drawable *drawable;
246 
247 	/*pointer to clipped and uncliped (for sensors) rect in pixels.*/
248 	BoundInfo *bi;
249 
250 	/*draw info*/
251 	DrawAspect2D aspect;
252 	/*transform matrix from top*/
253 	GF_Matrix2D transform;
254 	/*color matrix, NULL if none/identity*/
255 	GF_ColorMatrix *col_mat;
256 
257 	/* extra check data for bounds matching
258 		for MPEG-4: appearance node
259 		for SVG: parent <use> node if any
260 	*/
261 	GF_Node *appear;
262 
263 #ifdef GF_SR_USE_DEPTH
264 	//local gain and offset
265 	Fixed depth_gain, depth_offset;
266 #endif
267 
268 };
269 
270 DrawableContext *NewDrawableContext();
271 void DeleteDrawableContext(DrawableContext *);
272 void drawctx_reset(DrawableContext *ctx);
273 void drawctx_update_info(DrawableContext *ctx, GF_VisualManager *visual);
274 
275 #ifndef GPAC_DISABLE_VRML
276 /*inits context - may return NULL if the node doesn't have to be drawn*/
277 DrawableContext *drawable_init_context_mpeg4(Drawable *node, GF_TraverseState *tr_state);
278 #endif
279 
280 /*inits context for SVG - may return NULL if the node doesn't have to be drawn*/
281 DrawableContext *drawable_init_context_svg(Drawable *drawable, GF_TraverseState *tr_state);
282 
283 /*base draw function for 2D objects (texturing, fill and strike)
284 	in 2D, the current context is passed in the traversing state
285 */
286 void drawable_draw(Drawable *drawable, GF_TraverseState *tr_state);
287 
288 /*picking function for VRML-based scene graphs*/
289 void vrml_drawable_pick(Drawable *drawable, GF_TraverseState *tr_state);
290 
291 /*SVG picking function (uses SVG pointrer events)*/
292 void svg_drawable_pick(GF_Node *node, Drawable *drawable, GF_TraverseState *tr_state);
293 
294 /*stored at compositor level and in each drawable node*/
295 typedef struct _strikeinfo2d
296 {
297 	struct _strikeinfo2d *next;
298 	/*vectorial outline*/
299 	GF_Path *outline;
300 	/*drawable using this outline*/
301 	Drawable *drawable;
302 	/*lineprops used to build outline (MPEG-4 only)*/
303 	GF_Node *lineProps;
304 	/*user+world->local scaling for non-scalable outlines*/
305 	Fixed line_scale;
306 	/*SVG path length*/
307 	Fixed path_length;
308 	/*set only for text, indicates sub-path outline*/
309 	GF_Path *original;
310 
311 
312 #ifndef GPAC_DISABLE_3D
313 	/*3D drawing*/
314 	Bool is_vectorial;
315 	GF_Mesh *mesh_outline;
316 #endif
317 } StrikeInfo2D;
318 
319 void delete_strikeinfo2d(StrikeInfo2D *info);
320 /*get strike and manage any scale change&co. This avoids recomputing outline at each frame...*/
321 StrikeInfo2D *drawable_get_strikeinfo(GF_Compositor *compositor, Drawable *drawable, DrawAspect2D *asp, GF_Node *appear, GF_Path *path, u32 svg_flags, GF_TraverseState *tr_state);
322 
323 
324 void drawable_compute_line_scale(GF_TraverseState *tr_state, DrawAspect2D *asp);
325 
326 Bool svg_drawable_is_over(Drawable *drawable, Fixed x, Fixed y, DrawAspect2D *asp, GF_TraverseState *tr_state, GF_Rect *glyph_rc);
327 
328 void drawable_check_texture_dirty(DrawableContext *ctx, Drawable *drawable, GF_TraverseState *tr_state);
329 #endif
330