ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
Text.h File Reference

Text rendered with TrueType fonts. More...

#include <SDL3/SDL_gpu.h>
#include <ObjectivelyMVC/Font.h>
#include <ObjectivelyMVC/ImageAtlas.h>
#include <ObjectivelyMVC/View.h>

Go to the source code of this file.

Data Structures

struct  Text
 Text rendered with TrueType fonts. More...
 
struct  TextRun
 One quad of a rendered TrueType Text: a region of its texture, in texels, drawn in color, or, when icon is set, that icon drawn as a square of the line height within it. More...
 
struct  TextSpan
 One span of a laid-out string, in bytes of the layout string MVC_LayoutText returns: either the characters drawn in color, or a placeholder standing in for icon. More...
 

Enumerations

enum  TextTransform { TextTransformNone , TextTransformUppercase , TextTransformLowercase , TextTransformCapitalize }
 Case transforms a Text applies when drawing, leaving Text::text as set. More...
 

Functions

OBJECTIVELYMVC_EXPORT Class * _Text (void)
 
OBJECTIVELYMVC_EXPORT bool MVC_HasColorEscapes (const char *text)
 
OBJECTIVELYMVC_EXPORT size_t MVC_IconEscapeLength (const char *chars, const ImageAtlas *icons, AtlasImage **image)
 Parses an icon escape at the start of chars: :name:, where name is one or more of [A-Za-z0-9_-] and under 64 bytes, and is registered in icons. An unregistered name is not an escape, so 12:30:45 stays literal unless someone registers an icon called 30.
 
OBJECTIVELYMVC_EXPORT char * MVC_LayoutText (const Font *font, const char *text, SDL_Color color, const ImageAtlas *icons, TextSpan **spans, size_t *count)
 Resolves the escapes in text into the string to lay out and the spans to draw it as.
 
OBJECTIVELYMVC_EXPORT char * MVC_StripColorEscapes (const char *text)
 Strips color escape sequences from the given text: ^0 through ^9 are removed, and ^^ collapses to ^.
 

Variables

OBJECTIVELYMVC_EXPORT SDL_Color TextEscapeColors [10]
 Color palette for text escape sequences (^0 through ^9).
 
OBJECTIVELYMVC_EXPORT const EnumName TextTransformNames []
 

Detailed Description

Text rendered with TrueType fonts.

Definition in file Text.h.

Enumeration Type Documentation

◆ TextTransform

Case transforms a Text applies when drawing, leaving Text::text as set.

ASCII letters only; multi-byte UTF-8 sequences and color escapes pass through unchanged. Resolved :icon: escapes also pass through unchanged, so icon names keep their case.

Enumerator
TextTransformNone 
TextTransformUppercase 
TextTransformLowercase 
TextTransformCapitalize 

Definition at line 67 of file Text.h.

67 {
TextTransform
Case transforms a Text applies when drawing, leaving Text::text as set.
Definition Text.h:67
@ TextTransformUppercase
Definition Text.h:69
@ TextTransformCapitalize
Definition Text.h:71
@ TextTransformLowercase
Definition Text.h:70
@ TextTransformNone
Definition Text.h:68

Function Documentation

◆ _Text()

OBJECTIVELYMVC_EXPORT Class * _Text ( void  )

Definition at line 988 of file Text.c.

988 {
989 static Class *clazz;
990 static Once once;
991
992 do_once(&once, {
993 clazz = _initialize(&(const ClassDef) {
994 .name = "Text",
995 .superclass = _View(),
996 .instanceSize = sizeof(Text),
997 .interfaceSize = sizeof(TextInterface),
998 .initialize = initialize,
999 });
1000 });
1001
1002 return clazz;
1003}
static void initialize(Class *clazz)
Definition Text.c:961
Class * _View(void)
Definition View.c:2336
Text rendered with TrueType fonts.
Definition Text.h:131

◆ MVC_HasColorEscapes()

OBJECTIVELYMVC_EXPORT bool MVC_HasColorEscapes ( const char *  text)
Parameters
textThe text, or NULL.
Returns
True if text contains a color escape (^0 through ^9, or ^^).

Definition at line 65 of file Text.c.

65 {
66
67 for (const char *p = text ? strchr(text, '^') : NULL; p; p = strchr(p + 1, '^')) {
68 if (colorEscapeLength(p)) {
69 return true;
70 }
71 }
72
73 return false;
74}
static size_t colorEscapeLength(const char *chars)
Length of the color escape at chars, or 0 if there is none: ^N selects a color, ^^ is a literal caret...
Definition Text.c:58

◆ MVC_IconEscapeLength()

OBJECTIVELYMVC_EXPORT size_t MVC_IconEscapeLength ( const char *  chars,
const ImageAtlas *  icons,
AtlasImage **  image 
)

Parses an icon escape at the start of chars: :name:, where name is one or more of [A-Za-z0-9_-] and under 64 bytes, and is registered in icons. An unregistered name is not an escape, so 12:30:45 stays literal unless someone registers an icon called 30.

Parameters
charsThe text, positioned at a candidate :.
iconsThe icon ImageAtlas, or NULL for none.
imageIf not NULL, receives the icon, or NULL.
Returns
The byte length of the escape, or 0 if chars does not start with one.

Definition at line 104 of file Text.c.

104 {
105
106 if (image) {
107 *image = NULL;
108 }
109
110 if (chars == NULL || icons == NULL || chars[0] != ':') {
111 return 0;
112 }
113
114 const char *q = chars + 1;
115 while (SDL_isalnum((unsigned char) *q) || *q == '_' || *q == '-') {
116 q++;
117 }
118
119 char name[64];
120 const size_t len = q - chars - 1;
121
122 if (*q != ':' || len == 0 || len >= sizeof(name)) {
123 return 0;
124 }
125
126 memcpy(name, chars + 1, len);
127 name[len] = '\0';
128
130 if (icon == NULL) {
131 return 0;
132 }
133
134 if (image) {
135 *image = icon;
136 }
137
138 return len + 2;
139}
static String * name(const Font *self)
Definition Font.c:303
static AtlasImage * imageWithName(const ImageAtlas *self, const char *name)
Definition ImageAtlas.c:112
static AtlasImage * icon(Theme *self, const char *name)
Definition Theme.c:175
static ImageAtlas * icons(Theme *self)
Definition Theme.c:144
static Image * image(Theme *self, const char *name, float pixelDensity)
Definition Theme.c:82
An Image packed into an ImageAtlas.
Definition AtlasImage.h:41

◆ MVC_LayoutText()

OBJECTIVELYMVC_EXPORT char * MVC_LayoutText ( const Font *  font,
const char *  text,
SDL_Color  color,
const ImageAtlas *  icons,
TextSpan **  spans,
size_t *  count 
)

Resolves the escapes in text into the string to lay out and the spans to draw it as.

^N selects a color for what follows, ^^ becomes ^, and a registered :icon: becomes a run of placeholder characters at least a line height wide, for the icon to be drawn over. The placeholder is never a line-break opportunity, so an icon stays with its word. With no icons, and spans NULL, the result is that of MVC_StripColorEscapes.

Parameters
fontThe Font the text will be laid out in.
textThe text.
colorThe color in effect at the start of text.
iconsThe icon ImageAtlas, or NULL for none.
spansIf not NULL, receives the spans, which the caller MUST free.
countIf not NULL, receives the number of spans; meaningful only with spans.
Returns
The layout string, which the caller MUST free.

Definition at line 220 of file Text.c.

220 {
221
222 assert(font);
223 assert(text);
224
225 LayoutBuffer layout = { 0 };
226 append(&layout, "", 0);
227
228 size_t n = 0;
229 if (spans) {
230 *spans = NULL;
231 }
232
233 size_t start = 0;
234
235 for (const char *p = text; ; ) {
236
237 const bool end = *p == '\0';
238 const bool escape = !end && p[0] == '^' && p[1] >= '0' && p[1] <= '9';
239
240 AtlasImage *icon = NULL;
241 const size_t iconLength = (!end && *p == ':') ? MVC_IconEscapeLength(p, icons, &icon) : 0;
242
243 if (end || escape || iconLength) {
244 if (layout.length > start) {
245 appendSpan(spans, &n, (TextSpan) { (int) start, (int) (layout.length - start), color, NULL });
246 }
247 if (end) {
248 break;
249 }
250 if (escape) {
251 color = TextEscapeColors[p[1] - '0'];
252 p += 2;
253 } else {
254 const char *placeholder = iconPlaceholder(font);
255 appendSpan(spans, &n, (TextSpan) { (int) layout.length, (int) strlen(placeholder), Colors.White, icon });
256 append(&layout, placeholder, strlen(placeholder));
257 p += iconLength;
258 }
259 start = layout.length;
260 } else if (p[0] == '^' && p[1] == '^') {
261 append(&layout, "^", 1);
262 p += 2;
263 } else {
264 append(&layout, p, 1);
265 p++;
266 }
267 }
268
269 if (count) {
270 *count = n;
271 }
272
273 return layout.chars;
274}
static void appendSpan(TextSpan **spans, size_t *count, TextSpan span)
Definition Text.c:207
SDL_Color TextEscapeColors[]
Definition Text.c:41
static const char * iconPlaceholder(const Font *font)
The placeholder an icon occupies in font's layout: a codepoint that is not a line-break opportunity,...
Definition Text.c:171
static void append(LayoutBuffer *buffer, const char *chars, size_t length)
Definition Text.c:150
size_t MVC_IconEscapeLength(const char *chars, const ImageAtlas *icons, AtlasImage **image)
Parses an icon escape at the start of chars: :name:, where name is one or more of [A-Za-z0-9_-] and u...
Definition Text.c:104
static Font * font(Theme *self, const FontAttributes *attributes, float pixelDensity)
Definition Theme.c:108
W3C Color constants.
Definition Colors.h:37
SDL_Color White
Definition Colors.h:185
A growable string for MVC_LayoutText.
Definition Text.c:144
char * chars
Definition Text.c:145
size_t length
Definition Text.c:146
One span of a laid-out string, in bytes of the layout string MVC_LayoutText returns: either the chara...
Definition Text.h:91

◆ MVC_StripColorEscapes()

OBJECTIVELYMVC_EXPORT char * MVC_StripColorEscapes ( const char *  text)

Strips color escape sequences from the given text: ^0 through ^9 are removed, and ^^ collapses to ^.

Parameters
textThe text.
Returns
A newly allocated copy of text without escape sequences. The caller must free it.

Definition at line 83 of file Text.c.

83 {
84
85 assert(text);
86
87 char *stripped = malloc(strlen(text) + 1);
88 size_t idx = 0;
89
90 for (const char *p = text; *p; p++) {
91 if (p[0] == '^' && p[1] >= '0' && p[1] <= '9') {
92 p++;
93 } else if (p[0] == '^' && p[1] == '^') {
94 stripped[idx++] = *p++;
95 } else {
96 stripped[idx++] = *p;
97 }
98 }
99
100 stripped[idx] = '\0';
101 return stripped;
102}

Variable Documentation

◆ TextEscapeColors

OBJECTIVELYMVC_EXPORT SDL_Color TextEscapeColors[10]

Color palette for text escape sequences (^0 through ^9).

Escapes are always interpreted, on every Text: ^N selects TextEscapeColors[N] for the characters that follow, and ^^ renders a literal ^. Embedding applications MAY customize this array at runtime, before rendering.

Default mapping: ^0 Black, ^1 Red, ^2 Green, ^3 Yellow, ^4 Blue, ^5 Magenta, ^6 Cyan, ^7 White, ^8 Orange, ^9 Grey.

Definition at line 46 of file Text.h.

◆ TextTransformNames

OBJECTIVELYMVC_EXPORT const EnumName TextTransformNames[]

Definition at line 74 of file Text.h.