Package org.jvnet.substance.utils

Source Code of org.jvnet.substance.utils.SubstanceTextUtilities

/*
* Copyright (c) 2005-2009 Substance Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  o Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*
*  o Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*
*  o Neither the name of Substance Kirill Grouchnikov nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jvnet.substance.utils;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.*;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.plaf.basic.BasicGraphicsUtils;

import org.jvnet.lafwidget.animation.FadeKind;
import org.jvnet.lafwidget.layout.TransitionLayout;
import org.jvnet.lafwidget.utils.RenderingUtils;
import org.jvnet.substance.api.ComponentState;
import org.jvnet.substance.painter.utils.BackgroundPaintingUtils;
import org.jvnet.substance.utils.border.SubstanceBorder;
import org.jvnet.substance.watermark.SubstanceWatermark;

/**
* Text-related utilities. This class if for internal use only.
*
* @author Kirill Grouchnikov
*/
public class SubstanceTextUtilities {
  public static final String ENFORCE_FG_COLOR = "substancelaf.internal.textUtilities.enforceFgColor";

  /**
   * Paints text with drop shadow.
   *
   * @param c
   *            Component.
   * @param g
   *            Graphics context.
   * @param foregroundColor
   *            Foreground color.
   * @param text
   *            Text to paint.
   * @param width
   *            Text rectangle width.
   * @param height
   *            Text rectangle height.
   * @param xOffset
   *            Text rectangle X offset.
   * @param yOffset
   *            Text rectangle Y offset.
   */
  public static void paintTextWithDropShadow(JComponent c, Graphics g,
      Color foregroundColor, String text, int width, int height,
      int xOffset, int yOffset) {
    Graphics2D graphics = (Graphics2D) g.create();
    RenderingUtils.installDesktopHints(graphics, c);

    // blur the text shadow
    BufferedImage blurred = SubstanceCoreUtilities.getBlankImage(width,
        height);
    Graphics2D gBlurred = (Graphics2D) blurred.getGraphics();
    gBlurred.setFont(graphics.getFont());
    gBlurred.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
        RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
    // Color neg =
    // SubstanceColorUtilities.getNegativeColor(foregroundColor);
    float luminFactor = SubstanceColorUtilities
        .getColorStrength(foregroundColor);
    gBlurred.setColor(SubstanceColorUtilities
        .getNegativeColor(foregroundColor));
    ConvolveOp convolve = new ConvolveOp(new Kernel(3, 3, new float[] {
        .0f, .05f, .1f, .05f, .0f, .1f, .1f, .1f, .1f }),
        ConvolveOp.EDGE_NO_OP, null);
    gBlurred.drawString(text, xOffset + 1, yOffset + 1);
    blurred = convolve.filter(blurred, null);

    graphics.setComposite(TransitionLayout.getAlphaComposite(c,
        luminFactor, g));
    graphics.drawImage(blurred, 0, 0, null);
    graphics.setComposite(TransitionLayout.getAlphaComposite(c, g));

    FontMetrics fm = graphics.getFontMetrics();
    SubstanceTextUtilities.paintText(graphics, c, new Rectangle(xOffset,
        yOffset - fm.getAscent(), width - xOffset, fm.getHeight()),
        text, -1, graphics.getFont(), foregroundColor, graphics
            .getClipBounds());

    graphics.dispose();
  }

  /**
   * Paints the specified text.
   *
   * @param g
   *            Graphics context.
   * @param comp
   *            Component.
   * @param textRect
   *            Text rectangle.
   * @param text
   *            Text to paint.
   * @param mnemonicIndex
   *            Mnemonic index.
   * @param font
   *            Font to use.
   * @param color
   *            Color to use.
   * @param clip
   *            Optional clip. Can be <code>null</code>.
   * @param transform
   *            Optional transform to apply. Can be <code>null</code>.
   */
  private static void paintText(Graphics g, JComponent comp,
      Rectangle textRect, String text, int mnemonicIndex,
      java.awt.Font font, java.awt.Color color, java.awt.Rectangle clip,
      java.awt.geom.AffineTransform transform) {
    if ((text == null) || (text.length() == 0))
      return;

    Graphics2D g2d = (Graphics2D) g.create();
    // workaroundBug6576507(g2d);
    // RenderingUtils.installDesktopHints(g2d);

    g2d.setFont(font);
    g2d.setColor(color);
    // fix for issue 420 - call clip() instead of setClip() to
    // respect the currently set clip shape
    if (clip != null)
      g2d.clip(clip);
    if (transform != null)
      g2d.transform(transform);
    BasicGraphicsUtils.drawStringUnderlineCharAt(g2d, text, mnemonicIndex,
        textRect.x, textRect.y + g2d.getFontMetrics().getAscent());
    g2d.dispose();
  }

  /**
   * Paints the specified text.
   *
   * @param g
   *            Graphics context.
   * @param comp
   *            Component.
   * @param textRect
   *            Text rectangle.
   * @param text
   *            Text to paint.
   * @param mnemonicIndex
   *            Mnemonic index.
   * @param font
   *            Font to use.
   * @param color
   *            Color to use.
   * @param clip
   *            Optional clip. Can be <code>null</code>.
   */
  public static void paintText(Graphics g, JComponent comp,
      Rectangle textRect, String text, int mnemonicIndex,
      java.awt.Font font, java.awt.Color color, java.awt.Rectangle clip) {
    SubstanceTextUtilities.paintText(g, comp, textRect, text,
        mnemonicIndex, font, color, clip, null);
  }

  /**
   * Paints the specified vertical text.
   *
   * @param g
   *            Graphics context.
   * @param comp
   *            Component.
   * @param textRect
   *            Text rectangle.
   * @param text
   *            Text to paint.
   * @param mnemonicIndex
   *            Mnemonic index.
   * @param font
   *            Font to use.
   * @param color
   *            Color to use.
   * @param clip
   *            Optional clip. Can be <code>null</code>.
   * @param isFromBottomToTop
   *            If <code>true</code>, the text will be painted from bottom to
   *            top, otherwise the text will be painted from top to bottom.
   */
  public static void paintVerticalText(Graphics g, JComponent comp,
      Rectangle textRect, String text, int mnemonicIndex,
      java.awt.Font font, java.awt.Color color, java.awt.Rectangle clip,
      boolean isFromBottomToTop) {
    if ((text == null) || (text.length() == 0))
      return;

    AffineTransform at = null;

    if (!isFromBottomToTop) {
      at = AffineTransform.getTranslateInstance(textRect.x
          + textRect.width, textRect.y);
      at.rotate(Math.PI / 2);
    } else {
      at = AffineTransform.getTranslateInstance(textRect.x, textRect.y
          + textRect.height);
      at.rotate(-Math.PI / 2);
    }
    Rectangle newRect = new Rectangle(0, 0, textRect.width, textRect.height);

    SubstanceTextUtilities.paintText(g, comp, newRect, text, mnemonicIndex,
        font, color, clip, at);
  }

  /**
   * Paints the text of the specified button.
   *
   * @param g
   *            Graphic context.
   * @param button
   *            Button
   * @param textRect
   *            Text rectangle
   * @param text
   *            Text to paint
   * @param mnemonicIndex
   *            Mnemonic index.
   */
  public static void paintText(Graphics g, AbstractButton button,
      Rectangle textRect, String text, int mnemonicIndex) {
    paintText(g, button, button.getModel(), textRect, text, mnemonicIndex);
  }

  /**
   * Paints the text of the specified button.
   *
   * @param g
   *            Graphic context.
   * @param button
   *            Button
   * @param model
   *            Button model.
   * @param textRect
   *            Text rectangle
   * @param text
   *            Text to paint
   * @param mnemonicIndex
   *            Mnemonic index.
   */
  public static void paintText(Graphics g, AbstractButton button,
      ButtonModel model, Rectangle textRect, String text,
      int mnemonicIndex) {
    // Ignore the selection state of the menu item. This is especially
    // relevant for dark color schemes.
    ComponentState state = ComponentState.getState(model, button,
        button instanceof JMenuItem);
    ComponentState prevState = (state == ComponentState.ACTIVE) ? state
        : SubstanceCoreUtilities.getPrevComponentState(button);

    // special case for enabled buttons with no background -
    // always use the color scheme for the default state.
    if (SubstanceCoreUtilities.isButtonNeverPainted(button)
        || !button.isContentAreaFilled()
        || (button instanceof JRadioButton)
        || (button instanceof JCheckBox)) {
      if (state.isKindActive(FadeKind.ENABLE)) {
        state = ComponentState.DEFAULT;
        prevState = ComponentState.DEFAULT;
      }
    }

    float buttonAlpha = SubstanceColorSchemeUtilities.getAlpha(button,
        ComponentState.getState(button));
    paintText(g, button, textRect, text, mnemonicIndex, state, prevState,
        buttonAlpha);
  }

  /**
   * Paints the specified text.
   *
   * @param g
   *            Graphics context.
   * @param component
   *            Component.
   * @param textRect
   *            Text rectangle.
   * @param text
   *            Text to paint.
   * @param mnemonicIndex
   *            Mnemonic index.
   * @param state
   *            Component state.
   * @param prevState
   *            Component previous state.
   * @param textAlpha
   *            Alpha channel for painting the text.
   */
  public static void paintText(Graphics g, JComponent component,
      Rectangle textRect, String text, int mnemonicIndex,
      ComponentState state, ComponentState prevState, float textAlpha) {
    Color fgColor = getForegroundColor(component, text, state, prevState,
        textAlpha);

    SubstanceTextUtilities.paintText(g, component, textRect, text,
        mnemonicIndex, component.getFont(), fgColor, null);
  }

  /**
   * Returns the foreground color for the specified component.
   *
   * @param component
   *            Component.
   * @param text
   *            Text. If empty or <code>null</code>, the result is
   *            <code>null</code>.
   * @param state
   *            Component state.
   * @param prevState
   *            Component previous state.
   * @param textAlpha
   *            Alpha channel for painting the text. If value is less than
   *            1.0, the result is an opaque color which is an interpolation
   *            between the "real" foreground color and the background color
   *            of the component. This is done to ensure that native text
   *            rasterization will be performed on 6u10 on Windows.
   * @return The foreground color for the specified component.
   */
  public static Color getForegroundColor(JComponent component, String text,
      ComponentState state, ComponentState prevState, float textAlpha) {
    if ((text == null) || (text.length() == 0))
      return null;

    boolean toEnforceFgColor = (SwingUtilities.getAncestorOfClass(
        CellRendererPane.class, component) != null)
        || Boolean.TRUE.equals(component
            .getClientProperty(ENFORCE_FG_COLOR));

    Color fgColor = toEnforceFgColor ? component.getForeground()
        : SubstanceColorUtilities.getForegroundColor(component, state,
            prevState);

    // System.out.println(text + ":" + prevState.name() + "->" +
    // state.name() + ":" + fgColor);
    if (textAlpha < 1.0f) {
      Color bgFillColor = SubstanceColorUtilities
          .getBackgroundFillColor(component);
      fgColor = SubstanceColorUtilities.getInterpolatedColor(fgColor,
          bgFillColor, textAlpha);
    }
    return fgColor;
  }

  /**
   * Paints background of the specified text component.
   *
   * @param g
   *            Graphics context.
   * @param comp
   *            Component.
   */
  public static void paintTextCompBackground(Graphics g, JComponent comp) {
    paintTextCompBackground(g, comp, SubstanceColorUtilities
        .getBackgroundFillColor(comp), SubstanceCoreUtilities
        .toDrawWatermark(comp)
        || !comp.isOpaque());
  }

  /**
   * Paints background of the specified text component.
   *
   * @param g
   *            Graphics context.
   * @param comp
   *            Component.
   * @param backgr
   *            Background color.
   * @param toOverlayWatermark
   *            If <code>true</code>, this method will paint the watermark
   *            overlay on top of the background fill.
   */
  private static void paintTextCompBackground(Graphics g, JComponent comp,
      Color backgr, boolean toOverlayWatermark) {
    Graphics2D g2d = (Graphics2D) g.create();

    int componentFontSize = SubstanceSizeUtils.getComponentFontSize(comp);
    int borderDelta = (int) Math.floor(SubstanceSizeUtils
        .getBorderStrokeWidth(componentFontSize) / 2.0);
    Border compBorder = comp.getBorder();
    boolean isSubstanceBorder = compBorder instanceof SubstanceBorder;
    if (compBorder instanceof CompoundBorder) {
      isSubstanceBorder = isSubstanceBorder
          || (((CompoundBorder) compBorder).getOutsideBorder() instanceof SubstanceBorder);
    }

    Shape contour = isSubstanceBorder ? SubstanceOutlineUtilities
        .getBaseOutline(
            comp.getWidth(),
            comp.getHeight(),
            SubstanceSizeUtils
                .getClassicButtonCornerRadius(componentFontSize),
            null, borderDelta)
        : new Rectangle(0, 0, comp.getWidth(), comp.getHeight());

    BackgroundPaintingUtils.update(g, comp, false);
    g2d.setColor(backgr);
    g2d.fill(contour);

    if (toOverlayWatermark) {
      SubstanceWatermark watermark = SubstanceCoreUtilities.getSkin(comp)
          .getWatermark();
      if (watermark != null) {
        watermark.drawWatermarkImage(g2d, comp, 0, 0, comp.getWidth(),
            comp.getHeight());
      }
    }

    g2d.dispose();
  }
}
TOP

Related Classes of org.jvnet.substance.utils.SubstanceTextUtilities

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.