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.AbstractValueManager;
26 import org.apache.batik.css.engine.value.ListValue;
27 import org.apache.batik.css.engine.value.StringMap;
28 import org.apache.batik.css.engine.value.StringValue;
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 factory for the 'font-family' property values.
41  *
42  * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
43  * @version $Id: FontFamilyManager.java 1733416 2016-03-03 07:07:13Z gadams $
44  */

45 public class FontFamilyManager extends AbstractValueManager {
46
47     /**
48      * The default value.
49      */

50     protected static final ListValue DEFAULT_VALUE = new ListValue();
51     static {
52         DEFAULT_VALUE.append
53             (new StringValue(CSSPrimitiveValue.CSS_STRING,
54                              "Arial"));
55         DEFAULT_VALUE.append
56             (new StringValue(CSSPrimitiveValue.CSS_STRING,
57                              "Helvetica"));
58         DEFAULT_VALUE.append
59             (new StringValue(CSSPrimitiveValue.CSS_IDENT,
60                              CSSConstants.CSS_SANS_SERIF_VALUE));
61     }
62
63     /**
64      * The identifier values.
65      */

66     protected static final StringMap values = new StringMap();
67     static {
68         values.put(CSSConstants.CSS_CURSIVE_VALUE,
69                    ValueConstants.CURSIVE_VALUE);
70         values.put(CSSConstants.CSS_FANTASY_VALUE,
71                    ValueConstants.FANTASY_VALUE);
72         values.put(CSSConstants.CSS_MONOSPACE_VALUE,
73                    ValueConstants.MONOSPACE_VALUE);
74         values.put(CSSConstants.CSS_SERIF_VALUE,
75                    ValueConstants.SERIF_VALUE);
76         values.put(CSSConstants.CSS_SANS_SERIF_VALUE,
77                    ValueConstants.SANS_SERIF_VALUE);
78     }
79
80     /**
81      * Implements {@link ValueManager#isInheritedProperty()}.
82      */

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

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

97     public boolean isAdditiveProperty() {
98         return false;
99     }
100
101     /**
102      * Implements {@link ValueManager#getPropertyType()}.
103      */

104     public int getPropertyType() {
105         return SVGTypes.TYPE_FONT_FAMILY_VALUE;
106     }
107
108     /**
109      * Implements {@link ValueManager#getPropertyName()}.
110      */

111     public String getPropertyName() {
112         return CSSConstants.CSS_FONT_FAMILY_PROPERTY;
113     }
114
115     /**
116      * Implements {@link ValueManager#getDefaultValue()}.
117      */

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

125     public Value createValue(LexicalUnit lu, CSSEngine engine)
126         throws DOMException {
127         switch (lu.getLexicalUnitType()) {
128         case LexicalUnit.SAC_INHERIT:
129             return ValueConstants.INHERIT_VALUE;
130
131         default:
132             throw createInvalidLexicalUnitDOMException
133                 (lu.getLexicalUnitType());
134
135         case LexicalUnit.SAC_IDENT:
136         case LexicalUnit.SAC_STRING_VALUE:
137         }
138         ListValue result = new ListValue();
139         for (;;) {
140             switch (lu.getLexicalUnitType()) {
141             case LexicalUnit.SAC_STRING_VALUE:
142                 result.append(new StringValue(CSSPrimitiveValue.CSS_STRING,
143                                               lu.getStringValue()));
144                 lu = lu.getNextLexicalUnit();
145                 break;
146
147             case LexicalUnit.SAC_IDENT:
148                 StringBuffer sb = new StringBuffer(lu.getStringValue());
149                 lu = lu.getNextLexicalUnit();
150                 if (lu != null && isIdentOrNumber(lu)) {
151                     do {
152                         sb.append(' ');
153                         switch (lu.getLexicalUnitType()) {
154                         case LexicalUnit.SAC_IDENT:
155                             sb.append(lu.getStringValue());
156                             break;
157                         case LexicalUnit.SAC_INTEGER:
158                             //Some font names contain integer values but are not quoted!
159                             //Example: "Univers 45 Light"
160                             sb.append(Integer.toString(lu.getIntegerValue()));
161                         }
162                         lu = lu.getNextLexicalUnit();
163                     } while (lu != null && isIdentOrNumber(lu));
164                     result.append(new StringValue(CSSPrimitiveValue.CSS_STRING,
165                                                   sb.toString()));
166                 } else {
167                     String id = sb.toString();
168                     String s = id.toLowerCase().intern();
169                     Value v = (Value)values.get(s);
170                     result.append((v != null)
171                                   ? v
172                                   : new StringValue
173                                         (CSSPrimitiveValue.CSS_STRING, id));
174                 }
175             }
176             if (lu == null)
177                 return result;
178             if (lu.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA)
179                 throw createInvalidLexicalUnitDOMException
180                     (lu.getLexicalUnitType());
181             lu = lu.getNextLexicalUnit();
182             if (lu == null)
183                 throw createMalformedLexicalUnitDOMException();
184         }
185     }
186
187     private boolean isIdentOrNumber(LexicalUnit lu) {
188         short type = lu.getLexicalUnitType();
189         switch (type) {
190         case LexicalUnit.SAC_IDENT:
191         case LexicalUnit.SAC_INTEGER:
192             return true;
193         default:
194             return false;
195         }
196     }
197
198     /**
199      * Implements {@link
200      * ValueManager#computeValue(CSSStylableElement,String,CSSEngine,int,StyleMap,Value)}.
201      */

202     public Value computeValue(CSSStylableElement elt,
203                               String pseudo,
204                               CSSEngine engine,
205                               int idx,
206                               StyleMap sm,
207                               Value value) {
208         if (value == DEFAULT_VALUE) {
209             CSSContext ctx = engine.getCSSContext();
210             value = ctx.getDefaultFontFamily();
211         }
212         return value;
213     }
214 }
215