/**
  * Returns the insets of this box, which is the sum of the margin, border, and padding on each
  * side. If no element is associated with this box returns all zeros.
  */
 public Insets getInsets(LayoutContext context, int containerWidth) {
   Element element = this.getElement();
   if (element == null) {
     return Insets.ZERO_INSETS;
   } else {
     return getInsets(context.getStyleSheet().getStyles(element), containerWidth);
   }
 }
  /**
   * Draws the background and borders of a CSS-styled box.
   *
   * @param context LayoutContext used for drawing.
   * @param element Element to use when determining styles. This is used by TableBodyBox to specify
   *     the corresponding table element.
   * @param x x-coordinate of the left side of the box
   * @param y y-coordinate of the top of the box
   * @param containerWidth width of the containing client area. Used for calculating padding
   *     expressed as a percentage.
   * @param drawBorders If true, the background is filled and the borders are drawn; otherwise, just
   *     the background is filled. This is handy when removing the borders when drawing the
   *     selection frame.
   */
  protected void drawBox(
      LayoutContext context,
      Element element,
      int x,
      int y,
      int containerWidth,
      boolean drawBorders) {

    if (element == null) {
      return;
    }

    Graphics g = context.getGraphics();
    Styles styles = context.getStyleSheet().getStyles(element);

    boolean hasLeft = true;
    boolean hasRight = true;
    int left = x - styles.getPaddingLeft().get(containerWidth) - styles.getBorderLeftWidth();
    int top = y - styles.getPaddingTop().get(containerWidth) - styles.getBorderTopWidth();
    int right =
        x
            + this.getWidth()
            + styles.getPaddingRight().get(containerWidth)
            + styles.getBorderRightWidth();
    int bottom =
        y
            + this.getHeight()
            + styles.getPaddingBottom().get(containerWidth)
            + styles.getBorderBottomWidth();

    if (this instanceof InlineElementBox) {
      // TODO fix boxes for inline elements
      hasLeft = this.getStartOffset() == element.getStartOffset() + 1;
      hasRight = this.getEndOffset() == element.getEndOffset();
      if (hasLeft) {
        // left += styles.getMarginLeft().get(0);
      }
      if (hasRight) {
        // right -= styles.getMarginRight().get(0);
      }
      // top = y - styles.getPaddingTop().get(0) - styles.getBorderTopWidth();
      // bottom = y + box.getHeight() + styles.getPaddingBottom().get(0) +
      // styles.getBorderBottomWidth();
    }

    Color backgroundColor = styles.getBackgroundColor();

    if (backgroundColor != null) {
      ColorResource color = g.createColor(backgroundColor);
      ColorResource oldColor = g.setColor(color);
      g.fillRect(left, top, right - left, bottom - top);
      g.setColor(oldColor);
      color.dispose();
    }

    if (drawBorders) {
      //        Object oldAntiAlias =
      //            g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
      //
      //        g.setRenderingHint(
      //            RenderingHints.KEY_ANTIALIASING,
      //            RenderingHints.VALUE_ANTIALIAS_OFF);
      boolean oldAntiAlias = g.isAntiAliased();
      g.setAntiAliased(false);

      int bw2 = styles.getBorderBottomWidth() / 2;
      int lw2 = styles.getBorderLeftWidth() / 2;
      int rw2 = styles.getBorderRightWidth() / 2;
      int tw2 = styles.getBorderTopWidth() / 2;

      // Bottom border
      if (styles.getBorderBottomWidth() > 0) {
        ColorResource color = g.createColor(styles.getBorderBottomColor());
        ColorResource oldColor = g.setColor(color);
        g.setLineStyle(lineStyle(styles.getBorderBottomStyle()));
        g.setLineWidth(styles.getBorderBottomWidth());
        g.drawLine(left + bw2, bottom - bw2 - 1, right - bw2, bottom - bw2 - 1);
        g.setColor(oldColor);
        color.dispose();
      }

      // Left border
      if (hasLeft && styles.getBorderLeftWidth() > 0) {
        ColorResource color = g.createColor(styles.getBorderLeftColor());
        ColorResource oldColor = g.setColor(color);
        g.setLineStyle(lineStyle(styles.getBorderLeftStyle()));
        g.setLineWidth(styles.getBorderLeftWidth());
        g.drawLine(left + lw2, top + lw2, left + lw2, bottom - lw2 - 1);
        g.setColor(oldColor);
        color.dispose();
      }

      // Right border
      if (hasRight && styles.getBorderRightWidth() > 0) {
        ColorResource color = g.createColor(styles.getBorderRightColor());
        ColorResource oldColor = g.setColor(color);
        g.setLineStyle(lineStyle(styles.getBorderRightStyle()));
        g.setLineWidth(styles.getBorderRightWidth());
        g.drawLine(right - rw2 - 1, top + rw2, right - rw2 - 1, bottom - rw2 - 1);
        g.setColor(oldColor);
        color.dispose();
      }

      // Top border
      if (styles.getBorderTopWidth() > 0) {
        ColorResource color = g.createColor(styles.getBorderTopColor());
        ColorResource oldColor = g.setColor(color);
        g.setLineStyle(lineStyle(styles.getBorderTopStyle()));
        g.setLineWidth(styles.getBorderTopWidth());
        g.drawLine(left + tw2, top + tw2, right - tw2, top + tw2);
        g.setColor(oldColor);
        color.dispose();
      }

      //        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAntiAlias);
      g.setAntiAliased(oldAntiAlias);
    }
  }
  /**
   * Returns true if this box is outside the clip region. Implementations of <code>paint</code>
   * should use this to avoid unnecessary painting.
   *
   * @param context <code>LayoutContext</code> in effect.
   * @param x the x-coordinate at which the box is being painted
   * @param y the y-coordinate at which the box is being painted
   */
  protected boolean skipPaint(LayoutContext context, int x, int y) {
    Rectangle clipBounds = context.getGraphics().getClipBounds();

    return clipBounds.getY() + clipBounds.getHeight() <= y
        || clipBounds.getY() >= y + this.getHeight();
  }