Skip to content

Commit

Permalink
Fixed rounding error in glyph size code that was truncating descenders.
Browse files Browse the repository at this point in the history
  • Loading branch information
cmuratori committed Jul 12, 2021
1 parent 4f20e81 commit 6ffa228
Showing 1 changed file with 62 additions and 41 deletions.
103 changes: 62 additions & 41 deletions refterm_example_dwrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ extern "C" int D2DAcquire(IDXGISurface *GlyphTransferSurface,
struct ID2D1SolidColorBrush **DWriteFillBrush)
{
int Result = 0;

// TODO(casey): Obey "ClearType" here.

// TODO(casey): Not sure about these props...
D2D1_RENDER_TARGET_PROPERTIES Props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
0, 0);

ID2D1Factory *Factory = 0;
D2D1_FACTORY_OPTIONS Options = {};
Options.debugLevel = D2D1_DEBUG_LEVEL_ERROR;
Expand All @@ -34,10 +34,10 @@ extern "C" int D2DAcquire(IDXGISurface *GlyphTransferSurface,
(*DWriteRenderTarget)->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), DWriteFillBrush);
Result = (*DWriteFillBrush != 0);
}

Factory->Release();
}

return Result;
}

Expand All @@ -49,7 +49,7 @@ extern "C" void D2DRelease(struct ID2D1RenderTarget **DWriteRenderTarget,
(*DWriteFillBrush)->Release();
*DWriteFillBrush = 0;
}

if(*DWriteRenderTarget)
{
(*DWriteRenderTarget)->Release();
Expand All @@ -60,33 +60,35 @@ extern "C" void D2DRelease(struct ID2D1RenderTarget **DWriteRenderTarget,
extern "C" int DWriteInit(glyph_generator *GlyphGen, IDXGISurface *GlyphTransferSurface)
{
int Result = 0;

DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), (IUnknown**)&GlyphGen->DWriteFactory);
if(GlyphGen->DWriteFactory)
{
Result = 1;
}

return Result;
}

extern "C" SIZE DWriteGetTextExtent(glyph_generator *GlyphGen, int StringLen, wchar_t *String)
{
SIZE Result = {0};

IDWriteTextLayout *Layout = 0;
GlyphGen->DWriteFactory->CreateTextLayout(String, StringLen, GlyphGen->TextFormat,
(float)GlyphGen->TransferWidth, (float)GlyphGen->TransferHeight, &Layout);
if(Layout)
{
DWRITE_TEXT_METRICS Metrics = {0};
Layout->GetMetrics(&Metrics);
Result.cx = (uint32_t)Metrics.width;
Result.cy = (uint32_t)Metrics.height;

Assert(Metrics.left == 0);
Assert(Metrics.top == 0);
Result.cx = (uint32_t)(Metrics.width + 0.5f);
Result.cy = (uint32_t)(Metrics.height + 0.5f);

Layout->Release();
}

return Result;
}

Expand All @@ -97,14 +99,48 @@ void DWriteReleaseFont(glyph_generator *GlyphGen)
GlyphGen->FontFace->Release();
GlyphGen->FontFace = 0;
}
}

void IncludeLetterBounds(glyph_generator *GlyphGen, wchar_t Letter)
{
IDWriteTextLayout *Layout = 0;
GlyphGen->DWriteFactory->CreateTextLayout(&Letter, 1, GlyphGen->TextFormat,
(float)GlyphGen->TransferWidth, (float)GlyphGen->TransferHeight, &Layout);
if(Layout)
{
// TODO(casey): Real cell size determination would go here - probably with input from the user?
DWRITE_TEXT_METRICS CharMetrics = {0};
Layout->GetMetrics(&CharMetrics);

DWRITE_LINE_METRICS LineMetrics = {0};
UINT32 Ignored;
Layout->GetLineMetrics(&LineMetrics, 1, &Ignored);

if(GlyphGen->FontHeight < (uint32_t)(LineMetrics.height + 0.5f))
{
GlyphGen->FontHeight = (uint32_t)(LineMetrics.height + 0.5f);
}

if(GlyphGen->FontHeight < (uint32_t)(CharMetrics.height + 0.5f))
{
GlyphGen->FontHeight = (uint32_t)(CharMetrics.height + 0.5f);
}

if(GlyphGen->FontWidth < (uint32_t)(CharMetrics.width + 0.5f))
{
GlyphGen->FontWidth = (uint32_t)(CharMetrics.width + 0.5f);
}

Layout->Release();
}
}

extern "C" int DWriteSetFont(glyph_generator *GlyphGen, wchar_t *FontName, uint32_t FontHeight)
{
int Result = 0;

DWriteReleaseFont(GlyphGen);

if(GlyphGen->DWriteFactory)
{
GlyphGen->DWriteFactory->CreateTextFormat(FontName,
Expand All @@ -119,31 +155,16 @@ extern "C" int DWriteSetFont(glyph_generator *GlyphGen, wchar_t *FontName, uint3
{
GlyphGen->TextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
GlyphGen->TextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);

wchar_t M = L'M';
IDWriteTextLayout *Layout = 0;
GlyphGen->DWriteFactory->CreateTextLayout(&M, 1, GlyphGen->TextFormat,
(float)GlyphGen->TransferWidth, (float)GlyphGen->TransferHeight, &Layout);
if(Layout)
{
// TODO(casey): Real cell size determination would go here - probably with input from the user?
DWRITE_TEXT_METRICS CharMetrics = {0};
Layout->GetMetrics(&CharMetrics);

DWRITE_LINE_METRICS LineMetrics = {0};
UINT32 Ignored;
Layout->GetLineMetrics(&LineMetrics, 1, &Ignored);

GlyphGen->FontHeight = (uint32_t)LineMetrics.height;
GlyphGen->FontWidth = (uint32_t)CharMetrics.width;

Layout->Release();

Result = 1;
}

GlyphGen->FontWidth = 0;
GlyphGen->FontHeight = 0;
IncludeLetterBounds(GlyphGen, L'M');
IncludeLetterBounds(GlyphGen, L'g');

Result = 1;
}
}

return Result;
}

Expand All @@ -154,7 +175,7 @@ extern "C" void DWriteDrawText(glyph_generator *GlyphGen, int StringLen, WCHAR *
float XScale, float YScale)
{
D2D1_RECT_F Rect;

Rect.left = (float)Left;
Rect.top = (float)Top;
Rect.right = (float)Right;
Expand All @@ -176,12 +197,12 @@ extern "C" void DWriteDrawText(glyph_generator *GlyphGen, int StringLen, WCHAR *
extern "C" void DWriteRelease(glyph_generator *GlyphGen)
{
/* NOTE(casey): There is literally no point to this function
whatsoever except to stop the D3D debug runtime from
whatsoever except to stop the D3D debug runtime from
complaining about unreleased resources when the program
exits. EVEN THOUGH THEY WOULD BE AUTOMATICALLY RELEASED
AT THAT TIME. So now here I am manually releasing them,
which wastes the user's time, for no reason at all. */

DWriteReleaseFont(GlyphGen);
if(GlyphGen->DWriteFactory) GlyphGen->DWriteFactory->Release();
}

0 comments on commit 6ffa228

Please sign in to comment.