private void paintImmediately(final Graphics2D g, final int offset, final char c2) {
    final EditorImpl editor = myEditor;
    final Document document = editor.getDocument();
    final LexerEditorHighlighter highlighter = (LexerEditorHighlighter)myEditor.getHighlighter();

    final EditorSettings settings = editor.getSettings();
    final boolean isBlockCursor = editor.isInsertMode() == settings.isBlockCursor();
    final int lineHeight = editor.getLineHeight();
    final int caretHeight = editor.myView.getCaretHeight();
    final int ascent = editor.getAscent();
    final int topOverhang = settings.isFullLineHeightCursor() ? 0 : editor.myView.getTopOverhang();

    final char c1 = offset == 0 ? ' ' : document.getCharsSequence().charAt(offset - 1);

    final List<TextAttributes> attributes;
    try {
      attributes = highlighter.getAttributesForPreviousAndTypedChars(document, offset, c2);
    }
    catch (Exception e) {
      throw new RuntimeException("Error calculating attributes, highlighter: " + highlighter + ", offset: " + offset + ", document length" +
                                 document.getTextLength() + ", highlighter's last offset:" + highlighter.getSegments().getLastValidOffset(),
                                 e);
    }
    updateAttributes(editor, offset, attributes);

    final TextAttributes attributes1 = attributes.get(0);
    final TextAttributes attributes2 = attributes.get(1);

    if (!(canRender(attributes1) && canRender(attributes2))) {
      return;
    }

    FontLayoutService fontLayoutService = FontLayoutService.getInstance();
    final float width1 = fontLayoutService.charWidth2D(editor.getFontMetrics(attributes1.getFontType()), c1);
    final float width2 = fontLayoutService.charWidth2D(editor.getFontMetrics(attributes2.getFontType()), c2);

    final Font font1 = EditorUtil.fontForChar(c1, attributes1.getFontType(), editor).getFont();
    final Font font2 = EditorUtil.fontForChar(c1, attributes2.getFontType(), editor).getFont();

    final Point2D p2 = editor.offsetToPoint2D(offset);
    float p2x = (float)p2.getX();
    int p2y = (int)p2.getY();

    Caret caret = editor.getCaretModel().getPrimaryCaret();
    //noinspection ConstantConditions
    final float caretWidth = isBlockCursor ? editor.getCaretLocations(false)[0].myWidth
                                         : JBUIScale.scale(caret.getVisualAttributes().getWidth(settings.getLineCursorWidth()));
    final float caretShift = isBlockCursor ? 0 : caretWidth <= 1 ? 0 : 1 / JBUIScale.sysScale(g);
    final Rectangle2D caretRectangle = new Rectangle2D.Float(p2x + width2 - caretShift, p2y - topOverhang,
                                                             caretWidth, caretHeight);

    final float rectangle2Start = (float)PaintUtil.alignToInt(p2x, g, PaintUtil.RoundingMode.FLOOR);
    final float rectangle2End = (float)PaintUtil.alignToInt(p2x + width2 + caretWidth - caretShift, g, PaintUtil.RoundingMode.CEIL);
    final Rectangle2D rectangle1 = new Rectangle2D.Float(p2x - width1, p2y, width1, lineHeight);
    final Rectangle2D rectangle2 = new Rectangle2D.Float(rectangle2Start, p2y, rectangle2End - rectangle2Start, lineHeight);

    final Consumer<Graphics2D> painter = graphics -> {
      EditorUIUtil.setupAntialiasing(graphics);
      graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, UISettings.getEditorFractionalMetricsHint());

      fillRect(graphics, rectangle2, attributes2.getBackgroundColor());
      drawChar(graphics, c2, p2x, p2y + ascent, font2, attributes2.getForegroundColor());

      fillRect(graphics, caretRectangle, getCaretColor(editor));

      fillRect(graphics, rectangle1, attributes1.getBackgroundColor());
      drawChar(graphics, c1, p2x - width1, p2y + ascent, font1, attributes1.getForegroundColor());
    };

    final Shape originalClip = g.getClip();

    float clipStartX = (float)PaintUtil.alignToInt(p2x > editor.getContentComponent().getInsets().left ? p2x - caretShift : p2x,
                                                   g, PaintUtil.RoundingMode.FLOOR);
    float clipEndX = (float)PaintUtil.alignToInt(p2x + width2 - caretShift + caretWidth,
                                                 g, PaintUtil.RoundingMode.CEIL);
    if (clipEndX > editor.getContentComponent().getWidth()) {
      // we cannot paint beyond component bounds (this will go beyond dev clip in graphics anyway)
      return;
    }

    g.setClip(new Rectangle2D.Float(clipStartX, p2y, clipEndX - clipStartX, lineHeight));
    // at the moment, lines in editor are not aligned to dev pixel grid along Y axis, when fractional scale is used,
    // so double buffering is disabled (as it might not produce the same result as direct painting, and will case text jitter)
    if (DOUBLE_BUFFERING.asBoolean() && !PaintUtil.isFractionalScale(g.getTransform())) {
      paintWithDoubleBuffering(g, painter);
    }
    else {
      painter.consume(g);
    }

    g.setClip(originalClip);

    if (PIPELINE_FLUSH.asBoolean()) {
      Toolkit.getDefaultToolkit().sync();
    }

    if (DEBUG.asBoolean()) {
      pause();
    }
  }
private void paintImmediately(final Graphics2D g, final int offset, final char c2)