View Javadoc

1   package org.vectomatic.dom.svg.impl;
2   
3   import java.util.ArrayList;
4   import java.util.HashMap;
5   import java.util.List;
6   import java.util.Map;
7   
8   import org.vectomatic.dom.svg.OMCSSPrimitiveValue;
9   import org.vectomatic.dom.svg.OMCSSValue;
10  import org.vectomatic.dom.svg.OMCSSValueList;
11  import org.vectomatic.dom.svg.utils.SVGConstants;
12  
13  import com.gargoylesoftware.htmlunit.javascript.host.css.CSSPrimitiveValue;
14  import com.google.gwt.core.client.JavaScriptException;
15  import com.google.gwt.regexp.shared.MatchResult;
16  import com.google.gwt.regexp.shared.RegExp;
17  
18  /**
19   * Class to parse SVG dash arrays. Do not call this class directly,
20   * it will be removed when browser provide good native support for it.
21   * Following is the BNF grammar of the expression supported.
22   * <pre>
23   * dasharray ::= (length | percentage) (comma-wsp dasharray)?
24   * length ::= number (~"em" | ~"ex" | ~"px" | ~"in" | ~"cm" | ~"mm" | ~"pt" | ~"pc")?
25   * length ::= number ("em" | "ex" | "px" | "in" | "cm" | "mm" | "pt" | "pc" | "%")?
26   * number ::= integer | [+-]? [0-9]* "." [0-9]+
27   * </pre>
28   * @author laaglu
29   */
30  public class DashArrayParser {
31  	private static final String WS = "\\s*";
32  	private static final String COMMA = WS + "," + WS;
33  	private static final RegExp LENGTH = RegExp.compile("^[+-]?((?:0|[1-9][0-9]*)(?:\\.[0-9]+)?)(em|ex|px|in|cm|mm|pt|pc|%)?$", "i");
34  	public static final DashArrayParser INSTANCE = new DashArrayParser();
35  	private Map<String, Short> unitToPrimitiveType;
36  
37  	private DashArrayParser() {
38  		unitToPrimitiveType = new HashMap<String, Short>();
39  		unitToPrimitiveType.put("em", CSSPrimitiveValue.CSS_EMS);
40  		unitToPrimitiveType.put("ex", CSSPrimitiveValue.CSS_EXS);
41  		unitToPrimitiveType.put("px", CSSPrimitiveValue.CSS_PX);
42  		unitToPrimitiveType.put("in", CSSPrimitiveValue.CSS_IN);
43  		unitToPrimitiveType.put("cm", CSSPrimitiveValue.CSS_CM);
44  		unitToPrimitiveType.put("mm", CSSPrimitiveValue.CSS_MM);
45  		unitToPrimitiveType.put("pt", CSSPrimitiveValue.CSS_PT);
46  		unitToPrimitiveType.put("pc", CSSPrimitiveValue.CSS_PC);
47  		unitToPrimitiveType.put("%", CSSPrimitiveValue.CSS_PERCENTAGE);
48  	}
49  	
50  	public OMCSSValue parse(String cssText) {
51  		OMCSSValue[] values = null;
52  		if (SVGConstants.CSS_NONE_VALUE.equals(cssText) || cssText == null || cssText.length() == 0) {
53  			return new OMCSSPrimitiveValue(cssText, OMCSSPrimitiveValue.CSS_IDENT);
54  		} else if (SVGConstants.CSS_INHERIT_VALUE.equals(cssText)) {
55  			return new OMCSSPrimitiveValue(cssText, OMCSSPrimitiveValue.CSS_IDENT);
56  		}
57  		
58  		List<OMCSSPrimitiveValue> lengths = new ArrayList<OMCSSPrimitiveValue>();
59  		String[] lengthArray = cssText.split(COMMA);
60  		for (int i = 0; i < lengthArray.length; i++) {
61  			if (lengthArray[i].length() > 0) {
62  				LENGTH.setLastIndex(0);
63  				String length = lengthArray[i].trim();
64  				MatchResult result = LENGTH.exec(length);
65  				if (result != null && result.getGroupCount() == 3) {
66  					short primitiveType = CSSPrimitiveValue.CSS_NUMBER;
67  					String unit = result.getGroup(2);
68  					if (unit != null) {
69  						primitiveType = unitToPrimitiveType.get(unit.toLowerCase());
70  					}
71  					float value = Float.parseFloat(result.getGroup(1));
72  					lengths.add(new OMCSSPrimitiveValue(value, primitiveType));
73  				} else {
74  					throw new JavaScriptException("Invalid length spec: " + length);
75  				}
76  			}
77  		}
78  		values = lengths.toArray(new OMCSSValue[lengths.size()]);
79  		return new OMCSSValueList(values, cssText);
80  	}
81  
82  }