@NotNull
  Point2D offsetToXY(int offset, boolean leanTowardsLargerOffsets, boolean beforeSoftWrap) {
    offset = Math.max(0, Math.min(myDocument.getTextLength(), offset));
    offset = DocumentUtil.alignToCodePointBoundary(myDocument, offset);
    int logicalLine = myDocument.getLineNumber(offset);
    int visualLine = offsetToVisualLine(offset, beforeSoftWrap);
    int visualLineStartOffset = visualLineToOffset(visualLine);
    int y = visualLineToY(visualLine);
    float x = getStartX(logicalLine);
    boolean firstFragment = true;
    for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, offset, beforeSoftWrap, true)) {
      if (firstFragment && offset == visualLineStartOffset && !leanTowardsLargerOffsets ||
          fragment.getCurrentFoldRegion() instanceof CustomFoldRegion) {
        x = fragment.getStartX();
        break;
      }
      firstFragment = false;
      int minOffset = fragment.getMinOffset();
      int maxOffset = fragment.getMaxOffset();
      if (fragment.getCurrentInlay() == null &&
          (offset > minOffset && offset < maxOffset ||
          offset == minOffset && leanTowardsLargerOffsets ||
          offset == maxOffset && !leanTowardsLargerOffsets)) {
        x = fragment.offsetToX(offset);
        break;
      }
      else {
        x = fragment.getEndX();
      }
    }
    return new Point2D.Double(x, y);
  }
@NotNull
  Point2D offsetToXY(int offset, boolean leanTowardsLargerOffsets, boolean beforeSoftWrap)