8#include <utility/graphic/text/font_sized.hpp>
21namespace utility::graphic
25 constexpr int GLYPH_PADDING = 2;
30 , _correspondingFace(face)
39 throw std::runtime_error(
"Invalid FreeType face");
42 if (FT_Set_Pixel_Sizes(ftFace, 0,
_fontSize) != 0) {
43 throw std::runtime_error(
"FT_Set_Pixel_Sizes failed");
46 _ascender = ftFace->size->metrics.ascender / 64.0f;
47 _descender = std::abs(ftFace->size->metrics.descender / 64.0f);
67 if (FT_Set_Pixel_Sizes(ftFace, 0,
_fontSize) != 0) {
68 throw std::runtime_error(
"FT_Set_Pixel_Sizes failed");
71 if (FT_Load_Char(ftFace, codePoint, FT_LOAD_RENDER) != 0) {
72 throw std::runtime_error(
"Glyph not found");
75 FT_GlyphSlot g = ftFace->glyph;
77 throw std::runtime_error(
"Invalid glyph slot");
80 if (g->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY
81 || g->bitmap.num_grays != 256) {
82 throw std::runtime_error(
"Unsupported glyph bitmap format");
85 const int glyphWidth =
static_cast<int>(g->bitmap.width);
86 const int glyphHeight =
static_cast<int>(g->bitmap.rows);
88 if (
_penX + glyphWidth + GLYPH_PADDING
95 if (
_penY + glyphHeight + GLYPH_PADDING
100 const int pitch = g->bitmap.pitch;
101 const int absPitch = std::abs(pitch);
103 for (
int y = 0; y < glyphHeight; ++y) {
104 const uint8_t *srcRow =
nullptr;
107 srcRow =
reinterpret_cast<const uint8_t *
>(g->bitmap.buffer)
110 srcRow =
reinterpret_cast<const uint8_t *
>(g->bitmap.buffer)
111 + (glyphHeight - 1 - y) * absPitch;
114 for (
int x = 0; x < glyphWidth; ++x) {
115 const int dstX =
_penX + x;
116 const int dstY =
_penY + y;
124 glyph.
size = {
static_cast<float>(glyphWidth),
125 static_cast<float>(glyphHeight) };
126 glyph.
bearing = {
static_cast<float>(g->bitmap_left),
127 static_cast<float>(g->bitmap_top) };
128 glyph.
advance =
static_cast<float>(g->advance.x) / 64.0f;
135 glyph.
uvMax = {
static_cast<float>(
_penX + glyphWidth)
137 static_cast<float>(
_penY + glyphHeight)
142 _penX += glyphWidth + GLYPH_PADDING;
151 std::vector<Glyph> glyphs;
152 glyphs.reserve(codePoints.size());
154 for (
auto codePoint: codePoints) {
169 if (FT_Set_Pixel_Sizes(ftFace, 0,
_fontSize) != 0) {
174 if (FT_Load_Char(ftFace, codePoint, FT_LOAD_NO_BITMAP) != 0) {
178 FT_GlyphSlot g = ftFace->glyph;
183 glyph.
size = {
static_cast<float>(g->metrics.width) / 64.0f,
184 static_cast<float>(g->metrics.height) / 64.0f };
185 glyph.
bearing = {
static_cast<float>(g->metrics.horiBearingX) / 64.0f,
186 static_cast<float>(g->metrics.horiBearingY) / 64.0f };
187 glyph.
advance =
static_cast<float>(g->metrics.horiAdvance) / 64.0f;
197 shouldRegenerate =
true;
200 if (shouldRegenerate) {
215 throw std::runtime_error(
"Atlas texture is null");
238 std::vector<uint8_t> resized(
241 const int oldWidth =
static_cast<int>(
_atlasWidth);
244 for (
int y = 0; y < oldHeight; ++y) {
245 const size_t srcRowStart =
static_cast<size_t>(y) * oldWidth;
246 const size_t dstRowStart =
static_cast<size_t>(y) * oldWidth;
249 atlasPixels.begin() +
static_cast<std::ptrdiff_t
>(srcRowStart),
251 +
static_cast<std::ptrdiff_t
>(srcRowStart + oldWidth),
252 resized.begin() +
static_cast<std::ptrdiff_t
>(dstRowStart));
std::map< uint32_t, Glyph > _generatedGlyphs
A map storing the generated glyphs for this font size.
uint32_t _fontSize
The font size in points for this FontSized object.
FontSized(uint32_t fontSize, void *face)
Constructs a FontSized object for a specific font size and corresponding FreeType face.
void resizeAtlas(int newHeight)
Grow the atlas to the given new height, preserving existing glyphs.
std::shared_ptr< Texture > getAtlas(bool shouldRegenerate=false)
Retrieves the texture atlas containing the rendered glyphs for this font size.
std::shared_ptr< Texture > _generatedAtlas
The font size in points for this FontSized object.
int _atlasWidth
The width of the texture atlas.
void generateAtlas()
Generates the texture atlas based on the currently generated glyphs for this font size.
int _penY
The y-coordinate of the pen for glyph placement.
void * _correspondingFace
The corresponding FreeType face associated with this FontSized object.
int _rowHeight
The height of each row in the texture atlas.
int _atlasHeight
The height of the texture atlas.
float _descender
The descender value for the font size, representing the depth of the lowest glyph below the baseline.
Glyph generateGlyph(uint32_t codePoint)
Generates a glyph for a specific Unicode code point and adds it to the texture atlas.
std::vector< Glyph > generateGlyphs(const codePointString &codePoints)
Generates glyphs for a string of Unicode code points and adds them to the texture atlas.
float _ascender
The ascender value for the font size, representing the height of the tallest glyph above the baseline...
Glyph measureGlyph(uint32_t codePoint) const
Compute glyph metrics for a code point without rasterizing or mutating the texture atlas.
bool hasGlyph(uint32_t codePoint) const
Checks whether a glyph has already been generated for this font size.
float _lineHeight
The line height value for the font size, representing the vertical distance between lines of text.
int _penX
The x-coordinate of the pen for glyph placement.
std::vector< uint32_t > codePointString
A type representing a string of Unicode code points.
The Glyph struct represents a single character's visual representation in a font atlas.
math::Vector2F uvMax
Maximum UV coordinates for the glyph in the font atlas.
math::Vector2F size
Size of the glyph in pixels (width and height).
math::Vector2F uvMin
Minimum UV coordinates for the glyph in the font atlas.
math::Vector2F bearing
Bearing of the glyph, representing the offset from the baseline to the top-left corner of the glyph.
float advance
Advance value, specifying the horizontal distance to advance the cursor after rendering the glyph.