123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dirent.h>
- #include <unistd.h>
- #include "hash.h"
- #include "texture.h"
- // for debugging
- #include "dumpImage.h"
- TextureAtlas* TextureAtlas_alloc() {
- TextureAtlas* ta;
- ta = calloc(1, sizeof(*ta));
-
- TextureAtlas_init(ta);
-
- return ta;
- }
- void TextureAtlas_init(TextureAtlas* ta) {
- VEC_INIT(&ta->sources);
- VEC_INIT(&ta->atlas);
- HT_init(&ta->items, 4);
- }
- void TextureAtlas_addPNG(TextureAtlas* ta, char* path) {
- BitmapRGBA8 bmp;
- TextureAtlasSource* src;
- int ret;
- char* name = "fixme";
-
- bmp.data = NULL;
- ret = readPNG2(path, &bmp);
- if(ret) {
- if(bmp.data) free(bmp.data);
- return;
- }
-
-
- src = calloc(1, sizeof(*src));
- src->name = strdup(name);
-
- src->size.x = bmp.width;
- src->size.y = bmp.height;
- src->aspectRatio = src->size.x / src->size.y;
- src->data = (void*)bmp.data;
-
- VEC_PUSH(&ta->sources, src);
- }
- // not the most efficient function. could use some optimization later.
- void TextureAtlas_addFolder(TextureAtlas* ta, char* prefix, char* dirPath, int recursive) {
- DIR* d;
- struct dirent *dir;
- char* path;
- int prefixlen = strlen(prefix);
-
- d = opendir(dirPath);
- if(!d) return;
-
- while(dir = readdir(d)) {
- if(0 == strncmp(dir->d_name, ".", 1)) continue;
- if(0 == strncmp(dir->d_name, "..", 2)) continue;
-
- path = pathJoin(dirPath, dir->d_name);
-
- if(dir->d_type == DT_REG) { // regular file
- int namelen;
- char* ext = pathExt2(dir->d_name, &namelen);
- char* name = malloc(namelen + prefixlen + 2);
- strcpy(name, prefix);
- strcat(name, "/");
- strncat(name, dir->d_name, namelen);
-
- if(streq(ext, "png")) {
- // printf("loading '%s' into atlas as '%s'\n", path, name);
- TextureAtlas_addPNG(ta, path);
- }
-
- free(name);
- }
- else if(recursive && dir->d_type == DT_DIR) {
- char* dirpre = pathJoin(prefix, dir->d_name);
-
- TextureAtlas_addFolder(ta, dirpre, path, 1);
- free(dirpre);
- }
-
- free(path);
- }
-
- closedir(d);
- }
- static void blit32(
- int src_x, int src_y, int dst_x, int dst_y, int w, int h,
- int src_w, int dst_w, uint32_t* src, uint32_t* dst) {
-
-
- int y, x, s, d;
-
- for(y = 0; y < h; y++) {
- for(x = 0; x < w; x++) {
- s = ((y + src_y) * src_w) + src_x + x;
- d = ((y + dst_y) * dst_w) + dst_x + x;
-
- dst[d] = src[s];
- }
- }
- }
- // sort tallest and widest first
- static int source_sort_comp(const void* aa, const void * bb) {
- TextureAtlasSource* a = *((TextureAtlasSource**)aa);
- TextureAtlasSource* b = *((TextureAtlasSource**)bb);
-
- if(a->size.y == b->size.y) {
- return b->size.x - a->size.x;
- }
- else {
- return b->size.y - a->size.y;
- }
- }
- void TextureAtlas_finalize(TextureAtlas* ta) {
- char buf[32]; // for debugging
-
- if(VEC_LEN(&ta->sources) == 0) {
- printf("Texture atlas finalized without any sources\n");
- return;
- }
-
- VEC_SORT(&ta->sources, source_sort_comp);
-
- int width = ta->width;
- int width2 = width * width;
- float fwidth = width;
-
- uint32_t* texData = malloc(sizeof(*texData) * width2);
- memset(texData, 0, sizeof(*texData) * width2);
-
-
- int row = 0;
- int hext = 0;
- int prevhext = VEC_ITEM(&ta->sources, 0)->size.y;
- int rowWidth = 0;
- VEC_EACH(&ta->sources, ind, src) {
-
- if(rowWidth + src->size.x > width) {
- row++;
- rowWidth = 0;
- hext += prevhext;
- prevhext = src->size.y;
-
- // next texture
- if(hext + prevhext > width) { // the texture is square; width == height
- VEC_PUSH(&ta->atlas, texData);
-
- // sprintf(buf, "texatlas-%d.png", VEC_LEN(&ta->atlas));
- // writePNG(buf, 4, texData, width, width);
- //
- texData = malloc(sizeof(*texData) * width2);
- memset(texData, 0, sizeof(*texData) * width2);
-
- hext = 0;
- }
- }
-
- // blit the sdf bitmap data
- blit32(
- 0, 0, // src x and y offset for the image
- rowWidth, hext, // dst offset
- src->size.x, src->size.y, // width and height
- src->size.x, width, // src and dst row widths
- (void*)src->data, // source
- texData); // destination
-
-
- TextureAtlasItem* it = calloc(1, sizeof(it));
- *it = (TextureAtlasItem){
- .offsetPx = {rowWidth, hext},
- .offsetNorm = {(float)rowWidth / fwidth, (float)hext / fwidth},
-
- .sizePx = src->size,
- .sizeNorm = {src->size.x / fwidth, src->size.y / fwidth},
-
- .index = VEC_LEN(&ta->atlas)
- };
-
- // printf("added icon '%s'\n", src->name);
- HT_set(&ta->items, strdup(src->name), it);
-
-
- rowWidth += src->size.x;
-
-
- // writePNG("sourceour.png", 4, src->data, src->size.x, src->size.y);
-
- free(src->name);
- free(src->data);
- free(src);
-
- // break;
- }
-
- // printf("last push %p\n", texData);
- VEC_PUSH(&ta->atlas, texData);
-
- // sprintf(buf, "texatlas-%d.png", VEC_LEN(&ta->atlas));
- // writePNG(buf, 4, texData, width, width);
- }
- // bump on format changes. there is no backward compatibility. saving is for caching only.
- static uint16_t TEXTURE_ATLAS_FILE_VERSION = 0;
- void TextureAtlas_saveAtlas(TextureAtlas* ta, char* path) {
-
- }
- int TextureAtlas_loadAtlas(TextureAtlas* ta, char* path) {
-
- }
|