Commit graph

62 commits

Author SHA1 Message Date
Mike Griese b421ee6ca0 Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok 2021-11-16 06:22:35 -06:00
Leonard Hecker 2353349fe5
Introduce AtlasEngine - A new text rendering prototype (#11623)
This commit introduces "AtlasEngine", a new text renderer based on DxEngine.
But unlike it, DirectWrite and Direct2D are only used to rasterize glyphs.
Blending and placing these glyphs into the target view is being done using
Direct3D and a simple HLSL shader. Since this new renderer more aggressively
assumes that the text is monospace, it simplifies the implementation:
The viewport is divided into cells, and its data is stored as a simple matrix.
Modifications to this matrix involve only simple pointer arithmetic and is easy
to understand. But just like with DxEngine however, DirectWrite
related code remains extremely complex and hard to understand.

Supported features:
* Basic text rendering with grayscale AA
* Foreground and background colors
* Emojis, including zero width joiners
* Underline, dotted underline, strikethrough
* Custom font axes and features
* Selections
* All cursor styles
* Full alpha support for all colors
* _Should_ work with Windows 7

Unsupported features:
* A more conservative GPU memory usage
  The backing texture atlas for glyphs is grow-only and will not shrink.
  After 256MB of memory is used up (~20k glyphs) text output
  will be broken until the renderer is restarted.
* ClearType
* Remaining gridlines (left, right, top, bottom, double underline)
* Hyperlinks don't get full underlines if hovered in WT
* Softfonts
* Non-default line renditions

Performance:
* Runs at up to native display refresh rate
  Unfortunately the frame rate often drops below refresh rate, due us
  fighting over the buffer lock with other parts of the application.
* CPU consumption is up to halved compared to DxEngine
  AtlasEngine is still highly unoptimized. Glyph hashing
  consumes up to a third of the current CPU time.
* No regressions in WT performance
  VT parsing and related buffer management takes up most of the CPU time (~85%),
  due to which the AtlasEngine can't show any further improvements.
* ~2x improvement in raw text throughput in OpenConsole
  compared to DxEngine running at 144 FPS
* ≥10x improvement in colored VT output in WT/OpenConsole
  compared to DxEngine running at 144 FPS
2021-11-13 00:10:06 +00:00
Mike Griese 5adb327703 rename this one too 2021-11-11 10:34:25 -06:00
Mike Griese 88f2e64bb3 Transparency is hard 2021-11-10 16:51:09 -06:00
Mike Griese 713f72e1e5 5/6 transparency cases seem to work. Previewing with unfocused apprearance is broken again. 2021-11-10 15:42:10 -06:00
Mike Griese 03711944f1 okay this seems to fix opacity & cleartype in all cases 2021-10-20 11:50:50 -05:00
James Holderness dacff61f88
Use the til::enumset type for the GridLines enum in the renderers (#11345)
## Summary of the Pull Request

This replaces the `GridLines` enum in the renderers with a `til::enumset` type, avoiding the need for the various `WI_IsFlagSet` macros and flag operators.

## References

This is followup to PR #10492 which introduced the `enumset` class.

## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema 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.

## Validation Steps Performed

I've manually confirmed that all the different gridlines are still rendering correctly in both the GDI and DX renderers.
2021-09-29 10:48:32 +00:00
Mike Griese a544f56e17
Add an ENUM setting for disabling rendering "intense" text as bold (#10759)
## Summary of the Pull Request

This adds a new setting `intenseTextStyle`. It's a per-appearance, control setting, defaulting to `"all"`.
* When set to `"all"` or `["bold", "bright"]`, then we'll render text as both **bold** and bright (1.10 behavior)
* When set to `"bold"`, `["bold"]`, we'll render text formatted with `^[[1m` as **bold**, but not bright
* When set to `"bright"`, `["bright"]`, we'll render text formatted with `^[[1m` as bright, but not bold. This is the pre 1.10 behavior
* When set to `"none"`, we won't do anything special for it at all. 

## references
* I last did this in #10648. This time it's an enum, so we can add bright in the future. It's got positive wording this time.
* ~We will want to add `"bright"` as a value in the future, to disable the auto intense->bright conversion.~ I just did that now.
* #5682 is related

## PR Checklist
* [x] Closes #10576 
* [x] I seriously don't think we have an issue for "disable intense is bright", but I'm not crazy, people wanted that, right? https://github.com/microsoft/terminal/issues/2916#issuecomment-544880423 was the closest
* [x] I work here
* [x] Tests added/passed
* [x] https://github.com/MicrosoftDocs/terminal/pull/381

## Validation Steps Performed

<!-- ![image](https://user-images.githubusercontent.com/18356694/125480327-07f6b711-6bca-4c1b-9a76-75fc978c702d.png) -->
![image](https://user-images.githubusercontent.com/18356694/128929228-504933ee-cf50-43a2-9982-55110ba39191.png)


Yea that works. Printed some bold text, toggled it on, the text was no longer bold. hooray.


### EDIT, 10 Aug

```json
"intenseTextStyle": "none",
"intenseTextStyle": "bold",
"intenseTextStyle": "bright",
"intenseTextStyle": "all",
"intenseTextStyle": ["bold", "bright"],
```

all work now. Repro script:
```sh
printf "\e[1m[bold]\e[m[normal]\e[34m[blue]\e[1m[bold blue]\e[m\n"
```
2021-08-16 13:45:56 +00:00
James Holderness 90ff261c35
Add support for downloadable soft fonts (#10011)
This PR adds conhost support for downloadable soft fonts - also known as
dynamically redefinable character sets (DRCS) - using the `DECDLD`
escape sequence.

These fonts are typically designed to work on a specific terminal model,
and each model tends to have a different character cell size. So in
order to support as many models as possible, the code attempts to detect
the original target size of the font, and then scale the glyphs to fit
our current cell size.

Once a font has been downloaded to the terminal, it can be designated in
the same way you would a standard character set, using an `SCS` escape
sequence. The identification string for the set is defined by the
`DECDLD` sequence. Internally we map the characters in this set to code
points `U+EF20` to `U+EF7F` in the Unicode private use are (PUA).

Then in the renderer, any characters in that range are split off into
separate runs, which get painted with a special font. The font itself is
dynamically generated as an in-memory resource, constructed from the
downloaded character bitmaps which have been scaled to the appropriate
size.

If no soft fonts are in use, then no mapping of the PUA code points will
take place, so this shouldn't interfere with anyone using those code
points for something else, as along as they aren't also trying to use
soft fonts. I also tried to pick a PUA range that hadn't already been
snatched up by Nerd Fonts, but if we do receive reports of a conflict,
it's easy enough to change.

## Validation Steps Performed

I added an adapter test that runs through a bunch of parameter
variations for the `DECDLD` sequence, to make sure we're correctly
detecting the font sizes for most of the known DEC terminal models.

I've also tested manually on a wide range of existing fonts, of varying
dimensions, and from multiple sources, and made sure they all worked
reasonably well.

Closes #9164
2021-08-06 20:41:02 +00:00
Leonard Hecker 20e88d3e3e
Fix conhost UseDx mode (#10770)
This commit fixes the UseDx mode for conhost.
In order to add support for UseDx without calling `SetWindowSize`,
responsibility for resizing `_invalidMap` has been moved to occur
only when the renderer itself recognizes a new size. Furthermore
`InvalidateAll` is now the central point to invalidate `_invalidMap`.

## Validation Steps Performed

* Enabling `UseDx` enables the DxEngine for conhost ✔️
* Resizing windows in conhost works ✔️
* Resizing windows in WT works ✔️

Closes #5455
2021-07-23 20:19:07 +02:00
PankajBhojwani 4c16cb278e
Allow users to set font features and font axes (#10525)
Adds support for users to be able to set font features and axes (see the spec for more details!)

## Detailed Description

**CustomTextLayout**
- Asks the `DxFontRenderData` for the font features when getting glyphs
- _If any features have been set/updated, we always skip the "isTextSimple" shortcut_
- Asks the `_formatInUse` for any font axes when mapping characters in `_AnalyzeFontFallback`

**DxFontRenderData**
- Stores a map of font features (initialized to the [standard feature list])
- Stores a map of font axes
- Has methods to add font features/axes to the map or update existing ones
- Has methods to retrieve the font features/axes
- Sets the font axes in the `IDWriteTextFormat` when creating it

## Validation Steps Performed
It works!

[standard feature list]: ac5aef67d1/DrawableObject.ixx (L802)

Specified in #10457
Related to #1790 
Closes #759
Closes #5828
2021-07-22 23:15:44 +00:00
Mike Griese 9f45963e73
Use DComp surface handle for Swap Chain management (#10023)
## Summary of the Pull Request

This PR changes the DxEngine to create a swapchain HANDLE, then have the TermControl attach _that_ handle to the SwapChainPanel, rather than returning the swapchain via a `IDXGISwapChain1`.

I didn't write this code originally, @miniksa helped me out. The original commit was so succinct that I didn't think there was anything else to add or take away.

I'm going to need this for tear-out (#1256), so that I can have the content process create swap chain handles, then duplicate those handles out to the window process that will end up embedding the content.

## References

* [`DCompositionCreateSurfaceHandle`](https://docs.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-dcompositioncreatesurfacehandle)
* [`CreateSwapChainForCompositionSurfaceHandle`](https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_3/nf-dxgi1_3-idxgifactorymedia-createswapchainforcompositionsurfacehandle)
* [`CreateSwapChainForComposition`](https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/nf-dxgi1_2-idxgifactory2-createswapchainforcomposition)
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

This reverts commit c113b65d9b.

That commit reverted 30b8335479

## Validation Steps Performed

* [x] Built and ran the Terminal, it still seems to work
* [x] Does a TDR still work? or do we need to recreate the handle, or something.
* [x] Does this work on Win7? I honestly have no idea how DX compatibility works. Presumably, the WPF version uses the `ForHwnd` path, so this will still work, but I don't know if this will suddenly fail to launch on Win7 or something. Tagging in @miniksa.
2021-05-12 11:54:17 -05:00
Mike Griese 8910a16fd0
Split TermControl into a Core, Interactivity, and Control layer (#9820)
## Summary of the Pull Request

Brace yourselves, it's finally here. This PR does the dirty work of splitting the monolithic `TermControl` into three components. These components are: 

* `ControlCore`: This encapsulates the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. This is intended to everything that someone might need to stand up a terminal instance in a control, but without any regard for how the UX works.
* `ControlInteractivity`: This is a wrapper for the `ControlCore`, which holds the logic for things like double-click, right click copy/paste, selection, etc. This is intended to be a UI framework-independent abstraction. The methods this layer exposes can be called the same from both the WinUI TermControl and the WPF control.
* `TermControl`: This is the UWP control. It's got a Core and Interactivity inside it, which it uses for the actual logic of the terminal itself. TermControl's main responsibility is now 

By splitting into smaller pieces, it will enable us to
* write unit tests for the `Core` and `Interactivity` bits, which we desparately need
* Combine `ControlCore` and `ControlInteractivity` in an out-of-proc core process in the future, to enable tab tearout.

However, we're not doing that work quite yet. There's still lots of work to be done to enable that, thought this is likely the biggest portion.

Ideally, this would just be methods moved wholesale from one file to another. Unfortunately, there are a bunch of cases where that didn't work as well as expected. Especially when trying to better enforce the boundary between the classes. 

We've got a couple tests here that I've added. These are partially examples, and partially things I ran into while implementing this. A bunch of things from #7001 can go in now that we have this.

This PR is gonna be a huge pain to review - 38 files with 3,730 additions and 1,661 deletions is nothing to scoff at. It will also conflict 100% with anything that's targeting `TermControl`. I'm hoping we can review this over the course of the next week and just be done with it, and leave plenty of runway for 1.9 bugs in post.

## References

* In pursuit of #1256
* Proc Model: #5000
* https://github.com/microsoft/terminal/projects/5

## PR Checklist
* [x] Closes #6842
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

* I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names.
* I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` need to know". In the future, these will all need to be handled specially, because they might involve an RPC call to retrieve the info from the core (or cache it) in the window process.
* I've added more `EventArgs` to make more events proper `TypedEvent`s.
* I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore.
* ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @miniksa wrote this originally in 30b8335, I'm just finally committing it here. We'll need that in the future for the out-of-proc stuff.~~
  * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it.
* I've changed the acrylic handler a decent amount. But added tests!
* All the `ThrottledFunc` things are left in `TermControl`. Some might be able to move down into core/interactivity, but once we figure out how to use a different kind of Dispatcher (because a UI thread won't necessarily exist for those components).
* I've undoubtably messed up the merging of the locking around the appearance config stuff recently

## Validation Steps Performed

I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 15:50:45 +00:00
Chester Liu eb349935a0
Introduce DxFontRenderData (#9096)
This is my attempt to isolate all the dwrite font related thing by
introducing a new layer - `DxFontRenderData`. This will free
`DxRenderer` & `CustomTextLayout` from the burden of handling fonts &
box effects. The logic is more simplified & streamlined.

In short I just moved everything fonts-related into `DxFontRenderData`
and started from there. There's no modification to code logic. Just pure
structural stuff.

SGR support tracking issue: #6879
Initial Italic support PR: #8580
2021-02-18 06:11:38 +00:00
James Holderness 4c53c595e7
Add support for double-width/double-height lines in conhost (#8664)
This PR adds support for the VT line rendition attributes, which allow
for double-width and double-height line renditions. These renditions are
enabled with the `DECDWL` (double-width line) and `DECDHL`
(double-height line) escape sequences. Both reset to the default
rendition with the `DECSWL` (single-width line) escape sequence. For now
this functionality is only supported by the GDI renderer in conhost.

There are a lot of changes, so this is just a general overview of the
main areas affected.

Previously it was safe to assume that the screen had a fixed width, at
least for a given point in time. But now we need to deal with the
possibility of different lines have different widths, so all the
functions that are constrained by the right border (text wrapping,
cursor movement operations, and sequences like `EL` and `ICH`) now need
to lookup the width of the active line in order to behave correctly.

Similarly it used to be safe to assume that buffer and screen
coordinates were the same thing, but that is no longer true. Lots of
places now need to translate back and forth between coordinate systems
dependent on the line rendition. This includes clipboard handling, the
conhost color selection and search, accessibility location tracking and
screen reading, IME editor positioning, "snapping" the viewport, and of
course all the rendering calculations.

For the rendering itself, I've had to introduce a new
`PrepareLineTransform` method that the render engines can use to setup
the necessary transform matrix for a given line rendition. This is also
now used to handle the horizontal viewport offset, since that could no
longer be achieved just by changing the target coordinates (on a double
width line, the viewport offset may be halfway through a character).

I've also had to change the renderer's existing `InvalidateCursor`
method to take a `SMALL_RECT` rather than a `COORD`, to allow for the
cursor being a variable width. Technically this was already a problem,
because the cursor could occupy two screen cells when over a
double-width character, but now it can be anything between one and four
screen cells (e.g. a double-width character on the double-width line).

In terms of architectural changes, there is now a new `lineRendition`
field in the `ROW` class that keeps track of the line rendition for each
row, and several new methods in the `ROW` and `TextBuffer` classes for
manipulating that state. This includes a few helper methods for handling
the various issues discussed above, e.g. position clamping and
translating between coordinate systems.

## Validation Steps Performed

I've manually confirmed all the double-width and double-height tests in
_Vttest_ are now working as expected, and the _VT100 Torture Test_ now
renders correctly (at least the line rendition aspects). I've also got
my own test scripts that check many of the line rendition boundary cases
and have confirmed that those are now passing.

I've manually tested as many areas of the conhost UI that I could think
of, that might be affected by line rendition, including things like
searching, selection, copying, and color highlighting. For
accessibility, I've confirmed that the _Magnifier_ and _Narrator_
correctly handle double-width lines. And I've also tested the Japanese
IME, which while not perfect, is at least useable.

Closes #7865
2021-02-18 05:44:50 +00:00
Michael Niksa 525be22bd8
Eliminate more transient allocations: Titles and invalid rectangles and bitmap runs and utf8 conversions (#8621)
## References
* See also #8617 

## PR Checklist
* [x] Supports #3075
* [x] I work here.
* [x] Manual test.

## Detailed Description of the Pull Request / Additional comments

### Window Title Generation
Every time the renderer checks the title, it's doing two bad things that
I've fixed:
1. It's assembling the prefix to the full title doing a concatenation.
   No one ever gets just the prefix ever after it is set besides the
   concat. So instead of storing prefix and the title, I store the
   assembled prefix + title and the bare title.
2. A copy must be made because it was returning `std::wstring` instead
   of `std::wstring&`. Now it returns the ref.

### Dirty Area Return
Every time the renderer checks the dirty area, which is sometimes
multiple times per pass (regular text printing, again for selection,
etc.), a vector is created off the heap to return the rectangles. The
consumers only ever iterate this data. Now we return a span over a
rectangle or rectangles that the engine must store itself.
1. For some renderers, it's always a constant 1 element. They update
   that 1 element when dirty is queried and return it in the span with a
   span size of 1.
2. For other renderers with more complex behavior, they're already
   holding a cached vector of rectangles. Now it's effectively giving
   out the ref to those in the span for iteration.

### Bitmap Runs
The `til::bitmap` used a `std::optional<std::vector<til::rectangle>>`
inside itself to cache its runs and would clear the optional when the
runs became invalidated. Unfortunately doing `.reset()` to clear the
optional will destroy the underlying vector and have it release its
memory. We know it's about to get reallocated again, so we're just going
to make it a `std::pmr::vector` and give it a memory pool. 

The alternative solution here was to use a `bool` and
`std::vector<til::rectangle>` and just flag when the vector was invalid,
but that was honestly more code changes and I love excuses to try out
PMR now.

Also, instead of returning the ref to the vector... I'm just returning a
span now. Everyone just iterates it anyway, may as well not share the
implementation detail.

### UTF-8 conversions
When testing with Terminal and looking at the `conhost.exe`'s PTY
renderer, it spends a TON of allocation time on converting all the
UTF-16 stuff inside to UTF-8 before it sends it out the PTY. This was
because `ConvertToA` was allocating a string inside itself and returning
it just to have it freed after printing and looping back around again...
as a PTY does.

The change here is to use `til::u16u8` that accepts a buffer out
parameter so the caller can just hold onto it.

## Validation Steps Performed
- [x] `big.txt` in conhost.exe (GDI renderer)
- [x] `big.txt` in Terminal (DX, PTY renderer)
- [x] Ensure WDDM and BGFX build under Razzle with this change.
2021-02-16 20:52:33 +00:00
Michael Niksa 3b247812ce
Teach the renderer to keep thread alive if engine requests it (#9091)
Teaches renderer base to keep thread alive if engine requests it.
`DxEngine` now requests it if shaders are on.

- The render engine interface now has a true/false to return whether the
  specific renderer wants another frame to immediately follow up. The
  renderer base will ask for this information as it ends the paint on
  any particular engine (which is the time where invalid regions are
  typically cleaned up) and just poke the render thread the same as if
  an invalidation request came in from outside of render-land. That will
  trigger the render thread to just keep moving in the same way as any
  other invalidation.

## Validation Steps Performed
- [x] Actually built it
- [x] Actually try it

I promised this in #8994
2021-02-10 11:24:45 -08:00
Lachlan Picking 9fb4fb2741
Fix shader time input (#8994)
Correctly sets the time input on the pixelShaderSettings struct, which was previously hard-coded to `0.0f`. 

## PR Checklist
* [x] Closes #8935
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] 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: #8935

## Detailed Description of the Pull Request / Additional comments
I added a private field to `DxEngine` to store the timestamp for when a custom shader is first loaded. The field is initialized in `_SetupTerminalEffects()`, and the calculated time value (seconds since the timestamp) passed to the actual shader is set in `_ComputePixelShaderSettings()`. 

There remains an issue with with jerky animation due to the renderer not repainting when the window contents are not updated (see discussion in the original issue).

This is basically my first time writing C++; constructive review is enthusiastically welcomed 🙂

## Validation Steps Performed
I manually tested using a variety of simple shaders that rely on time input for animation.
2021-02-02 17:12:04 +00:00
James Holderness fc7b052461
Add support for the "italic" graphic rendition attribute (#8580)
This PR adds support for the ANSI _italic_ graphic rendition attribute,
which is enabled by the `SGR 3` escape sequence.

For the GDI renderer, I've just created an additional italic variant of
the font, and then the `UpdateDrawingBrushes` method selects the
appropriate font variant into the device context based on the requested
text attributes.

It's a bit more complicated in the DX renderer, because we need both an
italic variant of the font, and a variant of the text format object. The
`CustomTextLayout` class also had to be updated to hold the two font and
format instances, and decide which of the variants to use based on a
`useItalicFont` property in the drawing context, initially set in the
`UpdateDrawingBrushes` method.

## Validation Steps Performed
I've created some test content using a range of different character sets
(e.g. CJK, block characters, emoji, etc.), then applied the italic
attribute mixed with various other SGR attributes to see how they
interact. The output isn't always perfect, but I think it seems
reasonable given the constraints of a cell-based terminal renderer.

Closes #5461
2020-12-18 11:23:54 -08:00
Mike Griese b140299e50
Implement user-specified pixel shaders, redux (#8565)
Co-authored-by: mrange <marten_range@hotmail.com>

I loved the pixel shaders in #7058, but that PR needed a bit of polish
to be ready for ingestion. This PR is almost _exactly_ that PR, with
some small changes.

* It adds a new pre-profile setting `"experimental.pixelShaderPath"`,
  which lets the user set a pixel shader to use with the Terminal.
    - CHANGED FROM #7058: It does _not_ add any built-in shaders.
    - CHANGED FROM #7058: it will _override_
      `experimental.retroTerminalEffect`
* It adds a bunch of sample shaders in `samples/shaders`. Included: 
    - A NOP shader as a base to build from.
    - An "invert" shader that inverts the colors, as a simple example
    - An "grayscale" shader that converts all colors to grayscale, as a
      simple example
    - An "raster bars" shader that draws some colored bars on the screen
      with a drop shadow, as a more involved example
    - The original retro terminal effects, as a more involved example
    - It also includes a broken shader, as an example of what heppens
      when the shader fails to compile
    - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were
      all worried about.
* When a shader fails to be found or fails to compile, we'll display an
  error dialog to the user with a relevant error message.
    - CHANGED FROM #7058: Originally, #7058 would display "error bars"
      on the screen. I've removed that, and had the Terminal disable the
      shader entirely then.
* Renames the `toggleRetroEffect` action to `toggleShaderEffect`.
  (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This
  action will turn the shader OR the retro effects on/off. 

`toggleShaderEffect` works the way you'd expect it to, but the mental
math on _how_ is a little weird. The logic is basically:

```
useShader = shaderEffectsEnabled ? 
                (pixelShaderProvided ? 
                    pixelShader : 
                    (retroEffectEnabled ? 
                        retroEffect : null
                    )
                ) : 
                null
```

and `toggleShaderEffect` toggles `shaderEffectsEnabled`.

* If you've got both a shader and retro enabled, `toggleShaderEffect`
  will toggle between the shader on/off.
* If you've got a shader and retro disabled, `toggleShaderEffect` will
  toggle between the shader on/off.

References #6191
References #7058

Closes #7013

Closes #3930 "Add setting to retro terminal shader to control blur
radius, color" 
Closes #3929 "Add setting to retro terminal shader to enable drawing
scanlines" 
     - At this point, just roll your own version of the shader.
2020-12-15 20:40:22 +00:00
Javier 9e86e29584
wpf: Add AutoFill to control whether the connection/buffer resizes (#7853)
Adds the ability to manually handle the terminal renderer resizing
events by allowing different render size and WPF control size. This is
done by adding an `AutoFill` property to the control that prevents the
renderer from automatically resizing and tells the WPF control to fill
in the extra space with the terminal background as shown below:

This PR adds the following:
- Helper method in the DX engine to convert character viewports into
  pixel viewports
- `AutoFill` property that prevents automatic resizing of the renderer
- Tweaks and fixes that automatically fill in the empty space if
  `AutoFill` is set to false
- Fixes resizing methods and streamlines their codepath

## Validation Steps Performed
Manual validation with the Visual Studio Integrated Terminal tool
window.
2020-10-09 22:25:18 +00:00
PankajBhojwani be50e563e6
Display URI tooltip, render dashed/solid underline for links (#7420)
- Render hyperlinks with a dashed underline
- Render hovered hyperlinks with a solid underline
- Show URI tooltip on hover

TermControl now has a canvas that contains a tiny border to which a
tooltip is attached. When we hover over hyperlinked text, we move the
border to the mouse location and update the tooltip content with the
URI. 

Introduced a new underline type (HyperlinkUnderline), supports rendering
for it, and uses it to render hyperlinks. HyperlinkUnderline is usually
a dashed underline, but when a link is hovered, all text with the same
hyperlink ID is rendered with a solid underline. 

References #5001
2020-09-10 14:59:56 -07:00
Javier 20b7fe4ef4
Expose selection background and alpha through the WPF control (#7339)
Adds the ability to set the selection background opacity when setting the
selection background. This also exposes the selection background and alpha
through the terminal WPF container.
2020-08-18 16:11:41 -07:00
James Holderness e7a1a675af
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 17:06:16 +00:00
James Holderness 6ee8099a2c
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-30 22:43:37 +00:00
Michael Niksa 3a91fc0ab4
Skip DX invalidation if we've already scrolled an entire screen worth of height (#6922)
We spend a lot of time invalidating in the DX Renderer. This is a
creative trick to not bother invalidating any further if we can tell
that the bitmap is already completely invalidated. That is, if we've
scrolled at least an entire screen in height... then the entire bitmap
had to have been marked as invalid as the new areas were "uncovered" by
the `InvalidateScroll` command. So further setting invalid bits on top
of a fully invalid map is pointless. 

Note: I didn't use `bitmap::all()` here because it is significantly
slower to check all the bits than it is to just reason out that the
bitmap was already fully marked.

## Validation Steps Performed
- Run `time cat big.txt`. Checked average time before/after, WPR traces
  before/after.
2020-07-17 19:32:36 +00:00
Dustin L. Howett 80da24ecf8
Replace basic_string_view<T> with span<const T> (#6921)
We were using std::basic_string_view as a stand-in for std::span so that
we could change over all at once when C++20 dropped with full span
support. That day's not here yet, but as of 54a7fce3e we're using GSL 3,
whose span is C++20-compliant.

This commit replaces every instance of basic_string_view that was not
referring to an actual string with a span of the appropriate type.

I moved the `const` qualifier into span's `T` because while
`basic_string_view.at()` returns `const T&`, `span.at()` returns `T&`
(without the const). I wanted to maintain the invariant that members of
the span were immutable.

* Mechanical Changes
   * `sv.at(x)` -> `gsl::at(sp, x)`
   * `sv.c{begin,end}` -> `sp.{begin,end}` (span's iterators are const)

I had to replace a `std::basic_string<>` with a `std::vector<>` in
ConImeInfo, and I chose to replace a manual array walk in
ScreenInfoUiaProviderBase with a ranged-for. Please review those
specifically.

This will almost certainly cause a code size regression in Windows
because I'm blowing out all the PGO counts. Whoops.

Related: #3956, #975.
2020-07-15 16:40:42 +00:00
Mike Griese 396cbbb151
Add a ShortcutAction for toggling retro terminal effect (#6691)
Pretty straightforward. `toggleRetroEffect` will work to toggle the
retro terminal effect on/off. 

* Made possible by contributions from #6551, _and viewers like you_
2020-07-01 23:17:43 +00:00
James Holderness ddbe370d22
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 11:10:36 -07:00
Michael Niksa e7d3dc5da2
Recycle assorted rendering components to accelerate drawing (#6483)
This saves an awful lot of construction/destruction and memory
allocation, especially with text that changes a lot (see: cacafire).

Three things:
1. Recycling the text layouts. This holds onto the `CustomTextLayout` so
   all the things that don't change related to drawing targets and
   whatnot aren't freed and recreated every frame.
2. Reordering the runs in place. This saves a vector
   allocation/copy/delete every time OrderRuns is called. They can be
   rearranged in place.
3. Only clip once per row. This reduces the clip push/pop to only one
   time per row. Since we're always redrawing an entire row at a time,
   this saves a lot of alloc/free of the clip frame, dramatically
   reduces queued commands, and makes less work on the flush since
   clipping requires staging the drawing and then bringing it back to
   the main surface.
2020-06-22 16:13:09 +00:00
Michael Niksa 951f389210
Use D2DDeviceContext and friends over D2DRenderTarget (#6527)
I was told that the DeviceContext version supercedes the RenderTarget
one. This moves us to it so we can gain access to a higher level of
control over the various pieces in our pipeline as we continue to evolve
the renderer.

The underlying motivation here is to potentially use a
`ID2D1CommandList` to batch our commands and run them all later outside
the lock. That can only really be done with this more granular level of
control over the pipeline. So this moves to that in a single step that
is easily findable in history should we have problems

I discussed this with @NiklasBorson of the Direct2D/DirectWrite team as
well as with @DHowett before doing it.

## Validation
- [x] Checked docs to make sure that these work on Windows 7 with
  Platform Update
- [x] Manual smoke test real quick
- [ ] Try running on Win7 + Platform Update after change
- [x] Probably do more than just a smoke test manually or otherwise

Closes #6525
2020-06-19 22:14:01 +00:00
Michael Niksa b91430b64d
Enable hot reload of renderer settings that aren't already hot reload capable (#6551)
## Summary of the Pull Request

## PR Checklist
* [x] Closes #3927
* [x] I work here.
* [x] Tested manually.
* [x] Requires documentation to be updated: (generate doc bug here)
* [x] Am core contributor.

## Detailed Description of the Pull Request / Additional comments
- I found four settings that weren't hot reloadable with the 3927 comment above them:
1. Experimental retro terminal effect
2. Experimental software rendering
3. Experimental full repaint rendering
4. Antialiasing settings for text

I made them all hot reloadable by telling the `TermControl` to propagate them on settings change to the `DxEngine`.
Then I set up the `DxEngine` inside the setters to only set them if they changed. And if they do change, to trigger a full repaint and/or a complete drop and recreate of the entire DX device chain (as would happen if it were lost for another reason like a user-mode graphics failure, disconnected display, etc.)
I made the boolean an atomic because the settings can be coming in off of another thread (the XAML eventing one) and the renderer is picking the status up on its thread at the top of the BeginPaint frame.

## Validation Steps Performed
- [x] Opened it up and toggled all the settings while staring at PowerShell
- [x] Opened it up and toggled all the settings while staring at something intensive like a `cacafire` fire
2020-06-19 21:09:37 +00:00
greg904 a921bbfebb
Reduce latency with DXGI 1.3 GetFrameLatencyWaitableObject (#6435)
This pull request reduces input lag, especially with selection, by using
`IDXGISwapChain2::GetFrameLatencyWaitableObject`.

This is based on the [DXGI 1.3 documentation].

Excerpt from the [DXGI 1.3 improvement list]:
> The following functionality has been added in Microsoft DirectX
Graphics Infrastructure (DXGI) 1.3, which is included starting in
Windows 8.1.

Before, during rendering:
1. render frame
2. call `Present` on swap chain:
   2.a. blocks until it can present
   2.b. meanwhile, selection/text in terminal might have changed, but
     we're still using the frame that we rendered before blocking
   2.c. presents

After, during rendering:
1. block until we can present
2. render frame with latest data
3. call `Present` on swap chain:
  3.a. present without blocking

[DXGI 1.3 documentation]: https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains
[DXGI 1.3 improvement list]: https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/dxgi-1-3-improvements:
2020-06-10 22:35:14 +00:00
Mike Griese 1fcd95704d
Draw the cursor underneath text, and above the background (#6337)
## Summary of the Pull Request

![textAboveCursor003](https://user-images.githubusercontent.com/18356694/83681722-67a24d00-a5a8-11ea-8d9b-2d294065e4e4.gif)

This is the plan that @miniksa suggested to me. Instead of trying to do lots of work in all the renderers to do backgrounds as one pass, and foregrounds as another, we can localize this change to basically just the DX renderer. 
1. First, we give the DX engine a "heads up" on where the cursor is going to be drawn during the frame, in `PrepareRenderInfo`.
  - This function is left unimplemented in the other render engines.
2. While printing runs of text, the DX renderer will try to paint the cursor in `CustomTextRenderer::DrawGlyphRun` INSTEAD of `DxEngine::PaintCursor`. This lets us weave the cursor background between the text background and the text. 

## References

* #6151 was a spec in this general area. I should probably go back and update it, and we should probably approve that first.
* #6193 is also right up in this mess

## PR Checklist
* [x] Closes #1203
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

* This is essentially `"cursorTextColor": "textForeground"` from #6151.
* A follow up work item is needed to add support for the current behavior, (`"cursorTextColor": null`), and hooking up that setting to the renderer.
2020-06-04 12:58:22 +00:00
Michael Niksa d01317c9db
Add renderer settings to mitigate blurry text for some graphics devices
## Summary of the Pull Request
Adds user settings to adjust rendering behavior to mitigate blurry text on some devices.

## References
- #778 introduced this, almost certainly.

## PR Checklist
* [x] Closes #5759, mostly
* [x] I work here.
* [ ] We need community verification that this will help.
* [x] Updated schema and schema doc.
* [x] Am core contributor. Discussed in Monday sync meeting and w/ @DHowett-MSFT. 

## Detailed Description of the Pull Request / Additional comments
When we switched from full-screen repaints to incremental rendering, it seems like we exposed a situation where some display drivers and hardware combinations do not handle scroll and/or dirty regions (from `IDXGISwapChain::Present1`) without blurring the data from the previous frame. As we're really close to ship, I'm offering two options to let people in this situation escape it on their own. We hope in the future to figure out what's actually going on here and mitigate it further in software, but until then, these escape hatches are available.

1. `experimental.rendering.forceFullRepaint` - This one restores the pre-778 behavior to the Terminal. On every single frame paint, we'll invalidate the entire screen and repaint it.
2. `experimental.rendering.software` - This one uses the software WARP renderer instead of using the hardware and display driver directly. The theory is that this will sidestep any driver bugs or hardware variations.

One, the other, or both of these may be field-applied by users who are experiencing this behavior. 

Reverting #778 completely would also resolve this, but it would give back our largest performance win in the whole Terminal project. We don't believe that's acceptable when seemingly a majority of the users are experiencing the performance benefit with no detriment to graphical display.

## Validation Steps Performed
- [x] Flipped them on and verified with the debugger that they are being applied to the rendering pipeline
- [ ] Gave a private copy to community members in #5759 and had them try whether one, the other, or both resolved their issue.
2020-05-11 14:54:03 -07:00
Michael Niksa 70867df077
Scale box drawing glyphs to fit cells for visual bliss (#5743)
## Summary of the Pull Request
Identifies and scales glyphs in the box and line drawing ranges U+2500-U+259F to fit their cells.

## PR Checklist
* [x] Closes #455
* [x] I work here.
* [x] Manual tests. This is all graphical.
* [x] Metric ton of comments
* [x] Math spreadsheet included in PR.
* [x] Double check RTL glyphs.
* [x] Why is there the extra pixel?
* [x] Scrolling the mouse wheel check is done.
* [x] Not drawing outline?
* [x] Am core contributor. Roar.
* [x] Try suppressing negative scale factors and see if that gets rid of weird shading.

## Detailed Description of the Pull Request / Additional comments

### Background
- We want the Terminal to be fast at drawing. To be fast at drawing, we perform differential drawing, or only drawing what is different from the previous frame. We use DXGI's `Present1` method to help us with this as it helps us compose only the deltas onto the previous frame at drawing time and assists us in scrolling regions from the previous frame without intervention. However, it only works on strictly integer pixel row heights.
- Most of the hit testing and size-calculation logic in both the `conhost` and the Terminal products are based on the size of an individual cell. Historically, a cell was always dictated in a `COORD` structure, or two `SHORT` values... which are integers. As such, when we specify the space for any individual glyph to be displayed inside our terminal drawing region, we want it to fall perfectly inside of an integer box to ensure all these other algorithms work correctly and continue to do so.
- Finally, we want the Terminal to have font fallback and locate glyphs that aren't in the primary selected font from any other font it can find on the system that contains the glyph, per DirectWrite's font fallback mechanisms. These glyphs won't necessarily have the same font or glyph metrics as the base font, but we need them to fit inside the same cell dimensions as if they did because the hit testing and other algorithms aren't aware of which particular font is sourcing each glyph, just the dimensions of the bounding box per cell.

### How does Terminal deal with this?
- When we select a font, we perform some calculations using the design metrics of the font and glyphs to determine how we could fit them inside a cell with integer dimensions. Our process here is that we take the requested font size (which is generally a proxy for height), find the matching glyph width for that height then round it to an integer. We back convert from that now integer width to a height value which is almost certainly now a floating point number. But because we need an integer box value, we add line padding above and below the glyphs to ensure that the height is an integer as well as the width. Finally, we don't add the padding strictly equally. We attempt to align the English baseline of the glyph box directly onto an integer pixel multiple so most characters sit crisply on a line when displayed. 
- Note that fonts and their glyphs have a prescribed baseline, line gap, and advance values. We use those as guidelines to get us started, but then to meet our requirements, we pad out from those. This results in fonts that should be properly authored showing gaps. It also results in fonts that are improperly authored looking even worse than they normally would.

### Now how does block and line drawing come in?
- Block and Line drawing glyphs are generally authored so they will look fine when the font and glyph metrics are followed exactly as prescribed by the font. (For some fonts, this still isn't true and we want them to look fine anyway.)
- When we add additional padding or rounding to make glyphs fit inside of a cell, we can be adding more space than was prescribed around these glyphs. This can cause a gap to be visible.
- Additionally, when we move things like baselines to land on a perfect integer pixel, we may be drawing a glyph lower in the bounding box than was prescribed originally.

### And how do we solve it?
- We identify all glyphs in the line and block drawing ranges.
- We find the bounding boxes of both the cell and the glyph.
- We compare the height of the glyph to the height of the cell to see if we need to scale. We prescribe a scale transform if the glyph wouldn't be tall enough to fit the box. (We leave it alone otherwise as some glyphs intentionally overscan the box and scaling them can cause banding effects.)
- We inspect the overhang/underhang above and below the boxes and translate transform them (slide them) so they cover the entire cell area.
- We repeat the previous two steps but in the horizontal direction.

## Validation Steps Performed
- See these commments:
   - https://github.com/microsoft/terminal/issues/455#issuecomment-620248375
   - https://github.com/microsoft/terminal/issues/455#issuecomment-621533916
   - https://github.com/microsoft/terminal/issues/455#issuecomment-622585453

Also see the below one with more screenshots:
   - https://github.com/microsoft/terminal/pull/5743#issuecomment-624940567
2020-05-08 14:09:32 -07:00
Mike Griese c803893c22
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 17:16:34 +00:00
Michael Niksa 8ea9b327f3
Adjusts High DPI scaling to enable differential rendering (#5345)
## Summary of the Pull Request
- Adjusts scaling practices in `DxEngine` (and related scaling practices in `TerminalControl`) for pixel-perfect row baselines and spacing at High DPI such that differential row-by-row rendering can be applied at High DPI.

## References
- #5185 

## PR Checklist
* [x] Closes #5320, closes #3515, closes #1064
* [x] I work here.
* [x] Manually tested.
* [x] No doc.
* [x] Am core contributor. Also discussed with some of them already via Teams.

## Detailed Description of the Pull Request / Additional comments

**WAS:**
- We were using implicit DPI scaling on the `ID2D1RenderTarget` and running all of our processing in DIPs (Device-Independent Pixels). That's all well and good for getting things bootstrapped quickly, but it leaves the actual scaling of the draw commands up to the discretion of the rendering target.
- When we don't get to explicitly choose exactly how many pixels tall/wide and our X/Y placement perfectly, the nature of floating point multiplication and division required to do the presentation can cause us to drift off slightly out of our control depending on what the final display resolution actually is.
- Differential drawing cannot work unless we can know the exact integer pixels that need to be copied/moved/preserved/replaced between frames to give to the `IDXGISwapChain1::Present1` method. If things spill into fractional pixels or the sizes of rows/columns vary as they are rounded up and down implicitly, then we cannot do the differential rendering.

**NOW:**
- When deciding on a font, the `DxEngine` will take the scale factor into account and adjust the proposed height of the requested font. Then the remainder of the existing code that adjusts the baseline and integer-ifies each character cell will run naturally from there. That code already works correctly to align the height at normal DPI and scale out the font heights and advances to take an exact integer of pixels.
- `TermControl` has to use the scale now, in some places, and stop scaling in other places. This has to do with how the target's nature used to be implicit and is now explicit. For instance, determining where the cursor click hits must be scaled now. And determining the pixel size of the display canvas must no longer be scaled.
- `DxEngine` will no longer attempt to scale the invalid regions per my attempts in #5185 because the cell size is scaled. So it should work the same as at 96 DPI.
- The block is removed from the `DxEngine` that was causing a full invalidate on every frame at High DPI.
- A TODO was removed from `TermControl` that was invalidating everything when the DPI changed because the underlying renderer will already do that.

## Validation Steps Performed
* [x] Check at 150% DPI. Print text, scroll text down and up, do selection.
* [x] Check at 100% DPI. Print text, scroll text down and up, do selection.
* [x] Span two different DPI monitors and drag between them.
* [x] Giant pile of tests in https://github.com/microsoft/terminal/pull/5345#issuecomment-614127648

Co-authored-by: Dustin Howett <duhowett@microsoft.com>
Co-authored-by: Mike Griese <migrie@microsoft.com>
2020-04-22 14:59:51 -07:00
Michael Niksa 79684bf821
Render row-by-row instead of invalidating entire screen (#5185)
## Summary of the Pull Request
Adjusts DirectX renderer to use `til::bitmap` to track invalidation
regions. Uses special modification to invalidate a row-at-a-time to
ensure ligatures and NxM glyphs continue to work.

## References
Likely helps #1064

## PR Checklist
* [x] Closes #778
* [x] I work here.
* [x] Manual testing performed. See Performance traces in #778.
* [x] Automated tests for `til` changes.
* [x] Am core contributor. And discussed with @DHowett-MSFT.

## Detailed Description of the Pull Request / Additional comments
- Applies `til::bitmap` as the new invalidation scheme inside the
  DirectX renderer and updates all entrypoints for collecting
  invalidation data to coalesce into this structure.
- Semi-permanently routes all invalidations through a helper method
  `_InvalidateRectangle` that will expand any invalidation to cover the
  entire line. This ensures that ligatures and NxM glyphs will continue
  to render appropriately while still allowing us to dramatically reduce
  the number of lines drawn overall. In the future, we may come up with
  a tighter solution than line-by-line invalidation and can modify this
  helper method appropriately at that later date to further scope the
  invalid region.
- Ensures that the `experimental.retroTerminalEffects` feature continues
  to invalidate the entire display on start of frame as the shader is
  applied at the end of the frame composition and will stack on itself
  in an amusing fashion when we only redraw part of the display.
- Moves many member variables inside the DirectX renderer into the new
  `til::size`, `til::point`, and `til::rectangle` methods to facilitate
  easier management and mathematical operations. Consequently adds
  `try/catch` blocks around many of the already-existing `noexcept`
  methods to deal with mathematical or casting failures now detected by
  using the support classes.
- Corrects `TerminalCore` redraw triggers to appropriately communicate
  scrolling circumstances to the renderer so it can optimize the draw
  regions appropriately.
- Fixes an issue in the base `Renderer` that was causing overlapping
  scroll regions due to behavior of `Viewport::TrimToViewport` modifying
  the local. This fix is "good enough" for now and should go away when
  `Viewport` is fully migrated to `til::rectangle`.
- Adds multiplication and division operators to `til::rectangle` and
  supporting tests. These operates will help scale back and forth
  between a cell-based rectangle and a pixel-based rectangle. They take
  special care to ensure that a pixel rectangle being divided downward
  back to cells will expand (with the ceiling division methods) to cover
  a full cell when even one pixel inside the cell is touched (as is how
  a redraw would have to occur).
- Blocks off trace logging of invalid regions if no one is listening to
  optimize performance.
- Restores full usage of `IDXGISwapChain1::Present1` to accurately and
  fully communicate dirty and scroll regions to the underlying DirectX
  framework. This additional information allows the framework to
  optimize drawing between frames by eliminating data transfer of
  regions that aren't modified and shuffling frames in place. See
  [Remarks](https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/nf-dxgi1_2-idxgiswapchain1-present1#remarks)
  for more details.
- Updates `til::bitmap` set methods to use more optimized versions of
  the setters on the `dynamic_bitset<>` that can bulk fill bits as the
  existing algorithm was noticeably slow after applying the
  "expand-to-row" helper to the DirectX renderer invalidation.
- All `til` import hierarchy is now handled in the parent `til.h` file
  and not in the child files to prevent circular imports from happening.
  We don't expect the import of any individual library file, only the
  base one. So this should be OK for now.

## Validation Steps Performed
- Ran `cmatrix`, `cmatrix -u0`, and `cacafire` after changes were made.
- Made a bunch of ligatures with `Cascadia Code` in the Terminal
  before/after the changes and confirmed they still ligate.
- Ran `dir` in Powershell and fixed the scrolling issues
- Clicked all over the place and dragged to make sure selection works.
- Checked retro terminal effect manually with Powershell.
2020-04-13 20:09:02 +00:00
Michael Niksa ca33d895a3
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 15:57:54 +00:00
Michael Niksa 2b6e96a745
Move dirty interface to N rectangles, not just one (#4854)
## Summary of the Pull Request
- Changes the `IRenderEngine` interface to return a vector of values instead of just a single one. Engines that want to report one still can. Engines that want to report multiple smaller ones will be able to do so going forward.

## PR Checklist
* [x] In support of differential rendering #778
* [x] I work here.
* [x] Manually tested it still works.
* [x] Am core contributor.

## Detailed Description of the Pull Request / Additional comments
- Some of my ideas for the `DxEngine` require the ability to specify multiple smaller rectangles instead of one giant one, specifically to mitigate the case where someone refreshes just one cell in two opposite corners of the display (which currently coalesces into refreshing the entire display.)
- This is pulled out into an individual PR to make it easier to review that concept changing.

## Validation Steps Performed
- Ran the Terminal
2020-03-10 20:31:46 +00:00
Mike Griese e5182fb3e8
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 16:40:11 +00:00
Paul Ming de5e72f3a4
Scale retro terminal scan lines (#4716)
<!-- 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
- Scale the retro terminal effects (#3468) scan lines with the screen's DPI.
- Remove artifacts from sampling wrap around.

Before & after, with my display scale set to 350%:
![Scaling scan lines](https://user-images.githubusercontent.com/38924837/75214566-df0f4780-5742-11ea-9bdc-3430eb24ccca.png)

Before & after showing artifact removal, with my display scale set to 100%, and image enlarged to 400%:
![Sampling artifacts annotated](https://user-images.githubusercontent.com/38924837/75214618-05cd7e00-5743-11ea-9060-f4eba257ea56.png)

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #4362
* [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

Adds a constant buffer, which could be used for other settings for the retro terminal pixel shader.

I haven't touched C++ in over a decade before this change, and this is the first time I've played with DirectX, so please assume my code isn't exactly best practice. 🙂

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

- Changed display scale with experimental.retroTerminalEffect enabled, enjoyed scan lines on high resolution monitors.
- Enabled experimental.retroTerminalEffect, turned the setting off, changed display scale. Retro tabs still scale scan lines.
2020-02-26 00:08:45 +00:00
Mike Griese 8a5407c13a
Add support for cleartype text antialiasing (#4711)
## Summary of the Pull Request

I needed to do something to keep sane so today I day of learned about antialiasing. This PR adds the ability to specify the `"antialiasingMode"` as a setting.
* "antialiasingMode": "grayscale": the current behavior, `D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE`
* "antialiasingMode": "cleartype": use `D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE` instead


## PR Checklist
* [x] Closes #1298
* [x] I work here
* [ ] I didn't add tests 
* [x] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments
Grayscale:
 
![image](https://user-images.githubusercontent.com/18356694/75173847-2373f680-56f5-11ea-8896-c1cf04c61d41.png)



Cleartype:
![image](https://user-images.githubusercontent.com/18356694/75173854-25d65080-56f5-11ea-9de1-e2d1c343cae5.png)

 


Side-by-side (can you tell which is which?) <!-- grayscale, cleartype -->
 
![image](https://user-images.githubusercontent.com/18356694/75173864-28d14100-56f5-11ea-8bdd-d47a60fbbe4d.png)
2020-02-25 22:19:57 +00:00
Michael Niksa 215df3212f
Add DxEngine drawing ETW tracing for debugging and diagnostics purposes (#4664)
## Summary of the Pull Request
Adds an ETW provider for tracing out operations inside the DirectX Renderer.

## References
This supports #2191 and #778 and other rendering issues.

## PR Checklist
* [x] I work here

## Detailed Description of the Pull Request / Additional comments
This declares and defines the provider with the a GUID appropriate for the namespace and adds an initial invalidation rectangle method for figuring out what is being drawn mostly to understand what could be differential.

## Validation Steps Performed
Implemented provider.
Opened real-time ETW tracing tool
Ran the Terminal and watched invalidation events appear live
2020-02-20 23:13:43 +00:00
ironyman 9ae43377b0 Add experimental retro terminal effects (#3468)
<!-- 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
Cool retro terminal effects
- glow
- scan lines
- cool
- will make terminal competitive with iterm2

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> 
## References

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #xxx
* [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

<!-- 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/502496/68365644-20bda900-00e6-11ea-8a9d-0a4482e48c5a.png)
2019-12-12 13:44:01 +00:00
Leon Liang a404778271 Add Selection Background Color as a setting to Profiles and Col… (#3471)
<!-- 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 introduces a setting to both Profiles and ColorSchemes called <code>selectionBackground</code> that allows you to change the selection background color to what's specified. If <code>selectionBackground</code> isn't set in either the profile or color scheme, it'll default to what it was before - white.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #3326
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [x] Requires documentation to be updated

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
- Added selectionBackground to existing profile and colorscheme tests.
- Verified that the color does change to what I expect it to be when I add "selectionBackground" to either/both a profile and a color scheme.


<hr>

* adding selectionBackground to ColorScheme and TerminalSettings

* Changing PaintSelection inside the renderers to take a SelectionBackground COLORREF

* changes to conhost and terminal renderdata, and to terminal settings and core

* IT WORKS

* modification of unit tests, json schemas, reordering of functions

* more movement

* changed a couple of unit tests to add selectionBackground, added the setting to schemas, also added the optional setting to profiles

* default selection background should be slightly offwhite like the default foreground is

* reverting changes to .sln

* cleaning up

* adding comment

* oops

* added clangformat to my vs hehe

* moving selectionBackground to IControlSettings and removing from ICoreSettings

* trying to figure out why the WHOLE FILE LOOKS LIKE ITS CHANGED

* here it goes again

* pls

* adding default foreground as the default for selection background in dx
2019-11-13 12:17:39 -06:00
Mike Griese dec5c11e19
Add support for passing through extended text attributes, like… (#2917)
## Summary of the Pull Request
Adds support for Italics, Blinking, Invisible, CrossedOut text, THROUGH CONPTY. This does **NOT** add support for those styles to conhost or the terminal.

We will store these "Extended Text Attributes" in a `TextAttribute`. When we go to render a line, we'll see if the state has changed from our previous state, and if so, we'll appropriately toggle that state with VT. Boldness has been moved from a `bool` to a single bit in these flags.

Technically, now that these are stored in the buffer, we only need to make changes to the renderers to be able to support them. That's not being done as a part of this PR however.

## References
See also #2915 and #2916, which are some follow-up tasks from this fix. I thought them too risky for 20H1.

## PR Checklist
* [x] Closes #2554
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated


<hr>

* store text with extended attributes too

* Plumb attributes through all the renderers

* parse extended attrs, though we're not renderering them right

* Render these states correctly

* Add a very extensive test

* Cleanup for PR

* a block of PR feedback

* add 512 test cases

* Fix the build

* Fix @carlos-zamora's suggestions

* @miniksa's PR feedback
2019-10-04 15:53:54 -05:00
Michael Niksa 52534c94cc Combined changes to make the build work again (see inside) (#2945)
* Revert "Add source linking information during the build (#2857)"

This reverts commit 6b728cd6d0.

* Need reference to renderer base inside UnitTests_TerminalCore
* add dependency for TerminalControl to Types project.
* Set build to single threaded as parallel build is broken by 16.3 build toolchain.
* Disable new rule C26814 as it's breaking builds
   Wrote a follow up task #2941 to roll it out later.
* Add noexcept to dx header.
2019-09-30 10:39:55 -07:00
Michael Niksa d8ff47a0d3 Some of the PR feedback. 2019-09-05 17:21:54 -07:00