2019-05-03 00:29:04 +02:00
|
|
|
/*++
|
|
|
|
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
|
|
|
|
|
2020-11-25 22:02:10 +01:00
|
|
|
#include "../inc/RenderEngineBase.hpp"
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
namespace Microsoft::Console::Render
|
|
|
|
{
|
|
|
|
class GdiEngine final : public RenderEngineBase
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
GdiEngine();
|
|
|
|
~GdiEngine() override;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT SetHwnd(const HWND hwnd) noexcept;
|
|
|
|
|
|
|
|
[[nodiscard]] HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT InvalidateSystem(const RECT* const prcDirtyClient) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT InvalidateCursor(const COORD* const pcoordCursor) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
|
|
|
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override;
|
|
|
|
|
|
|
|
[[nodiscard]] HRESULT StartPaint() noexcept override;
|
|
|
|
[[nodiscard]] HRESULT EndPaint() noexcept override;
|
|
|
|
[[nodiscard]] HRESULT Present() noexcept override;
|
|
|
|
|
|
|
|
[[nodiscard]] HRESULT ScrollFrame() noexcept override;
|
|
|
|
|
|
|
|
[[nodiscard]] HRESULT PaintBackground() noexcept override;
|
2020-07-15 18:40:42 +02:00
|
|
|
[[nodiscard]] HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters,
|
2019-06-11 22:27:09 +02:00
|
|
|
const COORD coord,
|
Make Conpty emit wrapped lines as actually wrapped lines (#4415)
## Summary of the Pull Request
Changes how conpty emits text to preserve line-wrap state, and additionally adds rudimentary support to the Windows Terminal for wrapped lines.
## References
* Does _not_ fix (!) #3088, but that might be lower down in conhost. This makes wt behave like conhost, so at least there's that
* Still needs a proper deferred EOL wrap implementation in #780, which is left as a todo
* #4200 is the mega bucket with all this work
* MSFT:16485846 was the first attempt at this task, which caused the regression MSFT:18123777 so we backed it out.
* #4403 - I made sure this worked with that PR before I even sent #4403
## PR Checklist
* [x] Closes #405
* [x] Closes #3367
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I started with the following implementation:
When conpty is about to write the last column, note that we wrapped this line here. If the next character the vt renderer is told to paint get is supposed to be at the start of the following line, then we know that the previous line had wrapped, so we _won't_ emit the usual `\r\n` here, and we'll just continue emitting text.
However, this isn't _exactly_ right - if someone fills the row _exactly_ with text, the information that's available to the vt renderer isn't enough to know for sure if this line broke or not. It is possible for the client to write a full line of text, with a `\n` at the end, to manually break the line. So, I had to also add the `lineWrapped` param to the `IRenderEngine` interface, which is about half the files in this changelist.
## Validation Steps Performed
* Ran tests
* Checked how the Windows Terminal behaves with these changes
* Made sure that conhost/inception and gnome-terminal both act as you'd expect with wrapped lines from conpty
2020-02-27 17:40:11 +01:00
|
|
|
const bool trimLeft,
|
|
|
|
const bool lineWrapped) noexcept override;
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT PaintBufferGridLines(const GridLines lines,
|
|
|
|
const COLORREF color,
|
|
|
|
const size_t cchLine,
|
|
|
|
const COORD coordTarget) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT PaintSelection(const SMALL_RECT rect) noexcept override;
|
|
|
|
|
|
|
|
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
|
|
|
|
|
Improve the propagation of color attributes over ConPTY (#6506)
This PR reimplements the VT rendering engines to do a better job of
preserving the original color types when propagating attributes over
ConPTY. For the 16-color renderers it provides better support for
default colors and improves the efficiency of the color narrowing
conversions. It also fixes problems with the ordering of character
renditions that could result in attributes being dropped.
Originally the base renderer would calculate the RGB color values and
legacy/extended attributes up front, passing that data on to the active
engine's `UpdateDrawingBrushes` method. With this new implementation,
the renderer now just passes through the original `TextAttribute` along
with an `IRenderData` interface, and leaves it to the engines to extract
the information they need.
The GDI and DirectX engines now have to lookup the RGB colors themselves
(via simple `IRenderData` calls), but have no need for the other
attributes. The VT engines extract the information that they need from
the `TextAttribute`, instead of having to reverse engineer it from
`COLORREF`s.
The process for the 256-color Xterm engine starts with a check for
default colors. If both foreground and background are default, it
outputs a SGR 0 reset, and clears the `_lastTextAttribute` completely to
make sure any reset state is reapplied. With that out the way, the
foreground and background are updated (if changed) in one of 4 ways.
They can either be a default value (SGR 39 and 49), a 16-color index
(using ANSI or AIX sequences), a 256-color index, or a 24-bit RGB value
(both using SGR 38 and 48 sequences).
Then once the colors are accounted for, there is a separate step that
handles the character rendition attributes (bold, italics, underline,
etc.) This step must come _after_ the color sequences, in case a SGR
reset is required, which would otherwise have cleared any character
rendition attributes if it came last (which is what happened in the
original implementation).
The process for the 16-color engines is a little different. The target
client in this case (Windows telnet) is incapable of setting default
colors individually, so we need to output an SGR 0 reset if _either_
color has changed to default. With that out the way, we use the
`TextColor::GetLegacyIndex` method to obtain an approximate 16-color
index for each color, and apply the bold attribute by brightening the
foreground index (setting bit 8) if the color type permits that.
However, since Windows telnet only supports the 8 basic ANSI colors, the
best we can do for bright colors is to output an SGR 1 attribute to get
a bright foreground. There is nothing we can do about a bright
background, so after that we just have to drop the high bit from the
colors. If the resulting index values have changed from what they were
before, we then output ANSI 8-color SGR sequences to update them.
As with the 256-color engine, there is also a final step to handle the
character rendition attributes. But in this case, the only supported
attributes are underline and reversed video.
Since the VT engines no longer depend on the active color table and
default color values, there was quite a lot of code that could now be
removed. This included the `IDefaultColorProvider` interface and
implementations, the `Find(Nearest)TableIndex` functions, and also the
associated HLS conversion and difference calculations.
VALIDATION
Other than simple API parameter changes, the majority of updates
required in the unit tests were to correct assumptions about the way the
colors should be rendered, which were the source of the narrowing bugs
this PR was trying to fix. Like passing white on black to the
`UpdateDrawingBrushes` API, and expecting it to output the default `SGR
0` sequence, or passing an RGB color and expecting an indexed SGR
sequence.
In addition to that, I've added some VT renderer tests to make sure the
rendition attributes (bold, underline, etc) are correctly retained when
a default color update causes an `SGR 0` sequence to be generated (the
source of bug #3076). And I've extended the VT renderer color tests
(both 256-color and 16-color) to make sure we're covering all of the
different color types (default, RGB, and both forms of indexed colors).
I've also tried to manually verify that all of the test cases in the
linked bug reports (and their associated duplicates) are now fixed when
this PR is applied.
Closes #2661
Closes #3076
Closes #3717
Closes #5384
Closes #5864
This is only a partial fix for #293, but I suspect the remaining cases
are unfixable.
2020-07-01 20:10:36 +02:00
|
|
|
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes,
|
|
|
|
const gsl::not_null<IRenderData*> pData,
|
2019-06-11 22:27:09 +02:00
|
|
|
const bool isSettingDefaultBrushes) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired,
|
|
|
|
_Out_ FontInfo& FontInfo) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT UpdateDpi(const int iDpi) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT UpdateViewport(const SMALL_RECT srNewViewport) noexcept override;
|
|
|
|
|
|
|
|
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& FontDesired,
|
|
|
|
_Out_ FontInfo& Font,
|
|
|
|
const int iDpi) noexcept override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
Move ConPTY to use til::bitmap (#5024)
## Summary of the Pull Request
Moves the ConPTY drawing mechanism (`VtRenderer`) to use the fine-grained `til::bitmap` individual-dirty-bit tracking mechanism instead of coarse-grained rectangle unions to improve drawing performance by dramatically reducing the total area redrawn.
## PR Checklist
* [x] Part of #778 and #1064
* [x] I work here
* [x] Tests added and updated.
* [x] I'm a core contributor
## Detailed Description of the Pull Request / Additional comments
- Converted `GetDirtyArea()` interface from `IRenderEngine` to use a vector of `til::rectangle` instead of the `SMALL_RECT` to banhammer inclusive rectangles.
- `VtEngine` now holds and operates on the `til::bitmap` for invalidation regions. All invalidation operation functions that used to be embedded inside `VtEngine` are deleted in favor of using the ones in `til::bitmap`.
- Updated `VtEngine` tracing to use new `til::bitmap` on trace and the new `to_string()` methods detailed below.
- Comparison operators for `til::bitmap` and complementary tests.
- Fixed an issue where the dirty rectangle shortcut in `til::bitmap` was set to 0,0,0,0 by default which means that `|=` on it with each `set()` operation was stretching the rectangle from 0,0. Now it's a `std::optional` so it has no value after just being cleared and will build from whatever the first invalidated rectangle is. Complementary tests added.
- Optional run caching for `til::bitmap` in the `runs()` method since both VT and DX renderers will likely want to generate the set of runs at the beginning of a frame and refer to them over and over through that frame. Saves the iteration and creation and caches inside `til::bitmap` where the chance of invalidation of the underlying data is known best. It is still possible to iterate manually with `begin()` and `end()` from the outside without caching, if desired. Complementary tests added.
- WEX templates added for `til::bitmap` and used in tests.
- `translate()` method for `til::bitmap` which will slide the dirty points in the direction specified by a `til::point` and optionally back-fill the uncovered area as dirty. Complementary tests added.
- Moves all string generation for `til` types `size`, `point`, `rectangle`, and `some` into a `to_string` method on each object such that it can be used in both ETW tracing scenarios AND in the TAEF templates uniformly. Adds a similar method for `bitmap`.
- Add tagging to `_bitmap_const_iterator` such that it appears as a valid **Input Iterator** to STL collections and can be used in a `std::vector` constructor as a range. Adds and cleans up operators on this iterator to match the theoretical requirements for an **Input Iterator**. Complementary tests added.
- Add loose operators to `til` which will allow some basic math operations (+, -, *, /) between `til::size` and `til::point` and vice versa. Complementary tests added. Complementary tests added.
- Adds operators to `til::rectangle` to allow scaling with basic math operations (+, -, *) versus `til::size` and translation with basic math operations (+, -) against `til::point`. Complementary tests added.
- In-place variants of some operations added to assorted `til` objects. Complementary tests added.
- Update VT tests to compare invalidation against the new map structure instead of raw rectangles where possible.
## Validation Steps Performed
- Wrote additional til Unit Tests for all additional operators and functions added to the project to support this operation
- Updated the existing VT renderer tests
- Ran perf check
2020-03-23 16:57:54 +01:00
|
|
|
[[nodiscard]] std::vector<til::rectangle> GetDirtyArea() override;
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
|
|
|
|
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
protected:
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring& newTitle) noexcept override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
HWND _hwndTargetWindow;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] static HRESULT s_SetWindowLongWHelper(const HWND hWnd,
|
|
|
|
const int nIndex,
|
|
|
|
const LONG dwNewLong) noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
bool _fPaintStarted;
|
|
|
|
|
|
|
|
PAINTSTRUCT _psInvalidData;
|
|
|
|
HDC _hdcMemoryContext;
|
|
|
|
bool _isTrueTypeFont;
|
|
|
|
UINT _fontCodepage;
|
|
|
|
HFONT _hfont;
|
|
|
|
TEXTMETRICW _tmFontMetrics;
|
|
|
|
|
|
|
|
static const size_t s_cPolyTextCache = 80;
|
|
|
|
POLYTEXTW _pPolyText[s_cPolyTextCache];
|
|
|
|
size_t _cPolyText;
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _FlushBufferLines() noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
std::vector<RECT> cursorInvertRects;
|
|
|
|
|
Refactor grid line renderers with support for more line types (#7107)
This is a refactoring of the grid line renderers, adjusting the line
widths to scale with the font size, and optimising the implementation to
cut down on the number of draw calls. It also extends the supported grid
line types to include true underlines and strike-through lines in the
style of the active font.
The main gist of the optimisation was to render the horizontal lines
with a single draw call, instead of a loop with lots of little strokes
joined together. In the case of the vertical lines, which still needed
to be handled in a loop, I've tried to move the majority of static
calculations outside the loop, so there is bit of optimisation there
too.
At the same time this code was updated to support a variable stroke
width for the lines, instead of having them hardcoded to 1 pixel. The
width is now calculated as a fraction of the font size (0.025 "em"),
which is still going to be 1 pixel wide in most typical usage, but will
scale up appropriately if you zoom in far enough.
And in preparation for supporting the SGR strike-through attribute, and
true underlines, I've extended the grid line renders with options for
handling those line types as well. The offset and thickness of the lines
is obtained from the font metrics (rounded to a pixel width, with a
minimum of one pixel), so they match the style of the font.
VALIDATION
For now we're still only rendering grid lines, and only the top and
bottom lines in the case of the DirectX renderer in Windows Terminal. So
to test, I hacked in some code to force the renderer to use all the
different options, confirming that they were working in both the GDI and
DirectX renderers.
I've tested the output with a number of different fonts, comparing it
with the same text rendered in WordPad. For the most part they match
exactly, but there can be slight differences when we adjust the font
size for grid alignment. And in the case of the GDI renderer, where
we're working with pixel heights rather than points, it's difficult to
match the sizes exactly.
This is a first step towards supporting the strike-through attribute
(#6205) and true underlines (#2915).
Closes #6911
2020-07-31 00:43:37 +02:00
|
|
|
struct LineMetrics
|
|
|
|
{
|
|
|
|
int gridlineWidth;
|
|
|
|
int underlineOffset;
|
Add support for the "doubly underlined" graphic rendition attribute (#7223)
This PR adds support for the ANSI _doubly underlined_ graphic rendition
attribute, which is enabled by the `SGR 21` escape sequence.
There was already an `ExtendedAttributes::DoublyUnderlined` flag in the
`TextAttribute` class, but I needed to add `SetDoublyUnderlined` and
`IsDoublyUnderlined` methods to access that flag, and update the
`SetGraphicsRendition` methods of the two dispatchers to set the
attribute on receipt of the `SGR 21` sequence. I also had to update the
existing `SGR 24` handler to reset _DoublyUnderlined_ in addition to
_Underlined_, since they share the same reset sequence.
For the rendering, I've added a new grid line type, which essentially
just draws an additional line with the same thickness as the regular
underline, but slightly below it - I found a gap of around 0.05 "em"
between the lines looked best. If there isn't enough space in the cell
for that gap, the second line will be clamped to overlap the first, so
you then just get a thicker line. If there isn't even enough space below
for a thicker line, we move the offset _above_ the first line, but just
enough to make it thicker.
The only other complication was the update of the `Xterm256Engine` in
the VT renderer. As mentioned above, the two underline attributes share
the same reset sequence, so to forward that state over conpty we require
a slightly more complicated process than with most other attributes
(similar to _Bold_ and _Faint_). We first check whether either underline
attribute needs to be turned off to send the reset sequence, and then
check individually if each of them needs to be turned back on again.
## Validation Steps Performed
For testing, I've extended the existing attribute tests in
`AdapterTest`, `VTRendererTest`, and `ScreenBufferTests`, to make sure
we're covering both the _Underlined_ and _DoublyUnderlined_ attributes.
I've also manually tested the `SGR 21` sequence in conhost and Windows
Terminal, with a variety of fonts and font sizes, to make sure the
rendering was reasonably distinguishable from a single underline.
Closes #2916
2020-08-10 19:06:16 +02:00
|
|
|
int underlineOffset2;
|
Refactor grid line renderers with support for more line types (#7107)
This is a refactoring of the grid line renderers, adjusting the line
widths to scale with the font size, and optimising the implementation to
cut down on the number of draw calls. It also extends the supported grid
line types to include true underlines and strike-through lines in the
style of the active font.
The main gist of the optimisation was to render the horizontal lines
with a single draw call, instead of a loop with lots of little strokes
joined together. In the case of the vertical lines, which still needed
to be handled in a loop, I've tried to move the majority of static
calculations outside the loop, so there is bit of optimisation there
too.
At the same time this code was updated to support a variable stroke
width for the lines, instead of having them hardcoded to 1 pixel. The
width is now calculated as a fraction of the font size (0.025 "em"),
which is still going to be 1 pixel wide in most typical usage, but will
scale up appropriately if you zoom in far enough.
And in preparation for supporting the SGR strike-through attribute, and
true underlines, I've extended the grid line renders with options for
handling those line types as well. The offset and thickness of the lines
is obtained from the font metrics (rounded to a pixel width, with a
minimum of one pixel), so they match the style of the font.
VALIDATION
For now we're still only rendering grid lines, and only the top and
bottom lines in the case of the DirectX renderer in Windows Terminal. So
to test, I hacked in some code to force the renderer to use all the
different options, confirming that they were working in both the GDI and
DirectX renderers.
I've tested the output with a number of different fonts, comparing it
with the same text rendered in WordPad. For the most part they match
exactly, but there can be slight differences when we adjust the font
size for grid alignment. And in the case of the GDI renderer, where
we're working with pixel heights rather than points, it's difficult to
match the sizes exactly.
This is a first step towards supporting the strike-through attribute
(#6205) and true underlines (#2915).
Closes #6911
2020-07-31 00:43:37 +02:00
|
|
|
int underlineWidth;
|
|
|
|
int strikethroughOffset;
|
|
|
|
int strikethroughWidth;
|
|
|
|
};
|
|
|
|
|
|
|
|
LineMetrics _lineMetrics;
|
2019-05-03 00:29:04 +02:00
|
|
|
COORD _coordFontLast;
|
|
|
|
int _iCurrentDpi;
|
|
|
|
|
|
|
|
static const int s_iBaseDpi = USER_DEFAULT_SCREEN_DPI;
|
|
|
|
|
|
|
|
SIZE _szMemorySurface;
|
|
|
|
HBITMAP _hbitmapMemorySurface;
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _PrepareMemoryBitmap(const HWND hwnd) noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
SIZE _szInvalidScroll;
|
|
|
|
RECT _rcInvalid;
|
|
|
|
bool _fInvalidRectUsed;
|
|
|
|
|
|
|
|
COLORREF _lastFg;
|
|
|
|
COLORREF _lastBg;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _InvalidCombine(const RECT* const prc) noexcept;
|
|
|
|
[[nodiscard]] HRESULT _InvalidOffset(const POINT* const ppt) noexcept;
|
|
|
|
[[nodiscard]] HRESULT _InvalidRestrict() noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _InvalidateRect(const RECT* const prc) noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _PaintBackgroundColor(const RECT* const prc) noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
static const ULONG s_ulMinCursorHeightPercent = 25;
|
|
|
|
static const ULONG s_ulMaxCursorHeightPercent = 100;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _ScaleByFont(const COORD* const pcoord, _Out_ POINT* const pPoint) const noexcept;
|
|
|
|
[[nodiscard]] HRESULT _ScaleByFont(const SMALL_RECT* const psr, _Out_ RECT* const prc) const noexcept;
|
|
|
|
[[nodiscard]] HRESULT _ScaleByFont(const RECT* const prc, _Out_ SMALL_RECT* const psr) const noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
static int s_ScaleByDpi(const int iPx, const int iDpi);
|
|
|
|
static int s_ShrinkByDpi(const int iPx, const int iDpi);
|
|
|
|
|
|
|
|
POINT _GetInvalidRectPoint() const;
|
|
|
|
SIZE _GetInvalidRectSize() const;
|
|
|
|
SIZE _GetRectSize(const RECT* const pRect) const;
|
|
|
|
|
|
|
|
void _OrRect(_In_ RECT* const pRectExisting, const RECT* const pRectToOr) const;
|
|
|
|
|
|
|
|
bool _IsFontTrueType() const;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _GetProposedFont(const FontInfoDesired& FontDesired,
|
|
|
|
_Out_ FontInfo& Font,
|
|
|
|
const int iDpi,
|
|
|
|
_Inout_ wil::unique_hfont& hFont) noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
COORD _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
|
|
|
|
};
|
|
|
|
}
|