-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve glyph scaling correction #4747
Conversation
…sidered for the column space allocated. Applies excess pen advance space to the final one only.
…t, not glyph). Provide length to corrections as well. Change scaling down algorithm to be based on advances we already know. Correct remaining advance distances to deal with multiple glyph clusters.
…er to understand in regards to indexes/offsets.
This represents me needing to check in the big Excel spreadsheet that I used to diagnose this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any way we can add tests to cover the examples you've provided? (and the table you created)
src/renderer/dx/CustomTextLayout.cpp
Outdated
for (auto i = 1; i < text.size(); ++i) | ||
{ | ||
_textClusterColumns.push_back(0); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for (auto i = 1; i < text.size(); ++i) | |
{ | |
_textClusterColumns.push_back(0); | |
} | |
_textClusterColumns.resize(text.size(), 0); // expand vector to text length, but filled with 0s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternatively, std::fill_n(std::back_inserter(_textClusterColumns), count, 0);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used fill over fill_n just because I had an inkling that the optimizer might be sad about that one too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nnnn fill isn't quite right because of the insertion nature of this. trying fill_n and hoping for the best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fill_n with back_inserter works, but now Dustin has another idea of using .resize which sounds even better to me.
Crash:
|
0e04 is a base, 0e49 and 0e33 are combiners. It only reproduces with both combiners. |
... it only crashes in opt builds lol |
diff --git a/src/renderer/dx/CustomTextLayout.cpp b/src/renderer/dx/CustomTextLayout.cpp
index b40bd9140..c977789f5 100644
--- a/src/renderer/dx/CustomTextLayout.cpp
+++ b/src/renderer/dx/CustomTextLayout.cpp
@@ -651,9 +651,9 @@ try
// Move the X offset (pixels to the right from the left edge) by half the excess space
// so half of it will be left of the glyph and the other half on the right.
// Here we need to move every glyph in the cluster.
- std::for_each_n(_glyphOffsets.begin() + clusterGlyphBegin,
- clusterGlyphLength,
- [halfDiff = diff / 2](DWRITE_GLYPH_OFFSET& offset) -> void { offset.advanceOffset += halfDiff; });
+ std::for_each(_glyphOffsets.begin() + clusterGlyphBegin,
+ _glyphOffsets.begin() + clusterGlyphBegin + clusterGlyphLength,
+ [halfDiff = diff / 2](DWRITE_GLYPH_OFFSET& offset) -> void { offset.advanceOffset += halfDiff; });
// Set the advance of the final glyph in the set to all excess space not consumed by the first few so
// we get the perfect width we want. it's a bug in VS 16.4's optimizer -- glyphClusterLength gets stored in register $rdi and subsequently gets the heck clobbered out of it when |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it makes to me. I guess I'll hold my sign-off while we wait on the opt crash to get fixed.
…monospaced fonts work by consequence. Monospace fonts should be fine because M and 0x20 should be the same width...
… with it stomping one of the registers allocated for the N count.
Dustin found out that |
…rted, so go back to fill_n with the back_inserter as Dustin originally suggested.
…'t want an underflow if columns is weirdly 0.
Hello @miniksa! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
… more text than the column value we were also given. (#4781) ## Summary of the Pull Request Adjusts column padding code in `CustomTextLayout` to only pad out for surrogate pairs, not anything that reports two columns. ## References - See also #4747 ## PR Checklist * [x] Closes #4780 * [x] I work here. * [x] Manual tests. * [x] No doc, this fixes code to match comment. Oops. * [x] Am core contributor. Also discussed with @leonMSFT. ## Detailed Description of the Pull Request / Additional comments For surrogate pairs like high Unicode emoji, we receive two wchar_ts but only one column count (which is usually 2 because emoji are usually inscribed in the full-width squares.) To compensate for this, I added in a little padding function at the top of the `CustomTextLayout` construction that adds a column of 0 aligned with the second half of a surrogate pair so the text-to-glyph mapping lines up correctly. Unfortunately, I made a mistake while either responding to PR feedback in #4747 or in the first place and I made it pad out extra 0 columns based on the FIRST column count, not based on whether or not there is a trailing surrogate pair. The correct thing to do is to pad it out based on the LENGTH of text associated with the given column count. This means that full width characters which can be represented in one wchar_t, like those coming from the IME in most cases (U+5C41 for example) will have a column count of 2. This is perfectly correct for mapping text-to-glyphs and doesn't need a 0 added after it. A house emoji (U+1F3E0) comes in as two wchar_ts (0xD83C 0xDFE0) with the column count of 2. To ensure that the arrays are aligned, the 2 matches up with the 0xD83C but the 0xDFE0 needs a 0 on it so it will be skipped over. (Don't worry, because it's a surrogate, it's naturally consumed correctly by the glyph mapper.) The effect was that every OTHER character inserted by the IME was scaled to 0 size (as an advance of 0 was expected for 0 columns). The fix restores it so those characters don't have an associated count and aren't scaled. ## Validation Steps Performed - Opened it up - Put in the house emoji like #4747 (U+1f3e0) - Put in some characters with simplified Chinese IME (fixed now) - Put in the utf83.txt sample text used in #4747
Is there any way I can revert this? I want my double wide glyphs to display and not be shrunken down into what amounts to as dots.. an we get a setting for this? |
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request This fixes the RTL regression caused in #4747. We create the rectangle taking the direction (through the BiDi Level) into account, and then the rendering works again. The GlyphRun shaping could still probably use some work to be a polished thingy, and there are still issues with RTL getting chopped up a lot when there's font fallback going on, but this fixes the regression, and it's now functional again. <!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> ## References #4779 #4747 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [x] Closes #4779 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Requires documentation to be updated * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments The baseline is actually direction dependent. So when it was being initialized, the unconditional baseline as left broke it, setting the box off to right of the text. We just check if the `GlyphRun->bidiLevel` is set, and if so, we adjust it so that the baseline lines up with the right, not with the left. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed ![image](https://user-images.githubusercontent.com/16987694/80968891-681cbc00-8e21-11ea-9e5c-9b7cf6d78d53.png)
Summary of the Pull Request
glyphs if they are too large or too small for the number of columns that
the text buffer is expecting
References
Supersedes Adding primitive support for glyph clusters and n-to-m mapping. #4438
Co-authored-by: Mili (Yi) Zhang milizhang@gmail.com
Related to Some kind of unicode regression #4704 (Avoid splitting surrogate pairs when breaking runs for scaling #4731)
PR Checklist
"x" * ($Host.UI.RawUI.BufferSize.Width - 1) + "
u{241b}"`_CorrectGlyphRun
merged to master (weird repeats and splits of runs)
Detailed Description of the Pull Request / Additional comments
_CorrectGlyphRun
function now walks through and uses the_glyphClusters
map to determine the text span and glyph span for eachcluster so it can be considered as a single unit for scaling.
text/glyph unit is considered for the available spacing for drawing
take
offset into the center and the extra space is padded onto the advance of
the last glyph in the range.
shrinking as a single unit by providing the initial text index and
length (that is back-mapped out of the glyph run) up to the parent
function so it can use the
_SetCurrentRun
and_SplitCurrentRun
existing functions (which operate on text) to split the run into pieces
and only scale the one glyph cluster, not things next to it as well.
of the advances instead of going through some font math wizardry
attempt to split off text after the cluster if it's already at the end.
This was @DHowett-MSFT's crash.
glyphStart
position of the back half (it failed to
+=
instead of=
whichresulted in duplicated text, sometimes).
_textClusterColumns
. The constructor has been updated such that thetrailing half of surrogate pairs gets a 0 column width (as the lead is
marked appropriately by the
GetColumns()
function). This was theexception thrown.
_glyphScaleCorrections
array stored up over the calls to_CorrectGlyphRun
now uses a structScaleCorrection
as we're up to 3values.
ScaleCorrection
values are named to clearly indicate they're inrelation to the original text span, not the glyph spans.
ScaleCorrection
s within_CorrectGlyphRun
have been double checked and corrected to notaccidentally use glyph index/counts when text index/counts are what's
required.
Validation Steps Performed
specifically at Burmese through Thai to ensure restoration (for the most
part) of the behavior
with its ligatures