@@ -183,6 +183,11 @@ public LineInfo(LineInfo info) {
183
183
}
184
184
}
185
185
}
186
+
187
+ private record LineDrawInfo (int index , TextLayout layout , String text , int offset , int height ) {
188
+
189
+ }
190
+
186
191
static int cap (TextLayout layout , int offset ) {
187
192
if (layout == null ) return offset ;
188
193
return Math .min (layout .getText ().length () -1 , Math .max (0 , offset ));
@@ -452,32 +457,63 @@ void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lin
452
457
layout .draw (gc , x , paintY );
453
458
layout .dispose ();
454
459
}
455
- int drawLine (int lineIndex , int paintX , int paintY , GC gc , Color widgetBackground , Color widgetForeground ) {
460
+
461
+ /**
462
+ * Caches draw-related info that may be expensive to calculate twice when
463
+ * drawing first background and then foreground.
464
+ */
465
+ private LineDrawInfo makeLineDrawInfo (int lineIndex ) {
456
466
TextLayout layout = getTextLayout (lineIndex );
457
- String line = content .getLine (lineIndex );
458
- int lineOffset = content .getOffsetAtLine (lineIndex );
459
- int lineLength = line .length ();
467
+ String text = content .getLine (lineIndex );
468
+ int offset = content .getOffsetAtLine (lineIndex );
469
+ int height = layout .getBounds ().height ;
470
+ return new LineDrawInfo (lineIndex , layout , text , offset , height );
471
+ }
472
+
473
+ int drawLines (int startLine , int endLine , int begX , int begY , int endY , GC gc , Color widgetBackground , Color widgetForeground ) {
474
+ final boolean drawBackBeforeFore = false ;
475
+
476
+ if (drawBackBeforeFore ) {
477
+ return 0 ;
478
+ }
479
+
480
+ int y = begY ;
481
+ for (int iLine = startLine ; y < endY && iLine < endLine ; iLine ++) {
482
+ LineDrawInfo lineInfo = makeLineDrawInfo (iLine );
483
+ drawLineBackground (lineInfo , y , gc , widgetBackground );
484
+ drawLineForeground (lineInfo , begX , y , gc , widgetForeground );
485
+ disposeTextLayout (lineInfo .layout );
486
+ y += lineInfo .height ;
487
+ }
488
+ return y - begY ;
489
+ }
490
+
491
+ private void drawLineBackground (LineDrawInfo lineInfo , int paintY , GC gc , Color widgetBackground ) {
460
492
Rectangle client = styledText .getClientArea ();
461
- Color lineBackground = getLineBackground (lineIndex , null );
462
- StyledTextEvent event = styledText .getLineBackgroundData (lineOffset , line );
493
+ Color lineBackground = getLineBackground (lineInfo . index , null );
494
+ StyledTextEvent event = styledText .getLineBackgroundData (lineInfo . offset , lineInfo . text );
463
495
if (event != null && event .lineBackground != null ) lineBackground = event .lineBackground ;
464
- int height = layout .getBounds (). height ;
465
- int verticalIndent = layout . getVerticalIndent ();
496
+ int verticalIndent = lineInfo . layout .getVerticalIndent () ;
497
+
466
498
if (lineBackground != null ) {
467
499
if (verticalIndent > 0 ) {
468
500
gc .setBackground (widgetBackground );
469
501
gc .fillRectangle (client .x , paintY , client .width , verticalIndent );
470
502
}
471
503
gc .setBackground (lineBackground );
472
- gc .fillRectangle (client .x , paintY + verticalIndent , client .width , height - verticalIndent );
504
+ gc .fillRectangle (client .x , paintY + verticalIndent , client .width , lineInfo . height - verticalIndent );
473
505
} else {
474
506
gc .setBackground (widgetBackground );
475
- styledText .drawBackground (gc , client .x , paintY , client .width , height );
507
+ styledText .drawBackground (gc , client .x , paintY , client .width , lineInfo . height );
476
508
}
509
+ }
510
+
511
+ private void drawLineForeground (LineDrawInfo lineInfo , int paintX , int paintY , GC gc , Color widgetForeground ) {
512
+ int lineLength = lineInfo .text .length ();
477
513
gc .setForeground (widgetForeground );
478
- Point [] selection = intersectingRelativeNonEmptySelections (lineOffset , lineOffset + lineLength );
514
+ Point [] selection = intersectingRelativeNonEmptySelections (lineInfo . offset , lineInfo . offset + lineLength );
479
515
if (styledText .getBlockSelection () || selection .length == 0 ) {
480
- layout .draw (gc , paintX , paintY );
516
+ lineInfo . layout .draw (gc , paintX , paintY );
481
517
} else {
482
518
Color selectionFg = styledText .getSelectionForeground ();
483
519
Color selectionBg = styledText .getSelectionBackground ();
@@ -490,7 +526,7 @@ int drawLine(int lineIndex, int paintX, int paintY, GC gc, Color widgetBackgroun
490
526
flags |= SWT .LAST_LINE_SELECTION ;
491
527
}
492
528
// TODO calling draw multiple times here prints line multiple times, overriding some colors
493
- layout .draw (gc , paintX , paintY , start , end - 1 , selectionFg , selectionBg , flags );
529
+ lineInfo . layout .draw (gc , paintX , paintY , start , end - 1 , selectionFg , selectionBg , flags );
494
530
}
495
531
}
496
532
@@ -499,48 +535,47 @@ int drawLine(int lineIndex, int paintX, int paintY, GC gc, Color widgetBackgroun
499
535
int bulletIndex = -1 ;
500
536
if (bullets != null ) {
501
537
if (bulletsIndices != null ) {
502
- int index = lineIndex - topIndex ;
538
+ int index = lineInfo . index - topIndex ;
503
539
if (0 <= index && index < CACHE_SIZE ) {
504
540
bullet = bullets [index ];
505
541
bulletIndex = bulletsIndices [index ];
506
542
}
507
543
} else {
508
544
for (Bullet b : bullets ) {
509
545
bullet = b ;
510
- bulletIndex = bullet .indexOf (lineIndex );
546
+ bulletIndex = bullet .indexOf (lineInfo . index );
511
547
if (bulletIndex != -1 ) break ;
512
548
}
513
549
}
514
550
}
515
551
if (bulletIndex != -1 && bullet != null ) {
516
- FontMetrics metrics = layout .getLineMetrics (0 );
552
+ FontMetrics metrics = lineInfo . layout .getLineMetrics (0 );
517
553
int lineAscent = metrics .getAscent () + metrics .getLeading ();
518
554
if (bullet .type == ST .BULLET_CUSTOM ) {
519
- bullet .style .start = lineOffset ;
555
+ bullet .style .start = lineInfo . offset ;
520
556
styledText .paintObject (gc , paintX , paintY , lineAscent , metrics .getDescent (), bullet .style , bullet , bulletIndex );
521
557
} else {
522
558
drawBullet (bullet , gc , paintX , paintY , bulletIndex , lineAscent , metrics .getDescent ());
523
559
}
524
560
}
525
- TextStyle [] styles = layout .getStyles ();
561
+ TextStyle [] styles = lineInfo . layout .getStyles ();
526
562
int [] ranges = null ;
527
563
for (int i = 0 ; i < styles .length ; i ++) {
528
564
if (styles [i ].metrics != null ) {
529
- if (ranges == null ) ranges = layout .getRanges ();
565
+ if (ranges == null ) ranges = lineInfo . layout .getRanges ();
530
566
int start = ranges [i << 1 ];
531
567
int length = ranges [(i << 1 ) + 1 ] - start + 1 ;
532
- Point point = layout .getLocation (start , false );
533
- FontMetrics metrics = layout .getLineMetrics (layout .getLineIndex (start ));
568
+ Point point = lineInfo . layout .getLocation (start , false );
569
+ FontMetrics metrics = lineInfo . layout .getLineMetrics (lineInfo . layout .getLineIndex (start ));
534
570
StyleRange style = (StyleRange )((StyleRange )styles [i ]).clone ();
535
- style .start = start + lineOffset ;
571
+ style .start = start + lineInfo . offset ;
536
572
style .length = length ;
537
573
int lineAscent = metrics .getAscent () + metrics .getLeading ();
538
574
styledText .paintObject (gc , point .x + paintX , point .y + paintY , lineAscent , metrics .getDescent (), style , null , 0 );
539
575
}
540
576
}
541
- disposeTextLayout (layout );
542
- return height ;
543
577
}
578
+
544
579
private Point [] intersectingRelativeNonEmptySelections (int fromOffset , int toOffset ) {
545
580
int [] selectionRanges = styledText .getSelectionRanges ();
546
581
int lineLength = toOffset - fromOffset ;
0 commit comments