1 18 package org.apache.batik.bridge; 19 20 import java.awt.Paint ; 21 import java.awt.Shape ; 22 import java.awt.Stroke ; 23 import java.awt.geom.AffineTransform ; 24 import java.awt.geom.Point2D ; 25 import java.util.StringTokenizer ; 26 import java.util.Vector ; 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 ; 37 import org.w3c.dom.Element ; 38 import org.w3c.dom.NamedNodeMap ; 39 import org.w3c.dom.Node ; 40 import org.w3c.dom.NodeList ; 41 42 48 public class SVGGlyphElementBridge extends AbstractSVGBridge 49 implements ErrorConstants { 50 51 54 protected SVGGlyphElementBridge() {} 55 56 59 public String getLocalName() { 60 return SVG_GLYPH_TAG; 61 } 62 63 76 public Glyph createGlyph(BridgeContext ctx, 77 Element glyphElement, 78 Element 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 scaleTransform 89 = AffineTransform.getScaleInstance(scale, -scale); 90 91 String d = glyphElement.getAttributeNS(null, SVG_D_ATTRIBUTE); 93 Shape dShape = null; 94 if (d.length() != 0) { 95 AWTPathProducer app = new AWTPathProducer(); 96 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 [] {SVG_D_ATTRIBUTE}); 106 } finally { 107 Shape shape = app.getShape(); 109 Shape transformedShape 110 = scaleTransform.createTransformedShape(shape); 111 dShape = transformedShape; 112 } 113 } 114 115 117 120 NodeList 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) { 134 GVTBuilder builder = ctx.getGVTBuilder(); 136 137 glyphContentNode = new CompositeGraphicsNode(); 138 139 Element fontElementClone 144 = (Element )glyphElement.getParentNode().cloneNode(false); 145 146 NamedNodeMap fontAttributes 148 = glyphElement.getParentNode().getAttributes(); 149 150 int numAttributes = fontAttributes.getLength(); 151 for (int i = 0; i < numAttributes; i++) { 152 fontElementClone.setAttributeNode((Attr )fontAttributes.item(i)); 153 } 154 Element clonedGlyphElement = (Element )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 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 childElement = (Element )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 181 String unicode 183 = glyphElement.getAttributeNS(null, SVG_UNICODE_ATTRIBUTE); 184 185 String nameList 187 = glyphElement.getAttributeNS(null, SVG_GLYPH_NAME_ATTRIBUTE); 188 Vector names = new Vector (); 189 StringTokenizer st = new StringTokenizer (nameList, " ,"); 190 while (st.hasMoreTokens()) { 191 names.add(st.nextToken()); 192 } 193 194 String orientation 196 = glyphElement.getAttributeNS(null, SVG_ORIENTATION_ATTRIBUTE); 197 198 String arabicForm 200 = glyphElement.getAttributeNS(null, SVG_ARABIC_FORM_ATTRIBUTE); 201 202 String lang = glyphElement.getAttributeNS(null, SVG_LANG_ATTRIBUTE); 204 205 206 Element parentFontElement = (Element )glyphElement.getParentNode(); 207 208 String s = glyphElement.getAttributeNS(null, SVG_HORIZ_ADV_X_ATTRIBUTE); 210 if (s.length() == 0) { 211 s = parentFontElement.getAttributeNS(null, SVG_HORIZ_ADV_X_ATTRIBUTE); 213 if (s.length() == 0) { 214 throw new BridgeException (parentFontElement, ERR_ATTRIBUTE_MISSING, 216 new Object [] {SVG_HORIZ_ADV_X_ATTRIBUTE}); 217 } 218 } 219 float horizAdvX; 220 try { 221 horizAdvX = SVGUtilities.convertSVGNumber(s) * scale; 222 } catch (NumberFormatException ex) { 223 throw new BridgeException 224 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 225 new Object [] {SVG_HORIZ_ADV_X_ATTRIBUTE, s}); 226 } 227 228 s = glyphElement.getAttributeNS(null, SVG_VERT_ADV_Y_ATTRIBUTE); 230 if (s.length() == 0) { 231 s = parentFontElement.getAttributeNS(null, SVG_VERT_ADV_Y_ATTRIBUTE); 233 if (s.length() == 0) { 234 s = String.valueOf(fontFace.getUnitsPerEm()); 236 } 237 } 238 float vertAdvY; 239 try { 240 vertAdvY = SVGUtilities.convertSVGNumber(s) * scale; 241 } catch (NumberFormatException ex) { 242 throw new BridgeException 243 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 244 new Object [] {SVG_VERT_ADV_Y_ATTRIBUTE, s}); 245 } 246 247 s = glyphElement.getAttributeNS(null, SVG_VERT_ORIGIN_X_ATTRIBUTE); 249 if (s.length() == 0) { 250 s = parentFontElement.getAttributeNS(null, SVG_VERT_ORIGIN_X_ATTRIBUTE); 252 if (s.length() == 0) { 253 s = Float.toString(horizAdvX/2); 255 } 256 } 257 float vertOriginX; 258 try { 259 vertOriginX = SVGUtilities.convertSVGNumber(s) * scale; 260 } catch (NumberFormatException ex) { 261 throw new BridgeException 262 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 263 new Object [] {SVG_VERT_ORIGIN_X_ATTRIBUTE, s}); 264 } 265 266 s = glyphElement.getAttributeNS(null, SVG_VERT_ORIGIN_Y_ATTRIBUTE); 268 if (s.length() == 0) { 269 s = parentFontElement.getAttributeNS(null, SVG_VERT_ORIGIN_Y_ATTRIBUTE); 271 if (s.length() == 0) { 272 s = String.valueOf(fontFace.getAscent()); 274 } 275 } 276 float vertOriginY; 277 try { 278 vertOriginY = SVGUtilities.convertSVGNumber(s) * -scale; 279 } catch (NumberFormatException ex) { 280 throw new BridgeException 281 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 282 new Object [] {SVG_VERT_ORIGIN_Y_ATTRIBUTE, s}); 283 } 284 285 Point2D vertOrigin = new Point2D.Float (vertOriginX, vertOriginY); 286 287 288 290 s = parentFontElement.getAttributeNS(null, SVG_HORIZ_ORIGIN_X_ATTRIBUTE); 292 if (s.length() == 0) { 293 s = SVG_HORIZ_ORIGIN_X_DEFAULT_VALUE; 295 } 296 float horizOriginX; 297 try { 298 horizOriginX = SVGUtilities.convertSVGNumber(s) * scale; 299 } catch (NumberFormatException ex) { 300 throw new BridgeException 301 (parentFontElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 302 new Object [] {SVG_HORIZ_ORIGIN_X_ATTRIBUTE, s}); 303 } 304 305 s = parentFontElement.getAttributeNS(null, SVG_HORIZ_ORIGIN_Y_ATTRIBUTE); 307 if (s.length() == 0) { 308 s = SVG_HORIZ_ORIGIN_Y_DEFAULT_VALUE; 310 } 311 float horizOriginY; 312 try { 313 horizOriginY = SVGUtilities.convertSVGNumber(s) * -scale; 314 } catch (NumberFormatException ex) { 315 throw new BridgeException 316 (glyphElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 317 new Object [] {SVG_HORIZ_ORIGIN_Y_ATTRIBUTE, s}); 318 } 319 320 Point2D horizOrigin = new Point2D.Float (horizOriginX, horizOriginY); 321 322 return new Glyph(unicode, names, orientation, 324 arabicForm, lang, horizOrigin, vertOrigin, 325 horizAdvX, vertAdvY, glyphCode, 326 tpi, dShape, glyphContentNode); 327 } 328 } 329 | Popular Tags |