terminal/src/renderer/dx/ut_dx/CustomTextLayoutTests.cpp
Michael Niksa 4420950337
Restrict DX run height adjustment to only relevant glyph AND Correct PTY rendering on trailing half of fullwidth glyphs (#4668)
## Summary of the Pull Request
- Height adjustment of a glyph is now restricted to itself in the DX
  renderer instead of applying to the entire run
- ConPTY compensates for drawing the right half of a fullwidth
  character. The entire render base has this behavior restored now as
  well.

## PR Checklist
* [x] Closes #2191
* [x] I work here
* [x] Tests added/passed
* [x] No doc
* [x] Am core contributor.

## Detailed Description of the Pull Request / Additional comments
Two issues:
1. On the DirectX renderer side, when confronted with shrinking a glyph,
   the correction code would apply the shrunken size to the entire run, not
   just the potentially individual glyph that needed to be reduced in size.
   Unfortunately while adjusting the horizontal X width can be done for
   each glyph in a run, the vertical Y height has to be adjusted for an
   entire run. So the solution here was to split the individual glyph
   needing shrinking out of the run into its own run so it can be shrunk.
2. On the ConPTY side, there was a long standing TODO that was never
   completed to deal with a request to draw only the right half of a
   two-column character. This meant that when encountering a request for
   the right half only, we would transmit the entire full character to be
   drawn, left and right halves, struck over the right half position. Now
   we correct the cursor back a position (if space) and draw it out so the
   right half is struck over where we believe the right half should be (and
   the left half is updated as well as a consequence, which should be OK.)

The reason this happens right now is because despite VIM only updating
two cells in the buffer, the differential drawing calculation in the
ConPTY is very simplistic and intersects only rectangles. This means
from the top left most character drawn down to the row/col cursor count
indicator in vim's modeline are redrawn with each character typed. This
catches the line below the edited line in the typing and refreshes it.
But incorrectly.

We need to address making ConPTY smarter about what it draws
incrementally as it's clearly way too chatty. But I plan to do that with
some of the structures I will be creating to solve #778.

## Validation Steps Performed
- Ran the scenario listed in #2191 in vim in the Terminal
- Added unit tests similar to examples given around glyph/text mapping
  in runs from Microsoft community page
2020-02-21 00:24:12 +00:00

101 lines
3.5 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "WexTestClass.h"
#include "..\..\inc\consoletaeftemplates.hpp"
#include "..\CustomTextLayout.h"
using namespace WEX::Common;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace Microsoft::Console::Render;
class Microsoft::Console::Render::CustomTextLayoutTests
{
TEST_CLASS(CustomTextLayoutTests);
TEST_METHOD(OrderRuns)
{
CustomTextLayout layout;
// Create linked list runs where a --> c --> b
CustomTextLayout::LinkedRun a;
a.nextRunIndex = 2;
a.textStart = 0;
CustomTextLayout::LinkedRun b;
b.nextRunIndex = 0;
b.textStart = 20;
CustomTextLayout::LinkedRun c;
c.nextRunIndex = 1;
c.textStart = 10;
// but insert them into the runs as a, b, c
layout._runs.push_back(a);
layout._runs.push_back(b);
layout._runs.push_back(c);
// Now order them.
layout._OrderRuns();
// Validate that they've been reordered to a, c, b by index so they can be iterated to go in order.
// The text starts should be in order 0, 10, 20.
// The next run indexes should point at each other.
VERIFY_ARE_EQUAL(a.textStart, layout._runs.at(0).textStart);
VERIFY_ARE_EQUAL(1u, layout._runs.at(0).nextRunIndex);
VERIFY_ARE_EQUAL(c.textStart, layout._runs.at(1).textStart);
VERIFY_ARE_EQUAL(2u, layout._runs.at(1).nextRunIndex);
VERIFY_ARE_EQUAL(b.textStart, layout._runs.at(2).textStart);
VERIFY_ARE_EQUAL(0u, layout._runs.at(2).nextRunIndex);
}
TEST_METHOD(SplitCurrentRunIncludingGlyphs)
{
CustomTextLayout layout;
// Put glyph data into the layout as if we've already gone through analysis.
// This data matches the verbose comment from the CustomTextLayout.cpp file
// and is derived from
// https://social.msdn.microsoft.com/Forums/en-US/993365bc-8689-45ff-a675-c5ed0c011788/dwriteglyphrundescriptionclustermap-explained
layout._text = L"fiñe";
layout._glyphIndices.push_back(19);
layout._glyphIndices.push_back(81);
layout._glyphIndices.push_back(23);
layout._glyphIndices.push_back(72);
layout._glyphClusters.push_back(0);
layout._glyphClusters.push_back(0);
layout._glyphClusters.push_back(1);
layout._glyphClusters.push_back(3);
// Set up the layout to have a run that already has glyph data inside of it.
CustomTextLayout::LinkedRun run;
run.textStart = 0;
run.textLength = 4;
run.glyphStart = 0;
run.glyphCount = 4;
layout._runs.push_back(run);
// Now split it in the middle per the comment example
layout._SetCurrentRun(2);
layout._SplitCurrentRun(2);
// And validate that the split state matches what we expected.
VERIFY_ARE_EQUAL(0u, layout._runs.at(0).textStart);
VERIFY_ARE_EQUAL(2u, layout._runs.at(0).textLength);
VERIFY_ARE_EQUAL(0u, layout._runs.at(0).glyphStart);
VERIFY_ARE_EQUAL(1u, layout._runs.at(0).glyphCount);
VERIFY_ARE_EQUAL(2u, layout._runs.at(1).textStart);
VERIFY_ARE_EQUAL(2u, layout._runs.at(1).textLength);
VERIFY_ARE_EQUAL(1u, layout._runs.at(1).glyphStart);
VERIFY_ARE_EQUAL(3u, layout._runs.at(1).glyphCount);
}
};