KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > bridge > SVGFontUtilities


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

18 package org.apache.batik.bridge;
19
20 import java.util.ArrayList JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.LinkedList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.StringTokenizer JavaDoc;
26
27 import org.apache.batik.dom.svg.SVGOMDocument;
28 import org.apache.batik.gvt.font.GVTFontFamily;
29 import org.apache.batik.gvt.font.GVTFontFace;
30 import org.apache.batik.gvt.font.UnresolvedFontFamily;
31 import org.apache.batik.util.SVGConstants;
32
33 import org.apache.batik.css.engine.CSSEngine;
34 import org.apache.batik.css.engine.FontFaceRule;
35
36 import org.w3c.dom.Document JavaDoc;
37 import org.w3c.dom.Element JavaDoc;
38 import org.w3c.dom.NodeList JavaDoc;
39
40 /**
41  * Utility class for SVG fonts.
42  *
43  * @author <a HREF="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
44  * @version $Id: SVGFontUtilities.java,v 1.17 2004/08/18 07:12:34 vhardy Exp $
45  */

46 public abstract class SVGFontUtilities implements SVGConstants {
47
48     public static List JavaDoc getFontFaces(Document doc,
49                                     BridgeContext ctx) {
50         // check fontFamilyMap to see if we have already created an
51
// FontFamily that matches
52
Map JavaDoc fontFamilyMap = ctx.getFontFamilyMap();
53         List JavaDoc ret = (List JavaDoc)fontFamilyMap.get(doc);
54         if (ret != null)
55             return ret;
56
57         ret = new LinkedList JavaDoc();
58
59         NodeList JavaDoc fontFaceElements = doc.getElementsByTagNameNS
60         (SVG_NAMESPACE_URI, SVG_FONT_FACE_TAG);
61
62         SVGFontFaceElementBridge fontFaceBridge;
63         fontFaceBridge = (SVGFontFaceElementBridge)ctx.getBridge
64             (SVG_NAMESPACE_URI, SVG_FONT_FACE_TAG);
65
66         for (int i = 0; i < fontFaceElements.getLength(); i++) {
67             Element JavaDoc fontFaceElement = (Element JavaDoc)fontFaceElements.item(i);
68             ret.add(fontFaceBridge.createFontFace
69                     (ctx, fontFaceElement));
70         }
71
72         CSSEngine engine = ((SVGOMDocument)doc).getCSSEngine();
73         List JavaDoc sms = engine.getFontFaces();
74         Iterator JavaDoc iter = sms.iterator();
75         while (iter.hasNext()) {
76             FontFaceRule ffr = (FontFaceRule)iter.next();
77             ret.add(CSSFontFace.createCSSFontFace(engine, ffr));
78         }
79         return ret;
80     }
81                                        
82
83     /**
84      * Given a font family name tries to find a matching SVG font
85      * object. If finds one, returns an SVGFontFamily otherwise
86      * returns an UnresolvedFontFamily.
87      *
88      * @param textElement The text element that the font family will
89      * be attached to.
90      * @param ctx The bridge context, used to search for a matching
91      * SVG font element.
92      * @param fontFamilyName The name of the font family to search
93      * for.
94      * @param fontWeight The weight of the font to use when trying to
95      * match an SVG font family.
96      * @param fontStyle The style of the font to use when trying to
97      * match as SVG font family.
98      *
99      * @return A GVTFontFamily for the specified font attributes. This
100      * will be unresolved unless a matching SVG font was found.
101      */

102     public static GVTFontFamily getFontFamily(Element JavaDoc textElement,
103                                              BridgeContext ctx,
104                                              String JavaDoc fontFamilyName,
105                                              String JavaDoc fontWeight,
106                                              String JavaDoc fontStyle) {
107
108         // TODO: should match against font-variant as well
109
String JavaDoc fontKeyName = fontFamilyName.toLowerCase() + " " +
110             fontWeight + " " + fontStyle;
111
112         // check fontFamilyMap to see if we have already created an
113
// FontFamily that matches
114
Map JavaDoc fontFamilyMap = ctx.getFontFamilyMap();
115         GVTFontFamily fontFamily =
116             (GVTFontFamily)fontFamilyMap.get(fontKeyName);
117         if (fontFamily != null) {
118             return fontFamily;
119         }
120
121         // try to find a matching SVGFontFace element
122
Document doc = textElement.getOwnerDocument();
123
124         List JavaDoc fontFaces = (List JavaDoc)fontFamilyMap.get(doc);
125         
126         if (fontFaces == null) {
127             fontFaces = getFontFaces(doc, ctx);
128             fontFamilyMap.put(doc, fontFaces);
129         }
130
131         
132         Iterator JavaDoc iter = fontFaces.iterator();
133         List JavaDoc svgFontFamilies = new LinkedList JavaDoc();
134         while (iter.hasNext()) {
135             FontFace fontFace = (FontFace)iter.next();
136
137             if (!fontFace.hasFamilyName(fontFamilyName)) {
138                 continue;
139             }
140
141             String JavaDoc fontFaceStyle = fontFace.getFontStyle();
142             if (fontFaceStyle.equals(SVG_ALL_VALUE) ||
143                 fontFaceStyle.indexOf(fontStyle) != -1) {
144                 GVTFontFamily ffam = fontFace.getFontFamily(ctx);
145                 if (ffam != null)
146                     svgFontFamilies.add(ffam);
147             }
148         }
149
150         if (svgFontFamilies.size() == 1) {
151             // only found one matching svg font family
152
fontFamilyMap.put(fontKeyName, svgFontFamilies.get(0));
153             return (GVTFontFamily)svgFontFamilies.get(0);
154             
155         } else if (svgFontFamilies.size() > 1) {
156             // need to find font face that matches the font-weight closest
157
String JavaDoc fontWeightNumber = getFontWeightNumberString(fontWeight);
158
159             // create lists of font weight numbers for each font family
160
List JavaDoc fontFamilyWeights = new ArrayList JavaDoc(svgFontFamilies.size());
161             Iterator JavaDoc ffiter = svgFontFamilies.iterator();
162             while(ffiter.hasNext()) {
163                 GVTFontFace fontFace;
164                 fontFace = ((GVTFontFamily)ffiter.next()).getFontFace();
165                 String JavaDoc fontFaceWeight = fontFace.getFontWeight();
166                 fontFaceWeight = getFontWeightNumberString(fontFaceWeight);
167                 fontFamilyWeights.add(fontFaceWeight);
168             }
169
170             // make sure that each possible font-weight has been
171
// assigned to a font-face, if not then need to "fill the
172
// holes"
173

174             List JavaDoc newFontFamilyWeights = new ArrayList JavaDoc(fontFamilyWeights);
175             for (int i = 100; i <= 900; i+= 100) {
176                 String JavaDoc weightString = String.valueOf(i);
177                 boolean matched = false;
178                 int minDifference = 1000;
179                 int minDifferenceIndex = 0;
180                 for (int j = 0; j < fontFamilyWeights.size(); j++) {
181                     String JavaDoc fontFamilyWeight = (String JavaDoc)fontFamilyWeights.get(j);
182                     if (fontFamilyWeight.indexOf(weightString) > -1) {
183                         matched = true;
184                         break;
185                     }
186                     StringTokenizer JavaDoc st =
187                         new StringTokenizer JavaDoc(fontFamilyWeight, " ,");
188                     while (st.hasMoreTokens()) {
189                         int weightNum = Integer.parseInt(st.nextToken());
190                         int difference = Math.abs(weightNum - i);
191                         if (difference < minDifference) {
192                             minDifference = difference;
193                             minDifferenceIndex = j;
194                         }
195                     }
196                 }
197                 if (!matched) {
198                     String JavaDoc newFontFamilyWeight =
199                         newFontFamilyWeights.get(minDifferenceIndex) +
200                         ", " + weightString;
201                     newFontFamilyWeights.set(minDifferenceIndex,
202                                              newFontFamilyWeight);
203                 }
204             }
205
206
207             // now find matching font weight
208
for (int i = 0; i < svgFontFamilies.size(); i++) {
209                 String JavaDoc fontFaceWeight = (String JavaDoc)newFontFamilyWeights.get(i);
210                 if (fontFaceWeight.indexOf(fontWeightNumber) > -1) {
211                     fontFamilyMap.put(fontKeyName, svgFontFamilies.get(i));
212                     return (GVTFontFamily)svgFontFamilies.get(i);
213                 }
214             }
215             // should not get here, just return the first svg font family
216
fontFamilyMap.put(fontKeyName, svgFontFamilies.get(0));
217             return (GVTFontFamily) svgFontFamilies.get(0);
218
219         } else {
220             // couldn't find one so return an UnresolvedFontFamily object
221
GVTFontFamily gvtFontFamily =
222                 new UnresolvedFontFamily(fontFamilyName);
223             fontFamilyMap.put(fontKeyName, gvtFontFamily);
224             return gvtFontFamily;
225         }
226     }
227
228     /**
229      * Returns a string that contains all of the font weight numbers for the
230      * specified font weight attribute value.
231      *
232      * @param fontWeight The font-weight attribute value.
233      *
234      * @return The font weight expressed as font weight numbers.
235      * e.g. "normal" becomes "400".
236      */

237     protected static String JavaDoc getFontWeightNumberString(String JavaDoc fontWeight) {
238         if (fontWeight.equals(SVG_NORMAL_VALUE)) {
239             return SVG_400_VALUE;
240         } else if (fontWeight.equals(SVG_BOLD_VALUE)) {
241             return SVG_700_VALUE;
242         } else if (fontWeight.equals(SVG_ALL_VALUE)) {
243             return "100, 200, 300, 400, 500, 600, 700, 800, 900";
244         }
245         return fontWeight;
246     }
247 }
248
Popular Tags