88import Foundation
99
1010extension TextSelectionManager {
11- /// Calculate a set of rects for a text selection suitable for highlighting the selection.
11+ /// Calculate a set of rects for a text selection suitable for filling with the selection color to indicate a multi-line selection.
12+ ///
13+ /// The returned rects are inset by edge insets passed to the text view, the given `rect` parameter can be the 'raw'
14+ /// rect to draw in, no need to inset it before this method call.
15+ ///
1216 /// - Parameters:
1317 /// - rect: The bounding rect of available draw space.
1418 /// - textSelection: The selection to use.
@@ -25,27 +29,35 @@ extension TextSelectionManager {
2529 return [ ]
2630 }
2731
32+ let insetXPos = max ( layoutManager. edgeInsets. left, rect. minX)
33+ let insetWidth = max ( 0 , rect. maxX - insetXPos - layoutManager. edgeInsets. right)
34+ let insetRect = NSRect ( x: insetXPos, y: rect. origin. y, width: insetWidth, height: rect. height)
35+
2836 // Calculate the first line and any rects selected
2937 // If the last line position is not the same as the first, calculate any rects from that line.
3038 // If there's > 0 space between the first and last positions, add a rect between them to cover any
3139 // intermediate lines.
3240
33- fillRects. append ( contentsOf: getFillRects ( in: rect, selectionRange: range, forPosition: firstLinePosition) )
34-
35- if lastLinePosition. range != firstLinePosition. range {
36- fillRects. append ( contentsOf: getFillRects ( in: rect, selectionRange: range, forPosition: lastLinePosition) )
41+ let firstLineRects = getFillRects ( in: rect, selectionRange: range, forPosition: firstLinePosition)
42+ let lastLineRects : [ CGRect ] = if lastLinePosition. range != firstLinePosition. range {
43+ getFillRects ( in: rect, selectionRange: range, forPosition: lastLinePosition)
44+ } else {
45+ [ ]
3746 }
3847
48+ fillRects. append ( contentsOf: firstLineRects + lastLineRects)
49+
3950 if firstLinePosition. yPos + firstLinePosition. height < lastLinePosition. yPos {
4051 fillRects. append ( CGRect (
41- x: max ( layoutManager . edgeInsets . left , rect . minX ) ,
52+ x: insetXPos ,
4253 y: firstLinePosition. yPos + firstLinePosition. height,
43- width: rect . width ,
54+ width: insetWidth ,
4455 height: lastLinePosition. yPos - ( firstLinePosition. yPos + firstLinePosition. height)
4556 ) )
4657 }
4758
48- return fillRects
59+ // Pixel align these to avoid aliasing on the edges of each rect that should be a solid box.
60+ return fillRects. map { $0. intersection ( insetRect) . pixelAligned }
4961 }
5062
5163 /// Find fill rects for a specific line position.
0 commit comments