Fix line width calculation for expressions with superscripts/subscripts

The typesetter was incorrectly measuring line width when expressions contained
  superscripts or subscripts (e.g., b²). After rendering a superscript, the line
  is split into multiple display segments, but the width checking code was only
  measuring the current segment, not the total visual line width.

  Key changes:
  - Use currentPosition.x to track actual horizontal position across all segments
  - Calculate visualLineWidth = currentPosition.x + currentSegmentWidth
  - Pass remainingWidth (maxWidth - currentPosition.x) to findBestBreakPoint
  - Apply fix to both interatom breaking and inline text breaking

  This fixes truncation issues where content like "Δ=b²-4ac avec a=1..." was
  being clipped instead of wrapped to a new line.

  Before: Each segment checked in isolation → segments appeared to fit individually
          but total visual width exceeded maxWidth → content truncated/clipped

  After:  Total visual width tracked correctly → line breaking triggered when
          actual visual width exceeds maxWidth → content wraps properly
This commit is contained in:
Nicolas Guillot
2025-11-17 17:51:30 +01:00
parent 43c69240bd
commit 3aa6c6c98b
3 changed files with 57 additions and 23 deletions

View File

@@ -225,6 +225,39 @@ class MTMathUILabelLineWrappingTests: XCTestCase {
XCTAssertLessThan(constrainedSize.width, 250, "Width should respect constraint")
}
func testMixedTextMathNoTruncation() {
// Test for truncation bug: content should wrap, not be lost
// Input: \(\text{Calculer le discriminant }\Delta=b^{2}-4ac\text{ avec }a=1\text{, }b=-1\text{, }c=-5\)
let label = MTMathUILabel()
label.latex = "\\(\\text{Calculer le discriminant }\\Delta=b^{2}-4ac\\text{ avec }a=1\\text{, }b=-1\\text{, }c=-5\\)"
label.font = MTFontManager.fontManager.defaultFont
label.labelMode = .text
// Set width constraint that should cause wrapping
label.preferredMaxLayoutWidth = 235
let constrainedSize = label.intrinsicContentSize
// Verify the label can render without errors
label.frame = CGRect(origin: .zero, size: constrainedSize)
#if os(macOS)
label.layout()
#else
label.layoutSubviews()
#endif
XCTAssertNotNil(label.displayList, "Display list should be created")
XCTAssertNil(label.error, "Should have no rendering error")
// Verify content is not truncated - should wrap to multiple lines
XCTAssertGreaterThan(constrainedSize.height, 30, "Should wrap to multiple lines (not truncate)")
// Check that we have multiple display elements (wrapped content)
if let displayList = label.displayList {
print("Display has \(displayList.subDisplays.count) subdisplays")
XCTAssertGreaterThan(displayList.subDisplays.count, 1, "Should have multiple display elements from wrapping")
}
}
func testNumberProtection_FrenchDecimal() {
let label = MTMathUILabel()
// French decimal number should NOT be broken