/*
 *			GPAC - Multimedia Framework C SDK
 *
 *			Authors: Jean Le Feuvre 
 *			Copyright (c) Telecom ParisTech 2000-2012
 *					All rights reserved
 *
 *  This file is part of GPAC / Scene Compositor sub-project
 *
 *  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 MPEG4_GROUPING_H
#define MPEG4_GROUPING_H

#include <gpac/internal/compositor_dev.h>

enum
{
	GROUP_HAS_SENSORS	=	1,
	GROUP_SKIP_CULLING	=	1<<1,
	GROUP_HAS_LIGHTS	=	1<<2,
	GROUP_IS_ANCHOR		=	1<<3,
	/*set if group has been detected as a good candidate for caching*/
	GROUP_IS_CACHABLE	=	1<<4,
	/*set if group is cached*/
	GROUP_IS_CACHED				=	1<<5,
	GROUP_PERMANENT_CACHE		=	1<<6,
};

/*this is only used for type-casting of the common 2D/3D stacks to get the flags*/
typedef struct
{
	u32 flags;
} BaseGroupingStack;



#ifdef GF_SR_USE_VIDEO_CACHE


#define GROUPING_NODE_STACK_2D		\
	u32 flags;						\
	GF_Rect bounds;					\
	struct _group_cache *cache;		\
	u16 traverse_time;		\
	u8 changed;				\
	u8 nb_stats_frame;		\
	/*cache candidates are sorted by priority*/		\
	Fixed priority;			\
	/*size of offscreen cache in kbytes*/		\
	u32 cached_size;		\
	/*number of objects in cache - for debug purposes only*/		\
	u32 nb_objects;		\


#else

#define GROUPING_NODE_STACK_2D		\
	u32 flags;						\
	GF_Rect bounds;					\

#endif

#define GROUPING_MPEG4_STACK_2D		\
	GROUPING_NODE_STACK_2D			\
	GF_List *sensors;				\

typedef struct _mpeg4_group2d
{
	GROUPING_MPEG4_STACK_2D
} GroupingNode2D;

/*traverse all children of the node */
void group_2d_traverse(GF_Node *node, GroupingNode2D *group, GF_TraverseState *tr_state);

/*traverse all children of the node with the given traversing order*/
void group_2d_traverse_with_order(GF_Node *node, GroupingNode2D *group, GF_TraverseState *tr_state, u32 *positions);

#ifdef GF_SR_USE_VIDEO_CACHE
/*traverse the grouping node - returns 1 if the group is cached, in which case children nodes should not need
to be traversed in SORT mode - this function takes care of zoom changes & stats resetup if needed*/
Bool group_2d_cache_traverse(GF_Node *node, GroupingNode2D *group, GF_TraverseState *tr_state);
/*record the traversal information and turn cache on if possible*/
void group_2d_cache_evaluate(GF_Node *node, GroupingNode2D *group, GF_TraverseState *tr_state, struct _drawable_context *first_child, Bool skip_first_child, u32 last_cache_idx);
#endif

void group_2d_destroy(GF_Node *node, GroupingNode2D *group);

/*for SVG <g> only when using offscreen group caches*/
void group_2d_destroy_svg(GF_Node *node, GroupingNode2D *group);

#ifndef GPAC_DISABLE_3D

/*
	@children: pointer to children field
	@sensors: cached list of sensors at this level, NULL if none
	@lights: cached list of lights (local and global) at this level, NULL if none
	@bbox: bounding box of sub-tree
	@dont_cull: if set, traversing always occur (needed for audio subgraph)
*/

#define GROUPING_NODE_STACK_3D	\
	u32 flags;						\
	GF_BBox bbox;				\

typedef struct _parent_node_3d
{
	GROUPING_NODE_STACK_3D
} GroupingNode;

GroupingNode *group_3d_new(GF_Node *node);
void group_3d_delete(GF_Node *node);


/*traverse all children of the node */
void group_3d_traverse(GF_Node *n, GroupingNode *group, GF_TraverseState *tr_state);

#endif



/*
 * ParentNode (Form, Layout, PathLayout, ...) tools
*/


typedef struct 
{
	/*the associated child (can be a group or a shape)*/
	GF_Node *child;

	/*child bounds before and after placement*/
	GF_Rect original, final;
	
	/*layout run-time scroll*/
	Fixed scroll_x, scroll_y;

	/*if text node, ascent and descent of the text is stored for baseline alignment*/
	Fixed ascent, descent;
	u32 text_split_idx;
	/*discard_type 0: not discardable, 1 disardable, 2 line break at the end of the group*/
	u8 text_type;
} ChildGroup;



#define PARENT_MPEG4_STACK_2D	\
			GROUPING_MPEG4_STACK_2D	\
			/*list of ChildGroup drawn (can be fully transparents) - used for post placement*/	\
			GF_List *groups;	


typedef struct _parent_node_2d
{
	PARENT_MPEG4_STACK_2D
} ParentNode2D;

/*performs stack init (allocate all base stuff of stack)*/
void parent_node_setup(ParentNode2D *ptr);
/*performs stack init (frees all base stuff of stack, but not the stack)*/
void parent_node_predestroy(ParentNode2D *gr);
/*reset children list*/
void parent_node_reset(ParentNode2D *gr);
/*creates a new group for the given node. If the node is NULL, the previous group's node is used*/
void parent_node_start_group(ParentNode2D *group, GF_Node *n, Bool discardable);
/*sets the current group bounds*/
void parent_node_end_group(ParentNode2D *group, GF_Rect *bounds);
/*sets the current group bounds + font properties*/
void parent_node_end_text_group(ParentNode2D *group, GF_Rect *bounds, Fixed ascent, Fixed descent, u32 split_text_idx);

/*traverse the parent group's children for bounds compute. Starts a new ChildGroup for each child*/
void parent_node_traverse(GF_Node *node, ParentNode2D *group, GF_TraverseState *tr_state);

/*updates the matrix (translations only, computed between final and original bounds) and traverse the given child*/
void parent_node_child_traverse(ChildGroup *cg, GF_TraverseState *tr_state);

/*updates the matrix (position assigned by caller) and traverse the given child. Do not traverse if the matrix is NULL*/
void parent_node_child_traverse_matrix(ChildGroup *cg, GF_TraverseState *tr_state, GF_Matrix2D *mat2D);


#endif	/*MPEG4_GROUPING_H*/

