private void paintCaret() {
      if (myEditor.isPurePaintingMode()) return;
      if (myEditor.isStickyLinePainting()) return; // suppress caret painting on sticky lines panel
      EditorImpl.CaretRectangle[] locations = myEditor.getCaretLocations(true);
      if (locations == null) return;

      Graphics2D g = IdeBackgroundUtil.getOriginalGraphics(myGraphics);
      int caretHeight = myView.getCaretHeight();
      EditorSettings settings = myEditor.getSettings();
      int topOverhang = settings.isFullLineHeightCursor() ? 0 : myView.getTopOverhang();
      Color caretColor = myEditor.getColorsScheme().getColor(EditorColors.CARET_COLOR);
      if (caretColor == null) caretColor = new JBColor(CARET_DARK, CARET_LIGHT);
      int minX = myInsets.left;
      for (EditorImpl.CaretRectangle location : locations) {
        float x = (float)location.myPoint.getX();
        int y = (int)location.myPoint.getY() - topOverhang + myYShift;
        Caret caret = location.myCaret;
        CaretVisualAttributes attr = caret == null ? CaretVisualAttributes.getDefault() : caret.getVisualAttributes();
        g.setColor(attr.getColor() != null ? attr.getColor() : caretColor);
        boolean isRtl = location.myIsRtl;
        float width = location.myWidth;
        float startX = Math.max(minX, isRtl ? x - width : x);

        CaretVisualAttributes.Shape shape = attr.getShape();
        switch (shape) {
          case DEFAULT -> {
            if (myEditor.isInsertMode() != settings.isBlockCursor()) {
              int lineWidth = JBUIScale.scale(attr.getWidth(settings.getLineCursorWidth()));
              // fully cover extra character's pixel which can appear due to antialiasing
              // see IDEA-148843 for more details
              if (x > minX && lineWidth > 1) x -= 1 / JBUIScale.sysScale(g);
              paintCaretBar(g, caret, x, y, lineWidth, caretHeight, isRtl);
            }
            else {
              paintCaretBlock(g, startX, y, width, caretHeight);
              paintCaretText(g, caret, caretColor, startX, y, topOverhang, isRtl);
            }
          }
          case BLOCK -> {
            paintCaretBlock(g, startX, y, width, caretHeight);
            paintCaretText(g, caret, caretColor, startX, y, topOverhang, isRtl);
          }
          case BAR -> {
            // Don't draw if thickness is zero. This allows a plugin to "hide" carets, e.g. to visually emulate a block selection as a
            // selection rather than as multiple carets with discrete selections
            if (attr.getThickness() > 0) {
              int barWidth = Math.max((int)(width * attr.getThickness()), JBUIScale.scale(settings.getLineCursorWidth()));
              if (!isRtl && x > minX && barWidth > 1 && barWidth < (width / 2)) x -= 1 / JBUIScale.sysScale(g);
              paintCaretBar(g, caret, isRtl ? x - barWidth : x, y, barWidth, caretHeight, isRtl);
              Shape savedClip = g.getClip();
              g.setClip(new Rectangle2D.Float(isRtl ? x - barWidth : x, y, barWidth, caretHeight));
              paintCaretText(g, caret, caretColor, startX, y, topOverhang, isRtl);
              g.setClip(savedClip);
            }
          }
          case UNDERSCORE -> {
            if (attr.getThickness() > 0) {
              int underscoreHeight = Math.max((int)(caretHeight * attr.getThickness()), 1);
              paintCaretUnderscore(g, startX, y + caretHeight - underscoreHeight, width, underscoreHeight);
              Shape oldClip = g.getClip();
              g.setClip(new Rectangle2D.Float(startX, y + caretHeight - underscoreHeight, width, underscoreHeight));
              paintCaretText(g, caret, caretColor, startX, y, topOverhang, isRtl);
              g.setClip(oldClip);
            }
          }
          case BOX -> paintCaretBox(g, startX, y, width, caretHeight);
        }
      }
    }
private void paintCaret()