int getVisualLineWidth( VisualLinesIterator visualLinesIterator, @Nullable Runnable quickEvaluationListener) { assert !visualLinesIterator.atEnd(); int visualLine = visualLinesIterator.getVisualLine(); FoldRegion[] topLevelRegions = myEditor.getFoldingModel().fetchTopLevel(); if (quickEvaluationListener != null && (topLevelRegions == null || topLevelRegions.length == 0) && myEditor.getSoftWrapModel().getRegisteredSoftWraps().isEmpty() && !myView.getTextLayoutCache().hasCachedLayoutFor(visualLine)) { // fast path - speeds up editor opening quickEvaluationListener.run(); return myView .getLogicalPositionCache() .offsetToLogicalColumn( visualLine, myDocument.getLineEndOffset(visualLine) - myDocument.getLineStartOffset(visualLine)) * myView.getMaxCharWidth(); } float x = 0; int maxOffset = visualLinesIterator.getVisualLineStartOffset(); for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, visualLinesIterator, quickEvaluationListener)) { x = fragment.getEndX(); maxOffset = Math.max(maxOffset, fragment.getMaxOffset()); } if (myEditor.getSoftWrapModel().getSoftWrap(maxOffset) != null) { x += myEditor .getSoftWrapModel() .getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); } return (int) x; }
private void paintLineFragments( Graphics2D g, Rectangle clip, int visualLine, int y, LineFragmentPainter painter) { float x = visualLine == 0 ? myView.getPrefixTextWidthInPixels() : 0; int offset = myView.visualPositionToOffset(new VisualPosition(visualLine, 0)); int visualLineEndOffset = myView.visualPositionToOffset(new VisualPosition(visualLine, Integer.MAX_VALUE, true)); IterationState it = null; int prevEndOffset = -1; boolean firstFragment = true; int maxColumn = 0; for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, false)) { int fragmentStartOffset = fragment.getStartOffset(); int start = fragmentStartOffset; int end = fragment.getEndOffset(); x = fragment.getStartX(); if (firstFragment) { firstFragment = false; SoftWrap softWrap = myEditor.getSoftWrapModel().getSoftWrap(offset); if (softWrap != null) { prevEndOffset = offset; it = new IterationState( myEditor, offset == 0 ? 0 : offset - 1, visualLineEndOffset, true, false, false, false); if (it.getEndOffset() <= offset) { it.advance(); } painter.paintBeforeLineStart( g, it.getStartOffset() == offset ? it.getBeforeLineStartBackgroundAttributes() : it.getMergedAttributes(), fragment.getStartVisualColumn(), fragment.getStartX(), y); } } FoldRegion foldRegion = fragment.getCurrentFoldRegion(); if (foldRegion == null) { if (start != prevEndOffset) { it = new IterationState( myEditor, start, fragment.isRtl() ? offset : visualLineEndOffset, true, false, false, fragment.isRtl()); } prevEndOffset = end; assert it != null; 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); painter.paint( g, fragment, fragment.isRtl() ? fragmentStartOffset - start : start - fragmentStartOffset, fragment.isRtl() ? fragmentStartOffset - curEnd : curEnd - fragmentStartOffset, attributes, x, xNew, y); x = xNew; start = curEnd; } } else { float xNew = fragment.getEndX(); painter.paint( g, fragment, 0, fragment.getEndVisualColumn() - fragment.getStartVisualColumn(), getFoldRegionAttributes(foldRegion), x, xNew, y); x = xNew; prevEndOffset = -1; it = null; } maxColumn = fragment.getEndVisualColumn(); } if (it == null || it.getEndOffset() != visualLineEndOffset) { it = new IterationState( myEditor, visualLineEndOffset == offset ? visualLineEndOffset : visualLineEndOffset - 1, visualLineEndOffset, true, false, false, false); } if (!it.atEnd()) { it.advance(); } assert it.atEnd(); painter.paintAfterLineEnd(g, clip, it, maxColumn, x, y); }