Skip to content

Commit bf4c2b6

Browse files
committed
Fixed dynamic resizing issue for font
1 parent 16fecc9 commit bf4c2b6

File tree

6 files changed

+111
-111
lines changed

6 files changed

+111
-111
lines changed

engine/render/renderer/platform/vulkan/Font.cpp

Lines changed: 74 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,48 +12,41 @@
1212
#include <utils/Defer.h>
1313
#include <utils/Logging.h>
1414

15-
#include "Context.h"
1615
#include "render/renderer/statics/Statics.h"
1716
#include "utils/Descriptor.h"
1817
#include "utils/TypeAdaptor.h"
1918

19+
#define CAST_F(val) static_cast<float>(val)
20+
2021
namespace Siege::Vulkan
2122
{
2223
Font::Font(const char* filePath)
2324
{
24-
auto device = Context::GetCurrentDevice();
25+
FT_Face fontFace;
2526

26-
auto ft = Statics::GetFontLib();
27+
CC_ASSERT(!FT_New_Face(Statics::GetFontLib(), filePath, 0, &fontFace), "Failed to load font!")
2728

28-
FT_Face fontFace;
29+
FT_Set_Pixel_Sizes(fontFace, 0, 64);
2930

30-
CC_ASSERT(!FT_New_Face(ft, filePath, 0, &fontFace), "Failed to load font!")
31+
Utils::Offset2D textPadding = {1, 2};
3132

32-
uint8_t* buffer = new uint8_t[width * height];
33+
uint8_t* buffer = new uint8_t[MAX_ATLAS_WIDTH * MAX_ATLAS_HEIGHT];
3334
defer([buffer]() { delete[] buffer; });
35+
memset(buffer, 0, sizeof(uint8_t) * MAX_ATLAS_WIDTH * MAX_ATLAS_HEIGHT);
3436

35-
memset(buffer, 0, sizeof(uint8_t) * width * height);
37+
extent = PopulateGlyphs(fontFace, textPadding, buffer);
3638

3739
texture = Texture2D(filePath,
3840
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,
4244
Texture2D::Usage::TEX_USAGE_FONT);
4345

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);
4947

5048
id = INTERN_STR(filePath);
5149

52-
for (size_t i = 32; i < 126; i++)
53-
{
54-
AddChar(static_cast<unsigned char>(i), fontFace);
55-
}
56-
5750
info.textureInfo = texture.GetInfo();
5851
}
5952

@@ -64,102 +57,102 @@ Font::~Font()
6457

6558
void Font::Free()
6659
{
67-
auto device = Context::GetVkLogicalDevice();
68-
69-
if (device == nullptr) return;
70-
71-
vkDestroySampler(device, info.sampler, nullptr);
72-
7360
texture.Free();
7461

75-
info = {{}, nullptr};
62+
info = {{}};
7663
}
7764

7865
void Font::Swap(Font& other)
7966
{
8067
auto tmpId = id;
81-
auto tmpWidth = width;
82-
auto tmpHeight = height;
68+
auto tmpAtlasExtent = extent;
8369
auto tmpGlyphs = glyphs;
84-
auto tmpSpaceFilledX = spaceFilledX;
85-
auto tmpSpaceFilledY = spaceFilledY;
86-
auto tmpMaxHeight = maxHeight;
8770
auto tmpInfo = info;
8871
auto tmpTexture = std::move(texture);
8972

9073
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;
9675
glyphs = other.glyphs;
9776
info = other.info;
9877
texture = std::move(other.texture);
9978

10079
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;
10681
other.glyphs = tmpGlyphs;
10782
other.info = tmpInfo;
10883
other.texture = std::move(tmpTexture);
10984
}
11085

111-
void Font::AddChar(const unsigned char c, FontFace fontFace)
86+
Utils::Extent2D Font::PopulateGlyphs(FontFace fontFace, Utils::Offset2D padding, uint8_t* buffer)
11287
{
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};
11489

115-
CC_ASSERT(!FT_Load_Char(fontFace, c, FT_LOAD_RENDER),
116-
String("Unable to load char: ") + String(c))
90+
uint32_t offset {0};
11791

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;
11998

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};
122100

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;
125102

126-
unsigned long size = glyph->bitmap.width * glyph->bitmap.rows;
103+
float atlasX = x * !exceededWidth;
104+
float atlasY = y + (exceededWidth * rowHeight);
127105

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};
142116

143-
if (size == 0) return;
117+
rowHeight = (height > rowHeight) * height + (height <= rowHeight) * rowHeight;
144118

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));
148121

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;
153124

154-
CC_ASSERT(!exceededWidth || !exceededHeight, "Cannot add any more images to the atlas!")
125+
auto size = sizeof(uint8_t) * width * height;
155126

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+
}
158130

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};
163132
}
164133

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+
}
165158
} // namespace Siege::Vulkan

engine/render/renderer/platform/vulkan/Font.h

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ class Font
2929
{
3030
public:
3131

32-
// Constexpr declarations
33-
static constexpr uint32_t INITIAL_FONT_ATLAS_WIDTH {512};
34-
static constexpr uint32_t INITIAL_FONT_ATLAS_HEIGHT {512};
35-
3632
// Structs
3733

3834
/**
@@ -41,7 +37,6 @@ class Font
4137
struct Info
4238
{
4339
Texture2D::Info textureInfo {};
44-
VkSampler sampler {nullptr};
4540
};
4641

4742
/**
@@ -53,15 +48,14 @@ class Font
5348
{
5449
float uvxMin {0};
5550
float uvyMin {0};
56-
float uvxMax {0};
57-
float uvyMax {0};
5851
float width {0};
5952
float height {0};
6053
float widthNormalised {0};
6154
float heightNormalised {0};
6255
float bearingX {0};
6356
float bearingY {0};
64-
unsigned int advance {0};
57+
signed long advance {0};
58+
unsigned long bufferOffset {0};
6559
};
6660

6761
// 'Structors
@@ -153,27 +147,34 @@ class Font
153147

154148
private:
155149

150+
// Constexpr declarations
151+
static constexpr uint32_t MAX_ATLAS_WIDTH {512};
152+
static constexpr uint32_t MAX_ATLAS_HEIGHT {1024};
153+
156154
/**
157155
* Swaps the values of two Fonts
158156
* @param other the Font to swap values with
159157
*/
160158
void Swap(Font& other);
161159

162160
/**
163-
* Adds a character glyph to the font atlas
164-
* @param c the character to add
161+
* Populates the font with all glyphs stored in the ttf file
162+
* @param fontFace the font face used to render the characters
163+
* @param padding padding between the characters in the font
164+
* @param buffer a buffer of pixels to copy data from the font face into
165+
* @return the width and height of the texture
165166
*/
166-
void AddChar(const unsigned char c, FontFace fontFace);
167-
168-
uint32_t width {INITIAL_FONT_ATLAS_WIDTH};
169-
uint32_t height {INITIAL_FONT_ATLAS_HEIGHT};
167+
Utils::Extent2D PopulateGlyphs(FontFace fontFace, Utils::Offset2D padding, uint8_t* buffer);
170168

171-
SArray<Glyph, 256> glyphs;
169+
/**
170+
* Populates the texture atlas with the glyphs collected from PopulateGlyphs
171+
* @param buffer the pixel buffer storing our glyph pixels
172+
*/
173+
void PopulateTextureAtlas(uint8_t* buffer);
172174

173-
int32_t spaceFilledX {0};
174-
int32_t spaceFilledY {0};
175+
Utils::Extent2D extent {};
175176

176-
uint32_t maxHeight {0};
177+
SArray<Glyph, 256> glyphs;
177178

178179
Hash::StringId id {0};
179180
Texture2D texture;

engine/render/renderer/platform/vulkan/LogicalDevice.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ LogicalDevice::LogicalDevice(const Surface& surface, PhysicalDevice& physDevice)
8080
GET_UNIQUE_QUEUES(queueCreateInfos, graphicsIdx, presentIdx)
8181

8282
auto deviceExtensions = Vulkan::Config::deviceExtensions;
83+
auto layers = Vulkan::Config::validationLayers;
8384

8485
CREATE_LOGICAL_DEVICE(
8586
vkPhysicalDevice,

engine/render/renderer/platform/vulkan/utils/Types.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,12 @@ struct Offset3D
213213
int32_t depth {0};
214214
};
215215

216+
struct Offset2D
217+
{
218+
int32_t width {0};
219+
int32_t height {0};
220+
};
221+
216222
struct Image2DConfig
217223
{
218224
ImageFormat format;

engine/utils/collections/HeapArray.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,6 @@ class MHArray
315315
void Clear()
316316
{
317317
count = 0;
318-
memset(data, 0, sizeof(T) * size);
319318
bitField.Clear();
320319
}
321320

0 commit comments

Comments
 (0)