private boolean paintPlaceholderText(Graphics2D g) {
    CharSequence hintText = myEditor.getPlaceholder();
    EditorComponentImpl editorComponent = myEditor.getContentComponent();
    if (myDocument.getTextLength() > 0
        || hintText == null
        || hintText.length() == 0
        || KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() == editorComponent
            && !myEditor.getShowPlaceholderWhenFocused()) {
      return false;
    }

    hintText =
        SwingUtilities.layoutCompoundLabel(
            g.getFontMetrics(),
            hintText.toString(),
            null,
            0,
            0,
            0,
            0,
            editorComponent.getBounds(),
            new Rectangle(),
            new Rectangle(),
            0);
    g.setColor(myEditor.getFoldingModel().getPlaceholderAttributes().getForegroundColor());
    g.setFont(myEditor.getColorsScheme().getFont(EditorFontType.PLAIN));
    g.drawString(hintText.toString(), 0, myView.getAscent());
    return true;
  }
  private void paintCaret(Graphics2D g_) {
    EditorImpl.CaretRectangle[] locations = myEditor.getCaretLocations(true);
    if (locations == null) return;

    Graphics2D g = IdeBackgroundUtil.getOriginalGraphics(g_);
    int lineHeight = myView.getLineHeight();
    EditorSettings settings = myEditor.getSettings();
    Color caretColor = myEditor.getColorsScheme().getColor(EditorColors.CARET_COLOR);
    if (caretColor == null) caretColor = new JBColor(CARET_DARK, CARET_LIGHT);
    g.setColor(caretColor);
    for (EditorImpl.CaretRectangle location : locations) {
      int x = location.myPoint.x;
      int y = location.myPoint.y;
      Caret caret = location.myCaret;
      boolean isRtl = location.myIsRtl;
      if (myEditor.isInsertMode() != settings.isBlockCursor()) {
        int lineWidth = JBUI.scale(settings.getLineCursorWidth());
        g.fillRect(x, y, lineWidth, lineHeight);
        if (myDocument.getTextLength() > 0
            && caret != null
            && !myView.getLineLayout(caret.getLogicalPosition().line).isLtr()) {
          g.fillPolygon(
              new int[] {
                isRtl ? x + lineWidth : x,
                isRtl ? x + lineWidth - CARET_DIRECTION_MARK_SIZE : x + CARET_DIRECTION_MARK_SIZE,
                isRtl ? x + lineWidth : x
              },
              new int[] {y, y, y + CARET_DIRECTION_MARK_SIZE},
              3);
        }
      } else {
        int width = location.myWidth;
        int startX = Math.max(0, isRtl ? x - width : x);
        g.fillRect(startX, y, width, lineHeight - 1);
        if (myDocument.getTextLength() > 0 && caret != null) {
          int targetVisualColumn = caret.getVisualPosition().column;
          for (VisualLineFragmentsIterator.Fragment fragment :
              VisualLineFragmentsIterator.create(myView, caret.getVisualLineStart(), false)) {
            int startVisualColumn = fragment.getStartVisualColumn();
            int endVisualColumn = fragment.getEndVisualColumn();
            if (startVisualColumn < targetVisualColumn && endVisualColumn > targetVisualColumn
                || startVisualColumn == targetVisualColumn && !isRtl
                || endVisualColumn == targetVisualColumn && isRtl) {
              g.setColor(ColorUtil.isDark(caretColor) ? CARET_LIGHT : CARET_DARK);
              fragment.draw(
                  g,
                  startX,
                  y + myView.getAscent(),
                  targetVisualColumn - startVisualColumn - (isRtl ? 1 : 0),
                  targetVisualColumn - startVisualColumn + (isRtl ? 0 : 1));
              break;
            }
          }
        }
      }
    }
  }
  private void paintComposedTextDecoration(Graphics2D g) {
    TextRange composedTextRange = myEditor.getComposedTextRange();
    if (composedTextRange != null) {
      Point p1 =
          myView.offsetToXY(
              Math.min(composedTextRange.getStartOffset(), myDocument.getTextLength()),
              true,
              false);
      Point p2 =
          myView.offsetToXY(
              Math.min(composedTextRange.getEndOffset(), myDocument.getTextLength()), false, true);

      int y = p1.y + myView.getAscent() + 1;

      g.setStroke(IME_COMPOSED_TEXT_UNDERLINE_STROKE);
      g.setColor(myEditor.getColorsScheme().getDefaultForeground());
      UIUtil.drawLine(g, p1.x, y, p2.x, y);
    }
  }
 private void paintHighlighterAfterEndOfLine(Graphics2D g, RangeHighlighterEx highlighter) {
   if (!highlighter.isAfterEndOfLine()) {
     return;
   }
   int startOffset = highlighter.getStartOffset();
   int lineEndOffset = myDocument.getLineEndOffset(myDocument.getLineNumber(startOffset));
   if (myEditor.getFoldingModel().isOffsetCollapsed(lineEndOffset)) return;
   Point lineEnd = myView.offsetToXY(lineEndOffset, true, false);
   int x = lineEnd.x;
   int y = lineEnd.y;
   TextAttributes attributes = highlighter.getTextAttributes();
   paintBackground(g, attributes, x, y, myView.getPlainSpaceWidth());
   if (attributes != null
       && hasTextEffect(attributes.getEffectColor(), attributes.getEffectType())) {
     paintTextEffect(
         g,
         x,
         x + myView.getPlainSpaceWidth() - 1,
         y + myView.getAscent(),
         attributes.getEffectColor(),
         attributes.getEffectType());
   }
 }
  private void paintTextWithEffects(
      Graphics2D g, Rectangle clip, int startVisualLine, int endVisualLine) {
    final CharSequence text = myDocument.getImmutableCharSequence();
    final EditorImpl.LineWhitespacePaintingStrategy whitespacePaintingStrategy =
        myEditor.new LineWhitespacePaintingStrategy();
    int lineCount = myEditor.getVisibleLineCount();
    for (int visualLine = startVisualLine; visualLine <= endVisualLine; visualLine++) {
      int y = myView.visualLineToY(visualLine) + myView.getAscent();
      LineLayout prefixLayout = myView.getPrefixLayout();
      if (visualLine == 0 && prefixLayout != null) {
        g.setColor(myView.getPrefixAttributes().getForegroundColor());
        paintLineLayoutWithEffect(
            g,
            prefixLayout,
            0,
            y,
            myView.getPrefixAttributes().getEffectColor(),
            myView.getPrefixAttributes().getEffectType());
      }
      if (visualLine >= lineCount) break;

      final int[] currentLogicalLine = new int[] {-1};

      paintLineFragments(
          g,
          clip,
          visualLine,
          y,
          new LineFragmentPainter() {
            @Override
            public void paintBeforeLineStart(
                Graphics2D g, TextAttributes attributes, int columnEnd, float xEnd, int y) {
              SoftWrapModelImpl softWrapModel = myEditor.getSoftWrapModel();
              int symbolWidth =
                  softWrapModel.getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
              softWrapModel.paint(
                  g,
                  SoftWrapDrawingType.AFTER_SOFT_WRAP,
                  (int) xEnd - symbolWidth,
                  y - myView.getAscent(),
                  myView.getLineHeight());
            }

            @Override
            public void paint(
                Graphics2D g,
                VisualLineFragmentsIterator.Fragment fragment,
                int start,
                int end,
                TextAttributes attributes,
                float xStart,
                float xEnd,
                int y) {
              if (attributes != null && attributes.getForegroundColor() != null) {
                g.setColor(attributes.getForegroundColor());
                fragment.draw(g, xStart, y, start, end);
              }
              if (fragment.getCurrentFoldRegion() == null) {
                int logicalLine = fragment.getStartLogicalLine();
                if (logicalLine != currentLogicalLine[0]) {
                  whitespacePaintingStrategy.update(
                      text,
                      myDocument.getLineStartOffset(logicalLine),
                      myDocument.getLineEndOffset(logicalLine));
                  currentLogicalLine[0] = logicalLine;
                }
                paintWhitespace(
                    g, text, xStart, y, start, end, whitespacePaintingStrategy, fragment);
              }
              if (attributes != null
                  && hasTextEffect(attributes.getEffectColor(), attributes.getEffectType())) {
                paintTextEffect(
                    g, xStart, xEnd, y, attributes.getEffectColor(), attributes.getEffectType());
              }
            }

            @Override
            public void paintAfterLineEnd(
                Graphics2D g,
                Rectangle clip,
                IterationState iterationState,
                int columnStart,
                float x,
                int y) {
              int offset = iterationState.getEndOffset();
              SoftWrapModelImpl softWrapModel = myEditor.getSoftWrapModel();
              if (softWrapModel.getSoftWrap(offset) == null) {
                int logicalLine = myDocument.getLineNumber(offset);
                paintLineExtensions(g, logicalLine, x, y);
              } else {
                softWrapModel.paint(
                    g,
                    SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED,
                    (int) x,
                    y - myView.getAscent(),
                    myView.getLineHeight());
              }
            }
          });
    }
  }