Sparkle 0.0.1
Loading...
Searching...
No Matches
spk_font.hpp
1// spk_font.hpp
2#pragma once
3
4#include <array>
5#include <cmath>
6#include <cstddef>
7#include <cstdint>
8#include <filesystem>
9#include <stdexcept>
10#include <string>
11#include <unordered_map>
12#include <vector>
13
14#include "structure/design_pattern/spk_contract_provider.hpp"
15#include "structure/opengl/spk_texture_object.hpp"
16#include "utils/spk_file_utils.hpp"
17
18#include "stb_truetype.h"
19
20namespace spk
21{
32 class Font
33 {
34 public:
39 struct Size
40 {
44 size_t glyph;
48 size_t outline;
49
55 bool operator==(const Size &p_other) const noexcept
56 {
57 return glyph == p_other.glyph && outline == p_other.outline;
58 }
59 };
60
61 private:
62 struct SizeHasher
63 {
64 std::size_t operator()(const Size &p_s) const noexcept
65 {
66 std::size_t h1 = std::hash<std::size_t>{}(p_s.glyph);
67 std::size_t h2 = std::hash<std::size_t>{}(p_s.outline);
68 return h1 ^ (h2 + 0x9e3779b97f4a7c15ULL + (h1 << 6) + (h1 >> 2));
69 }
70 };
71
72 public:
78 {
79 public:
104
108 using EditionContract = spk::ContractProvider::Contract;
113
118 struct Glyph
119 {
123 std::array<spk::Vector2Int, 4> positions;
127 std::array<spk::Vector2, 4> uvs;
131 spk::Vector2Int step;
135 spk::Vector2Int baselineOffset;
139 spk::Vector2UInt size;
143 wchar_t codepoint = 0;
144
148 static inline std::array<unsigned int, 6> indexesOrder = {0, 1, 2, 2, 1, 3};
149
154 void applyRatioOnUV(const spk::Vector2 &p_scaleRatio)
155 {
156 for (size_t i = 0; i < 4; i++)
157 {
158 uvs[i] *= p_scaleRatio;
159 }
160 }
161 };
162
163 private:
164 struct RasterizedGlyph
165 {
166 std::vector<uint8_t> pixels;
167 spk::Vector2UInt size{0, 0};
168 spk::Vector2Int offset{0, 0};
169 int advance = 0;
170
171 bool valid() const
172 {
173 return pixels.empty() == false;
174 }
175 };
176
177 class KerningCache
178 {
179 private:
180 using KerningMap = std::unordered_map<wchar_t, int>;
181 std::unordered_map<wchar_t, KerningMap> _cache;
182
183 public:
184 int get(const stbtt_fontinfo *p_fontInfo, const wchar_t p_previous, const wchar_t p_current, float p_scale);
185 };
186
187 class AtlasPacker
188 {
189 private:
190 enum class Quadrant
191 {
192 TopLeft,
193 TopRight,
194 DownLeft,
195 DownRight
196 };
197
198 Quadrant _currentQuadrant = Quadrant::TopLeft;
199 spk::Vector2Int _quadrantAnchor = {0, 0};
200 spk::Vector2UInt _quadrantSize = {0, 0};
201 spk::Vector2Int _nextGlyphAnchor = {0, 0};
202 spk::Vector2Int _nextLineAnchor = {0, 0};
203
204 void _resizeTexture(Bitmap &p_bitmap, const spk::Vector2UInt &p_size);
205
206 public:
207 AtlasPacker() = default;
208
209 void reset(const spk::Vector2UInt &p_initialSize);
210 spk::Vector2UInt textureSize(const Bitmap &p_bitmap) const;
211 spk::Vector2Int allocate(Bitmap &p_bitmap, const spk::Vector2UInt &p_glyphSize);
212 void blit(Bitmap &p_bitmap, const uint8_t *p_pixelsToApply, const spk::Vector2Int &p_glyphPosition, const spk::Vector2UInt &p_glyphSize);
213 };
214
215 const stbtt_fontinfo *_fontInfo;
216 Size _fontSize;
217 std::unordered_map<wchar_t, Glyph> _glyphs;
218 Glyph _unknownGlyph;
219 AtlasPacker _atlas;
220 mutable KerningCache _kerningCache;
221 spk::ContractProvider _onEditionContractProvider;
222
223 float _scale() const;
224 void _rescaleGlyphs(const spk::Vector2 &p_scaleRatio);
225 RasterizedGlyph _rasterizeGlyph(const wchar_t &p_glyphChar) const;
226 Glyph _placeGlyph(const RasterizedGlyph &p_raster, const wchar_t &p_glyphChar);
227 void _cacheGlyph(const wchar_t &p_glyphChar, Glyph p_glyph);
228 void _loadGlyph(const wchar_t &p_glyphChar);
229 void _onSynchronize() override;
230
231 public:
237 Bitmap(const stbtt_fontinfo *p_fontInfo, const Size &p_fontSize);
238
245
251 const Glyph &operator[](const wchar_t &p_glyphChar);
252
257 int lineHeight() const;
264 int kerning(const wchar_t p_previous, const wchar_t p_current) const;
269 void preloadGlyphs(const std::wstring &p_glyphs);
270 };
271
272 private:
273 std::vector<uint8_t> _fontData;
274 stbtt_fontinfo _fontInfo;
275 std::unordered_map<Size, Bitmap, SizeHasher> _loadedFonts;
276
277 public:
282 Font(const std::vector<uint8_t> &p_rawData);
283
289 static Font fromFile(const std::filesystem::path &p_path);
295 static Font fromRawData(const std::vector<uint8_t> &p_rawData);
296
302 Bitmap &bitmap(const Size &p_fontSize);
303 };
304}
Font atlas texture and glyph metadata for a specific size.
Definition spk_font.hpp:78
int kerning(const wchar_t p_previous, const wchar_t p_current) const
Returns kerning adjustment between two glyphs.
Definition spk_font.cpp:376
spk::OpenGL::TextureObject::Wrapper Wrapper
Texture wrapper type for the bitmap.
Definition spk_font.hpp:99
spk::OpenGL::TextureObject::Mipmap Mipmap
Texture mipmap type for the bitmap.
Definition spk_font.hpp:103
spk::ContractProvider::Contract EditionContract
Contract type returned by edition subscriptions.
Definition spk_font.hpp:108
spk::OpenGL::TextureObject::Filtering Filtering
Texture filtering type for the bitmap.
Definition spk_font.hpp:87
void preloadGlyphs(const std::wstring &p_glyphs)
Preloads glyphs into the bitmap atlas.
Definition spk_font.cpp:347
EditionContract subscribeToEdition(const EditionJob &p_job)
Subscribes to bitmap edition notifications.
Definition spk_font.cpp:333
spk::OpenGL::TextureObject::Wrap Wrap
Texture wrap type for the bitmap.
Definition spk_font.hpp:95
spk::ContractProvider::Job EditionJob
Job type invoked on bitmap edits.
Definition spk_font.hpp:112
const Glyph & operator[](const wchar_t &p_glyphChar)
Returns glyph data for the requested codepoint.
Definition spk_font.cpp:338
Bitmap(const stbtt_fontinfo *p_fontInfo, const Size &p_fontSize)
Builds a bitmap atlas for a font size.
Definition spk_font.cpp:316
spk::OpenGL::TextureObject::Format Format
Texture format type for the bitmap.
Definition spk_font.hpp:83
spk::OpenGL::TextureObject::Filter Filter
Texture filter type for the bitmap.
Definition spk_font.hpp:91
int lineHeight() const
Returns the line height for this font size.
Definition spk_font.cpp:360
static Font fromFile(const std::filesystem::path &p_path)
Loads a font from file.
Definition spk_font.cpp:390
Font(const std::vector< uint8_t > &p_rawData)
Builds a font from raw font data.
Definition spk_font.cpp:381
static Font fromRawData(const std::vector< uint8_t > &p_rawData)
Loads a font from raw data.
Definition spk_font.cpp:395
Bitmap & bitmap(const Size &p_fontSize)
Returns a bitmap atlas for the requested size.
Definition spk_font.cpp:400
CPU-staged 2D texture with activation and parameter controls.
Definition spk_texture_object.hpp:25
spk::ActivationStatus Mipmap
Indicates whether mipmaps are active.
Definition spk_texture_object.hpp:89
void _onSynchronize() override
Synchronizes CPU-side data with the GPU texture.
Definition spk_texture_object.cpp:99
Wrap
Texture coordinate wrapping strategies.
Definition spk_texture_object.hpp:66
Filtering
Texture sampling algorithms for minification/magnification.
Definition spk_texture_object.hpp:43
Format
Supported GPU pixel formats.
Definition spk_texture_object.hpp:29
spk::Vector2UInt size() const
Returns texture dimensions.
Definition spk_texture_object.cpp:325
typename Contract::Job Job
Definition spk_contract_provider.hpp:267
Glyph quad data and layout metrics.
Definition spk_font.hpp:119
spk::Vector2Int step
Glyph advance step.
Definition spk_font.hpp:131
wchar_t codepoint
Unicode codepoint for this glyph.
Definition spk_font.hpp:143
spk::Vector2Int baselineOffset
Baseline offset for glyph placement.
Definition spk_font.hpp:135
spk::Vector2UInt size
Glyph dimensions in pixels.
Definition spk_font.hpp:139
std::array< spk::Vector2Int, 4 > positions
Quad positions for the glyph.
Definition spk_font.hpp:123
void applyRatioOnUV(const spk::Vector2 &p_scaleRatio)
Applies a scaling ratio to glyph UVs.
Definition spk_font.hpp:154
std::array< spk::Vector2, 4 > uvs
Quad UV coordinates for the glyph.
Definition spk_font.hpp:127
static std::array< unsigned int, 6 > indexesOrder
Index order used to render the glyph quad.
Definition spk_font.hpp:148
Defines glyph and outline sizes for a font bitmap.
Definition spk_font.hpp:40
bool operator==(const Size &p_other) const noexcept
Compares sizes for equality.
Definition spk_font.hpp:55
size_t outline
Outline size in pixels.
Definition spk_font.hpp:48
size_t glyph
Glyph size in pixels.
Definition spk_font.hpp:44
Filtering modes applied on minification and magnification.
Definition spk_texture_object.hpp:53
Wrapping policy along each texture axis.
Definition spk_texture_object.hpp:77