Skip to content

Commit 6ffa228

Browse files
committed
Fixed rounding error in glyph size code that was truncating descenders.
1 parent 4f20e81 commit 6ffa228

File tree

1 file changed

+62
-41
lines changed

1 file changed

+62
-41
lines changed

refterm_example_dwrite.cpp

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ extern "C" int D2DAcquire(IDXGISurface *GlyphTransferSurface,
1414
struct ID2D1SolidColorBrush **DWriteFillBrush)
1515
{
1616
int Result = 0;
17-
17+
1818
// TODO(casey): Obey "ClearType" here.
19-
19+
2020
// TODO(casey): Not sure about these props...
2121
D2D1_RENDER_TARGET_PROPERTIES Props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
2222
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
2323
0, 0);
24-
24+
2525
ID2D1Factory *Factory = 0;
2626
D2D1_FACTORY_OPTIONS Options = {};
2727
Options.debugLevel = D2D1_DEBUG_LEVEL_ERROR;
@@ -34,10 +34,10 @@ extern "C" int D2DAcquire(IDXGISurface *GlyphTransferSurface,
3434
(*DWriteRenderTarget)->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), DWriteFillBrush);
3535
Result = (*DWriteFillBrush != 0);
3636
}
37-
37+
3838
Factory->Release();
3939
}
40-
40+
4141
return Result;
4242
}
4343

@@ -49,7 +49,7 @@ extern "C" void D2DRelease(struct ID2D1RenderTarget **DWriteRenderTarget,
4949
(*DWriteFillBrush)->Release();
5050
*DWriteFillBrush = 0;
5151
}
52-
52+
5353
if(*DWriteRenderTarget)
5454
{
5555
(*DWriteRenderTarget)->Release();
@@ -60,33 +60,35 @@ extern "C" void D2DRelease(struct ID2D1RenderTarget **DWriteRenderTarget,
6060
extern "C" int DWriteInit(glyph_generator *GlyphGen, IDXGISurface *GlyphTransferSurface)
6161
{
6262
int Result = 0;
63-
63+
6464
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), (IUnknown**)&GlyphGen->DWriteFactory);
6565
if(GlyphGen->DWriteFactory)
6666
{
6767
Result = 1;
6868
}
69-
69+
7070
return Result;
7171
}
7272

7373
extern "C" SIZE DWriteGetTextExtent(glyph_generator *GlyphGen, int StringLen, wchar_t *String)
7474
{
7575
SIZE Result = {0};
76-
76+
7777
IDWriteTextLayout *Layout = 0;
7878
GlyphGen->DWriteFactory->CreateTextLayout(String, StringLen, GlyphGen->TextFormat,
7979
(float)GlyphGen->TransferWidth, (float)GlyphGen->TransferHeight, &Layout);
8080
if(Layout)
8181
{
8282
DWRITE_TEXT_METRICS Metrics = {0};
8383
Layout->GetMetrics(&Metrics);
84-
Result.cx = (uint32_t)Metrics.width;
85-
Result.cy = (uint32_t)Metrics.height;
86-
84+
Assert(Metrics.left == 0);
85+
Assert(Metrics.top == 0);
86+
Result.cx = (uint32_t)(Metrics.width + 0.5f);
87+
Result.cy = (uint32_t)(Metrics.height + 0.5f);
88+
8789
Layout->Release();
8890
}
89-
91+
9092
return Result;
9193
}
9294

@@ -97,14 +99,48 @@ void DWriteReleaseFont(glyph_generator *GlyphGen)
9799
GlyphGen->FontFace->Release();
98100
GlyphGen->FontFace = 0;
99101
}
102+
}
103+
104+
void IncludeLetterBounds(glyph_generator *GlyphGen, wchar_t Letter)
105+
{
106+
IDWriteTextLayout *Layout = 0;
107+
GlyphGen->DWriteFactory->CreateTextLayout(&Letter, 1, GlyphGen->TextFormat,
108+
(float)GlyphGen->TransferWidth, (float)GlyphGen->TransferHeight, &Layout);
109+
if(Layout)
110+
{
111+
// TODO(casey): Real cell size determination would go here - probably with input from the user?
112+
DWRITE_TEXT_METRICS CharMetrics = {0};
113+
Layout->GetMetrics(&CharMetrics);
114+
115+
DWRITE_LINE_METRICS LineMetrics = {0};
116+
UINT32 Ignored;
117+
Layout->GetLineMetrics(&LineMetrics, 1, &Ignored);
118+
119+
if(GlyphGen->FontHeight < (uint32_t)(LineMetrics.height + 0.5f))
120+
{
121+
GlyphGen->FontHeight = (uint32_t)(LineMetrics.height + 0.5f);
122+
}
123+
124+
if(GlyphGen->FontHeight < (uint32_t)(CharMetrics.height + 0.5f))
125+
{
126+
GlyphGen->FontHeight = (uint32_t)(CharMetrics.height + 0.5f);
127+
}
128+
129+
if(GlyphGen->FontWidth < (uint32_t)(CharMetrics.width + 0.5f))
130+
{
131+
GlyphGen->FontWidth = (uint32_t)(CharMetrics.width + 0.5f);
132+
}
133+
134+
Layout->Release();
100135
}
136+
}
101137

102138
extern "C" int DWriteSetFont(glyph_generator *GlyphGen, wchar_t *FontName, uint32_t FontHeight)
103139
{
104140
int Result = 0;
105-
141+
106142
DWriteReleaseFont(GlyphGen);
107-
143+
108144
if(GlyphGen->DWriteFactory)
109145
{
110146
GlyphGen->DWriteFactory->CreateTextFormat(FontName,
@@ -119,31 +155,16 @@ extern "C" int DWriteSetFont(glyph_generator *GlyphGen, wchar_t *FontName, uint3
119155
{
120156
GlyphGen->TextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
121157
GlyphGen->TextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
122-
123-
wchar_t M = L'M';
124-
IDWriteTextLayout *Layout = 0;
125-
GlyphGen->DWriteFactory->CreateTextLayout(&M, 1, GlyphGen->TextFormat,
126-
(float)GlyphGen->TransferWidth, (float)GlyphGen->TransferHeight, &Layout);
127-
if(Layout)
128-
{
129-
// TODO(casey): Real cell size determination would go here - probably with input from the user?
130-
DWRITE_TEXT_METRICS CharMetrics = {0};
131-
Layout->GetMetrics(&CharMetrics);
132-
133-
DWRITE_LINE_METRICS LineMetrics = {0};
134-
UINT32 Ignored;
135-
Layout->GetLineMetrics(&LineMetrics, 1, &Ignored);
136-
137-
GlyphGen->FontHeight = (uint32_t)LineMetrics.height;
138-
GlyphGen->FontWidth = (uint32_t)CharMetrics.width;
139-
140-
Layout->Release();
141-
142-
Result = 1;
143-
}
158+
159+
GlyphGen->FontWidth = 0;
160+
GlyphGen->FontHeight = 0;
161+
IncludeLetterBounds(GlyphGen, L'M');
162+
IncludeLetterBounds(GlyphGen, L'g');
163+
164+
Result = 1;
144165
}
145166
}
146-
167+
147168
return Result;
148169
}
149170

@@ -154,7 +175,7 @@ extern "C" void DWriteDrawText(glyph_generator *GlyphGen, int StringLen, WCHAR *
154175
float XScale, float YScale)
155176
{
156177
D2D1_RECT_F Rect;
157-
178+
158179
Rect.left = (float)Left;
159180
Rect.top = (float)Top;
160181
Rect.right = (float)Right;
@@ -176,12 +197,12 @@ extern "C" void DWriteDrawText(glyph_generator *GlyphGen, int StringLen, WCHAR *
176197
extern "C" void DWriteRelease(glyph_generator *GlyphGen)
177198
{
178199
/* NOTE(casey): There is literally no point to this function
179-
whatsoever except to stop the D3D debug runtime from
200+
whatsoever except to stop the D3D debug runtime from
180201
complaining about unreleased resources when the program
181202
exits. EVEN THOUGH THEY WOULD BE AUTOMATICALLY RELEASED
182203
AT THAT TIME. So now here I am manually releasing them,
183204
which wastes the user's time, for no reason at all. */
184-
205+
185206
DWriteReleaseFont(GlyphGen);
186207
if(GlyphGen->DWriteFactory) GlyphGen->DWriteFactory->Release();
187208
}

0 commit comments

Comments
 (0)