170 {
171
173
174 const size_t count = self->
images->count;
175 if (count == 0) {
176 return true;
177 }
178
180 assert(images);
181
182 SDL_Rect *rects = calloc(count, sizeof(SDL_Rect));
183 assert(rects);
184
185 size_t area = 0;
187
188 for (size_t i = 0; i < count; i++) {
189 images[i] = $(self->
images, objectAtIndex, i);
190
192 area += (size_t) surface->w * (size_t) surface->h;
193 size = max(
size, max(surface->w, surface->h));
194 }
195
197
198 size = max(
size, (
int) ceil(sqrt((
double) area)));
199
200 int sheetSize = 1;
201 while (sheetSize <
size) {
202 sheetSize <<= 1;
203 }
204
205 bool packed = false;
206 while (sheetSize <= self->maxSize) {
207 if (
pack(images, rects, count, sheetSize)) {
208 packed = true;
209 break;
210 }
211 sheetSize <<= 1;
212 }
213
214 if (packed) {
215
216 for (size_t i = 0; i < count; i++) {
217 images[i]->
rect = rects[i];
218 }
219
220 SDL_Surface *sheet = SDL_CreateSurface(sheetSize, sheetSize, SDL_PIXELFORMAT_RGBA32);
221 assert(sheet);
222
223 SDL_FillSurfaceRect(sheet, NULL, 0);
224
225 for (size_t i = 0; i < count; i++) {
226
229 const size_t pitch = surface->w * SDL_BYTESPERPIXEL(surface->format);
230
231 for (int y = 0; y < surface->h; y++) {
232 memcpy((Uint8 *) sheet->pixels + (
image->rect.y + y) * sheet->pitch +
image->rect.x * SDL_BYTESPERPIXEL(sheet->format),
233 (const Uint8 *) surface->pixels + y * surface->pitch,
234 pitch);
235 }
236 }
237
238 release(self->
image);
241
242 SDL_DestroySurface(sheet);
243
244 self->texture = release(self->texture);
245
246 } else {
248 }
249
250 free(rects);
251 free(images);
252
253 return packed;
254}
static Image * imageWithSurface(SDL_Surface *surface)
static SDL_Size size(const Image *self)
static int compareImages(const void *a, const void *b)
Sorts AtlasImages tallest first, then widest, so that shelf rows waste the least.
static bool pack(AtlasImage **images, SDL_Rect *rects, size_t count, int size)
Lays out the sorted images in shelves on a square of the given size, writing their rects to rects rat...
SDL_Rect rect
This AtlasImage's rectangle within the atlas sheet, in texels.
Image image
The superclass.
int maxSize
The largest sheet dimension ImageAtlas::compile will attempt.
Image * image
The compiled sheet, or NULL until ImageAtlas::compile.
SDL_Surface * surface
The backing surface.