/* (C) 2001-2002, DIUF, http://www.unifr.ch/diuf * * 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 2 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, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package iiuf.xmillum; import iiuf.dom.DOMUtils; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Composite; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Stroke; import java.awt.Toolkit; import java.awt.font.TextAttribute; import java.util.HashMap; import java.util.Map; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * Style * * Represents a drawing style. * * @author $Author: ohitz $ * @version $Revision: 1.1 $ */ public class Style { static Map parameters = new HashMap(); boolean isFilled = false; boolean isXOR = false; boolean isHilight = false; Color foreground; Color background; Composite composite; String fontFamily = "helvetica"; Float fontSlope = TextAttribute.POSTURE_REGULAR; Float fontWeight = TextAttribute.WEIGHT_REGULAR; float fontSize = 8.0f; Boolean textDirection = TextAttribute.RUN_DIRECTION_LTR; Stroke stroke = new BasicStroke(1.0f); int resolution = 300; static { parameters.put("foreground", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; s.foreground = Color.getColor(v); if (s.foreground == null) { c.log("Color "+v+" not found, using red instead"); s.foreground = Color.red; } } }); parameters.put("background", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; s.background = Color.getColor(v); if (s.background == null) { c.log("Color "+v+" not found, using red instead"); s.background = Color.red; } } }); parameters.put("xor", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; if (trueFalse(v)) s.isXOR = true; } }); parameters.put("fill", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; if (trueFalse(v)) s.isFilled = true; } }); parameters.put("hilight", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; if (trueFalse(v)) s.isHilight = true; } }); parameters.put("transparency", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; float transparency = 0.0f; if (v != null) { try { transparency = Float.parseFloat(v); } catch (NumberFormatException n) { throw new ParameterException("Not a valid transparency value "+v); } if (transparency < 0.0f || transparency > 1.0f) { throw new ParameterException("Not a valid transparency value "+transparency); } } s.composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transparency); } }); parameters.put("fontfamily", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; s.fontFamily = v; } }); parameters.put("fontweight", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; if ("regular".equals(v)) { s.fontWeight = TextAttribute.WEIGHT_REGULAR; } else if ("medium".equals(v)) { s.fontWeight = TextAttribute.WEIGHT_MEDIUM; } else if ("bold".equals(v)) { s.fontWeight = TextAttribute.WEIGHT_BOLD; } else if ("extrabold".equals(v)) { s.fontWeight = TextAttribute.WEIGHT_EXTRABOLD; } else { throw new ParameterException("Unknown fontweight value "+v); } } }); parameters.put("fontslope", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; if ("upright".equals(v)) { s.fontSlope = TextAttribute.POSTURE_REGULAR; } else if ("slanted".equals(v)) { s.fontSlope = TextAttribute.POSTURE_OBLIQUE; } else { throw new ParameterException("Unknown fontslope value "+v); } } }); parameters.put("fontsize", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; try { s.fontSize = Float.parseFloat(v); } catch (NumberFormatException n) { throw new ParameterException("Not a valid fontsize value "+v); } } }); parameters.put("textdirection", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; if ("l2r".equals(v)) { s.textDirection = TextAttribute.RUN_DIRECTION_LTR; } else if ("r2l".equals(v)) { s.textDirection = TextAttribute.RUN_DIRECTION_RTL; } else { throw new ParameterException("Not a valid textdirection value "+v); } } }); parameters.put("resolution", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; try { s.resolution = Integer.parseInt(v); } catch (NumberFormatException n) { throw new ParameterException("Not a valid resolution value "+v); } } }); parameters.put("stroke-width", new Parameter() { public void setParam(BrowserContext c, Object o, String v) throws ParameterException { Style s = (Style) o; try { s.stroke = new BasicStroke(Float.parseFloat(v)); } catch (NumberFormatException n) { throw new ParameterException("Not a valid stroke-width value "+v); } } }); } /** * Creates a default style. */ public Style() { } /** * Creates a style with the specified XOR value */ public Style(boolean hl) { isHilight = hl; } /** * Creates a new style. * * @param context Current browser context * @param name Name of the style * @param e Element containing the style description */ public Style(BrowserContext context, String name, Element e) { Parameter.setParameters(context, e, this, parameters); } /** * Set style parameters on a graphics object. * * @param g Graphics object to update */ public void setStyle(Graphics2D g) { g.setStroke(getStroke()); if (isHilight()) { Color c = g.getColor(); g.setColor(getHilightColor(c)); c = g.getBackground(); g.setBackground(getHilightColor(c)); } else { Color c = getForeground(); if (c != null) g.setColor(c); c = getBackground(); if (c != null) g.setBackground(c); if (getComposite() != null) { g.setComposite(getComposite()); } else if (isXOR()) { g.setXORMode(Color.white); } else { g.setPaintMode(); } } } /** * Returns whether to hilight or not * * @return true for hilight, false otherwise */ public boolean isHilight() { return isHilight; } /** * Returns whether to fill areas or not. * * @return true for fill, false otherwise */ public boolean isFilled() { return isFilled; } /** * Returns whether to draw in XOR mode or not. * * @return true for XOR mode, false otherwise */ public boolean isXOR() { return isXOR; } /** * Returns the foreground color. * * @return foreground color or null */ public Color getForeground() { return foreground; } /** * Returns the background color. * * @return background color or null */ public Color getBackground() { return background; } /** * Returns the composite. * * @return composite or null if the composite is not changed */ public Composite getComposite() { return composite; } /** * Returns the stroke. * * @return composite or null if the composite is not changed */ public Stroke getStroke() { return stroke; } /** * Returns the font attributes for use in new Font(). * * @param scale The current zoom value (0 < scale) * @return font attributes */ public Map getFontAttributes(double scale) { HashMap fontAttributes = new HashMap(); fontAttributes.put(TextAttribute.FAMILY, fontFamily); fontAttributes.put(TextAttribute.WEIGHT, fontWeight); fontAttributes.put(TextAttribute.POSTURE, fontSlope); float rs = (float) resolution / (float) Toolkit.getDefaultToolkit().getScreenResolution(); float size = rs * (float) scale * fontSize; fontAttributes.put(TextAttribute.SIZE, new Float(size)); fontAttributes.put(TextAttribute.RUN_DIRECTION, textDirection); return fontAttributes; } /** Cache for already calculated colors */ static Map hilightColors = new HashMap(); /** * Calculates hilight colors. * * @param rgbColor Base color * @return "hilighted" version of rgbColor */ Color getHilightColor(Color rgbColor) { Color h = (Color) hilightColors.get(rgbColor); if (h == null) { float[] rgb = rgbColor.getRGBColorComponents(null); // Some implementations return values between 0 and 1, others between 0 and 255... // if (rgb[0] <= 1.0 && rgb[1] <= 1.0 && rgb[2] < 1.0) { // rgb[0] = rgb[0]*256; // rgb[1] = rgb[1]*256; // rgb[2] = rgb[2]*256; // } float[] hsb = Color.RGBtoHSB((int) rgb[0], (int) rgb[1], (int) rgb[2], null); h = Color.getHSBColor(hsb[0]+0.5F, hsb[1], Math.max(1.0F, hsb[2]*2)); hilightColors.put(rgbColor, h); } return h; } }