1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.css;
16
17 import static org.htmlunit.css.CssStyleSheet.AUTO;
18
19 import java.util.regex.Pattern;
20
21 import org.apache.commons.lang3.math.NumberUtils;
22 import org.htmlunit.html.DomElement;
23 import org.htmlunit.html.DomNode;
24 import org.htmlunit.html.HtmlCanvas;
25 import org.htmlunit.html.HtmlHtml;
26
27
28
29
30
31
32 public final class CssPixelValueConverter {
33
34 private static final Pattern TO_FLOAT_PATTERN = Pattern.compile("(\\d+(?:\\.\\d+)?).*");
35
36
37
38
39 private CssPixelValueConverter() {
40
41 }
42
43
44
45
46
47
48
49
50
51
52 public static int pixelValue(final DomElement element, final CssValue value) {
53 final ComputedCssStyleDeclaration style =
54 element.getPage().getEnclosingWindow().getComputedStyle(element, null);
55 final String s = value.get(style);
56 return pixelValue(element, s, value, false);
57 }
58
59
60
61
62
63
64
65
66
67
68 public static String pixelString(final DomElement element, final CssValue value) {
69 final ComputedCssStyleDeclaration style =
70 element.getPage().getEnclosingWindow().getComputedStyle(element, null);
71 final String styleValue = value.get(style);
72 if (styleValue.endsWith("px")) {
73 return styleValue;
74 }
75 return pixelValue(element, styleValue, value, false) + "px";
76 }
77
78
79
80
81
82
83
84
85
86
87 public static int pixelValue(final String value) {
88 float i = NumberUtils.toFloat(TO_FLOAT_PATTERN.matcher(value).replaceAll("$1"), 0);
89 if (value.length() < 2) {
90 return Math.round(i);
91 }
92 if (value.endsWith("px")) {
93 return Math.round(i);
94 }
95
96 if (value.endsWith("em")) {
97 i = i * 16;
98 }
99 else if (value.endsWith("%")) {
100 i = i * 16 / 100;
101 }
102 else if (value.endsWith("ex")) {
103 i = i * 10;
104 }
105 else if (value.endsWith("in")) {
106 i = i * 150;
107 }
108 else if (value.endsWith("cm")) {
109 i = i * 50;
110 }
111 else if (value.endsWith("mm")) {
112 i = i * 5;
113 }
114 else if (value.endsWith("pt")) {
115 i = i * 2;
116 }
117 else if (value.endsWith("pc")) {
118 i = i * 24;
119 }
120 return Math.round(i);
121 }
122
123 private static int pixelValue(final DomElement element,
124 final String styleValue, final CssValue value, final boolean percentMode) {
125 if (styleValue.endsWith("%") || (styleValue.isEmpty() && element instanceof HtmlHtml)) {
126 final float i = NumberUtils.toFloat(TO_FLOAT_PATTERN.matcher(styleValue).replaceAll("$1"), 100);
127
128 final DomNode parent = element.getParentNode();
129 final int absoluteValue;
130 if (parent instanceof DomElement) {
131 final DomElement parentElem = (DomElement) parent;
132 final ComputedCssStyleDeclaration style =
133 parentElem.getPage().getEnclosingWindow().getComputedStyle(parentElem, null);
134 final String parentStyleValue = value.get(style);
135 absoluteValue = pixelValue((DomElement) parent, parentStyleValue, value, true);
136 }
137 else {
138 absoluteValue = value.getWindowDefaultValue();
139 }
140 return Math.round((i / 100f) * absoluteValue);
141 }
142 if (AUTO.equals(styleValue)) {
143 return value.getDefaultValue();
144 }
145 if (styleValue.isEmpty()) {
146 if (element instanceof HtmlCanvas) {
147 return value.getWindowDefaultValue();
148 }
149
150
151
152 if (percentMode) {
153 final DomNode parent = element.getParentNode();
154 if (parent == null || parent instanceof HtmlHtml) {
155 return value.getWindowDefaultValue();
156 }
157 final DomElement parentElem = (DomElement) parent;
158 final ComputedCssStyleDeclaration style =
159 parentElem.getPage().getEnclosingWindow().getComputedStyle(parentElem, null);
160 final String parentStyleValue = value.get(style);
161 return pixelValue(parentElem, parentStyleValue, value, true);
162 }
163
164 return 0;
165 }
166 return pixelValue(styleValue);
167 }
168
169
170
171
172 public abstract static class CssValue {
173 private final int defaultValue_;
174 private final int windowDefaultValue_;
175
176
177
178
179
180
181 public CssValue(final int defaultValue, final int windowDefaultValue) {
182 defaultValue_ = defaultValue;
183 windowDefaultValue_ = windowDefaultValue;
184 }
185
186
187
188
189
190 public int getDefaultValue() {
191 return defaultValue_;
192 }
193
194
195
196
197
198 public int getWindowDefaultValue() {
199 return windowDefaultValue_;
200 }
201
202
203
204
205
206
207 public abstract String get(ComputedCssStyleDeclaration style);
208 }
209 }