diff options
author | Neil <nyamatongwe@gmail.com> | 2021-05-01 16:48:50 +1000 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2021-05-01 16:48:50 +1000 |
commit | 93591238af8bf8b5246adcfe7a115f443442f44e (patch) | |
tree | 94b402e2a6c39d622a49be999517ff83be9ce378 /src/EditView.cxx | |
parent | 1f5a3b0b2d81351819ebb189a1ae4379e8762e75 (diff) | |
download | scintilla-mirror-93591238af8bf8b5246adcfe7a115f443442f44e.tar.gz |
Improve selection drawing code. Use InSelection enum instead of int.
Add Selection::RangeType and EditModel::LineEndInSelection to hoist code out of
EditView.
Replace SimpleAlphaRectangle with Surface::FillRectangleAligned when alpha known
to not be SC_ALPHA_NOALPHA.
Diffstat (limited to 'src/EditView.cxx')
-rw-r--r-- | src/EditView.cxx | 119 |
1 files changed, 65 insertions, 54 deletions
diff --git a/src/EditView.cxx b/src/EditView.cxx index 1061d28fc..8b9eff781 100644 --- a/src/EditView.cxx +++ b/src/EditView.cxx @@ -821,30 +821,41 @@ Sci::Position EditView::StartEndDisplayLine(Surface *surface, const EditModel &m return posRet; } -static ColourAlpha SelectionBackground(const ViewStyle &vsDraw, bool main, bool primarySelection) noexcept { - return main ? - (primarySelection ? *vsDraw.selection.colours.back : vsDraw.selection.background2) : - vsDraw.selection.additionalBackground; +namespace { + +ColourAlpha SelectionBackground(const ViewStyle &vsDraw, InSelection inSelection, bool primarySelection) noexcept { + if (!inSelection) + return ColourAlpha(0, 0, 0, 0); // Not selected -> transparent + + if (!vsDraw.selection.colours.back) + return ColourAlpha(0, 0, 0, 0); // Not set -> transparent + + if (!primarySelection) + return vsDraw.selection.background2; // Secondary selection + + if (inSelection == 1) + return *vsDraw.selection.colours.back; // Main selection + + return vsDraw.selection.additionalBackground; // Additional selection +} + } static ColourAlpha TextBackground(const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - std::optional<ColourAlpha> background, int inSelection, bool inHotspot, int styleMain, Sci::Position i) noexcept { - if (inSelection == 1) { - if (vsDraw.selection.colours.back && (vsDraw.selection.alpha == SC_ALPHA_NOALPHA)) { - return SelectionBackground(vsDraw, true, model.primarySelection); - } - } else if (inSelection == 2) { - if (vsDraw.selection.colours.back && (vsDraw.selection.additionalAlpha == SC_ALPHA_NOALPHA)) { - return SelectionBackground(vsDraw, false, model.primarySelection); - } - } else { - if ((vsDraw.edgeState == EDGE_BACKGROUND) && - (i >= ll->edgeColumn) && - (i < ll->numCharsBeforeEOL)) - return vsDraw.theEdge.colour; - if (inHotspot && vsDraw.hotspotColours.back) - return *vsDraw.hotspotColours.back; - } + std::optional<ColourAlpha> background, InSelection inSelection, bool inHotspot, int styleMain, Sci::Position i) noexcept { + if (inSelection && vsDraw.selection.colours.back) { + if ((inSelection == InSelection::inMain) && (vsDraw.selection.alpha == SC_ALPHA_NOALPHA)) { + return SelectionBackground(vsDraw, inSelection, model.primarySelection); + } else if ((inSelection == InSelection::inAdditional) && (vsDraw.selection.additionalAlpha == SC_ALPHA_NOALPHA)) { + return SelectionBackground(vsDraw, inSelection, model.primarySelection); + } + } + if ((vsDraw.edgeState == EDGE_BACKGROUND) && + (i >= ll->edgeColumn) && + (i < ll->numCharsBeforeEOL)) + return vsDraw.theEdge.colour; + if (inHotspot && vsDraw.hotspotColours.back) + return *vsDraw.hotspotColours.back; if (background && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) { return *background; } else { @@ -942,7 +953,8 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle if (virtualSpace > 0.0f) { rcSegment.left = xEol + xStart; rcSegment.right = xEol + xStart + virtualSpace; - surface->FillRectangleAligned(rcSegment, Fill(background ? *background : vsDraw.styles[ll->styles[ll->numCharsInLine]].back)); + const ColourAlpha backgroundFill = background.value_or(vsDraw.styles[ll->styles[ll->numCharsInLine]].back); + surface->FillRectangleAligned(rcSegment, backgroundFill); if (!hideSelection && ((vsDraw.selection.alpha == SC_ALPHA_NOALPHA) || (vsDraw.selection.additionalAlpha == SC_ALPHA_NOALPHA))) { const SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)), SelectionPosition(model.pdoc->LineEnd(line), @@ -959,21 +971,22 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth; rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; - surface->FillRectangleAligned(rcSegment, Fill(SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection))); + surface->FillRectangleAligned(rcSegment, Fill(SelectionBackground(vsDraw, model.sel.RangeType(r), model.primarySelection))); } } } } } - int eolInSelection = 0; + InSelection eolInSelection = InSelection::inNone; int alpha = SC_ALPHA_NOALPHA; - if (!hideSelection) { - const Sci::Position posAfterLineEnd = model.pdoc->LineStart(line + 1); - eolInSelection = lastSubLine ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0; - alpha = (eolInSelection == 1) ? vsDraw.selection.alpha : vsDraw.selection.additionalAlpha; + if (!hideSelection && lastSubLine) { + eolInSelection = model.LineEndInSelection(line); + alpha = (eolInSelection == InSelection::inMain) ? vsDraw.selection.alpha : vsDraw.selection.additionalAlpha; } + const ColourAlpha selectionBack = SelectionBackground(vsDraw, eolInSelection, model.primarySelection); + // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on XYPOSITION blobsWidth = 0; if (lastSubLine) { @@ -1000,11 +1013,11 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle } ColourAlpha textFore = vsDraw.styles[styleMain].fore; if (eolInSelection && vsDraw.selection.colours.fore) { - textFore = (eolInSelection == 1) ? *vsDraw.selection.colours.fore : vsDraw.selection.additionalForeground; + textFore = (eolInSelection == InSelection::inMain) ? *vsDraw.selection.colours.fore : vsDraw.selection.additionalForeground; } if (eolInSelection && vsDraw.selection.colours.back && (line < model.pdoc->LinesTotal() - 1)) { if (alpha == SC_ALPHA_NOALPHA) { - surface->FillRectangleAligned(rcSegment, Fill(SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection))); + surface->FillRectangleAligned(rcSegment, Fill(selectionBack)); } else { surface->FillRectangleAligned(rcSegment, Fill(textBack)); } @@ -1013,7 +1026,7 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle } DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, phasesDraw == PhasesDraw::one); if (eolInSelection && vsDraw.selection.colours.back && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); + surface->FillRectangleAligned(rcSegment, ColourAlpha(selectionBack, alpha)); } } } @@ -1023,7 +1036,7 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle rcSegment.right = rcSegment.left + vsDraw.aveCharWidth; if (eolInSelection && vsDraw.selection.colours.back && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { - surface->FillRectangleAligned(rcSegment, Fill(SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection))); + surface->FillRectangleAligned(rcSegment, Fill(selectionBack)); } else { if (background) { surface->FillRectangleAligned(rcSegment, Fill(*background)); @@ -1035,7 +1048,7 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle surface->FillRectangleAligned(rcSegment, Fill(vsDraw.styles[STYLE_DEFAULT].back)); } if (eolInSelection && vsDraw.selection.colours.back && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); + surface->FillRectangleAligned(rcSegment, ColourAlpha(selectionBack, alpha)); } } @@ -1202,12 +1215,11 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con const Font *fontText = vsDraw.styles[STYLE_FOLDDISPLAYTEXT].font.get(); const int widthFoldDisplayText = static_cast<int>(surface->WidthText(fontText, foldDisplayText)); - int eolInSelection = 0; + InSelection eolInSelection = InSelection::inNone; int alpha = SC_ALPHA_NOALPHA; if (!hideSelection) { - const Sci::Position posAfterLineEnd = model.pdoc->LineStart(line + 1); - eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0; - alpha = (eolInSelection == 1) ? vsDraw.selection.alpha : vsDraw.selection.additionalAlpha; + eolInSelection = model.LineEndInSelection(line); + alpha = (eolInSelection == InSelection::inMain) ? vsDraw.selection.alpha : vsDraw.selection.additionalAlpha; } const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; @@ -1219,7 +1231,7 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con const std::optional<ColourAlpha> background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret); ColourAlpha textFore = vsDraw.styles[STYLE_FOLDDISPLAYTEXT].fore; if (eolInSelection && (vsDraw.selection.colours.fore)) { - textFore = (eolInSelection == 1) ? *vsDraw.selection.colours.fore : vsDraw.selection.additionalForeground; + textFore = (eolInSelection == InSelection::inMain) ? *vsDraw.selection.colours.fore : vsDraw.selection.additionalForeground; } const ColourAlpha textBack = TextBackground(model, vsDraw, ll, background, eolInSelection, false, STYLE_FOLDDISPLAYTEXT, -1); @@ -1266,7 +1278,7 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con if (FlagSet(phase, DrawPhase::selectionTranslucent)) { if (eolInSelection && vsDraw.selection.colours.back && (line < model.pdoc->LinesTotal() - 1) && alpha != SC_ALPHA_NOALPHA) { - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); + surface->FillRectangleAligned(rcSegment, ColourAlpha(SelectionBackground(vsDraw, eolInSelection, model.primarySelection), alpha)); } } } @@ -1345,7 +1357,7 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c const std::optional<ColourAlpha> background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret); const ColourAlpha textFore = vsDraw.styles[style].fore; - const ColourAlpha textBack = TextBackground(model, vsDraw, ll, background, false, + const ColourAlpha textBack = TextBackground(model, vsDraw, ll, background, InSelection::inNone, false, static_cast<int>(style), -1); if (model.trackLineWidth) { @@ -1705,7 +1717,7 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi if (rcSegment.right > rcLine.right) rcSegment.right = rcLine.right; - const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); + const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc); const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); ColourAlpha textBack = TextBackground(model, vsDraw, ll, background, inSelection, inHotspot, ll->styles[i], i); @@ -1803,13 +1815,13 @@ static void DrawTranslucentSelection(Surface *surface, const EditModel &model, c if (alpha != SC_ALPHA_NOALPHA) { const SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange); if (!portion.Empty()) { + const ColourAlpha selectionBack = ColourAlpha( + SelectionBackground(vsDraw, model.sel.RangeType(r), model.primarySelection), alpha); const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; if (model.BidirectionalEnabled()) { const int selectionStart = static_cast<int>(portion.start.Position() - posLineStart - lineRange.start); const int selectionEnd = static_cast<int>(portion.end.Position() - posLineStart - lineRange.start); - const ColourAlpha background = SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection); - const ScreenLine screenLine(ll, subLine, vsDraw, rcLine.right, tabWidthMinimumPixels); std::unique_ptr<IScreenLineLayout> slLayout = surface->Layout(&screenLine); @@ -1818,7 +1830,7 @@ static void DrawTranslucentSelection(Surface *surface, const EditModel &model, c const XYPOSITION rcRight = interval.right + xStart; const XYPOSITION rcLeft = interval.left + xStart; const PRectangle rcSelection(rcLeft, rcLine.top, rcRight, rcLine.bottom); - SimpleAlphaRectangle(surface, rcSelection, background, alpha); + surface->FillRectangleAligned(rcSelection, selectionBack); } if (portion.end.VirtualSpace()) { @@ -1827,7 +1839,7 @@ static void DrawTranslucentSelection(Surface *surface, const EditModel &model, c PRectangle rcSegment = rcLine; rcSegment.left = xStartVirtual + portion.start.VirtualSpace() * spaceWidth; rcSegment.right = xStartVirtual + portion.end.VirtualSpace() * spaceWidth; - SimpleAlphaRectangle(surface, rcSegment, background, alpha); + surface->FillRectangleAligned(rcSegment, selectionBack); } } else { PRectangle rcSegment = rcLine; @@ -1842,7 +1854,7 @@ static void DrawTranslucentSelection(Surface *surface, const EditModel &model, c rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; if (rcSegment.right > rcLine.left) - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection), alpha); + surface->FillRectangleAligned(rcSegment, selectionBack); } } } @@ -1950,7 +1962,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi } } } - const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); + const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc); if (inSelection && (vsDraw.selection.colours.fore)) { textFore = (inSelection == 1) ? *vsDraw.selection.colours.fore : vsDraw.selection.additionalForeground; } @@ -2439,18 +2451,17 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan void EditView::FillLineRemainder(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, Sci::Line line, PRectangle rcArea, int subLine) const { - int eolInSelection = 0; + InSelection eolInSelection = InSelection::inNone; int alpha = SC_ALPHA_NOALPHA; - if (!hideSelection) { - const Sci::Position posAfterLineEnd = model.pdoc->LineStart(line + 1); - eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0; - alpha = (eolInSelection == 1) ? vsDraw.selection.alpha : vsDraw.selection.additionalAlpha; + if ((!hideSelection) && (subLine == (ll->lines - 1))) { + eolInSelection = model.LineEndInSelection(line); + alpha = (eolInSelection == InSelection::inMain) ? vsDraw.selection.alpha : vsDraw.selection.additionalAlpha; } const std::optional<ColourAlpha> background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret); if (eolInSelection && vsDraw.selection.eolFilled && vsDraw.selection.colours.back && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { - surface->FillRectangleAligned(rcArea, Fill(SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection))); + surface->FillRectangleAligned(rcArea, Fill(SelectionBackground(vsDraw, eolInSelection, model.primarySelection))); } else { if (background) { surface->FillRectangleAligned(rcArea, Fill(*background)); @@ -2460,7 +2471,7 @@ void EditView::FillLineRemainder(Surface *surface, const EditModel &model, const surface->FillRectangleAligned(rcArea, Fill(vsDraw.styles[STYLE_DEFAULT].back)); } if (eolInSelection && vsDraw.selection.eolFilled && vsDraw.selection.colours.back && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { - SimpleAlphaRectangle(surface, rcArea, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); + surface->FillRectangleAligned(rcArea, ColourAlpha(SelectionBackground(vsDraw, eolInSelection, model.primarySelection), alpha)); } } } |