terminal/src/renderer/dx/CustomTextRenderer.h

116 lines
6.8 KiB
C
Raw Normal View History

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include <wrl/implements.h>
namespace Microsoft::Console::Render
{
struct DrawingContext
{
DrawingContext(ID2D1RenderTarget* renderTarget,
ID2D1Brush* foregroundBrush,
ID2D1Brush* backgroundBrush,
Use grayscale AA always on non-opaque backgrounds (#5277) ## Summary of the Pull Request When we're on acrylic, we can't have cleartype text unfortunately. This PR changes the DX renderer to force cleartype runs of text that are on a non-opaque background to use grayscale AA instead. ## References Here are some of the URLS I was referencing as writing this: * https://stackoverflow.com/q/23587787 * https://docs.microsoft.com/en-us/windows/win32/direct2d/supported-pixel-formats-and-alpha-modes#cleartype-and-alpha-modes * https://devblogs.microsoft.com/oldnewthing/20150129-00/?p=44803 * https://docs.microsoft.com/en-us/windows/win32/api/d2d1/ne-d2d1-d2d1_layer_options * https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-layers-overview#d2d1_layer_parameters1-and-d2d1_layer_options1 * https://docs.microsoft.com/en-us/windows/win32/api/dcommon/ne-dcommon-d2d1_alpha_mode?redirectedfrom=MSDN#cleartype-and-alpha-modes * https://stackoverflow.com/a/26523006 Additionally: * This was introduced in #4711 ## PR Checklist * [x] Closes #5098 * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Basically, if you use cleartype on a light background, what you'll get today is the text foreground color _added_ to the background. This will make the text look basically invisible. So, what I did was use some trickery with `PushLayer` to basically create a layer where the text would be forced to render in grayscale AA. I only enable this layer pushing business when both: * The user has enabled cleartype text * The background opacity < 1.0 This plumbs some information through from the TermControl to the DX Renderer to make this smooth. ## Validation Steps Performed Opened both cleartype and grayscale panes SxS, and messed with the opacity liberally.
2020-04-24 19:16:34 +02:00
bool forceGrayscaleAA,
IDWriteFactory* dwriteFactory,
const DWRITE_LINE_SPACING spacing,
const D2D_SIZE_F cellSize,
const D2D1_DRAW_TEXT_OPTIONS options = D2D1_DRAW_TEXT_OPTIONS_NONE) noexcept
{
this->renderTarget = renderTarget;
this->foregroundBrush = foregroundBrush;
this->backgroundBrush = backgroundBrush;
Use grayscale AA always on non-opaque backgrounds (#5277) ## Summary of the Pull Request When we're on acrylic, we can't have cleartype text unfortunately. This PR changes the DX renderer to force cleartype runs of text that are on a non-opaque background to use grayscale AA instead. ## References Here are some of the URLS I was referencing as writing this: * https://stackoverflow.com/q/23587787 * https://docs.microsoft.com/en-us/windows/win32/direct2d/supported-pixel-formats-and-alpha-modes#cleartype-and-alpha-modes * https://devblogs.microsoft.com/oldnewthing/20150129-00/?p=44803 * https://docs.microsoft.com/en-us/windows/win32/api/d2d1/ne-d2d1-d2d1_layer_options * https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-layers-overview#d2d1_layer_parameters1-and-d2d1_layer_options1 * https://docs.microsoft.com/en-us/windows/win32/api/dcommon/ne-dcommon-d2d1_alpha_mode?redirectedfrom=MSDN#cleartype-and-alpha-modes * https://stackoverflow.com/a/26523006 Additionally: * This was introduced in #4711 ## PR Checklist * [x] Closes #5098 * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Basically, if you use cleartype on a light background, what you'll get today is the text foreground color _added_ to the background. This will make the text look basically invisible. So, what I did was use some trickery with `PushLayer` to basically create a layer where the text would be forced to render in grayscale AA. I only enable this layer pushing business when both: * The user has enabled cleartype text * The background opacity < 1.0 This plumbs some information through from the TermControl to the DX Renderer to make this smooth. ## Validation Steps Performed Opened both cleartype and grayscale panes SxS, and messed with the opacity liberally.
2020-04-24 19:16:34 +02:00
this->forceGrayscaleAA = forceGrayscaleAA;
this->dwriteFactory = dwriteFactory;
this->spacing = spacing;
this->cellSize = cellSize;
this->options = options;
}
ID2D1RenderTarget* renderTarget;
ID2D1Brush* foregroundBrush;
ID2D1Brush* backgroundBrush;
Use grayscale AA always on non-opaque backgrounds (#5277) ## Summary of the Pull Request When we're on acrylic, we can't have cleartype text unfortunately. This PR changes the DX renderer to force cleartype runs of text that are on a non-opaque background to use grayscale AA instead. ## References Here are some of the URLS I was referencing as writing this: * https://stackoverflow.com/q/23587787 * https://docs.microsoft.com/en-us/windows/win32/direct2d/supported-pixel-formats-and-alpha-modes#cleartype-and-alpha-modes * https://devblogs.microsoft.com/oldnewthing/20150129-00/?p=44803 * https://docs.microsoft.com/en-us/windows/win32/api/d2d1/ne-d2d1-d2d1_layer_options * https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-layers-overview#d2d1_layer_parameters1-and-d2d1_layer_options1 * https://docs.microsoft.com/en-us/windows/win32/api/dcommon/ne-dcommon-d2d1_alpha_mode?redirectedfrom=MSDN#cleartype-and-alpha-modes * https://stackoverflow.com/a/26523006 Additionally: * This was introduced in #4711 ## PR Checklist * [x] Closes #5098 * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Basically, if you use cleartype on a light background, what you'll get today is the text foreground color _added_ to the background. This will make the text look basically invisible. So, what I did was use some trickery with `PushLayer` to basically create a layer where the text would be forced to render in grayscale AA. I only enable this layer pushing business when both: * The user has enabled cleartype text * The background opacity < 1.0 This plumbs some information through from the TermControl to the DX Renderer to make this smooth. ## Validation Steps Performed Opened both cleartype and grayscale panes SxS, and messed with the opacity liberally.
2020-04-24 19:16:34 +02:00
bool forceGrayscaleAA;
IDWriteFactory* dwriteFactory;
DWRITE_LINE_SPACING spacing;
D2D_SIZE_F cellSize;
D2D1_DRAW_TEXT_OPTIONS options;
};
class CustomTextRenderer : public ::Microsoft::WRL::RuntimeClass<::Microsoft::WRL::RuntimeClassFlags<::Microsoft::WRL::ClassicCom | ::Microsoft::WRL::InhibitFtmBase>, IDWriteTextRenderer>
{
public:
// http://www.charlespetzold.com/blog/2014/01/Character-Formatting-Extensions-with-DirectWrite.html
// https://docs.microsoft.com/en-us/windows/desktop/DirectWrite/how-to-implement-a-custom-text-renderer
// IDWritePixelSnapping methods
[[nodiscard]] HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(void* clientDrawingContext,
_Out_ BOOL* isDisabled) noexcept override;
[[nodiscard]] HRESULT STDMETHODCALLTYPE GetPixelsPerDip(void* clientDrawingContext,
_Out_ FLOAT* pixelsPerDip) noexcept override;
[[nodiscard]] HRESULT STDMETHODCALLTYPE GetCurrentTransform(void* clientDrawingContext,
_Out_ DWRITE_MATRIX* transform) noexcept override;
// IDWriteTextRenderer methods
[[nodiscard]] HRESULT STDMETHODCALLTYPE DrawGlyphRun(void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
_In_ const DWRITE_GLYPH_RUN* glyphRun,
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,
IUnknown* clientDrawingEffect) override;
[[nodiscard]] HRESULT STDMETHODCALLTYPE DrawUnderline(void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
_In_ const DWRITE_UNDERLINE* underline,
IUnknown* clientDrawingEffect) noexcept override;
[[nodiscard]] HRESULT STDMETHODCALLTYPE DrawStrikethrough(void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
_In_ const DWRITE_STRIKETHROUGH* strikethrough,
IUnknown* clientDrawingEffect) noexcept override;
[[nodiscard]] HRESULT STDMETHODCALLTYPE DrawInlineObject(void* clientDrawingContext,
FLOAT originX,
FLOAT originY,
IDWriteInlineObject* inlineObject,
BOOL isSideways,
BOOL isRightToLeft,
IUnknown* clientDrawingEffect) noexcept override;
private:
[[nodiscard]] HRESULT _FillRectangle(void* clientDrawingContext,
IUnknown* clientDrawingEffect,
float x,
float y,
float width,
float thickness,
DWRITE_READING_DIRECTION readingDirection,
DWRITE_FLOW_DIRECTION flowDirection) noexcept;
[[nodiscard]] HRESULT _DrawBasicGlyphRun(DrawingContext* clientDrawingContext,
D2D1_POINT_2F baselineOrigin,
DWRITE_MEASURING_MODE measuringMode,
_In_ const DWRITE_GLYPH_RUN* glyphRun,
_In_opt_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,
ID2D1Brush* brush);
[[nodiscard]] HRESULT _DrawBasicGlyphRunManually(DrawingContext* clientDrawingContext,
D2D1_POINT_2F baselineOrigin,
DWRITE_MEASURING_MODE measuringMode,
_In_ const DWRITE_GLYPH_RUN* glyphRun,
_In_opt_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription) noexcept;
[[nodiscard]] HRESULT _DrawGlowGlyphRun(DrawingContext* clientDrawingContext,
D2D1_POINT_2F baselineOrigin,
DWRITE_MEASURING_MODE measuringMode,
_In_ const DWRITE_GLYPH_RUN* glyphRun,
_In_opt_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription) noexcept;
};
}