// License: GPL. For details, see LICENSE file. package symbols; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RectangularShape; import java.awt.geom.RoundRectangle2D; import java.util.ArrayList; /** * @author Malcolm Herring */ public final class Symbols { private Symbols() { // Hide default constructor for utilities classes } // CHECKSTYLE.OFF: LineLength public static final Color Yland = new Color(0xedbc0c); // public static final Color Bwater = new Color(0x78acd2); public static final Color Bwater = new Color(0x9bc5e3); public static final Color Gdries = new Color(0x689868); public static final Color Mline = new Color(0x9a6078); public static final Color Msymb = new Color(0xa30075); public static final Color Mtss = new Color(0xc0c480ff, true); public enum Form { BBOX, STRK, COLR, FILL, LINE, RECT, RRCT, ELPS, EARC, PLIN, PGON, RSHP, TEXT, SYMB, N1, N2, P1, P2, H2, H3, H4, H5, V2, V3, D2, D3, D4, B1, S2, S3, S4, C2, X2 } public enum Patt { Z, H, V, D, B, S, C, X } public enum Handle { CC, TL, TR, TC, LC, RC, BL, BR, BC } public static class Instr { public Form type; public Object params; public Instr(Form itype, Object iparams) { type = itype; params = iparams; } } public static class Delta { public Handle h; public AffineTransform t; public Delta(Handle ih, AffineTransform it) { h = ih; t = it; } public Delta(Handle ih) { h = ih; t = new AffineTransform(); } } public static class Scheme { public ArrayList<Patt> pat; public ArrayList<Color> col; public Scheme(ArrayList<Color> icol) { pat = new ArrayList<>(); col = icol; } public Scheme(ArrayList<Patt> ipat, ArrayList<Color> icol) { pat = ipat; col = icol; } public Scheme(Color icol) { pat = new ArrayList<>(); col = new ArrayList<>(); col.add(icol); } public Scheme() { pat = new ArrayList<>(); col = new ArrayList<>(); } } public static class Caption { public String string; public Font font; public Color colour; public Delta dd; public Caption(String istr, Font ifont, Color icolour, Delta idd) { string = istr; font = ifont; colour = icolour; dd = idd; } } public static class LineStyle { public Color line; public float width; public float[] dash; public Color fill; public LineStyle(Color ifill) { line = null; width = 0; dash = null; fill = ifill; } public LineStyle(Color iline, float iwidth) { line = iline; width = iwidth; dash = null; fill = null; } public LineStyle(Color iline, float iwidth, float[] idash) { line = iline; width = iwidth; dash = idash; fill = null; } public LineStyle(Color iline, float iwidth, Color ifill) { line = iline; width = iwidth; dash = null; fill = ifill; } public LineStyle(Color iline, float iwidth, float[] idash, Color ifill) { line = iline; width = iwidth; dash = idash; fill = ifill; } } public static class Symbol extends ArrayList<Instr> { public Symbol() { super(); } } public static class SubSymbol { public Symbol instr; public double scale; public double x; public double y; public Delta delta; public Scheme scheme; public SubSymbol(Symbol iinstr, double iscale, double ix, double iy, Scheme ischeme, Delta idelta) { instr = iinstr; scale = iscale; x = ix; y = iy; delta = idelta; scheme = ischeme; } } public static void drawSymbol(Graphics2D g2, Symbol symbol, double scale, double x, double y, Scheme cs, Delta dd) { int pn = 0; int cn = 0; Patt bpat = Patt.Z; Color bcol = null; g2.setPaint(Color.black); if (cs != null) { if ((cs.pat.size() > 0) && (cs.col.size() > 0) && (cs.pat.get(0) == Patt.B)) { bpat = (cs.pat.remove(0)); bcol = (cs.col.remove(0)); } pn = cs.pat.size(); cn = cs.col.size() - ((pn != 0) ? pn - 1 : 0); if ((pn == 0) && (cs.col.size() == 1)) { g2.setPaint(cs.col.get(0)); } } AffineTransform savetr = g2.getTransform(); g2.translate(x, y); g2.scale(scale, scale); if (symbol != null) { for (Instr item : symbol) { switch (item.type) { case BBOX: Rectangle2D.Double bbox = (Rectangle2D.Double) item.params; double dx = 0.0; double dy = 0.0; if (dd != null) { g2.transform(dd.t); switch (dd.h) { case CC: dx -= bbox.x + (bbox.width / 2.0); dy -= bbox.y + (bbox.height / 2.0); break; case TL: dx -= bbox.x; dy -= bbox.y; break; case TR: dx -= bbox.x + bbox.width; dy -= bbox.y; break; case TC: dx -= bbox.x + (bbox.width / 2.0); dy -= bbox.y; break; case LC: dx -= bbox.x; dy -= bbox.y + (bbox.height / 2.0); break; case RC: dx -= bbox.x + bbox.width; dy -= bbox.y + (bbox.height / 2.0); break; case BL: dx -= bbox.x; dy -= bbox.y + bbox.height; break; case BR: dx -= bbox.x + bbox.width; dy -= bbox.y + bbox.height; break; case BC: dx -= bbox.x + (bbox.width / 2.0); dy -= bbox.y + bbox.height; break; } g2.translate(dx, dy); } break; case COLR: if ((cs != null) && (cs.col != null)) { for (Instr patch : (Symbol) item.params) { switch (patch.type) { case N1: if (cn > 0) { Symbol s = (Symbol) patch.params; drawSymbol(g2, s, 1.0, 0, 0, new Scheme(cs.col.get(0)), null); } break; case N2: if (cn > 0) { Symbol s = (Symbol) patch.params; drawSymbol(g2, s, 1.0, 0, 0, new Scheme((cn > 1) ? cs.col.get(1) : cs.col.get(0)), null); } break; case P1: if (cn > 0) { g2.setPaint(cs.col.get(0)); g2.fill((Path2D.Double) patch.params); } break; case P2: if (cn > 0) { if (cn > 1) { g2.setPaint(cs.col.get(1)); } else { g2.setPaint(cs.col.get(0)); } g2.fill((Path2D.Double) patch.params); } break; case H2: if ((cn > 1) && (pn > 0) && (cs.pat.get(0) == Patt.H)) { g2.setPaint(cs.col.get(cs.col.size() - pn)); g2.fill((Path2D.Double) patch.params); } break; case H3: if ((cn == 3) && (pn > 0) && (cs.pat.get(0) == Patt.H)) { g2.setPaint(cs.col.get(1)); g2.fill((Path2D.Double) patch.params); } break; case H4: if ((cn == 4) && (pn > 0) && (cs.pat.get(0) == Patt.H)) { g2.setPaint(cs.col.get(1)); g2.fill((Path2D.Double) patch.params); } break; case H5: if ((cn == 4) && (pn > 0) && (cs.pat.get(0) == Patt.H)) { g2.setPaint(cs.col.get(2)); g2.fill((Path2D.Double) patch.params); } break; case V2: if ((cn > 1) && (pn > 0) && (cs.pat.get(0) == Patt.V)) { g2.setPaint(cs.col.get(cs.col.size() - pn)); g2.fill((Path2D.Double) patch.params); } break; case V3: if ((cn == 3) && (pn > 0) && (cs.pat.get(0) == Patt.V)) { g2.setPaint(cs.col.get(1)); g2.fill((Path2D.Double) patch.params); } break; case B1: if (bpat == Patt.B) { g2.setPaint(bcol); g2.fill((Path2D.Double) patch.params); } break; case S2: if ((cn > 1) && (pn > 0) && (cs.pat.get(0) == Patt.S)) { g2.setPaint(cs.col.get(1)); g2.fill((Path2D.Double) patch.params); } break; case S3: if ((cn > 2) && (pn > 0) && (cs.pat.get(0) == Patt.S)) { g2.setPaint(cs.col.get(2)); g2.fill((Path2D.Double) patch.params); } break; case S4: if ((cn == 4) && (pn > 0) && (cs.pat.get(0) == Patt.S)) { g2.setPaint(cs.col.get(3)); g2.fill((Path2D.Double) patch.params); } break; default: break; } } } break; case STRK: g2.setStroke((BasicStroke) item.params); break; case FILL: g2.setPaint((Color) item.params); break; case LINE: g2.draw((Line2D.Double) item.params); break; case RECT: g2.draw((Rectangle2D.Double) item.params); break; case RRCT: g2.draw((RoundRectangle2D.Double) item.params); break; case ELPS: g2.draw((Ellipse2D.Double) item.params); break; case EARC: g2.draw((Arc2D.Double) item.params); break; case PLIN: g2.draw((Path2D.Double) item.params); break; case PGON: g2.fill((Path2D.Double) item.params); break; case RSHP: g2.fill((RectangularShape) item.params); break; case SYMB: SubSymbol s = (SubSymbol) item.params; drawSymbol(g2, s.instr, s.scale, s.x, s.y, (s.scheme != null ? s.scheme : cs), s.delta); break; case TEXT: Caption c = (Caption) item.params; g2.setPaint(c.colour); TextLayout layout = new TextLayout(c.string, c.font, g2.getFontRenderContext()); Rectangle2D bb = layout.getBounds(); dx = 0; dy = 0; if (c.dd != null) { if (c.dd.t != null) g2.transform(c.dd.t); switch (c.dd.h) { case CC: dx -= bb.getX() + (bb.getWidth() / 2.0); dy -= bb.getY() + (bb.getHeight() / 2.0); break; case TL: dx -= bb.getX(); dy -= bb.getY(); break; case TR: dx -= bb.getX() + bb.getWidth(); dy -= bb.getY(); break; case TC: dx -= bb.getX() + (bb.getWidth() / 2.0); dy -= bb.getY(); break; case LC: dx -= bb.getX(); dy -= bb.getY() + (bb.getHeight() / 2.0); break; case RC: dx -= bb.getX() + bb.getWidth(); dy -= bb.getY() + (bb.getHeight() / 2.0); break; case BL: dx -= bb.getX(); dy -= bb.getY() + bb.getHeight(); break; case BR: dx -= bb.getX() + bb.getWidth(); dy -= bb.getY() + bb.getHeight(); break; case BC: dx -= bb.getX() + (bb.getWidth() / 2.0); dy -= bb.getY() + bb.getHeight(); break; } } layout.draw(g2, (float) dx, (float) dy); break; default: break; } } } g2.setTransform(savetr); } }