Files
terminal/src/renderer/gdi/gdirenderer.hpp
Alex Alabuzhev 84cc3e3e52 Add initial bold font support to the GDI renderer (#19441)
Render SGR1 as bold in 256 and true colors, where "bold is intense" is
not applicable.
Implemented by creating 2 extra fonts: bold for 1 and bold italic for 1
+ 3.

No non-trivial changes, just extensions.
LOGFONT also supports Underline and StrikeOut, but they seem to be
already covered by other means, so no combinatorial explosion of fonts
expected.

Refs #18919

Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2025-10-14 17:00:13 -05:00

235 lines
9.6 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- GdiRenderer.hpp
Abstract:
- This is the definition of the GDI specific implementation of the renderer.
Author(s):
- Michael Niksa (MiNiksa) 17-Nov-2015
--*/
#pragma once
#include "../inc/RenderEngineBase.hpp"
#include "../inc/FontResource.hpp"
namespace Microsoft::Console::Render
{
class GdiEngine final : public RenderEngineBase
{
public:
GdiEngine();
~GdiEngine() override;
[[nodiscard]] HRESULT SetHwnd(const HWND hwnd) noexcept;
[[nodiscard]] HRESULT InvalidateSelection(std::span<const til::rect> selections) noexcept override;
[[nodiscard]] HRESULT InvalidateScroll(const til::point* const pcoordDelta) noexcept override;
[[nodiscard]] HRESULT InvalidateSystem(const til::rect* const prcDirtyClient) noexcept override;
[[nodiscard]] HRESULT Invalidate(const til::rect* const psrRegion) noexcept override;
[[nodiscard]] HRESULT InvalidateCursor(const til::rect* const psrRegion) noexcept override;
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
[[nodiscard]] HRESULT StartPaint() noexcept override;
[[nodiscard]] HRESULT EndPaint() noexcept override;
[[nodiscard]] HRESULT Present() noexcept override;
[[nodiscard]] HRESULT ScrollFrame() noexcept override;
[[nodiscard]] HRESULT ResetLineTransform() noexcept override;
[[nodiscard]] HRESULT PrepareLineTransform(const LineRendition lineRendition,
const til::CoordType targetRow,
const til::CoordType viewportLeft) noexcept override;
[[nodiscard]] HRESULT PaintBackground() noexcept override;
[[nodiscard]] HRESULT PaintBufferLine(const std::span<const Cluster> clusters,
const til::point coord,
const bool trimLeft,
const bool lineWrapped) noexcept override;
[[nodiscard]] HRESULT PaintBufferGridLines(const GridLineSet lines,
const COLORREF gridlineColor,
const COLORREF underlineColor,
const size_t cchLine,
const til::point coordTarget) noexcept override;
[[nodiscard]] HRESULT PaintImageSlice(const ImageSlice& imageSlice,
const til::CoordType targetRow,
const til::CoordType viewportLeft) noexcept override;
[[nodiscard]] HRESULT PaintSelection(const til::rect& rect) noexcept override;
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes,
const RenderSettings& renderSettings,
const gsl::not_null<IRenderData*> pData,
const bool usingSoftFont,
const bool isSettingDefaultBrushes) noexcept override;
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired,
_Out_ FontInfo& FontInfo) noexcept override;
[[nodiscard]] HRESULT UpdateSoftFont(const std::span<const uint16_t> bitPattern,
const til::size cellSize,
const size_t centeringHint) noexcept override;
[[nodiscard]] HRESULT UpdateDpi(const int iDpi) noexcept override;
[[nodiscard]] HRESULT UpdateViewport(const til::inclusive_rect& srNewViewport) noexcept override;
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& FontDesired,
_Out_ FontInfo& Font,
const int iDpi) noexcept override;
[[nodiscard]] HRESULT GetDirtyArea(std::span<const til::rect>& area) noexcept override;
[[nodiscard]] HRESULT GetFontSize(_Out_ til::size* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
protected:
[[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring_view newTitle) noexcept override;
private:
HWND _hwndTargetWindow;
[[nodiscard]] static HRESULT s_SetWindowLongWHelper(const HWND hWnd,
const int nIndex,
const LONG dwNewLong) noexcept;
static bool FontHasWesternScript(HDC hdc);
bool _fPaintStarted;
til::rect _invalidCharacters;
PAINTSTRUCT _psInvalidData;
HDC _hdcMemoryContext;
bool _isTrueTypeFont;
UINT _fontCodepage;
enum class FontType : uint8_t
{
// Indices for _hfonts array below
Default,
Bold,
Italic,
BoldItalic,
// The number of fonts in _hfonts array below
FontCount,
// Other
Undefined = FontCount,
Soft
};
std::array<HFONT, static_cast<size_t>(FontType::FontCount)> _hfonts{};
TEXTMETRICW _tmFontMetrics;
FontResource _softFont;
static const size_t s_cPolyTextCache = 80;
POLYTEXTW _pPolyText[s_cPolyTextCache];
size_t _cPolyText;
[[nodiscard]] HRESULT _FlushBufferLines() noexcept;
std::vector<RECT> cursorInvertRects;
XFORM cursorInvertTransform;
struct LineMetrics
{
int gridlineWidth;
int underlineCenter;
int underlineWidth;
int doubleUnderlinePosTop;
int doubleUnderlinePosBottom;
int doubleUnderlineWidth;
int strikethroughOffset;
int strikethroughWidth;
int curlyLineCenter;
int curlyLinePeriod;
int curlyLineControlPointOffset;
};
LineMetrics _lineMetrics;
til::size _coordFontLast;
int _iCurrentDpi;
static const int s_iBaseDpi = USER_DEFAULT_SCREEN_DPI;
til::size _szMemorySurface;
HBITMAP _hbitmapMemorySurface;
[[nodiscard]] HRESULT _PrepareMemoryBitmap(const HWND hwnd) noexcept;
til::size _szInvalidScroll;
til::rect _rcInvalid;
bool _fInvalidRectUsed;
COLORREF _lastFg;
COLORREF _lastBg;
FontType _lastFontType;
bool _fontHasWesternScript = false;
XFORM _currentLineTransform;
LineRendition _currentLineRendition;
// Memory pooling to save alloc/free work to the OS for things
// frequently created and dropped.
// It's important the pool is first so it can be given to the others on construction.
std::pmr::unsynchronized_pool_resource _pool;
std::pmr::vector<std::pmr::wstring> _polyStrings;
std::pmr::vector<std::pmr::vector<int>> _polyWidths;
std::vector<DWORD> _imageMask;
[[nodiscard]] HRESULT _InvalidCombine(const til::rect* const prc) noexcept;
[[nodiscard]] HRESULT _InvalidOffset(const til::point* const ppt) noexcept;
[[nodiscard]] HRESULT _InvalidRestrict() noexcept;
[[nodiscard]] HRESULT _InvalidateRect(const til::rect* const prc) noexcept;
[[nodiscard]] HRESULT _PaintBackgroundColor(const RECT* const prc) noexcept;
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;
void _OrRect(_In_ til::rect* const pRectExisting, const til::rect* const pRectToOr) const;
bool _IsFontTrueType() const;
[[nodiscard]] HRESULT _GetProposedFont(const FontInfoDesired& FontDesired,
_Out_ FontInfo& Font,
const int iDpi,
_Inout_ std::array<wil::unique_hfont, static_cast<size_t>(FontType::FontCount)>& hFonts) noexcept;
til::size _GetFontSize() const;
bool _IsMinimized() const;
bool _IsWindowValid() const;
#ifdef DBG
// Helper functions to diagnose issues with painting from the in-memory buffer.
// These are only actually effective/on in Debug builds when the flag is set using an attached debugger.
bool _fDebug = false;
void _PaintDebugRect(const RECT* const prc) const;
void _DoDebugBlt(const RECT* const prc) const;
void _DebugBltAll() const;
HWND _debugWindow;
void _CreateDebugWindow();
HDC _debugContext;
#endif
};
constexpr XFORM IDENTITY_XFORM = { 1, 0, 0, 1 };
inline bool operator==(const XFORM& lhs, const XFORM& rhs) noexcept
{
return ::memcmp(&lhs, &rhs, sizeof(XFORM)) == 0;
};
}