12
12
#include < utils/Defer.h>
13
13
#include < utils/Logging.h>
14
14
15
- #include " Context.h"
16
15
#include " render/renderer/statics/Statics.h"
17
16
#include " utils/Descriptor.h"
18
17
#include " utils/TypeAdaptor.h"
19
18
19
+ #define CAST_F (val ) static_cast <float >(val)
20
+
20
21
namespace Siege ::Vulkan
21
22
{
22
23
Font::Font (const char * filePath)
23
24
{
24
- auto device = Context::GetCurrentDevice () ;
25
+ FT_Face fontFace ;
25
26
26
- auto ft = Statics::GetFontLib ();
27
+ CC_ASSERT (! FT_New_Face ( Statics::GetFontLib (), filePath, 0 , &fontFace), " Failed to load font! " )
27
28
28
- FT_Face fontFace;
29
+ FT_Set_Pixel_Sizes ( fontFace, 0 , 64 ) ;
29
30
30
- CC_ASSERT (! FT_New_Face (ft, filePath, 0 , &fontFace), " Failed to load font! " )
31
+ Utils::Offset2D textPadding = { 1 , 2 };
31
32
32
- uint8_t * buffer = new uint8_t [width * height ];
33
+ uint8_t * buffer = new uint8_t [MAX_ATLAS_WIDTH * MAX_ATLAS_HEIGHT ];
33
34
defer ([buffer]() { delete[] buffer; });
35
+ memset (buffer, 0 , sizeof (uint8_t ) * MAX_ATLAS_WIDTH * MAX_ATLAS_HEIGHT);
34
36
35
- memset (buffer, 0 , sizeof ( uint8_t ) * width * height );
37
+ extent = PopulateGlyphs (fontFace, textPadding, buffer );
36
38
37
39
texture = Texture2D (filePath,
38
40
buffer,
39
- sizeof (uint8_t ) * width * height,
40
- width,
41
- height,
41
+ sizeof (uint8_t ) * extent. width * extent. height ,
42
+ extent. width ,
43
+ extent. height ,
42
44
Texture2D::Usage::TEX_USAGE_FONT);
43
45
44
- VkSamplerCreateInfo samplerInfo =
45
- Utils::Descriptor::SamplerCreateInfo (VK_FILTER_LINEAR,
46
- VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
47
-
48
- vkCreateSampler (device->GetDevice (), &samplerInfo, nullptr , &info.sampler );
46
+ PopulateTextureAtlas (buffer);
49
47
50
48
id = INTERN_STR (filePath);
51
49
52
- for (size_t i = 32 ; i < 126 ; i++)
53
- {
54
- AddChar (static_cast <unsigned char >(i), fontFace);
55
- }
56
-
57
50
info.textureInfo = texture.GetInfo ();
58
51
}
59
52
@@ -64,102 +57,102 @@ Font::~Font()
64
57
65
58
void Font::Free ()
66
59
{
67
- auto device = Context::GetVkLogicalDevice ();
68
-
69
- if (device == nullptr ) return ;
70
-
71
- vkDestroySampler (device, info.sampler , nullptr );
72
-
73
60
texture.Free ();
74
61
75
- info = {{}, nullptr };
62
+ info = {{}};
76
63
}
77
64
78
65
void Font::Swap (Font& other)
79
66
{
80
67
auto tmpId = id;
81
- auto tmpWidth = width;
82
- auto tmpHeight = height;
68
+ auto tmpAtlasExtent = extent;
83
69
auto tmpGlyphs = glyphs;
84
- auto tmpSpaceFilledX = spaceFilledX;
85
- auto tmpSpaceFilledY = spaceFilledY;
86
- auto tmpMaxHeight = maxHeight;
87
70
auto tmpInfo = info;
88
71
auto tmpTexture = std::move (texture);
89
72
90
73
id = other.id ;
91
- width = other.width ;
92
- height = other.height ;
93
- spaceFilledX = other.spaceFilledX ;
94
- spaceFilledY = other.spaceFilledY ;
95
- maxHeight = other.maxHeight ;
74
+ extent = other.extent ;
96
75
glyphs = other.glyphs ;
97
76
info = other.info ;
98
77
texture = std::move (other.texture );
99
78
100
79
other.id = tmpId;
101
- other.width = tmpWidth;
102
- other.height = tmpHeight;
103
- other.spaceFilledX = tmpSpaceFilledX;
104
- other.spaceFilledY = tmpSpaceFilledY;
105
- other.maxHeight = tmpMaxHeight;
80
+ other.extent = tmpAtlasExtent;
106
81
other.glyphs = tmpGlyphs;
107
82
other.info = tmpInfo;
108
83
other.texture = std::move (tmpTexture);
109
84
}
110
85
111
- void Font::AddChar ( const unsigned char c, FontFace fontFace )
86
+ Utils::Extent2D Font::PopulateGlyphs (FontFace fontFace, Utils::Offset2D padding, uint8_t * buffer )
112
87
{
113
- FT_Set_Pixel_Sizes (fontFace, 0 , 64 ) ;
88
+ float x { 0 . f }, y { 0 . f }, rowHeight { 0 . f }, maxX { 0 . f }, maxY { 0 . f } ;
114
89
115
- CC_ASSERT (!FT_Load_Char (fontFace, c, FT_LOAD_RENDER),
116
- String (" Unable to load char: " ) + String (c))
90
+ uint32_t offset {0 };
117
91
118
- auto glyph = fontFace->glyph ;
92
+ for (unsigned char c = 32 ; c < 126 ; c++)
93
+ {
94
+ auto message = String (" Unable to load char: " ) + String (c);
95
+ CC_ASSERT (!FT_Load_Char (fontFace, c, FT_LOAD_RENDER), message.Str ())
96
+
97
+ auto glyph = fontFace->glyph ;
119
98
120
- bool exceededWidth = (glyph->bitmap .width + spaceFilledX) >= width;
121
- bool exceededHeight = (glyph->bitmap .rows + spaceFilledY) >= height;
99
+ uint32_t width {glyph->bitmap .width }, height {glyph->bitmap .rows };
122
100
123
- int32_t positionXInAtlas = (spaceFilledX) * !exceededWidth;
124
- int32_t positionYInAtlas = spaceFilledY + static_cast <int32_t >(exceededWidth * maxHeight);
101
+ bool exceededWidth = (width + x) >= MAX_ATLAS_WIDTH;
125
102
126
- unsigned long size = glyph->bitmap .width * glyph->bitmap .rows ;
103
+ float atlasX = x * !exceededWidth;
104
+ float atlasY = y + (exceededWidth * rowHeight);
127
105
128
- glyphs[c] = {
129
- static_cast <float >(static_cast <float >(positionXInAtlas + 1 ) / static_cast <float >(width)),
130
- static_cast <float >(static_cast <float >(positionYInAtlas + 2 ) / static_cast <float >(height)),
131
- static_cast <float >(static_cast <float >(glyph->bitmap .width + positionXInAtlas + 1 ) /
132
- static_cast <float >(width)),
133
- static_cast <float >(static_cast <float >(glyph->bitmap .rows + positionYInAtlas + 2 ) /
134
- static_cast <float >(height)),
135
- static_cast <float >(glyph->bitmap .width ),
136
- static_cast <float >(glyph->bitmap .rows ),
137
- static_cast <float >(glyph->bitmap .width ) / static_cast <float >(width),
138
- static_cast <float >(glyph->bitmap .rows ) / static_cast <float >(height),
139
- static_cast <float >(glyph->bitmap_left ),
140
- static_cast <float >(glyph->bitmap_top ),
141
- static_cast <unsigned int >(glyph->advance .x )};
106
+ glyphs[c] = {atlasX + padding.width ,
107
+ atlasY + padding.height ,
108
+ CAST_F (width),
109
+ CAST_F (height),
110
+ CAST_F (width),
111
+ CAST_F (height),
112
+ CAST_F (glyph->bitmap_left ),
113
+ CAST_F (glyph->bitmap_top ),
114
+ glyph->advance .x ,
115
+ offset};
142
116
143
- if (size == 0 ) return ;
117
+ rowHeight = (height > rowHeight) * height + (height <= rowHeight) * rowHeight ;
144
118
145
- Utils::Extent3D imageExtent {static_cast <uint32_t >(glyph->bitmap .width ),
146
- static_cast <uint32_t >(glyph->bitmap .rows ),
147
- 1 };
119
+ x = ((!exceededWidth * (width + x)) + (exceededWidth * width)) + padding.width ;
120
+ y += (exceededWidth * (rowHeight + padding.height ));
148
121
149
- texture.CopyToRegion (glyph->bitmap .buffer ,
150
- size,
151
- imageExtent,
152
- {positionXInAtlas + 1 , positionYInAtlas + 2 });
122
+ maxX = (x > maxX) * x + (x <= maxX) * maxX;
123
+ maxY = (y > maxY) * (y + rowHeight + padding.height ) + (y <= maxY) * maxY;
153
124
154
- CC_ASSERT (!exceededWidth || !exceededHeight, " Cannot add any more images to the atlas! " )
125
+ auto size = sizeof ( uint8_t ) * width * height;
155
126
156
- maxHeight = ((glyph->bitmap .rows > maxHeight) * glyph->bitmap .rows ) +
157
- ((glyph->bitmap .rows <= maxHeight) * maxHeight);
127
+ memcpy (buffer + offset, glyph->bitmap .buffer , size);
128
+ offset += size;
129
+ }
158
130
159
- spaceFilledX = ((!exceededWidth * (glyph->bitmap .width + spaceFilledX)) +
160
- (exceededWidth * glyph->bitmap .width )) +
161
- 1 ;
162
- spaceFilledY += (exceededWidth * (maxHeight + 2 ));
131
+ return {(uint32_t ) maxX + padding.width , (uint32_t ) maxY + padding.height };
163
132
}
164
133
134
+ void Font::PopulateTextureAtlas (uint8_t * buffer)
135
+ {
136
+ for (unsigned char c = 32 ; c < 126 ; c++)
137
+ {
138
+ auto & glyph = glyphs[c];
139
+ float xPos {glyph.uvxMin }, yPos {glyph.uvyMin };
140
+
141
+ glyph.uvxMin /= CAST_F (extent.width );
142
+ glyph.uvyMin /= CAST_F (extent.height );
143
+
144
+ glyph.widthNormalised /= CAST_F (extent.width );
145
+ glyph.heightNormalised /= CAST_F (extent.height );
146
+
147
+ Utils::Extent3D imageExtent {(uint32_t ) glyph.width , (uint32_t ) glyph.height , 1 };
148
+
149
+ size_t size = sizeof (uint8_t ) * glyph.width * glyph.height ;
150
+ if (size == 0 ) continue ;
151
+
152
+ texture.CopyToRegion (buffer + glyph.bufferOffset ,
153
+ size,
154
+ imageExtent,
155
+ {int32_t (xPos), int32_t (yPos)});
156
+ }
157
+ }
165
158
} // namespace Siege::Vulkan
0 commit comments