3535import android .graphics .Color ;
3636import android .graphics .DashPathEffect ;
3737import android .graphics .Path ;
38+ import android .graphics .PorterDuff ;
3839import android .graphics .Rect ;
3940import android .graphics .RectF ;
4041import android .graphics .RenderNode ;
5556import java .util .List ;
5657import java .util .Objects ;
5758
59+ import io .github .rosemoe .sora .R ;
5860import io .github .rosemoe .sora .annotations .UnsupportedUserUsage ;
5961import io .github .rosemoe .sora .graphics .BubbleHelper ;
6062import io .github .rosemoe .sora .graphics .BufferedDrawPoints ;
@@ -503,7 +505,7 @@ protected void drawSingleTextLine(Canvas canvas, int line, float offsetX, float
503505 int nonPrintableFlags = editor .getNonPrintablePaintingFlags ();
504506 // Draw hard wrap
505507 if ((nonPrintableFlags & CodeEditor .FLAG_DRAW_LINE_SEPARATOR ) != 0 ) {
506- drawMiniGraph (canvas , offsetX , -1 , "↵" );
508+ drawMiniGraph (canvas , offsetX , -1 , editor . getContext (). getDrawable ( R . drawable . line_break ) );
507509 }
508510 paintGeneral .setTextSkewX (0 );
509511 paintGeneral .setFakeBoldText (false );
@@ -1146,6 +1148,7 @@ protected void drawRows(Canvas canvas, float offset, LongArrayList postDrawLineN
11461148 int leadingWhitespaceEnd = 0 ;
11471149 int trailingWhitespaceStart = 0 ;
11481150 float circleRadius = 0f ;
1151+ float miniGraphWidth = editor .isWordwrap () && (editor .getNonPrintablePaintingFlags () & CodeEditor .FLAG_DRAW_SOFT_WRAP ) != 0 ? getMiniGraphWidth () : 0f ;
11491152 var composingPosition = editor .inputConnection .composingText .isComposing () && editor .inputConnection .composingText .startIndex >= 0 && editor .inputConnection .composingText .startIndex < content .length () ? content .getIndexer ().getCharPosition (editor .inputConnection .composingText .startIndex ) : null ;
11501153 var composingLength = editor .inputConnection .composingText .endIndex - editor .inputConnection .composingText .startIndex ;
11511154 var draggingSelection = editor .getEventHandler ().draggingSelection ;
@@ -1236,6 +1239,7 @@ protected void drawRows(Canvas canvas, float offset, LongArrayList postDrawLineN
12361239 // Get visible region on the line
12371240 long charPos = findDesiredVisibleChar (offset3 , line , rowInf .startColumn , rowInf .endColumn );
12381241 float paintingOffset = CharPosDesc .getPixelWidthOrOffset (charPos ) - offset2 ;
1242+ paintingOffset += miniGraphWidth ;
12391243
12401244 // Draw matched text background
12411245 if (matchedPositions .size () > 0 ) {
@@ -1336,6 +1340,12 @@ protected void drawRows(Canvas canvas, float offset, LongArrayList postDrawLineN
13361340 long charPos = findDesiredVisibleChar (offset3 , line , rowInf .startColumn , rowInf .endColumn );
13371341 int firstVisibleChar = CharPosDesc .getTextOffset (charPos );
13381342 float paintingOffset = CharPosDesc .getPixelWidthOrOffset (charPos ) - offset2 ;
1343+ if (!rowInf .isLeadingRow ) {
1344+ if ((editor .getNonPrintablePaintingFlags () & CodeEditor .FLAG_DRAW_SOFT_WRAP ) != 0 ) {
1345+ drawMiniGraph (canvas , offset , row , editor .getContext ().getDrawable (R .drawable .softwrap_left ));
1346+ }
1347+ paintingOffset += miniGraphWidth ;
1348+ }
13391349 charPos = findDesiredVisibleChar (editor .getWidth () - paintingOffset , line , firstVisibleChar , rowInf .endColumn , rowInf .startColumn , true );
13401350 int lastVisibleChar = CharPosDesc .getTextOffset (charPos );
13411351
@@ -1462,7 +1472,9 @@ protected void drawRows(Canvas canvas, float offset, LongArrayList postDrawLineN
14621472
14631473 // Draw hard wrap
14641474 if (lastVisibleChar == columnCount && (nonPrintableFlags & CodeEditor .FLAG_DRAW_LINE_SEPARATOR ) != 0 ) {
1465- drawMiniGraph (canvas , paintingOffset , row , "↵" );
1475+ drawMiniGraph (canvas , paintingOffset , row , editor .getContext ().getDrawable (R .drawable .line_break ));
1476+ } else if (lastVisibleChar != columnCount && editor .isWordwrap () && (nonPrintableFlags & CodeEditor .FLAG_DRAW_SOFT_WRAP ) != 0 ) {
1477+ drawMiniGraph (canvas , paintingOffset , row , editor .getContext ().getDrawable (R .drawable .softwrap_right ));
14661478 }
14671479 } else {
14681480 paintingOffset = offset + editor .getRenderContext ().getRenderNodeHolder ().drawLineHardwareAccelerated (canvas , line , offset , editor .getRowTop (line ) - editor .getOffsetY ()) - editor .getDpUnit () * 20 ;
@@ -1726,14 +1738,36 @@ protected void drawWhitespacesOnCanvas(Canvas canvas, float offset, int line, fl
17261738 }
17271739 }
17281740
1741+ public float getMiniGraphWidth () {
1742+ float height = editor .getRowHeightOfText () * editor .getProps ().miniMarkerSizeFactor ;
1743+ var graph = editor .getContext ().getDrawable (R .drawable .line_break );
1744+ if (graph == null ) {
1745+ return 0 ;
1746+ }
1747+ int w = graph .getIntrinsicWidth (), h = graph .getIntrinsicHeight ();
1748+ if (w <= 0 || h <= 0 || height <= 0 ) {
1749+ return 0f ;
1750+ }
1751+ return height * ((float ) w / h );
1752+ }
1753+
17291754 /**
17301755 * Draw small characters as graph
17311756 */
1732- protected void drawMiniGraph (Canvas canvas , float offset , int row , String graph ) {
1733- // Draw
1734- paintGraph .setColor (editor .getColorScheme ().getColor (EditorColorScheme .NON_PRINTABLE_CHAR ));
1757+ protected void drawMiniGraph (Canvas canvas , float offset , int row , Drawable graph ) {
17351758 float baseline = row == -1 ? (editor .getRowBottom (0 ) - metricsGraph .descent ) : (editor .getRowBottom (row ) - editor .getOffsetY () - metricsGraph .descent );
1736- canvas .drawText (graph , 0 , graph .length (), offset , baseline , paintGraph );
1759+ float height = editor .getRowHeightOfText () * editor .getProps ().miniMarkerSizeFactor ;
1760+ if (height <= 0 || graph == null ) {
1761+ return ;
1762+ }
1763+ int w = graph .getIntrinsicWidth (), h = graph .getIntrinsicHeight ();
1764+ if (w <= 0 || h <= 0 ) {
1765+ return ;
1766+ }
1767+ float width = height * ((float ) w / h );
1768+ graph .setColorFilter (editor .getColorScheme ().getColor (EditorColorScheme .NON_PRINTABLE_CHAR ), PorterDuff .Mode .SRC_ATOP );
1769+ graph .setBounds ((int ) offset , (int ) (baseline - height ), (int ) (offset + width ), (int ) baseline );
1770+ graph .draw (canvas );
17371771 }
17381772
17391773 protected int getRowTopForBackground (int row ) {
@@ -2445,6 +2479,9 @@ protected List<TextDisplayPosition> getTextRegionPositions(int start, int end) {
24452479 position .row = i ;
24462480 var line = content .getLine (row .lineIndex );
24472481 position .left = measureText (line , row .lineIndex , row .startColumn , startOnRow - row .startColumn );
2482+ if (!row .isLeadingRow && (editor .getNonPrintablePaintingFlags () & CodeEditor .FLAG_DRAW_SOFT_WRAP ) != 0 ) {
2483+ position .left += getMiniGraphWidth ();
2484+ }
24482485 position .right = position .left + measureText (line , row .lineIndex , startOnRow , endOnRow - startOnRow );
24492486 position .startColumn = startOnRow ;
24502487 position .endColumn = endOnRow ;
@@ -2474,10 +2511,15 @@ protected void patchTextRegions(Canvas canvas, float textOffset, List<TextDispla
24742511 }
24752512 var startCol = position .startColumn ;
24762513 var endCol = position .endColumn ;
2514+ var rowRegion = editor .getLayout ().getRowAt (position .row );
2515+ var limitCol = rowRegion .endColumn ;
24772516 var lineText = getLine (line );
24782517 var column = lineText .length ();
24792518 canvas .save ();
24802519 var horizontalOffset = textOffset ;
2520+ if ((editor .getNonPrintablePaintingFlags () & CodeEditor .FLAG_DRAW_SOFT_WRAP ) != 0 && !rowRegion .isLeadingRow ) {
2521+ horizontalOffset += getMiniGraphWidth ();
2522+ }
24812523 boolean first = true ;
24822524 // Find spans to draw
24832525 Span nextSpan = null ;
@@ -2493,6 +2535,7 @@ protected void patchTextRegions(Canvas canvas, float textOffset, List<TextDispla
24932535 var spanStart = Math .max (span .getColumn (), position .rowStart );
24942536 var sharedStart = Math .max (startCol , spanStart );
24952537 var spanEnd = nextSpan == null ? column : nextSpan .getColumn ();
2538+ spanEnd = Math .min (limitCol , spanEnd );
24962539 spanEnd = Math .min (column , spanEnd ); // Spans can be corrupted
24972540 if (spanEnd <= position .startColumn ) {
24982541 continue ;
@@ -2705,24 +2748,6 @@ public long findDesiredVisibleChar(float target, int lineIndex, int start, int e
27052748 return result ;
27062749 }
27072750
2708- /**
2709- * Find first visible character
2710- *
2711- * @return Character position description, {@link CharPosDesc}
2712- */
2713- @ UnsupportedUserUsage
2714- public long findFirstVisibleCharForWordwrap (float target , int lineIndex , int start , int end , int contextStart , Paint paint ) {
2715- if (start >= end ) {
2716- return CharPosDesc .make (end , 0 );
2717- }
2718- var gtr = GraphicTextRow .obtain (basicDisplayMode );
2719- gtr .set (content , lineIndex , contextStart , end , sSpansForWordwrap , paint , editor .getRenderContext ());
2720- gtr .disableCache ();
2721- var res = gtr .findOffsetByAdvance (start , target );
2722- gtr .recycle ();
2723- return res ;
2724- }
2725-
27262751 @ UnsupportedUserUsage
27272752 public float [] computeLineAdvances (int line , Paint paint ) {
27282753 var gtr = GraphicTextRow .obtain (basicDisplayMode );
0 commit comments