// // $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; /** *
* 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);
}
}