This repository has been archived on 2022-05-21. You can view files and clone it, but cannot push or open issues or pull requests.
LEFTONE/util/glyphas/cache.c

112 lines
2.7 KiB
C
Raw Normal View History

#include "./cache.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <GL/glew.h>
#include "util/container/array.h"
#include "util/gleasy/atlas.h"
#include "util/memory/memory.h"
#include "./face.h"
struct glyphas_cache_t {
gleasy_atlas_t* atlas;
glyphas_face_t* face;
int32_t char_width;
int32_t char_height;
/* TODO(catfoot): linear search isn't efficient. :( */
CONTAINER_ARRAY glyphas_cache_glyph_t* items;
};
glyphas_cache_t* glyphas_cache_new(
gleasy_atlas_t* atlas,
glyphas_face_t* face,
int32_t char_width,
int32_t char_height) {
assert(atlas != NULL);
assert(face != NULL);
assert(char_width > 0);
assert(char_height > 0);
glyphas_cache_t* cache = memory_new(sizeof(*cache));
*cache = (typeof(*cache)) {
.atlas = atlas,
.face = face,
.char_width = char_width,
.char_height = char_height,
};
return cache;
}
void glyphas_cache_delete(glyphas_cache_t* cache) {
if (cache == NULL) return;
container_array_delete(cache->items);
memory_delete(cache);
}
const glyphas_cache_glyph_t* glyphas_cache_add_glyph(
glyphas_cache_t* cache, uint32_t unicode) {
assert(cache != NULL);
const glyphas_cache_glyph_t* found =
glyphas_cache_lookup_glyph(cache, unicode);
if (found != NULL) return found;
if (!glyphas_face_set_pixel_size(
cache->face, cache->char_width, cache->char_height)) {
return NULL;
}
if (!glyphas_face_render_glyph(cache->face, unicode)) {
return NULL;
}
gleasy_atlas_geometry_t geo = {0};
const glyphas_glyph_t* rendered = &cache->face->glyph;
if (rendered->bitmap.width > 0) {
const gleasy_atlas_bitmap_t bmp = {
.width = rendered->bitmap.width,
.height = rendered->bitmap.height,
.buffer = rendered->bitmap.buffer,
.format = GL_RED,
.type = GL_UNSIGNED_BYTE,
};
if (!gleasy_atlas_add(cache->atlas, &geo, &bmp)) {
return NULL;
}
}
const size_t index = container_array_get_length(cache->items);
container_array_insert(cache->items, index);
glyphas_cache_glyph_t* g = &cache->items[index];
*g = (typeof(*g)) {
.unicode = unicode,
.width = rendered->bitmap.width,
.height = rendered->bitmap.height,
.geometry = geo,
.hmetrics = rendered->hmetrics,
.vmetrics = rendered->vmetrics,
};
return g;
}
const glyphas_cache_glyph_t* glyphas_cache_lookup_glyph(
const glyphas_cache_t* cache, uint32_t unicode) {
assert(cache != NULL);
const size_t len = container_array_get_length(cache->items);
for (size_t i = 0; i < len; ++i) {
const glyphas_cache_glyph_t* g = &cache->items[i];
if (g->unicode == unicode) return g;
}
return NULL;
}