KickJava   Java API By Example, From Geeks To Geeks.

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


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.awt.Paint JavaDoc;
21 import java.awt.Shape JavaDoc;
22 import java.awt.Stroke JavaDoc;
23 import java.awt.geom.AffineTransform JavaDoc;
24 import java.awt.geom.Point2D JavaDoc;
25 import java.util.StringTokenizer JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 import org.apache.batik.gvt.CompositeGraphicsNode;
29 import org.apache.batik.gvt.GraphicsNode;
30 import org.apache.batik.gvt.font.Glyph;
31 import org.apache.batik.gvt.font.GVTFontFace;
32 import org.apache.batik.gvt.text.TextPaintInfo;
33 import org.apache.batik.parser.AWTPathProducer;
34 import org.apache.batik.parser.ParseException;
35 import org.apache.batik.parser.PathParser;
36 import org.w3c.dom.Attr JavaDoc;
37 import org.w3c.dom.Element JavaDoc;
38 import org.w3c.dom.NamedNodeMap JavaDoc;
39 import org.w3c.dom.Node JavaDoc;
40 import org.w3c.dom.NodeList JavaDoc;
41
42 /**
43  * Bridge class for the <glyph> element.
44  *
45  * @author <a HREF="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
46  * @version $Id: SVGGlyphElementBridge.java,v 1.14 2004/09/06 00:01:58 deweese Exp $
47  */

48 public class SVGGlyphElementBridge extends AbstractSVGBridge
49     implements ErrorConstants {
50
51     /**
52      * Constructs a new bridge for the &lt;glyph> element.
53      */

54     protected SVGGlyphElementBridge() {}
55
56     /**
57      * Returns 'glyph'.
58      */

59     public String JavaDoc getLocalName() {
60         return SVG_GLYPH_TAG;
61     }
62
63     /**
64      * Constructs a new Glyph that represents the specified &lt;glyph> element
65      * at the requested size.
66      *
67      * @param ctx The current bridge context.
68      * @param glyphElement The glyph element to base the glyph construction on.
69      * @param textElement The textElement the glyph will be used for.
70      * @param glyphCode The unique id to give to the new glyph.
71      * @param fontSize The font size used to determine the size of the glyph.
72      * @param fontFace The font face object that contains the font attributes.
73      *
74      * @return The new Glyph.
75      */

76     public Glyph createGlyph(BridgeContext ctx,
77                              Element JavaDoc glyphElement,
78                              Element JavaDoc textElement,
79                              int glyphCode,
80                              float fontSize,
81                              GVTFontFace fontFace,
82                              TextPaintInfo tpi) {
83
84
85
86         float fontHeight = fontFace.getUnitsPerEm();
87         float scale = fontSize/fontHeight;
88         AffineTransform JavaDoc scaleTransform
89             = AffineTransform.getScaleInstance(scale, -scale);
90
91         // create a shape that represents the d attribute
92
String JavaDoc d = glyphElement.getAttributeNS(null, SVG_D_ATTRIBUTE);
93         Shape JavaDoc dShape = null;
94         if (d.length() != 0) {
95             AWTPathProducer app = new AWTPathProducer();
96             // Glyph is supposed to use properties from text element.
97
app.setWindingRule(CSSUtilities.convertFillRule(textElement));
98             try {
99                 PathParser pathParser = new PathParser();
100                 pathParser.setPathHandler(app);
101                 pathParser.parse(d);
102             } catch (ParseException ex) {
103                 throw new BridgeException(glyphElement,
104                                           ERR_ATTRIBUTE_VALUE_MALFORMED,
105                                           new Object JavaDoc [] {SVG_D_ATTRIBUTE});
106             } finally {
107                 // transform the shape into the correct coord system
108
Shape JavaDoc shape = app.getShape();
109                 Shape JavaDoc transformedShape
110                     = scaleTransform.createTransformedShape(shape);
111                 dShape = transformedShape;
112             }
113         }
114
115         // process any glyph children
116

117         // first see if there are any, because don't want to do the following
118
// bit of code if we can avoid it
119

120         NodeList JavaDoc glyphChildren = glyphElement.getChildNodes();
121         int numChildren = glyphChildren.getLength();
122         int numGlyphChildren = 0;
123         for (int i = 0; i < numChildren; i++) {
124             Node childNode = glyphChildren.item(i);
125             if (childNode.getNodeType() == Node.ELEMENT_NODE) {
126                 numGlyphChildren++;
127             }
128         }
129
130         CompositeGraphicsNode glyphContentNode = null;
131
132         if (numGlyphChildren > 0) { // the glyph has child elements
133

134             // build the GVT tree that represents the glyph children
135
GVTBuilder builder = ctx.getGVTBuilder();
136
137             glyphContentNode = new CompositeGraphicsNode();
138
139             //
140
// need to clone the parent font element and glyph element
141
// this is so that the glyph doesn't inherit anything past the font element
142
//
143
Element JavaDoc fontElementClone
144                 = (Element JavaDoc)glyphElement.getParentNode().cloneNode(false);
145
146             // copy all font attributes over
147
NamedNodeMap JavaDoc fontAttributes
148                 = glyphElement.getParentNode().getAttributes();
149
150             int numAttributes = fontAttributes.getLength();
151             for (int i = 0; i < numAttributes; i++) {
152                 fontElementClone.setAttributeNode((Attr JavaDoc)fontAttributes.item(i));
153             }
154             Element JavaDoc clonedGlyphElement = (Element JavaDoc)glyphElement.cloneNode(true);
155             fontElementClone.appendChild(clonedGlyphElement);
156
157             textElement.appendChild(fontElementClone);
158
159             CompositeGraphicsNode glyphChildrenNode
160                 = new CompositeGraphicsNode();
161
162             glyphChildrenNode.setTransform(scaleTransform);
163
164             NodeList JavaDoc clonedGlyphChildren = clonedGlyphElement.getChildNodes();
165             int numClonedChildren = clonedGlyphChildren.getLength();
166             for (int i = 0; i < numClonedChildren; i++) {
167                 Node childNode = clonedGlyphChildren.item(i);
168                 if (childNode.getNodeType() == Node.ELEMENT_NODE) {
169                     Element JavaDoc childElement = (Element JavaDoc)childNode;
170                     GraphicsNode childGraphicsNode =
171                          builder.build(ctx, childElement);
172                     glyphChildrenNode.add(childGraphicsNode);
173                 }
174             }
175             glyphContentNode.add(glyphChildrenNode);
176             textElement.removeChild(fontElementClone);
177         }
178
179         // set up glyph attributes
180

181         // unicode
182
String JavaDoc unicode
183             = glyphElement.getAttributeNS(null, SVG_UNICODE_ATTRIBUTE);
184
185         // glyph-name
186
String JavaDoc nameList
187             = glyphElement.getAttributeNS(null, SVG_GLYPH_NAME_ATTRIBUTE);
188         Vector JavaDoc names = new Vector JavaDoc();
189         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(nameList, " ,");
190         while (st.hasMoreTokens()) {
191             names.add(st.nextToken());
192         }
193
194         // orientation
195
String JavaDoc orientation
196             = glyphElement.getAttributeNS(null, SVG_ORIENTATION_ATTRIBUTE);
197
198         // arabicForm
199
String JavaDoc arabicForm
200             = glyphElement.getAttributeNS(null, SVG_ARABIC_FORM_ATTRIBUTE);
201
202         // lang
203
String JavaDoc lang = glyphElement.getAttributeNS(null, SVG_LANG_ATTRIBUTE);
204
205
206         Element JavaDoc parentFontElement = (Element JavaDoc)glyphElement.getParentNode();
207
208         // horz-adv-x
209
String JavaDoc s = glyphElement.getAttributeNS(null, SVG_HORIZ_ADV_X_ATTRIBUTE);
210         if (s.length() == 0) {
211             // look for attribute on parent font element
212
s = parentFontElement.getAttributeNS(null, SVG_HORIZ_ADV_X_ATTRIBUTE);
213             if (s.length() == 0) {
214                 // throw an exception since this attribute is required on the font element
215
throw new BridgeException (parentFontElement, ERR_ATTRIBUTE_MISSING,
216                                            new Object JavaDoc[] {SVG_HORIZ_ADV_X_ATTRIBUTE});
217             }
218         }
219         float horizAdvX;
220         try {
221             horizAdvX = SVGUtilities.convertSVGNumber(s) * scale;
222         } catch (NumberFormatException JavaDoc ex) {
223             throw new BridgeException
224                 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED,
225                 new Object JavaDoc [] {SVG_HORIZ_ADV_X_ATTRIBUTE, s});
226         }
227
228         // vert-adv-y
229
s = glyphElement.getAttributeNS(null, SVG_VERT_ADV_Y_ATTRIBUTE);
230         if (s.length() == 0) {
231             // look for attribute on parent font element
232
s = parentFontElement.getAttributeNS(null, SVG_VERT_ADV_Y_ATTRIBUTE);
233             if (s.length() == 0) {
234                 // not specified on parent either, use one em
235
s = String.valueOf(fontFace.getUnitsPerEm());
236             }
237         }
238         float vertAdvY;
239         try {
240             vertAdvY = SVGUtilities.convertSVGNumber(s) * scale;
241         } catch (NumberFormatException JavaDoc ex) {
242             throw new BridgeException
243                 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED,
244                 new Object JavaDoc [] {SVG_VERT_ADV_Y_ATTRIBUTE, s});
245         }
246
247         // vert-origin-x
248
s = glyphElement.getAttributeNS(null, SVG_VERT_ORIGIN_X_ATTRIBUTE);
249         if (s.length() == 0) {
250             // look for attribute on parent font element
251
s = parentFontElement.getAttributeNS(null, SVG_VERT_ORIGIN_X_ATTRIBUTE);
252             if (s.length() == 0) {
253                 // not specified so use the default value which is horizAdvX/2
254
s = Float.toString(horizAdvX/2);
255             }
256         }
257         float vertOriginX;
258         try {
259             vertOriginX = SVGUtilities.convertSVGNumber(s) * scale;
260         } catch (NumberFormatException JavaDoc ex) {
261             throw new BridgeException
262                 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED,
263                 new Object JavaDoc [] {SVG_VERT_ORIGIN_X_ATTRIBUTE, s});
264         }
265
266         // vert-origin-y
267
s = glyphElement.getAttributeNS(null, SVG_VERT_ORIGIN_Y_ATTRIBUTE);
268         if (s.length() == 0) {
269             // look for attribute on parent font element
270
s = parentFontElement.getAttributeNS(null, SVG_VERT_ORIGIN_Y_ATTRIBUTE);
271             if (s.length() == 0) {
272                 // not specified so use the default value which is the fonts ascent
273
s = String.valueOf(fontFace.getAscent());
274             }
275         }
276         float vertOriginY;
277         try {
278             vertOriginY = SVGUtilities.convertSVGNumber(s) * -scale;
279         } catch (NumberFormatException JavaDoc ex) {
280             throw new BridgeException
281                 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED,
282                 new Object JavaDoc [] {SVG_VERT_ORIGIN_Y_ATTRIBUTE, s});
283         }
284
285         Point2D JavaDoc vertOrigin = new Point2D.Float JavaDoc(vertOriginX, vertOriginY);
286
287
288         // get the horizontal origin from the parent font element
289

290         // horiz-origin-x
291
s = parentFontElement.getAttributeNS(null, SVG_HORIZ_ORIGIN_X_ATTRIBUTE);
292         if (s.length() == 0) {
293             // not specified so use the default value which is 0
294
s = SVG_HORIZ_ORIGIN_X_DEFAULT_VALUE;
295         }
296         float horizOriginX;
297         try {
298             horizOriginX = SVGUtilities.convertSVGNumber(s) * scale;
299         } catch (NumberFormatException JavaDoc ex) {
300             throw new BridgeException
301                 (parentFontElement, ERR_ATTRIBUTE_VALUE_MALFORMED,
302                 new Object JavaDoc [] {SVG_HORIZ_ORIGIN_X_ATTRIBUTE, s});
303         }
304
305         // horiz-origin-y
306
s = parentFontElement.getAttributeNS(null, SVG_HORIZ_ORIGIN_Y_ATTRIBUTE);
307         if (s.length() == 0) {
308             // not specified so use the default value which is 0
309
s = SVG_HORIZ_ORIGIN_Y_DEFAULT_VALUE;
310         }
311         float horizOriginY;
312         try {
313             horizOriginY = SVGUtilities.convertSVGNumber(s) * -scale;
314         } catch (NumberFormatException JavaDoc ex) {
315             throw new BridgeException
316                 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED,
317                 new Object JavaDoc [] {SVG_HORIZ_ORIGIN_Y_ATTRIBUTE, s});
318         }
319
320         Point2D JavaDoc horizOrigin = new Point2D.Float JavaDoc(horizOriginX, horizOriginY);
321
322         // return a new Glyph
323
return new Glyph(unicode, names, orientation,
324                          arabicForm, lang, horizOrigin, vertOrigin,
325                          horizAdvX, vertAdvY, glyphCode,
326                          tpi, dShape, glyphContentNode);
327     }
328 }
329
Popular Tags