@NotNull
  VisualPosition logicalToVisualPosition(@NotNull LogicalPosition pos, boolean beforeSoftWrap) {
    int line = pos.line;
    int column = pos.column;
    int logicalLineCount = Math.max(1, myDocument.getLineCount());
    if (line >= logicalLineCount) {
      return new VisualPosition(line - logicalLineCount + myView.getEditor().getVisibleLineCount(), column, pos.leansForward);
    }
    int offset = logicalPositionToOffset(pos);
    int visualLine = offsetToVisualLine(offset, beforeSoftWrap);
    int maxVisualColumn = 0;
    int maxLogicalColumn = 0;
    int endLogicalLine = line;
    for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, beforeSoftWrap)) {
      if (!pos.leansForward && offset == fragment.getVisualLineStartOffset()) {
        return new VisualPosition(visualLine, fragment.getStartVisualColumn());
      }
      endLogicalLine = fragment.getEndLogicalLine();
      maxVisualColumn = fragment.getEndVisualColumn();
      FoldRegion foldRegion = fragment.getCurrentFoldRegion();
      if (foldRegion != null) {
        if (foldRegion instanceof CustomFoldRegion) {
          return new VisualPosition(visualLine, 0);
        }
        int startLogicalLine = fragment.getStartLogicalLine();
        int startLogicalColumn = fragment.getStartLogicalColumn();
        int endLogicalColumn = fragment.getEndLogicalColumn();
        if ((line > startLogicalLine || line == startLogicalLine && (column > startLogicalColumn ||
                                                                     column == startLogicalColumn && pos.leansForward)) &&
            (line < endLogicalLine || line == endLogicalLine && column < endLogicalColumn)) {
          return new VisualPosition(visualLine, fragment.getStartVisualColumn(), true);
        }
        if (line == endLogicalLine && column == endLogicalColumn && !pos.leansForward) {
          return new VisualPosition(visualLine, maxVisualColumn);
        }
        maxLogicalColumn = startLogicalLine == endLogicalLine ? Math.max(maxLogicalColumn, endLogicalColumn) : endLogicalColumn;
      }
      else if (fragment.getCurrentInlay() == null) {
        int minColumn = fragment.getMinLogicalColumn();
        int maxColumn = fragment.getMaxLogicalColumn();
        if (line == fragment.getStartLogicalLine() &&
            (column > minColumn && column < maxColumn ||
             column == minColumn && pos.leansForward ||
             column == maxColumn && !pos.leansForward)) {
          return new VisualPosition(visualLine, fragment.logicalToVisualColumn(column), fragment.isRtl() ^ pos.leansForward);
        }
        maxLogicalColumn = Math.max(maxLogicalColumn, maxColumn);
      }
    }
    int resultColumn = maxVisualColumn + logToVisWithInlays(endLogicalLine, column - maxLogicalColumn, pos.leansForward);
    if (resultColumn < 0) resultColumn = Integer.MAX_VALUE; // guarding against overflow
    return new VisualPosition(visualLine, resultColumn, pos.leansForward);
  }
@NotNull
  VisualPosition logicalToVisualPosition(@NotNull LogicalPosition pos, boolean beforeSoftWrap)