/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package forge.view.toolbox;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import forge.gui.GuiUtils;
import forge.view.SplashFrame;
/**
* Assembles settings from selected or default theme as appropriate. Saves in a
* hashtable, access using .get(settingName) method.
*
*/
public enum FSkin {
/** Singleton instance of skin. */
SINGLETON_INSTANCE;
/** */
public enum Backgrounds implements SkinProp { /** */
BG_SPLASH (null), /** */
BG_TEXTURE (null), /** */
BG_MATCH (null); /** */
private int[] coords;
/** @param xy int[] coordinates */
Backgrounds(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** */
public enum Colors implements SkinProp { /** */
CLR_THEME (new int[] {70, 10}), /** */
CLR_BORDERS (new int[] {70, 30}), /** */
CLR_ZEBRA (new int[] {70, 50}), /** */
CLR_HOVER (new int[] {70, 70}), /** */
CLR_ACTIVE (new int[] {70, 90}), /** */
CLR_INACTIVE (new int[] {70, 110}), /** */
CLR_TEXT (new int[] {70, 130}), /** */
CLR_PHASE_INACTIVE_ENABLED (new int[] {70, 150}), /** */
CLR_PHASE_INACTIVE_DISABLED (new int[] {70, 170}), /** */
CLR_PHASE_ACTIVE_ENABLED (new int[] {70, 190}), /** */
CLR_PHASE_ACTIVE_DISABLED (new int[] {70, 210}), /** */
CLR_THEME2 (new int[] {70, 230});
private int[] coords;
/** @param xy int[] coordinates */
Colors(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** int[] can hold [xcoord, ycoord, width, height, newwidth, newheight]. */
public enum ZoneImages implements SkinProp { /** */
ICO_HAND (new int[] {280, 40, 40, 40}), /** */
ICO_LIBRARY (new int[] {280, 0, 40, 40}), /** */
ICO_EXILE (new int[] {320, 40, 40, 40}), /** */
ICO_FLASHBACK (new int[] {280, 80, 40, 40}), /** */
ICO_GRAVEYARD (new int[] {320, 0, 40, 40}), /** */
ICO_POISON (new int[] {320, 80, 40, 40});
private int[] coords;
/** @param xy int[] coordinates */
ZoneImages(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** int[] can hold [xcoord, ycoord, width, height, newwidth, newheight]. */
public enum ManaImages implements SkinProp { /** */
IMG_BLACK (new int[] {360, 160, 40, 40}), /** */
IMG_RED (new int[] {400, 160, 40, 40}), /** */
IMG_COLORLESS (new int[] {440, 160, 40, 40}), /** */
IMG_BLUE (new int[] {360, 200, 40, 40}), /** */
IMG_GREEN (new int[] {400, 200, 40, 40}), /** */
IMG_WHITE (new int[] {440, 200, 40, 40}), /** */
IMG_2B (new int[] {360, 400, 40, 40}), /** */
IMG_2G (new int[] {400, 400, 40, 40}), /** */
IMG_2R (new int[] {440, 360, 40, 40}), /** */
IMG_2U (new int[] {440, 360, 40, 40}), /** */
IMG_2W (new int[] {400, 360, 40, 40}), /** */
IMG_BLACK_GREEN (new int[] {360, 240, 40, 40}), /** */
IMG_BLACK_RED (new int[] {400, 240, 40, 40}), /** */
IMG_GREEN_BLUE (new int[] {360, 280, 40, 40}), /** */
IMG_GREEN_WHITE (new int[] {440, 280, 40, 40}), /** */
IMG_RED_GREEN (new int[] {360, 320, 40, 40}), /** */
IMG_RED_WHITE (new int[] {400, 320, 40, 40}), /** */
IMG_BLUE_BLACK (new int[] {440, 240, 40, 40}), /** */
IMG_BLUE_RED (new int[] {440, 320, 40, 40}), /** */
IMG_WHITE_BLACK (new int[] {400, 280, 40, 40}), /** */
IMG_WHITE_BLUE (new int[] {360, 360, 40, 40}), /** */
IMG_PHRYX_BLUE (new int[] {320, 200, 40, 40}), /** */
IMG_PHRYX_WHITE (new int[] {320, 240, 40, 40}), /** */
IMG_PHRYX_RED (new int[] {320, 280, 40, 40}), /** */
IMG_PHRYX_GREEN (new int[] {320, 320, 40, 40}), /** */
IMG_PHRYX_BLACK (new int[] {320, 360, 40, 40});
private int[] coords;
/** @param xy int[] coordinates */
ManaImages(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** int[] can hold [xcoord, ycoord, width, height, newwidth, newheight]. */
public enum ColorlessManaImages implements SkinProp { /** */
IMG_0 (new int[] {640, 200, 20, 20}), /** */
IMG_1 (new int[] {660, 200, 20, 20}), /** */
IMG_2 (new int[] {640, 220, 20, 20}), /** */
IMG_3 (new int[] {660, 220, 20, 20}), /** */
IMG_4 (new int[] {640, 240, 20, 20}), /** */
IMG_5 (new int[] {660, 240, 20, 20}), /** */
IMG_6 (new int[] {640, 260, 20, 20}), /** */
IMG_7 (new int[] {660, 260, 20, 20}), /** */
IMG_8 (new int[] {640, 280, 20, 20}), /** */
IMG_9 (new int[] {660, 280, 20, 20}), /** */
IMG_10 (new int[] {640, 300, 20, 20}), /** */
IMG_11 (new int[] {660, 300, 20, 20}), /** */
IMG_12 (new int[] {640, 320, 20, 20}), /** */
IMG_15 (new int[] {660, 340, 20, 20}), /** */
IMG_16 (new int[] {640, 360, 20, 20}), /** */
IMG_20 (new int[] {640, 400, 20, 20}), /** */
IMG_X (new int[] {640, 420, 20, 20}), /** */
IMG_Y (new int[] {660, 420, 20, 20}), /** */
IMG_Z (new int[] {640, 440, 20, 20});
private int[] coords;
/** @param xy int[] coordinates */
ColorlessManaImages(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** int[] can hold [xcoord, ycoord, width, height, newwidth, newheight]. */
public enum GameplayImages implements SkinProp { /** */
IMG_SNOW (new int[] {320, 160, 40, 40}), /** */
IMG_TAP (new int[] {660, 440, 20, 20}), /** */
IMG_UNTAP (new int[] {640, 460, 20, 20}), /** */
IMG_SLASH (new int[] {660, 400, 10, 13}), /** */
IMG_ATTACK (new int[] {160, 320, 80, 80, 32, 32}), /** */
IMG_DEFEND (new int[] {160, 400, 80, 80, 32, 32}), /** */
IMG_SUMMONSICK (new int[] {240, 400, 80, 80, 32, 32}), /** */
IMG_PHASING (new int[] {240, 320, 80, 80, 32, 32}), /** */
IMG_COUNTERS1 (new int[] {0, 320, 80, 80}), /** */
IMG_COUNTERS2 (new int[] {0, 400, 80, 80}), /** */
IMG_COUNTERS3 (new int[] {80, 320, 80, 80}), /** */
IMG_COUNTERS_MULTI (new int[] {80, 400, 80, 80});
private int[] coords;
/** @param xy int[] coordinates */
GameplayImages(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** */
public enum Foils implements SkinProp { /** */
FOIL_01 (new int[] {0, 0, 400, 570}), /** */
FOIL_02 (new int[] {400, 0, 400, 570}), /** */
FOIL_03 (new int[] {0, 570, 400, 570}), /** */
FOIL_04 (new int[] {400, 570, 400, 570}), /** */
FOIL_05 (new int[] {0, 1140, 400, 570}), /** */
FOIL_06 (new int[] {400, 1140, 400, 570}), /** */
FOIL_07 (new int[] {0, 1710, 400, 570}), /** */
FOIL_08 (new int[] {400, 1710, 400, 570}), /** */
FOIL_09 (new int[] {0, 2280, 400, 570}), /** */
FOIL_10 (new int[] {400, 2280, 400, 570});
private int[] coords;
/** @param xy int[] coordinates */
Foils(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** */
public enum DockIcons implements SkinProp { /** */
ICO_SHORTCUTS (new int[] {160, 640, 80, 80}), /** */
ICO_SETTINGS (new int[] {80, 640, 80, 80}), /** */
ICO_ENDTURN (new int[] {320, 640, 80, 80}), /** */
ICO_CONCEDE (new int[] {240, 640, 80, 80}), /** */
ICO_DECKLIST (new int[] {400, 640, 80, 80});
private int[] coords;
/** @param xy int[] coordinates */
DockIcons(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** */
public enum QuestIcons implements SkinProp { /** */
ICO_ZEP (new int[] {0, 480, 80, 80}), /** */
ICO_GEAR (new int[] {80, 480, 80, 80}), /** */
ICO_GOLD (new int[] {160, 480, 80, 80}), /** */
ICO_ELIXER (new int[] {240, 480, 80, 80}), /** */
ICO_BOOK (new int[] {320, 480, 80, 80}), /** */
ICO_BOTTLES (new int[] {400, 480, 80, 80}), /** */
ICO_BOX (new int[] {480, 480, 80, 80}), /** */
ICO_COIN (new int[] {560, 480, 80, 80}), /** */
ICO_FOX (new int[] {0, 560, 80, 80}), /** */
ICO_LEAF (new int[] {80, 560, 80, 80}), /** */
ICO_LIFE (new int[] {160, 560, 80, 80}), /** */
ICO_COINSTACK (new int[] {240, 560, 80, 80}), /** */
ICO_MAP (new int[] {320, 560, 80, 80}), /** */
ICO_NOTES (new int[] {400, 560, 80, 80}), /** */
ICO_HEART (new int[] {480, 560, 80, 80}), /** */
ICO_BREW (new int[] {560, 560, 80, 80}), /** */
ICO_MINUS (new int[] {560, 640, 80, 80}), /** */
ICO_PLUS (new int[] {480, 640, 80, 80});
private int[] coords;
/** @param xy int[] coordinates */
QuestIcons(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** */
public enum ForgeIcons implements SkinProp { /** */
ICO_EDIT (new int[] {640, 500, 20, 20}), /** */
ICO_EDIT_OVER (new int[] {660, 500, 20, 20}), /** */
ICO_DELETE (new int[] {640, 480, 20, 20}), /** */
ICO_DELETE_OVER (new int[] {660, 480, 20, 20}), /** */
ICO_UNKNOWN (new int[] {80, 720, 80, 80}), /** */
ICO_LOGO (new int[] {480, 0, 200, 200}), /** */
ICO_DEFAULT_MAGE (new int[] {0, 720, 80, 80}), /** */
ICO_FAVICON (new int[] {0, 640, 80, 80});
private int[] coords;
/** @param xy int[] coordinates */
ForgeIcons(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** */
public enum ButtonImages implements SkinProp { /** */
IMG_BTN_START_UP (new int[] {480, 200, 160, 80}), /** */
IMG_BTN_START_OVER (new int[] {480, 280, 160, 80}), /** */
IMG_BTN_START_DOWN (new int[] {480, 360, 160, 80}), /** */
IMG_BTN_UP_LEFT (new int[] {80, 0, 40, 40}), /** */
IMG_BTN_UP_CENTER (new int[] {120, 0, 1, 40}), /** */
IMG_BTN_UP_RIGHT (new int[] {160, 0, 40, 40}), /** */
IMG_BTN_OVER_LEFT (new int[] {80, 40, 40, 40}), /** */
IMG_BTN_OVER_CENTER (new int[] {120, 40, 1, 40}), /** */
IMG_BTN_OVER_RIGHT (new int[] {160, 40, 40, 40}), /** */
IMG_BTN_DOWN_LEFT (new int[] {80, 80, 40, 40}), /** */
IMG_BTN_DOWN_CENTER (new int[] {120, 80, 1, 40}), /** */
IMG_BTN_DOWN_RIGHT (new int[] {160, 80, 40, 40}), /** */
IMG_BTN_FOCUS_LEFT (new int[] {80, 120, 40, 40}), /** */
IMG_BTN_FOCUS_CENTER (new int[] {120, 120, 1, 40}), /** */
IMG_BTN_FOCUS_RIGHT (new int[] {160, 120, 40, 40}), /** */
IMG_BTN_TOGGLE_LEFT (new int[] {80, 160, 40, 40}), /** */
IMG_BTN_TOGGLE_CENTER (new int[] {120, 160, 1, 40}), /** */
IMG_BTN_TOGGLE_RIGHT (new int[] {160, 160, 40, 40}), /** */
IMG_BTN_DISABLED_LEFT (new int[] {80, 200, 40, 40}), /** */
IMG_BTN_DISABLED_CENTER (new int[] {120, 200, 1, 40}), /** */
IMG_BTN_DISABLED_RIGHT (new int[] {160, 200, 40, 40});
private int[] coords;
/** @param xy int[] coordinates */
ButtonImages(int[] xy) { this.coords = xy; }
/** @return int[] */
public int[] getCoords() { return coords; }
}
/** Properties of various components that make up the skin.
* This interface allows all enums to be under the same roof.
* It also enforces a getter for coordinate locations in sprites. */
public interface SkinProp {
/** @return int[] */
int[] getCoords();
}
private static Map icons;
private static Map images;
private static Map colors;
private static Map plainFonts;
private static Map boldFonts;
private static Map italicFonts;
private static Map avatars;
private static final String
FILE_SKINS_DIR = "res/skins/",
FILE_ICON_SPRITE = "sprite_icons.png",
FILE_FOIL_SPRITE = "sprite_foils.png",
FILE_AVATAR_SPRITE = "sprite_avatars.png",
FILE_FONT = "font1.ttf",
FILE_SPLASH = "bg_splash.png",
FILE_MATCH_BG = "bg_match.jpg",
FILE_TEXTURE_BG = "bg_texture.jpg",
DEFAULT_DIR = FILE_SKINS_DIR + "default/";
private static String preferredDir;
private static String preferredName;
private static Font font;
private static BufferedImage bimDefaultSprite, bimPreferredSprite, bimFoils, bimAvatars;
private static int x0, y0, w0, h0, newW, newH, preferredW, preferredH;
private static int[] tempCoords;
/**
* FSkin constructor, using skin name. Generates custom skin settings,
* fonts, and backgrounds.
*
* @param skinName
* the skin name
*/
public static void loadLight(final String skinName) {
// No need for this method to be loaded while on the EDT.
GuiUtils.checkEDT("FSkin$constructor", false);
// Non-default (preferred) skin name and dir.
FSkin.preferredName = skinName.toLowerCase().replace(' ', '_');
FSkin.preferredDir = FILE_SKINS_DIR + preferredName + "/";
if (FSkin.icons != null) { FSkin.icons.clear(); }
if (FSkin.images != null) { FSkin.images.clear(); }
if (FSkin.colors != null) { FSkin.colors.clear(); }
FSkin.icons = new HashMap();
FSkin.images = new HashMap();
FSkin.colors = new HashMap();
final File f = new File(preferredDir + FILE_SPLASH);
if (!f.exists()) {
FSkin.loadLight("default");
}
else {
final BufferedImage img;
try {
img = ImageIO.read(f);
final int h = img.getHeight();
final int w = img.getWidth();
FSkin.setIcon(Backgrounds.BG_SPLASH, img.getSubimage(0, 0, w, h - 100));
UIManager.put("ProgressBar.background", FSkin.getColorFromPixel(img.getRGB(25, h - 75)));
UIManager.put("ProgressBar.selectionBackground", FSkin.getColorFromPixel(img.getRGB(75, h - 75)));
UIManager.put("ProgressBar.foreground", FSkin.getColorFromPixel(img.getRGB(25, h - 25)));
UIManager.put("ProgressBar.selectionForeground", FSkin.getColorFromPixel(img.getRGB(75, h - 25)));
UIManager.put("ProgressBar.border", new LineBorder(Color.BLACK, 0));
} catch (final IOException e) {
e.printStackTrace();
}
}
}
/**
* Loads two sprites: the default (which should be a complete
* collection of all symbols) and the preferred (which may be
* incomplete).
*
* Font must be present in the skin folder, and will not
* be replaced by default. The fonts are pre-derived
* in this method and saved in a HashMap for future access.
*
* Color swatches must be present in the preferred
* sprite, and will not be replaced by default.
*
* Background images must be present in skin folder,
* and will not be replaced by default.
*
* Icons, however, will be pulled from the two sprites. Obviously,
* preferred takes precedence over default, but if something is
* missing, the default picture is retrieved.
*/
public static void loadFull() {
// No need for this method to be loaded while on the EDT.
GuiUtils.checkEDT("FSkin$load", false);
// Preferred skin name must be called via loadLight() method,
// which does some cleanup and init work.
if (FSkin.preferredName.isEmpty()) { FSkin.loadLight("default"); }
// Everything OK?
final FProgressBar barProgress = SplashFrame.PROGRESS_BAR;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
barProgress.reset();
barProgress.setShowETA(false);
barProgress.setDescription("Processing image sprites: ");
}
});
// Grab and test various sprite files.
barProgress.setMaximum(4);
final File f1 = new File(DEFAULT_DIR + FILE_ICON_SPRITE);
final File f2 = new File(preferredDir + FILE_ICON_SPRITE);
final File f3 = new File(DEFAULT_DIR + FILE_FOIL_SPRITE);
final File f4 = new File(DEFAULT_DIR + FILE_AVATAR_SPRITE);
try {
bimDefaultSprite = ImageIO.read(f1);
barProgress.increment();
bimPreferredSprite = ImageIO.read(f2);
barProgress.increment();
bimFoils = ImageIO.read(f3);
barProgress.increment();
bimAvatars = ImageIO.read(f4);
barProgress.increment();
preferredH = bimPreferredSprite.getHeight();
preferredW = bimPreferredSprite.getWidth();
}
catch (Exception e) {
System.err.println("FSkin$loadFull: Missing a sprite (default icons, "
+ "preferred icons, or foils.");
e.printStackTrace();
}
// Pre-derive most fonts (plain, bold, and italic).
// Exceptions handled inside method.
FSkin.font = GuiUtils.newFont(FILE_SKINS_DIR + preferredName + "/" + FILE_FONT);
plainFonts = new HashMap();
boldFonts = new HashMap();
italicFonts = new HashMap();
for (int i = 10; i <= 22; i++) { setFont(i); }
for (int i = 10; i <= 20; i += 2) { setBoldFont(i); }
for (int i = 12; i <= 14; i += 2) { setItalicFont(i); }
// Put various images into map (except sprite and splash).
// Exceptions handled inside method.
FSkin.setIcon(Backgrounds.BG_TEXTURE, preferredDir + FILE_TEXTURE_BG);
FSkin.setIcon(Backgrounds.BG_MATCH, preferredDir + FILE_MATCH_BG);
// Run through enums and load their coords.
for (Colors e : Colors.values()) { FSkin.setColor(e); }
for (ZoneImages e : ZoneImages.values()) { FSkin.setImage(e); }
for (DockIcons e : DockIcons.values()) { FSkin.setIcon(e); }
for (ForgeIcons e : ForgeIcons.values()) { FSkin.setIcon(e); }
for (ButtonImages e : ButtonImages.values()) { FSkin.setIcon(e); }
for (QuestIcons e : QuestIcons.values()) { FSkin.setIcon(e); }
for (ManaImages e : ManaImages.values()) { FSkin.setImage(e); }
for (ColorlessManaImages e : ColorlessManaImages.values()) { FSkin.setImage(e); }
for (GameplayImages e : GameplayImages.values()) { FSkin.setImage(e); }
// Foils have a separate sprite, so uses a specific method.
for (Foils e : Foils.values()) { FSkin.setFoil(e); }
// Assemble avatar images
FSkin.assembleAvatars();
// Images loaded; can start UI init.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
barProgress.setShowETA(false);
barProgress.setShowCount(false);
barProgress.setDescription("Creating display components.");
}
});
// Clear references to buffered images
FSkin.bimDefaultSprite.flush();
FSkin.bimFoils.flush();
FSkin.bimPreferredSprite.flush();
FSkin.bimAvatars.flush();
FSkin.bimDefaultSprite = null;
FSkin.bimFoils = null;
FSkin.bimPreferredSprite = null;
FSkin.bimAvatars = null;
}
/** @return {@link java.awt.font} font */
public static Font getFont() {
return FSkin.font;
}
/**
* @param size - integer, pixel size
* @return {@link java.awt.font} font1
*/
public static Font getFont(int size) {
if (plainFonts.get(size) == null) {
plainFonts.put(size, getFont().deriveFont(Font.PLAIN, size));
}
return plainFonts.get(size);
}
/**
* @param size - integer, pixel size
* @return {@link java.awt.font} font1
*/
public static Font getBoldFont(int size) {
if (boldFonts.get(size) == null) {
boldFonts.put(size, getFont().deriveFont(Font.BOLD, size));
}
return boldFonts.get(size);
}
/**
* @param size - integer, pixel size
* @return {@link java.awt.font} font1
*/
public static Font getItalicFont(int size) {
if (boldFonts.get(size) == null) {
italicFonts.put(size, getFont().deriveFont(Font.ITALIC, size));
}
return italicFonts.get(size);
}
/**
* Gets the name.
*
* @return Name of the current skin.
*/
public static String getName() {
return FSkin.preferredName;
}
/**
* Gets an image.
*
* @param s0 SkinProp enum
* @return {@link java.awt.Image}
*/
public static Image getImage(final SkinProp s0) {
if (FSkin.images.get(s0) == null) {
throw new NullPointerException("Can't find an image for SkinProp " + s0);
}
return FSkin.images.get(s0);
}
/**
* Gets an icon.
*
* @param s0 SkinProp enum
* @return {@link javax.swing.ImageIcon}
*/
public static ImageIcon getIcon(final SkinProp s0) {
if (FSkin.icons.get(s0) == null) {
throw new NullPointerException("Can't find an icon for SkinProp " + s0);
}
return FSkin.icons.get(s0);
}
/**
* Gets a scaled version of an image from this skin's image map.
*
* @param s0
* String image enum
* @param w0
* int new width
* @param h0
* int new height
* @return {@link java.awt.Image}
*/
public static Image getImage(final SkinProp s0, int w0, int h0) {
w0 = (w0 < 1) ? 1 : w0;
h0 = (h0 < 1) ? 1 : h0;
final Image original = FSkin.images.get(s0);
final BufferedImage scaled = new BufferedImage(w0, h0, BufferedImage.TYPE_INT_ARGB);
final Graphics2D g2d = scaled.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(original, 0, 0, w0, h0, 0, 0, original.getWidth(null), original.getHeight(null), null);
g2d.dispose();
return scaled;
}
/**
* Retrieves a color from this skin's color map.
*
* @param s0 Skin property (from enum)
* @return Color
*/
public static Color getColor(final SkinProp s0) {
return colors.get(s0);
}
/**
* Gets the skins.
*
* @return the skins
*/
public static ArrayList getSkins() {
final ArrayList mySkins = new ArrayList();
File dir = new File(FILE_SKINS_DIR);
String[] children = dir.list();
if (children == null) {
System.err.println("FSkin > can't find skins directory!");
} else {
for (int i = 0; i < children.length; i++) {
if (children[i].equalsIgnoreCase(".svn")) { continue; }
if (children[i].equalsIgnoreCase(".DS_Store")) { continue; }
mySkins.add(children[i]);
}
}
return mySkins;
}
/** @return Map */
public static Map getAvatars() {
return avatars;
}
/**
*
* getColorFromPixel.
*
*
* @param {@link java.lang.Integer} pixel information
*/
private static Color getColorFromPixel(final int pixel) {
int r, g, b, a;
a = (pixel >> 24) & 0x000000ff;
r = (pixel >> 16) & 0x000000ff;
g = (pixel >> 8) & 0x000000ff;
b = (pixel) & 0x000000ff;
return new Color(r, g, b, a);
}
private static BufferedImage testPreferredSprite(SkinProp s0) {
tempCoords = s0.getCoords();
x0 = tempCoords[0];
y0 = tempCoords[1];
w0 = tempCoords[2];
h0 = tempCoords[3];
// Test if requested sub-image in inside bounds of preferred sprite.
// (Height and width of preferred sprite were set in loadFontAndImages.)
if (x0 > preferredW || x0 + w0 > preferredW
|| y0 > preferredH || y0 + h0 > preferredH) {
return bimDefaultSprite;
}
// Test if various points of requested sub-image are transparent.
// If any return true, image exists.
int x = 0, y = 0;
Color c;
// Center
x = (int) (x0 + w0 / 2);
y = (int) (y0 + h0 / 2);
c = FSkin.getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
x += 2;
y += 2;
c = FSkin.getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
x -= 4;
c = FSkin.getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
y -= 4;
c = FSkin.getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
x += 4;
c = FSkin.getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
return bimDefaultSprite;
}
private static void assembleAvatars() {
FSkin.avatars = new HashMap();
int counter = 0;
Color pxTest;
final int aw = bimAvatars.getWidth();
final int ah = bimAvatars.getHeight();
for (int j = 0; j < aw; j += 100) {
for (int i = 0; i < ah; i += 100) {
if (i == 0 && j == 0) { continue; }
pxTest = FSkin.getColorFromPixel(bimAvatars.getRGB(i + 50, j + 50));
if (pxTest.getAlpha() == 0) { continue; }
FSkin.avatars.put(counter++, bimAvatars.getSubimage(i, j, 100, 100));
}
}
}
private static void setFoil(final SkinProp s0) {
tempCoords = s0.getCoords();
x0 = tempCoords[0];
y0 = tempCoords[1];
w0 = tempCoords[2];
h0 = tempCoords[3];
FSkin.images.put(s0, bimFoils.getSubimage(x0, y0, w0, h0));
}
private static void setColor(final SkinProp s0) {
tempCoords = s0.getCoords();
x0 = tempCoords[0];
y0 = tempCoords[1];
FSkin.colors.put(s0, FSkin.getColorFromPixel(bimPreferredSprite.getRGB(x0, y0)));
}
private static void setFont(int size) {
plainFonts.put(size, font.deriveFont(Font.PLAIN, size));
}
private static void setBoldFont(int size) {
boldFonts.put(size, font.deriveFont(Font.BOLD, size));
}
private static void setItalicFont(int size) {
italicFonts.put(size, FSkin.font.deriveFont(Font.ITALIC, size));
}
private static void setIcon(final SkinProp s0) {
tempCoords = s0.getCoords();
x0 = tempCoords[0];
y0 = tempCoords[1];
w0 = tempCoords[2];
h0 = tempCoords[3];
BufferedImage img = testPreferredSprite(s0);
FSkin.icons.put(s0, new ImageIcon(img.getSubimage(x0, y0, w0, h0)));
}
/**
* Sets an icon in this skin's icon map from a file address.
* Throws IO exception for debugging if needed.
*
* @param s0
* Skin property (from enum)
* @param s1
* File address
*/
private static void setIcon(final SkinProp s0, final String s1) {
try {
final File file = new File(s1);
ImageIO.read(file);
} catch (IOException e) {
e.printStackTrace();
}
FSkin.icons.put(s0, new ImageIcon(s1));
}
/**
* Sets an icon in this skin's icon map from a buffered image.
*
* @param s0 Skin property (from enum)
* @param bi0 BufferedImage
*/
private static void setIcon(final SkinProp s0, final BufferedImage bi0) {
FSkin.icons.put(s0, new ImageIcon(bi0));
}
/**
* setImage, with auto-scaling assumed true.
*
* @param s0
*/
private static void setImage(final SkinProp s0) {
FSkin.setImage(s0, true);
}
/**
* Checks the preferred sprite for existence of a sub-image
* defined by X, Y, W, H.
*
* If an image is not present at those coordinates, default
* icon is substituted.
*
* The result is saved in a HashMap.
*
* @param s0 An address in the hashmap, derived from SkinProp enum
*/
private static void setImage(final SkinProp s0, boolean scale) {
tempCoords = s0.getCoords();
x0 = tempCoords[0];
y0 = tempCoords[1];
w0 = tempCoords[2];
h0 = tempCoords[3];
newW = (tempCoords.length == 6 ? tempCoords[4] : 0);
newH = (tempCoords.length == 6 ? tempCoords[5] : 0);
BufferedImage img = FSkin.testPreferredSprite(s0);
BufferedImage bi0 = img.getSubimage(x0, y0, w0, h0);
if (scale && newW != 0) {
FSkin.images.put(s0, bi0.getScaledInstance(newW, newH, Image.SCALE_AREA_AVERAGING));
}
else {
FSkin.images.put(s0, bi0);
}
}
}