rajdeep / proton

Purely native and extensible rich text editor for iOS and macOS Catalyst apps
Other
1.25k stars 81 forks source link

Issues with non-zero line spacing #282

Closed Chunngai closed 5 months ago

Chunngai commented 5 months ago

When testing the feature of background colour with rounded corners (as introduced here), I found two issues with a non-zero line spacing, as shown in the attached screenshot.

Screenshot 2024-02-21 at 2 24 21 PM

Issues

  1. Incorrect background location for text on the last line: the background colour of the word "to" on the last line of the text view is incorrect.
  2. Additional cursor height for text selection: when selecting the word "that" on the first line, the cursor height is greater than the line height (also, the height of the coloured background). (When using the vanilla approach to set the background colour with [.backgroundColor: myBackgroundColor], the cursor height is equal to line height)

Reproduction

  1. In the setup() method of ExampleApp/ExampleApp/AdvancedFeatures/CommandsExampleViewController, I added typingAttributes as follows:
    editor.typingAttributes = [.paragraphStyle:{
    let paraStyle = NSMutableParagraphStyle()
    paraStyle.lineSpacing = 10
    paraStyle.paragraphSpacing = 30
    return paraStyle
    }()]
  2. In the execute() method of ExampleApp/ExampleApp/Commands/TextBlockCommand.swift, I updated the background style as follows:
    let style = BackgroundStyle(
    color: .green,
    roundedCornerStyle: .absolute(value: 5),
    heightMode: .matchText
    )
  3. Run the app, and type some text in the text view. (Note that I have modified the button stack and only kept the "TextBlock" button)
  4. Select some text on the last line and click "TextBlock" to reproduce the first problem.
  5. Select arbitrary text to reproduce the second problem.

Any ideas to fix it?

The first problem may be caused by the code for .matchText in the drawBackground(forGlyphRange:at:) method of the customized LayoutManager.

rajdeep commented 5 months ago

@Chunngai, you may use matchTextExact with insets to get around this issue. Using the following style, you can achive the output below:

 let style = BackgroundStyle(color: .green, roundedCornerStyle: .absolute(value: 5), border: BorderStyle(lineWidth: 1, color: UIColor.blue),
                                    shadow: ShadowStyle(color: .red, offset: CGSize(width: 2, height: 2), blur: 1),
                                    heightMode: .matchTextExact, insets: UIEdgeInsets(top: -5, left: 0, bottom: -5, right: 0))
image

If you wish for the backgrounds to be merged as shown in the article, you can also use matchLine for heightMode.

I'll be fixing the matchText option in a future release to work better with lineSpacing. The key difference in matchText and matchTextExact is that the matchTextExact assumes the exact text height by default where as matchText keeps a little padding all around based on iOS string boundingRect logic. Since similar output can be achieved by matchTextExact with insets, I may also consider dropping matchText altogether.

Chunngai commented 5 months ago

@rajdeep Thanks, the problem was solved.