// // $Id: CssLength.java,v 1.9 2012/02/09 17:36:33 ylafon Exp $ // From Philippe Le Hegaret (Philippe.Le_Hegaret@sophia.inria.fr) // Updated September 25th 2000 Sijtsche de Jong (sy.de.jong@let.rug.nl) // // (c) COPYRIGHT MIT and INRIA, 1997. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.values; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import java.math.BigDecimal; /** *

*    Length units *

*

* The format of a length value is an optional sign character ('+' or '-', with * '+' being the default) immediately followed by a number (with or without * a decimal point) immediately followed by a unit identifier (a two-letter * abbreviation). After a '0' number, the unit identifier is optional. *

* Some properties allow negative length units, but this may complicate the * formatting model and there may be implementation-specific limits. If a negative * length value cannot be supported, it should be clipped to the nearest value * that can be supported. *

* There are two types of length units: relative and absolute. Relative units * specify a length relative to another length property. Style sheets that use * relative units will more easily scale from one medium to another (e.g. from * a computer display to a laser printer). Percentage * units (described below) and keyword values (e.g. 'x-large') offer similar * advantages. *

* These relative units are supported: *

 * H1 { margin: 0.5em }      /* ems, the height of the element's font * /
 * H1 { margin: 1ex }        /* x-height, ~ the height of the letter 'x' * /
 * P  { font-size: 12px }    /* pixels, relative to canvas * /
 * P  { layout-grid: strict both 20 pt 15 pt; margin 1gd 3gd 1gd 2gd } /* grid units * /
 * 
*

* The relative units 'em' and 'ex' are relative to the font size of the element * itself. The only exception to this rule in CSS1 is the 'font-size' property * where 'em' and 'ex' values refer to the font size of the parent element. *

* The existence of a grid in an element makes it possible and very useful to express various * measurements in that element in terms of grid units. Grid units are used very frequently * in East Asian typography, especially for the left, right, top and bottom element margins. * Therefore a new length unit is necessary: gd to enable the author to specify the various * measurements in terms of the grid. *

* Pixel units, as used in the last rule, are relative to the resolution of * the canvas, i.e. most often a computer display. If the pixel density of the * output device is very different from that of a typical computer display, * the UA should rescale pixel values. The suggested reference pixel * is the visual angle of one pixel on a device with a pixel density of 90dpi * and a distance from the reader of an arm's length. For a nominal arm's length * of 28 inches, the visual angle is about 0.0227 degrees. *

* Child elements inherit the computed value, not the relative value: *

 * BODY {
 * font-size: 12pt;
 * text-indent: 3em;  /* i.e. 36pt * /
 * }
 * H1 { font-size: 15pt }
 * 
*

* In the example above, the 'text-indent' value of 'H1' elements will be 36pt, * not 45pt. *

* Absolute length units are only useful when the physical properties of the * output medium are known. These absolute units are supported: *

 * H1 { margin: 0.5in }      /* inches, 1in = 2.54cm * /
 * H2 { line-height: 3cm }   /* centimeters * /
 * H3 { word-spacing: 4mm }  /* millimeters * /
 * H4 { font-size: 12pt }    /* points, 1pt = 1/72 in * /
 * H4 { font-size: 1pc }     /* picas, 1pc = 12pt * /
 * 
*

* In cases where the specified length cannot be supported, UAs should try to * approximate. For all CSS1 properties, further computations and inheritance * should be based on the approximated value. * * @version $Revision: 1.9 $ * @see CssPercentage */ public class CssLength extends CssValue { public static final int type = CssTypes.CSS_LENGTH; public final int getType() { return type; } private BigDecimal value; private int unit; private static String[] units = {"mm", "cm", "pt", "pc", "em", "ex", "px", "in", "gd"}; private static int[] hash_units; static { hash_units = new int[units.length]; for (int i = 0; i < units.length; i++) hash_units[i] = units[i].hashCode(); } /** * Create a new CssLength */ public CssLength() { value = BigDecimal.ZERO; } /** * Set the value of this length. * * @param s the string representation of the length. * @throws InvalidParamException The unit is incorrect */ public void set(String s, ApplContext ac) throws InvalidParamException { s = s.toLowerCase(); int length = s.length(); String unit = s.substring(length - 2, length); this.value = new BigDecimal(s.substring(0, length - 2)); this.unit = 2; // there is no unit by default if (unit.equals("gd") && (cssversion.equals("css2"))) { throw new InvalidParamException("unit", unit, ac); } if (value.floatValue() != 0) { int hash = unit.hashCode(); int i = 0; while (i < units.length) { if (hash == hash_units[i]) { this.unit = i; return; } i++; } } else { return; } throw new InvalidParamException("unit", unit, ac); } /** * Returns the current value */ public Object get() { // TODO this is old ugly crap, needed for not breaking everything // remove as soon as reference to get is removed... return new Float(value.floatValue()); } /** * return the float value */ public float floatValue() { return value.floatValue(); } /** * Returns true is the value is positive of null * * @return a boolean */ public boolean isPositive() { return (value.signum() >= 0); } /** * Returns true is the value is positive of null * * @return a boolean */ public boolean isStrictlyPositive() { return (value.signum() == 1); } /** * Returns true is the value is zero * * @return a boolean */ public boolean isZero() { return BigDecimal.ZERO.equals(value); } /** * Returns the current value */ public String getUnit() { return units[unit]; } /** * Returns a string representation of the object. */ public String toString() { if (BigDecimal.ZERO.equals(value)) { return value.toPlainString(); } return value.toPlainString() + getUnit(); } /** * Compares two values for equality. * * @param value The other value. */ public boolean equals(Object value) { return (value instanceof CssLength && this.value.equals(((CssLength) value).value) && unit == ((CssLength) value).unit); } }