universe@11: /* universe@11: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. universe@11: * Copyright 2023 Mike Becker. All rights reserved. universe@11: * universe@11: * Redistribution and use in source and binary forms, with or without universe@11: * modification, are permitted provided that the following conditions are met: universe@11: * universe@11: * 1. Redistributions of source code must retain the above copyright universe@11: * notice, this list of conditions and the following disclaimer. universe@11: * universe@11: * 2. Redistributions in binary form must reproduce the above copyright universe@11: * notice, this list of conditions and the following disclaimer in the universe@11: * documentation and/or other materials provided with the distribution. universe@11: * universe@11: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" universe@11: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE universe@11: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE universe@11: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE universe@11: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR universe@11: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF universe@11: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS universe@11: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN universe@11: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) universe@11: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE universe@11: * POSSIBILITY OF SUCH DAMAGE. universe@11: */ universe@11: universe@48: #include "ascension/ui/font.h" universe@11: #include "ascension/context.h" universe@11: #include "ascension/error.h" universe@11: universe@66: #include universe@66: #include universe@66: universe@66: void asc_font(enum AscFontStyle style, int size) { universe@66: asc_context.active_font.style = style; universe@66: asc_context.active_font.size = size; universe@66: } universe@66: universe@11: static char const *asc_font_filename(enum AscFontStyle style) { universe@11: // TODO: do not assume we are running from the program dir universe@11: switch (style) { universe@11: case ASC_FONT_REGULAR: universe@11: return "fonts/OpenSans-Regular.ttf"; universe@11: case ASC_FONT_BOLD: universe@11: return "fonts/OpenSans-Bold.ttf"; universe@11: case ASC_FONT_ITALIC: universe@11: return "fonts/OpenSans-Italic.ttf"; universe@11: case ASC_FONT_BOLD_ITALIC: universe@11: return "fonts/OpenSans-BoldItalic.ttf"; universe@11: } universe@11: } universe@11: universe@66: struct asc_font_cache_entry { universe@66: AscFont font; universe@66: TTF_Font *ttf; universe@66: }; universe@66: universe@66: static CxList *asc_font_cache; universe@66: universe@66: static void asc_font_unload(struct asc_font_cache_entry *entry) { universe@66: TTF_CloseFont(entry->ttf); universe@66: asc_dprintf("Closed font size %u, style %u", entry->font.size, entry->font.style); universe@66: } universe@66: universe@66: void asc_font_cache_init(void) { universe@66: assert(asc_font_cache == NULL); universe@66: asc_font_cache = cxArrayListCreateSimple( universe@66: sizeof(struct asc_font_cache_entry), 16 universe@66: ); universe@66: asc_font_cache->simple_destructor = (cx_destructor_func) asc_font_unload; universe@66: } universe@66: universe@66: void asc_font_cache_destroy(void) { universe@66: assert(asc_font_cache != NULL); universe@66: cxListDestroy(asc_font_cache); universe@66: } universe@66: universe@66: universe@66: TTF_Font *asc_font_load(AscFont font) { universe@66: CxIterator iter = cxListIterator(asc_font_cache); universe@66: cx_foreach(struct asc_font_cache_entry*, cache, iter) { universe@66: if (cache->font.style == font.style && cache->font.size == font.size) { universe@66: return cache->ttf; universe@11: } universe@11: } universe@11: universe@66: struct asc_font_cache_entry entry; universe@66: entry.font = font; universe@66: entry.ttf = TTF_OpenFont(asc_font_filename(font.style), font.size); universe@66: if (entry.ttf == NULL) { universe@11: asc_error(TTF_GetError()); universe@66: return NULL; universe@65: } else { universe@66: cxListAdd(asc_font_cache, &entry); universe@66: asc_dprintf("Loaded font size %d, style %d from disk", font.size, font.style); universe@66: return entry.ttf; universe@11: } universe@11: }