efl/src/lib/eina/eina_tiler.h

416 lines
14 KiB
C

/* EINA - EFL data type library
* Copyright (C) 2007-2008 Jorge Luis Zapata Muga
*
* This library 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.1 of the License, or (at your option) any later version.
*
* This library 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;
* if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EINA_TILER_H_
#define EINA_TILER_H_
#include "eina_types.h"
#include "eina_iterator.h"
#include "eina_rectangle.h"
/**
* @page eina_tiler_example_01
* @dontinclude eina_tiler_01.c
*
* This is an example that illustrates how Eina_Tiler works for a given set of
* rectangles. The rectangles must be given in the command line in the form:
* \<width\>x\<height\>+\<x offset\>+\<y offset\>
* The example will show two panels, the first(input) will show the given
* rectangles(in different colors) and in the seconds(output) it will show the
* rectangles given by the tiler. The rectangles will be added one by one every
* two seconds. A lot of the example deals with actually painting the rectangles
* so we'll skip over quite a bit of code, but you can see all of it in @ref
* eina_tiler_01.c "eina_tiler_01.c".
*
* The first thing of note in our example is the creation of the tiler:
* @skipline eina_tiler_new
* @note @p maxw and @p maxh are calculated such that the tiler's size will
* fully encompass all given rectangles.
*
* We'll now look at the function that actually adds rectangles to our tiler. It
* first checks if we added all rectangles already and if so stops right there:
* @dontinclude eina_tiler_01.c
* @skip static Eina_Bool
* @until }
*
* Our function then clears all rectangles given to us by tiler from the last
* execution. It does this because each rectangle we add may change everything
* about the output of eina_tiler:
* @until output_rects_reset
*
* Next we get another rectangle, print it and show it in the input panel:
* @until add_input_rect
*
* We now come to the tiler stuff, we add our new rectangle to it and get a new
* iterator for the tiler:
* @until itr
*
* We now iterate over our tiler printing every rect it gives us and sowing it
* in the output panel:
* @until }
*
* We of course must remember to free our iterator and that's it for this
* function:
* @until }
*
* You should try many different inputs to see how the tiler works, here are a
* few suggestions:
* @li 100x100+0+0 100x100+200+200
* @li 100x100+0+0 100x100+5+5 100x100+10+10 100x100+15+15 100x100+20+20
* @li 100x100+0+0 100x100+100+100 100x100+200+0 100x100+0+200 100x100+200+200
* @li 10x10+0+0 10x10+10+10 10x10+20+0 10x10+0+20 10x10+20+20
*
* @example eina_tiler_01.c
*/
/**
* @addtogroup Eina_Data_Types_Group Data Types
*
* @{
*/
/**
* @defgroup Eina_Tiler_Group Tiler
*
* @warning This is a very low level tool, in most situations (for example if
* you're using evas) you won't need this.
*
* @section basic Basic usage
*
* Eina_Tiler is a tool to facilitate calculations of which areas are damaged
* and thus need to be re-rendered. The basic usage of Eina_Tiler is to give it
* the size of your canvas and a set of rectangular areas that need
* re-rendering, from that and using heuristics it'll tell you an efficient way
* to re-render in the form of a set of non-overlapping rectangles that covers
* the whole area that needs re-rendering.
*
* The following is pseudo-code showing some simple use of Eina_Tiler:
* @code
* tiler = eina_tiler_new(MY_CANVAS_WIDTH, MY_CANVAS_HEIGHT);
* EINA_LIST_FOREACH(list_of_areas_that_need_re_rendering, l, rect)
* eina_tiler_add(tiler, rect);
* itr = eina_tiler_iterator_new(tiler);
* EINA_ITERATOR_FOREACH(itr, rect)
* my_function_that_repaints_areas_of_the_canvas(rect);
* @endcode
*
* @see eina_tiler_new()
* @see eina_tiler_rect_add()
* @see eina_tiler_iterator_new()
*
* @warning There are no guarantees that this will be the most efficient way to
* re-render for any particular case.
*
* @section grid_slicer Grid Slicer
*
* Grid slicer and Eina_Tiler are usually used together, that is however @b not
* necessary, they can be used independently. Grid slicer provides an easy API
* to divide an area in tiles which is useful in certain applications to divide
* the area that will be rendered into tiles. It's customary to, then create one
* Eina_Tiler for each tile.
*
* The following is pseudo-code showing a very simplified use of grid slicer
* together with Eina_Tiler:
* @code
* itr = eina_tile_grid_slicer_iterator_new(0, 0, MY_CANVAS_WIDTH, MY_CANVAS_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
* EINA_ITERATOR_FOREACH(itr, grid_info)
* {
* tiler = eina_tiler_new(grid_info->rect.w, grid_info->rect.w);
* EINA_LIST_FOREACH(list_of_areas_that_need_re_rendering_in_this_tile, l, rect)
* eina_tiler_add(tiler, rect);
* itr = eina_tiler_iterator_new(tiler);
* EINA_ITERATOR_FOREACH(itr, rect)
* my_function_that_repaints_areas_of_the_canvas(rect);
* }
* @endcode
*
* @see eina_tiler_new()
* @see eina_tiler_rect_add()
* @see eina_tile_grid_slicer_setup()
* @see eina_tile_grid_slicer_next()
* @see eina_tile_grid_slicer_iterator_new()
*
* @{
*/
/**
* @typedef Eina_Tiler
* Tiler type.
*/
typedef struct _Eina_Tiler Eina_Tiler;
/**
* @typedef Eina_Tile_Grid_Info
* Grid type of a tiler.
*/
typedef struct Eina_Tile_Grid_Info Eina_Tile_Grid_Info;
/**
* @struct Eina_Tile_Grid_Info
* Grid type of a tiler.
*/
struct Eina_Tile_Grid_Info
{
unsigned long col; /**< column of the tile grid */
unsigned long row; /**< row of the tile grid*/
Eina_Rectangle rect; /**< rectangle of the tile grid, coordinates are
relative to tile*/
Eina_Bool full; /**< whether the grid is full or not */
};
typedef struct _Eina_Tile_Grid_Slicer Eina_Tile_Grid_Slicer;
/**
* @brief Creates a new tiler with @p w width and @p h height.
*
* @param[in] w Width of the tiler
* @param[in] h Height of the tiler
* @return The newly created tiler
*
* @see eina_tiler_free()
*/
EAPI Eina_Tiler *eina_tiler_new(int w, int h);
/**
* @brief Frees a tiler.
*
* @param[in] t The tiler to free.
*
* This function frees @p t. It does not free the memory allocated for the
* elements of @p t.
*/
EAPI void eina_tiler_free(Eina_Tiler *t);
/**
* @brief Sets the size of tiles for a tiler.
*
* @param[in,out] t The tiler whose tile size will be set.
* @param[in] w Width of the tiles.
* @param[in] h Height of the tiles.
*
* @warning @p w and @p h @b must be greater than zero, otherwise tile size
* won't be changed.
* @warning Tile size is not used!
*/
EAPI void eina_tiler_tile_size_set(Eina_Tiler *t, int w, int h);
/**
* @brief Changes the size of the area covered by the tiler.
*
* @param[in,out] t The tiler whose area size will be set.
* @param[in] w Width of the area.
* @param[in] h Height of the area.
*
* @since 1.8
*
* @warning Must clear the tiler before changing its size.
*/
EAPI void eina_tiler_area_size_set(Eina_Tiler *t, int w, int h);
/**
* @brief Gets the size of the area covered by the tiler.
*
* @param[in] t The tiler whose area size will be fetched.
* @param[out] w Width of the area.
* @param[out] h Height of the area.
*
* @since 1.8
*/
EAPI void eina_tiler_area_size_get(const Eina_Tiler *t, int *w, int *h);
/**
* @brief Defines if we need to follow a strict grid of tile or a loose one.
*
* @param[in,out] t The tiler to apply the strict rules to.
* @param[in] strict Define if it will be strict or loose
*
* By default it will be loose.
*
* @since 1.8
*/
EAPI void eina_tiler_strict_set(Eina_Tiler *t, Eina_Bool strict);
/**
* @brief Tells if a tiler is empty or not.
*
* @param[in] t The tiler to apply the strict rules to.
* @return #EINA_TRUE when empty, #EINA_FALSE when not.
*
* @since 1.8
*/
EAPI Eina_Bool eina_tiler_empty(const Eina_Tiler *t);
/**
* @brief Adds a rectangle to a tiler.
*
* @param[in,out] t The tiler in which to add a container.
* @param[in] r The rectangle to be added.
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
*
* @see eina_tiler_rect_del()
*/
EAPI Eina_Bool eina_tiler_rect_add(Eina_Tiler *t, const Eina_Rectangle *r);
/**
* @brief Removes a rectangle from a tiler.
*
* @param[in,out] t The tiler in which to add a container.
* @param[in] r The rectangle to be removed.
*
* @see eina_tiler_rect_add()
* @see eina_tiler_clear()
*/
EAPI void eina_tiler_rect_del(Eina_Tiler *t, const Eina_Rectangle *r);
/**
* @brief Removes all rectangles from tiles.
*
* @param[in,out] t The tiler to clear.
*
* @see eina_tiler_rect_del()
*/
EAPI void eina_tiler_clear(Eina_Tiler *t);
/**
* @brief Creates a iterator to access the tilers calculated rectangles.
*
* @param[in] t The tiler to iterate over.
* @return A iterator containing Eina_Rectangle.
*/
EAPI Eina_Iterator *eina_tiler_iterator_new(const Eina_Tiler *t);
/**
* @brief Creates a new Eina_Iterator that iterates over a list of tiles.
*
* @param[in] x X axis coordinate.
* @param[in] y Y axis coordinate.
* @param[in] w Width.
* @param[in] h Height.
* @param[in] tile_w Tile width.
* @param[in] tile_h Tile height.
* @return A pointer to the Eina_Iterator. @c NULL on failure.
*
* The region defined by @a x, @a y, @a w, @a h will be divided in to a grid of
* tiles of width @a tile_w and height @p tile_h, the returned iterator will
* iterate over every tile in the grid having as its data a #Eina_Tile_Grid_Info.
*
* @note This is a convenience function, iterating over the returned iterator is
* equivalent to calling eina_tile_grid_slicer_setup() and calling
* eina_tile_grid_slicer_next() until it returns #EINA_FALSE.
*/
EAPI Eina_Iterator *eina_tile_grid_slicer_iterator_new(int x, int y, int w, int h, int tile_w, int tile_h);
/**
* @brief Gets the union of two tilers.
*
* @param[in,out] dst The first tiler, will store the result.
* @param[in] src The second tiler.
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
*
* This function gets the union of tilers @p dst and @p src.
* The result is stored in @p dst. It returns #EINA_TRUE if it succeeds.
* @since 1.11
*/
EAPI Eina_Bool eina_tiler_union(Eina_Tiler *dst, Eina_Tiler *src);
/**
* @brief Subtracts two tilers.
*
* @param[in,out] dst The first tiler, will store the result.
* @param[in] src The second tiler.
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
*
* This function subtracts two tilers @p dst and @p src.
* The result is stored in @p dst. It returns #EINA_TRUE if it succeeds.
* @since 1.11
*/
EAPI Eina_Bool eina_tiler_subtract(Eina_Tiler *dst, Eina_Tiler *src);
/**
* @brief Gets the intersection of two tilers.
*
* @param[in] t1 The first tile.
* @param[in] t2 The second tiler.
* @return A pointer of intersection result. @c NULL if intersection doesn't exist.
*
* This function gets the intersection of two tilers @p t1 and @p t2.
* It returns a pointer of result if intersection of two tilers exists., otherwise returns NULL.
* @since 1.11
*/
EAPI Eina_Tiler *eina_tiler_intersection(Eina_Tiler *t1, Eina_Tiler *t2);
/**
* @brief Gets whether two tilers are equal in rects or not.
*
* @param[in] t1 The first tiler.
* @param[in] t2 The second tiler.
* @return #EINA_TRUE if equal, #EINA_FALSE if unequal.
*
* This function gets result of comparison for @p t1 and @p t2.
* It returns #EINA_TRUE if tilers are equal.
* @since 1.11
*/
EAPI Eina_Bool eina_tiler_equal(const Eina_Tiler *t1, const Eina_Tiler *t2);
/**
* @brief Iterates over the tiles set by eina_tile_grid_slicer_setup().
*
* @param[in,out] slc Pointer to an Eina_Tile_Grid_Slicer struct.
* @param[out] rect Pointer to a struct Eina_Tile_Grid_Info *.
* @return #EINA_TRUE if the current rect is valid. #EINA_FALSE if there
* are no more rects to iterate over (and thus the current one isn't valid).
*
* This functions iterates over each Eina_Tile_Grid_Info *rect of the grid.
* eina_tile_grid_slicer_setup() must be called first, and *rect is only valid
* if this function returns #EINA_TRUE. Its content shouldn't be modified.
*
* @note Consider using eina_tile_grid_slicer_iterator_new() instead.
*/
static inline Eina_Bool eina_tile_grid_slicer_next(Eina_Tile_Grid_Slicer *slc, const Eina_Tile_Grid_Info **rect);
/**
* @brief Sets up an Eina_Tile_Grid_Slicer struct.
*
* @param[out] slc Pointer to an Eina_Tile_Grid_Slicer struct.
* @param[in] x X axis coordinate.
* @param[in] y Y axis coordinate.
* @param[in] w Width.
* @param[in] h Height.
* @param[in] tile_w Tile width.
* @param[in] tile_h Tile height.
* @return A pointer to the Eina_Iterator, @c NULL on failure.
*
* The region defined by @a x, @a y, @a w, @a h will be divided into a grid of
* tiles of width @a tile_w and height @p tile_h, @p slc can then be used with
* eina_tile_grid_slicer_next() to access each tile.
*
* @note Consider using eina_tile_grid_slicer_iterator_new() instead.
*/
static inline Eina_Bool eina_tile_grid_slicer_setup(Eina_Tile_Grid_Slicer *slc, int x, int y, int w, int h, int tile_w, int tile_h);
#include "eina_inline_tiler.x"
/**
* @}
*/
/**
* @}
*/
#endif /* EINA_TILER_H_ */