27 |
27 |
28 #include "ascension/ui/font.h" |
28 #include "ascension/ui/font.h" |
29 #include "ascension/context.h" |
29 #include "ascension/context.h" |
30 #include "ascension/error.h" |
30 #include "ascension/error.h" |
31 |
31 |
|
32 #include <assert.h> |
|
33 #include <cx/array_list.h> |
|
34 |
|
35 void asc_font(enum AscFontStyle style, int size) { |
|
36 asc_context.active_font.style = style; |
|
37 asc_context.active_font.size = size; |
|
38 } |
|
39 |
32 static char const *asc_font_filename(enum AscFontStyle style) { |
40 static char const *asc_font_filename(enum AscFontStyle style) { |
33 // TODO: do not assume we are running from the program dir |
41 // TODO: do not assume we are running from the program dir |
34 switch (style) { |
42 switch (style) { |
35 case ASC_FONT_REGULAR: |
43 case ASC_FONT_REGULAR: |
36 return "fonts/OpenSans-Regular.ttf"; |
44 return "fonts/OpenSans-Regular.ttf"; |
41 case ASC_FONT_BOLD_ITALIC: |
49 case ASC_FONT_BOLD_ITALIC: |
42 return "fonts/OpenSans-BoldItalic.ttf"; |
50 return "fonts/OpenSans-BoldItalic.ttf"; |
43 } |
51 } |
44 } |
52 } |
45 |
53 |
46 void asc_font(enum AscFontStyle style, int size) { |
54 struct asc_font_cache_entry { |
47 for (unsigned int i = 0 ; i < asc_context.fonts_loaded ; i++) { |
55 AscFont font; |
48 AscFont *font = &asc_context.fonts[i]; |
56 TTF_Font *ttf; |
49 if (font->size == size && font->style == style) { |
57 }; |
50 asc_context.active_font = i; |
58 |
51 return; |
59 static CxList *asc_font_cache; |
|
60 |
|
61 static void asc_font_unload(struct asc_font_cache_entry *entry) { |
|
62 TTF_CloseFont(entry->ttf); |
|
63 asc_dprintf("Closed font size %u, style %u", entry->font.size, entry->font.style); |
|
64 } |
|
65 |
|
66 void asc_font_cache_init(void) { |
|
67 assert(asc_font_cache == NULL); |
|
68 asc_font_cache = cxArrayListCreateSimple( |
|
69 sizeof(struct asc_font_cache_entry), 16 |
|
70 ); |
|
71 asc_font_cache->simple_destructor = (cx_destructor_func) asc_font_unload; |
|
72 } |
|
73 |
|
74 void asc_font_cache_destroy(void) { |
|
75 assert(asc_font_cache != NULL); |
|
76 cxListDestroy(asc_font_cache); |
|
77 } |
|
78 |
|
79 |
|
80 TTF_Font *asc_font_load(AscFont font) { |
|
81 CxIterator iter = cxListIterator(asc_font_cache); |
|
82 cx_foreach(struct asc_font_cache_entry*, cache, iter) { |
|
83 if (cache->font.style == font.style && cache->font.size == font.size) { |
|
84 return cache->ttf; |
52 } |
85 } |
53 } |
86 } |
54 |
87 |
55 if (asc_context.fonts_loaded == ASC_MAX_FONTS) { |
88 struct asc_font_cache_entry entry; |
56 asc_error("Too many fonts. Cannot load more until cache is repaired."); |
89 entry.font = font; |
57 asc_context.active_font = ASC_MAX_FONTS; |
90 entry.ttf = TTF_OpenFont(asc_font_filename(font.style), font.size); |
58 return; |
91 if (entry.ttf == NULL) { |
59 } |
|
60 |
|
61 unsigned int slot = asc_context.fonts_loaded++; |
|
62 AscFont *font = &asc_context.fonts[slot]; |
|
63 font->size = size; |
|
64 font->style = style; |
|
65 font->ptr = TTF_OpenFont(asc_font_filename(style), size); |
|
66 if (font->ptr == NULL) { |
|
67 asc_context.fonts_loaded--; |
|
68 asc_error(TTF_GetError()); |
92 asc_error(TTF_GetError()); |
|
93 return NULL; |
69 } else { |
94 } else { |
70 asc_dprintf("Loaded font size %u, style %u in slot %u", size, style, slot); |
95 cxListAdd(asc_font_cache, &entry); |
71 asc_context.active_font = slot; |
96 asc_dprintf("Loaded font size %d, style %d from disk", font.size, font.style); |
|
97 return entry.ttf; |
72 } |
98 } |
73 } |
99 } |