- /*
- * @(#)BlueprintEngine.java 1.23 03/12/19
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package com.sun.java.swing.plaf.gtk;
-
- import java.awt.*;
- import java.awt.image.*;
- import java.security.AccessController;
- import java.util.*;
- import javax.swing.*;
- import javax.swing.plaf.ComponentUI;
- import javax.swing.plaf.synth.*;
- import sun.security.action.GetPropertyAction;
- import sun.swing.plaf.synth.SynthUI;
-
- /**
- * GTKEngine implementation that renders using images. The images to render
- * are dictated by the <code>BlueprintStyle.Info</code>.
- *
- * @version 1.23 12/19/03
- * @author Joshua Outwater
- */
- class BlueprintEngine extends GTKEngine implements GTKConstants {
- /**
- * By default we don't use smooth scaling as it is currently not optimized.
- */
- private static final Object RENDERING_HINT;
-
- private int COMPONENT_NORTH_WEST = 1;
- private int COMPONENT_NORTH = 2;
- private int COMPONENT_NORTH_EAST = 4;
- private int COMPONENT_WEST = 8;
- private int COMPONENT_CENTER = 16;
- private int COMPONENT_EAST = 32;
- private int COMPONENT_SOUTH_EAST = 64;
- private int COMPONENT_SOUTH = 128;
- private int COMPONENT_SOUTH_WEST = 256;
- private int COMPONENT_ALL = 512;
-
- private int _clipX1;
- private int _clipX2;
- private int _clipY1;
- private int _clipY2;
-
- static {
- if ("true".equals((String)AccessController.doPrivileged(
- new GetPropertyAction("swing.pixmap.smoothScaling")))) {
- RENDERING_HINT = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
- }
- else {
- RENDERING_HINT = null;
- }
- }
-
- public void paintSlider(SynthContext context, Graphics g, int state,
- int shadowType, String info,
- int x, int y, int w, int h, int orientation) {
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)context.getStyle()).
- getInfo("SLIDER", info, state, shadowType, orientation,
- UNDEFINED, UNDEFINED, null))) {
- super.paintSlider(context, g, state, shadowType, info,
- x, y, w, h, orientation);
- }
- }
-
- public void paintHline(SynthContext context, Graphics g, int state,
- String info, int x, int y, int w, int h) {
-
- SynthStyle style = context.getStyle();
- Component c = context.getComponent();
-
- // We have a different style to use if we are the child of
- // a popup menu.
- c = c.getParent();
- if (c instanceof JPopupMenu) {
- SynthStyle newStyle = getStyle((JPopupMenu)c,
- ((JPopupMenu)c).getUI());
- if (newStyle != null) {
- style = newStyle;
- }
- }
-
- BlueprintStyle.Info blueprintInfo =
- ((BlueprintStyle)style).getInfo("HLINE", info,
- state, UNDEFINED, GTKConstants.HORIZONTAL,
- UNDEFINED, UNDEFINED, null);
- if (blueprintInfo != null && blueprintInfo.getImage() != null) {
- themeBlueprintRender(context, g, x, y, w, h,
- blueprintInfo.getImage(), blueprintInfo.getImageInsets(),
- COMPONENT_ALL, blueprintInfo.getStretch(), false,
- blueprintInfo.isBkgMask(), blueprintInfo.isRecolorable(),
- blueprintInfo.getColorizeColor());
- } else {
- super.paintHline(context, g, state, info, x, y, w, h);
- }
- }
-
- public void paintVline(SynthContext context, Graphics g, int state,
- String info, int x, int y, int w, int h) {
- BlueprintStyle.Info blueprintInfo =
- ((BlueprintStyle)context.getStyle()).getInfo("VLINE", info,
- state, UNDEFINED, GTKConstants.VERTICAL,
- UNDEFINED, UNDEFINED, null);
- if (blueprintInfo != null && blueprintInfo.getImage() != null) {
- themeBlueprintRender(context, g, x, y, w, h, blueprintInfo.getImage(),
- blueprintInfo.getImageInsets(), COMPONENT_ALL,
- blueprintInfo.getStretch(), false,
- blueprintInfo.isBkgMask(), blueprintInfo.isRecolorable(),
- blueprintInfo.getColorizeColor());
- } else {
- super.paintVline(context, g, state, info, x, y, w, h);
- }
- }
-
- public void paintArrow(SynthContext context, Graphics g, int state,
- int shadowType, int direction, String info,
- int x, int y, int w, int h) {
- Component c = context.getComponent();
-
- // Don't paint the arrow if we're in a spinner or combo box.
- // We get that from the image.
- if (c.getName() == "Spinner.nextButton" ||
- c.getName() == "Spinner.previousButton" ||
- c.getName() == "ComboBox.arrowButton") {
- return;
- }
-
- String parentType = null;
- c = c.getParent();
- if (c != null && c instanceof JComponent) {
- c = c.getParent();
- if (c != null && c instanceof JComponent) {
- parentType = getComponentType((JComponent)c);
- }
- }
-
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)context.getStyle()).
- getInfo("ARROW", info, state, shadowType,
- UNDEFINED, UNDEFINED, direction, parentType))) {
- super.paintArrow(context, g, state, shadowType, direction,
- info, x, y, w, h);
- }
- }
-
- public void paintBox(SynthContext context, Graphics g, int state,
- int shadowType, String info, int x, int y,
- int w, int h) {
- int orientation;
- Region id = context.getRegion();
- Component c = context.getComponent();
- SynthStyle style = context.getStyle();
-
- // Blueprint checks to make sure that we aren't calling
- // paintBox on a slider/scrollbar with detail hscrollbar or
- // vscrollbar, because they do the work in paintArrow instead.
- // We do it here because we have the correct bounds for the whole
- // button.
- Integer arrowDirection =
- (Integer)((JComponent)c).getClientProperty("__arrow_direction__");
- if (info == "vscrollbar" || info == "hscrollbar" &&
- arrowDirection != null) {
- int direction = arrowDirection.intValue();
- switch (direction) {
- case SwingConstants.NORTH:
- direction = GTKConstants.ARROW_UP;
- break;
- case SwingConstants.SOUTH:
- direction = GTKConstants.ARROW_DOWN;
- break;
- case SwingConstants.EAST:
- direction = GTKConstants.ARROW_RIGHT;
- break;
- case SwingConstants.WEST:
- direction = GTKConstants.ARROW_LEFT;
- break;
- }
-
- c = (JComponent)c.getParent();
- if (c == null || !(c instanceof JComponent)) {
- return;
- }
-
- if (c instanceof JScrollBar) {
- SynthStyle newStyle = getStyle((JScrollBar)c,
- ((JScrollBar)c).getUI());
- if (newStyle != null) {
- style = newStyle;
- }
-
- if (paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)style).getInfo("STEPPER", info,
- state, UNDEFINED, UNDEFINED, UNDEFINED,
- direction, null))) {
- return;
- }
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)style).getInfo("BOX", info, state,
- shadowType, UNDEFINED, UNDEFINED,
- UNDEFINED, null))) {
- super.paintBox(context, g, state, shadowType, info,
- x, y, w, h);
- }
- return;
- }
- }
-
- // If the button is in a spinner get the style of the JSpinner.
- if (c.getName() == "Spinner.nextButton" ||
- c.getName() == "Spinner.previousButton" &&
- arrowDirection != null) {
- if (arrowDirection.intValue() == SwingConstants.NORTH) {
- info = "spinbutton_up";
- } else {
- info = "spinbutton_down";
- }
- c = c.getParent();
- if (c instanceof JSpinner) {
- SynthStyle newStyle = getStyle((JSpinner)c,
- ((JSpinner)c).getUI());
- if (newStyle != null) {
- style = newStyle;
- }
- }
- }
-
- if (id == Region.SCROLL_BAR) {
- if (((JScrollBar)c).getOrientation() ==
- SwingConstants.HORIZONTAL) {
- orientation = GTKConstants.HORIZONTAL;
- }
- else {
- orientation = GTKConstants.VERTICAL;
- }
- }
- else if (id == Region.SLIDER_TRACK) {
- if (((JSlider)c).getOrientation() ==
- SwingConstants.HORIZONTAL) {
- orientation = GTKConstants.HORIZONTAL;
- }
- else {
- orientation = GTKConstants.VERTICAL;
- }
- }
- else {
- orientation = UNDEFINED;
- }
-
- String parentType = null;
- if (c != null) {
- c = c.getParent();
- if (c != null && c instanceof JComponent) {
- parentType = getComponentType((JComponent)c);
- }
- }
-
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)style).getInfo("BOX", info, state,
- shadowType, orientation, UNDEFINED, UNDEFINED,
- parentType))) {
- super.paintBox(context, g, state, shadowType, info, x, y, w, h);
- }
- }
-
- public void paintBoxGap(SynthContext context, Graphics g, int state,
- int shadow, String key, int x, int y,
- int w, int h, int gapSide, int gapStart,
- int gapSize) {
- BlueprintStyle.Info info = ((BlueprintStyle)context.getStyle()).getInfo(
- "BOX_GAP", key, state, shadow, UNDEFINED, gapSide, UNDEFINED,
- null);
-
- if (info != null) {
- paintGapImage(context, info, g, x, y, w, h, true, gapSide,
- gapStart, gapSize);
- } else {
- super.paintBoxGap(context, g, state, shadow, key, x, y, w, h,
- gapSide, gapStart, gapSize);
- }
- }
-
- public void paintHandle(SynthContext context, Graphics g, int paintState,
- int shadowType, String info, int x, int y,
- int w, int h, int orientation) {
- if (info == "handlebox" || info == "dockitem") {
- w -=2;
- h -=1;
- }
-
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)context.getStyle()).
- getInfo("HANDLE", info, paintState, shadowType,
- orientation, UNDEFINED, UNDEFINED, null))) {
- super.paintHandle(context, g, paintState, shadowType, info, x, y,
- w, h, orientation);
- }
- }
-
- public void paintOption(SynthContext context, Graphics g, int paintState,
- int shadowType, String info, int x, int y,
- int w, int h) {
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)context.getStyle()).
- getInfo("OPTION", info, paintState, shadowType,
- UNDEFINED, UNDEFINED, UNDEFINED, null))) {
- super.paintOption(context, g, paintState, shadowType, info, x, y,
- w, h);
- }
- }
-
- public void paintFocus(SynthContext context, Graphics g, int state,
- String key, int x, int y, int w, int h) {
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)context.getStyle()).
- getInfo("FOCUS", key, state, UNDEFINED, UNDEFINED,
- UNDEFINED, UNDEFINED, null))) {
- super.paintFocus(context, g, state, key, x, y, w, h);
- }
- }
-
- public void paintShadow(SynthContext context, Graphics g, int state,
- int shadowType, String info, int x, int y,
- int w, int h) {
- Component c = context.getComponent();
- String parentType = null;
- SynthStyle style = context.getStyle();
-
- if (c.getName() == "ComboBox.textField") {
- parentType = "GtkCombo";
- } else if (c.getName() == "ComboBox.renderer") {
- c = c.getParent();
- if (c != null) {
- c = c.getParent();
- parentType = "GtkCombo";
- }
- }
-
- if (c instanceof JComboBox) {
- // Use the Style from the editor
- JComboBox cb = (JComboBox)c;
- Component editor = cb.getEditor().getEditorComponent();
- if (editor instanceof JTextField) {
- if (!cb.isEditable() && editor.getParent() == null) {
- // GTKStyleFactory hands back a bogus Style when a
- // Component doesn't have a parent. As the editor
- // is only parented when the JComboBox is editable it
- // means we can get back a bogus style. To force the
- // real style to be assigned we parent the editor.
- // YES, this is ugly!
- cb.add(editor);
- cb.remove(editor);
- }
- SynthStyle newStyle = getStyle((JTextField)editor,
- ((JTextField)editor).getUI());
- if (newStyle != null) {
- style = newStyle;
- }
- }
- }
-
- if (info == "menu" && parentType == "GtkHBox") {
- return;
- }
-
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)style).getInfo("SHADOW", info, state,
- shadowType, UNDEFINED, UNDEFINED, UNDEFINED,
- parentType))) {
- super.paintShadow(context, g, state, shadowType, info, x, y, w, h);
- }
- }
-
- public void paintExpander(SynthContext context, Graphics g, int state,
- int expanderStyle, String info, int x,
- int y, int w, int h) {
- // It does not appear that there is a way to override this.
- super.paintExpander(context, g, state, expanderStyle, info, x, y, w,h);
- }
-
- public void paintCheck(SynthContext context, Graphics g, int state,
- int shadowType, String info, int x, int y,
- int w, int h) {
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)context.getStyle()).
- getInfo("CHECK", info, state, shadowType, UNDEFINED,
- UNDEFINED, UNDEFINED, null))) {
- super.paintCheck(context, g, state, shadowType, info, x, y, w, h);
- }
- }
-
- public void paintExtension(SynthContext context, Graphics g, int state,
- int shadowType, String info, int x, int y,
- int w, int h, int placement, int tabIndex) {
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)context.getStyle()).
- getInfo("EXTENSION", info, state, shadowType,
- UNDEFINED, placement, UNDEFINED, null))) {
- super.paintExtension(context, g, state, shadowType, info, x, y,
- w, h, placement, tabIndex);
- }
- }
-
- public void paintFlatBox(SynthContext context, Graphics g, int state,
- String key, int x, int y, int w, int h) {
- if (key == "checkbutton" && state == SynthConstants.MOUSE_OVER) {
- return;
- }
-
- Component c = context.getComponent();
-
- String parentType = null;
- c = c.getParent();
- if (c instanceof CellRendererPane) {
- // Skip the CellRendererPane
- c = c.getParent();
- }
- if (c != null && c instanceof JComponent) {
- parentType = getComponentType((JComponent)c);
- }
-
- if (!paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)context.getStyle()).
- getInfo("FLAT_BOX", key, state, UNDEFINED, UNDEFINED,
- UNDEFINED, UNDEFINED, parentType))) {
- super.paintFlatBox(context, g, state, key, x, y, w, h);
- }
- }
-
- void paintBackground(SynthContext context, Graphics g, int state,
- Color color, int x, int y, int w, int h) {
- JComponent c = context.getComponent();
- if (c instanceof JPopupMenu) {
- if (paintSimpleImage(context, g, x, y, w, h, true,
- ((BlueprintStyle)context.getStyle()).
- getInfo("BACKGROUND", null, state, UNDEFINED,
- UNDEFINED, UNDEFINED, UNDEFINED, null))) {
- return;
- }
- }
- super.paintBackground(context, g, state, color, x, y, w, h);
- }
-
- /**
- * Paints a gap image. This renders the image into a portion of
- * the passed in region that is dictated
- * by the <code>gapSide</code> and <code>size</code> arguments. For
- * example, if <code>gapSide</code> is <code>GTKConstants.TOP</code>,
- * this will render the image into the space:
- * <table>
- * <tr><td>x origin<td> <code>x</code> + <code>gapStart</code>
- * <tr><td>y origin<td> <code>y</code>
- * <tr><td>width<td> <code>gapSize</code>
- * <tr><td>height<td> <code>size</code>
- * </table>
- *
- * @param context Context used to retrieve style information.
- * @param info Blueprint style info
- * @param g Graphics object to paint to
- * @param x X origin
- * @param y Y origin
- * @param w Width to draw to
- * @param h Height to draw to
- * @param drawCenter Whether or not the center is drawn.
- * @param gapSide Side the gap is on, one of GTKConstants.LEFT,
- * GTKConstants.RIGHT, GTKConstants.TOP or GTKConstants.BOTTOM
- * @param gapStart Starting location of the gap. The axis the gap is
- * on is dictated by the gapSide
- * @param gapSize size of the gap
- */
- private void paintGapImage(SynthContext context, BlueprintStyle.Info info,
- Graphics g, int x, int y, int w, int h,
- boolean drawCenter, int gapSide, int gapStart,
- int gapSize) {
-
- Rectangle r1 = new Rectangle();
- Rectangle r2 = new Rectangle();
- Rectangle r3 = new Rectangle();
- int size = 0;
- int componentMask = COMPONENT_ALL;
- Image startImage = info.getGapStartImage();
- Image image = info.getGapImage();
- Image endImage = info.getGapEndImage();
-
- if (!drawCenter) {
- componentMask |= COMPONENT_CENTER;
- }
-
- // Blueprint doesn't look at each individual image for size, just the
- // starting image.
- if (startImage != null) {
- if (gapSide == TOP || gapSize == BOTTOM) {
- size = startImage.getHeight(null);
- } else {
- size = startImage.getWidth(null);
- }
- } else {
- if (gapSide == TOP || gapSize == BOTTOM) {
- size = ((BlueprintStyle)context.getStyle()).getYThickness();
- } else {
- size = ((BlueprintStyle)context.getStyle()).getXThickness();
- }
- }
-
- if (gapSize > 0) {
- switch(gapSide) {
- case TOP:
- if (!drawCenter) {
- componentMask |= COMPONENT_NORTH_WEST | COMPONENT_NORTH |
- COMPONENT_NORTH_EAST;
- }
- // gap start
- r1.x = x;
- r1.y = y;
- r1.width = gapStart;
- r1.height = size;
- // gap
- r2.x = x + gapStart;
- r2.y = y;
- r2.width = gapSize;
- r2.height = size;
- // gap end
- r3.x = x + gapStart + gapSize;
- r3.y = y;
- r3.width = w - (gapStart + gapSize);
- r3.height = size;
- break;
- case BOTTOM:
- if (!drawCenter) {
- componentMask |= COMPONENT_SOUTH_WEST | COMPONENT_SOUTH |
- COMPONENT_SOUTH_EAST;
- }
- // gap start
- r1.x = x;
- r1.y = y + h - size;
- r1.width = gapStart;
- r1.height = size;
- // gap
- r2.x = x + gapStart;
- r2.y = y + h - size;
- r2.width = gapSize;
- r2.height = size;
- // gap end
- r3.x = x + gapStart + gapSize;
- r3.y = y + h - size;
- r3.width = w - (gapStart + gapSize);
- r3.height = size;
- break;
- case LEFT:
- if (!drawCenter) {
- componentMask |= COMPONENT_NORTH_WEST | COMPONENT_WEST |
- COMPONENT_SOUTH_WEST;
- }
- // gap start
- r1.x = x;
- r1.y = y;
- r1.width = size;
- r1.height = gapStart;
- // gap
- r2.x = x;
- r2.y = y + gapStart;
- r2.width = size;
- r2.height = gapSize;
- // gap end
- r3.x = x;
- r3.y = y + gapStart + gapSize;
- r3.width = size;
- r3.height = h - (gapStart + gapSize);
- break;
- case RIGHT:
- if (!drawCenter) {
- componentMask |= COMPONENT_NORTH_EAST | COMPONENT_EAST |
- COMPONENT_SOUTH_EAST;
- }
- // gap start
- r1.x = x + w - size;
- r1.y = y;
- r1.width = size;
- r1.height = gapStart;
- // gap
- r2.x = x + w - size;
- r2.y = y + gapStart;
- r2.width = size;
- r2.height = gapSize;
- // gap end
- r3.x = x + w - size;
- r3.y = y + gapStart + gapSize;
- r3.width = size;
- r3.height = h - (gapStart + gapSize);
- break;
- }
-
- themeBlueprintRender(context, g, x, y, w, h, info.getImage(),
- info.getImageInsets(), componentMask, true, false,
- info.isBkgMask(), info.isRecolorable(),
- info.getColorizeColor());
-
- // NOTE:
- // stretch should be queried from the info, but there is currently
- // no support for that field for gap images in BlueprintStyle.Info.
- if (startImage != null) {
- themeBlueprintRender(context, g, r1.x, r1.y, r1.width, r1.height,
- startImage, info.getGapStartInsets(), COMPONENT_ALL,
- true, false, false, false, null);
- }
- if (image != null) {
- themeBlueprintRender(context, g, r2.x, r2.y, r2.width, r2.height,
- image, info.getGapInsets(), COMPONENT_ALL,
- true, false, false, false, null);
- }
- if (endImage != null) {
- themeBlueprintRender(context, g, r3.x, r3.y, r3.width, r3.height,
- endImage, info.getGapEndInsets(), COMPONENT_ALL,
- true, false, false, false, null);
- }
- }
- }
-
- /**
- * Paints the image and overlay image from the passed in style.
- *
- * @param g Graphics object to paint to
- * @param x X origin
- * @param y Y origin
- * @param w Width to draw to
- * @param h Height to draw to
- * @param drawCenter Whether the center of the image should be drawn
- * @param info Used to fetch image, insets and overlay image from
- */
- private boolean paintSimpleImage(SynthContext context, Graphics g, int x, int y,
- int w, int h, boolean drawCenter, BlueprintStyle.Info info) {
- if (info != null) {
- Rectangle clip = g.getClipBounds();
- _clipX1 = clip.x;
- _clipY1 = clip.y;
- _clipX2 = _clipX1 + clip.width;
- _clipY2 = _clipY1 + clip.height;
- themeBlueprintRender(context, g, x, y, w, h, info.getImage(),
- info.getImageInsets(), drawCenter ? COMPONENT_ALL :
- COMPONENT_ALL | COMPONENT_CENTER, info.getStretch(),
- false, info.isBkgMask(), info.isRecolorable(),
- info.getColorizeColor());
- if (drawCenter) {
- themeBlueprintRender(context, g, x, y, w, h,
- info.getOverlayImage(), info.getOverlayInsets(),
- COMPONENT_ALL, info.getOverlayStretch(), true,
- false, false, null);
- }
- return true;
- }
- return false;
- }
-
- /**
- * Paints the image in the specified region.
- *
- * @param g Graphics object to paint to
- * @param x X origin
- * @param y Y origin
- * @param w Width to draw to
- * @param h Height to draw to
- * @param image Image to render
- * @param insets Insets used to determine portion of image that is fixed.
- * @param componentMask Mask defining the areas of the image to draw.
- * @param stretch Stretch the image to fit the drawing area.
- * @param center Centers the image to the middle of the drawing area.
- * @param isBkgMask Whether or not the image is a background mask.
- * @param isRecolorable If the image is recolorable.
- * @param colorizeColor Color to use if image is recolorable.
- */
- private void themeBlueprintRender(SynthContext context, Graphics g,
- int x, int y, int w, int h, Image image,
- Insets insets, int componentMask,
- boolean stretch, boolean center,
- boolean isBkgMask, boolean isRecolorable,
- Color colorizeColor) {
- if (image == null) {
- return;
- }
- if (insets == null) {
- insets = GTKPainter.EMPTY_INSETS;
- }
- int iw = image.getWidth(null);
- int ih = image.getHeight(null);
-
- if (isBkgMask) {
- // Colorize mask using the colorizeColor from info.
- BufferedImage i = new BufferedImage(iw, ih,
- BufferedImage.TYPE_INT_ARGB);
- Graphics2D g3 = i.createGraphics();
-
- boolean topParentReached = false;
- int steps = 0;
-
- Component compParent = context.getComponent();
-
- while (!topParentReached && steps <= 2) {
- compParent = compParent.getParent ();
- steps ++;
-
- if (compParent != null) {
- Color color = compParent.getBackground ();
- if (color != null) {
- if (!color.equals (colorizeColor) &&
- !color.equals (Color.black) &&
- !(compParent instanceof JFileChooser)) {
- colorizeColor = color;
- topParentReached = true;
- }
- }
- } else {
- topParentReached = true;
- }
- }
-
- if (colorizeColor == null) {
- colorizeColor = ((GTKStyle)context.getStyle()).
- getGTKColor(context.getComponent(), context.getRegion(),
- context.getComponentState(),
- ColorType.BACKGROUND);
- }
- g3.setColor(colorizeColor);
- g3.fillRect(0, 0, iw, ih);
- g3.setComposite(AlphaComposite.DstIn);
- g3.drawImage(image, 0, 0, null);
- g3.dispose();
- image = i;
- } else if (isRecolorable) {
- // Create a copy of the image to manipulate the pixels.
- BufferedImage i = new BufferedImage(iw, ih,
- BufferedImage.TYPE_INT_ARGB);
- Graphics2D g3 = i.createGraphics();
- g3.setComposite(AlphaComposite.Src);
- g3.drawImage(image, 0, 0, null);
- g3.dispose();
-
- int red = colorizeColor.getRed();
- int green = colorizeColor.getGreen();
- int blue = colorizeColor.getBlue();
- int alpha = colorizeColor.getAlpha();
-
- Color color = RGBtoHLS(red, green, blue);
-
- int hue = color.getRed();
- int lum = color.getGreen();
- int sat = color.getBlue();
-
- int[] pixels = null;
- // Get the pixel data from the image.
- pixels = i.getRaster().getPixels(0, 0, iw, ih, pixels);
-
- // Colorize the pixels.
- for (int index = 0; index < pixels.length; index+=4) {
- red = pixels[index];
- green = pixels[index + 1];
- blue = pixels[index + 2];
-
- color = RGBtoHLS(red, green, blue);
- red = hue;
- green = color.getGreen();
- blue = sat;
-
- color = HLStoRGB(red, green, blue);
-
- pixels[index] = color.getRed();
- pixels[index + 1] = color.getGreen();
- pixels[index + 2] = color.getBlue();
- pixels[index + 3] = Math.min(
- pixels[index + 3], alpha);
- }
- // Set the pixel data for the image.
- i.getRaster().setPixels(0, 0, iw, ih, pixels);
- image = i;
- }
-
- if (stretch) {
- // themeBlueprintComputeHints();
- }
-
- if (iw <= 0 || ih <= 0) {
- return;
- }
- Object lastHint;
- Object renderingHint = RENDERING_HINT;
-
- if (renderingHint != null && stretch) {
- Graphics2D g2 = (Graphics2D)g;
-
- lastHint = g2.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
- if (lastHint == null) {
- lastHint = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
- }
- g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- renderingHint);
- }
- else {
- lastHint = null;
- }
-
- if (!stretch) {
- if (center) {
- /* Center the image. */
- blueprintRender(image, g, 0, 0, iw, ih, x + (w / 2) - (iw / 2),
- y + (h / 2) - (ih / 2), iw, ih);
- }
- else {
- /* Tile the image. */
- int lastIY = 0;
- for (int yCounter = y, maxY = y + h; yCounter < maxY;
- yCounter += (ih - lastIY), lastIY = 0) {
- int lastIX = 0;
- for (int xCounter = x, maxX = x + w; xCounter < maxX;
- xCounter += (iw - lastIX), lastIX = 0) {
- int dx2 = Math.min(maxX, xCounter + iw - lastIX);
- int dy2 = Math.min(maxY, yCounter + ih - lastIY);
- if (intersectsClip(xCounter, yCounter, dx2, dy2)) {
- g.drawImage(image, xCounter, yCounter, dx2, dy2,
- lastIX, lastIY, lastIX + dx2 -xCounter,
- lastIY + dy2 - yCounter, null);
- }
- }
- }
- }
- }
- else {
- int srcX[] = new int[4];
- int srcY[] = new int[4];
- int destX[] = new int[4];
- int destY[] = new int[4];
-
- srcX[0] = 0;
- srcX[1] = insets.left;
- srcX[2] = iw - insets.right;
- srcX[3] = iw;
-
- srcY[0] = 0;
- srcY[1] = insets.top;
- srcY[2] = ih - insets.bottom;
- srcY[3] = ih;
-
- destX[0] = x;
- destX[1] = x + insets.left;
- destX[2] = x + w - insets.right;
- destX[3] = x + w;
-
- destY[0] = y;
- destY[1] = y + insets.top;
- destY[2] = y + h - insets.bottom;
- destY[3] = y + h;
-
- /* Scale the image. */
- if ((componentMask & COMPONENT_ALL) != 0) {
- componentMask = (COMPONENT_ALL - 1) & ~componentMask;
- }
-
- // top left
- if ((componentMask & COMPONENT_NORTH_WEST) != 0) {
- blueprintRender(image, g,
- srcX[0], srcY[0],
- srcX[1] - srcX[0], srcY[1] - srcY[0],
- destX[0], destY[0],
- destX[1] - destX[0], destY[1] - destY[0]);
- }
- // top
- if ((componentMask & COMPONENT_NORTH) != 0) {
- blueprintRender(image, g,
- srcX[1], srcY[0],
- srcX[2] - srcX[1], srcY[1] - srcY[0],
- destX[1], destY[0],
- destX[2] - destX[1], destY[1] - destY[0]);
- }
- // top right
- if ((componentMask & COMPONENT_NORTH_EAST) != 0) {
- blueprintRender(image, g,
- srcX[2], srcY[0],
- srcX[3] - srcX[2], srcY[1] - srcY[0],
- destX[2], destY[0],
- destX[3] - destX[2], destY[1] - destY[0]);
- }
- // left
- if ((componentMask & COMPONENT_WEST) != 0) {
- blueprintRender(image, g,
- srcX[0], srcY[1],
- srcX[1] - srcX[0], srcY[2] - srcY[1],
- destX[0], destY[1],
- destX[1] - destX[0], destY[2] - destY[1]);
- }
- // center
- if ((componentMask & COMPONENT_CENTER) != 0) {
- blueprintRender(image, g,
- srcX[1], srcY[1],
- srcX[2] - srcX[1], srcY[2] - srcY[1],
- destX[1], destY[1],
- destX[2] - destX[1], destY[2] - destY[1]);
- }
- // right
- if ((componentMask & COMPONENT_EAST) != 0) {
- blueprintRender(image, g,
- srcX[2], srcY[1],
- srcX[3] - srcX[2], srcY[2] - srcY[1],
- destX[2], destY[1],
- destX[3] - destX[2], destY[2] - destY[1]);
- }
- // bottom left
- if ((componentMask & COMPONENT_SOUTH_WEST) != 0) {
- blueprintRender(image, g,
- srcX[0], srcY[2],
- srcX[1] - srcX[0], srcY[3] - srcY[2],
- destX[0], destY[2],
- destX[1] - destX[0], destY[3] - destY[2]);
- }
- // bottom
- if ((componentMask & COMPONENT_SOUTH) != 0) {
- blueprintRender(image, g,
- srcX[1], srcY[2],
- srcX[2] - srcX[1], srcY[3] - srcY[2],
- destX[1], destY[2],
- destX[2] - destX[1], destY[3] - destY[2]);
- }
- // bottom right
- if ((componentMask & COMPONENT_SOUTH_EAST) != 0) {
- blueprintRender(image, g,
- srcX[2], srcY[2],
- srcX[3] - srcX[2], srcY[3] - srcY[2],
- destX[2], destY[2],
- destX[3] - destX[2], destY[3] - destY[2]);
- }
- }
-
- if (lastHint != null) {
- ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- lastHint);
- }
- }
-
- /**
- * Draws a portion of an image stretched.
- *
- * @param image Image to render.
- * @param g Graphics to render to
- * @param srcX X origin to draw from
- * @param srxY Y origin to draw from
- * @param srcWidth Width of source
- * @param srcHeight Height of source
- * @param destX X origin to draw to
- * @param destY Y origin to draw to
- * @param destWidth Width of destination
- * @param destHeight Height of destination
- */
- private void blueprintRender(Image image, Graphics g,
- int srcX, int srcY, int srcWidth, int srcHeight,
- int destX, int destY, int destWidth, int destHeight) {
- if (destWidth <= 0 || destHeight <= 0 ||
- !intersectsClip(destX, destY,
- destX + destWidth, destY + destHeight)) {
- // Bogus location, nothing to paint
- return;
- }
-
- if (srcWidth == 0 && srcHeight == 0) {
- // Paint bilinear gradient.
- } else if (srcHeight == 0 && destHeight == srcHeight) {
- // Paint horizontal gradient.
- } else if (srcHeight == 0 && destWidth == srcWidth) {
- // Paint vertical gradient.
- }
-
- g.drawImage(image, destX, destY, destX + destWidth, destY + destHeight,
- srcX, srcY, srcX + srcWidth, srcY + srcHeight, null);
- }
-
- private boolean hasAncestorOfTypeFromList(JComponent c, ArrayList list) {
- if (list == null) {
- return false;
- }
-
- Iterator itr = list.iterator();
- while (itr.hasNext()) {
- if (hasAncestorOfType(c, (String)itr.next())) {
- return true;
- }
- }
- return false;
- }
-
- private boolean hasAncestorOfType(JComponent c, String parentType) {
- String type = null;
- while (c != null) {
- type = getComponentType(c);
- if (type == parentType) {
- return true;
- }
- if (c.getParent() instanceof JComponent) {
- c = (JComponent)c.getParent();
- } else {
- c = null;
- }
- }
- return false;
- }
-
- private String getComponentType(JComponent c) {
- return GTKStyleFactory.gtkClassFor(SynthLookAndFeel.getRegion(c));
- }
-
- private SynthStyle getStyle(JComponent c, ComponentUI ui) {
- if (ui instanceof SynthUI) {
- SynthContext parentContext = ((SynthUI)ui).getContext(c);
- // Note that we don't dispose of the context here, while this
- // isn't good, it just means we won't be recycling as often as
- // we can.
- return parentContext.getStyle();
- }
- return null;
- }
-
- /**
- * Returns true if the passed in region intersects the clip.
- */
- private boolean intersectsClip(int x1, int y1, int x2, int y2) {
- return ((x2 < x1 || x2 > _clipX1) &&
- (y2 < y1 || y2 > _clipY1) &&
- (_clipX2 < _clipX1 || _clipX2 > x1) &&
- (_clipY2 < _clipY1 || _clipY2 > y1));
- }
-
- /**
- * Convert RGB to HLS.
- *
- * @param r Red
- * @param g Green
- * @param b Blue
- * @return Color Where red = hue, green = lightness and blue = saturation.
- */
- private Color RGBtoHLS(int r, int g, int b) {
- int h, l, s;
- int min, max;
- int delta;
-
- if (r > g) {
- max = Math.max(r, b);
- min = Math.min(g, b);
- } else {
- max = Math.max(g, b);
- min = Math.min(r, b);
- }
-
- l = (max + min) / 2;
-
- if (max == min) {
- s = 0;
- h = 0;
- } else {
- delta = (max - min);
-
- if (l < 128) {
- s = 255 * delta / (max + min);
- } else {
- s = 255 * delta / (511 - max - min);
- }
-
- if (r == max) {
- h = (g - b) / delta;
- } else if (g == max) {
- h = 2 + (b - r) / delta;
- } else {
- h = 4 + (r - g) / delta;
- }
-
- h = (int)(h * 42.5);
-
- if (h < 0) {
- h+= 255;
- } else if (h > 255) {
- h -= 255;
- }
- }
-
- return new Color(h, l, s);
- }
-
- /**
- * Convert HLS to RGB.
- *
- * @param hue Hue
- * @param lightness Lightness
- * @param saturation Saturation
- * @return Color Resulting RGB color.
- */
- private Color HLStoRGB(int hue, int lightness, int saturation) {
- double h = hue;
- double l = lightness;
- double s = saturation;
- double m1, m2;
-
- if (s == 0) {
- hue = lightness;
- saturation = lightness;
- } else {
- if (l < 128) {
- m2 = (l * (255 + s)) / 65025.0;
- } else {
- m2 = (l + s - (l * s) / 255.0) / 255.0;
- }
- m1 = (l / 127.5) - m2;
-
- hue = HLSvalue(m1, m2, h + 85);
- lightness = HLSvalue(m1, m2, h);
- saturation = HLSvalue(m1, m2, h - 85);
- }
- return new Color(hue, lightness, saturation);
- }
-
- private int HLSvalue(double n1, double n2, double hue) {
- double value;
-
- if (hue > 255) {
- hue -= 255;
- } else if (hue < 0) {
- hue += 255;
- }
-
- if (hue < 42.5) {
- value = n1 + (n2 - n1) * (hue / 42.5);
- } else if (hue < 127.5) {
- value = n2;
- } else if (hue < 170) {
- value = n1 + (n2 - n1) * ((170 - hue) / 42.5);
- } else {
- value = n1;
- }
-
- return (int)(value * 255);
- }
- }