/**
  * Updates painted label layout and returns clipped or full label text.
  *
  * @param label label to process
  * @param fm label font metrics
  * @param width label width
  * @param height label height
  * @return clipped or full label text
  */
 protected String layout(final E label, final FontMetrics fm, final int width, final int height) {
   final Insets insets = label.getInsets(null);
   final String text = label.getText();
   final Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();
   final Rectangle paintViewR = new Rectangle();
   paintViewR.x = insets.left;
   paintViewR.y = insets.top;
   paintViewR.width = width - (insets.left + insets.right);
   paintViewR.height = height - (insets.top + insets.bottom);
   paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
   paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;
   return layoutCL(label, fm, text, icon, paintViewR, paintIconR, paintTextR);
 }
  /** {@inheritDoc} */
  @Override
  public void paint(final Graphics2D g2d, final Rectangle bounds, final E label) {
    // Applying graphics settings
    final Composite oc = LafUtils.setupAlphaComposite(g2d, transparency, transparency != null);
    final Map textHints =
        drawShade ? StyleConstants.defaultTextRenderingHints : StyleConstants.textRenderingHints;
    final Font oldFont = LafUtils.setupFont(g2d, label.getFont());
    final Map oldHints = SwingUtils.setupTextAntialias(g2d, textHints);

    // Retrieving icon & text
    final String text = label.getText();
    final Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();

    // Painting background
    if (backgroundPainter != null) {
      backgroundPainter.paint(g2d, bounds, label);
    }

    // We don't need to go futher if there is not icon/text
    if (icon == null && text == null) {
      return;
    }

    final FontMetrics fm = label.getFontMetrics(label.getFont());
    final String clippedText = layout(label, fm, label.getWidth(), label.getHeight());

    if (icon != null) {
      icon.paintIcon(label, g2d, paintIconR.x, paintIconR.y);
    }

    if (text != null) {
      final View v = (View) label.getClientProperty(BasicHTML.propertyKey);
      if (v != null) {
        // Painting HTML label view
        v.paint(g2d, paintTextR);
      } else {
        // Painting plain label view
        final int textX = paintTextR.x;
        final int textY = paintTextR.y + fm.getAscent();
        if (label.isEnabled()) {
          paintEnabledText(label, g2d, clippedText, textX, textY);
        } else {
          paintDisabledText(label, g2d, clippedText, textX, textY);
        }
      }
    }

    SwingUtils.restoreTextAntialias(g2d, oldHints);
    LafUtils.restoreFont(g2d, oldFont);
    LafUtils.restoreComposite(g2d, oc, transparency != null);
  }
  /** {@inheritDoc} */
  @Override
  public Dimension getPreferredSize(final E label) {
    final String text = label.getText();
    final Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();
    final Insets insets = label.getInsets(null);
    final Font font = label.getFont();

    final int dx = insets.left + insets.right;
    final int dy = insets.top + insets.bottom;

    if ((icon == null) && ((text == null) || ((text != null) && (font == null)))) {
      return new Dimension(dx, dy);
    } else if ((text == null) || ((icon != null) && (font == null))) {
      return new Dimension(icon.getIconWidth() + dx, icon.getIconHeight() + dy);
    } else {
      final FontMetrics fm = label.getFontMetrics(font);

      final Rectangle iconR = new Rectangle();
      final Rectangle textR = new Rectangle();
      final Rectangle viewR = new Rectangle();
      iconR.x = iconR.y = iconR.width = iconR.height = 0;
      textR.x = textR.y = textR.width = textR.height = 0;
      viewR.x = dx;
      viewR.y = dy;
      viewR.width = viewR.height = Short.MAX_VALUE;

      layoutCL(label, fm, text, icon, viewR, iconR, textR);

      final int x1 = Math.min(iconR.x, textR.x);
      final int x2 = Math.max(iconR.x + iconR.width, textR.x + textR.width);
      final int y1 = Math.min(iconR.y, textR.y);
      final int y2 = Math.max(iconR.y + iconR.height, textR.y + textR.height);
      final Dimension rv = new Dimension(x2 - x1, y2 - y1);
      rv.width += dx;
      rv.height += dy;
      return rv;
    }
  }