/*
* $Id$
*
* Copyright (c) 2005 by Rodney Kinney, Brent Easton
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License (LGPL) as published by the Free Software Foundation.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, copies are available
* at http://www.opensource.org.
*/
package VASSAL.build.module.gamepieceimage;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import VASSAL.tools.image.ImageUtils;
public class Symbol {
protected static final String NATO = "NATO Unit Symbols";
protected static final String[] SYMBOL_SETS = new String[] { NATO };
// public static void draw(Graphics g, Rectangle r, Color fg, Color bg, String
// symbolSet, String symbolName) {
//
// if (symbolSet.equals(NATO_SIZE_SET)) {
//
// }
// else if (symbolSet.equals(NATO_UNIT_SET)) {
// NatoUnitSymbolSet.draw(g, r, fg, bg, symbolName);
// }
//
// }
protected String symbolSetName;
protected String symbolName1;
protected String symbolName2;
protected String symbolSize;
public Symbol(String setName, String name1, String name2, String size) {
symbolSetName = setName;
symbolName1 = name1;
symbolName2 = name2;
symbolSize = size;
}
public void draw(Graphics g, Rectangle bounds, Color fg, Color bg, Color sz, float lineWidth) {
if (symbolSetName.equals(NATO)) {
NatoUnitSymbolSet.draw(symbolName1, symbolName2, g, bounds, fg, bg, sz, lineWidth, symbolSize);
}
}
public static class NatoUnitSymbolSet {
protected static final String SZ_NONE = "None";
protected static final String SZ_INSTALLATION = "Installation";
protected static final String SZ_TEAM = "Team";
protected static final String SZ_SQUAD = "Squad";
protected static final String SZ_SECTION = "Section";
protected static final String SZ_PLATOON = "Platoon";
protected static final String SZ_ECHELON = "Echelon";
protected static final String SZ_COMPANY = "Company";
protected static final String SZ_BATTALION = "Battalion";
protected static final String SZ_REGIMENT = "Regiment";
protected static final String SZ_BRIGADE = "Brigade";
protected static final String SZ_DIVISION = "Division";
protected static final String SZ_CORPS = "Corps";
protected static final String SZ_ARMY = "Army";
protected static final String SZ_ARMY_GROUP = "Army Group";
protected static final String SZ_REGION = "Region";
protected static final String NONE = "None";
protected static final String AIRBORNE = "Airborne";
protected static final String AIR_DEFENCE = "Air Defence";
protected static final String AIR_FORCE = "Air Force";
// protected static final String AIR_MOBILE = "Air Mobile";
// protected static final String AMPHIBIOUS = "Amphibious";
protected static final String ANTI_TANK = "Anti Tank";
protected static final String ARMORED = "Armored";
protected static final String ARMY_AVIATION = "Army Aviation";
protected static final String ARTILLERY = "Artillery";
// protected static final String BRIDGING = "Bridging";
// protected static final String COMBAT_SERVICE_SUPPORT = "";
protected static final String COMMANDO = "Commando";
// protected static final String ELECTRONIC_RANGING = "";
// protected static final String ELECTRONIC_WARFARE = "";
protected static final String ENGINEERS = "Engineers";
protected static final String GLIDER = "Glider-Borne";
protected static final String GUERILLA = "Guerilla";
// protected static final String HEADQUARTERS_SUPPORT = "";
protected static final String INFANTRY = "Infantry";
// protected static final String LABOR_RESOURCES = "";
// protected static final String MAINTENANCE = "";
protected static final String MARINES = "Marines";
// protected static final String METEOROLOGICAL = "";
// protected static final String MILITARY_CIVIL = "";
// protected static final String MP = "";
// protected static final String MISSILE = "";
protected static final String MOUNTAIN = "Mountain";
protected static final String NAVY = "";
// protected static final String NBC = "";
// protected static final String ORDNANCE = "";
// protected static final String PARACHUTE = "";
// protected static final String PAY_FINANCE = "";
// protected static final String PERSONNEL = "";
// protected static final String PIPELINE = "";
// protected static final String POSTAL = "";
// protected static final String PSYCH = "";
// protected static final String QUARTERMASTER = "";
protected static final String RECON = "Cavalry/Recon";
// protected static final String REPLACEMENT = "";
// protected static final String SERVICE = "";
// protected static final String SIGNAL = "";
// protected static final String SOUND_RANGING = "";
// protected static final String SUPPLY = "";
// protected static final String TRANSPORT = "";
// protected static final String TOPO = "";
// protected static final String UNMANNED_AIR = "";
// protected static final String VET = "";
protected static final String INSTALLATION_SYMBOL = "m"; //$NON-NLS-1$
protected static final String TEAM_SYMBOL = "o"; //$NON-NLS-1$
protected static final String SQUAD_SYMBOL = "s"; //$NON-NLS-1$
protected static final String COMPANY_SYMBOL = "i"; //$NON-NLS-1$
protected static final String BRIGADE_SYMBOL = "x"; //$NON-NLS-1$
protected static final String[] getSymbolNames() {
return new String[] {
NONE,
INFANTRY,
RECON,
ARMORED,
ARTILLERY,
ENGINEERS,
AIRBORNE,
AIR_DEFENCE,
AIR_FORCE,
ANTI_TANK,
ARMY_AVIATION,
COMMANDO,
GLIDER,
GUERILLA,
//MARINES,
MOUNTAIN,
NAVY
};
}
protected static String[] sizeNames;
protected static String[] getSymbolSizes() {
if (sizeNames == null) {
sizeNames = new String[SIZES.length];
for (int i = 0; i < SIZES.length; i++) {
sizeNames[i] = SIZES[i].getName();
}
}
return sizeNames;
}
protected static SizeOption findSize(String name) {
for (int i = 0; i < SIZES.length; i++) {
if (name.equals(SIZES[i].getName())) {
return SIZES[i];
}
}
return SIZES[0];
}
protected static final SizeOption[] SIZES = new SizeOption[] {
new SizeOption(SZ_NONE, 0, ""), //$NON-NLS-1$
new SizeOption(SZ_INSTALLATION, 1, INSTALLATION_SYMBOL),
new SizeOption(SZ_TEAM, 1, TEAM_SYMBOL),
new SizeOption(SZ_SQUAD, 1, SQUAD_SYMBOL),
new SizeOption(SZ_SECTION, 2, SQUAD_SYMBOL),
new SizeOption(SZ_PLATOON, 3, SQUAD_SYMBOL),
new SizeOption(SZ_ECHELON, 4, SQUAD_SYMBOL),
new SizeOption(SZ_COMPANY, 1, COMPANY_SYMBOL),
new SizeOption(SZ_BATTALION, 2, COMPANY_SYMBOL),
new SizeOption(SZ_REGIMENT, 3, COMPANY_SYMBOL),
new SizeOption(SZ_BRIGADE, 1, BRIGADE_SYMBOL),
new SizeOption(SZ_DIVISION, 2, BRIGADE_SYMBOL),
new SizeOption(SZ_CORPS, 3, BRIGADE_SYMBOL),
new SizeOption(SZ_ARMY, 4, BRIGADE_SYMBOL),
new SizeOption(SZ_ARMY_GROUP, 5, BRIGADE_SYMBOL),
new SizeOption(SZ_REGION, 6, BRIGADE_SYMBOL)
};
protected static void draw(String name1, String name2, Graphics g, Rectangle bounds, Color fg, Color bg,
Color sz, float lineWidth, String size) {
if (bg != null) {
g.setColor(bg);
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
}
g.setColor(fg);
BasicStroke stroke = new BasicStroke(lineWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
Graphics2D g2 = ((Graphics2D) g);
g2.setStroke(stroke);
//g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
g.setColor(sz);
drawSize(g, size, bounds);
g.setColor(fg);
draw(g, lineWidth, name1, bounds, false);
draw(g, lineWidth, name2, bounds, true);
}
protected static void draw(Graphics g, float lineWidth, String name, Rectangle bounds, boolean drawLow) {
Graphics2D g2 = (Graphics2D) g;
BasicStroke stroke = new BasicStroke(lineWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g2.setStroke(stroke);
int x_left = bounds.x;
int x_center = bounds.x + bounds.width / 2 + 1;
int x_right = bounds.x + bounds.width;
int y_top = bounds.y;
int y_center = bounds.y + bounds.height / 2;
int y_bottom = bounds.y + bounds.height;
if (name.equals(NONE)) {
}
else if (name.equals(AIRBORNE)) {
int x1 = x_center - bounds.width / 4;
int y1 = y_top + bounds.height * 4 / 5 + 1;
g2.draw(new Arc2D.Double(x1, y1, bounds.width/4, bounds.height/4, 0,
180, Arc2D.OPEN));
g2.draw(new Arc2D.Double(x_center, y1, bounds.width/4, bounds.height/4, 0,
180, Arc2D.OPEN));
}
else if (name.equals(AIR_DEFENCE)) {
g2.draw(new Arc2D.Double(x_left, y_top+ bounds.height / 4, bounds.width, bounds.height*1.5, 0,
180, Arc2D.OPEN));
}
else if (name.equals(AIR_FORCE)) {
int xoff1 = (int) (bounds.width * 0.15);
int xoff2 = (int) (bounds.width * 0.2);
int yoff = (int) (bounds.height * 0.35);
g.drawLine(x_center-xoff2, y_top+yoff, x_center+xoff2, y_bottom-yoff);
g.drawLine(x_center+xoff2, y_top+yoff, x_center-xoff2, y_bottom-yoff);
g2.draw(new Arc2D.Double(x_center-xoff2-xoff1, y_top+yoff, xoff1*2, bounds.height-(2*yoff), 90, 180, Arc2D.OPEN));
g2.draw(new Arc2D.Double(x_center+xoff2-xoff1, y_top+yoff, xoff1*2, bounds.height-(2*yoff), 270, 180, Arc2D.OPEN));
}
else if (name.equals(ANTI_TANK)) {
g.drawLine(x_left, y_bottom, x_center, y_top);
g.drawLine(x_center, y_top, x_right, y_bottom);
}
else if (name.equals(ARMORED)) {
int yoff = (int) (bounds.height * .25);
int xoff1 = (int) (bounds.width * .15);
int xoff2 = (int) (bounds.width * .20);
g.drawLine(x_left+xoff1+xoff2, y_top+yoff, x_right-xoff1-xoff2, y_top+yoff);
g.drawLine(x_left+xoff1+xoff2, y_bottom-yoff, x_right-xoff1-xoff2, y_bottom-yoff);
g2.draw(new Arc2D.Double(x_left+xoff1, y_top+yoff, xoff2*2, bounds.height-(yoff*2), 90, 180, Arc2D.OPEN));
g2.draw(new Arc2D.Double(x_right-xoff1-(2*xoff2), y_top+yoff, xoff2*2, bounds.height-(yoff*2), 270, 180, Arc2D.OPEN));
}
else if (name.equals(ARMY_AVIATION)) {
int xoff = (int) (bounds.height * 0.25);
int yoff = (int) (bounds.height * 0.33);
GeneralPath p = new GeneralPath();
p.moveTo(x_left+xoff, y_top+yoff);
p.lineTo(x_right-yoff, y_bottom-yoff);
p.lineTo(x_right-yoff, y_top+yoff);
p.lineTo(x_left+xoff, y_bottom-yoff);
p.closePath();
g2.draw(p);
}
else if (name.equals(ARTILLERY)) {
int radius = bounds.height / 5;
int yoff = (drawLow ? (int) (bounds.height * .2) : 0);
g.fillOval(x_center - radius, y_center - radius + yoff, radius * 2, radius * 2);
}
else if (name.equals(COMMANDO)) {
g.drawLine(x_left, y_top, x_right, y_bottom);
g.drawLine(x_left, y_bottom, x_right, y_top);
int x1 = (int) (bounds.width / 2.5);
int y1 = (int) (bounds.height / 2.5);
GeneralPath p = new GeneralPath();
p.moveTo(x_left, y_top);
p.lineTo(x_left+x1, y_top);
p.lineTo(x_left+x1, y_top + y1);
p.lineTo(x_left, y_top);
p.moveTo(x_right, y_top);
p.lineTo(x_right-x1, y_top);
p.lineTo(x_right-x1, y_top + y1);
p.lineTo(x_right, y_top);
g2.fill(p);
}
else if (name.equals(ENGINEERS)) {
BasicStroke oldStroke = (BasicStroke) g2.getStroke();
BasicStroke estroke = new BasicStroke(oldStroke.getLineWidth() * 1.2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g2.setStroke(estroke);
int yh = (int) (bounds.height * 0.2);
int y1 = drawLow ? y_bottom - yh - 1 : y_top + (bounds.height - yh) / 2;
int y2 = y1 + yh;
int x1 = x_center - bounds.width / 5;
int x2 = x_center + bounds.width / 5;
GeneralPath p = new GeneralPath();
p.moveTo(x1, y2);
p.lineTo(x1, y1);
p.lineTo(x2, y1);
p.lineTo(x2, y2);
p.moveTo(x_center, y2);
p.lineTo(x_center, y1);
g2.draw(p);
}
else if (name.equals(GLIDER)) {
g.drawLine(x_left+(x_center-x_left)/3, y_center, x_right-(x_center-x_left)/3,y_center);
}
else if (name.equals(GUERILLA)) {
GeneralPath p = new GeneralPath();
p.moveTo(x_left, y_top);
p.lineTo(x_right, y_bottom);
p.lineTo(x_right, y_top);
p.lineTo(x_left, y_bottom);
p.lineTo(x_left, y_top);
g2.fill(p);
}
else if (name.equals(INFANTRY)) {
g.drawLine(x_left, y_top, x_right, y_bottom);
g.drawLine(x_left, y_bottom, x_right, y_top);
}
else if (name.equals(MARINES)) {
}
else if (name.equals(MOUNTAIN)) {
int x_off = bounds.width / 6;
GeneralPath p = new GeneralPath();
p.moveTo(x_center, y_center);
p.lineTo(x_center+x_off, y_bottom);
p.lineTo(x_center-x_off, y_bottom);
p.closePath();
g2.fill(p);
}
else if (name.equals(NAVY)) {
int yoff1 = (int) (bounds.height * 0.20);
int yoff2 = (int) (bounds.height * 0.15);
int xoff1 = (int) (bounds.width * 0.15);
int xoff2 = (int) (bounds.width * 0.30);
g.drawLine(x_center, y_top+yoff1, x_center, y_bottom-yoff1);
g.drawLine(x_center-xoff1, y_top+yoff1+yoff2, x_center+xoff1, y_top+yoff1+yoff2);
g2.draw(new Arc2D.Double(x_center-xoff2, y_top+yoff1, xoff2*2, bounds.height-(2*yoff1), 225, 90, Arc2D.OPEN));
}
else if (name.equals(RECON)) {
g.drawLine(bounds.x, bounds.y + bounds.height, bounds.x + bounds.width, bounds.y);
}
}
/**
*
* @param g Grahics
* @param size Name of size symbol
* @param bounds Size of the unit symbol
*/
protected static void drawSize(Graphics g, String size, Rectangle bounds) {
if (size.equals(SZ_NONE) || size.equals("")) { //$NON-NLS-1$
return;
}
SizeOption option = findSize(size);
String type = option.getType();
int count = option.getCount();
int sym_w;
int sym_h = bounds.height / 3;
if (count <= 4) {
sym_w = bounds.width / 5;
}
else {
sym_w = bounds.width / 7;
}
int gap = bounds.width / 15;
BufferedImage bi = buildSizeImage(g, count, type, sym_w, sym_h, gap);
int xpos = bounds.x + (bounds.width/2) - (bi.getWidth()/2) + gap; // + (gap/2) - (bi.getWidth()/2);
int ypos = bounds.y - sym_h - 1;
g.drawImage(bi, xpos, ypos , null);
}
public static BufferedImage buildSizeImage(String size, int sym_w, int sym_h, int gap) {
SizeOption option = findSize(size);
String type = option.getType();
int count = option.getCount();
BufferedImage bi = createImage(count, sym_w, sym_h, gap);
Graphics2D g = bi.createGraphics();
g.setBackground(null);
g.setColor(Color.BLACK);
return buildSizeImage(g, count, type, sym_w, sym_h, gap);
}
protected static BufferedImage createImage(int count, int sym_w, int sym_h, int gap) {
int w = sym_w * count + gap * (count-1)+1;
if (w < 1) w = sym_w;
return ImageUtils.createCompatibleTranslucentImage(w, sym_h+1);
}
public static BufferedImage buildSizeImage(Graphics g, int count, String type, int sym_w, int sym_h, int gap) {
Graphics2D g2 = (Graphics2D) g;
BufferedImage bi;
if (type.equals(INSTALLATION_SYMBOL)) {
bi = createImage(count, sym_w*3, sym_h, gap);
}
else {
bi = createImage(count, sym_w, sym_h, gap);
}
Graphics2D big = bi.createGraphics();
big.setColor(g2.getColor());
big.setBackground(null);
// Force Size symbol to be drawn 1 pixel wide with anti-aliasing to ensure readability
big.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
big.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int x_pos = 0;
for (int i = 0; i < count; i++) {
if (type.equals(TEAM_SYMBOL)) {
int radius = sym_w / 2;
big.drawOval(x_pos, sym_h/3, radius * 2, radius * 2);
big.drawLine(x_pos, sym_h, x_pos+sym_w, 0);
}
else if (type.equals(SQUAD_SYMBOL)) {
int radius = sym_w / 2;
big.fillOval(x_pos, sym_h/3, radius * 2, radius * 2);
}
else if (type.equals(COMPANY_SYMBOL)) {
big.drawLine(x_pos+sym_w/2, 0, x_pos+sym_w/2, sym_h);
}
else if (type.equals(BRIGADE_SYMBOL)) {
big.drawLine(x_pos, 0, x_pos+sym_w, sym_h);
big.drawLine(x_pos, sym_h, x_pos+sym_w, 0);
}
else if (type.equals(INSTALLATION_SYMBOL)) {
big.fillRect(x_pos, sym_h/2, x_pos+3*sym_w, sym_h);
}
x_pos += sym_w + gap;
}
big.dispose();
return bi;
}
}
}
class SizeOption {
String name;
String type;
int count;
public SizeOption (String n, int c, String t) {
name = n;
type = t;
count = c;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public int getCount() {
return count;
}
}