Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_atlas.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
27
28#include "nilorea/n_atlas.h"
29
30#include "allegro5/allegro_image.h"
31#include "allegro5/allegro_memfile.h"
32
44 ALLEGRO_DISPLAY* d = al_get_current_display();
45 int m = d ? al_get_display_option(d, ALLEGRO_MAX_BITMAP_SIZE) : 0;
46 return m > 0 ? m : 2048;
47}
48
54N_ATLAS* new_n_atlas(size_t npages) {
55 N_ATLAS* atlas = NULL;
56
57 __n_assert(npages > 0, return NULL);
58
59 Malloc(atlas, N_ATLAS, 1);
60 __n_assert(atlas, return NULL);
61
62 Malloc(atlas->pages, N_ATLAS_PAGE, npages);
63 if (!atlas->pages) {
64 Free(atlas);
65 return NULL;
66 }
67 atlas->npages = npages;
68 return atlas;
69}
70
75void n_atlas_destroy(N_ATLAS** atlas) {
76 __n_assert(atlas && (*atlas), return);
77
78 if ((*atlas)->pages) {
79 size_t it = 0;
80 for (it = 0; it < (*atlas)->npages; it++) {
81 if ((*atlas)->pages[it].bmp) {
82 al_destroy_bitmap((*atlas)->pages[it].bmp);
83 (*atlas)->pages[it].bmp = NULL;
84 }
85 }
86 Free((*atlas)->pages);
87 }
88 Free((*atlas));
89 return;
90}
91
112int n_atlas_set_page(N_ATLAS* atlas, size_t page, const void* bytes, size_t len, const char* ext, uint16_t cols, uint16_t rows) {
113 ALLEGRO_FILE* mf = NULL;
114 ALLEGRO_BITMAP* bmp = NULL;
115 int maxpx = 0;
116
117 __n_assert(atlas, return FALSE);
118 __n_assert(atlas->pages, return FALSE);
119 __n_assert(bytes, return FALSE);
120 __n_assert(ext, return FALSE);
121 __n_assert(page < atlas->npages, return FALSE);
122 __n_assert(len > 0, return FALSE);
123 __n_assert(cols > 0, return FALSE);
124 __n_assert(rows > 0, return FALSE);
125
126 mf = al_open_memfile((void*)bytes, (int64_t)len, "r");
127 if (!mf) {
128 n_log(LOG_ERR, "could not open a memfile over %zu bytes", len);
129 return FALSE;
130 }
131 bmp = al_load_bitmap_f(mf, ext);
132 al_fclose(mf);
133 if (!bmp) {
134 n_log(LOG_ERR, "could not decode a '%s' atlas page from %zu bytes", ext, len);
135 return FALSE;
136 }
137
138 maxpx = n_atlas_max_bitmap_size();
139 if (al_get_bitmap_width(bmp) > maxpx || al_get_bitmap_height(bmp) > maxpx) {
140 n_log(LOG_ERR, "atlas page %zu is %dx%d, over this display's %d limit", page, al_get_bitmap_width(bmp), al_get_bitmap_height(bmp), maxpx);
141 al_destroy_bitmap(bmp);
142 return FALSE;
143 }
144
145 if (atlas->pages[page].bmp) {
146 al_destroy_bitmap(atlas->pages[page].bmp);
147 }
148 atlas->pages[page].bmp = bmp;
149 atlas->pages[page].cols = cols;
150 atlas->pages[page].rows = rows;
151 return TRUE;
152}
153
160int n_atlas_page_ready(const N_ATLAS* atlas, size_t page) {
161 __n_assert(atlas, return FALSE);
162 __n_assert(atlas->pages, return FALSE);
163 if (page >= atlas->npages) {
164 return FALSE;
165 }
166 return (atlas->pages[page].bmp && atlas->pages[page].cols > 0 && atlas->pages[page].rows > 0) ? TRUE : FALSE;
167}
168
183int n_atlas_cell_rect(const N_ATLAS* atlas, size_t page, size_t index, float* sx, float* sy, float* sw, float* sh) {
184 size_t col = 0, row = 0;
185 float cw = 0.0, ch = 0.0;
186
187 if (!n_atlas_page_ready(atlas, page)) {
188 return FALSE;
189 }
190 col = index % (size_t)atlas->pages[page].cols;
191 row = index / (size_t)atlas->pages[page].cols;
192 if (row >= (size_t)atlas->pages[page].rows) {
193 return FALSE; /* index past the end of the grid */
194 }
195 cw = (float)al_get_bitmap_width(atlas->pages[page].bmp) / (float)atlas->pages[page].cols;
196 ch = (float)al_get_bitmap_height(atlas->pages[page].bmp) / (float)atlas->pages[page].rows;
197
198 if (sx) {
199 (*sx) = (float)col * cw;
200 }
201 if (sy) {
202 (*sy) = (float)row * ch;
203 }
204 if (sw) {
205 (*sw) = cw;
206 }
207 if (sh) {
208 (*sh) = ch;
209 }
210 return TRUE;
211}
212
226int n_atlas_draw_cell(N_ATLAS* atlas, size_t page, size_t index, float x, float y, float size) {
227 float sx = 0.0, sy = 0.0, sw = 0.0, sh = 0.0;
228
229 __n_assert(size > 0.0, return FALSE);
230 if (!n_atlas_cell_rect(atlas, page, index, &sx, &sy, &sw, &sh)) {
231 return FALSE;
232 }
233 al_draw_scaled_bitmap(atlas->pages[page].bmp, sx, sy, sw, sh, x, y, size, size, 0);
234 return TRUE;
235}
static const char * row(N_GUI_TREE *tree, int index)
the text of a visible row, "" past the end
uint16_t cols
grid width in cells
Definition n_atlas.h:49
N_ATLAS_PAGE * pages
page array, npages entries
Definition n_atlas.h:57
ALLEGRO_BITMAP * bmp
the decoded page bitmap, NULL until set
Definition n_atlas.h:47
uint16_t rows
grid height in cells
Definition n_atlas.h:51
size_t npages
number of pages
Definition n_atlas.h:59
int n_atlas_max_bitmap_size(void)
get the largest bitmap dimension this display can hold
Definition n_atlas.c:43
int n_atlas_set_page(N_ATLAS *atlas, size_t page, const void *bytes, size_t len, const char *ext, uint16_t cols, uint16_t rows)
decode bytes into one atlas page
Definition n_atlas.c:112
int n_atlas_draw_cell(N_ATLAS *atlas, size_t page, size_t index, float x, float y, float size)
draw one cell as a size x size square
Definition n_atlas.c:226
void n_atlas_destroy(N_ATLAS **atlas)
destroy an atlas and every bitmap it owns
Definition n_atlas.c:75
int n_atlas_page_ready(const N_ATLAS *atlas, size_t page)
test whether a page holds a usable bitmap
Definition n_atlas.c:160
int n_atlas_cell_rect(const N_ATLAS *atlas, size_t page, size_t index, float *sx, float *sy, float *sw, float *sh)
compute the source rectangle of one cell
Definition n_atlas.c:183
N_ATLAS * new_n_atlas(size_t npages)
allocate an atlas holding npages empty pages
Definition n_atlas.c:54
a set of atlas pages addressed as (page, cell index)
Definition n_atlas.h:55
one atlas page: a bitmap holding cols*rows equally sized cells
Definition n_atlas.h:45
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:204
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:279
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:263
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_ERR
error conditions
Definition n_log.h:100
Multi-page sprite atlas: random-access cell blitting from a grid.