int (@NotNull Graphics g, final CharSequence text, int start, final int end, @NotNull Point position, @NotNull Rectangle clip, Color effectColor, EffectType effectType, @JdkConstants.FontStyle int fontType, Color fontColor, int startDrawingOffset, WhitespacePaintingStrategy context) { if (start >= end && getSoftWrapModel().getSoftWrap(start) == null) { return position.x; } // Given 'end' offset is exclusive though SoftWrapModel.getSoftWrapsForRange() uses inclusive end offset. // Hence, we decrement it if necessary. Please note that we don't do that if start is equal to end. That is the case, // for example, for soft-wrapped collapsed fold region - we need to draw soft wrap before it. int softWrapRetrievalEndOffset = end; if (start < end) { softWrapRetrievalEndOffset--; } outer: for (SoftWrap softWrap : getSoftWrapModel().getSoftWrapsForRange(start, softWrapRetrievalEndOffset)) { char[] softWrapChars = softWrap.getChars(); CharArrayCharSequence softWrapSeq = new CharArrayCharSequence(softWrapChars); if (softWrap.getStart() == startDrawingOffset) { // If we are here that means that we are located on soft wrap-introduced visual line just after soft wrap. Hence, we need // to draw soft wrap indent if any and 'after soft wrap' sign. int i = CharArrayUtil.lastIndexOf(softWrapChars, '\n', 0, softWrapChars.length); if (i < softWrapChars.length - 1) { position.x = 0; // Soft wrap starts new visual line position.x = drawString( g, softWrapSeq, i + 1, softWrapChars.length, position, clip, null, null, fontType, fontColor, context ); } position.x += mySoftWrapModel.paint(g, SoftWrapDrawingType.AFTER_SOFT_WRAP, position.x, position.y, getLineHeight()); continue; } // Draw token text before the wrap. if (softWrap.getStart() > start) { position.x = drawString( g, text, start, softWrap.getStart(), position, clip, null, null, fontType, fontColor, context ); } start = softWrap.getStart(); // We don't draw every soft wrap symbol one-by-one but whole visual line. Current variable holds index that points // to the first soft wrap symbol that is not drawn yet. int softWrapSegmentStartIndex = 0; for (int i = 0; i < softWrapChars.length; i++) { // Delay soft wraps symbols drawing until EOL is found. if (softWrapChars[i] != '\n') { continue; } // Draw soft wrap symbols on current visual line if any. if (i - softWrapSegmentStartIndex > 0) { drawString( g, softWrapSeq, softWrapSegmentStartIndex, i, position, clip, null, null, fontType, fontColor, context ); } mySoftWrapModel.paint(g, SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED, position.x, position.y, getLineHeight()); // Reset 'x' coordinate because of new line start. position.x = 0; // Stop the processing if we drew the whole clip. if (position.y > clip.y + clip.height) { break outer; } position.y += getLineHeight(); softWrapSegmentStartIndex = i + 1; } // Draw remaining soft wrap symbols from its last line if any. if (softWrapSegmentStartIndex < softWrapChars.length) { position.x += drawString( g, softWrapSeq, softWrapSegmentStartIndex, softWrapChars.length, position, clip, null, null, fontType, fontColor, context ); } position.x += mySoftWrapModel.paint(g, SoftWrapDrawingType.AFTER_SOFT_WRAP, position.x, position.y, getLineHeight()); } return position.x = drawString(g, text, start, end, position, clip, effectColor, effectType, fontType, fontColor, context); }