ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
Font Struct Reference

TrueType fonts. More...

#include <Font.h>

Inheritance diagram for Font:

Public Member Functions

Class * _Font (void)
 The Font archetype.
 
void cacheFont (Data *data, const char *family)
 
void clearCache (void)
 Clears the Font cache.
 
Font * defaultFont (void)
 
Font * defaultMonospaceFont (void)
 
Font * fontWithAttributes (const FontAttributes *attributes, float pixelDensity)
 Resolves a new Font with the given attributes from the cached font Data.
 
Font * fontWithName (const char *name, float pixelDensity)
 Resolves a Font from a name in the format produced by Font::name.
 
Font * initWithData (Font *self, Data *data, const FontAttributes *attributes, float pixelDensity)
 Initializes this Font with the given TTF Data and attributes.
 
String * name (const Font *self)
 
String * nameWithAttributes (const FontAttributes *attributes)
 
void renderBitmapCharacters (Font *self, const Renderer *renderer, const char *chars, SDL_Color color, int wrapWidth, const SDL_Point *origin, const ImageAtlas *icons)
 Records one quad per glyph of the given characters from this Font's bitmap.
 
void renderCharacters (const Font *self, const char *chars, SDL_Color color, int wrapWidth)
 Renders the given characters in this Font.
 
void renderDeviceWillReset (Font *self)
 Releases this Font's bitmap Texture, if any, ahead of a render device reset. It is recreated on the next draw.
 
void sizeBitmapCharacters (const Font *self, const char *chars, int wrapWidth, const ImageAtlas *icons, int *w, int *h)
 Measures the given characters against this Font's bitmap.
 
void sizeCharacters (const Font *self, const char *chars, int *w, int *h)
 Measures the given characters in this Font.
 

Data Fields

FontBitmap bitmap
 The glyphs of a fixed-width Font, baked into one sheet; bitmap.surface is NULL for a proportional Font.
 
Data * data
 The raw font data.
 
char * family
 The family name.
 
TTF_Font * font
 The backing font.
 
Object object
 The superclass.
 
float pixelDensity
 The display pixel density scale, greater than 1.0 on high-density displays.
 
int renderSize
 The render size, adjusted for pixel density.
 
int size
 The point size.
 
int style
 The style.
 

Static Public Attributes

void(* cacheFont )(Data *data, const char *family)
 Caches the specified font Data.
 

Protected Attributes

FontInterface * interface [0]
 The interface type.
 

Detailed Description

TrueType fonts.

Definition at line 88 of file Font.h.

Member Function Documentation

◆ _Font()

Class * _Font ( void  )

The Font archetype.

Returns
The Font Class.

Definition at line 464 of file Font.c.

464 {
465 static Class *clazz;
466 static Once once;
467
468 do_once(&once, {
469 clazz = _initialize(&(const ClassDef) {
470 .name = "Font",
471 .superclass = _Object(),
472 .instanceSize = sizeof(Font),
473 .interfaceSize = sizeof(FontInterface),
474 .initialize = initialize,
475 .destroy = destroy,
476 });
477 });
478
479 return clazz;
480}
static void initialize(Class *clazz)
Definition AtlasImage.c:74
static void destroy(Class *clazz)
Definition Checkbox.c:172
TrueType fonts.
Definition Font.h:88

◆ cacheFont()

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

Definition at line 122 of file Font.c.

122 {
123 $(_cache, setObjectForKeyPath, data, family);
124}
static Dictionary * _cache
Definition Font.c:116
char * family
The family name.
Definition Font.h:117
Data * data
The raw font data.
Definition Font.h:112

◆ clearCache()

void clearCache ( void  )

Clears the Font cache.

Definition at line 149 of file Font.c.

149 {
150 $(_cache, removeAllObjects);
151}

◆ defaultFont()

Font * defaultFont ( void  )
Returns
The default Font, at a pixel density of 1.0.
Remarks
This is the fallback for Views that are not yet attached to a window; on attachment, style application re-resolves Fonts through the window's cache.

Definition at line 159 of file Font.c.

159 {
160 static Once once;
161
162 const FontAttributes attrs = {
164 };
165
166 do_once(&once, {
167 _defaultFont = $$(Font, fontWithAttributes, &attrs, 1.f);
168 assert(_defaultFont);
169 });
170
171 return _defaultFont;
172}
static Font * _defaultFont
Definition Font.c:153
#define DEFAULT_FONT_STYLE
Definition Font.h:38
#define DEFAULT_FONT_FAMILY
Definition Font.h:36
#define DEFAULT_FONT_SIZE
Definition Font.h:37
The family, size and style attributes that identify a Font, independent of the pixel density at which...
Definition Font.h:64
Font * fontWithAttributes(const FontAttributes *attributes, float pixelDensity)
Resolves a new Font with the given attributes from the cached font Data.
Definition Font.c:199

◆ defaultMonospaceFont()

Font * defaultMonospaceFont ( void  )
Returns
The default monospaced Font, at a pixel density of 1.0.
Remarks
Bundled so that a bitmap font is always available; this is the fallback for Views that are not yet attached to a window, mirroring Font::defaultFont.

Definition at line 180 of file Font.c.

180 {
181 static Once once;
182
183 const FontAttributes attrs = {
185 };
186
187 do_once(&once, {
189 assert(_defaultMonospaceFont);
190 });
191
193}
static Font * _defaultMonospaceFont
Definition Font.c:174
#define DEFAULT_MONOSPACE_FONT_FAMILY
Definition Font.h:40

◆ fontWithAttributes()

Font * fontWithAttributes ( const FontAttributes *  attributes,
float  pixelDensity 
)

Resolves a new Font with the given attributes from the cached font Data.

"Cached" refers to the font Data registered via Font::cacheFont; the returned instance itself is newly created. Instance caching is provided by Theme::font, which callers with a Theme SHOULD prefer, since it supplies the pixel density implicitly and avoids re-opening the same Font repeatedly. Attributes are normalized to their defaults exactly as Font::nameWithAttributes normalizes them.

Parameters
attributesThe FontAttributes.
pixelDensityThe pixel density.
Returns
The Font, or the default Font if attributes->family is not registered. The caller owns the returned Font, and MUST release it.

Definition at line 199 of file Font.c.

199 {
200
201 FontAttributes normalized = *attributes;
202 normalizeAttributes(&normalized);
203
204 if (pixelDensity < 1.f) {
205 pixelDensity = 1.f;
206 }
207
208 Data *data = $((Dictionary *) _cache, objectForKeyPath, normalized.family);
209 if (data) {
210 Font *font = $(alloc(Font), initWithData, data, &normalized, pixelDensity);
211 assert(font);
212
213 return font;
214 }
215
216 MVC_LogWarn("%s-%d-%d not found\n", normalized.family, normalized.size, normalized.style);
217 return retain($$(Font, defaultFont));
218}
static void normalizeAttributes(FontAttributes *attributes)
Normalizes Font attributes to their defaults, in one place, so that Font::nameWithAttributes and Font...
Definition Font.c:130
#define MVC_LogWarn(fmt,...)
Definition Log.h:54
const char * family
The family, or NULL for the default.
Definition Font.h:68
int style
The FontStyle, or -1 for the default.
Definition Font.h:78
int size
The point size, or 0 for the default.
Definition Font.h:73
float pixelDensity
The display pixel density scale, greater than 1.0 on high-density displays.
Definition Font.h:134
Font * initWithData(Font *self, Data *data, const FontAttributes *attributes, float pixelDensity)
Initializes this Font with the given TTF Data and attributes.
Definition Font.c:263
Font * defaultFont(void)
Definition Font.c:159
TTF_Font * font
The backing font.
Definition Font.h:122

◆ fontWithName()

Font * fontWithName ( const char *  name,
float  pixelDensity 
)

Resolves a Font from a name in the format produced by Font::name.

The name is parsed from the right, so families MAY contain -: the final token is the style, the preceding token the point size, and the remainder the family.

Parameters
nameThe name, e.g. "Coda-16-regular".
pixelDensityThe pixel density.
Returns
The Font, or the default Font if name is not parseable or not registered. The caller owns the returned Font, and MUST release it.

Definition at line 224 of file Font.c.

224 {
225
226 assert(name);
227
228 char *chars = strdup(name);
229 assert(chars);
230
231 Font *font = NULL;
232
233 char *styleToken = strrchr(chars, '-');
234 if (styleToken) {
235 *styleToken++ = '\0';
236
237 char *sizeToken = strrchr(chars, '-');
238 if (sizeToken) {
239 *sizeToken++ = '\0';
240
241 const FontAttributes attributes = {
242 chars, (int) strtol(sizeToken, NULL, 10), valueof(FontStyleNames, styleToken)
243 };
244
245 font = $$(Font, fontWithAttributes, &attributes, pixelDensity);
246 }
247 }
248
249 free(chars);
250
251 if (font == NULL) {
252 MVC_LogWarn("%s is not a valid Font name\n", name);
253 font = retain($$(Font, defaultFont));
254 }
255
256 return font;
257}
OBJECTIVELYMVC_EXPORT const EnumName FontStyleNames[]
Definition Font.h:58
String * name(const Font *self)
Definition Font.c:303

◆ initWithData()

Font * initWithData ( Font *  self,
Data *  data,
const FontAttributes *  attributes,
float  pixelDensity 
)

Initializes this Font with the given TTF Data and attributes.

Fonts are immutable: the backing TTF_Font is opened here at size * pixelDensity and never re-opened. A pixel density change MUST be handled by resolving a new instance (see Theme::font).

Parameters
selfThe Font.
dataThe Data.
attributesThe FontAttributes.
pixelDensityThe pixel density.
Returns
The initialized Font, or NULL on error.

Definition at line 263 of file Font.c.

263 {
264
265 self = (Font *) super(Object, self, init);
266 if (self) {
267
268 self->data = retain(data);
269 assert(self->data);
270
271 self->family = strdup(attributes->family);
272 assert(self->family);
273
274 self->size = attributes->size;
275 assert(self->size);
276
277 self->style = attributes->style;
278
280 self->renderSize = self->size * self->pixelDensity;
281
282 SDL_IOStream *buffer = SDL_IOFromConstMem(self->data->bytes, (int) self->data->length);
283 assert(buffer);
284
285 self->font = TTF_OpenFontIO(buffer, 1, self->renderSize);
286 assert(self->font);
287
288 TTF_SetFontStyle(self->font, self->style);
289 TTF_SetFontHinting(self->font, TTF_HINTING_LIGHT_SUBPIXEL);
290
291 if (TTF_FontIsFixedWidth(self->font)) {
292 initBitmap(&self->bitmap, self);
293 }
294 }
295
296 return self;
297}
static View * init(View *self)
Definition Box.c:67
bool initBitmap(FontBitmap *bitmap, Font *font)
Bakes FONT_BITMAP_COUNT codepoints of font, from FONT_BITMAP_FIRST, into a glyph sheet,...
int renderSize
The render size, adjusted for pixel density.
Definition Font.h:139
FontBitmap bitmap
The glyphs of a fixed-width Font, baked into one sheet; bitmap.surface is NULL for a proportional Fon...
Definition Font.h:107
int size
The point size.
Definition Font.h:144
int style
The style.
Definition Font.h:149

◆ name()

String * name ( const Font *  self)
Returns
This Font's name, in the format family-size-style, e.g. "Coda-16-regular".
Remarks
The format is stable and MAY be parsed by Font::fontWithName; it is also the key under which Theme caches Font instances. Pixel density is deliberately absent: it is implied by the window whose cache is consulted.

Definition at line 303 of file Font.c.

303 {
304 const FontAttributes attributes = { self->family, self->size, self->style };
305 return $$(Font, nameWithAttributes, &attributes);
306}
String * nameWithAttributes(const FontAttributes *attributes)
Definition Font.c:312

◆ nameWithAttributes()

String * nameWithAttributes ( const FontAttributes *  attributes)
Returns
The Font name for the given attributes, in the format of Font::name.

Definition at line 312 of file Font.c.

312 {
313
314 FontAttributes normalized = *attributes;
315 normalizeAttributes(&normalized);
316
317 for (const EnumName *en = FontStyleNames; en->name; en++) {
318 if (en->value == normalized.style) {
319 return str("%s-%d-%s", normalized.family, normalized.size, en->alias ?: en->name);
320 }
321 }
322
323 return str("%s-%d-%d", normalized.family, normalized.size, normalized.style);
324}

◆ renderBitmapCharacters()

void renderBitmapCharacters ( Font *  self,
const Renderer *  renderer,
const char *  chars,
SDL_Color  color,
int  wrapWidth,
const SDL_Point *  origin,
const ImageAtlas *  icons 
)

Records one quad per glyph of the given characters from this Font's bitmap.

Parameters
selfThe Font, which MUST have a bitmap.
rendererThe Renderer.
charsThe null-terminated UTF-8 encoded C string to render.
colorThe color; ^0 through ^9 in chars select from TextEscapeColors, and ^^ is a literal ^.
wrapWidthThe maximum line width, in logical pixels, or 0 for no wrapping.
originThe top-left corner of the first line, in logical pixels.
iconsThe ImageAtlas resolving :icon: escapes, or NULL for none.

◆ renderCharacters()

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

Renders the given characters in this Font.

Parameters
selfThe Font.
charsThe null-terminated UTF-8 encoded C string to render.
colorThe color.
wrapWidthThe maximum line width, in logical pixels, where wrapping should occur.
Returns
The rendered surface, or NULL on error.

Definition at line 330 of file Font.c.

330 {
331
332 // Always the wrapping renderer: with a width of 0 it breaks on newlines only, which is what
333 // Font::sizeCharacters and the TTF_Text layout Text builds its color runs from both assume,
334 // whereas TTF_RenderText_Blended draws a newline as a missing glyph on a single line
335 SDL_Surface *surface = TTF_RenderText_Blended_Wrapped(self->font, chars, 0, color, wrapWidth * self->pixelDensity);
336
337 SDL_Surface *converted = NULL;
338 if (surface) {
339 converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32);
340 SDL_DestroySurface(surface);
341 } else {
342 MVC_LogError("%s\n", SDL_GetError());
343 }
344
345 return converted;
346}
#define MVC_LogError(fmt,...)
Definition Log.h:57

◆ renderDeviceWillReset()

void renderDeviceWillReset ( Font *  self)

Releases this Font's bitmap Texture, if any, ahead of a render device reset. It is recreated on the next draw.

Parameters
selfThe Font.

◆ sizeBitmapCharacters()

void sizeBitmapCharacters ( const Font *  self,
const char *  chars,
int  wrapWidth,
const ImageAtlas *  icons,
int *  w,
int *  h 
)

Measures the given characters against this Font's bitmap.

Parameters
selfThe Font, which MUST have a bitmap.
charsThe null-terminated UTF-8 encoded C string to size.
wrapWidthThe maximum line width, in logical pixels, or 0 for no wrapping.
iconsThe ImageAtlas resolving :icon: escapes, or NULL for none.
wThe width to return, in logical pixels.
hThe height to return, in logical pixels.

◆ sizeCharacters()

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

Measures the given characters in this Font.

Parameters
selfThe Font.
charsThe null-terminated UTF-8 encoded C string to size.
wThe width to return.
hThe height to return.
Returns
The size of the rendered characters in logical pixels.

Definition at line 352 of file Font.c.

352 {
353
354 if (w) {
355 *w = 0;
356 }
357 if (h) {
358 *h = 0;
359 }
360
361 if (chars) {
362 char *lines = strdup(chars);
363
364 const int font_h = TTF_GetFontHeight(self->font);
365
366 for (char *line = strtok(lines, "\n\r"); line; line = strtok(NULL, "\n\r")) {
367
368 if (w) {
369
370 int lineWidth;
371 TTF_GetStringSize(self->font, line, 0, &lineWidth, NULL);
372
373 // TTF_GetStringSize sums glyph advances, but the final glyph's ink can extend past its
374 // own advance (common with bold or large faces). Check the final glyph's bounds and
375 // ensure we take the larger value.
376 const char *end = line + strlen(line);
377 const Uint32 ch = SDL_StepBackUTF8(line, &end);
378 if (ch) {
379 int maxX, advance;
380 if (TTF_GetGlyphMetrics(self->font, ch, NULL, &maxX, NULL, NULL, &advance)) {
381 if (maxX > advance) {
382 lineWidth += maxX - advance;
383 }
384 }
385 }
386
387 *w = max(*w, lineWidth);
388 }
389 if (h) {
390 *h += font_h;
391 }
392 }
393 free(lines);
394
395 if (w) {
396 *w = ceilf(*w / self->pixelDensity);
397 }
398 if (h) {
399 *h = ceilf(*h / self->pixelDensity);
400 }
401 }
402}

Field Documentation

◆ bitmap

FontBitmap Font::bitmap

The glyphs of a fixed-width Font, baked into one sheet; bitmap.surface is NULL for a proportional Font.

Monospaced Fonts are bitmap fonts: Text draws a Font with a bitmap as one quad per glyph from the sheet, with no opt-in.

Definition at line 107 of file Font.h.

◆ cacheFont

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

Caches the specified font Data.

Parameters
dataThe TTF Data.
familyThe family.

Definition at line 169 of file Font.h.

◆ data

Data* Font::data

The raw font data.

Definition at line 112 of file Font.h.

◆ family

char* Font::family

The family name.

Definition at line 117 of file Font.h.

◆ font

TTF_Font* Font::font

The backing font.

Definition at line 122 of file Font.h.

◆ interface

FontInterface* Font::interface[0]
protected

The interface type.

Definition at line 99 of file Font.h.

◆ object

Object Font::object

The superclass.

Definition at line 93 of file Font.h.

◆ pixelDensity

float Font::pixelDensity

The display pixel density scale, greater than 1.0 on high-density displays.

Definition at line 134 of file Font.h.

◆ renderSize

int Font::renderSize

The render size, adjusted for pixel density.

Definition at line 139 of file Font.h.

◆ size

int Font::size

The point size.

Definition at line 144 of file Font.h.

◆ style

int Font::style

The style.

Definition at line 149 of file Font.h.


The documentation for this struct was generated from the following files: