ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
Font.c File Reference
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Objectively/Hash.h>
#include <Objectively/Array.h>
#include <Objectively/String.h>
#include "Font.h"
#include "Log.h"
#include "View.h"
#include "Window.h"
#include "../Assets/coda.ttf.h"

Go to the source code of this file.

Macros

#define _Class   _Font
 

Functions

Class * _Font (void)
 
static FontcachedFont (const char *family, int size, int style)
 
static void cacheFont (Data *data, const char *family)
 
static void clearCache (void)
 
static void dealloc (Object *self)
 
static FontdefaultFont (void)
 
static void destroy (Class *clazz)
 
static int hash (const Object *self)
 
static void initialize (Class *clazz)
 
static FontinitWithData (Font *self, Data *data, const char *family, int size, int style)
 
static bool isEqual (const Object *self, const Object *other)
 
static SDL_Surface * renderCharacters (const Font *self, const char *chars, SDL_Color color, int wrapWidth)
 
static void renderDeviceDidReset (Font *self)
 
static void sizeCharacters (const Font *self, const char *chars, int *w, int *h)
 

Variables

static Dictionary * _cache
 
static Array * _fonts
 
const EnumName FontStyleNames []
 

Macro Definition Documentation

◆ _Class

#define _Class   _Font

Definition at line 49 of file Font.c.

Function Documentation

◆ _Font()

Class * _Font ( void  )

Definition at line 365 of file Font.c.

365 {
366 static Class *clazz;
367 static Once once;
368
369 do_once(&once, {
370 clazz = _initialize(&(const ClassDef) {
371 .name = "Font",
372 .superclass = _Object(),
373 .instanceSize = sizeof(Font),
374 .interfaceOffset = offsetof(Font, interface),
375 .interfaceSize = sizeof(FontInterface),
377 .destroy = destroy,
378 });
379 });
380
381 return clazz;
382}
static void destroy(Class *clazz)
Definition Font.c:353
static void initialize(Class *clazz)
Definition Font.c:324
TrueType fonts.
Definition Font.h:63

◆ cachedFont()

static Font * cachedFont ( const char *  family,
int  size,
int  style 
)
static

Definition at line 127 of file Font.c.

127 {
128
129 if (family == NULL) {
130 family = DEFAULT_FONT_FAMILY;
131 }
132 if (size < 1) {
134 }
135 if (style < FontStyleRegular || style > FontStyleStrikeThrough) {
136 style = DEFAULT_FONT_STYLE;
137 }
138
139 const Array *fonts = (Array *) _fonts;
140 for (size_t i = 0; i < fonts->count; i++) {
141
142 Font *font = $(fonts, objectAtIndex, i);
143
144 if (!strcmp(font->family, family) &&
145 font->size == size &&
146 font->style == style) {
147 return font;
148 }
149 }
150
151 Data *data = $((Dictionary *) _cache, objectForKeyPath, family);
152 if (data) {
153 Font *font = $(alloc(Font), initWithData, data, family, size, style);
154 assert(font);
155
156 $(_fonts, addObject, font);
157 release(font);
158
159 return font;
160 }
161
162 MVC_LogWarn("%s-%d-%d not found\n", family, size, style);
163 return $$(Font, defaultFont);
164}
static Font * initWithData(Font *self, Data *data, const char *family, int size, int style)
Definition Font.c:197
static Dictionary * _cache
Definition Font.c:112
static Array * _fonts
Definition Font.c:113
static Font * defaultFont(void)
Definition Font.c:178
#define DEFAULT_FONT_STYLE
Definition Font.h:36
@ FontStyleStrikeThrough
Definition Font.h:51
#define DEFAULT_FONT_FAMILY
Definition Font.h:34
#define DEFAULT_FONT_SIZE
Definition Font.h:35
static SDL_Size size(const Image *self)
Definition Image.c:181
#define MVC_LogWarn(fmt,...)
Definition Log.h:54
char * family
The family name.
Definition Font.h:84
int size
The point size.
Definition Font.h:105
int style
The style.
Definition Font.h:110

◆ cacheFont()

static void cacheFont ( Data *  data,
const char *  family 
)
static

Definition at line 119 of file Font.c.

119 {
120 $(_cache, setObjectForKeyPath, data, family);
121}

◆ clearCache()

static void clearCache ( void  )
static

Definition at line 170 of file Font.c.

170 {
171 $(_cache, removeAllObjects);
172}

◆ dealloc()

static void dealloc ( Object *  self)
static
See also
Object::dealloc(Object *)

Definition at line 56 of file Font.c.

56 {
57
58 Font *this = (Font *) self;
59
60 free(this->family);
61
62 release(this->data);
63
64 TTF_CloseFont(this->font);
65
66 super(Object, self, dealloc);
67}
static void dealloc(Object *self)
Definition Font.c:56

◆ defaultFont()

static Font * defaultFont ( void  )
static

Definition at line 178 of file Font.c.

178 {
179 static Once once;
180
181 do_once(&once, {
182 Data *data = $(alloc(Data), initWithConstMemory, coda_ttf, coda_ttf_len - 1);
183 assert(data);
184
186
187 release(data);
188 });
189
191}
static Font * cachedFont(const char *family, int size, int style)
Definition Font.c:127
static void cacheFont(Data *data, const char *family)
Definition Font.c:119

◆ destroy()

static void destroy ( Class *  clazz)
static
See also
Class::destroy(Class *)

Definition at line 353 of file Font.c.

353 {
354
355 release(_cache);
356 release(_fonts);
357
358 TTF_Quit();
359}

◆ hash()

static int hash ( const Object *  self)
static
See also
Object::hash(const Object *)

Definition at line 72 of file Font.c.

72 {
73
74 Font *this = (Font *) self;
75
76 int hash = HASH_SEED;
77 hash = HashForCString(hash, this->family);
78 hash = HashForInteger(hash, this->size);
79 hash = HashForInteger(hash, this->style);
80 hash = HashForInteger(hash, this->renderSize);
81
82 return hash;
83}
static int hash(const Object *self)
Definition Font.c:72

◆ initialize()

static void initialize ( Class *  clazz)
static
See also
Class::initialize(Class *)

Definition at line 324 of file Font.c.

324 {
325
326 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
327 ((ObjectInterface *) clazz->interface)->hash = hash;
328 ((ObjectInterface *) clazz->interface)->isEqual = isEqual;
329
330 ((FontInterface *) clazz->interface)->cachedFont = cachedFont;
331 ((FontInterface *) clazz->interface)->cacheFont = cacheFont;
332 ((FontInterface *) clazz->interface)->clearCache = clearCache;
333 ((FontInterface *) clazz->interface)->defaultFont = defaultFont;
334 ((FontInterface *) clazz->interface)->initWithData = initWithData;
335 ((FontInterface *) clazz->interface)->renderCharacters = renderCharacters;
336 ((FontInterface *) clazz->interface)->renderDeviceDidReset = renderDeviceDidReset;
337 ((FontInterface *) clazz->interface)->sizeCharacters = sizeCharacters;
338
339 const bool init = TTF_Init();
340 assert(init);
341 (void) init;
342
343 _cache = $$(Dictionary, dictionary);
344 assert(_cache);
345
346 _fonts = $$(Array, array);
347 assert(_fonts);
348}
static View * init(View *self)
Definition Box.c:67
static void sizeCharacters(const Font *self, const char *chars, int *w, int *h)
Definition Font.c:274
static SDL_Surface * renderCharacters(const Font *self, const char *chars, SDL_Color color, int wrapWidth)
Definition Font.c:224
static void clearCache(void)
Definition Font.c:170
static bool isEqual(const Object *self, const Object *other)
Definition Font.c:88
static void renderDeviceDidReset(Font *self)
Definition Font.c:248
void(* cacheFont)(Data *data, const char *family)
Caches the specified font Data.
Definition Font.h:142
void renderCharacters(const Font *self, const char *chars, SDL_Color color, int wrapWidth)
Renders the given characters in this Font.
Definition Font.c:224
Font * initWithData(Font *self, Data *data, int size, int index)

◆ initWithData()

static Font * initWithData ( Font self,
Data *  data,
const char *  family,
int  size,
int  style 
)
static

Definition at line 197 of file Font.c.

197 {
198
199 self = (Font *) super(Object, self, init);
200 if (self) {
201
202 self->data = retain(data);
203 assert(self->data);
204
205 self->family = strdup(family);
206 assert(self->family);
207
208 self->size = size;
209 assert(self->size);
210
211 self->style = style;
212 self->scale = 1.0f;
213
214 $(self, renderDeviceDidReset);
215 }
216
217 return self;
218}
float scale
The display pixel density scale (e.g. 2.0 on Retina). Updated by callers via the scale field before i...
Definition Font.h:100
Data * data
The raw font data.
Definition Font.h:79

◆ isEqual()

static bool isEqual ( const Object *  self,
const Object *  other 
)
static
See also
Object::isEqual(const Object *, const Object *)

Definition at line 88 of file Font.c.

88 {
89
90 if (super(Object, self, isEqual, other)) {
91 return true;
92 }
93
94 if (other && $(other, isKindOfClass, _Font())) {
95
96 const Font *this = (Font *) self;
97 const Font *that = (Font *) other;
98
99 if (!strcmp(this->family, that->family) &&
100 this->size == that->size &&
101 this->style == that->style &&
102 this->renderSize == that->renderSize) {
103 return true;
104 }
105 }
106
107 return false;
108}
Class * _Font(void)
Definition Font.c:365
int renderSize
The render size, adjusted for display density.
Definition Font.h:94

◆ renderCharacters()

static SDL_Surface * renderCharacters ( const Font self,
const char *  chars,
SDL_Color  color,
int  wrapWidth 
)
static

Definition at line 224 of file Font.c.

224 {
225
226 SDL_Surface *surface;
227 if (wrapWidth) {
228 surface = TTF_RenderText_Blended_Wrapped(self->font, chars, 0, color, wrapWidth * self->scale);
229 } else {
230 surface = TTF_RenderText_Blended(self->font, chars, 0, color);
231 }
232
233 SDL_Surface *converted = NULL;
234 if (surface) {
235 converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32);
236 SDL_DestroySurface(surface);
237 } else {
238 MVC_LogError("%s\n", SDL_GetError());
239 }
240
241 return converted;
242}
#define MVC_LogError(fmt,...)
Definition Log.h:57
TTF_Font * font
The backing font.
Definition Font.h:89

◆ renderDeviceDidReset()

static void renderDeviceDidReset ( Font self)
static

Definition at line 248 of file Font.c.

248 {
249
250 const int renderSize = self->size * self->scale;
251 if (renderSize != self->renderSize) {
252
253 self->renderSize = renderSize;
254
255 if (self->font) {
256 TTF_CloseFont(self->font);
257 }
258
259 SDL_IOStream *buffer = SDL_IOFromConstMem(self->data->bytes, (int) self->data->length);
260 assert(buffer);
261
262 self->font = TTF_OpenFontIO(buffer, 1, self->renderSize);
263 assert(self->font);
264
265 TTF_SetFontStyle(self->font, self->style);
266 TTF_SetFontHinting(self->font, TTF_HINTING_LIGHT_SUBPIXEL);
267 }
268}

◆ sizeCharacters()

static void sizeCharacters ( const Font self,
const char *  chars,
int *  w,
int *  h 
)
static

Definition at line 274 of file Font.c.

274 {
275
276 if (w) {
277 *w = 0;
278 }
279 if (h) {
280 *h = 0;
281 }
282
283 if (chars) {
284 char *lines = strdup(chars);
285
286 const int font_h = TTF_GetFontHeight(self->font);
287
288 for (char *line = strtok(lines, "\n\r"); line; line = strtok(NULL, "\n\r")) {
289
290 if (w) {
291
292 // A little ghetto whitespace padding to ensure TTF doesn't truncate words 🫠
293
294 const size_t len = strlen(line) + 2;
295 char buf[len];
296
297 snprintf(buf, len, "%s ", line);
298
299 int line_w;
300
301 TTF_GetStringSize(self->font, buf, 0, &line_w, NULL);
302 *w = max(*w, line_w);
303 }
304 if (h) {
305 *h += font_h;
306 }
307 }
308 free(lines);
309
310 if (w) {
311 *w = ceilf(*w / self->scale);
312 }
313 if (h) {
314 *h = ceilf(*h / self->scale);
315 }
316 }
317}

Variable Documentation

◆ _cache

Dictionary* _cache
static

Definition at line 112 of file Font.c.

◆ _fonts

Array* _fonts
static

Definition at line 113 of file Font.c.

◆ FontStyleNames

const EnumName FontStyleNames[]
Initial value:
= MakeEnumNames(
MakeEnumAlias(FontStyleRegular, regular),
MakeEnumAlias(FontStyleBold, bold),
MakeEnumAlias(FontStyleItalic, italic),
MakeEnumAlias(FontStyleUnderline, underline),
MakeEnumAlias(FontStyleStrikeThrough, strikethrough)
)
@ FontStyleUnderline
Definition Font.h:50
@ FontStyleBold
Definition Font.h:48
@ FontStyleRegular
Definition Font.h:47
@ FontStyleItalic
Definition Font.h:49

Definition at line 41 of file Font.c.