Skip to content

Commit 34648c1

Browse files
committed
test(render): force deterministic font rasterization
Force ANTIALIASED_QUALITY for render tests by setting FW_FONT_QUALITY=4 in the render test assembly setup and reading that override in the native LOGFONT creation paths. This keeps local and CI rasterization aligned without changing production rendering. Also remove the RootSite per-channel pixel tolerance now that tests render deterministically again, so snapshot failures remain strict and actionable.
1 parent e282a30 commit 34648c1

5 files changed

Lines changed: 51 additions & 13 deletions

File tree

Src/Common/Controls/DetailControls/DetailControlsTests/RenderTestAssemblySetup.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ public sealed class RenderTestAssemblySetup
1818
[OneTimeSetUp]
1919
public void OneTimeSetup()
2020
{
21+
// Force grayscale antialiasing (ANTIALIASED_QUALITY=4) for deterministic
22+
// rendering across dev machines and CI (Windows Server 2025).
23+
// The native VwGraphics reads this env var when creating GDI fonts.
24+
Environment.SetEnvironmentVariable("FW_FONT_QUALITY", "4");
25+
2126
try
2227
{
2328
SetProcessDpiAwarenessContext(DpiAwarenessContextUnaware);

Src/Common/RootSite/RootSiteTests/RenderBaselineVerifier.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ internal static class RenderBaselineVerifier
1010
{
1111
private const string UpdateBaselinesEnvVar = "FW_UPDATE_RENDER_BASELINES";
1212
private const int MaxAllowedPixelDifferences = 4;
13-
private const int PerChannelTolerance = 8;
14-
private const int AlphaTolerance = 8;
1513

1614
internal static string GetSourceFileDirectory([CallerFilePath] string sourceFile = "")
1715
{
@@ -111,7 +109,7 @@ private static int CountDifferentPixels(Bitmap expectedBitmap, Bitmap actualBitm
111109
var expected = expectedBitmap.GetPixel(x, y);
112110
var actual = actualBitmap.GetPixel(x, y);
113111

114-
if (!PixelsAreEquivalent(expected, actual))
112+
if (expected != actual)
115113
differentPixelCount++;
116114
}
117115
}
@@ -156,14 +154,6 @@ private static int ScaleDiffChannel(int expected, int actual)
156154
{
157155
return Math.Min(255, Math.Abs(expected - actual) * 4);
158156
}
159-
160-
private static bool PixelsAreEquivalent(Color expected, Color actual)
161-
{
162-
return Math.Abs(expected.A - actual.A) <= AlphaTolerance &&
163-
Math.Abs(expected.R - actual.R) <= PerChannelTolerance &&
164-
Math.Abs(expected.G - actual.G) <= PerChannelTolerance &&
165-
Math.Abs(expected.B - actual.B) <= PerChannelTolerance;
166-
}
167157
}
168158

169159
internal sealed class RenderBaselineVerificationResult

Src/Common/RootSite/RootSiteTests/RenderTestAssemblySetup.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ public sealed class RenderTestAssemblySetup
1818
[OneTimeSetUp]
1919
public void OneTimeSetup()
2020
{
21+
// Force grayscale antialiasing (ANTIALIASED_QUALITY=4) for deterministic
22+
// rendering across dev machines and CI (Windows Server 2025).
23+
// The native VwGraphics reads this env var when creating GDI fonts.
24+
Environment.SetEnvironmentVariable("FW_FONT_QUALITY", "4");
25+
2126
try
2227
{
2328
SetProcessDpiAwarenessContext(DpiAwarenessContextUnaware);

Src/views/VwPropertyStore.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,25 @@ static int g_rgnFontSizes[] = {
4343
// kvfsSmaller and kvfsLarger don't have absolute values
4444
static int knDefaultFontSize = 10000; // 10 point default
4545

46+
// Returns the lfQuality value to use for LOGFONT creation.
47+
// If the FW_FONT_QUALITY env var is set to a valid value (0-6), that value is used.
48+
// This allows tests to force ANTIALIASED_QUALITY (4) for deterministic rendering.
49+
static BYTE GetFontQualityOverride()
50+
{
51+
static BYTE s_quality = []() -> BYTE {
52+
wchar_t buf[16] = {};
53+
DWORD len = ::GetEnvironmentVariableW(L"FW_FONT_QUALITY", buf, _countof(buf));
54+
if (len > 0 && len < _countof(buf))
55+
{
56+
int val = _wtoi(buf);
57+
if (val >= 0 && val <= 6)
58+
return static_cast<BYTE>(val);
59+
}
60+
return DRAFT_QUALITY;
61+
}();
62+
return s_quality;
63+
}
64+
4665
// The order of these is signficant--it is the order the font properties are recorded in
4766
// for each writing system, in the wsStyle string.
4867
// A copy of this list is in VwPropertyStore.cpp -- the two lists must be kept in sync.
@@ -358,7 +377,7 @@ int VwPropertyStore::AdjustedLineHeight(VwPropertyStore * pzvpsLeaf, int * pdymp
358377
lf.lfCharSet = DEFAULT_CHARSET; // let name determine it; WS should specify valid
359378
lf.lfOutPrecision = OUT_TT_ONLY_PRECIS; // only work with TrueType fonts
360379
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; // ??
361-
lf.lfQuality = DRAFT_QUALITY; // I (JohnT) don't think this matters for TrueType fonts.
380+
lf.lfQuality = GetFontQualityOverride();
362381
lf.lfPitchAndFamily = 0; // must be zero for EnumFontFamiliesEx
363382
wcscpy_s(lf.lfFaceName, LF_FACESIZE, pchrp->szFaceName);
364383
qzvpsWithWsAndFont->Unlock();

Src/views/lib/VwGraphics.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,25 @@ DEFINE_THIS_FILE
2828
Local Constants and static variables
2929
***********************************************************************************************/
3030

31+
// Returns the lfQuality value to use for LOGFONT creation.
32+
// If the FW_FONT_QUALITY env var is set to a valid value (0-6), that value is used.
33+
// This allows tests to force ANTIALIASED_QUALITY (4) for deterministic rendering.
34+
static BYTE GetFontQualityOverride()
35+
{
36+
static BYTE s_quality = []() -> BYTE {
37+
wchar_t buf[16] = {};
38+
DWORD len = ::GetEnvironmentVariableW(L"FW_FONT_QUALITY", buf, _countof(buf));
39+
if (len > 0 && len < _countof(buf))
40+
{
41+
int val = _wtoi(buf);
42+
if (val >= 0 && val <= 6)
43+
return static_cast<BYTE>(val);
44+
}
45+
return DRAFT_QUALITY;
46+
}();
47+
return s_quality;
48+
}
49+
3150
/***********************************************************************************************
3251
Two local classes, copied from AfGfx.h. Maybe we should move them to somewhere they
3352
can be shared more easily?
@@ -1247,7 +1266,7 @@ STDMETHODIMP VwGraphics::SetupGraphics(LgCharRenderProps * pchrp)
12471266
lf.lfCharSet = DEFAULT_CHARSET; // let name determine it; WS should specify valid
12481267
lf.lfOutPrecision = OUT_TT_ONLY_PRECIS; // only work with TrueType fonts
12491268
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; // ??
1250-
lf.lfQuality = DRAFT_QUALITY; // I (JohnT) don't think this matters for TrueType fonts.
1269+
lf.lfQuality = GetFontQualityOverride();
12511270
lf.lfPitchAndFamily = 0; // must be zero for EnumFontFamiliesEx
12521271
#ifdef UNICODE
12531272
// ENHANCE: test this path if ever needed.

0 commit comments

Comments
 (0)