1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
/*
* Copyright (c) 2018-2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef VKVG_FONTS_H
#define VKVG_FONTS_H
// disable warning on iostream functions on windows
#define _CRT_SECURE_NO_WARNINGS
#ifdef VKVG_USE_FREETYPE
#include <ft2build.h>
#include FT_FREETYPE_H
#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
#include <freetype/ftlcdfil.h>
#endif
#define FT_CHECK_RESULT(f) \
{ \
FT_Error res = (f); \
if (res != 0) { \
fprintf(stderr, "Fatal : FreeType error is %d in %s at line %d\n", res, __FILE__, __LINE__); \
assert(res == 0); \
} \
}
#else
#include "stb_truetype.h"
#endif
#ifdef VKVG_USE_HARFBUZZ
#include <harfbuzz/hb.h>
#include <harfbuzz/hb-ft.h>
#else
#endif
#ifdef VKVG_USE_FONTCONFIG
#include <fontconfig/fontconfig.h>
#endif
#define FONT_PAGE_SIZE 1024
#define FONT_CACHE_INIT_LAYERS 1
#define FONT_FILE_NAME_MAX_SIZE 1024
#define FONT_NAME_MAX_SIZE 128
#include "vkvg_internal.h"
#include "vkh_buffer.h"
// texture coordinates of one character in font cache array texture.
typedef struct {
vec4 bounds; /* normalized float bounds of character bitmap in font cache texture. */
vec2i16 bmpDiff; /* Difference in pixel between char bitmap top left corner and char glyph*/
uint8_t pageIdx; /* Page index in font cache texture array */
#ifdef VKVG_USE_FREETYPE
FT_Vector advance; /* horizontal or vertical advance */
#else
vec2 advance;
#endif
} _char_ref;
// Current location in font cache texture array for new character addition. Each font holds such structure to locate
// where to upload new chars.
typedef struct {
uint8_t pageIdx; /* Current page number in font cache */
int penX; /* Current X in cache for next char addition */
int penY; /* Current Y in cache for next char addition */
int height; /* Height of current line pointed by this structure */
} _tex_ref_t;
// Loaded font structure, one per size, holds informations for glyphes upload in cache and the lookup table of
// characters.
typedef struct {
#ifdef VKVG_USE_FREETYPE
FT_F26Dot6 charSize; /* Font size*/
FT_Face face; /* FreeType face*/
#else
uint32_t charSize; /* Font size in pixel */
float scale; /* scale factor for the given size */
int ascent; /* unscalled stb font metrics */
int descent;
int lineGap;
#endif
#ifdef VKVG_USE_HARFBUZZ
hb_font_t *hb_font; /* HarfBuzz font instance*/
#endif
_char_ref **charLookup; /* Lookup table of characteres in cache, if not found, upload is queued*/
_tex_ref_t curLine; /* tex coord where to add new char bmp's */
} _vkvg_font_t;
/* Font identification structure */
typedef struct {
char **names; /* Resolved Input names to this font by fontConfig or custom name set by @ref vkvg_load_from_path*/
uint32_t namesCount; /* Count of resolved names by fontConfig */
unsigned char *fontBuffer; /* stb_truetype in memory buffer */
long fontBufSize; /* */
char *fontFile; /* Font file full path*/
#ifndef VKVG_USE_FREETYPE
stbtt_fontinfo stbInfo; /* stb_truetype structure */
int ascent; /* unscalled stb font metrics */
int descent;
int lineGap;
#endif
uint32_t sizeCount; /* available font size loaded */
_vkvg_font_t *sizes; /* loaded font size array */
} _vkvg_font_identity_t;
// Font cache global structure, entry point for all font related operations.
typedef struct {
#ifdef VKVG_USE_FREETYPE
FT_Library library; /* FreeType library*/
#else
#endif
#ifdef VKVG_USE_FONTCONFIG
FcConfig *config; /* Font config, used to find font files by font names*/
#endif
int stagingX; /* x pen in host buffer */
uint8_t *hostBuff; /* host memory where bitmaps are first loaded */
VkCommandBuffer cmd; /* vulkan command buffer for font textures upload */
vkh_buffer_t buff; /* stagin buffer */
VkhImage texture; /* 2d array texture used by contexts to draw characteres */
VkFormat texFormat; /* Format of the fonts texture array */
uint8_t texPixelSize; /* Size in byte of a single pixel in a font texture */
uint8_t texLength; /* layer count of 2d array texture, starts with FONT_CACHE_INIT_LAYERS count and increased when
needed */
int *pensY; /* array of current y pen positions for each texture in cache 2d array */
VkFence uploadFence; /* Signaled when upload is finished */
mtx_t mutex; /* font cache global mutex, used only if device is in thread aware mode (see:
vkvg_device_set_thread_aware) */
_vkvg_font_identity_t *fonts; /* Loaded fonts structure array */
int32_t fontsCount; /* Loaded fonts array count*/
} _font_cache_t;
#define LOCK_FONTCACHE(dev) \
if (dev->threadAware) \
mtx_lock(&dev->fontCache->mutex);
#define UNLOCK_FONTCACHE(dev) \
if (dev->threadAware) \
mtx_unlock(&dev->fontCache->mutex);
// Precompute everything necessary to measure and draw one line of text, usefull to draw the same text multiple times.
typedef struct _vkvg_text_run_t {
_vkvg_font_identity_t *fontId; /* vkvg font structure pointer */
_vkvg_font_t *font; /* vkvg font structure pointer */
VkvgDevice dev; /* vkvg device associated with this text run */
vkvg_text_extents_t extents; /* store computed text extends */
const char *text; /* utf8 char array of text*/
unsigned int glyph_count; /* Total glyph count */
#ifdef VKVG_USE_HARFBUZZ
hb_buffer_t *hbBuf; /* HarfBuzz buffer of text */
hb_glyph_position_t *glyphs; /* HarfBuzz computed glyph positions array */
#else
vkvg_glyph_info_t *glyphs; /* computed glyph positions array */
#endif
} vkvg_text_run_t;
// Create font cache.
void _fonts_cache_create(VkvgDevice dev);
// Release all ressources of font cache.
void _font_cache_destroy(VkvgDevice dev);
_vkvg_font_identity_t *_font_cache_add_font_identity(VkvgContext ctx, const char *fontFile, const char *name);
bool _font_cache_load_font_file_in_memory(_vkvg_font_identity_t *fontId);
// Draw text
void _font_cache_show_text(VkvgContext ctx, const char *text);
// Get text dimmensions
void _font_cache_text_extents(VkvgContext ctx, const char *text, int length, vkvg_text_extents_t *extents);
// Get font global dimmensions
void _font_cache_font_extents(VkvgContext ctx, vkvg_font_extents_t *extents);
// Create text object that could be drawn multiple times minimizing harfbuzz and compute processing.
void _font_cache_create_text_run(VkvgContext ctx, const char *text, int length, VkvgText textRun);
// Release ressources held by a text run.
void _font_cache_destroy_text_run(VkvgText textRun);
// Draw text run
void _font_cache_show_text_run(VkvgContext ctx, VkvgText tr);
// update context font cache descriptor set
void _font_cache_update_context_descset(VkvgContext ctx);
#endif
|