forked from enlightenment/efl
Added the Eina_Tile_Grid_Slicer iterator.
This new iterator receives a rectangle as argument and tile_w X tile_h sized tile, and slices the rectangle iterating over it on each iteration. SVN revision: 42427
This commit is contained in:
parent
7d1745e3c1
commit
52de9e33cd
|
@ -38,7 +38,8 @@ eina_main.h \
|
|||
eina_cpu.h \
|
||||
eina_tiler.h \
|
||||
eina_hamster.h \
|
||||
eina_matrixsparse.h
|
||||
eina_matrixsparse.h \
|
||||
eina_inline_tiler.x
|
||||
|
||||
installed_mainheaderdir = $(includedir)/eina-@VMAJ@
|
||||
dist_installed_mainheader_DATA = Eina.h eina_config.h
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
/* EINA - EFL data type library
|
||||
* Copyright (C) 2002-2009 Rafael Antognolli
|
||||
*
|
||||
* 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_INLINE_H_
|
||||
#define EINA_TILER_INLINE_H_
|
||||
|
||||
#include "eina_safety_checks.h"
|
||||
|
||||
/**
|
||||
* This struct should not be accessed directly, it is used by
|
||||
* eina_tile_grid_slicer functions to maintain context and fill "info"
|
||||
* member with correct values for given iteration.
|
||||
*/
|
||||
struct _Eina_Tile_Grid_Slicer
|
||||
{
|
||||
unsigned long col1, col2, row1, row2; // initial and final col,row
|
||||
int tile_w, tile_h; // tile width, height
|
||||
int x_rel, y_rel; // starting x,y coordinates of the first col,row
|
||||
int w1_rel, h1_rel; // width,height of the first col,row
|
||||
int w2_rel, h2_rel; // width,height of the last col,row
|
||||
struct Eina_Tile_Grid_Info info; // info about the current tile
|
||||
Eina_Bool first;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Iterates over the tiles set by eina_tile_grid_slicer_setup().
|
||||
*
|
||||
* @param slc Pointer to an Eina_Tile_Grid_Slicer struct.
|
||||
* @param rect Pointer to a struct Eina_Tile_Grid_Info *.
|
||||
* @return @c EINA_TRUE if the current rect is valid.
|
||||
* @c EINA_FALSE if there is 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.
|
||||
*/
|
||||
static inline Eina_Bool
|
||||
eina_tile_grid_slicer_next(Eina_Tile_Grid_Slicer *slc, const Eina_Tile_Grid_Info **rect)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(slc, 0);
|
||||
|
||||
if (slc->first)
|
||||
{
|
||||
slc->first = 0;
|
||||
*rect = &slc->info;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
slc->info.col++;
|
||||
|
||||
if (slc->info.col > slc->col2)
|
||||
{
|
||||
slc->info.row++;
|
||||
if (slc->info.row > slc->row2)
|
||||
return EINA_FALSE;
|
||||
else if (slc->info.row < slc->row2)
|
||||
slc->info.rect.h = slc->tile_h;
|
||||
else
|
||||
slc->info.rect.h = slc->h2_rel;
|
||||
slc->info.rect.y = 0;
|
||||
slc->info.col = slc->col1;
|
||||
slc->info.rect.x = slc->x_rel;
|
||||
slc->info.rect.w = slc->w1_rel;
|
||||
}
|
||||
else
|
||||
{
|
||||
slc->info.rect.x = 0;
|
||||
if (slc->info.col < slc->col2)
|
||||
slc->info.rect.w = slc->tile_w;
|
||||
else
|
||||
slc->info.rect.w = slc->w2_rel;
|
||||
}
|
||||
|
||||
if (slc->info.rect.w == slc->tile_w && slc->info.rect.h == slc->tile_h)
|
||||
slc->info.full = EINA_TRUE;
|
||||
else
|
||||
slc->info.full = EINA_FALSE;
|
||||
|
||||
*rect = &slc->info;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup an Eina_Tile_Grid_Slicer struct.
|
||||
*
|
||||
* @param slc Pointer to an Eina_Tile_Grid_Slicer struct.
|
||||
* @param x X axis coordinate.
|
||||
* @param y Y axis coordinate.
|
||||
* @param w width.
|
||||
* @param h height.
|
||||
* @param tile_w tile width.
|
||||
* @param tile_h tile height.
|
||||
* @return A pointer to the Eina_Iterator.
|
||||
* @c NULL on failure.
|
||||
*
|
||||
* This function splits the rectangle given as argument into tiles of size
|
||||
* tile_w X tile_h, and returns an iterator to them. The geometry of each
|
||||
* tile can be accessed with eina_tile_grid_slicer_next, where rect
|
||||
* will be a pointer to a struct Eina_Tile_Grid_Info.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
int x1, x2, y1, y2;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(slc, 0);
|
||||
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
x2 = x + w - 1;
|
||||
y2 = y + h - 1;
|
||||
|
||||
if (x < 0 || y < 0 || w <= 0 || h <= 0 || tile_w <= 0 || tile_h <= 0)
|
||||
{
|
||||
slc->col1 = slc->row1 = 0;
|
||||
slc->col2 = slc->row2 = 0;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
slc->col1 = x1 / tile_w;
|
||||
slc->row1 = y1 / tile_h;
|
||||
slc->col2 = (x2 - 0) / tile_w;
|
||||
slc->row2 = (y2 - 0) / tile_h;
|
||||
slc->x_rel = x1 % tile_w;
|
||||
slc->y_rel = y1 % tile_h;
|
||||
slc->w1_rel = tile_w - slc->x_rel;
|
||||
slc->h1_rel = tile_h - slc->y_rel;
|
||||
slc->w2_rel = x2 % tile_w + 1;
|
||||
slc->h2_rel = y2 % tile_h + 1;
|
||||
|
||||
slc->tile_w = tile_w;
|
||||
slc->tile_h = tile_h;
|
||||
|
||||
slc->first = 1;
|
||||
slc->info.col = slc->col1;
|
||||
slc->info.row = slc->row1;
|
||||
slc->info.rect.x = slc->x_rel;
|
||||
slc->info.rect.y = slc->y_rel;
|
||||
|
||||
if (slc->info.col == slc->col2)
|
||||
slc->w1_rel = slc->w2_rel - slc->x_rel;
|
||||
|
||||
if (slc->info.row == slc->row2)
|
||||
slc->h1_rel = slc->h2_rel - slc->y_rel;
|
||||
|
||||
slc->info.rect.w = slc->w1_rel;
|
||||
slc->info.rect.h = slc->h1_rel;
|
||||
|
||||
if (slc->info.rect.w == slc->tile_w && slc->info.rect.h == slc->tile_h)
|
||||
slc->info.full = EINA_TRUE;
|
||||
else
|
||||
slc->info.full = EINA_FALSE;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -25,6 +25,16 @@
|
|||
|
||||
typedef struct _Eina_Tiler Eina_Tiler;
|
||||
|
||||
struct Eina_Tile_Grid_Info
|
||||
{
|
||||
unsigned long col, row;
|
||||
Eina_Rectangle rect;
|
||||
Eina_Bool full;
|
||||
};
|
||||
|
||||
typedef struct Eina_Tile_Grid_Info Eina_Tile_Grid_Info;
|
||||
typedef struct _Eina_Tile_Grid_Slicer Eina_Tile_Grid_Slicer;
|
||||
|
||||
EAPI Eina_Tiler *eina_tiler_new(int w, int h);
|
||||
EAPI void eina_tiler_free(Eina_Tiler *t);
|
||||
EAPI void eina_tiler_tile_size_set(Eina_Tiler *t, int w, int h);
|
||||
|
@ -32,5 +42,10 @@ EAPI Eina_Bool eina_tiler_rect_add(Eina_Tiler *t, const Eina_Rectangle *r);
|
|||
EAPI void eina_tiler_rect_del(Eina_Tiler *t, const Eina_Rectangle *r);
|
||||
EAPI void eina_tiler_clear(Eina_Tiler *t);
|
||||
EAPI Eina_Iterator * eina_tiler_iterator_new(const Eina_Tiler *t);
|
||||
EAPI Eina_Iterator * eina_tile_grid_slicer_iterator_new(int x, int y, int w, int h, int tile_w, int tile_h);
|
||||
static inline Eina_Bool eina_tile_grid_slicer_next(Eina_Tile_Grid_Slicer *slc, const Eina_Tile_Grid_Info **rect);
|
||||
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_ */
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "eina_config.h"
|
||||
#include "eina_private.h"
|
||||
#include "eina_tiler.h"
|
||||
#include "eina_error.h"
|
||||
|
||||
/*============================================================================*
|
||||
* Local *
|
||||
|
@ -1215,3 +1216,66 @@ EAPI Eina_Iterator * eina_tiler_iterator_new(const Eina_Tiler *t)
|
|||
|
||||
return &it->iterator;
|
||||
}
|
||||
|
||||
struct _Eina_Tile_Grid_Slicer_Iterator
|
||||
{
|
||||
Eina_Iterator iterator;
|
||||
Eina_Tile_Grid_Slicer priv;
|
||||
};
|
||||
|
||||
typedef struct _Eina_Tile_Grid_Slicer_Iterator Eina_Tile_Grid_Slicer_Iterator;
|
||||
|
||||
static void
|
||||
eina_tile_grid_slicer_iterator_free(Eina_Tile_Grid_Slicer_Iterator *it)
|
||||
{
|
||||
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE);
|
||||
free(it);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
eina_tile_grid_slicer_iterator_next(Eina_Tile_Grid_Slicer_Iterator *it, void **data)
|
||||
{
|
||||
return eina_tile_grid_slicer_next(&it->priv, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new Eina_Iterator that slices over a list of tiles.
|
||||
*
|
||||
* @param x X axis coordinate.
|
||||
* @param y Y axis coordinate.
|
||||
* @param w width.
|
||||
* @param h height.
|
||||
* @param tile_w tile width.
|
||||
* @param tile_h tile height.
|
||||
* @return A pointer to the Eina_Iterator.
|
||||
* @c NULL on failure.
|
||||
*
|
||||
* The tile grid is defined by @a tile_w and @a tile_h while the region is
|
||||
* defined by @a x, @a y, @a w, @a h. The output is given as
|
||||
* @c Eina_Tile_Grid_Info where tile index is given in @c col col and
|
||||
* @c row row with tile-relative
|
||||
* coordinates in @c x, @c y, @c w, @c h. If tile was fully filled by
|
||||
* region, then @c full flag
|
||||
* is set.
|
||||
*/
|
||||
EAPI Eina_Iterator *
|
||||
eina_tile_grid_slicer_iterator_new(int x, int y, int w, int h, int tile_w, int tile_h)
|
||||
{
|
||||
Eina_Tile_Grid_Slicer_Iterator *it;
|
||||
|
||||
it = calloc(1, sizeof(*it));
|
||||
if (!it)
|
||||
{
|
||||
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
||||
|
||||
it->iterator.next = FUNC_ITERATOR_NEXT(eina_tile_grid_slicer_iterator_next);
|
||||
it->iterator.free = FUNC_ITERATOR_FREE(eina_tile_grid_slicer_iterator_free);
|
||||
|
||||
eina_tile_grid_slicer_setup(&it->priv, x, y, w, h, tile_w, tile_h);
|
||||
|
||||
return &it->iterator;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,8 @@ eina_test_benchmark.c \
|
|||
eina_test_mempool.c \
|
||||
eina_test_rectangle.c \
|
||||
eina_test_list.c \
|
||||
eina_test_matrixsparse.c
|
||||
eina_test_matrixsparse.c \
|
||||
eina_test_tiler.c
|
||||
|
||||
eina_suite_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libeina.la
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ static const Eina_Test_Case etc[] = {
|
|||
{ "Mempool", eina_test_mempool },
|
||||
{ "Rectangle", eina_test_rectangle },
|
||||
{ "Matrix Sparse", eina_test_matrixsparse },
|
||||
{ "Eina Tiler", eina_test_tiler },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -42,5 +42,6 @@ void eina_test_benchmark(TCase *tc);
|
|||
void eina_test_mempool(TCase *tc);
|
||||
void eina_test_rectangle(TCase *tc);
|
||||
void eina_test_matrixsparse(TCase *tc);
|
||||
void eina_test_tiler(TCase *tc);
|
||||
|
||||
#endif /* EINA_SUITE_H_ */
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/* EINA - EFL data type library
|
||||
* Copyright (C) 2009 Rafael Antognolli
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "eina_suite.h"
|
||||
#include "Eina.h"
|
||||
|
||||
struct test_rect {
|
||||
unsigned long col, row;
|
||||
int x, y, w, h;
|
||||
Eina_Bool full;
|
||||
};
|
||||
|
||||
static void
|
||||
check_iterator(Eina_Iterator *it, struct test_rect *cur_test)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
struct Eina_Tile_Grid_Info *tile;
|
||||
|
||||
EINA_ITERATOR_FOREACH(it, tile) {
|
||||
fail_if(cur_test[i].col != tile->col ||
|
||||
cur_test[i].row != tile->row ||
|
||||
cur_test[i].x != tile->rect.x ||
|
||||
cur_test[i].y != tile->rect.y ||
|
||||
cur_test[i].w != tile->rect.w ||
|
||||
cur_test[i].h != tile->rect.h ||
|
||||
cur_test[i].full != tile->full);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(eina_test_tile_grid_slicer_iterator)
|
||||
{
|
||||
Eina_Iterator *it;
|
||||
struct test_rect *cur_test;
|
||||
struct test_rect test1[] = {{1, 1, 72, 82, 10, 15, 0}};
|
||||
struct test_rect test2[] =
|
||||
{{1, 1, 72, 82, 56, 15, 0},
|
||||
{2, 1, 0, 82, 128, 15, 0},
|
||||
{3, 1, 0, 82, 116, 15, 0}};
|
||||
struct test_rect test3[] =
|
||||
{{1, 1, 72, 82, 10, 46, 0},
|
||||
{1, 2, 72, 0, 10, 128, 0},
|
||||
{1, 3, 72, 0, 10, 126, 0}};
|
||||
struct test_rect test4[] =
|
||||
{{1, 1, 72, 82, 56, 46, 0},
|
||||
{2, 1, 0, 82, 128, 46, 0},
|
||||
{3, 1, 0, 82, 128, 46, 0},
|
||||
{4, 1, 0, 82, 88, 46, 0},
|
||||
{1, 2, 72, 0, 56, 128, 0},
|
||||
{2, 2, 0, 0, 128, 128, 1},
|
||||
{3, 2, 0, 0, 128, 128, 1},
|
||||
{4, 2, 0, 0, 88, 128, 0},
|
||||
{1, 3, 72, 0, 56, 126, 0},
|
||||
{2, 3, 0, 0, 128, 126, 0},
|
||||
{3, 3, 0, 0, 128, 126, 0},
|
||||
{4, 3, 0, 0, 88, 126, 0}};
|
||||
struct test_rect test5[] = {{1, 1, 0, 0, 128, 128, 1}};
|
||||
struct test_rect test6[] = {{1, 1, 0, 0, 1, 1, 0}};
|
||||
struct test_rect test7[] =
|
||||
{{1, 1, 0, 0, 128, 128, 1},
|
||||
{2, 1, 0, 0, 1, 128, 0},
|
||||
{1, 2, 0, 0, 128, 1, 0},
|
||||
{2, 2, 0, 0, 1, 1, 0}};
|
||||
|
||||
|
||||
cur_test = test1;
|
||||
it = eina_tile_grid_slicer_iterator_new(200, 210, 10, 15, 128, 128);
|
||||
check_iterator(it, cur_test);
|
||||
eina_iterator_free(it);
|
||||
|
||||
cur_test = test2;
|
||||
it = eina_tile_grid_slicer_iterator_new(200, 210, 300, 15, 128, 128);
|
||||
check_iterator(it, cur_test);
|
||||
eina_iterator_free(it);
|
||||
|
||||
cur_test = test3;
|
||||
it = eina_tile_grid_slicer_iterator_new(200, 210, 10, 300, 128, 128);
|
||||
check_iterator(it, cur_test);
|
||||
eina_iterator_free(it);
|
||||
|
||||
cur_test = test4;
|
||||
it = eina_tile_grid_slicer_iterator_new(200, 210, 400, 300, 128, 128);
|
||||
check_iterator(it, cur_test);
|
||||
eina_iterator_free(it);
|
||||
|
||||
cur_test = test5;
|
||||
it = eina_tile_grid_slicer_iterator_new(128, 128, 128, 128, 128, 128);
|
||||
check_iterator(it, cur_test);
|
||||
eina_iterator_free(it);
|
||||
|
||||
cur_test = test6;
|
||||
it = eina_tile_grid_slicer_iterator_new(128, 128, 1, 1, 128, 128);
|
||||
check_iterator(it, cur_test);
|
||||
eina_iterator_free(it);
|
||||
|
||||
cur_test = test7;
|
||||
it = eina_tile_grid_slicer_iterator_new(128, 128, 129, 129, 128, 128);
|
||||
check_iterator(it, cur_test);
|
||||
eina_iterator_free(it);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
eina_test_tiler(TCase *tc)
|
||||
{
|
||||
tcase_add_test(tc, eina_test_tile_grid_slicer_iterator);
|
||||
}
|
Loading…
Reference in New Issue