1 /*
2
3    Licensed to the Apache Software Foundation (ASF) under one or more
4    contributor license agreements.  See the NOTICE file distributed with
5    this work for additional information regarding copyright ownership.
6    The ASF licenses this file to You under the Apache License, Version 2.0
7    (the "License"); you may not use this file except in compliance with
8    the License.  You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17
18  */

19 package org.apache.batik.css.engine.value.css2;
20
21 import org.apache.batik.css.engine.CSSContext;
22 import org.apache.batik.css.engine.CSSEngine;
23 import org.apache.batik.css.engine.CSSStylableElement;
24 import org.apache.batik.css.engine.StyleMap;
25 import org.apache.batik.css.engine.value.FloatValue;
26 import org.apache.batik.css.engine.value.IdentifierManager;
27 import org.apache.batik.css.engine.value.LengthManager;
28 import org.apache.batik.css.engine.value.StringMap;
29 import org.apache.batik.css.engine.value.Value;
30 import org.apache.batik.css.engine.value.ValueConstants;
31 import org.apache.batik.css.engine.value.ValueManager;
32 import org.apache.batik.util.CSSConstants;
33 import org.apache.batik.util.SVGTypes;
34
35 import org.w3c.css.sac.LexicalUnit;
36 import org.w3c.dom.DOMException;
37 import org.w3c.dom.css.CSSPrimitiveValue;
38
39 /**
40  * This class provides a manager for the 'font-size' property values.
41  *
42  * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
43  * @version $Id: FontSizeManager.java 1733416 2016-03-03 07:07:13Z gadams $
44  */

45 public class FontSizeManager extends LengthManager {
46
47     /**
48      * The identifier values.
49      */

50     protected static final StringMap values = new StringMap();
51     static {
52         values.put(CSSConstants.CSS_ALL_VALUE,
53                    ValueConstants.ALL_VALUE);
54         values.put(CSSConstants.CSS_LARGE_VALUE,
55                    ValueConstants.LARGE_VALUE);
56         values.put(CSSConstants.CSS_LARGER_VALUE,
57                    ValueConstants.LARGER_VALUE);
58         values.put(CSSConstants.CSS_MEDIUM_VALUE,
59                    ValueConstants.MEDIUM_VALUE);
60         values.put(CSSConstants.CSS_SMALL_VALUE,
61                    ValueConstants.SMALL_VALUE);
62         values.put(CSSConstants.CSS_SMALLER_VALUE,
63                    ValueConstants.SMALLER_VALUE);
64         values.put(CSSConstants.CSS_X_LARGE_VALUE,
65                    ValueConstants.X_LARGE_VALUE);
66         values.put(CSSConstants.CSS_X_SMALL_VALUE,
67                    ValueConstants.X_SMALL_VALUE);
68         values.put(CSSConstants.CSS_XX_LARGE_VALUE,
69                    ValueConstants.XX_LARGE_VALUE);
70         values.put(CSSConstants.CSS_XX_SMALL_VALUE,
71                    ValueConstants.XX_SMALL_VALUE);
72     }
73
74     /**
75      * Implements {@link IdentifierManager#getIdentifiers()}.
76      */

77     public StringMap getIdentifiers() {
78         return values;
79     }
80
81     /**
82      * Implements {@link ValueManager#isInheritedProperty()}.
83      */

84     public boolean isInheritedProperty() {
85         return true;
86     }
87
88     /**
89      * Implements {@link ValueManager#isAnimatableProperty()}.
90      */

91     public boolean isAnimatableProperty() {
92         return true;
93     }
94
95     /**
96      * Implements {@link ValueManager#isAdditiveProperty()}.
97      */

98     public boolean isAdditiveProperty() {
99         return true;
100     }
101
102     /**
103      * Implements {@link ValueManager#getPropertyName()}.
104      */

105     public String getPropertyName() {
106         return CSSConstants.CSS_FONT_SIZE_PROPERTY;
107     }
108
109     /**
110      * Implements {@link ValueManager#getPropertyType()}.
111      */

112     public int getPropertyType() {
113         return SVGTypes.TYPE_FONT_SIZE_VALUE;
114     }
115
116     /**
117      * Implements {@link ValueManager#getDefaultValue()}.
118      */

119     public Value getDefaultValue() {
120         return ValueConstants.MEDIUM_VALUE;
121     }
122
123     /**
124      * Implements {@link ValueManager#createValue(LexicalUnit,CSSEngine)}.
125      */

126     public Value createValue(LexicalUnit lu, CSSEngine engine)
127         throws DOMException {
128         switch (lu.getLexicalUnitType()) {
129         case LexicalUnit.SAC_INHERIT:
130             return ValueConstants.INHERIT_VALUE;
131
132         case LexicalUnit.SAC_IDENT:
133             String s = lu.getStringValue().toLowerCase().intern();
134             Object v = values.get(s);
135             if (v == null) {
136                 throw createInvalidIdentifierDOMException(s);
137             }
138             return (Value)v;
139         default:
140             break;
141         }
142         return super.createValue(lu, engine);
143     }
144
145     /**
146      * Implements {@link
147      * ValueManager#createStringValue(short,String,CSSEngine)}.
148      */

149     public Value createStringValue(short type, String value, CSSEngine engine)
150         throws DOMException {
151         if (type != CSSPrimitiveValue.CSS_IDENT) {
152             throw createInvalidStringTypeDOMException(type);
153         }
154         Object v = values.get(value.toLowerCase().intern());
155         if (v == null) {
156             throw createInvalidIdentifierDOMException(value);
157         }
158         return (Value)v;
159     }
160
161     /**
162      * Implements {@link
163      * ValueManager#computeValue(CSSStylableElement,String,CSSEngine,int,StyleMap,Value)}.
164      */

165     public Value computeValue(CSSStylableElement elt,
166                               String pseudo,
167                               CSSEngine engine,
168                               int idx,
169                               StyleMap sm,
170                               Value value) {
171         float scale = 1.0f;
172         boolean doParentRelative = false;
173
174         switch (value.getPrimitiveType()) {
175         case CSSPrimitiveValue.CSS_NUMBER:
176         case CSSPrimitiveValue.CSS_PX:
177             return value;
178
179         case CSSPrimitiveValue.CSS_MM:
180             CSSContext ctx = engine.getCSSContext();
181             float v = value.getFloatValue();
182             return new FloatValue(CSSPrimitiveValue.CSS_NUMBER,
183                                   v / ctx.getPixelUnitToMillimeter());
184
185         case CSSPrimitiveValue.CSS_CM:
186             ctx = engine.getCSSContext();
187             v = value.getFloatValue();
188             return new FloatValue(CSSPrimitiveValue.CSS_NUMBER,
189                                   v * 10f / ctx.getPixelUnitToMillimeter());
190
191         case CSSPrimitiveValue.CSS_IN:
192             ctx = engine.getCSSContext();
193             v = value.getFloatValue();
194             return new FloatValue(CSSPrimitiveValue.CSS_NUMBER,
195                                   v * 25.4f / ctx.getPixelUnitToMillimeter());
196
197         case CSSPrimitiveValue.CSS_PT:
198             ctx = engine.getCSSContext();
199             v = value.getFloatValue();
200             return new FloatValue(CSSPrimitiveValue.CSS_NUMBER,
201                                   v * 25.4f /
202                                   (72f * ctx.getPixelUnitToMillimeter()));
203
204         case CSSPrimitiveValue.CSS_PC:
205             ctx = engine.getCSSContext();
206             v = value.getFloatValue();
207             return new FloatValue(CSSPrimitiveValue.CSS_NUMBER,
208                                   (v * 25.4f /
209                                    (6f * ctx.getPixelUnitToMillimeter())));
210
211         case CSSPrimitiveValue.CSS_EMS:
212             doParentRelative = true;
213             scale = value.getFloatValue();
214             break;
215         case CSSPrimitiveValue.CSS_EXS:
216             doParentRelative = true;
217             scale = value.getFloatValue()*0.5f;   // !!! x-height
218             break;
219         case CSSPrimitiveValue.CSS_PERCENTAGE:
220             doParentRelative = true;
221             scale = value.getFloatValue()*0.01f;
222             break;
223         default:
224         }
225
226         if (value == ValueConstants.LARGER_VALUE) {
227             doParentRelative = true;
228             scale = 1.2f;
229         } else if (value == ValueConstants.SMALLER_VALUE) {
230             doParentRelative = true;
231             scale = 1/1.2f;
232         }
233
234         if (doParentRelative) {
235             sm.putParentRelative(idx, true);
236
237             CSSStylableElement p;
238             p = CSSEngine.getParentCSSStylableElement(elt);
239             float fs;
240             if (p == null) {
241                 CSSContext ctx = engine.getCSSContext();
242                 fs = ctx.getMediumFontSize();
243             } else {
244                 fs = engine.getComputedStyle(p, null, idx).getFloatValue();
245             }
246             return new FloatValue(CSSPrimitiveValue.CSS_NUMBER, fs * scale);
247         }
248
249         // absolute identifiers
250         CSSContext ctx = engine.getCSSContext();
251         float fs = ctx.getMediumFontSize();
252         String s = value.getStringValue();
253         switch (s.charAt(0)) {
254         case 'm':
255             break;
256
257         case 's':
258             fs = (float)(fs / 1.2);
259             break;
260
261         case 'l':
262             fs = (float)(fs * 1.2);
263             break;
264
265         default// 'x'
266             switch (s.charAt(1)) {
267             case 'x':
268                 switch (s.charAt(3)) {
269                 case 's':
270                     fs = (float)(((fs / 1.2) / 1.2) / 1.2);
271                     break;
272
273                 default// 'l'
274                     fs = (float)(fs * 1.2 * 1.2 * 1.2);
275                 }
276                 break;
277
278             default// '-'
279                 switch (s.charAt(2)) {
280                 case 's':
281                     fs = (float)((fs / 1.2) / 1.2);
282                     break;
283
284                 default// 'l'
285                     fs = (float)(fs * 1.2 * 1.2);
286                 }
287             }
288         }
289         return new FloatValue(CSSPrimitiveValue.CSS_NUMBER, fs);
290     }
291
292
293     /**
294      * Indicates the orientation of the property associated with
295      * this manager.
296      */

297     protected int getOrientation() {
298         return VERTICAL_ORIENTATION; // Not used
299     }
300 }
301