Skip to content

Commit

Permalink
Introduce DxFontRenderData (#9096)
Browse files Browse the repository at this point in the history
This is my attempt to isolate all the dwrite font related thing by
introducing a new layer - `DxFontRenderData`. This will free
`DxRenderer` & `CustomTextLayout` from the burden of handling fonts &
box effects. The logic is more simplified & streamlined.

In short I just moved everything fonts-related into `DxFontRenderData`
and started from there. There's no modification to code logic. Just pure
structural stuff.

SGR support tracking issue: #6879
Initial Italic support PR: #8580
  • Loading branch information
skyline75489 authored Feb 18, 2021
1 parent 4c53c59 commit eb34993
Show file tree
Hide file tree
Showing 10 changed files with 928 additions and 875 deletions.
2 changes: 1 addition & 1 deletion src/renderer/base/lib/base.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<RootNamespace>base</RootNamespace>
<ProjectName>RendererBase</ProjectName>
<TargetName>ConRenderBase</TargetName>
<ConfigurationType>StaticLibrary</ConfigurationType>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>
Expand Down
311 changes: 23 additions & 288 deletions src/renderer/dx/CustomTextLayout.cpp

Large diffs are not rendered by default.

25 changes: 4 additions & 21 deletions src/renderer/dx/CustomTextLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <wrl/implements.h>

#include "BoxDrawingEffect.h"
#include "DxFontRenderData.h"
#include "../inc/Cluster.hpp"

namespace Microsoft::Console::Render
Expand All @@ -20,14 +21,7 @@ namespace Microsoft::Console::Render
public:
// Based on the Windows 7 SDK sample at https://github.com/pauldotknopf/WindowsSDK7-Samples/tree/master/multimedia/DirectWrite/CustomLayout

CustomTextLayout(gsl::not_null<IDWriteFactory1*> const factory,
gsl::not_null<IDWriteTextAnalyzer1*> const analyzer,
gsl::not_null<IDWriteTextFormat*> const normalFormat,
gsl::not_null<IDWriteTextFormat*> const italicFormat,
gsl::not_null<IDWriteFontFace1*> const normalFont,
gsl::not_null<IDWriteFontFace1*> const italicFont,
size_t const width,
IBoxDrawingEffect* const boxEffect);
CustomTextLayout(gsl::not_null<DxFontRenderData*> const fontRenderData);

[[nodiscard]] HRESULT STDMETHODCALLTYPE AppendClusters(const gsl::span<const ::Microsoft::Console::Render::Cluster> clusters);

Expand Down Expand Up @@ -71,8 +65,6 @@ namespace Microsoft::Console::Render
UINT32 textLength,
_In_ IDWriteNumberSubstitution* numberSubstitution) override;

[[nodiscard]] static HRESULT STDMETHODCALLTYPE s_CalculateBoxEffect(IDWriteTextFormat* format, size_t widthPixels, IDWriteFontFace1* face, float fontScale, IBoxDrawingEffect** effect) noexcept;

protected:
// A single contiguous run of characters containing the same analysis results.
struct Run
Expand Down Expand Up @@ -157,24 +149,15 @@ namespace Microsoft::Console::Render
[[nodiscard]] static constexpr UINT32 _EstimateGlyphCount(const UINT32 textLength) noexcept;

private:
const ::Microsoft::WRL::ComPtr<IDWriteFactory1> _factory;

// DirectWrite analyzer
const ::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> _analyzer;
// DirectWrite font render data
DxFontRenderData* _fontRenderData;

// DirectWrite text formats
const ::Microsoft::WRL::ComPtr<IDWriteTextFormat> _format;
const ::Microsoft::WRL::ComPtr<IDWriteTextFormat> _formatItalic;
IDWriteTextFormat* _formatInUse;

// DirectWrite font faces
const ::Microsoft::WRL::ComPtr<IDWriteFontFace1> _font;
const ::Microsoft::WRL::ComPtr<IDWriteFontFace1> _fontItalic;
IDWriteFontFace1* _fontInUse;

// Box drawing effect
const ::Microsoft::WRL::ComPtr<IBoxDrawingEffect> _boxDrawingEffect;

// The text we're analyzing and processing into a layout
std::wstring _text;
std::vector<UINT16> _textClusterColumns;
Expand Down
755 changes: 755 additions & 0 deletions src/renderer/dx/DxFontRenderData.cpp

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions src/renderer/dx/DxFontRenderData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#pragma once

#include "../../renderer/inc/FontInfoDesired.hpp"
#include "BoxDrawingEffect.h"

#include <dwrite.h>
#include <dwrite_1.h>
#include <dwrite_2.h>
#include <dwrite_3.h>

#include <wrl.h>

namespace Microsoft::Console::Render
{
class DxFontRenderData
{
public:
struct LineMetrics
{
float gridlineWidth;
float underlineOffset;
float underlineOffset2;
float underlineWidth;
float strikethroughOffset;
float strikethroughWidth;
};

DxFontRenderData(::Microsoft::WRL::ComPtr<IDWriteFactory1> dwriteFactory) noexcept;

// DirectWrite text analyzer from the factory
[[nodiscard]] Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> Analyzer() noexcept;

[[nodiscard]] Microsoft::WRL::ComPtr<IDWriteFontFallback> SystemFontFallback();

[[nodiscard]] til::size GlyphCell() noexcept;
[[nodiscard]] LineMetrics GetLineMetrics() noexcept;

// The DirectWrite format object representing the size and other text properties to be applied (by default)
[[nodiscard]] Microsoft::WRL::ComPtr<IDWriteTextFormat> DefaultTextFormat() noexcept;

// The DirectWrite font face to use while calculating layout (by default)
[[nodiscard]] Microsoft::WRL::ComPtr<IDWriteFontFace1> DefaultFontFace() noexcept;

// Box drawing scaling effects that are cached for the base font across layouts
[[nodiscard]] Microsoft::WRL::ComPtr<IBoxDrawingEffect> DefaultBoxDrawingEffect() noexcept;

// The italic variant of the format object representing the size and other text properties for italic text
[[nodiscard]] Microsoft::WRL::ComPtr<IDWriteTextFormat> ItalicTextFormat() noexcept;

// The italic variant of the font face to use while calculating layout for italic text
[[nodiscard]] Microsoft::WRL::ComPtr<IDWriteFontFace1> ItalicFontFace() noexcept;

[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& desired, FontInfo& fiFontInfo, const int dpi) noexcept;

[[nodiscard]] static HRESULT STDMETHODCALLTYPE s_CalculateBoxEffect(IDWriteTextFormat* format, size_t widthPixels, IDWriteFontFace1* face, float fontScale, IBoxDrawingEffect** effect) noexcept;

private:
[[nodiscard]] ::Microsoft::WRL::ComPtr<IDWriteFontFace1> _ResolveFontFaceWithFallback(std::wstring& familyName,
DWRITE_FONT_WEIGHT& weight,
DWRITE_FONT_STRETCH& stretch,
DWRITE_FONT_STYLE& style,
std::wstring& localeName) const;

[[nodiscard]] ::Microsoft::WRL::ComPtr<IDWriteFontFace1> _FindFontFace(std::wstring& familyName,
DWRITE_FONT_WEIGHT& weight,
DWRITE_FONT_STRETCH& stretch,
DWRITE_FONT_STYLE& style,
std::wstring& localeName) const;

[[nodiscard]] std::wstring _GetFontFamilyName(gsl::not_null<IDWriteFontFamily*> const fontFamily,
std::wstring& localeName) const;

// A locale that can be used on construction of assorted DX objects that want to know one.
[[nodiscard]] std::wstring _GetUserLocaleName();

::Microsoft::WRL::ComPtr<IDWriteFactory1> _dwriteFactory;

::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> _dwriteTextAnalyzer;
::Microsoft::WRL::ComPtr<IDWriteTextFormat> _dwriteTextFormat;
::Microsoft::WRL::ComPtr<IDWriteTextFormat> _dwriteTextFormatItalic;
::Microsoft::WRL::ComPtr<IDWriteFontFace1> _dwriteFontFace;
::Microsoft::WRL::ComPtr<IDWriteFontFace1> _dwriteFontFaceItalic;

::Microsoft::WRL::ComPtr<IBoxDrawingEffect> _boxDrawingEffect;

::Microsoft::WRL::ComPtr<IDWriteFontFallback> _systemFontFallback;
std::wstring _userLocaleName;

til::size _glyphCell;

LineMetrics _lineMetrics;
};
}
Loading

0 comments on commit eb34993

Please sign in to comment.