private void RedrawAdornments()

in src/MatchMargin/MatchMarginElement.cs [294:390]


        private void RedrawAdornments(IList<ITextViewLine> newOrReformattedLines, double viewportLeft, double viewportRight)
        {
            if (_areAdornmentsEnabled)
            {
                if ((newOrReformattedLines == null) || (viewportLeft < _left) || (viewportRight > _right))
                {
                    _left = viewportLeft - 50.0;    //Add in a little padding so small scrolls won't trigger a refresh.
                    _right = viewportRight + 50.0;

                    _layer.RemoveAllAdornments();
                    newOrReformattedLines = _textView.TextViewLines;
                }

                if ((_highlight != null) && (_search != null))
                {
                    //Take a snapshot of the matches found to date (this could still be changing
                    //if the search has not completed yet).
                    IList<SnapshotSpan> matches = _search.Matches;
                    if ((matches.Count > 0) && (matches[0].Snapshot == _textView.TextSnapshot))
                    {
                        //matches is sorted, as is newOrReformattedLines (as are the spans in visibleText), so keep track of the last match found since it
                        //is a good starting point for the next match.
                        int firstLegalMatch = 0;

                        int caretPosition = _textView.Caret.Position.BufferPosition;

                        foreach (var line in newOrReformattedLines)
                        {
                            //Find all matches on the visible text in line.
                            if (line.TextRight > _left)
                            {
                                SnapshotPoint? leftCharacter = line.GetBufferPositionFromXCoordinate(_left);
                                if (!leftCharacter.HasValue)
                                    leftCharacter = line.Start;

                                SnapshotPoint? rightCharacter = line.GetBufferPositionFromXCoordinate(_right);
                                if (!rightCharacter.HasValue)
                                    rightCharacter = line.End;

                                if (leftCharacter.Value.Position > rightCharacter.Value.Position)
                                {
                                    // Swap left & right (due to bidi sequences, we could end up with left coming after right in the buffer)
                                    var t = leftCharacter;
                                    leftCharacter = rightCharacter;
                                    rightCharacter = t;
                                }

                                //We know the start & endpoints exist, the edit & visual snapshots represent the same instant and we're mapping up so just map up
                                SnapshotPoint leftInVisualBuffer = _textView.TextViewModel.GetNearestPointInVisualSnapshot(leftCharacter.Value, _textView.VisualSnapshot, PointTrackingMode.Negative);
                                SnapshotPoint rightInVisualBuffer = _textView.TextViewModel.GetNearestPointInVisualSnapshot(rightCharacter.Value, _textView.VisualSnapshot, PointTrackingMode.Negative);

                                NormalizedSnapshotSpanCollection visibleText = _textView.BufferGraph.MapDownToSnapshot(new SnapshotSpan(leftInVisualBuffer, rightInVisualBuffer),
                                                                                                                                  SpanTrackingMode.EdgeInclusive, _textView.TextSnapshot);

                                foreach (var span in visibleText)
                                {
                                    while (true)
                                    {
                                        firstLegalMatch = FindMatchIndex(matches, span.Start, firstLegalMatch);
                                        if (firstLegalMatch >= matches.Count)
                                        {
                                            //No more matches, we might as well stop.
                                            return;
                                        }

                                        SnapshotSpan matchingSpan = matches[firstLegalMatch];

                                        if (matchingSpan.Start <= span.End)
                                        {
                                            ++firstLegalMatch;  //Make sure we don't redraw this adornment.

                                            //Don't draw the adornment for the word the caret is adjacent to.
                                            if ((caretPosition < matchingSpan.Start) || (caretPosition > matchingSpan.End))
                                            {
                                                Geometry g = _textView.TextViewLines.GetMarkerGeometry(matchingSpan);
                                                if (g != null)
                                                {
                                                    _layer.AddAdornment(matchingSpan, null, new GeometryAdornment(_adornmentMatchBrush, g));
                                                }
                                            }
                                        }
                                        else
                                            break;  //No matches in this span.
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                _layer.RemoveAllAdornments();
                _left = double.MaxValue;        //reset the left/right bounds so we'll redraw when options are turned back on.
                _right = double.MinValue;
            }
        }