Repository: microsoft/terminal (language: cpp)

Issue:
Experimental text engine renders terminal window larger compared to default setting
### Windows Terminal version

1.15.2002.0

### Windows build number

10.0.19044.0

### Other Software

_No response_

### Steps to reproduce

Toggle "Enable experimental text rendering engine" 

### Expected Behavior

Terminal size to be consistent

### Actual Behavior

Top is with Atlas engine on, bottom with default setting. No other changes were altered:

![wt_experimental_compare](https://user-images.githubusercontent.com/3933920/185975569-03a39b30-bd33-44cd-b64a-e7768640703c.png)



Discussion / hints:
@lhecker lmao someone noticed
The previous renderer used `round()` to determine the width of a single cell in the terminal and then shrank/grew the font size to match that cell width. So you said you want 12pt, but you actually got 11.9945pt or something, which lead to the slightly blurry text in Windows Terminal (blurriness depends on the font family, font size and most importantly on the glyph).

My goal was to stop that font size adjustment and improve text clarity. To ensure glyphs aren't cut off with the possibly larger font size, I used `ceil()` to determine the cell width instead of `round()`. But I'm not saying that I'm 100% sure that `ceil()` is the correct choice there - I was just going by my intuition and I'm open to any and all change suggestions.

That said I don't consider this issue to be a bug, since I did do it intentionally.

Fix patch:
diff --git a/src/renderer/atlas/AtlasEngine.api.cpp b/src/renderer/atlas/AtlasEngine.api.cpp
index a1d1559f0e0..b738d5ece4b 100644
--- a/src/renderer/atlas/AtlasEngine.api.cpp
+++ b/src/renderer/atlas/AtlasEngine.api.cpp
@@ -606,21 +606,22 @@ void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const Fo
     // Point sizes are commonly treated at a 72 DPI scale
     // (including by OpenType), whereas DirectWrite uses 96 DPI.
     // Since we want the height in px we multiply by the display's DPI.
-    const auto fontSize = std::ceilf(requestedSize.Y / 72.0f * _api.dpi);
+    const auto fontSizeInPx = std::roundf(requestedSize.Y / 72.0f * _api.dpi);
 
-    const auto designUnitsPerPx = fontSize / static_cast<float>(metrics.designUnitsPerEm);
+    const auto designUnitsPerPx = fontSizeInPx / static_cast<float>(metrics.designUnitsPerEm);
     const auto ascent = static_cast<float>(metrics.ascent) * designUnitsPerPx;
     const auto descent = static_cast<float>(metrics.descent) * designUnitsPerPx;
     const auto lineGap = static_cast<float>(metrics.lineGap) * designUnitsPerPx;
-    const auto advanceWidth = static_cast<float>(glyphMetrics.advanceWidth) * designUnitsPerPx;
     const auto underlinePosition = static_cast<float>(-metrics.underlinePosition) * designUnitsPerPx;
     const auto underlineThickness = static_cast<float>(metrics.underlineThickness) * designUnitsPerPx;
     const auto strikethroughPosition = static_cast<float>(-metrics.strikethroughPosition) * designUnitsPerPx;
     const auto strikethroughThickness = static_cast<float>(metrics.strikethroughThickness) * designUnitsPerPx;
 
+    const auto advanceWidth = static_cast<float>(glyphMetrics.advanceWidth) * designUnitsPerPx;
+
     const auto halfGap = lineGap / 2.0f;
-    const auto baseline = std::ceilf(ascent + halfGap);
-    const auto lineHeight = std::ceilf(baseline + descent + halfGap);
+    const auto baseline = std::roundf(ascent + halfGap);
+    const auto lineHeight = std::roundf(baseline + descent + halfGap);
     const auto underlinePos = std::roundf(baseline + underlinePosition);
     const auto underlineWidth = std::max(1.0f, std::roundf(underlineThickness));
     const auto strikethroughPos = std::roundf(baseline + strikethroughPosition);
@@ -649,7 +650,7 @@ void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const Fo
     // Our cells can't overlap each other so we additionally clamp the bottom line to be inside the cell boundaries.
     doubleUnderlinePosBottom = std::min(doubleUnderlinePosBottom, lineHeight - thinLineWidth);
 
-    const auto cellWidth = gsl::narrow<u16>(std::ceilf(advanceWidth));
+    const auto cellWidth = gsl::narrow<u16>(std::roundf(advanceWidth));
     const auto cellHeight = gsl::narrow<u16>(lineHeight);
 
     {
@@ -686,7 +687,7 @@ void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const Fo
 
         fontMetrics->fontCollection = std::move(fontCollection);
         fontMetrics->fontName = std::move(fontName);
-        fontMetrics->fontSizeInDIP = fontSize / static_cast<float>(_api.dpi) * 96.0f;
+        fontMetrics->fontSizeInDIP = fontSizeInPx / static_cast<float>(_api.dpi) * 96.0f;
         fontMetrics->baselineInDIP = baseline / static_cast<float>(_api.dpi) * 96.0f;
         fontMetrics->advanceScale = cellWidth / advanceWidth;
         fontMetrics->cellSize = { cellWidth, cellHeight };
diff --git a/src/renderer/atlas/AtlasEngine.r.cpp b/src/renderer/atlas/AtlasEngine.r.cpp
index cbff3d22185..75f9e9cf930 100644
--- a/src/renderer/atlas/AtlasEngine.r.cpp
+++ b/src/renderer/atlas/AtlasEngine.r.cpp
@@ -443,14 +443,14 @@ void AtlasEngine::_drawGlyph(const AtlasQueueItem& item) const
         offset.x = clampedOverhang.left - clampedOverhang.right;
         offset.y = clampedOverhang.top - clampedOverhang.bottom;
 
-        if (actualSize.x > layoutBox.x)
+        if ((actualSize.x - layoutBox.x) > _r.dipPerPixel)
         {
             scalingRequired = true;
             offset.x = (overhang.left - overhang.right) * 0.5f;
             scale.x = layoutBox.x / actualSize.x;
             scale.y = scale.x;
         }
-        if (actualSize.y > layoutBox.y)
+        if ((actualSize.y - layoutBox.y) > _r.dipPerPixel)
         {
             scalingRequired = true;
             offset.y = (overhang.top - overhang.bottom) * 0.5f;


Test patch: