summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cogl/Makefile.am4
-rw-r--r--cogl/cogl-atlas-texture-private.h12
-rw-r--r--cogl/cogl-atlas-texture.c169
-rw-r--r--cogl/cogl-atlas.h78
-rw-r--r--cogl/cogl-context.c7
-rw-r--r--cogl/cogl-context.h4
-rw-r--r--cogl/cogl-rectangle-map.c (renamed from cogl/cogl-atlas.c)358
-rw-r--r--cogl/cogl-rectangle-map.h78
8 files changed, 366 insertions, 344 deletions
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 9ea001cc..d0ed8498 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -144,8 +144,8 @@ cogl_sources_c = \
$(srcdir)/cogl-texture-3d.c \
$(srcdir)/cogl-texture-rectangle-private.h \
$(srcdir)/cogl-texture-rectangle.c \
- $(srcdir)/cogl-atlas.h \
- $(srcdir)/cogl-atlas.c \
+ $(srcdir)/cogl-rectangle-map.h \
+ $(srcdir)/cogl-rectangle-map.c \
$(srcdir)/cogl-atlas-texture-private.h \
$(srcdir)/cogl-atlas-texture.c \
$(srcdir)/cogl-spans.h \
diff --git a/cogl/cogl-atlas-texture-private.h b/cogl/cogl-atlas-texture-private.h
index f4fdb720..c2c9fbd8 100644
--- a/cogl/cogl-atlas-texture-private.h
+++ b/cogl/cogl-atlas-texture-private.h
@@ -26,7 +26,7 @@
#include "cogl-handle.h"
#include "cogl-texture-private.h"
-#include "cogl-atlas.h"
+#include "cogl-rectangle-map.h"
#define COGL_ATLAS_TEXTURE(tex) ((CoglAtlasTexture *) tex)
@@ -34,23 +34,23 @@ typedef struct _CoglAtlasTexture CoglAtlasTexture;
struct _CoglAtlasTexture
{
- CoglTexture _parent;
+ CoglTexture _parent;
/* The format that the texture is in. This isn't necessarily the
same format as the atlas texture because we can store
pre-multiplied and non-pre-multiplied textures together */
- CoglPixelFormat format;
+ CoglPixelFormat format;
/* The rectangle that was used to add this texture to the
atlas. This includes the 1-pixel border */
- CoglAtlasRectangle rectangle;
+ CoglRectangleMapEntry rectangle;
/* The texture might need to be migrated out in which case this will
be set to TRUE and sub_texture will actually be a real texture */
- gboolean in_atlas;
+ gboolean in_atlas;
/* A CoglSubTexture representing the region for easy rendering */
- CoglHandle sub_texture;
+ CoglHandle sub_texture;
};
GQuark
diff --git a/cogl/cogl-atlas-texture.c b/cogl/cogl-atlas-texture.c
index 5d60476f..4afba0fc 100644
--- a/cogl/cogl-atlas-texture.c
+++ b/cogl/cogl-atlas-texture.c
@@ -39,7 +39,7 @@
#include "cogl-context.h"
#include "cogl-handle.h"
#include "cogl-texture-driver.h"
-#include "cogl-atlas.h"
+#include "cogl-rectangle-map.h"
#include "cogl-journal-private.h"
#include "cogl-material-opengl-private.h"
@@ -254,18 +254,18 @@ _cogl_atlas_texture_remove_from_atlas (CoglAtlasTexture *atlas_tex)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_atlas_remove_rectangle (ctx->atlas, &atlas_tex->rectangle);
+ _cogl_rectangle_map_remove (ctx->rectangle_map, &atlas_tex->rectangle);
COGL_NOTE (ATLAS, "Removed rectangle sized %ix%i",
atlas_tex->rectangle.width,
atlas_tex->rectangle.height);
COGL_NOTE (ATLAS, "Atlas is %ix%i, has %i textures and is %i%% waste",
- _cogl_atlas_get_width (ctx->atlas),
- _cogl_atlas_get_height (ctx->atlas),
- _cogl_atlas_get_n_rectangles (ctx->atlas),
- _cogl_atlas_get_remaining_space (ctx->atlas) * 100 /
- (_cogl_atlas_get_width (ctx->atlas) *
- _cogl_atlas_get_height (ctx->atlas)));
+ _cogl_rectangle_map_get_width (ctx->rectangle_map),
+ _cogl_rectangle_map_get_height (ctx->rectangle_map),
+ _cogl_rectangle_map_get_n_rectangles (ctx->rectangle_map),
+ _cogl_rectangle_map_get_remaining_space (ctx->rectangle_map) *
+ 100 / (_cogl_rectangle_map_get_width (ctx->rectangle_map) *
+ _cogl_rectangle_map_get_height (ctx->rectangle_map)));
atlas_tex->in_atlas = FALSE;
}
@@ -599,7 +599,7 @@ _cogl_atlas_texture_get_height (CoglTexture *tex)
static CoglHandle
_cogl_atlas_texture_create_sub_texture (CoglHandle full_texture,
- const CoglAtlasRectangle *rectangle)
+ const CoglRectangleMapEntry *rectangle)
{
/* Create a subtexture for the given rectangle not including the
1-pixel border */
@@ -615,7 +615,7 @@ typedef struct _CoglAtlasTextureRepositionData
/* The current texture which already has a position */
CoglAtlasTexture *texture;
/* The new position of the texture */
- CoglAtlasRectangle new_position;
+ CoglRectangleMapEntry new_position;
} CoglAtlasTextureRepositionData;
static void
@@ -679,32 +679,32 @@ typedef struct _CoglAtlasTextureGetRectanglesData
} CoglAtlasTextureGetRectanglesData;
static void
-_cogl_atlas_texture_get_rectangles_cb (const CoglAtlasRectangle *rectangle,
- gpointer rectangle_data,
- gpointer user_data)
+_cogl_atlas_texture_get_rectangles_cb (const CoglRectangleMapEntry *rectangle,
+ gpointer rect_data,
+ gpointer user_data)
{
CoglAtlasTextureGetRectanglesData *data = user_data;
- data->textures[data->n_textures++].texture = rectangle_data;
+ data->textures[data->n_textures++].texture = rect_data;
}
static void
-_cogl_atlas_texture_get_next_size (unsigned int *atlas_width,
- unsigned int *atlas_height)
+_cogl_atlas_texture_get_next_size (unsigned int *map_width,
+ unsigned int *map_height)
{
/* Double the size of the texture by increasing whichever dimension
is smaller */
- if (*atlas_width < *atlas_height)
- *atlas_width <<= 1;
+ if (*map_width < *map_height)
+ *map_width <<= 1;
else
- *atlas_height <<= 1;
+ *map_height <<= 1;
}
-static CoglAtlas *
-_cogl_atlas_texture_create_atlas (unsigned int atlas_width,
- unsigned int atlas_height,
- unsigned int n_textures,
- CoglAtlasTextureRepositionData *textures)
+static CoglRectangleMap *
+_cogl_atlas_texture_create_map (unsigned int map_width,
+ unsigned int map_height,
+ unsigned int n_textures,
+ CoglAtlasTextureRepositionData *textures)
{
GLint max_texture_size = 1024;
@@ -717,18 +717,20 @@ _cogl_atlas_texture_create_atlas (unsigned int atlas_width,
/* Keep trying increasingly larger atlases until we can fit all of
the textures */
- while (atlas_width < max_texture_size && atlas_height < max_texture_size)
+ while (map_width < max_texture_size && map_height < max_texture_size)
{
- CoglAtlas *new_atlas = _cogl_atlas_new (atlas_width, atlas_height, NULL);
+ CoglRectangleMap *new_atlas = _cogl_rectangle_map_new (map_width,
+ map_height,
+ NULL);
unsigned int i;
/* Add all of the textures and keep track of the new position */
for (i = 0; i < n_textures; i++)
- if (!_cogl_atlas_add_rectangle (new_atlas,
- textures[i].texture->rectangle.width,
- textures[i].texture->rectangle.height,
- textures[i].texture,
- &textures[i].new_position))
+ if (!_cogl_rectangle_map_add (new_atlas,
+ textures[i].texture->rectangle.width,
+ textures[i].texture->rectangle.height,
+ textures[i].texture,
+ &textures[i].new_position))
break;
/* If the atlas can contain all of the textures then we have a
@@ -736,8 +738,8 @@ _cogl_atlas_texture_create_atlas (unsigned int atlas_width,
if (i >= n_textures)
return new_atlas;
- _cogl_atlas_free (new_atlas);
- _cogl_atlas_texture_get_next_size (&atlas_width, &atlas_height);
+ _cogl_rectangle_map_free (new_atlas);
+ _cogl_atlas_texture_get_next_size (&map_width, &map_height);
}
/* If we get here then there's no atlas that can accommodate all of
@@ -766,25 +768,26 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
unsigned int height)
{
CoglAtlasTextureGetRectanglesData data;
- CoglAtlas *new_atlas;
+ CoglRectangleMap *new_map;
CoglHandle new_tex;
- unsigned int atlas_width, atlas_height;
+ unsigned int map_width, map_height;
gboolean ret;
_COGL_GET_CONTEXT (ctx, FALSE);
/* Check if we can fit the rectangle into the existing atlas */
- if (ctx->atlas && _cogl_atlas_add_rectangle (ctx->atlas, width, height,
- new_sub_tex,
- &new_sub_tex->rectangle))
+ if (ctx->rectangle_map &&
+ _cogl_rectangle_map_add (ctx->rectangle_map, width, height,
+ new_sub_tex,
+ &new_sub_tex->rectangle))
{
COGL_NOTE (ATLAS, "Atlas is %ix%i, has %i textures and is %i%% waste",
- _cogl_atlas_get_width (ctx->atlas),
- _cogl_atlas_get_height (ctx->atlas),
- _cogl_atlas_get_n_rectangles (ctx->atlas),
- _cogl_atlas_get_remaining_space (ctx->atlas) * 100 /
- (_cogl_atlas_get_width (ctx->atlas) *
- _cogl_atlas_get_height (ctx->atlas)));
+ _cogl_rectangle_map_get_width (ctx->rectangle_map),
+ _cogl_rectangle_map_get_height (ctx->rectangle_map),
+ _cogl_rectangle_map_get_n_rectangles (ctx->rectangle_map),
+ _cogl_rectangle_map_get_remaining_space (ctx->rectangle_map) *
+ 100 / (_cogl_rectangle_map_get_width (ctx->rectangle_map) *
+ _cogl_rectangle_map_get_height (ctx->rectangle_map)));
return TRUE;
}
@@ -792,15 +795,17 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
/* We need to reorganise the atlas so we'll get an array of all the
textures currently in the atlas. */
data.n_textures = 0;
- if (ctx->atlas == NULL)
+ if (ctx->rectangle_map == NULL)
data.textures = g_malloc (sizeof (CoglAtlasTextureRepositionData));
else
{
- data.textures =
- g_malloc (sizeof (CoglAtlasTextureRepositionData) *
- (_cogl_atlas_get_n_rectangles (ctx->atlas) + 1));
- _cogl_atlas_foreach (ctx->atlas, _cogl_atlas_texture_get_rectangles_cb,
- &data);
+ unsigned int n_rectangles =
+ _cogl_rectangle_map_get_n_rectangles (ctx->rectangle_map);
+ data.textures = g_malloc (sizeof (CoglAtlasTextureRepositionData) *
+ (n_rectangles + 1));
+ _cogl_rectangle_map_foreach (ctx->rectangle_map,
+ _cogl_atlas_texture_get_rectangles_cb,
+ &data);
}
/* Add the new rectangle as a dummy texture so that it can be
@@ -815,59 +820,61 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
_cogl_atlas_texture_compare_size_cb);
/* Try to create a new atlas that can contain all of the textures */
- if (ctx->atlas)
+ if (ctx->rectangle_map)
{
- atlas_width = _cogl_atlas_get_width (ctx->atlas);
- atlas_height = _cogl_atlas_get_height (ctx->atlas);
+ map_width = _cogl_rectangle_map_get_width (ctx->rectangle_map);
+ map_height = _cogl_rectangle_map_get_height (ctx->rectangle_map);
/* If there is enough space in the existing for the new
rectangle in the existing atlas we'll start with the same
size, otherwise we'll immediately double it */
- if (_cogl_atlas_get_remaining_space (ctx->atlas) < width * height)
- _cogl_atlas_texture_get_next_size (&atlas_width, &atlas_height);
+ if (_cogl_rectangle_map_get_remaining_space (ctx->rectangle_map) <
+ width * height)
+ _cogl_atlas_texture_get_next_size (&map_width, &map_height);
}
else
{
/* Start with an initial size of 256x256 */
- atlas_width = 256;
- atlas_height = 256;
+ map_width = 256;
+ map_height = 256;
}
- new_atlas = _cogl_atlas_texture_create_atlas (atlas_width, atlas_height,
- data.n_textures, data.textures);
+ new_map = _cogl_atlas_texture_create_map (map_width, map_height,
+ data.n_textures, data.textures);
+ map_width = _cogl_rectangle_map_get_width (new_map);
+ map_height = _cogl_rectangle_map_get_height (new_map);
- /* If we can't create an atlas with the texture then give up */
- if (new_atlas == NULL)
+ /* If we can't create a map with the texture then give up */
+ if (new_map == NULL)
{
COGL_NOTE (ATLAS, "Could not fit texture in the atlas");
ret = FALSE;
}
/* We need to migrate the existing textures into a new texture */
else if ((new_tex =
- _cogl_texture_2d_new_with_size (_cogl_atlas_get_width (new_atlas),
- _cogl_atlas_get_height (new_atlas),
+ _cogl_texture_2d_new_with_size (map_width, map_height,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_RGBA_8888)) ==
COGL_INVALID_HANDLE)
{
COGL_NOTE (ATLAS, "Could not create a CoglTexture2D");
- _cogl_atlas_free (new_atlas);
+ _cogl_rectangle_map_free (new_map);
ret = FALSE;
}
else
{
COGL_NOTE (ATLAS,
"Atlas %s with size %ix%i",
- ctx->atlas == NULL ||
- _cogl_atlas_get_width (ctx->atlas) !=
- _cogl_atlas_get_width (new_atlas) ||
- _cogl_atlas_get_height (ctx->atlas) !=
- _cogl_atlas_get_height (new_atlas) ?
+ ctx->rectangle_map == NULL ||
+ _cogl_rectangle_map_get_width (ctx->rectangle_map) !=
+ _cogl_rectangle_map_get_width (new_map) ||
+ _cogl_rectangle_map_get_height (ctx->rectangle_map) !=
+ _cogl_rectangle_map_get_height (new_map) ?
"resized" : "reorganized",
- _cogl_atlas_get_width (new_atlas),
- _cogl_atlas_get_height (new_atlas));
+ _cogl_rectangle_map_get_width (new_map),
+ _cogl_rectangle_map_get_height (new_map));
- if (ctx->atlas)
+ if (ctx->rectangle_map)
{
/* Move all the textures to the right position in the new
texture. This will also update the texture's rectangle */
@@ -876,7 +883,7 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
ctx->atlas_texture,
new_tex,
new_sub_tex);
- _cogl_atlas_free (ctx->atlas);
+ _cogl_rectangle_map_free (ctx->rectangle_map);
cogl_handle_unref (ctx->atlas_texture);
}
else
@@ -884,16 +891,16 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
update the rectangle from its new position */
data.textures[0].texture->rectangle = data.textures[0].new_position;
- ctx->atlas = new_atlas;
+ ctx->rectangle_map = new_map;
ctx->atlas_texture = new_tex;
COGL_NOTE (ATLAS, "Atlas is %ix%i, has %i textures and is %i%% waste",
- _cogl_atlas_get_width (ctx->atlas),
- _cogl_atlas_get_height (ctx->atlas),
- _cogl_atlas_get_n_rectangles (ctx->atlas),
- _cogl_atlas_get_remaining_space (ctx->atlas) * 100 /
- (_cogl_atlas_get_width (ctx->atlas) *
- _cogl_atlas_get_height (ctx->atlas)));
+ _cogl_rectangle_map_get_width (ctx->rectangle_map),
+ _cogl_rectangle_map_get_height (ctx->rectangle_map),
+ _cogl_rectangle_map_get_n_rectangles (ctx->rectangle_map),
+ _cogl_rectangle_map_get_remaining_space (ctx->rectangle_map) *
+ 100 / (_cogl_rectangle_map_get_width (ctx->rectangle_map) *
+ _cogl_rectangle_map_get_height (ctx->rectangle_map)));
ret = TRUE;
}
@@ -1003,7 +1010,7 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
if (dst_bmp == NULL)
{
- _cogl_atlas_remove_rectangle (ctx->atlas, &atlas_tex->rectangle);
+ _cogl_rectangle_map_remove (ctx->rectangle_map, &atlas_tex->rectangle);
g_free (atlas_tex);
return COGL_INVALID_HANDLE;
}
diff --git a/cogl/cogl-atlas.h b/cogl/cogl-atlas.h
deleted file mode 100644
index 15d26993..00000000
--- a/cogl/cogl-atlas.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * 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 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 __COGL_ATLAS_H
-#define __COGL_ATLAS_H
-
-#include <glib.h>
-
-typedef struct _CoglAtlas CoglAtlas;
-typedef struct _CoglAtlasRectangle CoglAtlasRectangle;
-
-typedef void (* CoglAtlasCallback) (const CoglAtlasRectangle *rectangle,
- gpointer rectangle_data,
- gpointer user_data);
-
-struct _CoglAtlasRectangle
-{
- unsigned int x, y;
- unsigned int width, height;
-};
-
-CoglAtlas *
-_cogl_atlas_new (unsigned int width,
- unsigned int height,
- GDestroyNotify value_destroy_func);
-
-gboolean
-_cogl_atlas_add_rectangle (CoglAtlas *atlas,
- unsigned int width,
- unsigned int height,
- gpointer data,
- CoglAtlasRectangle *rectangle);
-
-void
-_cogl_atlas_remove_rectangle (CoglAtlas *atlas,
- const CoglAtlasRectangle *rectangle);
-
-unsigned int
-_cogl_atlas_get_width (CoglAtlas *atlas);
-
-unsigned int
-_cogl_atlas_get_height (CoglAtlas *atlas);
-
-unsigned int
-_cogl_atlas_get_remaining_space (CoglAtlas *atlas);
-
-unsigned int
-_cogl_atlas_get_n_rectangles (CoglAtlas *atlas);
-
-void
-_cogl_atlas_foreach (CoglAtlas *atlas,
- CoglAtlasCallback callback,
- gpointer data);
-
-void
-_cogl_atlas_free (CoglAtlas *atlas);
-
-#endif /* __COGL_ATLAS_H */
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 80ef4613..2668043c 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -214,7 +214,7 @@ cogl_create_context (void)
_cogl_enable (enable_flags);
_cogl_flush_face_winding ();
- _context->atlas = NULL;
+ _context->rectangle_map = NULL;
_context->atlas_texture = COGL_INVALID_HANDLE;
/* As far as I can tell, GL_POINT_SPRITE doesn't have any effect
@@ -273,8 +273,9 @@ _cogl_destroy_context (void)
if (_context->default_layer_0)
cogl_handle_unref (_context->default_layer_0);
- if (_context->atlas)
- _cogl_atlas_free (_context->atlas);
+ if (_context->rectangle_map)
+ _cogl_rectangle_map_free (_context->rectangle_map);
+
if (_context->atlas_texture)
cogl_handle_unref (_context->atlas_texture);
diff --git a/cogl/cogl-context.h b/cogl/cogl-context.h
index 1d1d0745..b89ee057 100644
--- a/cogl/cogl-context.h
+++ b/cogl/cogl-context.h
@@ -31,7 +31,7 @@
#include "cogl-clip-stack.h"
#include "cogl-matrix-stack.h"
#include "cogl-material-private.h"
-#include "cogl-atlas.h"
+#include "cogl-rectangle-map.h"
#include "cogl-buffer-private.h"
#include "cogl-bitmask.h"
@@ -143,7 +143,7 @@ typedef struct
CoglMaterial *texture_download_material;
- CoglAtlas *atlas;
+ CoglRectangleMap *rectangle_map;
CoglHandle atlas_texture;
/* This debugging variable is used to pick a colour for visually
diff --git a/cogl/cogl-atlas.c b/cogl/cogl-rectangle-map.c
index d381589b..77f1d066 100644
--- a/cogl/cogl-atlas.c
+++ b/cogl/cogl-rectangle-map.c
@@ -30,7 +30,7 @@
#include <glib.h>
-#include "cogl-atlas.h"
+#include "cogl-rectangle-map.h"
#include "cogl-debug.h"
/* Implements a data structure which keeps track of unused
@@ -46,26 +46,26 @@
the atlas */
#include <cairo.h>
-static void _cogl_atlas_dump_image (CoglAtlas *atlas);
+static void _cogl_rectangle_map_dump_image (CoglRectangleMap *map);
#endif /* COGL_ENABLE_DEBUG */
-typedef struct _CoglAtlasNode CoglAtlasNode;
-typedef struct _CoglAtlasStackEntry CoglAtlasStackEntry;
+typedef struct _CoglRectangleMapNode CoglRectangleMapNode;
+typedef struct _CoglRectangleMapStackEntry CoglRectangleMapStackEntry;
-typedef void (* CoglAtlasInternalForeachCb) (CoglAtlasNode *node,
- gpointer data);
+typedef void (* CoglRectangleMapInternalForeachCb) (CoglRectangleMapNode *node,
+ void *data);
typedef enum
{
- COGL_ATLAS_BRANCH,
- COGL_ATLAS_FILLED_LEAF,
- COGL_ATLAS_EMPTY_LEAF
-} CoglAtlasNodeType;
+ COGL_RECTANGLE_MAP_BRANCH,
+ COGL_RECTANGLE_MAP_FILLED_LEAF,
+ COGL_RECTANGLE_MAP_EMPTY_LEAF
+} CoglRectangleMapNodeType;
-struct _CoglAtlas
+struct _CoglRectangleMap
{
- CoglAtlasNode *root;
+ CoglRectangleMapNode *root;
unsigned int space_remaining;
unsigned int n_rectangles;
@@ -73,80 +73,81 @@ struct _CoglAtlas
GDestroyNotify value_destroy_func;
};
-struct _CoglAtlasNode
+struct _CoglRectangleMapNode
{
- CoglAtlasNodeType type;
+ CoglRectangleMapNodeType type;
- CoglAtlasRectangle rectangle;
+ CoglRectangleMapEntry rectangle;
- CoglAtlasNode *parent;
+ CoglRectangleMapNode *parent;
union
{
/* Fields used when this is a branch */
struct
{
- CoglAtlasNode *left;
- CoglAtlasNode *right;
+ CoglRectangleMapNode *left;
+ CoglRectangleMapNode *right;
} branch;
/* Field used when this is a filled leaf */
- gpointer data;
+ void *data;
} d;
};
-struct _CoglAtlasStackEntry
+struct _CoglRectangleMapStackEntry
{
/* The node to search */
- CoglAtlasNode *node;
+ CoglRectangleMapNode *node;
/* Index of next branch of this node to explore. Basically either 0
to go left or 1 to go right */
gboolean next_index;
/* Next entry in the stack */
- CoglAtlasStackEntry *next;
+ CoglRectangleMapStackEntry *next;
};
-static CoglAtlasNode *
-_cogl_atlas_node_new (void)
+static CoglRectangleMapNode *
+_cogl_rectangle_map_node_new (void)
{
- return g_slice_new (CoglAtlasNode);
+ return g_slice_new (CoglRectangleMapNode);
}
static void
-_cogl_atlas_node_free (CoglAtlasNode *node)
+_cogl_rectangle_map_node_free (CoglRectangleMapNode *node)
{
- g_slice_free (CoglAtlasNode, node);
+ g_slice_free (CoglRectangleMapNode, node);
}
-CoglAtlas *
-_cogl_atlas_new (unsigned int width,
- unsigned int height,
- GDestroyNotify value_destroy_func)
+CoglRectangleMap *
+_cogl_rectangle_map_new (unsigned int width,
+ unsigned int height,
+ GDestroyNotify value_destroy_func)
{
- CoglAtlas *atlas = g_new (CoglAtlas, 1);
- CoglAtlasNode *root = _cogl_atlas_node_new ();
+ CoglRectangleMap *map = g_new (CoglRectangleMap, 1);
+ CoglRectangleMapNode *root = _cogl_rectangle_map_node_new ();
- root->type = COGL_ATLAS_EMPTY_LEAF;
+ root->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
root->parent = NULL;
root->rectangle.x = 0;
root->rectangle.y = 0;
root->rectangle.width = width;
root->rectangle.height = height;
- atlas->root = root;
- atlas->space_remaining = width * height;
- atlas->n_rectangles = 0;
- atlas->value_destroy_func = value_destroy_func;
+ map->root = root;
+ map->space_remaining = width * height;
+ map->n_rectangles = 0;
+ map->value_destroy_func = value_destroy_func;
- return atlas;
+ return map;
}
-static CoglAtlasStackEntry *
-_cogl_atlas_stack_push (CoglAtlasStackEntry *stack,
- CoglAtlasNode *node,
- gboolean next_index)
+static CoglRectangleMapStackEntry *
+_cogl_rectangle_map_stack_push (CoglRectangleMapStackEntry *stack,
+ CoglRectangleMapNode *node,
+ gboolean next_index)
{
- CoglAtlasStackEntry *new_entry = g_slice_new (CoglAtlasStackEntry);
+ CoglRectangleMapStackEntry *new_entry =
+ g_slice_new (CoglRectangleMapStackEntry);
new_entry->node = node;
new_entry->next_index = next_index;
@@ -155,19 +156,19 @@ _cogl_atlas_stack_push (CoglAtlasStackEntry *stack,
return new_entry;
}
-static CoglAtlasStackEntry *
-_cogl_atlas_stack_pop (CoglAtlasStackEntry *stack)
+static CoglRectangleMapStackEntry *
+_cogl_rectangle_map_stack_pop (CoglRectangleMapStackEntry *stack)
{
- CoglAtlasStackEntry *next = stack->next;
+ CoglRectangleMapStackEntry *next = stack->next;
- g_slice_free (CoglAtlasStackEntry, stack);
+ g_slice_free (CoglRectangleMapStackEntry, stack);
return next;
}
-static CoglAtlasNode *
-_cogl_atlas_node_split_horizontally (CoglAtlasNode *node,
- unsigned int left_width)
+static CoglRectangleMapNode *
+_cogl_rectangle_map_node_split_horizontally (CoglRectangleMapNode *node,
+ unsigned int left_width)
{
/* Splits the node horizontally (according to emacs' definition, not
vim) by converting it to a branch and adding two new leaf
@@ -175,13 +176,13 @@ _cogl_atlas_node_split_horizontally (CoglAtlasNode *node,
will be returned. If the node is already just the right size it
won't do anything */
- CoglAtlasNode *left_node, *right_node;
+ CoglRectangleMapNode *left_node, *right_node;
if (node->rectangle.width == left_width)
return node;
- left_node = _cogl_atlas_node_new ();
- left_node->type = COGL_ATLAS_EMPTY_LEAF;
+ left_node = _cogl_rectangle_map_node_new ();
+ left_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
left_node->parent = node;
left_node->rectangle.x = node->rectangle.x;
left_node->rectangle.y = node->rectangle.y;
@@ -189,8 +190,8 @@ _cogl_atlas_node_split_horizontally (CoglAtlasNode *node,
left_node->rectangle.height = node->rectangle.height;
node->d.branch.left = left_node;
- right_node = _cogl_atlas_node_new ();
- right_node->type = COGL_ATLAS_EMPTY_LEAF;
+ right_node = _cogl_rectangle_map_node_new ();
+ right_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
right_node->parent = node;
right_node->rectangle.x = node->rectangle.x + left_width;
right_node->rectangle.y = node->rectangle.y;
@@ -198,14 +199,14 @@ _cogl_atlas_node_split_horizontally (CoglAtlasNode *node,
right_node->rectangle.height = node->rectangle.height;
node->d.branch.right = right_node;
- node->type = COGL_ATLAS_BRANCH;
+ node->type = COGL_RECTANGLE_MAP_BRANCH;
return left_node;
}
-static CoglAtlasNode *
-_cogl_atlas_node_split_vertically (CoglAtlasNode *node,
- unsigned int top_height)
+static CoglRectangleMapNode *
+_cogl_rectangle_map_node_split_vertically (CoglRectangleMapNode *node,
+ unsigned int top_height)
{
/* Splits the node vertically (according to emacs' definition, not
vim) by converting it to a branch and adding two new leaf
@@ -213,13 +214,13 @@ _cogl_atlas_node_split_vertically (CoglAtlasNode *node,
will be returned. If the node is already just the right size it
won't do anything */
- CoglAtlasNode *top_node, *bottom_node;
+ CoglRectangleMapNode *top_node, *bottom_node;
if (node->rectangle.height == top_height)
return node;
- top_node = _cogl_atlas_node_new ();
- top_node->type = COGL_ATLAS_EMPTY_LEAF;
+ top_node = _cogl_rectangle_map_node_new ();
+ top_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
top_node->parent = node;
top_node->rectangle.x = node->rectangle.x;
top_node->rectangle.y = node->rectangle.y;
@@ -227,8 +228,8 @@ _cogl_atlas_node_split_vertically (CoglAtlasNode *node,
top_node->rectangle.height = top_height;
node->d.branch.left = top_node;
- bottom_node = _cogl_atlas_node_new ();
- bottom_node->type = COGL_ATLAS_EMPTY_LEAF;
+ bottom_node = _cogl_rectangle_map_node_new ();
+ bottom_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
bottom_node->parent = node;
bottom_node->rectangle.x = node->rectangle.x;
bottom_node->rectangle.y = node->rectangle.y + top_height;
@@ -236,36 +237,36 @@ _cogl_atlas_node_split_vertically (CoglAtlasNode *node,
bottom_node->rectangle.height = node->rectangle.height - top_height;
node->d.branch.right = bottom_node;
- node->type = COGL_ATLAS_BRANCH;
+ node->type = COGL_RECTANGLE_MAP_BRANCH;
return top_node;
}
gboolean
-_cogl_atlas_add_rectangle (CoglAtlas *atlas,
- unsigned int width,
- unsigned int height,
- gpointer data,
- CoglAtlasRectangle *rectangle)
+_cogl_rectangle_map_add (CoglRectangleMap *map,
+ unsigned int width,
+ unsigned int height,
+ void *data,
+ CoglRectangleMapEntry *rectangle)
{
/* Stack of nodes to search in */
- CoglAtlasStackEntry *node_stack;
- CoglAtlasNode *found_node = NULL;
+ CoglRectangleMapStackEntry *node_stack;
+ CoglRectangleMapNode *found_node = NULL;
/* Zero-sized rectangles break the algorithm for removing rectangles
so we'll disallow them */
g_return_val_if_fail (width > 0 && height > 0, FALSE);
/* Start with the root node */
- node_stack = _cogl_atlas_stack_push (NULL, atlas->root, FALSE);
+ node_stack = _cogl_rectangle_map_stack_push (NULL, map->root, FALSE);
/* Depth-first search for an empty node that is big enough */
while (node_stack)
{
/* Pop an entry off the stack */
- CoglAtlasNode *node = node_stack->node;
+ CoglRectangleMapNode *node = node_stack->node;
int next_index = node_stack->next_index;
- node_stack = _cogl_atlas_stack_pop (node_stack);
+ node_stack = _cogl_rectangle_map_stack_pop (node_stack);
/* Regardless of the type of the node, there's no point
descending any further if the new rectangle won't fit within
@@ -273,30 +274,33 @@ _cogl_atlas_add_rectangle (CoglAtlas *atlas,
if (node->rectangle.width >= width &&
node->rectangle.height >= height)
{
- if (node->type == COGL_ATLAS_EMPTY_LEAF)
+ if (node->type == COGL_RECTANGLE_MAP_EMPTY_LEAF)
{
/* We've found a node we can use */
found_node = node;
break;
}
- else if (node->type == COGL_ATLAS_BRANCH)
+ else if (node->type == COGL_RECTANGLE_MAP_BRANCH)
{
if (next_index)
/* Try the right branch */
- node_stack = _cogl_atlas_stack_push (node_stack,
- node->d.branch.right,
- 0);
+ node_stack =
+ _cogl_rectangle_map_stack_push (node_stack,
+ node->d.branch.right,
+ 0);
else
{
/* Make sure we remember to try the right branch once
we've finished descending the left branch */
- node_stack = _cogl_atlas_stack_push (node_stack,
- node,
- 1);
+ node_stack =
+ _cogl_rectangle_map_stack_push (node_stack,
+ node,
+ 1);
/* Try the left branch */
- node_stack = _cogl_atlas_stack_push (node_stack,
- node->d.branch.left,
- 0);
+ node_stack =
+ _cogl_rectangle_map_stack_push (node_stack,
+ node->d.branch.left,
+ 0);
}
}
}
@@ -304,7 +308,7 @@ _cogl_atlas_add_rectangle (CoglAtlas *atlas,
/* Free the stack */
while (node_stack)
- node_stack = _cogl_atlas_stack_pop (node_stack);
+ node_stack = _cogl_rectangle_map_stack_pop (node_stack);
if (found_node)
{
@@ -313,29 +317,33 @@ _cogl_atlas_add_rectangle (CoglAtlas *atlas,
if (found_node->rectangle.width - width >
found_node->rectangle.height - height)
{
- found_node = _cogl_atlas_node_split_horizontally (found_node, width);
- found_node = _cogl_atlas_node_split_vertically (found_node, height);
+ found_node =
+ _cogl_rectangle_map_node_split_horizontally (found_node, width);
+ found_node =
+ _cogl_rectangle_map_node_split_vertically (found_node, height);
}
else
{
- found_node = _cogl_atlas_node_split_vertically (found_node, height);
- found_node = _cogl_atlas_node_split_horizontally (found_node, width);
+ found_node =
+ _cogl_rectangle_map_node_split_vertically (found_node, height);
+ found_node =
+ _cogl_rectangle_map_node_split_horizontally (found_node, width);
}
- found_node->type = COGL_ATLAS_FILLED_LEAF;
+ found_node->type = COGL_RECTANGLE_MAP_FILLED_LEAF;
found_node->d.data = data;
if (rectangle)
*rectangle = found_node->rectangle;
/* Record how much empty space is remaining after this rectangle
is added */
- g_assert (width * height <= atlas->space_remaining);
- atlas->space_remaining -= width * height;
- atlas->n_rectangles++;
+ g_assert (width * height <= map->space_remaining);
+ map->space_remaining -= width * height;
+ map->n_rectangles++;
#ifdef COGL_ENABLE_DEBUG
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DUMP_ATLAS_IMAGE))
- _cogl_atlas_dump_image (atlas);
+ _cogl_rectangle_map_dump_image (map);
#endif
return TRUE;
@@ -345,15 +353,15 @@ _cogl_atlas_add_rectangle (CoglAtlas *atlas,
}
void
-_cogl_atlas_remove_rectangle (CoglAtlas *atlas,
- const CoglAtlasRectangle *rectangle)
+_cogl_rectangle_map_remove (CoglRectangleMap *map,
+ const CoglRectangleMapEntry *rectangle)
{
- CoglAtlasNode *node = atlas->root;
+ CoglRectangleMapNode *node = map->root;
/* We can do a binary-chop down the search tree to find the rectangle */
- while (node->type == COGL_ATLAS_BRANCH)
+ while (node->type == COGL_RECTANGLE_MAP_BRANCH)
{
- CoglAtlasNode *left_node = node->d.branch.left;
+ CoglRectangleMapNode *left_node = node->d.branch.left;
/* If and only if the rectangle is in the left node then the x,y
position of the rectangle will be within the node's
@@ -368,103 +376,103 @@ _cogl_atlas_remove_rectangle (CoglAtlas *atlas,
}
/* Make sure we found the right node */
- if (node->type != COGL_ATLAS_FILLED_LEAF ||
+ if (node->type != COGL_RECTANGLE_MAP_FILLED_LEAF ||
node->rectangle.x != rectangle->x ||
node->rectangle.y != rectangle->y ||
node->rectangle.width != rectangle->width ||
node->rectangle.height != rectangle->height)
/* This should only happen if someone tried to remove a rectangle
- that was not in the atlas so something has gone wrong */
+ that was not in the map so something has gone wrong */
g_return_if_reached ();
else
{
/* Convert the node back to an empty node */
- if (atlas->value_destroy_func)
- atlas->value_destroy_func (node->d.data);
- node->type = COGL_ATLAS_EMPTY_LEAF;
+ if (map->value_destroy_func)
+ map->value_destroy_func (node->d.data);
+ node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
/* Walk back up the tree combining branch nodes that have two
empty leaves back into a single empty leaf */
for (node = node->parent; node; node = node->parent)
{
/* This node is a parent so it should always be a branch */
- g_assert (node->type == COGL_ATLAS_BRANCH);
+ g_assert (node->type == COGL_RECTANGLE_MAP_BRANCH);
- if (node->d.branch.left->type == COGL_ATLAS_EMPTY_LEAF &&
- node->d.branch.right->type == COGL_ATLAS_EMPTY_LEAF)
+ if (node->d.branch.left->type == COGL_RECTANGLE_MAP_EMPTY_LEAF &&
+ node->d.branch.right->type == COGL_RECTANGLE_MAP_EMPTY_LEAF)
{
- _cogl_atlas_node_free (node->d.branch.left);
- _cogl_atlas_node_free (node->d.branch.right);
- node->type = COGL_ATLAS_EMPTY_LEAF;
+ _cogl_rectangle_map_node_free (node->d.branch.left);
+ _cogl_rectangle_map_node_free (node->d.branch.right);
+ node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
}
else
break;
}
/* There is now more free space and one less rectangle */
- atlas->space_remaining += rectangle->width * rectangle->height;
- g_assert (atlas->n_rectangles > 0);
- atlas->n_rectangles--;
+ map->space_remaining += rectangle->width * rectangle->height;
+ g_assert (map->n_rectangles > 0);
+ map->n_rectangles--;
}
#ifdef COGL_ENABLE_DEBUG
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DUMP_ATLAS_IMAGE))
- _cogl_atlas_dump_image (atlas);
+ _cogl_rectangle_map_dump_image (map);
#endif
}
unsigned int
-_cogl_atlas_get_width (CoglAtlas *atlas)
+_cogl_rectangle_map_get_width (CoglRectangleMap *map)
{
- return atlas->root->rectangle.width;
+ return map->root->rectangle.width;
}
unsigned int
-_cogl_atlas_get_height (CoglAtlas *atlas)
+_cogl_rectangle_map_get_height (CoglRectangleMap *map)
{
- return atlas->root->rectangle.height;
+ return map->root->rectangle.height;
}
unsigned int
-_cogl_atlas_get_remaining_space (CoglAtlas *atlas)
+_cogl_rectangle_map_get_remaining_space (CoglRectangleMap *map)
{
- return atlas->space_remaining;
+ return map->space_remaining;
}
unsigned int
-_cogl_atlas_get_n_rectangles (CoglAtlas *atlas)
+_cogl_rectangle_map_get_n_rectangles (CoglRectangleMap *map)
{
- return atlas->n_rectangles;
+ return map->n_rectangles;
}
static void
-_cogl_atlas_internal_foreach (CoglAtlas *atlas,
- CoglAtlasInternalForeachCb callback,
- gpointer data)
+_cogl_rectangle_map_internal_foreach (CoglRectangleMap *map,
+ CoglRectangleMapInternalForeachCb func,
+ void *data)
{
/* Stack of nodes to search in */
- CoglAtlasStackEntry *node_stack;
+ CoglRectangleMapStackEntry *node_stack;
/* Start with the root node */
- node_stack = _cogl_atlas_stack_push (NULL, atlas->root, 0);
+ node_stack = _cogl_rectangle_map_stack_push (NULL, map->root, 0);
/* Iterate all nodes depth-first */
while (node_stack)
{
- CoglAtlasNode *node = node_stack->node;
+ CoglRectangleMapNode *node = node_stack->node;
switch (node->type)
{
- case COGL_ATLAS_BRANCH:
+ case COGL_RECTANGLE_MAP_BRANCH:
if (node_stack->next_index == 0)
{
/* Next time we come back to this node, go to the right */
node_stack->next_index = 1;
/* Explore the left branch next */
- node_stack = _cogl_atlas_stack_push (node_stack,
- node->d.branch.left,
- 0);
+ node_stack = _cogl_rectangle_map_stack_push (node_stack,
+ node->d.branch.left,
+ 0);
}
else if (node_stack->next_index == 1)
{
@@ -472,22 +480,22 @@ _cogl_atlas_internal_foreach (CoglAtlas *atlas,
node_stack->next_index = 2;
/* Explore the right branch next */
- node_stack = _cogl_atlas_stack_push (node_stack,
- node->d.branch.right,
- 0);
+ node_stack = _cogl_rectangle_map_stack_push (node_stack,
+ node->d.branch.right,
+ 0);
}
else
{
/* We're finished with this node so we can call the callback */
- callback (node, data);
- node_stack = _cogl_atlas_stack_pop (node_stack);
+ func (node, data);
+ node_stack = _cogl_rectangle_map_stack_pop (node_stack);
}
break;
default:
/* Some sort of leaf node, just call the callback */
- callback (node, data);
- node_stack = _cogl_atlas_stack_pop (node_stack);
+ func (node, data);
+ node_stack = _cogl_rectangle_map_stack_pop (node_stack);
break;
}
}
@@ -496,65 +504,69 @@ _cogl_atlas_internal_foreach (CoglAtlas *atlas,
g_assert (node_stack == NULL);
}
-typedef struct _CoglAtlasForeachClosure
+typedef struct _CoglRectangleMapForeachClosure
{
- CoglAtlasCallback callback;
- gpointer data;
-} CoglAtlasForeachClosure;
+ CoglRectangleMapCallback callback;
+ void *data;
+} CoglRectangleMapForeachClosure;
static void
-_cogl_atlas_foreach_cb (CoglAtlasNode *node, gpointer data)
+_cogl_rectangle_map_foreach_cb (CoglRectangleMapNode *node, void *data)
{
- CoglAtlasForeachClosure *closure = data;
+ CoglRectangleMapForeachClosure *closure = data;
- if (node->type == COGL_ATLAS_FILLED_LEAF)
+ if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF)
closure->callback (&node->rectangle, node->d.data, closure->data);
}
void
-_cogl_atlas_foreach (CoglAtlas *atlas,
- CoglAtlasCallback callback,
- gpointer data)
+_cogl_rectangle_map_foreach (CoglRectangleMap *map,
+ CoglRectangleMapCallback callback,
+ void *data)
{
- CoglAtlasForeachClosure closure;
+ CoglRectangleMapForeachClosure closure;
closure.callback = callback;
closure.data = data;
- _cogl_atlas_internal_foreach (atlas, _cogl_atlas_foreach_cb, &closure);
+ _cogl_rectangle_map_internal_foreach (map,
+ _cogl_rectangle_map_foreach_cb,
+ &closure);
}
static void
-_cogl_atlas_free_cb (CoglAtlasNode *node, gpointer data)
+_cogl_rectangle_map_free_cb (CoglRectangleMapNode *node, void *data)
{
- CoglAtlas *atlas = data;
+ CoglRectangleMap *map = data;
- if (node->type == COGL_ATLAS_FILLED_LEAF && atlas->value_destroy_func)
- atlas->value_destroy_func (node->d.data);
+ if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF && map->value_destroy_func)
+ map->value_destroy_func (node->d.data);
- _cogl_atlas_node_free (node);
+ _cogl_rectangle_map_node_free (node);
}
void
-_cogl_atlas_free (CoglAtlas *atlas)
+_cogl_rectangle_map_free (CoglRectangleMap *map)
{
- _cogl_atlas_internal_foreach (atlas, _cogl_atlas_free_cb, atlas);
- g_free (atlas);
+ _cogl_rectangle_map_internal_foreach (map,
+ _cogl_rectangle_map_free_cb,
+ map);
+ g_free (map);
}
#ifdef COGL_ENABLE_DEBUG
static void
-_cogl_atlas_dump_image_cb (CoglAtlasNode *node, gpointer data)
+_cogl_rectangle_map_dump_image_cb (CoglRectangleMapNode *node, void *data)
{
cairo_t *cr = data;
- if (node->type == COGL_ATLAS_FILLED_LEAF ||
- node->type == COGL_ATLAS_EMPTY_LEAF)
+ if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF ||
+ node->type == COGL_RECTANGLE_MAP_EMPTY_LEAF)
{
/* Fill the rectangle using a different colour depending on
whether the rectangle is used */
- if (node->type == COGL_ATLAS_FILLED_LEAF)
+ if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF)
cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
else
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
@@ -574,23 +586,25 @@ _cogl_atlas_dump_image_cb (CoglAtlasNode *node, gpointer data)
}
static void
-_cogl_atlas_dump_image (CoglAtlas *atlas)
+_cogl_rectangle_map_dump_image (CoglRectangleMap *map)
{
- /* This dumps a png to help visualize the atlas. Each leaf rectangle
+ /* This dumps a png to help visualize the map. Each leaf rectangle
is drawn with a white outline. Unused leaves are filled in black
and used leaves are blue */
cairo_surface_t *surface =
cairo_image_surface_create (CAIRO_FORMAT_RGB24,
- _cogl_atlas_get_width (atlas),
- _cogl_atlas_get_height (atlas));
+ _cogl_rectangle_map_get_width (map),
+ _cogl_rectangle_map_get_height (map));
cairo_t *cr = cairo_create (surface);
- _cogl_atlas_internal_foreach (atlas, _cogl_atlas_dump_image_cb, cr);
+ _cogl_rectangle_map_internal_foreach (map,
+ _cogl_rectangle_map_dump_image_cb,
+ cr);
cairo_destroy (cr);
- cairo_surface_write_to_png (surface, "cogl-atlas-dump.png");
+ cairo_surface_write_to_png (surface, "cogl-rectangle-map-dump.png");
cairo_surface_destroy (surface);
}
diff --git a/cogl/cogl-rectangle-map.h b/cogl/cogl-rectangle-map.h
new file mode 100644
index 00000000..51b92608
--- /dev/null
+++ b/cogl/cogl-rectangle-map.h
@@ -0,0 +1,78 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2009 Intel Corporation.
+ *
+ * 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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __COGL_RECTANGLE_MAP_H
+#define __COGL_RECTANGLE_MAP_H
+
+#include <glib.h>
+
+typedef struct _CoglRectangleMap CoglRectangleMap;
+typedef struct _CoglRectangleMapEntry CoglRectangleMapEntry;
+
+typedef void (* CoglRectangleMapCallback) (const CoglRectangleMapEntry *entry,
+ void *rectangle_data,
+ void *user_data);
+
+struct _CoglRectangleMapEntry
+{
+ unsigned int x, y;
+ unsigned int width, height;
+};
+
+CoglRectangleMap *
+_cogl_rectangle_map_new (unsigned int width,
+ unsigned int height,
+ GDestroyNotify value_destroy_func);
+
+gboolean
+_cogl_rectangle_map_add (CoglRectangleMap *map,
+ unsigned int width,
+ unsigned int height,
+ void *data,
+ CoglRectangleMapEntry *rectangle);
+
+void
+_cogl_rectangle_map_remove (CoglRectangleMap *map,
+ const CoglRectangleMapEntry *rectangle);
+
+unsigned int
+_cogl_rectangle_map_get_width (CoglRectangleMap *map);
+
+unsigned int
+_cogl_rectangle_map_get_height (CoglRectangleMap *map);
+
+unsigned int
+_cogl_rectangle_map_get_remaining_space (CoglRectangleMap *map);
+
+unsigned int
+_cogl_rectangle_map_get_n_rectangles (CoglRectangleMap *map);
+
+void
+_cogl_rectangle_map_foreach (CoglRectangleMap *map,
+ CoglRectangleMapCallback callback,
+ void *data);
+
+void
+_cogl_rectangle_map_free (CoglRectangleMap *map);
+
+#endif /* __COGL_RECTANGLE_MAP_H */