Skip to content

Commit 2a3914a

Browse files
author
Trent Gamblin
authored
Add ALLEGRO_GLYPH structure and al_get_glyph. (#657)
The structure contains all the info need (including the bitmap) to draw text. The ttf addon's render_glyph was used to make the vtable function for the ttf addon.
1 parent 85fb938 commit 2a3914a

File tree

6 files changed

+176
-34
lines changed

6 files changed

+176
-34
lines changed

addons/font/allegro5/allegro_font.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
/* Type: ALLEGRO_FONT
4848
*/
4949
typedef struct ALLEGRO_FONT ALLEGRO_FONT;
50+
/* Type: ALLEGRO_GLYPH
51+
*/
52+
typedef struct ALLEGRO_GLYPH ALLEGRO_GLYPH;
5053
typedef struct ALLEGRO_FONT_VTABLE ALLEGRO_FONT_VTABLE;
5154

5255
struct ALLEGRO_FONT
@@ -58,6 +61,19 @@ struct ALLEGRO_FONT
5861
_AL_LIST_ITEM *dtor_item;
5962
};
6063

64+
struct ALLEGRO_GLYPH
65+
{
66+
ALLEGRO_BITMAP *bitmap;
67+
int x;
68+
int y;
69+
int w;
70+
int h;
71+
int kerning;
72+
int offset_x;
73+
int offset_y;
74+
int advance;
75+
};
76+
6177
/* text- and font-related stuff */
6278
struct ALLEGRO_FONT_VTABLE
6379
{
@@ -78,7 +94,8 @@ struct ALLEGRO_FONT_VTABLE
7894
int codepoint, int *bbx, int *bby, int *bbw, int *bbh));
7995
ALLEGRO_FONT_METHOD(int, get_glyph_advance, (const ALLEGRO_FONT *font,
8096
int codepoint1, int codepoint2));
81-
97+
98+
ALLEGRO_FONT_METHOD(bool, get_glyph, (const ALLEGRO_FONT *f, int prev_codepoint, int codepoint, ALLEGRO_GLYPH *glyph));
8299
};
83100

84101
enum {
@@ -130,6 +147,7 @@ ALLEGRO_FONT_FUNC(bool, al_get_glyph_dimensions, (const ALLEGRO_FONT *f,
130147
int codepoint, int *bbx, int *bby, int *bbw, int *bbh));
131148
ALLEGRO_FONT_FUNC(int, al_get_glyph_advance, (const ALLEGRO_FONT *f,
132149
int codepoint1, int codepoint2));
150+
ALLEGRO_FONT_FUNC(bool, al_get_glyph, (const ALLEGRO_FONT *f, int prev_codepoint, int codepoint, ALLEGRO_GLYPH *glyph));
133151

134152
ALLEGRO_FONT_FUNC(void, al_draw_multiline_text, (const ALLEGRO_FONT *font, ALLEGRO_COLOR color, float x, float y, float max_width, float line_height, int flags, const char *text));
135153
ALLEGRO_FONT_FUNC(void, al_draw_multiline_textf, (const ALLEGRO_FONT *font, ALLEGRO_COLOR color, float x, float y, float max_width, float line_height, int flags, const char *format, ...));

addons/font/font.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,27 @@ static int color_render(const ALLEGRO_FONT* f, ALLEGRO_COLOR color,
209209
}
210210

211211

212+
static bool color_get_glyph(const ALLEGRO_FONT *f, int prev_codepoint, int codepoint, ALLEGRO_GLYPH *glyph)
213+
{
214+
ALLEGRO_BITMAP *g = _al_font_color_find_glyph(f, codepoint);
215+
if (g) {
216+
glyph->bitmap = g;
217+
glyph->x = 0;
218+
glyph->y = 0;
219+
glyph->w = al_get_bitmap_width(g);
220+
glyph->h = al_get_bitmap_height(g);
221+
glyph->kerning = 0;
222+
glyph->offset_x = 0;
223+
glyph->offset_y = 0;
224+
glyph->advance = glyph->w;
225+
return true;
226+
}
227+
if (f->fallback) {
228+
return f->fallback->vtable->get_glyph(f->fallback, prev_codepoint, codepoint, glyph);
229+
}
230+
return false;
231+
}
232+
212233

213234
/* color_destroy:
214235
* (color vtable entry)
@@ -317,7 +338,8 @@ ALLEGRO_FONT_VTABLE _al_font_vtable_color = {
317338
color_get_text_dimensions,
318339
color_get_font_ranges,
319340
color_get_glyph_dimensions,
320-
color_get_glyph_advance
341+
color_get_glyph_advance,
342+
color_get_glyph
321343
};
322344

323345

addons/font/text.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,12 @@ int al_get_glyph_advance(const ALLEGRO_FONT *f, int codepoint1, int codepoint2)
402402
return f->vtable->get_glyph_advance(f, codepoint1, codepoint2);
403403
}
404404

405+
/* Function: al_get_glyph
406+
*/
407+
bool al_get_glyph(const ALLEGRO_FONT *f, int prev_codepoint, int codepoint, ALLEGRO_GLYPH *glyph)
408+
{
409+
return f->vtable->get_glyph(f, prev_codepoint, codepoint, glyph);
410+
};
405411

406412

407413
/* This helper function helps splitting an ustr in several delimited parts.

addons/ttf/ttf.c

Lines changed: 71 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -495,44 +495,81 @@ static int get_kerning(ALLEGRO_TTF_FONT_DATA const *data, FT_Face face,
495495
}
496496

497497

498-
static int render_glyph(ALLEGRO_FONT const *f, ALLEGRO_COLOR color,
499-
int prev_ft_index, int ft_index, int32_t ch, float xpos, float ypos)
498+
static bool ttf_get_glyph_worker(ALLEGRO_FONT const *f, int prev_ft_index, int ft_index, int prev_codepoint, int codepoint, ALLEGRO_GLYPH *info)
500499
{
501500
ALLEGRO_TTF_FONT_DATA *data = f->data;
502501
FT_Face face = data->face;
503502
ALLEGRO_TTF_GLYPH_DATA *glyph;
504503
int advance = 0;
505504

506505
if (!get_glyph(data, ft_index, &glyph)) {
507-
if (f->fallback) {
508-
al_draw_glyph(f->fallback, color, xpos, ypos, ch);
509-
return al_get_glyph_advance(f->fallback, ch,
510-
ALLEGRO_NO_KERNING);
511-
}
506+
if (f->fallback)
507+
return f->fallback->vtable->get_glyph(f->fallback, prev_codepoint, codepoint, info);
512508
else {
513509
get_glyph(data, 0, &glyph);
514510
ft_index = 0;
515511
}
516512
}
513+
517514
cache_glyph(data, face, ft_index, glyph, false);
518515

519516
advance += get_kerning(data, face, prev_ft_index, ft_index);
520517

521518
if (glyph->page_bitmap) {
522-
/* Each glyph has a 1-pixel border all around. */
523-
al_draw_tinted_bitmap_region(glyph->page_bitmap, color,
524-
glyph->region.x + 1, glyph->region.y + 1,
525-
glyph->region.w - 2, glyph->region.h - 2,
526-
xpos + glyph->offset_x + advance,
527-
ypos + glyph->offset_y, 0);
519+
info->bitmap = glyph->page_bitmap;
520+
info->x = glyph->region.x + 1;
521+
info->y = glyph->region.y + 1;
522+
info->w = glyph->region.w - 2;
523+
info->h = glyph->region.h - 2;
524+
info->kerning = advance;
525+
info->offset_x = glyph->offset_x;
526+
info->offset_y = glyph->offset_y;
528527
}
529528
else if (glyph->region.x > 0) {
530529
ALLEGRO_ERROR("Glyph %d not on any page.\n", ft_index);
530+
return false;
531+
}
532+
else {
533+
info->bitmap = 0;
531534
}
532535

533536
advance += glyph->advance;
534537

535-
return advance;
538+
info->advance = advance;
539+
540+
return true;
541+
}
542+
543+
544+
static bool ttf_get_glyph(ALLEGRO_FONT const *f, int prev_codepoint, int codepoint, ALLEGRO_GLYPH *glyph)
545+
{
546+
ALLEGRO_TTF_FONT_DATA *data = f->data;
547+
FT_Face face = data->face;
548+
int prev_ft_index = (prev_codepoint == -1) ? -1 : FT_Get_Char_Index(face, prev_codepoint);
549+
int ft_index = FT_Get_Char_Index(face, codepoint);
550+
return ttf_get_glyph_worker(f, prev_ft_index, ft_index, prev_codepoint, codepoint, glyph);
551+
}
552+
553+
554+
static int render_glyph(ALLEGRO_FONT const *f, ALLEGRO_COLOR color,
555+
int prev_ft_index, int ft_index, int32_t prev_ch, int32_t ch, float xpos, float ypos)
556+
{
557+
ALLEGRO_GLYPH glyph;
558+
559+
if (ttf_get_glyph_worker(f, prev_ft_index, ft_index, prev_ch, ch, &glyph) == false)
560+
return 0;
561+
562+
if (glyph.bitmap != NULL) {
563+
al_draw_tinted_bitmap_region(
564+
glyph.bitmap, color,
565+
glyph.x, glyph.y, glyph.w, glyph.h,
566+
xpos + glyph.offset_x + glyph.kerning,
567+
ypos + glyph.offset_y,
568+
0
569+
);
570+
}
571+
572+
return glyph.advance;
536573
}
537574

538575

@@ -578,10 +615,10 @@ static int ttf_render_char(ALLEGRO_FONT const *f, ALLEGRO_COLOR color,
578615
FT_Face face = data->face;
579616
int advance = 0;
580617
int32_t ch32 = (int32_t) ch;
581-
618+
582619
int ft_index = FT_Get_Char_Index(face, ch32);
583-
advance = render_glyph(f, color, -1, ft_index, ch, xpos, ypos);
584-
620+
advance = render_glyph(f, color, -1, ft_index, -1, ch, xpos, ypos);
621+
585622
return advance;
586623
}
587624

@@ -591,7 +628,7 @@ static int ttf_char_length(ALLEGRO_FONT const *f, int ch)
591628
int result;
592629
ALLEGRO_TTF_FONT_DATA *data = f->data;
593630
ALLEGRO_TTF_GLYPH_DATA *glyph;
594-
FT_Face face = data->face;
631+
FT_Face face = data->face;
595632
int ft_index = FT_Get_Char_Index(face, ch);
596633
if (!get_glyph(data, ft_index, &glyph)) {
597634
if (f->fallback) {
@@ -604,7 +641,7 @@ static int ttf_char_length(ALLEGRO_FONT const *f, int ch)
604641
}
605642
cache_glyph(data, face, ft_index, glyph, false);
606643
result = glyph->region.w - 2;
607-
644+
608645
return result;
609646
}
610647

@@ -617,6 +654,7 @@ static int ttf_render(ALLEGRO_FONT const *f, ALLEGRO_COLOR color,
617654
int pos = 0;
618655
int advance = 0;
619656
int prev_ft_index = -1;
657+
int32_t prev_ch = -1;
620658
int32_t ch;
621659
bool hold;
622660

@@ -625,9 +663,10 @@ static int ttf_render(ALLEGRO_FONT const *f, ALLEGRO_COLOR color,
625663

626664
while ((ch = al_ustr_get_next(text, &pos)) >= 0) {
627665
int ft_index = FT_Get_Char_Index(face, ch);
628-
advance += render_glyph(f, color, prev_ft_index, ft_index, ch,
666+
advance += render_glyph(f, color, prev_ft_index, ft_index, prev_ch, ch,
629667
x + advance, y);
630668
prev_ft_index = ft_index;
669+
prev_ch = ch;
631670
}
632671

633672
al_hold_bitmap_drawing(hold);
@@ -699,7 +738,7 @@ static void ttf_get_text_dimensions(ALLEGRO_FONT const *f,
699738

700739
*bby = ymin;
701740
*bbw = x - *bbx;
702-
*bbh = ymax - ymin;
741+
*bbh = ymax - ymin;
703742
}
704743

705744

@@ -803,7 +842,7 @@ ALLEGRO_FONT *al_load_ttf_font_stretch_f(ALLEGRO_FILE *file,
803842
al_get_config_value(system_cfg, "ttf", "max_page_size");
804843
const char* cache_str =
805844
al_get_config_value(system_cfg, "ttf", "cache_text");
806-
const char* skip_cache_misses_str =
845+
const char* skip_cache_misses_str =
807846
al_get_config_value(system_cfg, "ttf", "skip_cache_misses");
808847

809848
if ((h > 0 && w < 0) || (h < 0 && w > 0)) {
@@ -904,7 +943,7 @@ ALLEGRO_FONT *al_load_ttf_font_stretch_f(ALLEGRO_FILE *file,
904943

905944
_al_vector_init(&data->glyph_ranges, sizeof(ALLEGRO_TTF_GLYPH_RANGE));
906945
_al_vector_init(&data->page_bitmaps, sizeof(ALLEGRO_BITMAP*));
907-
946+
908947
if (data->skip_cache_misses) {
909948
cache_glyphs(data, "\0", 1);
910949
}
@@ -992,7 +1031,7 @@ static bool ttf_get_glyph_dimensions(ALLEGRO_FONT const *f,
9921031
{
9931032
ALLEGRO_TTF_FONT_DATA *data = f->data;
9941033
ALLEGRO_TTF_GLYPH_DATA *glyph;
995-
FT_Face face = data->face;
1034+
FT_Face face = data->face;
9961035
int ft_index = FT_Get_Char_Index(face, codepoint);
9971036
if (!get_glyph(data, ft_index, &glyph)) {
9981037
if (f->fallback) {
@@ -1009,7 +1048,7 @@ static bool ttf_get_glyph_dimensions(ALLEGRO_FONT const *f,
10091048
*bbw = glyph->region.w - 2;
10101049
*bbh = glyph->region.h - 2;
10111050
*bby = glyph->offset_y;
1012-
1051+
10131052
return true;
10141053
}
10151054

@@ -1019,10 +1058,10 @@ static int ttf_get_glyph_advance(ALLEGRO_FONT const *f, int codepoint1,
10191058
ALLEGRO_TTF_FONT_DATA *data = f->data;
10201059
FT_Face face = data->face;
10211060
int ft_index = FT_Get_Char_Index(face, codepoint1);
1022-
ALLEGRO_TTF_GLYPH_DATA *glyph;
1061+
ALLEGRO_TTF_GLYPH_DATA *glyph;
10231062
int kerning = 0;
10241063
int advance = 0;
1025-
1064+
10261065
if (codepoint1 == ALLEGRO_NO_KERNING) {
10271066
return 0;
10281067
}
@@ -1037,13 +1076,13 @@ static int ttf_get_glyph_advance(ALLEGRO_FONT const *f, int codepoint1,
10371076
}
10381077
}
10391078
cache_glyph(data, face, ft_index, glyph, false);
1040-
1041-
if (codepoint2 != ALLEGRO_NO_KERNING) {
1079+
1080+
if (codepoint2 != ALLEGRO_NO_KERNING) {
10421081
int ft_index1 = FT_Get_Char_Index(face, codepoint1);
1043-
int ft_index2 = FT_Get_Char_Index(face, codepoint2);
1082+
int ft_index2 = FT_Get_Char_Index(face, codepoint2);
10441083
kerning = get_kerning(data, face, ft_index1, ft_index2);
10451084
}
1046-
1085+
10471086
advance = glyph->advance;
10481087
return advance + kerning;
10491088
}
@@ -1072,6 +1111,7 @@ bool al_init_ttf_addon(void)
10721111
vt.get_font_ranges = ttf_get_font_ranges;
10731112
vt.get_glyph_dimensions = ttf_get_glyph_dimensions;
10741113
vt.get_glyph_advance = ttf_get_glyph_advance;
1114+
vt.get_glyph = ttf_get_glyph;
10751115

10761116
al_register_font_loader(".ttf", al_load_ttf_font);
10771117

docs/src/refman/font.txt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,39 @@ the FreeType library. If you instead pass the filename of a bitmap file, it will
1717
be loaded with [al_load_bitmap] and a font in Allegro's bitmap font format will
1818
be created from it with [al_grab_font_from_bitmap].
1919

20+
### API: ALLEGRO_GLYPH
21+
22+
A structure containing the properties of a character in a font.
23+
24+
~~~~c
25+
typedef struct ALLEGRO_GLYPH {
26+
ALLEGRO_BITMAP *bitmap; // the bitmap the character is on
27+
int x; // the x position of the glyph on bitmap
28+
int y; // the y position of the glyph on bitmap
29+
int w; // the width of the glyph in pixels
30+
int h; // the height of the glyph in pixels
31+
int kerning; // pixels of kerning (see below)
32+
int offset_x; // x offset to draw the glyph at
33+
int offset_y; // y offset to draw the glyph at
34+
int advance; // number of pixels to advance after this character
35+
} ALLEGRO_GLYPH;
36+
~~~~
37+
38+
bitmap may be a sub-bitmap in the case of color fonts.
39+
40+
kerning should be added to the x position you draw to if you want your text
41+
kerned and depends on which codepoints [al_get_glyph] was called with.
42+
43+
Glyphs are tightly packed onto the bitmap, so you need to add offset_x and
44+
offset_y to your draw position for the text to look right.
45+
46+
advance is the number of pixels to add to your x position to advance to the
47+
next character in a string and includes kerning.
48+
49+
Since: 5.2.1
50+
51+
See also: [al_get_glyph]
52+
2053
### API: al_init_font_addon
2154

2255
Initialise the font addon.
@@ -739,3 +772,15 @@ See also: [al_load_ttf_font_stretch]
739772

740773
Returns the (compiled) version of the addon, in the same format as
741774
[al_get_allegro_version].
775+
776+
### API: al_get_glyph
777+
778+
Gets all the information about a glyph, including the bitmap, needed to draw it
779+
yourself. prev_codepoint is the codepoint in the string before the one you want
780+
to draw and is used for kerning. codepoint is the character you want to get info
781+
about. You should clear the 'glyph' structure to 0 with memset before passing it
782+
to this function for future compatibility.
783+
784+
Since: 5.2.1
785+
786+
See also: [ALLEGRO_GLYPH]

0 commit comments

Comments
 (0)