class HighlightPainter extends DefaultHighlighter.DefaultHighlightPainter {

  private static final BasicStroke OO_STROKE1 = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, new float[]{3.0f, 5.0f}, 2);
  private static final BasicStroke OO_STROKE2 = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, new float[]{1.0f, 3.0f}, 3);
  private static final BasicStroke OO_STROKE3 = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, new float[]{3.0f, 5.0f}, 6);
  private static final BasicStroke ZIGZAG_STROKE1 = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, new float[]{1.0f, 1.0f}, 0);

  private final Color underlineColor;
  private final Color backgroundColor;

  HighlightPainter(Color backgroundColor, Color underlineColor) {
    super(backgroundColor);
    this.backgroundColor = backgroundColor;
    this.underlineColor = underlineColor;
  }

  @Override
  public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c, View view) {<FILL_FUNCTION_BODY>}

  private void drawCurvedLine(Graphics g, Rectangle rect) {
    int x1 = rect.x;
    int x2 = rect.x + rect.width;
    int y = rect.y + rect.height;
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setStroke(OO_STROKE1);
    g2.drawLine(x1, y - 1, x2, y - 1);
    g2.setStroke(OO_STROKE2);
    g2.drawLine(x1, y - 2, x2, y - 2);
    g2.setStroke(OO_STROKE3);
    g2.drawLine(x1, y - 3, x2, y - 3);
  }

  private void drawLine(Graphics g, Rectangle rect) {
    int x1 = rect.x;
    int x2 = rect.x + rect.width;
    int y = rect.y + rect.height;
    Graphics2D g2 = (Graphics2D) g;
    g2.setStroke(ZIGZAG_STROKE1);
    g2.drawLine(x1, y - 1, x2, y - 1);
  }
  
}

    if (backgroundColor != null) {
      super.paintLayer(g, offs0, offs1, bounds, c, view);
    }
    Rectangle rect;

    if (offs0 == view.getStartOffset() && offs1 == view.getEndOffset()) {
      if (bounds instanceof Rectangle) {
        rect = (Rectangle) bounds;
      } else {
        rect = bounds.getBounds();
      }
    } else {
      try {
        Shape shape = view.modelToView(offs0, Position.Bias.Forward, offs1, Position.Bias.Backward, bounds);
        rect = shape instanceof Rectangle ? (Rectangle) shape : shape.getBounds();
      } catch (BadLocationException e) {
        rect = null;
      }
    }

    if (rect != null) {
      Color color = underlineColor;

      if (color == null) {
        g.setColor(c.getSelectionColor());
      } else {
        g.setColor(color);
      }

      rect.width = Math.max(rect.width, 1);

      int descent = c.getFontMetrics(c.getFont()).getDescent();

      if (descent > 3) {
        drawCurvedLine(g, rect);
      } else if (descent > 2) {
        drawCurvedLine(g, rect);
      } else {
        drawLine(g, rect);
      }
    }

    return rect;
  
<methods>public void <init>(java.awt.Color) ,public java.awt.Color getColor() ,public void paint(java.awt.Graphics, int, int, java.awt.Shape, javax.swing.text.JTextComponent) ,public java.awt.Shape paintLayer(java.awt.Graphics, int, int, java.awt.Shape, javax.swing.text.JTextComponent, javax.swing.text.View) <variables>private java.awt.Color color