Compare commits

...

2 Commits

Author SHA1 Message Date
Leonard Hecker
02f9064015 Spel 2026-02-25 20:17:15 +01:00
Leonard Hecker
0221a4f576 Conhost font sizing for AtlasEngine 2026-02-25 20:07:12 +01:00
46 changed files with 446 additions and 578 deletions

View File

@@ -1199,6 +1199,7 @@ OSDEPENDSROOT
OSG
OSGENG
oss
otm
outdir
OUTOFCONTEXT
Outptr

View File

@@ -105,7 +105,6 @@
* `Registry.cpp`
* Connects to our relatively recently extracted renderer LIB to give it data about console state and user prefs
* `renderData.cpp`
* `renderFontDefaults.cpp`
* Maintains most of the information about what we should present inside the window on the screen (sizes, dimensions, also holds a text buffer instance and a cursor instance and a selection instance)
* `screenInfo.cpp`
* Handles some aspects of scrolling with the mouse and keyboard

View File

@@ -2209,7 +2209,7 @@ std::wstring TextBuffer::GetWithControlSequences(const CopyRequest& req) const
// Return Value:
// - string containing the generated HTML. Empty if the copy request is invalid.
std::string TextBuffer::GenHTML(const CopyRequest& req,
const int fontHeightPoints,
const float fontHeightPoints,
const std::wstring_view fontFaceName,
const COLORREF backgroundColor,
const bool isIntenseBold,
@@ -2245,7 +2245,7 @@ std::string TextBuffer::GenHTML(const CopyRequest& req,
// even with different font, add monospace as fallback
fmt::format_to(std::back_inserter(htmlBuilder), FMT_COMPILE("font-family:'{}',monospace;"), til::u16u8(fontFaceName));
fmt::format_to(std::back_inserter(htmlBuilder), FMT_COMPILE("font-size:{}pt;"), fontHeightPoints);
fmt::format_to(std::back_inserter(htmlBuilder), FMT_COMPILE("font-size:{}pt;"), lroundf(fontHeightPoints));
// note: MS Word doesn't support padding (in this way at least)
// todo: customizable padding
@@ -2420,7 +2420,7 @@ std::string TextBuffer::GenHTML(const CopyRequest& req,
// Return Value:
// - string containing the generated RTF. Empty if the copy request is invalid.
std::string TextBuffer::GenRTF(const CopyRequest& req,
const int fontHeightPoints,
const float fontHeightPoints,
const std::wstring_view fontFaceName,
const COLORREF backgroundColor,
const bool isIntenseBold,
@@ -2496,7 +2496,7 @@ std::string TextBuffer::GenRTF(const CopyRequest& req,
// \fsN: specifies font size in half-points. E.g. \fs20 results in a font
// size of 10 pts. That's why, font size is multiplied by 2 here.
fmt::format_to(std::back_inserter(contentBuilder), FMT_COMPILE("\\fs{}"), 2 * fontHeightPoints);
fmt::format_to(std::back_inserter(contentBuilder), FMT_COMPILE("\\fs{}"), lroundf(2 * fontHeightPoints));
// Set the background color for the page. But the standard way (\cbN) to do
// this isn't supported in Word. However, the following control words sequence

View File

@@ -275,14 +275,14 @@ public:
std::wstring GetWithControlSequences(const CopyRequest& req) const;
std::string GenHTML(const CopyRequest& req,
const int fontHeightPoints,
const float fontHeightPoints,
const std::wstring_view fontFaceName,
const COLORREF backgroundColor,
const bool isIntenseBold,
std::function<std::tuple<COLORREF, COLORREF, COLORREF>(const TextAttribute&)> GetAttributeColors) const noexcept;
std::string GenRTF(const CopyRequest& req,
const int fontHeightPoints,
const float fontHeightPoints,
const std::wstring_view fontFaceName,
const COLORREF backgroundColor,
const bool isIntenseBold,

View File

@@ -67,9 +67,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
ControlCore::ControlCore(Control::IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection) :
_desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, DEFAULT_FONT_SIZE, CP_UTF8 },
_actualFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false }
TerminalConnection::ITerminalConnection connection)
{
static const auto textMeasurementInit = [&]() {
TextMeasurementMode mode = TextMeasurementMode::Graphemes;
@@ -284,7 +282,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ControlCore::AttachToNewControl()
{
_setupDispatcherAndCallbacks();
const auto actualNewSize = _actualFont.GetSize();
const auto actualNewSize = _actualFont.GetCellSizeInPhysicalPx();
// Bubble this up, so our new control knows how big we want the font.
FontSizeChanged.raise(*this, winrt::make<FontSizeChangedArgs>(actualNewSize.width, actualNewSize.height));
@@ -1116,7 +1114,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
LOG_IF_FAILED(_renderEngine->UpdateFont(_desiredFont, _actualFont, featureMap, axesMap));
}
const auto actualNewSize = _actualFont.GetSize();
const auto actualNewSize = _actualFont.GetCellSizeInPhysicalPx();
FontSizeChanged.raise(*this, winrt::make<FontSizeChangedArgs>(actualNewSize.width, actualNewSize.height));
}
@@ -1128,20 +1126,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - Returns true if you need to call _refreshSizeUnderLock().
bool ControlCore::_setFontSizeUnderLock(float fontSize)
{
// Make sure we have a non-zero font size
const auto before = _actualFont.GetCellSizeInPhysicalPx();
const auto newSize = std::max(fontSize, 1.0f);
const auto fontFace = _settings.FontFace();
const auto fontWeight = _settings.FontWeight();
_desiredFont = { fontFace, 0, fontWeight.Weight, newSize, CP_UTF8 };
_actualFont = { fontFace, 0, fontWeight.Weight, _desiredFont.GetEngineSize(), CP_UTF8, false };
_desiredFont.SetEnableBuiltinGlyphs(_builtinGlyphs);
_desiredFont.SetEnableColorGlyphs(_colorGlyphs);
_desiredFont.SetCellSize(_cellWidth, _cellHeight);
_desiredFont.SetFontSizeInPt(newSize);
const auto before = _actualFont.GetSize();
_updateFont();
const auto after = _actualFont.GetSize();
const auto after = _actualFont.GetCellSizeInPhysicalPx();
return before != after;
}
@@ -1167,7 +1160,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
const auto lock = _terminal->LockForWriting();
if (_setFontSizeUnderLock(_desiredFont.GetFontSize() + fontSizeDelta))
if (_setFontSizeUnderLock(_desiredFont.GetFontSizeInPt() + fontSizeDelta))
{
_refreshSizeUnderLock();
}
@@ -1198,8 +1191,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Don't actually resize so small that a single character wouldn't fit
// in either dimension. The buffer really doesn't like being size 0.
cx = std::max(cx, _actualFont.GetSize().width);
cy = std::max(cy, _actualFont.GetSize().height);
cx = std::max(cx, _actualFont.GetCellSizeInPhysicalPx().width);
cy = std::max(cy, _actualFont.GetCellSizeInPhysicalPx().height);
// Convert our new dimensions to characters
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, { cx, cy });
@@ -1466,7 +1459,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::Windows::Foundation::Size ControlCore::FontSize() const noexcept
{
const auto fontSize = _actualFont.GetSize();
const auto fontSize = _actualFont.GetCellSizeInPhysicalPx();
return {
static_cast<float>(fontSize.width),
static_cast<float>(fontSize.height)
@@ -1480,7 +1473,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::Windows::Foundation::Size ControlCore::FontSizeInDips() const
{
const auto fontSize = _actualFont.GetSize();
const auto fontSize = _actualFont.GetCellSizeInPhysicalPx();
const auto scale = 1.0f / _compositionScale;
return {
fontSize.width * scale,

View File

@@ -698,7 +698,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::point ControlInteractivity::_getTerminalPosition(const til::point pixelPosition, bool roundToNearestCell)
{
// Get the size of the font, which is in pixels
const auto fontSize{ _core->GetFont().GetSize() };
const auto fontSize{ _core->GetFont().GetCellSizeInPhysicalPx() };
if (roundToNearestCell)
{

View File

@@ -64,7 +64,7 @@ RECT HwndTerminal::TsfDataProvider::GetCursorPosition()
{
const auto lock = _terminal->_terminal->LockForReading();
cursorPos = _terminal->_terminal->GetTextBuffer().GetCursor().GetPosition(); // measured in terminal cells
fontSize = _terminal->_actualFont.GetSize(); // measured in pixels, not DIP
fontSize = _terminal->_actualFont.GetCellSizeInPhysicalPx(); // measured in pixels, not DIP
}
POINT ptSuggestion = {
.x = cursorPos.x * fontSize.width,
@@ -239,8 +239,6 @@ static bool RegisterTermClass(HINSTANCE hInstance) noexcept
}
HwndTerminal::HwndTerminal(HWND parentHwnd) noexcept :
_desiredFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, 14, CP_UTF8 },
_actualFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, { 0, 14 }, CP_UTF8, false },
_uiaProvider{ nullptr },
_currentDpi{ USER_DEFAULT_SCREEN_DPI },
_pfnWriteCallback{ nullptr },
@@ -629,7 +627,7 @@ try
const auto lock = _terminal->LockForWriting();
const auto altPressed = GetKeyState(VK_MENU) < 0;
const til::size fontSize{ this->_actualFont.GetSize() };
const til::size fontSize{ this->_actualFont.GetCellSizeInPhysicalPx() };
this->_terminal->SetBlockSelection(altPressed);
@@ -672,7 +670,7 @@ try
};
const auto lock = _terminal->LockForWriting();
const til::size fontSize{ this->_actualFont.GetSize() };
const til::size fontSize{ this->_actualFont.GetCellSizeInPhysicalPx() };
RETURN_HR_IF(E_NOT_VALID_STATE, fontSize.area() == 0); // either dimension = 0, area == 0
@@ -807,7 +805,7 @@ try
GET_Y_LPARAM(lParam),
};
const til::size fontSize{ this->_actualFont.GetSize() };
const til::size fontSize{ this->_actualFont.GetCellSizeInPhysicalPx() };
short wheelDelta{ 0 };
if (uMsg == WM_MOUSEWHEEL || uMsg == WM_MOUSEHWHEEL)
{
@@ -967,7 +965,9 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
publicTerminal->_terminal->SetCursorStyle(static_cast<Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle>(theme.CursorStyle));
publicTerminal->_desiredFont = { fontFamily, 0, DEFAULT_FONT_WEIGHT, static_cast<float>(fontSize), CP_UTF8 };
publicTerminal->_desiredFont.SetFaceName(fontFamily);
publicTerminal->_desiredFont.SetWeight(DEFAULT_FONT_WEIGHT);
publicTerminal->_desiredFont.SetFontSizeInPt(static_cast<float>(fontSize));
publicTerminal->_desiredFont.SetEnableBuiltinGlyphs(true);
publicTerminal->_UpdateFont(newDpi);
}
@@ -1151,7 +1151,7 @@ void HwndTerminal::_PasteTextFromClipboard() noexcept
til::size HwndTerminal::GetFontSize() const noexcept
{
return _actualFont.GetSize();
return _actualFont.GetCellSizeInPhysicalPx();
}
til::rect HwndTerminal::GetBounds() const noexcept

View File

@@ -4,6 +4,7 @@
#pragma once
#include "../../buffer/out/textBuffer.hpp"
#include "../../renderer/inc/FontInfo.hpp"
#include "../../renderer/inc/FontInfoDesired.hpp"
#include "../../types/IControlAccessibilityInfo.h"
#include "../../tsf/Handle.h"
@@ -26,8 +27,6 @@ namespace Microsoft::Terminal::Core
class Terminal;
}
class FontInfo;
class FontInfoDesired;
class HwndTerminalAutomationPeer;
// Keep in sync with TerminalTheme.cs

View File

@@ -2756,6 +2756,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto cellHeight = CSSLengthPercentage::FromString(settings.CellHeight().c_str());
const auto scrollState = settings.ScrollState();
const auto padding = settings.Padding();
FontInfoDesired desiredFont;
FontInfo actualFont;
// Initialize our font information.
// The font width doesn't terribly matter, we'll only be using the
@@ -2764,9 +2766,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// The family is only used to determine if the font is truetype or
// not, but DX doesn't use that info at all.
// The Codepage is additionally not actually used by the DX engine at all.
FontInfoDesired desiredFont{ fontFace, 0, fontWeight.Weight, fontSize, CP_UTF8 };
desiredFont.SetCellSize(cellWidth, cellHeight);
FontInfo actualFont{ fontFace, 0, fontWeight.Weight, desiredFont.GetEngineSize(), CP_UTF8, false };
desiredFont.SetFaceName(std::wstring{ std::wstring_view{ fontFace } });
desiredFont.SetWeight(fontWeight.Weight);
desiredFont.SetFontSizeInPt(fontSize);
desiredFont.SetCellWidth(cellWidth);
desiredFont.SetCellHeight(cellHeight);
// Create a DX engine and initialize it with our font and DPI. We'll
// then use it to measure how much space the requested rows and columns
@@ -2780,7 +2784,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont));
const auto scale = dpi / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
const auto actualFontSize = actualFont.GetSize();
const auto actualFontSize = actualFont.GetCellSizeInPhysicalPx();
// UWP XAML scrollbars aren't guaranteed to be the same size as the
// ComCtl scrollbars, but it's certainly close enough.

View File

@@ -377,9 +377,7 @@ private:
std::wstring _workingDirectory;
bool _highContrastMode = false;
// This default fake font value is only used to check if the font is a raster font.
// Otherwise, the font is changed to a real value with the renderer via TriggerFontChange.
FontInfo _fontInfo{ DEFAULT_FONT_FACE, TMPF_TRUETYPE, 10, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false };
FontInfo _fontInfo;
#pragma region Text Selection
// a selection is represented as a range between two COORDs (start and end)
// the pivot is the til::point that remains selected when you extend a selection in any direction

View File

@@ -990,7 +990,7 @@ Terminal::TextCopyData Terminal::RetrieveSelectedTextFromBuffer(const bool singl
{
const auto bgColor = _renderSettings.GetAttributeColors({}).second;
const auto isIntenseBold = _renderSettings.GetRenderMode(::Microsoft::Console::Render::RenderSettings::Mode::IntenseIsBold);
const auto fontSizePt = _fontInfo.GetUnscaledSize().height; // already in points
const auto fontSizePt = _fontInfo.GetCellSizeInDIP().height; // already in points
const auto& fontName = _fontInfo.GetFaceName();
if (html)

View File

@@ -744,10 +744,10 @@ CATCH_RETURN();
// Create new screen buffer.
auto WindowSize = siExisting.GetViewport().Dimensions();
const auto& existingFont = siExisting.GetCurrentFont();
SCREEN_INFORMATION* ScreenInfo = nullptr;
auto Status = SCREEN_INFORMATION::CreateInstance(WindowSize,
existingFont,
siExisting.GetDesiredFont(),
siExisting.GetCurrentFont(),
WindowSize,
siExisting.GetAttributes(),
siExisting.GetAttributes(),

View File

@@ -232,7 +232,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
if (index == 0)
{
// As of the November 2015 renderer system, we only have a single font at index 0.
size = context.GetActiveBuffer().GetCurrentFont().GetUnscaledSize();
size = context.GetActiveBuffer().GetLegacyConhostFontCellSize();
return S_OK;
}
else
@@ -271,7 +271,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
}
else
{
WindowSize = activeScreenInfo.GetCurrentFont().GetUnscaledSize();
WindowSize = activeScreenInfo.GetLegacyConhostFontCellSize();
}
consoleFontInfoEx.dwFontSize = til::unwrap_coord_size(WindowSize);
@@ -305,19 +305,15 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
LockConsole();
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
auto& activeScreenInfo = context.GetActiveBuffer();
WCHAR FaceName[ARRAYSIZE(consoleFontInfoEx.FaceName)];
RETURN_IF_FAILED(StringCchCopyW(FaceName, ARRAYSIZE(FaceName), consoleFontInfoEx.FaceName));
FontInfo fi(FaceName,
gsl::narrow_cast<unsigned char>(consoleFontInfoEx.FontFamily),
consoleFontInfoEx.FontWeight,
til::wrap_coord_size(consoleFontInfoEx.dwFontSize),
gci.OutputCP);
FontInfoDesired fi;
fi.SetFaceName(consoleFontInfoEx.FaceName);
fi.SetFamily(gsl::narrow_cast<unsigned char>(consoleFontInfoEx.FontFamily));
fi.SetWeight(consoleFontInfoEx.FontWeight);
fi.SetCodePage(gci.OutputCP);
fi.SetPixelCellSize(til::wrap_coord_size(consoleFontInfoEx.dwFontSize));
// TODO: MSFT: 9574827 - should this have a failure case?
activeScreenInfo.UpdateFont(&fi);
context.GetActiveBuffer().UpdateFont(std::move(fi));
return S_OK;
}

View File

@@ -63,7 +63,6 @@ public:
Microsoft::Console::Render::Renderer* pRender;
Microsoft::Console::TSF::Handle tsf;
Microsoft::Console::AccessibilityNotifier accessibilityNotifier;
Microsoft::Console::Render::IFontDefaultList* pFontDefaultList;
bool IsHeadless() const;

View File

@@ -30,7 +30,6 @@
<ClCompile Include="..\readDataRaw.cpp" />
<ClCompile Include="..\registry.cpp" />
<ClCompile Include="..\renderData.cpp" />
<ClCompile Include="..\renderFontDefaults.cpp" />
<ClCompile Include="..\screenInfo.cpp" />
<ClCompile Include="..\scrolling.cpp" />
<ClCompile Include="..\selection.cpp" />
@@ -78,7 +77,6 @@
<ClInclude Include="..\readDataRaw.hpp" />
<ClInclude Include="..\registry.hpp" />
<ClInclude Include="..\renderData.hpp" />
<ClInclude Include="..\renderFontDefaults.hpp" />
<ClInclude Include="..\resource.h" />
<ClInclude Include="..\screenInfo.hpp" />
<ClInclude Include="..\scrolling.hpp" />

View File

@@ -69,9 +69,6 @@
<ClCompile Include="..\renderData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\renderFontDefaults.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\screenInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -291,5 +288,6 @@
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natstepfilter" />
</ItemGroup>
</Project>
</Project>

View File

@@ -21,11 +21,12 @@ using namespace Microsoft::Console::Interactivity;
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
FontInfo fiFont(gci.GetFaceName(),
gsl::narrow_cast<unsigned char>(gci.GetFontFamily()),
gci.GetFontWeight(),
gci.GetFontSize(),
gci.GetCodePage());
FontInfoDesired fiFont;
fiFont.SetFaceName(gci.GetFaceName());
fiFont.SetFamily(gsl::narrow_cast<unsigned char>(gci.GetFontFamily()));
fiFont.SetWeight(gci.GetFontWeight());
fiFont.SetCodePage(gci.GetCodePage());
fiFont.SetPixelCellSize(gci.GetFontSize());
// For East Asian version, we want to get the code page from the registry or shell32, so we can specify console
// codepage by console.cpl or shell32. The default codepage is OEMCP.
@@ -38,6 +39,7 @@ using namespace Microsoft::Console::Interactivity;
auto Status = SCREEN_INFORMATION::CreateInstance(gci.GetWindowSize(),
fiFont,
FontInfo{},
gci.GetScreenBufferSize(),
TextAttribute{},
TextAttribute{ gci.GetPopupFillAttribute() },

View File

@@ -1,30 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "renderFontDefaults.hpp"
#pragma hdrstop
RenderFontDefaults::RenderFontDefaults()
{
LOG_IF_NTSTATUS_FAILED(TrueTypeFontList::s_Initialize());
}
RenderFontDefaults::~RenderFontDefaults()
{
LOG_IF_FAILED(TrueTypeFontList::s_Destroy());
}
[[nodiscard]] HRESULT RenderFontDefaults::RetrieveDefaultFontNameForCodepage(const unsigned int codePage,
std::wstring& outFaceName)
try
{
// GH#3123: Propagate font length changes up through Settings and propsheet
wchar_t faceName[LF_FACESIZE]{ 0 };
auto status = TrueTypeFontList::s_SearchByCodePage(codePage, faceName, ARRAYSIZE(faceName));
outFaceName.assign(faceName);
return HRESULT_FROM_NT(status);
}
CATCH_RETURN();

View File

@@ -1,27 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- renderFontDefaults.hpp
Abstract:
- This provides the implementation of the interface that abstracts the lookup of default fonts from the actual rendering engine.
Author(s):
- Michael Niksa (miniksa) Mar 2016
--*/
#pragma once
#include "../renderer/inc/IFontDefaultList.hpp"
class RenderFontDefaults sealed : public Microsoft::Console::Render::IFontDefaultList
{
public:
RenderFontDefaults();
~RenderFontDefaults();
[[nodiscard]] HRESULT RetrieveDefaultFontNameForCodepage(const unsigned int codePage,
std::wstring& outFaceName);
};

View File

@@ -21,11 +21,12 @@ using namespace Microsoft::Console::VirtualTerminal;
SCREEN_INFORMATION::SCREEN_INFORMATION(
_In_ IWindowMetrics* pMetrics,
const TextAttribute popupAttributes,
const FontInfo fontInfo) :
FontInfoDesired fontInfoDesired,
FontInfo fontInfo) :
_pConsoleWindowMetrics{ pMetrics },
_PopupAttributes{ popupAttributes },
_currentFont{ fontInfo },
_desiredFont{ fontInfo }
_currentFont{ std::move(fontInfo) },
_desiredFont{ std::move(fontInfoDesired) }
{
// Check if VT mode should be enabled by default. This can be true if
// VirtualTerminalLevel is set to !=0 in the registry, or when conhost
@@ -35,7 +36,6 @@ SCREEN_INFORMATION::SCREEN_INFORMATION(
{
OutputMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
}
_desiredFont.SetEnableBuiltinGlyphs(gci.GetEnableBuiltinGlyphs());
}
// Routine Description:
@@ -59,7 +59,8 @@ SCREEN_INFORMATION::~SCREEN_INFORMATION()
// - dwScreenBufferSize - the initial size of the screen buffer (in rows/columns).
// Return Value:
[[nodiscard]] NTSTATUS SCREEN_INFORMATION::CreateInstance(_In_ til::size coordWindowSize,
const FontInfo fontInfo,
FontInfoDesired fontInfoDesired,
FontInfo fontInfo,
_In_ til::size coordScreenBufferSize,
const TextAttribute defaultAttributes,
const TextAttribute popupAttributes,
@@ -76,7 +77,7 @@ SCREEN_INFORMATION::~SCREEN_INFORMATION()
// It is possible for pNotifier to be null and that's OK.
// For instance, the PTY doesn't need to send events. Just pass it along
// and be sure that `SCREEN_INFORMATION` bypasses all event work if it's not there.
const auto pScreen = new SCREEN_INFORMATION(pMetrics, popupAttributes, fontInfo);
const auto pScreen = new SCREEN_INFORMATION(pMetrics, popupAttributes, std::move(fontInfoDesired), std::move(fontInfo));
// Set up viewport
pScreen->_viewport = Viewport::FromDimensions({ 0, 0 },
@@ -465,7 +466,7 @@ til::size SCREEN_INFORMATION::GetScrollBarSizesInCharacters() const
void SCREEN_INFORMATION::GetRequiredConsoleSizeInPixels(_Out_ til::size* const pRequiredSize) const
{
const auto coordFontSize = GetCurrentFont().GetSize();
const auto coordFontSize = GetCurrentFont().GetCellSizeInPhysicalPx();
// TODO: Assert valid size boundaries
pRequiredSize->width = GetViewport().Width() * coordFontSize.width;
@@ -480,7 +481,7 @@ til::size SCREEN_INFORMATION::GetScreenFontSize() const
til::size coordRet = { 1, 1 };
if (ServiceLocator::LocateGlobals().pRender != nullptr)
{
coordRet = GetCurrentFont().GetSize();
coordRet = GetCurrentFont().GetCellSizeInPhysicalPx();
}
// For sanity's sake, make sure not to leak 0 out as a possible value. These values are used in division operations.
@@ -525,14 +526,32 @@ void SCREEN_INFORMATION::RefreshFontWithRenderer()
}
}
void SCREEN_INFORMATION::UpdateFont(const FontInfo* const pfiNewFont)
void SCREEN_INFORMATION::UpdateFont(FontInfoDesired newFont)
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto& globals = ServiceLocator::LocateGlobals();
auto& gci = globals.getConsoleInformation();
FontInfoDesired fiDesiredFont(*pfiNewFont);
fiDesiredFont.SetEnableBuiltinGlyphs(gci.GetEnableBuiltinGlyphs());
newFont.SetEnableBuiltinGlyphs(gci.GetEnableBuiltinGlyphs());
GetDesiredFont() = fiDesiredFont;
if (newFont.GetFaceName() == DEFAULT_TT_FONT_FACENAME)
{
// GH#3123: Propagate font length changes up through Settings and propsheet
wchar_t faceName[LF_FACESIZE];
if (SUCCEEDED(TrueTypeFontList::s_SearchByCodePage(newFont.GetCodePage(), faceName, ARRAYSIZE(faceName))))
{
newFont.SetFaceName(faceName);
// If we're assigning a default true type font name, make sure the family is also set to TrueType
// to help GDI select the appropriate font when we actually create it.
newFont.SetFamily(TMPF_TRUETYPE);
}
}
_updateFont(std::move(newFont));
}
void SCREEN_INFORMATION::_updateFont(FontInfoDesired newFont)
{
_desiredFont = std::move(newFont);
RefreshFontWithRenderer();
@@ -551,7 +570,7 @@ void SCREEN_INFORMATION::UpdateFont(const FontInfo* const pfiNewFont)
// If we're an alt buffer, also update our main buffer.
if (_psiMainBuffer)
{
_psiMainBuffer->UpdateFont(pfiNewFont);
_psiMainBuffer->_updateFont(_desiredFont);
}
}
@@ -1773,10 +1792,9 @@ const SCREEN_INFORMATION* SCREEN_INFORMATION::GetAltBuffer() const noexcept
// Create new screen buffer.
auto WindowSize = _viewport.Dimensions();
const auto& existingFont = GetCurrentFont();
auto Status = SCREEN_INFORMATION::CreateInstance(WindowSize,
existingFont,
_desiredFont,
_currentFont,
WindowSize,
initAttributes,
GetPopupAttributes(),
@@ -2419,3 +2437,32 @@ const FontInfoDesired& SCREEN_INFORMATION::GetDesiredFont() const noexcept
{
return _desiredFont;
}
til::size SCREEN_INFORMATION::GetLegacyConhostFontCellSize() const noexcept
{
// This was previously quite different (in "GdiEngine", src\renderer\gdi\state.cpp).
// It set this size (coordSizeUnscaled) to the requested cell size,
// unless it was a raster font, in which case it uses the actual cell size.
// It also filled back the cell width if it was missing.
//
// My assumption is that the author wanted the desired cell size to round-trip
// for most fonts (TrueType fonts). I do not know why they didn't just use the
// desired font without feedback from the renderer. No round-trip logic needed.
// My assumption about the logic for raster fonts is that the author wanted the cell size
// to round-trip between calls to SetCurrentConsoleFontEx and GetCurrentConsoleFontEx.
//
// Well, it's mostly fixed now (aside from the necessary float -> int truncation).
// _desiredFont is always the source of truth. No backward feedback.
// _currentFont is always the true resulting render size. No size hacks.
// Try to use the given (desired) cell if we have one.
auto size = _desiredFont.GetPixelCellSize();
if (!size)
{
// Otherwise, fall back to the renderer size.
size = _currentFont.GetCellSizeInDIP().AsInteger_DoNotUse();
}
return size;
}

View File

@@ -23,6 +23,7 @@ Revision History:
#include "../buffer/out/OutputCellRect.hpp"
#include "../buffer/out/textBuffer.hpp"
#include "../interactivity/inc/IWindowMetrics.hpp"
#include "../renderer/inc/FontInfo.hpp"
#include "../renderer/inc/FontInfoDesired.hpp"
#include "../server/ObjectHeader.h"
@@ -71,7 +72,7 @@ public:
// GetScreenBufferInformation could return a struct. And so on.
// Creation
[[nodiscard]] static NTSTATUS CreateInstance(til::size windowSize, FontInfo fontInfo, til::size screenBufferSize, TextAttribute defaultAttributes, TextAttribute popupAttributes, UINT cursorSize, SCREEN_INFORMATION** screen);
[[nodiscard]] static NTSTATUS CreateInstance(til::size windowSize, FontInfoDesired fontInfoDesired, FontInfo fontInfo, til::size screenBufferSize, TextAttribute defaultAttributes, TextAttribute popupAttributes, UINT cursorSize, SCREEN_INFORMATION** screen);
static void s_InsertScreenBuffer(SCREEN_INFORMATION* screenInfo);
static void s_RemoveScreenBuffer(SCREEN_INFORMATION* screenInfo);
@@ -126,8 +127,9 @@ public:
const FontInfo& GetCurrentFont() const noexcept;
FontInfoDesired& GetDesiredFont() noexcept;
const FontInfoDesired& GetDesiredFont() const noexcept;
til::size GetLegacyConhostFontCellSize() const noexcept;
til::size GetScreenFontSize() const;
void UpdateFont(const FontInfo* newFont);
void UpdateFont(FontInfoDesired newFont);
void RefreshFontWithRenderer();
[[nodiscard]] NTSTATUS SetViewportOrigin(bool absolute, til::point coordWindowOrigin, bool updateBottom);
const Microsoft::Console::Types::Viewport& GetViewport() const noexcept;
@@ -173,7 +175,7 @@ public:
UINT ScrollScale = 1;
private:
SCREEN_INFORMATION(Microsoft::Console::Interactivity::IWindowMetrics* metrics, TextAttribute popupAttributes, FontInfo fontInfo);
SCREEN_INFORMATION(Microsoft::Console::Interactivity::IWindowMetrics* metrics, TextAttribute popupAttributes, FontInfoDesired fontInfoDesired, FontInfo fontInfo);
// Construction
[[nodiscard]] NTSTATUS _InitializeOutputStateMachine();
@@ -191,6 +193,7 @@ private:
void _makeCursorVisible();
// Rendering / Viewport
void _updateFont(FontInfoDesired newFont);
void _CalculateViewportSize(const til::rect* clientArea, til::size* size);
void _AdjustViewportSize(const til::rect* clientNew, const til::rect* clientOld, const til::size* size);
void _InternalSetViewportSize(const til::size* size, bool resizeFromTop, bool resizeFromLeft);

View File

@@ -80,7 +80,6 @@ SOURCES = \
..\readDataRaw.cpp \
..\writeData.cpp \
..\renderData.cpp \
..\renderFontDefaults.cpp \
..\AccessibilityNotifier.cpp \
..\ConsoleArguments.cpp \

View File

@@ -7,7 +7,6 @@
#include "dbcs.h"
#include "handle.h"
#include "registry.hpp"
#include "renderFontDefaults.hpp"
#include "../interactivity/base/ApiDetector.hpp"
#include "../interactivity/base/RemoteConsoleControl.hpp"
#include "../interactivity/inc/ServiceLocator.hpp"
@@ -44,10 +43,6 @@ try
Globals.uiOEMCP = GetOEMCP();
Globals.uiWindowsCP = GetACP();
Globals.pFontDefaultList = new RenderFontDefaults();
FontInfoBase::s_SetFontDefaultList(Globals.pFontDefaultList);
// Check if this conhost is allowed to delegate its activities to another.
// If so, look up the registered default console handler.
if (Globals.delegationPair.IsUndecided())

View File

@@ -58,6 +58,7 @@ class ObjectTests
SCREEN_INFORMATION* newOutput;
VERIFY_NT_SUCCESS(SCREEN_INFORMATION::CreateInstance(existingOutput.GetViewport().Dimensions(),
existingOutput.GetDesiredFont(),
existingOutput.GetCurrentFont(),
existingOutput.GetBufferSize().Dimensions(),
existingOutput.GetAttributes(),

View File

@@ -817,6 +817,7 @@ class ::Microsoft::Console::VirtualTerminal::VtIoTests
VERIFY_NT_SUCCESS(SCREEN_INFORMATION::CreateInstance(
screenInfo->GetViewport().Dimensions(),
screenInfo->GetDesiredFont(),
screenInfo->GetCurrentFont(),
screenInfo->GetBufferSize().Dimensions(),
screenInfo->GetAttributes(),

View File

@@ -35,7 +35,6 @@ public:
CommonState() :
m_heap(GetProcessHeap()),
m_hrTextBufferInfo(E_FAIL),
m_pFontInfo{ L"Consolas", 0, 0, { 8, 12 }, 0 },
m_backupTextBufferInfo(),
m_readHandle(nullptr)
{
@@ -63,7 +62,8 @@ public:
void PrepareGlobalFont(const til::size coordFontSize = { 8, 12 })
{
m_pFontInfo = { L"Consolas", 0, 0, coordFontSize, 0 };
m_pFontInfo.SetFaceName(L"Consolas");
m_pFontInfo.SetPixelCellSize(coordFontSize);
}
void PrepareGlobalScreenBuffer(const til::CoordType viewWidth = s_csWindowWidth,
@@ -85,6 +85,7 @@ public:
THROW_IF_FAILED(SCREEN_INFORMATION::CreateInstance(coordWindowSize,
m_pFontInfo,
FontInfo{},
coordScreenBufferSize,
TextAttribute{},
TextAttribute{ FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED },
@@ -266,7 +267,7 @@ public:
private:
HANDLE m_heap;
HRESULT m_hrTextBufferInfo;
FontInfo m_pFontInfo;
FontInfoDesired m_pFontInfo;
std::unique_ptr<TextBuffer> m_backupTextBufferInfo;
std::unique_ptr<INPUT_READ_HANDLE_DATA> m_readHandle;
};

View File

@@ -368,7 +368,7 @@ void Clipboard::StoreSelectionToClipboard(const bool copyFormatting)
{
const auto& fontData = gci.GetActiveOutputBuffer().GetCurrentFont();
const auto& fontName = fontData.GetFaceName();
const auto fontSizePt = fontData.GetUnscaledSize().height * 72 / ServiceLocator::LocateGlobals().dpi;
const auto fontSizePt = fontData.GetCellSizeInDIP().height * 72 / ServiceLocator::LocateGlobals().dpi;
const auto bgColor = renderSettings.GetAttributeColors({}).second;
const auto isIntenseBold = renderSettings.GetRenderMode(::Microsoft::Console::Render::RenderSettings::Mode::IntenseIsBold);

View File

@@ -304,11 +304,11 @@ void Menu::s_ShowPropertiesDialog(HWND const hwnd, BOOL const Defaults)
pStateInfo->WindowPosX = rcWindow.left;
pStateInfo->WindowPosY = rcWindow.top;
const auto& currentFont = ScreenInfo.GetCurrentFont();
pStateInfo->FontFamily = currentFont.GetFamily();
LOG_IF_FAILED(til::unwrap_coord_size_hr(currentFont.GetUnscaledSize(), pStateInfo->FontSize));
pStateInfo->FontWeight = currentFont.GetWeight();
LOG_IF_FAILED(StringCchCopyW(pStateInfo->FaceName, ARRAYSIZE(pStateInfo->FaceName), currentFont.GetFaceName().data()));
const auto& desiredFont = ScreenInfo.GetDesiredFont();
pStateInfo->FontFamily = desiredFont.GetFamily();
LOG_IF_FAILED(til::unwrap_coord_size_hr(desiredFont.GetPixelCellSize(), pStateInfo->FontSize));
pStateInfo->FontWeight = desiredFont.GetWeight();
desiredFont.FillLegacyNameBuffer(pStateInfo->FaceName);
const auto& cursor = ScreenInfo.GetTextBuffer().GetCursor();
pStateInfo->CursorSize = cursor.GetSize();
@@ -444,17 +444,19 @@ void Menu::s_PropertiesUpdate(PCONSOLE_STATE_INFO pStateInfo)
// end V2 console properties
// Apply font information (must come before all character calculations for window/buffer size).
FontInfo fiNewFont(pStateInfo->FaceName, gsl::narrow_cast<unsigned char>(pStateInfo->FontFamily), pStateInfo->FontWeight, til::wrap_coord_size(pStateInfo->FontSize), pStateInfo->CodePage);
ScreenInfo.UpdateFont(&fiNewFont);
const auto& fontApplied = ScreenInfo.GetCurrentFont();
FontInfoDesired fiNewFont;
fiNewFont.SetFaceName(pStateInfo->FaceName);
fiNewFont.SetFamily(gsl::narrow_cast<unsigned char>(pStateInfo->FontFamily));
fiNewFont.SetWeight(pStateInfo->FontWeight);
fiNewFont.SetCodePage(pStateInfo->CodePage);
fiNewFont.SetPixelCellSize(til::wrap_coord_size(pStateInfo->FontSize));
ScreenInfo.UpdateFont(std::move(fiNewFont));
// Now make sure internal font state reflects the font chosen
gci.SetFontFamily(fontApplied.GetFamily());
gci.SetFontSize(fontApplied.GetUnscaledSize());
gci.SetFontWeight(fontApplied.GetWeight());
gci.SetFaceName(fontApplied.GetFaceName());
gci.SetFontFamily(pStateInfo->FontFamily);
gci.SetFontSize(til::wrap_coord_size(pStateInfo->FontSize));
gci.SetFontWeight(pStateInfo->FontWeight);
gci.SetFaceName(pStateInfo->FaceName);
// Set the cursor properties in the Settings
const auto cursorType = static_cast<CursorType>(pStateInfo->CursorType);

View File

@@ -79,7 +79,7 @@ struct TsfDataProvider : Microsoft::Console::TSF::IDataProvider
coordCursor.y = std::clamp(coordCursor.y, 0, viewport.height() - 1);
// Convert from columns/rows to pixels.
const auto coordFont = screenBuffer.GetCurrentFont().GetSize();
const auto coordFont = screenBuffer.GetCurrentFont().GetCellSizeInPhysicalPx();
POINT ptSuggestion{
.x = coordCursor.x * coordFont.width,
.y = coordCursor.y * coordFont.height,
@@ -853,19 +853,18 @@ LRESULT Window::_HandleGetDpiScaledSize(UINT dpiNew, _Inout_ SIZE* pSizeNew) con
// Get the current DPI and font size.
HWND hwnd = GetWindowHandle();
UINT dpiCurrent = ServiceLocator::LocateHighDpiApi<WindowDpiApi>()->GetDpiForWindow(hwnd);
const auto& fontInfoCurrent = GetScreenInfo().GetCurrentFont();
til::size fontSizeCurrent = fontInfoCurrent.GetSize();
const auto& si = GetScreenInfo();
const auto& fontInfoDesired = si.GetDesiredFont();
til::size fontSizeCurrent = si.GetCurrentFont().GetCellSizeInPhysicalPx();
// Scale the current font to the new DPI and get the new font size.
FontInfoDesired fontInfoDesired(fontInfoCurrent);
FontInfo fontInfoNew(L"", 0, 0, { 0, 0 }, 0);
if (!SUCCEEDED(ServiceLocator::LocateGlobals().pRender->GetProposedFont(
dpiNew, fontInfoDesired, fontInfoNew)))
FontInfo fontInfoNew;
if (!SUCCEEDED(ServiceLocator::LocateGlobals().pRender->GetProposedFont(dpiNew, fontInfoDesired, fontInfoNew)))
{
// On failure, return FALSE, which scales the window linearly for DPI.
return FALSE;
}
til::size fontSizeNew = fontInfoNew.GetSize();
til::size fontSizeNew = fontInfoNew.GetCellSizeInPhysicalPx();
// The provided size is the window rect, which includes non-client area
// (caption bars, resize borders, scroll bars, etc). We want to scale the

View File

@@ -616,16 +616,8 @@ CATCH_RETURN()
void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics)
{
const auto& faceName = fontInfoDesired.GetFaceName();
const auto requestedFamily = fontInfoDesired.GetFamily();
auto requestedWeight = fontInfoDesired.GetWeight();
auto fontSize = std::clamp(fontInfoDesired.GetFontSize(), 1.0f, 100.0f);
auto requestedSize = fontInfoDesired.GetEngineSize();
if (!requestedSize.height)
{
fontSize = 12.0f;
requestedSize = { 0, 12 };
}
if (!requestedWeight)
{
requestedWeight = DWRITE_FONT_WEIGHT_NORMAL;
@@ -738,22 +730,59 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
// (including by OpenType), whereas DirectWrite uses 96 DPI.
// Since we want the height in px we multiply by the display's DPI.
const auto dpi = static_cast<f32>(_api.s->font->dpi);
const auto fontSizeInPx = fontSize / 72.0f * dpi;
const auto pxPerPt = dpi / 72.0f;
const auto pxPerDIP = dpi / 96.0f;
const auto emPerDesignUnit = 1.0f / static_cast<f32>(metrics.designUnitsPerEm);
auto fontSizeInPt = fontInfoDesired.GetFontSizeInPt();
auto desiredCellWidth = fontInfoDesired.GetCellWidth();
auto desiredCellHeight = fontInfoDesired.GetCellHeight();
auto advanceHeight = static_cast<f32>(metrics.ascent + metrics.descent + metrics.lineGap) * emPerDesignUnit;
auto advanceWidth = 0.5f;
const auto designUnitsPerPx = fontSizeInPx / static_cast<f32>(metrics.designUnitsPerEm);
const auto ascent = static_cast<f32>(metrics.ascent) * designUnitsPerPx;
const auto descent = static_cast<f32>(metrics.descent) * designUnitsPerPx;
const auto lineGap = static_cast<f32>(metrics.lineGap) * designUnitsPerPx;
const auto underlinePosition = static_cast<f32>(-metrics.underlinePosition) * designUnitsPerPx;
const auto underlineThickness = static_cast<f32>(metrics.underlineThickness) * designUnitsPerPx;
const auto strikethroughPosition = static_cast<f32>(-metrics.strikethroughPosition) * designUnitsPerPx;
const auto strikethroughThickness = static_cast<f32>(metrics.strikethroughThickness) * designUnitsPerPx;
const auto advanceHeight = ascent + descent + lineGap;
if (fontSizeInPt > 0.0f)
{
fontSizeInPt = clamp(fontSizeInPt, 1.0f, 100.0f);
}
else
{
// Assume a 12pt font size by default for the `ch` unit.
const auto fontSizeInPx = 12 * pxPerPt;
const auto aw = advanceWidth * fontSizeInPx;
// conhost is traditionally based on GDI and doesn't use a font-size like CSS does.
// Instead, its "font size" specifies the cell height in DIPs (= pixels at 96 DPI).
// conhost will thus leave the `fontSizeInPt` 0 but set a `requestedSize` in px.
// We can easily calculate the font-size by dividing by the advance height.
//
// Since we use GetMetrics and GetDesignGlyphMetrics instead of GetGdiCompatibleMetrics and
// GetGdiCompatibleGlyphMetrics we might still run into some subtle differences, however.
// It remains to be seen whether that's an actual issue or not though.
//
// I pass 0 as fallback so that we fall back to
// 12pt if the cell height is unspecified as well.
const auto height = desiredCellHeight.Resolve(0, 72.0f, fontSizeInPx, aw);
fontSizeInPt = height / advanceHeight;
if (fontSizeInPt >= 1.0f)
{
// Prevent further adjustments to the cell size.
//
// NOTE: This is _VERY_ important with conhost, because even for TrueType fonts it stores
// the full cell size in the registry and then tries to apply it to the renderer.
// And because it does so with integer DIPs, it stores a cell width of ~11 DIP as 12 "px".
// This just so coincidentally happens to work with GDI and would break the second GDI changes,
// but let's ignore that for a second. It means we have to ignore the cell width. It's garbage.
desiredCellWidth = {};
desiredCellHeight = {};
}
else
{
fontSizeInPt = 12.0f;
}
}
// We use the same character to determine the advance width as CSS for its "ch" unit ("0").
// According to the CSS spec, if it's impossible to determine the advance width,
// it must be assumed to be 0.5em wide. em in CSS refers to the computed font-size.
auto advanceWidth = 0.5f * fontSizeInPx;
// it must be assumed to be 0.5em wide.
{
static constexpr u32 codePoint = '0';
@@ -764,18 +793,31 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
{
DWRITE_GLYPH_METRICS glyphMetrics{};
THROW_IF_FAILED(primaryFontFace->GetDesignGlyphMetrics(&glyphIndex, 1, &glyphMetrics, FALSE));
advanceWidth = static_cast<f32>(glyphMetrics.advanceWidth) * designUnitsPerPx;
advanceWidth = static_cast<f32>(glyphMetrics.advanceWidth) * emPerDesignUnit;
}
}
auto adjustedWidth = std::roundf(fontInfoDesired.GetCellWidth().Resolve(advanceWidth, dpi, fontSizeInPx, advanceWidth));
auto adjustedHeight = std::roundf(fontInfoDesired.GetCellHeight().Resolve(advanceHeight, dpi, fontSizeInPx, advanceWidth));
// Now that we know the fontSize we can turn the advanceHeight/Width from em into px.
const auto fontSizeInPx = fontSizeInPt * pxPerPt;
advanceWidth *= fontSizeInPx;
advanceHeight *= fontSizeInPx;
auto adjustedWidth = std::roundf(desiredCellWidth.Resolve(advanceWidth, dpi, fontSizeInPx, advanceWidth));
auto adjustedHeight = std::roundf(desiredCellHeight.Resolve(advanceHeight, dpi, fontSizeInPx, advanceWidth));
// Protection against bad user values in GetCellWidth/Y.
// AtlasEngine fails hard with 0 cell sizes.
adjustedWidth = std::max(1.0f, adjustedWidth);
adjustedHeight = std::max(1.0f, adjustedHeight);
const auto designUnitsPerPx = fontSizeInPx / static_cast<f32>(metrics.designUnitsPerEm);
const auto ascent = static_cast<f32>(metrics.ascent) * designUnitsPerPx;
const auto lineGap = static_cast<f32>(metrics.lineGap) * designUnitsPerPx;
const auto underlinePosition = static_cast<f32>(-metrics.underlinePosition) * designUnitsPerPx;
const auto underlineThickness = static_cast<f32>(metrics.underlineThickness) * designUnitsPerPx;
const auto strikethroughPosition = static_cast<f32>(-metrics.strikethroughPosition) * designUnitsPerPx;
const auto strikethroughThickness = static_cast<f32>(metrics.strikethroughThickness) * designUnitsPerPx;
const auto baseline = std::roundf(ascent + (lineGap + adjustedHeight - advanceHeight) / 2.0f);
const auto underlinePos = std::roundf(baseline + underlinePosition);
const auto underlineWidth = std::max(1.0f, std::roundf(underlineThickness));
@@ -809,21 +851,13 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
const auto cellWidth = gsl::narrow<u16>(lrintf(adjustedWidth));
const auto cellHeight = gsl::narrow<u16>(lrintf(adjustedHeight));
{
til::size coordSize;
coordSize.width = cellWidth;
coordSize.height = cellHeight;
if (requestedSize.width == 0)
{
// The coordSizeUnscaled parameter to SetFromEngine is used for API functions like GetConsoleFontSize.
// Since clients expect that settings the font height to Y yields back a font height of Y,
// we're scaling the X relative/proportional to the actual cellWidth/cellHeight ratio.
requestedSize.width = gsl::narrow_cast<til::CoordType>(lrintf(fontSize / cellHeight * cellWidth));
}
fontInfo.SetFromEngine(primaryFontName, requestedFamily, requestedWeight, false, coordSize, requestedSize);
}
fontInfo.SetFaceName(faceName);
fontInfo.SetFamily(fontInfoDesired.GetFamily());
fontInfo.SetWeight(requestedWeight);
fontInfo.SetCodePage(fontInfoDesired.GetCodePage());
fontInfo.SetFontSizeInPt(fontSizeInPt);
fontInfo.SetCellSizeInDIP({ cellWidth / pxPerDIP, cellHeight / pxPerDIP });
fontInfo.SetCellSizeInPhysicalPx({ cellWidth, cellHeight });
if (fontMetrics)
{

View File

@@ -5,7 +5,7 @@
#include "../inc/CSSLengthPercentage.h"
CSSLengthPercentage CSSLengthPercentage::FromString(const wchar_t* str)
CSSLengthPercentage CSSLengthPercentage::FromString(const wchar_t* str) noexcept
{
auto& errnoRef = errno; // Nonzero cost, pay it once.
errnoRef = 0;
@@ -42,16 +42,35 @@ CSSLengthPercentage CSSLengthPercentage::FromString(const wchar_t* str)
}
else
{
return {};
value = 0;
}
}
// When we get weird input values we should pretend as if this instance is empty. To do so,
// we need to return ReferenceFrame::None, because otherwise we don't compare equal to a
// default constructed CSSLengthPercentage. This uses negation to properly handle NAN.
if (!(value > 0))
{
value = 0;
referenceFrame = ReferenceFrame::None;
}
CSSLengthPercentage obj;
obj._value = value;
obj._referenceFrame = referenceFrame;
return obj;
}
bool CSSLengthPercentage::operator==(const CSSLengthPercentage& other) const noexcept
{
return _referenceFrame == other._referenceFrame && abs(_value - other._value) < 0.0001;
}
CSSLengthPercentage::ReferenceFrame CSSLengthPercentage::Reference() const noexcept
{
return _referenceFrame;
}
float CSSLengthPercentage::Resolve(float fallback, float dpi, float fontSize, float advanceWidth) const noexcept
{
switch (_referenceFrame)

View File

@@ -4,27 +4,9 @@
#include "precomp.h"
#include "../inc/FontInfoBase.hpp"
FontInfoBase::FontInfoBase(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const unsigned int codePage) noexcept :
_faceName(faceName),
_family(family),
_weight(weight),
_fDefaultRasterSetFromEngine(fSetDefaultRasterFont),
_codePage(codePage)
const std::wstring& FontInfoBase::GetFaceName() const noexcept
{
ValidateFont();
}
bool FontInfoBase::operator==(const FontInfoBase& other) noexcept
{
return _faceName == other._faceName &&
_weight == other._weight &&
_family == other._family &&
_codePage == other._codePage &&
_fDefaultRasterSetFromEngine == other._fDefaultRasterSetFromEngine;
return _faceName;
}
unsigned char FontInfoBase::GetFamily() const noexcept
@@ -32,91 +14,41 @@ unsigned char FontInfoBase::GetFamily() const noexcept
return _family;
}
// When the default raster font is forced set from the engine, this is how we differentiate it from a simple apply.
// Default raster font is internally represented as a blank face name and zeros for weight, family, and size. This is
// the hint for the engine to use whatever comes back from GetStockObject(OEM_FIXED_FONT) (at least in the GDI world).
bool FontInfoBase::WasDefaultRasterSetFromEngine() const noexcept
{
return _fDefaultRasterSetFromEngine;
}
unsigned int FontInfoBase::GetWeight() const noexcept
{
return _weight;
}
const std::wstring& FontInfoBase::GetFaceName() const noexcept
{
return _faceName;
}
unsigned int FontInfoBase::GetCodePage() const noexcept
{
return _codePage;
}
// Method Description:
// - Populates a fixed-length **null-terminated** buffer with the name of this font, truncating it as necessary.
// Positions within the buffer that are not filled by the font name are zeroed.
// Arguments:
// - buffer: the buffer into which to copy characters
// - size: the size of buffer
void FontInfoBase::SetFaceName(std::wstring faceName) noexcept
{
_faceName = std::move(faceName);
}
void FontInfoBase::SetFamily(unsigned char family) noexcept
{
_family = family;
}
void FontInfoBase::SetWeight(unsigned int weight) noexcept
{
_weight = weight;
}
void FontInfoBase::SetCodePage(unsigned int codePage) noexcept
{
_codePage = codePage;
}
// Populates a fixed-length **null-terminated** buffer with the name of this font, truncating it as necessary.
// Positions within the buffer that are not filled by the font name are zeroed.
void FontInfoBase::FillLegacyNameBuffer(wchar_t (&buffer)[LF_FACESIZE]) const noexcept
{
const auto toCopy = std::min(std::size(buffer) - 1, _faceName.size());
const auto last = std::copy_n(_faceName.data(), toCopy, &buffer[0]);
*last = L'\0';
}
// NOTE: this method is intended to only be used from the engine itself to respond what font it has chosen.
void FontInfoBase::SetFromEngine(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont) noexcept
{
_faceName = faceName;
_family = family;
_weight = weight;
_fDefaultRasterSetFromEngine = fSetDefaultRasterFont;
}
// Internally, default raster font is represented by empty facename, and zeros for weight, family, and size. Since
// FontInfoBase doesn't have sizing information, this helper checks everything else.
bool FontInfoBase::IsDefaultRasterFontNoSize() const noexcept
{
return (_weight == 0 && _family == 0 && _faceName.empty());
}
void FontInfoBase::ValidateFont() noexcept
{
// If we were given a blank name, it meant raster fonts, which to us is always Terminal.
if (!IsDefaultRasterFontNoSize() && s_pFontDefaultList != nullptr)
{
// If we have a list of default fonts and our current font is the placeholder for the defaults, substitute here.
if (_faceName == DEFAULT_TT_FONT_FACENAME)
{
std::wstring defaultFontFace;
if (SUCCEEDED(s_pFontDefaultList->RetrieveDefaultFontNameForCodepage(GetCodePage(),
defaultFontFace)))
{
_faceName = defaultFontFace;
// If we're assigning a default true type font name, make sure the family is also set to TrueType
// to help GDI select the appropriate font when we actually create it.
_family = TMPF_TRUETYPE;
}
}
}
}
bool FontInfoBase::IsTrueTypeFont() const noexcept
{
return WI_IsFlagSet(_family, TMPF_TRUETYPE);
}
Microsoft::Console::Render::IFontDefaultList* FontInfoBase::s_pFontDefaultList;
void FontInfoBase::s_SetFontDefaultList(_In_ Microsoft::Console::Render::IFontDefaultList* const pFontDefaultList) noexcept
{
s_pFontDefaultList = pFontDefaultList;
}

View File

@@ -5,40 +5,6 @@
#include "../inc/FontInfoDesired.hpp"
FontInfoDesired::FontInfoDesired(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const float fontSize,
const unsigned int codePage) noexcept :
FontInfoBase(faceName, family, weight, false, codePage),
_coordSizeDesired{ 0, lroundf(fontSize) },
_fontSize{ fontSize }
{
}
FontInfoDesired::FontInfoDesired(const FontInfo& fiFont) noexcept :
FontInfoBase(fiFont),
_coordSizeDesired{ fiFont.GetUnscaledSize() },
_fontSize{ static_cast<float>(_coordSizeDesired.height) }
{
}
void FontInfoDesired::SetCellSize(const CSSLengthPercentage& cellWidth, const CSSLengthPercentage& cellHeight) noexcept
{
_cellWidth = cellWidth;
_cellHeight = cellHeight;
}
void FontInfoDesired::SetEnableBuiltinGlyphs(bool builtinGlyphs) noexcept
{
_builtinGlyphs = builtinGlyphs;
}
void FontInfoDesired::SetEnableColorGlyphs(bool colorGlyphs) noexcept
{
_colorGlyphs = colorGlyphs;
}
const CSSLengthPercentage& FontInfoDesired::GetCellWidth() const noexcept
{
return _cellWidth;
@@ -49,6 +15,11 @@ const CSSLengthPercentage& FontInfoDesired::GetCellHeight() const noexcept
return _cellHeight;
}
float FontInfoDesired::GetFontSizeInPt() const noexcept
{
return _fontSizeInPt;
}
bool FontInfoDesired::GetEnableBuiltinGlyphs() const noexcept
{
return _builtinGlyphs;
@@ -59,20 +30,48 @@ bool FontInfoDesired::GetEnableColorGlyphs() const noexcept
return _colorGlyphs;
}
float FontInfoDesired::GetFontSize() const noexcept
void FontInfoDesired::SetCellWidth(CSSLengthPercentage cellWidth) noexcept
{
return _fontSize;
_cellWidth = cellWidth;
}
til::size FontInfoDesired::GetEngineSize() const noexcept
void FontInfoDesired::SetCellHeight(CSSLengthPercentage cellHeight) noexcept
{
auto coordSize = _coordSizeDesired;
if (IsTrueTypeFont())
{
coordSize.width = 0; // Don't tell the engine about the width for a TrueType font. It makes a mess.
}
_cellHeight = cellHeight;
}
return coordSize;
void FontInfoDesired::SetFontSizeInPt(float fontSizeInPt) noexcept
{
_fontSizeInPt = fontSizeInPt;
}
void FontInfoDesired::SetEnableBuiltinGlyphs(bool builtinGlyphs) noexcept
{
_builtinGlyphs = builtinGlyphs;
}
void FontInfoDesired::SetEnableColorGlyphs(bool colorGlyphs) noexcept
{
_colorGlyphs = colorGlyphs;
}
til::size FontInfoDesired::GetPixelCellSize() const noexcept
{
return {
lrintf(_cellWidth.Resolve(0, 96.0f, 12.0f, 0)),
lrintf(_cellHeight.Resolve(0, 96.0f, 12.0f, 0)),
};
}
void FontInfoDesired::SetPixelCellSize(til::size size) noexcept
{
_cellWidth = CSSLengthPercentage::FromPixel(static_cast<float>(size.width));
_cellHeight = CSSLengthPercentage::FromPixel(static_cast<float>(size.height));
}
bool FontInfoDesired::IsTrueTypeFont() const noexcept
{
return WI_IsFlagSet(_family, TMPF_TRUETYPE);
}
// This helper determines if this object represents the default raster font. This can either be because internally we're
@@ -80,9 +79,10 @@ til::size FontInfoDesired::GetEngineSize() const noexcept
// dimensions from the engine that were the result of loading the default raster font. See GdiEngine::_GetProposedFont().
bool FontInfoDesired::IsDefaultRasterFont() const noexcept
{
// Either the raster was set from the engine...
// OR the face name is empty with a size of 0x0 or 8x12.
return WasDefaultRasterSetFromEngine() || (GetFaceName().empty() &&
(_coordSizeDesired == til::size{ 0, 0 } ||
_coordSizeDesired == til::size{ 8, 12 }));
static constexpr CSSLengthPercentage s_0 = CSSLengthPercentage::FromPixel(0);
static constexpr CSSLengthPercentage s_8 = CSSLengthPercentage::FromPixel(8);
static constexpr CSSLengthPercentage s_12 = CSSLengthPercentage::FromPixel(12);
return _faceName.empty() &&
((_cellWidth == s_0 && _cellHeight == s_0) ||
(_cellWidth == s_8 && _cellHeight == s_12));
}

View File

@@ -5,87 +5,46 @@
#include "../inc/FontInfo.hpp"
FontInfo::FontInfo(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const til::size coordSize,
const unsigned int codePage,
const bool fSetDefaultRasterFont /* = false */) noexcept :
FontInfoBase(faceName, family, weight, fSetDefaultRasterFont, codePage),
_coordSize(coordSize),
_coordSizeUnscaled(coordSize),
_didFallback(false)
// Truncates this size in DIPs to integers.
//
// "Do Not Use" because the conversion is lossy and doesn't roundtrip.
// It exists because we have legacy code and this is a discoverable "marker".
til::size CellSizeInDIP::AsInteger_DoNotUse() const noexcept
{
ValidateFont();
return { til::math::rounding, width, height };
}
bool FontInfo::operator==(const FontInfo& other) noexcept
float FontInfo::GetFontSizeInDIP() const noexcept
{
return FontInfoBase::operator==(other) &&
_coordSize == other._coordSize &&
_coordSizeUnscaled == other._coordSizeUnscaled;
return _fontSizeInPt;
}
til::size FontInfo::GetUnscaledSize() const noexcept
CellSizeInDIP FontInfo::GetCellSizeInDIP() const noexcept
{
return _coordSizeUnscaled;
return _cellSizeInDIP;
}
til::size FontInfo::GetSize() const noexcept
til::size FontInfo::GetCellSizeInPhysicalPx() const noexcept
{
return _coordSize;
return _cellSizeInPhysicalPx;
}
void FontInfo::SetFromEngine(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const til::size coordSize,
const til::size coordSizeUnscaled) noexcept
void FontInfo::SetFontSizeInPt(float fontSizeInPt) noexcept
{
FontInfoBase::SetFromEngine(faceName,
family,
weight,
fSetDefaultRasterFont);
_coordSize = coordSize;
_coordSizeUnscaled = coordSizeUnscaled;
_ValidateCoordSize();
_fontSizeInPt = fontSizeInPt;
}
bool FontInfo::GetFallback() const noexcept
void FontInfo::SetCellSizeInDIP(CellSizeInDIP cellSizeInDIP) noexcept
{
return _didFallback;
_cellSizeInDIP = cellSizeInDIP;
}
void FontInfo::SetFallback(const bool didFallback) noexcept
void FontInfo::SetCellSizeInPhysicalPx(til::size cellSizeInPhysicalPx) noexcept
{
_didFallback = didFallback;
_cellSizeInPhysicalPx = cellSizeInPhysicalPx;
}
void FontInfo::ValidateFont() noexcept
bool FontInfo::IsTrueTypeFont() const noexcept
{
_ValidateCoordSize();
}
void FontInfo::_ValidateCoordSize() noexcept
{
// a (0,0) font is okay for the default raster font, as we will eventually set the dimensions based on the font GDI
// passes back to us.
if (!IsDefaultRasterFontNoSize())
{
// Initialize X to 1 so we don't divide by 0
if (_coordSize.width == 0)
{
_coordSize.width = 1;
}
// If we have no font size, we want to use 8x12 by default
if (_coordSize.height == 0)
{
_coordSize.width = 8;
_coordSize.height = 12;
_coordSizeUnscaled = _coordSize;
}
}
return WI_IsFlagSet(_family, TMPF_TRUETYPE);
}

View File

@@ -30,7 +30,6 @@
<ClInclude Include="..\..\inc\FontInfoBase.hpp" />
<ClInclude Include="..\..\inc\FontInfoDesired.hpp" />
<ClInclude Include="..\..\inc\FontResource.hpp" />
<ClInclude Include="..\..\inc\IFontDefaultList.hpp" />
<ClInclude Include="..\..\inc\IRenderData.hpp" />
<ClInclude Include="..\..\inc\IRenderEngine.hpp" />
<ClInclude Include="..\..\inc\RenderEngineBase.hpp" />

View File

@@ -65,9 +65,6 @@
<ClInclude Include="..\..\inc\FontResource.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\IFontDefaultList.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\IRenderData.hpp">
<Filter>Header Files\inc</Filter>
</ClInclude>
@@ -93,5 +90,6 @@
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natstepfilter" />
</ItemGroup>
</Project>

View File

@@ -189,9 +189,6 @@ namespace Microsoft::Console::Render
static const ULONG s_ulMinCursorHeightPercent = 25;
static const ULONG s_ulMaxCursorHeightPercent = 100;
static int s_ScaleByDpi(const int iPx, const int iDpi);
static int s_ShrinkByDpi(const int iPx, const int iDpi);
til::point _GetInvalidRectPoint() const;
til::size _GetInvalidRectSize() const;
til::size _GetRectSize(const RECT* const pRect) const;

View File

@@ -70,30 +70,6 @@ using namespace Microsoft::Console::Render;
return S_OK;
}
// Routine Description:
// - Scales the given pixel measurement up from the typical system DPI (generally 96) to whatever the given DPI is.
// Arguments:
// - iPx - Pixel length measurement.
// - iDpi - Given DPI scalar value
// Return Value:
// - Pixel measurement scaled against the given DPI scalar.
int GdiEngine::s_ScaleByDpi(const int iPx, const int iDpi)
{
return MulDiv(iPx, iDpi, s_iBaseDpi);
}
// Routine Description:
// - Shrinks the given pixel measurement down from whatever the given DPI is to the typical system DPI (generally 96).
// Arguments:
// - iPx - Pixel measurement scaled against the given DPI.
// - iDpi - Given DPI for pixel scaling
// Return Value:
// - Pixel length measurement.
int GdiEngine::s_ShrinkByDpi(const int iPx, const int iDpi)
{
return MulDiv(iPx, s_iBaseDpi, iDpi);
}
// Routine Description:
// - Uses internal invalid structure to determine the top left pixel point of the invalid frame to be painted.
// Arguments:

View File

@@ -366,7 +366,7 @@ GdiEngine::~GdiEngine()
// There is no font metric for the grid line width, so we use a small
// multiple of the font size, which typically rounds to a pixel.
const auto cellHeight = static_cast<float>(Font.GetSize().height);
const auto cellHeight = static_cast<float>(Font.GetCellSizeInPhysicalPx().height);
const auto fontSize = static_cast<float>(_tmFontMetrics.tmHeight - _tmFontMetrics.tmInternalLeading);
const auto baseline = static_cast<float>(_tmFontMetrics.tmAscent);
float idealGridlineWidth = std::max(1.0f, fontSize * 0.025f);
@@ -471,7 +471,7 @@ GdiEngine::~GdiEngine()
_lineMetrics.curlyLineControlPointOffset = lroundf(curlyLineControlPointOffset);
// Now find the size of a 0 in this current font and save it for conversions done later.
_coordFontLast = Font.GetSize();
_coordFontLast = Font.GetCellSizeInPhysicalPx();
for (auto& hfont : _hfonts)
{
@@ -599,8 +599,7 @@ GdiEngine::~GdiEngine()
wil::unique_hdc hdcTemp(CreateCompatibleDC(_hdcMemoryContext));
RETURN_HR_IF_NULL(E_FAIL, hdcTemp.get());
// Get a special engine size because TT fonts can't specify X or we'll get weird scaling under some circumstances.
auto coordFontRequested = FontDesired.GetEngineSize();
const auto dpi = static_cast<float>(iDpi);
// First, check to see if we're asking for the default raster font.
if (FontDesired.IsDefaultRasterFont())
@@ -632,8 +631,8 @@ GdiEngine::~GdiEngine()
// attention to the font previews to ensure that the font being selected by GDI is exactly the font requested --
// some monospace fonts look very similar.
LOGFONTW lf = { 0 };
lf.lfHeight = s_ScaleByDpi(coordFontRequested.height, iDpi);
lf.lfWidth = s_ScaleByDpi(coordFontRequested.width, iDpi);
lf.lfHeight = lroundf(FontDesired.GetCellHeight().Resolve(16, dpi, 12, 0));
lf.lfWidth = lroundf(FontDesired.GetCellWidth().Resolve(0, dpi, 12, 0));
lf.lfWeight = FontDesired.GetWeight();
// If we're searching for Terminal, our supported Raster Font, then we must use OEM_CHARSET.
@@ -665,7 +664,17 @@ GdiEngine::~GdiEngine()
lf.lfQuality = DRAFT_QUALITY;
// NOTE: not using what GDI gave us because some fonts don't quite roundtrip (e.g. MS Gothic and VL Gothic)
// SetCurrentConsoleFontEx allows setting a "FontFamily" but at the time of writing this field is
// entirely unused in GdiEngine. Instead it sets the LOGFONT lfPitchAndFamily field to the following
// constant at all times. It's unclear when this change occurred and why, but it was described as:
// NOTE: not using what GDI gave us because some fonts don't quite roundtrip (e.g. MS Gothic and VL Gothic)
//
// To be entirely honest this sounds like a mistake to me. From what I can tell a "roundtrip" issue did
// in fact occur but only because someone mistakenly constructed the "new desired font info" from the
// previous "actual font info", which is inherently incorrect, because CreateFontIndirect is a lossy
// process. The correct fix would have been to fill the new "desired font info" based on the previous
// "desired font info" instead. In any case, changing this constant now without understanding the
// entire system behind it (I certainly don't) would probably just exchange one bug with another.
lf.lfPitchAndFamily = (FIXED_PITCH | FF_MODERN);
FontDesired.FillLegacyNameBuffer(lf.lfFaceName);
@@ -702,8 +711,8 @@ GdiEngine::~GdiEngine()
RETURN_HR_IF_NULL(E_FAIL, hFontOld.get());
// Save off the font metrics for various other calculations
TEXTMETRICW tm;
RETURN_HR_IF(E_FAIL, !(GetTextMetricsW(hdcTemp.get(), &tm)));
OUTLINETEXTMETRICW tm;
RETURN_HR_IF(E_FAIL, !(GetOutlineTextMetricsW(hdcTemp.get(), sizeof(tm), &tm)));
// Now find the size of a 0 in this current font and save it for conversions done later.
SIZE sz;
@@ -741,21 +750,13 @@ GdiEngine::~GdiEngine()
currentFaceName.resize(faceNameLength - 1); // remove the null terminator (wstring!)
if (FontDesired.IsDefaultRasterFont())
{
coordFontRequested = coordFont;
}
else if (coordFontRequested.width == 0)
{
coordFontRequested.width = s_ShrinkByDpi(coordFont.width, iDpi);
}
Font.SetFromEngine(currentFaceName,
tm.tmPitchAndFamily,
gsl::narrow_cast<unsigned int>(tm.tmWeight),
FontDesired.IsDefaultRasterFont(),
coordFont,
coordFontRequested);
Font.SetFaceName(std::move(currentFaceName));
Font.SetFamily(tm.otmTextMetrics.tmPitchAndFamily);
Font.SetWeight(tm.otmTextMetrics.tmWeight);
Font.SetCodePage(FontDesired.GetCodePage());
Font.SetFontSizeInPt((tm.otmAscent - tm.otmDescent) * 72.0f / dpi);
Font.SetCellSizeInDIP({ coordFont.width * 96.0f / dpi, coordFont.height * 96.0f / dpi });
Font.SetCellSizeInPhysicalPx(coordFont);
}
return S_OK;

View File

@@ -9,20 +9,42 @@ struct CSSLengthPercentage
{
// This indicates the object is empty/unset.
// No need to call Resolve().
//
// _value will be 0.
None,
// Call Resolve() with factor set to the target DPI (e.g. 96 for DIP).
// Returns an absolute length value scaled by that DPI.
//
// Inputs with a "pt" or "px" suffix are considered "absolute".
// _value contains an absolute size in CSS inches. In other words,
// an input of "96px" or "72pt" results in a _value of 1.
Absolute,
// Call Resolve() with factor set to the font size
// in an arbitrary DPI. Returns a value relative to it.
//
// Inputs with no suffix or "%" are considered font-size dependent.
// _value should be multiplied by the current font-size to get the new font-size.
FontSize,
// Call Resolve() with factor set to the "0" glyph advance width
// in an arbitrary DPI. Returns a value relative to it.
//
// Inputs with a "ch" suffix are considered advance-width dependent.
// _value should be multiplied by the current advance-width to get the new font-size.
AdvanceWidth,
};
static CSSLengthPercentage FromString(const wchar_t* str);
static CSSLengthPercentage FromString(const wchar_t* str) noexcept;
static constexpr CSSLengthPercentage FromPixel(float px) noexcept
{
CSSLengthPercentage obj;
obj._value = px / 96.0f;
obj._referenceFrame = ReferenceFrame::Absolute;
return obj;
}
bool operator==(const CSSLengthPercentage& other) const noexcept;
ReferenceFrame Reference() const noexcept;
float Resolve(float fallback, float dpi, float fontSize, float advanceWidth) const noexcept;
private:

View File

@@ -25,34 +25,29 @@ Author(s):
#include "FontInfoBase.hpp"
class FontInfo : public FontInfoBase
struct CellSizeInDIP
{
public:
FontInfo(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const til::size coordSize,
const unsigned int codePage,
const bool fSetDefaultRasterFont = false) noexcept;
float width = 0;
float height = 0;
bool operator==(const FontInfo& other) noexcept;
til::size AsInteger_DoNotUse() const noexcept;
};
til::size GetSize() const noexcept;
til::size GetUnscaledSize() const noexcept;
void SetFromEngine(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const til::size coordSize,
const til::size coordSizeUnscaled) noexcept;
bool GetFallback() const noexcept;
void SetFallback(const bool didFallback) noexcept;
void ValidateFont() noexcept;
struct FontInfo : FontInfoBase
{
float GetFontSizeInDIP() const noexcept;
CellSizeInDIP GetCellSizeInDIP() const noexcept;
til::size GetCellSizeInPhysicalPx() const noexcept;
// NOTE: Render backends are expected to call all of these setters, plus all FontInfoBase setters.
void SetFontSizeInPt(float fontSizeInPt) noexcept;
void SetCellSizeInDIP(CellSizeInDIP cellSizeInDIP) noexcept;
void SetCellSizeInPhysicalPx(til::size cellSizeInPhysicalPx) noexcept;
bool IsTrueTypeFont() const noexcept;
private:
void _ValidateCoordSize() noexcept;
til::size _coordSize;
til::size _coordSizeUnscaled;
bool _didFallback;
float _fontSizeInPt = 0;
CellSizeInDIP _cellSizeInDIP;
til::size _cellSizeInPhysicalPx;
};

View File

@@ -18,45 +18,26 @@ Author(s):
#pragma once
#include "IFontDefaultList.hpp"
inline constexpr wchar_t DEFAULT_TT_FONT_FACENAME[]{ L"__DefaultTTFont__" };
inline constexpr wchar_t DEFAULT_RASTER_FONT_FACENAME[]{ L"Terminal" };
class FontInfoBase
struct FontInfoBase
{
public:
FontInfoBase(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const unsigned int uiCodePage) noexcept;
bool operator==(const FontInfoBase& other) noexcept;
const std::wstring& GetFaceName() const noexcept;
unsigned char GetFamily() const noexcept;
unsigned int GetWeight() const noexcept;
const std::wstring& GetFaceName() const noexcept;
unsigned int GetCodePage() const noexcept;
void FillLegacyNameBuffer(wchar_t (&buffer)[LF_FACESIZE]) const noexcept;
bool IsTrueTypeFont() const noexcept;
void SetFromEngine(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont) noexcept;
bool WasDefaultRasterSetFromEngine() const noexcept;
void ValidateFont() noexcept;
static Microsoft::Console::Render::IFontDefaultList* s_pFontDefaultList;
static void s_SetFontDefaultList(_In_ Microsoft::Console::Render::IFontDefaultList* const pFontDefaultList) noexcept;
void SetFaceName(std::wstring faceName) noexcept;
void SetFamily(unsigned char family) noexcept;
void SetWeight(unsigned int weight) noexcept;
void SetCodePage(unsigned int codePage) noexcept;
void FillLegacyNameBuffer(wchar_t (&buffer)[LF_FACESIZE]) const noexcept;
protected:
bool IsDefaultRasterFontNoSize() const noexcept;
private:
std::wstring _faceName;
unsigned int _weight;
unsigned char _family;
unsigned int _codePage;
bool _fDefaultRasterSetFromEngine;
unsigned char _family = 0;
unsigned int _weight = 0;
unsigned int _codePage = 0;
};

View File

@@ -19,38 +19,31 @@ Author(s):
#pragma once
#include "FontInfoBase.hpp"
#include "FontInfo.hpp"
#include "CSSLengthPercentage.h"
class FontInfoDesired : public FontInfoBase
struct FontInfoDesired : FontInfoBase
{
public:
FontInfoDesired(const std::wstring_view& faceName,
const unsigned char family,
const unsigned int weight,
const float fontSize,
const unsigned int uiCodePage) noexcept;
FontInfoDesired(const FontInfo& fiFont) noexcept;
const CSSLengthPercentage& GetCellWidth() const noexcept;
const CSSLengthPercentage& GetCellHeight() const noexcept;
float GetFontSizeInPt() const noexcept;
bool GetEnableBuiltinGlyphs() const noexcept;
bool GetEnableColorGlyphs() const noexcept;
bool operator==(const FontInfoDesired& other) = delete;
void SetCellSize(const CSSLengthPercentage& cellWidth, const CSSLengthPercentage& cellHeight) noexcept;
void SetCellWidth(CSSLengthPercentage cellWidth) noexcept;
void SetCellHeight(CSSLengthPercentage cellHeight) noexcept;
void SetFontSizeInPt(float fontSizeInPt) noexcept;
void SetEnableBuiltinGlyphs(bool builtinGlyphs) noexcept;
void SetEnableColorGlyphs(bool colorGlyphs) noexcept;
const CSSLengthPercentage& GetCellWidth() const noexcept;
const CSSLengthPercentage& GetCellHeight() const noexcept;
bool GetEnableBuiltinGlyphs() const noexcept;
bool GetEnableColorGlyphs() const noexcept;
float GetFontSize() const noexcept;
til::size GetEngineSize() const noexcept;
til::size GetPixelCellSize() const noexcept;
void SetPixelCellSize(til::size size) noexcept;
bool IsTrueTypeFont() const noexcept;
bool IsDefaultRasterFont() const noexcept;
private:
til::size _coordSizeDesired;
float _fontSize;
CSSLengthPercentage _cellWidth;
CSSLengthPercentage _cellHeight;
float _fontSizeInPt = 0;
bool _builtinGlyphs = false;
bool _colorGlyphs = true;
};

View File

@@ -1,24 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- IFontDefaultList.hpp
Abstract:
- This serves as an abstraction to retrieve a list of default preferred fonts that we should use if the user hasn't chosen one.
Author(s):
- Michael Niksa (MiNiksa) 14-Mar-2016
--*/
#pragma once
namespace Microsoft::Console::Render
{
class IFontDefaultList
{
public:
[[nodiscard]] virtual HRESULT RetrieveDefaultFontNameForCodepage(const unsigned int codepage,
std::wstring& outFaceName) = 0;
};
}

View File

@@ -1291,7 +1291,7 @@ IFACEMETHODIMP UiaTextRangeBase::GetChildren(_Outptr_result_maybenull_ SAFEARRAY
til::size UiaTextRangeBase::_getScreenFontSize() const noexcept
{
auto coordRet = _pData->GetFontInfo().GetSize();
auto coordRet = _pData->GetFontInfo().GetCellSizeInPhysicalPx();
// For sanity's sake, make sure not to leak 0 out as a possible value. These values are used in division operations.
coordRet.width = std::max(coordRet.width, 1);

View File

@@ -145,6 +145,14 @@
</Expand>
</Type>
<Type Name="CSSLengthPercentage">
<DisplayString Condition="_referenceFrame == 0">[empty]</DisplayString>
<DisplayString Condition="_referenceFrame == 1" Optional="true">{_value*72,g}pt / {_value*96,g}px</DisplayString>
<DisplayString Condition="_referenceFrame == 2 &amp;&amp; _value &lt;= 1" Optional="true">{_value*100,g}%</DisplayString>
<DisplayString Condition="_referenceFrame == 2 &amp;&amp; _value &gt; 1" Optional="true">{_value,g}</DisplayString>
<DisplayString Condition="_referenceFrame == 3" Optional="true">{_value,g}ch</DisplayString>
</Type>
<Type Name="Microsoft::Console::Render::Atlas::Buffer&lt;*&gt;">
<DisplayString>{{ size={_size} }}</DisplayString>
<Expand>