Skip to content
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

AtlasEngine: Implement remaining underlines and builtin glyphs for D2D #17278

Merged
merged 6 commits into from
May 17, 2024

Conversation

lhecker
Copy link
Member

@lhecker lhecker commented May 16, 2024

This implements builtin glyphs for our Direct2D renderer, as well as
dashed and curly underlines. With this in place the only two features
it doesn't support are inverted cursors and VT soft fonts.
This allows us to remove the _hack* members introduced in a6a0e44.

The implementation of dashed underlines is trivial, while curly
underlines use quadratic bezier curves. Caching the curve as a sprite
is possible, however I feel like that can be done in the future.

Builtin glyphs on the other hand require a cache, because otherwise
filling the entire viewport with shaded glyphs would result in poor
performance. This is why it's built on top of ID2D1SpriteBatch.
Unfortunately the API causes an eager flush of other pending graphics
instructions, which is why there's still a decent perf hit.

Finally, as a little extra, this fixes the rounded powerline glyph
shapes being slightly cut off. The fix is to simply don't round the
position and radius of the ellipsis/semi-circle.

Closes #17224

Validation Steps Performed

  • RenderingTests.exe updated ✅
  • All supported builtin glyphs look sorta right at different sizes ✅

@lhecker lhecker changed the title AtlasEngine: Implement builtin glyphs for D2D AtlasEngine: Implement remaining underlines and builtin glyphs for D2D May 16, 2024
@@ -1183,13 +1177,13 @@ void BuiltinGlyphs::DrawBuiltinGlyph(ID2D1Factory* factory, ID2D1DeviceContext*
}
case Shape_FilledEllipsis:
{
const D2D1_ELLIPSE e{ { begXabs, begYabs }, endX, endY };
const D2D1_ELLIPSE e{ { rectX + begX, rectY + begY }, endX, endY };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this change? it doesn't take into account the line offsets any longer

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filled shapes don't have any line width, so this will work just fine.
This change ensures that the rounded powerline glyphs aren't slightly cut off anymore.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay but the empty glyphs DO have a line width - how does this apply on line 1186R?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(looks fine on my screen)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right. More generally speaking, the lineOffsetX/Y code is only for snapping the coordinates of lines. In case of the "arc" shape glyph, this probably doesn't matter much because the entire glyph uses a lot of anti-aliasing anyway.


_curlyLineHalfHeight = height * 0.5f;
_curlyUnderline.position = gsl::narrow_cast<u16>(lrintf(top));
_curlyUnderline.height = gsl::narrow_cast<u16>(lrintf(height));
_curlyUnderline.position = gsl::narrow_cast<u16>(position);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no more rounding - all this math now uses truncation. is that OK?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I don't 100% know why the changes to the D3D backend were needed -- can you explain? Did you test them again at different font sizes and scalings?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this because I copied the code over to D2D. While doing so I noticed that this code doesn't actually do any floating point math whatsoever. As you can see I don't need to do any explicit integer/float casts anywhere in the preceding lines (which would normally be required during AuditMode). I changed the D3D part so that it's mostly identical to the D2D part.

Copy link
Member

@DHowett DHowett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested, can't turn em off!

@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label May 16, 2024
@microsoft-github-policy-service microsoft-github-policy-service bot removed the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label May 16, 2024
@@ -1183,13 +1177,13 @@ void BuiltinGlyphs::DrawBuiltinGlyph(ID2D1Factory* factory, ID2D1DeviceContext*
}
case Shape_FilledEllipsis:
{
const D2D1_ELLIPSE e{ { begXabs, begYabs }, endX, endY };
const D2D1_ELLIPSE e{ { rectX + begX, rectY + begY }, endX, endY };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay but the empty glyphs DO have a line width - how does this apply on line 1186R?

@@ -1183,13 +1177,13 @@ void BuiltinGlyphs::DrawBuiltinGlyph(ID2D1Factory* factory, ID2D1DeviceContext*
}
case Shape_FilledEllipsis:
{
const D2D1_ELLIPSE e{ { begXabs, begYabs }, endX, endY };
const D2D1_ELLIPSE e{ { rectX + begX, rectY + begY }, endX, endY };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(looks fine on my screen)


void BackendD2D::_prepareBuiltinGlyphRenderTarget(const RenderingPayload& p)
{
if (!_builtinGlyphBatch || _builtinGlyphsRenderTarget)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!_builtinGlyphBatch || _builtinGlyphsRenderTarget)
if (!_builtinGlyphBatch || !_builtinGlyphsRenderTarget)

(I'm only like half-understanding what's going on so correct me if I'm wrong) Wouldn't we want to exit early if _buildinGlyphsRenderTarget is not defined? I see we overwrite it a few lines later. Curious.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah that condition sucks. Let me split it apart and add comments!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be much better now!

Copy link
Member

@DHowett DHowett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these comments are amazing

@DHowett DHowett enabled auto-merge May 16, 2024 23:30
@DHowett DHowett added this pull request to the merge queue May 16, 2024
Merged via the queue into main with commit 3486111 May 17, 2024
20 checks passed
@DHowett DHowett deleted the dev/lhecker/atlas-engine-d2d-improvements branch May 17, 2024 00:11
DHowett pushed a commit that referenced this pull request Jun 24, 2024
#17278)

This implements builtin glyphs for our Direct2D renderer, as well as
dashed and curly underlines. With this in place the only two features
it doesn't support are inverted cursors and VT soft fonts.
This allows us to remove the `_hack*` members introduced in a6a0e44.

The implementation of dashed underlines is trivial, while curly
underlines use quadratic bezier curves. Caching the curve as a sprite
is possible, however I feel like that can be done in the future.

Builtin glyphs on the other hand require a cache, because otherwise
filling the entire viewport with shaded glyphs would result in poor
performance. This is why it's built on top of `ID2D1SpriteBatch`.
Unfortunately the API causes an eager flush of other pending graphics
instructions, which is why there's still a decent perf hit.

Finally, as a little extra, this fixes the rounded powerline glyph
shapes being slightly cut off. The fix is to simply don't round the
position and radius of the ellipsis/semi-circle.

Closes #17224

## Validation Steps Performed
* RenderingTests.exe updated ✅
* All supported builtin glyphs look sorta right at different sizes ✅

(cherry picked from commit 3486111)
Service-Card-Id: 92572076
Service-Version: 1.21
@lhecker lhecker added Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Terminal The new Windows Terminal. Area-Settings UI Anything specific to the SUI labels Nov 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Area-Settings UI Anything specific to the SUI Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Terminal The new Windows Terminal.
Projects
Development

Successfully merging this pull request may close these issues.

Gaps between block elements when using Direct2D
3 participants