Skip to content

Commit

Permalink
atlas: add support for selection colors
Browse files Browse the repository at this point in the history
This lets us get rid of SelectionFrom/SelectionTo and the selection
quad.
  • Loading branch information
DHowett committed Aug 9, 2024
1 parent 899c001 commit 95384f5
Show file tree
Hide file tree
Showing 8 changed files with 12 additions and 93 deletions.
9 changes: 6 additions & 3 deletions src/renderer/atlas/AtlasEngine.api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Backend.h"
#include "../../buffer/out/textBuffer.hpp"
#include "../base/FontCache.h"
#include "../../types/inc/ColorFix.hpp"

// #### NOTE ####
// If you see any code in here that contains "_r." you might be seeing a race condition.
Expand Down Expand Up @@ -423,12 +424,14 @@ void AtlasEngine::SetRetroTerminalEffect(bool enable) noexcept
}
}

void AtlasEngine::SetSelectionBackground(const COLORREF color, const float alpha) noexcept
void AtlasEngine::SetSelectionBackground(const COLORREF color, const float /*alpha*/) noexcept
{
const u32 selectionColor = (color & 0xffffff) | gsl::narrow_cast<u32>(lrintf(alpha * 255.0f)) << 24;
const u32 selectionColor = (color & 0xffffff) | 0xff000000;
if (_api.s->misc->selectionColor != selectionColor)
{
_api.s.write()->misc.write()->selectionColor = selectionColor;
auto misc = _api.s.write()->misc.write();
misc->selectionColor = selectionColor;
misc->selectionForeground = 0xff000000 | ColorFix::GetPerceivableColor(color, color, 0.5f * 0.5f);
}
}

Expand Down
25 changes: 3 additions & 22 deletions src/renderer/atlas/AtlasEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ CATCH_RETURN()
_api.searchHighlightFocused = { info.searchHighlightFocused, 1 };
}
}

_api.selectionSpans = til::point_span_subspan_within_rect(info.selectionSpans, dr);
}

return S_OK;
Expand Down Expand Up @@ -497,6 +499,7 @@ try
// Apply the highlighting colors to the highlighted cells
RETURN_IF_FAILED(_drawHighlighted(_api.searchHighlights, y, x, columnEnd, highlightFg, highlightBg));
RETURN_IF_FAILED(_drawHighlighted(_api.searchHighlightFocused, y, x, columnEnd, highlightFocusFg, highlightFocusBg));
RETURN_IF_FAILED(_drawHighlighted(_api.selectionSpans, y, x, columnEnd, _api.s->misc->selectionForeground, _api.s->misc->selectionColor));

_api.lastPaintBufferLineCoord = { x, y };
return S_OK;
Expand Down Expand Up @@ -563,31 +566,9 @@ try
CATCH_RETURN()

[[nodiscard]] HRESULT AtlasEngine::PaintSelection(std::span<const til::rect> rects) noexcept
try
{
// Unfortunately there's no step after Renderer::_PaintBufferOutput that
// would inform us that it's done with the last AtlasEngine::PaintBufferLine.
// As such we got to call _flushBufferLine() here just to be sure.
_flushBufferLine();

for (auto&& rect : rects)
{
const auto y = gsl::narrow_cast<u16>(clamp<til::CoordType>(rect.top, 0, _p.s->viewportCellCount.y - 1));
const auto from = gsl::narrow_cast<u16>(clamp<til::CoordType>(rect.left, 0, _p.s->viewportCellCount.x - 1));
const auto to = gsl::narrow_cast<u16>(clamp<til::CoordType>(rect.right, from, _p.s->viewportCellCount.x));

auto& row = *_p.rows[y];
row.selectionFrom = from;
row.selectionTo = to;

_p.dirtyRectInPx.left = std::min(_p.dirtyRectInPx.left, from * _p.s->font->cellSize.x);
_p.dirtyRectInPx.top = std::min(_p.dirtyRectInPx.top, y * _p.s->font->cellSize.y);
_p.dirtyRectInPx.right = std::max(_p.dirtyRectInPx.right, to * _p.s->font->cellSize.x);
_p.dirtyRectInPx.bottom = std::max(_p.dirtyRectInPx.bottom, _p.dirtyRectInPx.top + _p.s->font->cellSize.y);
}
return S_OK;
}
CATCH_RETURN()

[[nodiscard]] HRESULT AtlasEngine::PaintCursor(const CursorOptions& options) noexcept
try
Expand Down
1 change: 1 addition & 0 deletions src/renderer/atlas/AtlasEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ namespace Microsoft::Console::Render::Atlas
// These tracks the highlighted regions on the screen that are yet to be painted.
std::span<const til::point_span> searchHighlights;
std::span<const til::point_span> searchHighlightFocused;
std::span<const til::point_span> selectionSpans;

// dirtyRect is a computed value based on invalidatedRows.
til::rect dirtyRect;
Expand Down
21 changes: 0 additions & 21 deletions src/renderer/atlas/BackendD2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ void BackendD2D::Render(RenderingPayload& p)
_drawCursorPart1(p);
_drawText(p);
_drawCursorPart2(p);
_drawSelection(p);
#if ATLAS_DEBUG_SHOW_DIRTY
_debugShowDirty(p);
#endif
Expand Down Expand Up @@ -938,26 +937,6 @@ void BackendD2D::_drawCursor(const RenderingPayload& p, ID2D1RenderTarget* rende
}
}

void BackendD2D::_drawSelection(const RenderingPayload& p)
{
u16 y = 0;
for (const auto& row : p.rows)
{
if (row->selectionTo > row->selectionFrom)
{
const D2D1_RECT_F rect{
static_cast<f32>(p.s->font->cellSize.x * row->selectionFrom),
static_cast<f32>(p.s->font->cellSize.y * y),
static_cast<f32>(p.s->font->cellSize.x * row->selectionTo),
static_cast<f32>(p.s->font->cellSize.y * (y + 1)),
};
_fillRectangle(rect, p.s->misc->selectionColor);
}

y++;
}
}

#if ATLAS_DEBUG_SHOW_DIRTY
void BackendD2D::_debugShowDirty(const RenderingPayload& p)
{
Expand Down
40 changes: 0 additions & 40 deletions src/renderer/atlas/BackendD3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@ void BackendD3D::Render(RenderingPayload& p)
_drawBackground(p);
_drawCursorBackground(p);
_drawText(p);
_drawSelection(p);
_debugShowDirty(p);
_flushQuads(p);

Expand Down Expand Up @@ -2248,45 +2247,6 @@ size_t BackendD3D::_drawCursorForegroundSlowPath(const CursorRect& c, size_t off
return addedInstances;
}

void BackendD3D::_drawSelection(const RenderingPayload& p)
{
u16 y = 0;
u16 lastFrom = 0;
u16 lastTo = 0;

for (const auto& row : p.rows)
{
if (row->selectionTo > row->selectionFrom)
{
// If the current selection line matches the previous one, we can just extend the previous quad downwards.
// The way this is implemented isn't very smart, but we also don't have very many rows to iterate through.
if (row->selectionFrom == lastFrom && row->selectionTo == lastTo)
{
_getLastQuad().size.y += p.s->font->cellSize.y;
}
else
{
_appendQuad() = {
.shadingType = static_cast<u16>(ShadingType::Selection),
.position = {
static_cast<i16>(p.s->font->cellSize.x * row->selectionFrom),
static_cast<i16>(p.s->font->cellSize.y * y),
},
.size = {
static_cast<u16>(p.s->font->cellSize.x * (row->selectionTo - row->selectionFrom)),
static_cast<u16>(p.s->font->cellSize.y),
},
.color = p.s->misc->selectionColor,
};
lastFrom = row->selectionFrom;
lastTo = row->selectionTo;
}
}

y++;
}
}

void BackendD3D::_debugShowDirty(const RenderingPayload& p)
{
#if ATLAS_DEBUG_SHOW_DIRTY
Expand Down
1 change: 0 additions & 1 deletion src/renderer/atlas/BackendD3D.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ namespace Microsoft::Console::Render::Atlas
SolidLine,

Cursor,
Selection,

TextDrawingFirst = TextGrayscale,
TextDrawingLast = SolidLine,
Expand Down
7 changes: 2 additions & 5 deletions src/renderer/atlas/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ namespace Microsoft::Console::Render::Atlas
struct MiscellaneousSettings
{
u32 backgroundColor = 0;
u32 selectionColor = 0x7fffffff;
u32 selectionColor = 0xffffffff;
u32 selectionForeground = 0xff000000;
std::wstring customPixelShaderPath;
std::wstring customPixelShaderImagePath;
bool useRetroTerminalEffect = false;
Expand Down Expand Up @@ -475,8 +476,6 @@ namespace Microsoft::Console::Render::Atlas
bitmap.active = false;
gridLineRanges.clear();
lineRendition = LineRendition::SingleWidth;
selectionFrom = 0;
selectionTo = 0;
dirtyTop = y * cellHeight;
dirtyBottom = dirtyTop + cellHeight;
}
Expand All @@ -496,8 +495,6 @@ namespace Microsoft::Console::Render::Atlas
Bitmap bitmap;
std::vector<GridLineRange> gridLineRanges;
LineRendition lineRendition = LineRendition::SingleWidth;
u16 selectionFrom = 0;
u16 selectionTo = 0;
til::CoordType dirtyTop = 0;
til::CoordType dirtyBottom = 0;
};
Expand Down
1 change: 0 additions & 1 deletion src/renderer/atlas/shader_common.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#define SHADING_TYPE_CURLY_LINE 7
#define SHADING_TYPE_SOLID_LINE 8
#define SHADING_TYPE_CURSOR 9
#define SHADING_TYPE_SELECTION 10

struct VSData
{
Expand Down

1 comment on commit 95384f5

@github-actions
Copy link

Choose a reason for hiding this comment

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

@check-spelling-bot Report

🔴 Please review

See the 📜action log or 📝 job summary for details.

Unrecognized words (1)

rvp

Previously acknowledged words that are now absent Consoleroot gitmodules NTSYSCALLAPI Tpp vsconfig WDK wmemory 🫥
To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the [email protected]:microsoft/terminal.git repository
on the dev/duhowett/sel-3-atlas branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.22/apply.pl' |
perl - 'https://github.com/microsoft/terminal/actions/runs/10323955407/attempts/1'
Available 📚 dictionaries could cover words (expected and unrecognized) not in the 📘 dictionary

This includes both expected items (2229) from .github/actions/spelling/expect/04cdb9b77d6827c0202f51acd4205b017015bfff.txt
.github/actions/spelling/expect/alphabet.txt
.github/actions/spelling/expect/expect.txt
.github/actions/spelling/expect/web.txt and unrecognized words (1)

Dictionary Entries Covers Uniquely
cspell:cpp/src/lang-jargon.txt 11 1 1
cspell:swift/src/swift.txt 53 1 1
cspell:gaming-terms/dict/gaming-terms.txt 59 1 1
cspell:monkeyc/src/monkeyc_keywords.txt 123 1 1
cspell:cryptocurrencies/cryptocurrencies.txt 125 1 1

Consider adding them (in .github/workflows/spelling2.yml) for uses: check-spelling/[email protected] in its with:

      with:
        extra_dictionaries:
          cspell:cpp/src/lang-jargon.txt
          cspell:swift/src/swift.txt
          cspell:gaming-terms/dict/gaming-terms.txt
          cspell:monkeyc/src/monkeyc_keywords.txt
          cspell:cryptocurrencies/cryptocurrencies.txt

To stop checking additional dictionaries, add (in .github/workflows/spelling2.yml) for uses: check-spelling/[email protected] in its with:

check_extra_dictionaries: ''
Errors (1)

See the 📜action log or 📝 job summary for details.

❌ Errors Count
❌ ignored-expect-variant 6

See ❌ Event descriptions for more information.

✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Please sign in to comment.