void (VisualLinesIterator visLineIterator, int y, LineFragmentPainter painter, MarginWidthConsumer marginWidthConsumer) { int visualLine = visLineIterator.getVisualLine(); float x = myCorrector.startX(visualLine) + (visualLine == 0 ? myView.getPrefixTextWidthInPixels() : 0); int offset = visLineIterator.getVisualLineStartOffset(); int visualLineEndOffset = visLineIterator.getVisualLineEndOffset(); IterationState it = null; int prevEndOffset = -1; boolean firstFragment = true; int maxColumn = 0; int endLogicalLine = visLineIterator.getEndLogicalLine(); boolean marginReached = false; for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, visLineIterator, null, true)) { int fragmentStartOffset = fragment.getStartOffset(); int start = fragmentStartOffset; int end = fragment.getEndOffset(); x = fragment.getStartX(); if (firstFragment) { firstFragment = false; SoftWrap softWrap = myEditor.getSoftWrapModel().getSoftWrap(offset); boolean hasSoftWrap = softWrap != null; if (hasSoftWrap || myEditor.isRightAligned()) { prevEndOffset = offset; it = new IterationState(myEditor, offset == 0 ? 0 : DocumentUtil.getPreviousCodePointOffset(myDocument, offset), visualLineEndOffset, myCaretData, false, false, false, false); if (it.getEndOffset() <= offset) { it.advance(); } if (x >= myClip.getMinX()) { TextAttributes attributes = it.getStartOffset() == offset ? it.getBeforeLineStartBackgroundAttributes() : it.getMergedAttributes(); painter.paintBeforeLineStart(attributes, hasSoftWrap, fragment.getStartVisualColumn(), x, y); } } } FoldRegion foldRegion = fragment.getCurrentFoldRegion(); if (foldRegion == null) { if (start != prevEndOffset) { it = new IterationState(myEditor, start, fragment.isRtl() ? offset : visualLineEndOffset, myCaretData, false, false, false, fragment.isRtl()); } prevEndOffset = end; assert it != null; if (start == end) { // special case of inlays if (start == it.getEndOffset() && !it.atEnd()) { it.advance(); } TextAttributes attributes = it.getStartOffset() == start ? it.getBreakAttributes() : it.getMergedAttributes(); float xNew = fragment.getEndX(); if (xNew >= myClip.getMinX()) { painter.paint(fragment, 0, 0, attributes, x, xNew, y); } x = xNew; } else { while (fragment.isRtl() ? start > end : start < end) { if (fragment.isRtl() ? it.getEndOffset() >= start : it.getEndOffset() <= start) { assert !it.atEnd(); it.advance(); } TextAttributes attributes = it.getMergedAttributes(); int curEnd = fragment.isRtl() ? Math.max(it.getEndOffset(), end) : Math.min(it.getEndOffset(), end); float xNew = fragment.offsetToX(x, start, curEnd); if (xNew >= myClip.getMinX()) { painter.paint(fragment, fragment.isRtl() ? fragmentStartOffset - start : start - fragmentStartOffset, fragment.isRtl() ? fragmentStartOffset - curEnd : curEnd - fragmentStartOffset, attributes, x, xNew, y); } x = xNew; start = curEnd; } if (marginWidthConsumer != null && fragment.getEndLogicalLine() == endLogicalLine && fragment.getStartLogicalColumn() <= myMarginColumns && fragment.getEndLogicalColumn() > myMarginColumns) { marginWidthConsumer.process(fragment.visualColumnToX(fragment.logicalToVisualColumn(myMarginColumns))); marginReached = true; } } } else if (foldRegion instanceof CustomFoldRegion) { break; // real painting happens in paintAfterLineEnd } else { float xNew = fragment.getEndX(); if (xNew >= myClip.getMinX()) { painter.paint(fragment, 0, fragment.getVisualLength(), getFoldRegionAttributes(foldRegion), x, xNew, y); } x = xNew; prevEndOffset = -1; it = null; } if (x > myClip.getMaxX()) return; maxColumn = fragment.getEndVisualColumn(); } if (firstFragment && myEditor.isRightAligned()) { it = new IterationState(myEditor, offset, visualLineEndOffset, myCaretData, false, false, false, false); if (it.getEndOffset() <= offset) { it.advance(); } painter.paintBeforeLineStart(it.getBeforeLineStartBackgroundAttributes(), false, maxColumn, x, y); } if (it == null || it.getEndOffset() != visualLineEndOffset) { it = new IterationState(myEditor, visualLineEndOffset == offset ? visualLineEndOffset : DocumentUtil.getPreviousCodePointOffset(myDocument, visualLineEndOffset), visualLineEndOffset, IterationState.CaretData.copyOf(myCaretData, visLineIterator.isCustomFoldRegionLine() && !Registry.is("highlight.caret.line.at.custom.fold")), false, false, false, false); } if (!it.atEnd()) { it.advance(); } assert it.atEnd(); painter.paintAfterLineEnd(it, maxColumn, x, y); if (marginWidthConsumer != null && !marginReached && (visualLine == myEditor.getCaretModel().getVisualPosition().line || x > myMarginColumns * myView.getPlainSpaceWidth())) { int endLogicalColumn = myView.offsetToLogicalPosition(visualLineEndOffset).column; if (endLogicalColumn <= myMarginColumns) { marginWidthConsumer.process(x + (myMarginColumns - endLogicalColumn) * myView.getPlainSpaceWidth()); } } }