Tue, 07 Nov 2023 21:24:06 +0100
add font management
fonts/OFL.txt | file | annotate | diff | comparison | revisions | |
fonts/OpenSans-Bold.ttf | file | annotate | diff | comparison | revisions | |
fonts/OpenSans-BoldItalic.ttf | file | annotate | diff | comparison | revisions | |
fonts/OpenSans-Italic.ttf | file | annotate | diff | comparison | revisions | |
fonts/OpenSans-Regular.ttf | file | annotate | diff | comparison | revisions | |
src/Makefile | file | annotate | diff | comparison | revisions | |
src/ascension/context.h | file | annotate | diff | comparison | revisions | |
src/ascension/font.h | file | annotate | diff | comparison | revisions | |
src/context.c | file | annotate | diff | comparison | revisions | |
src/font.c | file | annotate | diff | comparison | revisions | |
test/Makefile | file | annotate | diff | comparison | revisions |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/fonts/OFL.txt Tue Nov 07 21:24:06 2023 +0100 1.3 @@ -0,0 +1,93 @@ 1.4 +Copyright 2020 The Open Sans Project Authors (https://github.com/googlefonts/opensans) 1.5 + 1.6 +This Font Software is licensed under the SIL Open Font License, Version 1.1. 1.7 +This license is copied below, and is also available with a FAQ at: 1.8 +http://scripts.sil.org/OFL 1.9 + 1.10 + 1.11 +----------------------------------------------------------- 1.12 +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 1.13 +----------------------------------------------------------- 1.14 + 1.15 +PREAMBLE 1.16 +The goals of the Open Font License (OFL) are to stimulate worldwide 1.17 +development of collaborative font projects, to support the font creation 1.18 +efforts of academic and linguistic communities, and to provide a free and 1.19 +open framework in which fonts may be shared and improved in partnership 1.20 +with others. 1.21 + 1.22 +The OFL allows the licensed fonts to be used, studied, modified and 1.23 +redistributed freely as long as they are not sold by themselves. The 1.24 +fonts, including any derivative works, can be bundled, embedded, 1.25 +redistributed and/or sold with any software provided that any reserved 1.26 +names are not used by derivative works. The fonts and derivatives, 1.27 +however, cannot be released under any other type of license. The 1.28 +requirement for fonts to remain under this license does not apply 1.29 +to any document created using the fonts or their derivatives. 1.30 + 1.31 +DEFINITIONS 1.32 +"Font Software" refers to the set of files released by the Copyright 1.33 +Holder(s) under this license and clearly marked as such. This may 1.34 +include source files, build scripts and documentation. 1.35 + 1.36 +"Reserved Font Name" refers to any names specified as such after the 1.37 +copyright statement(s). 1.38 + 1.39 +"Original Version" refers to the collection of Font Software components as 1.40 +distributed by the Copyright Holder(s). 1.41 + 1.42 +"Modified Version" refers to any derivative made by adding to, deleting, 1.43 +or substituting -- in part or in whole -- any of the components of the 1.44 +Original Version, by changing formats or by porting the Font Software to a 1.45 +new environment. 1.46 + 1.47 +"Author" refers to any designer, engineer, programmer, technical 1.48 +writer or other person who contributed to the Font Software. 1.49 + 1.50 +PERMISSION & CONDITIONS 1.51 +Permission is hereby granted, free of charge, to any person obtaining 1.52 +a copy of the Font Software, to use, study, copy, merge, embed, modify, 1.53 +redistribute, and sell modified and unmodified copies of the Font 1.54 +Software, subject to the following conditions: 1.55 + 1.56 +1) Neither the Font Software nor any of its individual components, 1.57 +in Original or Modified Versions, may be sold by itself. 1.58 + 1.59 +2) Original or Modified Versions of the Font Software may be bundled, 1.60 +redistributed and/or sold with any software, provided that each copy 1.61 +contains the above copyright notice and this license. These can be 1.62 +included either as stand-alone text files, human-readable headers or 1.63 +in the appropriate machine-readable metadata fields within text or 1.64 +binary files as long as those fields can be easily viewed by the user. 1.65 + 1.66 +3) No Modified Version of the Font Software may use the Reserved Font 1.67 +Name(s) unless explicit written permission is granted by the corresponding 1.68 +Copyright Holder. This restriction only applies to the primary font name as 1.69 +presented to the users. 1.70 + 1.71 +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 1.72 +Software shall not be used to promote, endorse or advertise any 1.73 +Modified Version, except to acknowledge the contribution(s) of the 1.74 +Copyright Holder(s) and the Author(s) or with their explicit written 1.75 +permission. 1.76 + 1.77 +5) The Font Software, modified or unmodified, in part or in whole, 1.78 +must be distributed entirely under this license, and must not be 1.79 +distributed under any other license. The requirement for fonts to 1.80 +remain under this license does not apply to any document created 1.81 +using the Font Software. 1.82 + 1.83 +TERMINATION 1.84 +This license becomes null and void if any of the above conditions are 1.85 +not met. 1.86 + 1.87 +DISCLAIMER 1.88 +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1.89 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 1.90 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 1.91 +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 1.92 +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 1.93 +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 1.94 +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1.95 +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 1.96 +OTHER DEALINGS IN THE FONT SOFTWARE.
2.1 Binary file fonts/OpenSans-Bold.ttf has changed
3.1 Binary file fonts/OpenSans-BoldItalic.ttf has changed
4.1 Binary file fonts/OpenSans-Italic.ttf has changed
5.1 Binary file fonts/OpenSans-Regular.ttf has changed
6.1 --- a/src/Makefile Tue Nov 07 21:13:04 2023 +0100 6.2 +++ b/src/Makefile Tue Nov 07 21:24:06 2023 +0100 6.3 @@ -27,7 +27,7 @@ 6.4 6.5 BUILD_DIR=../build/lib 6.6 6.7 -SRC = context.c error.c window.c 6.8 +SRC = context.c error.c window.c font.c 6.9 6.10 OBJ = $(SRC:%.c=$(BUILD_DIR)/%.o) 6.11 6.12 @@ -41,17 +41,26 @@ 6.13 FORCE: 6.14 6.15 $(BUILD_DIR)/context.o: context.c ascension/context.h ascension/window.h \ 6.16 - ascension/datatypes.h ascension/utils.h 6.17 + ascension/datatypes.h ascension/font.h ascension/error.h \ 6.18 + ascension/utils.h 6.19 @echo "Compiling $<" 6.20 $(CC) -o $@ $(CFLAGS) -c $< 6.21 6.22 $(BUILD_DIR)/error.o: error.c ascension/context.h ascension/window.h \ 6.23 - ascension/datatypes.h ascension/error.h ascension/utils.h 6.24 + ascension/datatypes.h ascension/font.h ascension/error.h \ 6.25 + ascension/utils.h 6.26 + @echo "Compiling $<" 6.27 + $(CC) -o $@ $(CFLAGS) -c $< 6.28 + 6.29 +$(BUILD_DIR)/font.o: font.c ascension/font.h ascension/context.h \ 6.30 + ascension/window.h ascension/datatypes.h ascension/font.h \ 6.31 + ascension/error.h 6.32 @echo "Compiling $<" 6.33 $(CC) -o $@ $(CFLAGS) -c $< 6.34 6.35 $(BUILD_DIR)/window.o: window.c ascension/window.h ascension/datatypes.h \ 6.36 - ascension/context.h ascension/window.h ascension/error.h 6.37 + ascension/context.h ascension/window.h ascension/font.h \ 6.38 + ascension/error.h ascension/utils.h 6.39 @echo "Compiling $<" 6.40 $(CC) -o $@ $(CFLAGS) -c $< 6.41
7.1 --- a/src/ascension/context.h Tue Nov 07 21:13:04 2023 +0100 7.2 +++ b/src/ascension/context.h Tue Nov 07 21:24:06 2023 +0100 7.3 @@ -29,6 +29,7 @@ 7.4 #define ASCENSION_CONTEXT_H 7.5 7.6 #include "window.h" 7.7 +#include "font.h" 7.8 7.9 #include <cx/buffer.h> 7.10 #include <cx/list.h> 7.11 @@ -53,6 +54,8 @@ 7.12 unsigned int flags; 7.13 CxBuffer error_buffer; 7.14 AscWindow windows[ASC_MAX_WINDOWS]; 7.15 + AscFont fonts[ASC_MAX_FONTS]; 7.16 + unsigned int fonts_loaded; 7.17 } AscContext; 7.18 7.19 /** Global ascension context. */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/ascension/font.h Tue Nov 07 21:24:06 2023 +0100 8.3 @@ -0,0 +1,102 @@ 8.4 +/* 8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 8.6 + * Copyright 2023 Mike Becker. All rights reserved. 8.7 + * 8.8 + * Redistribution and use in source and binary forms, with or without 8.9 + * modification, are permitted provided that the following conditions are met: 8.10 + * 8.11 + * 1. Redistributions of source code must retain the above copyright 8.12 + * notice, this list of conditions and the following disclaimer. 8.13 + * 8.14 + * 2. Redistributions in binary form must reproduce the above copyright 8.15 + * notice, this list of conditions and the following disclaimer in the 8.16 + * documentation and/or other materials provided with the distribution. 8.17 + * 8.18 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 8.19 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 8.20 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 8.21 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 8.22 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 8.23 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 8.24 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8.25 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 8.26 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 8.27 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 8.28 + * POSSIBILITY OF SUCH DAMAGE. 8.29 + */ 8.30 + 8.31 +#ifndef ASCENSION_FONT_H 8.32 +#define ASCENSION_FONT_H 8.33 + 8.34 +#include <SDL2/SDL_ttf.h> 8.35 + 8.36 +#ifndef ASC_MAX_FONTS 8.37 +/** The maximum number of style/size combinations that can be loaded in parallel. */ 8.38 +#define ASC_MAX_FONTS 64u 8.39 +#endif // ASC_MAX_FONTS 8.40 + 8.41 +#ifdef __cplusplus 8.42 +extern "C" { 8.43 +#endif 8.44 + 8.45 +enum AscFontStyle { 8.46 + ASC_FONT_REGULAR, 8.47 + ASC_FONT_BOLD, 8.48 + ASC_FONT_ITALIC, 8.49 + ASC_FONT_BOLD_ITALIC, 8.50 +}; 8.51 + 8.52 +typedef struct AscFont { 8.53 + /** 8.54 + * Style of the font. 8.55 + */ 8.56 + enum AscFontStyle style; 8.57 + /** 8.58 + * Point size. 8.59 + */ 8.60 + int size; 8.61 + /** 8.62 + * Pointer to the SDL TTF font structure. 8.63 + */ 8.64 + TTF_Font *ptr; 8.65 +} AscFont; 8.66 + 8.67 +/** 8.68 + * Loads a font with the given style and size. 8.69 + * 8.70 + * The font is cached and returned faster the next time you call this 8.71 + * function with the same arguments. However, when you reach the maximum 8.72 + * number of fonts, the cache is completely cleared and rebuilt. 8.73 + * 8.74 + * That means in general, that you should not be using too many fonts of 8.75 + * different sizes at the same time, and you should not keep the pointer 8.76 + * returned by this function too long, because you would risking cache misses. 8.77 + * 8.78 + * @param style the style 8.79 + * @param size the point size 8.80 + * @return a pointer to the font structure (do not free) 8.81 + */ 8.82 +AscFont const *asc_font(enum AscFontStyle style, int size); 8.83 + 8.84 +/** 8.85 + * Unloads all cached fonts from the context. 8.86 + */ 8.87 +void asc_font_cache_clear(void); 8.88 + 8.89 +/** 8.90 + * Checks, if the font is still loaded and reloads it, if required. 8.91 + * 8.92 + * There is no need to call this function manually. Every Ascension function 8.93 + * that you pass a font will do that for you and use the returned pointer in 8.94 + * case of a cache miss. 8.95 + * 8.96 + * @param font the font to validate 8.97 + * @return \p font, or a pointer to the new location of the loaded font 8.98 + */ 8.99 +AscFont const *asc_font_cache_validate(AscFont const *font); 8.100 + 8.101 +#ifdef __cplusplus 8.102 +} // extern "C" 8.103 +#endif 8.104 + 8.105 +#endif //ASCENSION_FONT_H
9.1 --- a/src/context.c Tue Nov 07 21:13:04 2023 +0100 9.2 +++ b/src/context.c Tue Nov 07 21:24:06 2023 +0100 9.3 @@ -39,7 +39,7 @@ 9.4 void asc_context_initialize(void) { 9.5 if (asc_test_flag(asc_context.flags, ASC_FLAG_INITILIZED)) 9.6 return; 9.7 - asc_clear_flag(&asc_context.flags, ASC_FLAG_HAS_ERROR); 9.8 + memset(&asc_context, 0, sizeof(AscContext)); 9.9 9.10 // initialize error buffer 9.11 cxBufferInit( 9.12 @@ -50,9 +50,6 @@ 9.13 CX_BUFFER_AUTO_EXTEND 9.14 ); 9.15 9.16 - // initialize data 9.17 - memset(asc_context.windows, 0, sizeof (asc_context.windows)); 9.18 - 9.19 // initialize SDL 9.20 if (SDL_Init(SDL_INIT_VIDEO) < 0) { 9.21 asc_error(SDL_GetError()); 9.22 @@ -71,6 +68,7 @@ 9.23 for (unsigned int i = 0 ; i < ASC_MAX_WINDOWS ; i++) { 9.24 asc_window_destroy(&asc_context.windows[i]); 9.25 } 9.26 + asc_font_cache_clear(); 9.27 9.28 // quit SDL 9.29 if (TTF_WasInit())
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/font.c Tue Nov 07 21:24:06 2023 +0100 10.3 @@ -0,0 +1,90 @@ 10.4 +/* 10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 10.6 + * Copyright 2023 Mike Becker. All rights reserved. 10.7 + * 10.8 + * Redistribution and use in source and binary forms, with or without 10.9 + * modification, are permitted provided that the following conditions are met: 10.10 + * 10.11 + * 1. Redistributions of source code must retain the above copyright 10.12 + * notice, this list of conditions and the following disclaimer. 10.13 + * 10.14 + * 2. Redistributions in binary form must reproduce the above copyright 10.15 + * notice, this list of conditions and the following disclaimer in the 10.16 + * documentation and/or other materials provided with the distribution. 10.17 + * 10.18 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 10.19 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10.20 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 10.21 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 10.22 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 10.23 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 10.24 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 10.25 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 10.26 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10.27 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 10.28 + * POSSIBILITY OF SUCH DAMAGE. 10.29 + */ 10.30 + 10.31 +#include "ascension/font.h" 10.32 +#include "ascension/context.h" 10.33 +#include "ascension/error.h" 10.34 + 10.35 +static char const *asc_font_filename(enum AscFontStyle style) { 10.36 + // TODO: do not assume we are running from the program dir 10.37 + switch (style) { 10.38 + case ASC_FONT_REGULAR: 10.39 + return "fonts/OpenSans-Regular.ttf"; 10.40 + case ASC_FONT_BOLD: 10.41 + return "fonts/OpenSans-Bold.ttf"; 10.42 + case ASC_FONT_ITALIC: 10.43 + return "fonts/OpenSans-Italic.ttf"; 10.44 + case ASC_FONT_BOLD_ITALIC: 10.45 + return "fonts/OpenSans-BoldItalic.ttf"; 10.46 + } 10.47 +} 10.48 + 10.49 +AscFont const *asc_font(enum AscFontStyle style, int size) { 10.50 + for (unsigned int i = 0 ; i < asc_context.fonts_loaded ; i++) { 10.51 + AscFont *font = &asc_context.fonts[i]; 10.52 + if (font->size == size && font->style == style) { 10.53 + return font; 10.54 + } 10.55 + } 10.56 + 10.57 + if (asc_context.fonts_loaded == ASC_MAX_FONTS) { 10.58 + asc_dprintf("WARNING: Maximum number of fonts reached, wiping cache!"); 10.59 + asc_font_cache_clear(); 10.60 + } 10.61 + 10.62 + unsigned int slot = asc_context.fonts_loaded++; 10.63 + AscFont *font = &asc_context.fonts[slot]; 10.64 + font->size = size; 10.65 + font->style = style; 10.66 + font->ptr = TTF_OpenFont(asc_font_filename(style), size); 10.67 + if (font->ptr == NULL) { 10.68 + asc_context.fonts_loaded--; 10.69 + asc_error(TTF_GetError()); 10.70 + return NULL; 10.71 + } 10.72 + asc_dprintf("Loaded font size %u, style %u in slot %u", size, style, slot); 10.73 + return font; 10.74 +} 10.75 + 10.76 +void asc_font_cache_clear(void) { 10.77 + asc_dprintf("Fonts in cache that are being unloaded: %u", asc_context.fonts_loaded); 10.78 + while (asc_context.fonts_loaded > 0) { 10.79 + unsigned int i = --asc_context.fonts_loaded; 10.80 + AscFont *font = &asc_context.fonts[i]; 10.81 + TTF_CloseFont(font->ptr); 10.82 + font->ptr = NULL; 10.83 + } 10.84 +} 10.85 + 10.86 +AscFont const *asc_font_cache_validate(AscFont const *font) { 10.87 + if (font->ptr) { 10.88 + return font; 10.89 + } else { 10.90 + asc_dprintf("Cache miss for font size %u, style %u", font->size, font->style); 10.91 + return asc_font(font->style, font->size); 10.92 + } 10.93 +}
11.1 --- a/test/Makefile Tue Nov 07 21:13:04 2023 +0100 11.2 +++ b/test/Makefile Tue Nov 07 21:24:06 2023 +0100 11.3 @@ -40,7 +40,8 @@ 11.4 11.5 $(BUILD_DIR)/sandbox.o: sandbox.c ../src/ascension/ascension.h \ 11.6 ../src/ascension/context.h ../src/ascension/window.h \ 11.7 - ../src/ascension/datatypes.h ../src/ascension/error.h 11.8 + ../src/ascension/datatypes.h ../src/ascension/font.h \ 11.9 + ../src/ascension/error.h 11.10 @echo "Compiling $<" 11.11 $(CC) -o $@ $(CFLAGS) -c $< 11.12