Skip to content

Commit c2b71bd

Browse files
committed
Release measured glyphs and reuse text data
FreeType glyphs created during measurement were never released, and rendering copied text and cached metrics unnecessarily. Release the surviving glyph on success and failure, and borrow data for the duration of each call.
1 parent ddca27f commit c2b71bd

1 file changed

Lines changed: 38 additions & 36 deletions

File tree

‎FreeTypeWrapper/Source/FreeTypeConnector.cpp‎

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -101,20 +101,20 @@ namespace FreeType
101101
using namespace std;
102102
using namespace LLUtils;
103103

104-
const auto textCreateParams = measureParams.createParams;
105-
const BitFlags<TextCreateFlags> createFlags{ textCreateParams.flags };
106-
const bool useMetaText = createFlags.test(TextCreateFlags::UseMetaText);
104+
const auto& textCreateParams = measureParams.createParams;
105+
const BitFlags<TextCreateFlags> createFlags{textCreateParams.flags};
106+
const bool useMetaText = createFlags.test(TextCreateFlags::UseMetaText);
107107
const bool lineEndFixedWidth = createFlags.test(TextCreateFlags::LineEndFixedWidth);
108-
const bool usebidiText = createFlags.test(TextCreateFlags::Bidirectional);
108+
const bool usebidiText = createFlags.test(TextCreateFlags::Bidirectional);
109109

110-
const string_type text = textCreateParams.text;
111-
const string_type& fontPath = textCreateParams.fontPath;
112-
const uint16_t fontSize = textCreateParams.fontSize;
113-
const uint32_t OutlineWidth = textCreateParams.outlineWidth;
114-
FT_Render_Mode textRenderMOde = FreeTypeRenderer::GetRenderMode(textCreateParams.renderMode);
110+
const string_type& text = textCreateParams.text;
111+
const string_type& fontPath = textCreateParams.fontPath;
112+
const uint16_t fontSize = textCreateParams.fontSize;
113+
const uint32_t OutlineWidth = textCreateParams.outlineWidth;
114+
FT_Render_Mode textRenderMOde = FreeTypeRenderer::GetRenderMode(textCreateParams.renderMode);
115115
FT_Render_Mode outlineRenderMode = FreeTypeRenderer::GetRenderMode(textCreateParams.renderMode);
116-
const bool renderOutline = OutlineWidth > 0;
117-
mesureResult = {};
116+
const bool renderOutline = OutlineWidth > 0;
117+
mesureResult = {};
118118
if (measureParams.createParams.text.empty() == false)
119119
{
120120

@@ -201,6 +201,13 @@ namespace FreeType
201201
if (FT_Error error = FT_Get_Glyph(face->glyph, &glyph))
202202
LL_EXCEPTION(LLUtils::Exception::ErrorCode::RuntimeError, std::format("FreeType error {0}, {1}", error, GenerateFreeTypeErrorString("unable to render glyph",error)));
203203

204+
// Bitmap conversion replaces the handle; release the surviving glyph even if measurement fails.
205+
struct GlyphCleanup
206+
{
207+
FT_Glyph& glyph;
208+
~GlyphCleanup() { FT_Done_Glyph(glyph); }
209+
} cleanup{glyph};
210+
204211
if (glyph->format != FT_GLYPH_FORMAT_BITMAP)
205212
{
206213
if (FT_Error error = FT_Glyph_To_Bitmap(&glyph, textRenderMOde, nullptr, true); error != FT_Err_Ok)
@@ -288,16 +295,16 @@ namespace FreeType
288295
)
289296
{
290297
using namespace std;
291-
const string_type text = textCreateParams.text;
292-
const string_type& fontPath = textCreateParams.fontPath;
293-
const uint16_t fontSize = textCreateParams.fontSize;
294-
const uint32_t OutlineWidth = textCreateParams.outlineWidth;
295-
const LLUtils::Color outlineColor = textCreateParams.outlineColor;
298+
const string_type& text = textCreateParams.text;
299+
const string_type& fontPath = textCreateParams.fontPath;
300+
const uint16_t fontSize = textCreateParams.fontSize;
301+
const uint32_t OutlineWidth = textCreateParams.outlineWidth;
302+
const LLUtils::Color outlineColor = textCreateParams.outlineColor;
296303
const LLUtils::Color backgroundColor = textCreateParams.backgroundColor;
297304

298-
FT_Render_Mode textRenderMOde = FreeTypeRenderer::GetRenderMode(textCreateParams.renderMode);
305+
FT_Render_Mode textRenderMOde = FreeTypeRenderer::GetRenderMode(textCreateParams.renderMode);
299306
FT_Render_Mode outlineRenderMode = FreeTypeRenderer::GetRenderMode(textCreateParams.renderMode);
300-
const bool renderOutline = OutlineWidth > 0;
307+
const bool renderOutline = OutlineWidth > 0;
301308

302309
if (textRenderMOde == FT_Render_Mode::FT_RENDER_MODE_LCD && renderOutline == true)
303310
textRenderMOde = FT_Render_Mode::FT_RENDER_MODE_NORMAL;
@@ -311,17 +318,12 @@ namespace FreeType
311318

312319
font->SetSize(fontSize, textCreateParams.DPIx, textCreateParams.DPIy);
313320

314-
TextMesureParams params;
315-
params.createParams = textCreateParams;
316-
317321
TextMetrics metrics;
318322
if (in_metrics == nullptr)
319-
MeasureText(params, metrics);
320-
else
321-
metrics = *in_metrics;
323+
MeasureText({textCreateParams}, metrics);
322324

323-
324-
auto& mesaureResult = metrics;
325+
// Cached measurements remain valid for this render; borrow them instead of copying their line data.
326+
const auto& mesaureResult = in_metrics != nullptr ? *in_metrics : metrics;
325327

326328
using namespace LLUtils;
327329
const uint32_t destPixelSize = sizeof(ColorF32);
@@ -366,12 +368,11 @@ namespace FreeType
366368
dest.pixelSizeInbytes = destPixelSize;
367369
dest.rowPitch = destRowPitch;
368370

369-
370-
int32_t penX = -mesaureResult.rect.LeftTop().x;
371-
int32_t penY = -mesaureResult.rect.LeftTop().y;
371+
const PointI32 origin = mesaureResult.rect.GetCorner(Corner::TopLeft);
372+
int32_t penX = -origin.x;
373+
int32_t penY = -origin.y;
372374

373-
374-
FT_Face face = font->GetFace();
375+
FT_Face face = font->GetFace();
375376
const auto descender = face->size->metrics.descender >> 6;
376377
const uint32_t rowHeight = mesaureResult.rowHeight;
377378

@@ -392,7 +393,7 @@ namespace FreeType
392393
{
393394
if (codepoint == L'\n')
394395
{
395-
penX = static_cast<int>(-mesaureResult.rect.LeftTop().x);
396+
penX = static_cast<int>(-origin.x);
396397
penY += rowHeight;
397398
continue;
398399
}
@@ -410,10 +411,10 @@ namespace FreeType
410411
//Render outline
411412
const auto advance = face->glyph->advance.x >> 6;
412413

413-
if (textCreateParams.maxWidthPx > 0 && penX + advance + mesaureResult.rect.LeftTop().x > static_cast<int>(textCreateParams.maxWidthPx))
414+
if (textCreateParams.maxWidthPx > 0 && penX + advance + origin.x > static_cast<int>(textCreateParams.maxWidthPx))
414415
{
415416
penY += rowHeight;
416-
penX = static_cast<int>(-mesaureResult.rect.LeftTop().x);
417+
penX = static_cast<int>(-origin.x);
417418

418419
}
419420

@@ -448,12 +449,13 @@ namespace FreeType
448449
if (glyph->format != FT_GLYPH_FORMAT_BITMAP)
449450
{
450451
if (FT_Error error = FT_Glyph_To_Bitmap(&glyph, textRenderMOde, nullptr, true); error != FT_Err_Ok)
451-
LL_EXCEPTION(LLUtils::Exception::ErrorCode::RuntimeError, "FreeType error, unable to render glyph");
452+
LL_EXCEPTION(LLUtils::Exception::ErrorCode::RuntimeError,
453+
"FreeType error, unable to render glyph");
452454
}
453455

454456
FT_BitmapGlyph bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(glyph);
455457
FreeTypeRenderer::BitmapProperties bitmapProperties = FreeTypeRenderer::GetBitmapGlyphProperties(bitmapGlyph->bitmap);
456-
const auto textcolor = el.textColor != Color{ 0, 0, 0, 0 } ? el.textColor : params.createParams.textColor;
458+
const auto textcolor = el.textColor != Color{ 0, 0, 0, 0 } ? el.textColor : textCreateParams.textColor;
457459

458460
LLUtils::Buffer rasterizedGlyph = FreeTypeRenderer::RenderGlyphToBuffer({ bitmapGlyph , backgroundColor, textcolor , bitmapProperties });
459461

0 commit comments

Comments
 (0)