KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > extension > svg > BatikFlowTextElementBridge


1 /*
2
3    Copyright 1999-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
19 package org.apache.batik.extension.svg;
20
21 import java.awt.font.TextAttribute JavaDoc;
22 import java.awt.geom.Point2D JavaDoc;
23 import java.text.AttributedCharacterIterator JavaDoc;
24 import java.text.AttributedString JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30
31 import org.apache.batik.bridge.Bridge;
32 import org.apache.batik.bridge.BridgeContext;
33 import org.apache.batik.bridge.BridgeException;
34 import org.apache.batik.bridge.CSSUtilities;
35 import org.apache.batik.bridge.SVGAElementBridge;
36 import org.apache.batik.bridge.SVGTextElementBridge;
37 import org.apache.batik.bridge.SVGUtilities;
38 import org.apache.batik.bridge.TextUtilities;
39 import org.apache.batik.bridge.UnitProcessor;
40 import org.apache.batik.bridge.UserAgent;
41 import org.apache.batik.dom.util.XLinkSupport;
42 import org.apache.batik.dom.util.XMLSupport;
43 import org.apache.batik.gvt.GraphicsNode;
44 import org.apache.batik.gvt.TextNode;
45 import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
46 import org.apache.batik.gvt.text.TextPath;
47 import org.apache.batik.gvt.text.TextPaintInfo;
48 import org.apache.batik.util.SVGConstants;
49 import org.w3c.dom.Element JavaDoc;
50 import org.w3c.dom.Node JavaDoc;
51 import org.w3c.dom.events.EventTarget JavaDoc;
52
53 /**
54  * Bridge class for the <flowText> element.
55  *
56  * @author <a HREF="mailto:deweese@apache.org">Thomas DeWeese</a>
57  * @version $Id: BatikFlowTextElementBridge.java,v 1.3 2005/03/27 08:58:33 cam Exp $
58  */

59 public class BatikFlowTextElementBridge extends SVGTextElementBridge
60     implements BatikExtConstants {
61
62     public static final AttributedCharacterIterator.Attribute JavaDoc FLOW_PARAGRAPH
63         = GVTAttributedCharacterIterator.TextAttribute.FLOW_PARAGRAPH;
64
65     public static final AttributedCharacterIterator.Attribute JavaDoc
66         FLOW_EMPTY_PARAGRAPH
67         = GVTAttributedCharacterIterator.TextAttribute.FLOW_EMPTY_PARAGRAPH;
68
69     public static final AttributedCharacterIterator.Attribute JavaDoc FLOW_LINE_BREAK
70         = GVTAttributedCharacterIterator.TextAttribute.FLOW_LINE_BREAK;
71     
72     public static final AttributedCharacterIterator.Attribute JavaDoc FLOW_REGIONS
73         = GVTAttributedCharacterIterator.TextAttribute.FLOW_REGIONS;
74
75     public static final AttributedCharacterIterator.Attribute JavaDoc PREFORMATTED
76         = GVTAttributedCharacterIterator.TextAttribute.PREFORMATTED;
77
78     /**
79      * Constructs a new bridge for the &lt;flowText> element.
80      */

81     public BatikFlowTextElementBridge() {}
82
83     /**
84      * Returns the SVG namespace URI.
85      */

86     public String JavaDoc getNamespaceURI() {
87         return BATIK_12_NAMESPACE_URI;
88     }
89
90     /**
91      * Returns 'flowText'.
92      */

93     public String JavaDoc getLocalName() {
94         return BATIK_EXT_FLOW_TEXT_TAG;
95     }
96
97     /**
98      * Returns a new instance of this bridge.
99      */

100     public Bridge getInstance() {
101         return new BatikFlowTextElementBridge();
102     }
103
104     /**
105      * Returns false as text is not a container.
106      */

107     public boolean isComposite() {
108         return false;
109     }
110
111     protected GraphicsNode instantiateGraphicsNode() {
112         return new FlowExtTextNode();
113     }
114
115     /**
116      * Returns the text node location In this case the text node may
117      * have serveral effective locations (one for each flow region).
118      * So it always returns 0,0.
119      *
120      * @param ctx the bridge context to use
121      * @param e the text element
122      */

123     protected Point2D JavaDoc getLocation(BridgeContext ctx, Element JavaDoc e) {
124         return new Point2D.Float JavaDoc(0,0);
125     }
126
127     /**
128      * Creates the attributed string which represents the given text
129      * element children.
130      *
131      * @param ctx the bridge context to use
132      * @param element the text element
133      */

134     protected AttributedString JavaDoc buildAttributedString(BridgeContext ctx,
135                                                      Element JavaDoc element) {
136         List JavaDoc rgns = getRegions(ctx, element);
137         AttributedString JavaDoc ret = getFlowDiv(ctx, element);
138         ret.addAttribute(FLOW_REGIONS, rgns, 0, 1);
139         return ret;
140     }
141
142     /**
143      * Adds glyph position attributes to an AttributedString.
144      */

145     protected void addGlyphPositionAttributes(AttributedString JavaDoc as,
146                                               Element JavaDoc element,
147                                               BridgeContext ctx) {
148         if (element.getNodeType() != Node.ELEMENT_NODE) return;
149         String JavaDoc eNS = element.getNamespaceURI();
150         if ((!eNS.equals(getNamespaceURI())) &&
151             (!eNS.equals(SVG_NAMESPACE_URI)))
152             return;
153         if (element.getLocalName() != BATIK_EXT_FLOW_TEXT_TAG) {
154             // System.out.println("Elem: " + element);
155
super.addGlyphPositionAttributes(as, element, ctx);
156             return;
157         }
158
159         for (Node n = element.getFirstChild();
160              n != null; n = n.getNextSibling()) {
161             if (n.getNodeType() != Node.ELEMENT_NODE) continue;
162             String JavaDoc nNS = n.getNamespaceURI();
163             if ((!getNamespaceURI().equals(nNS)) &&
164                 (!SVG_NAMESPACE_URI.equals(nNS))) {
165                 continue;
166             }
167             Element JavaDoc e = (Element JavaDoc)n;
168             String JavaDoc ln = e.getLocalName();
169             if (ln.equals(BATIK_EXT_FLOW_DIV_TAG)) {
170                 // System.out.println("D Elem: " + e);
171
super.addGlyphPositionAttributes(as, e, ctx);
172                 return;
173             }
174         }
175     }
176
177     protected void addChildGlyphPositionAttributes(AttributedString JavaDoc as,
178                                                    Element JavaDoc element,
179                                                    BridgeContext ctx) {
180         // Add Paint attributres for children of text element
181
for (Node child = element.getFirstChild();
182              child != null;
183              child = child.getNextSibling()) {
184             if (child.getNodeType() != Node.ELEMENT_NODE) {
185                 continue;
186             }
187             String JavaDoc cNS = child.getNamespaceURI();
188             if ((!getNamespaceURI().equals(cNS)) &&
189                 (!SVG_NAMESPACE_URI.equals(cNS))) {
190                 continue;
191             }
192             String JavaDoc ln = child.getLocalName();
193             if (ln.equals(BATIK_EXT_FLOW_PARA_TAG) ||
194                 ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG) ||
195                 ln.equals(BATIK_EXT_FLOW_LINE_TAG) ||
196                 ln.equals(BATIK_EXT_FLOW_SPAN_TAG) ||
197                 ln.equals(SVG_A_TAG) ||
198                 ln.equals(SVG_TREF_TAG)) {
199                 addGlyphPositionAttributes(as, (Element JavaDoc)child, ctx);
200             }
201         }
202     }
203
204     protected void addNullPaintAttributes(AttributedString JavaDoc as,
205                                           Element JavaDoc element,
206                                           BridgeContext ctx) {
207         if (element.getNodeType() != Node.ELEMENT_NODE) return;
208         String JavaDoc eNS = element.getNamespaceURI();
209         if ((!eNS.equals(getNamespaceURI())) &&
210             (!eNS.equals(SVG_NAMESPACE_URI)))
211             return;
212         if (element.getLocalName() != BATIK_EXT_FLOW_TEXT_TAG) {
213             // System.out.println("Elem: " + element);
214
super.addNullPaintAttributes(as, element, ctx);
215             return;
216         }
217
218         for (Node n = element.getFirstChild();
219              n != null; n = n.getNextSibling()) {
220             if (n.getNodeType() != Node.ELEMENT_NODE) continue;
221             if (!getNamespaceURI().equals(n.getNamespaceURI())) continue;
222             Element JavaDoc e = (Element JavaDoc)n;
223             String JavaDoc ln = e.getLocalName();
224             if (ln.equals(BATIK_EXT_FLOW_DIV_TAG)) {
225                 // System.out.println("D Elem: " + e);
226
super.addNullPaintAttributes(as, e, ctx);
227                 return;
228             }
229         }
230     }
231
232
233     protected void addChildNullPaintAttributes(AttributedString JavaDoc as,
234                                                Element JavaDoc element,
235                                                BridgeContext ctx) {
236         // Add Paint attributres for children of text element
237
for (Node child = element.getFirstChild();
238              child != null;
239              child = child.getNextSibling()) {
240             if (child.getNodeType() != Node.ELEMENT_NODE) {
241                 continue;
242             }
243             String JavaDoc cNS = child.getNamespaceURI();
244             if ((!getNamespaceURI().equals(cNS)) &&
245                 (!SVG_NAMESPACE_URI.equals(cNS))) {
246                 continue;
247             }
248             String JavaDoc ln = child.getLocalName();
249             if (ln.equals(BATIK_EXT_FLOW_PARA_TAG) ||
250                 ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG) ||
251                 ln.equals(BATIK_EXT_FLOW_LINE_TAG) ||
252                 ln.equals(BATIK_EXT_FLOW_SPAN_TAG) ||
253                 ln.equals(SVG_A_TAG) ||
254                 ln.equals(SVG_TREF_TAG)) {
255                 Element JavaDoc childElement = (Element JavaDoc)child;
256                 addNullPaintAttributes(as, childElement, ctx);
257             }
258         }
259     }
260
261     /**
262      * Adds painting attributes to an AttributedString.
263      */

264     protected void addPaintAttributes(AttributedString JavaDoc as,
265                                       Element JavaDoc element,
266                                       TextNode node,
267                                       TextPaintInfo parentPI,
268                                       BridgeContext ctx) {
269         if (element.getNodeType() != Node.ELEMENT_NODE) return;
270         String JavaDoc eNS = element.getNamespaceURI();
271         if ((!eNS.equals(getNamespaceURI())) &&
272             (!eNS.equals(SVG_NAMESPACE_URI)))
273             return;
274         if (element.getLocalName() != BATIK_EXT_FLOW_TEXT_TAG) {
275             // System.out.println("Elem: " + element);
276
super.addPaintAttributes(as, element, node, parentPI, ctx);
277             return;
278         }
279
280         for (Node n = element.getFirstChild();
281              n != null; n = n.getNextSibling()) {
282             if (n.getNodeType() != Node.ELEMENT_NODE) continue;
283             if (!getNamespaceURI().equals(n.getNamespaceURI())) continue;
284             Element JavaDoc e = (Element JavaDoc)n;
285             String JavaDoc ln = e.getLocalName();
286             if (ln.equals(BATIK_EXT_FLOW_DIV_TAG)) {
287                 // System.out.println("D Elem: " + e);
288
super.addPaintAttributes(as, e, node, parentPI, ctx);
289                 return;
290             }
291         }
292     }
293
294     protected void addChildPaintAttributes(AttributedString JavaDoc as,
295                                            Element JavaDoc element,
296                                            TextNode node,
297                                            TextPaintInfo parentPI,
298                                            BridgeContext ctx) {
299         // Add Paint attributres for children of text element
300
for (Node child = element.getFirstChild();
301              child != null;
302              child = child.getNextSibling()) {
303             if (child.getNodeType() != Node.ELEMENT_NODE) {
304                 continue;
305             }
306             String JavaDoc cNS = child.getNamespaceURI();
307             if ((!getNamespaceURI().equals(cNS)) &&
308                 (!SVG_NAMESPACE_URI.equals(cNS))) {
309                 continue;
310             }
311             String JavaDoc ln = child.getLocalName();
312             if (ln.equals(BATIK_EXT_FLOW_PARA_TAG) ||
313                 ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG) ||
314                 ln.equals(BATIK_EXT_FLOW_LINE_TAG) ||
315                 ln.equals(BATIK_EXT_FLOW_SPAN_TAG) ||
316                 ln.equals(SVG_A_TAG) ||
317                 ln.equals(SVG_TREF_TAG)) {
318                 Element JavaDoc childElement = (Element JavaDoc)child;
319                 TextPaintInfo pi = getTextPaintInfo(childElement, node,
320                                                     parentPI, ctx);
321                 addPaintAttributes(as, childElement, node, pi, ctx);
322             }
323         }
324     }
325
326     protected AttributedString JavaDoc getFlowDiv
327         (BridgeContext ctx, Element JavaDoc element) {
328         for (Node n = element.getFirstChild();
329              n != null; n = n.getNextSibling()) {
330             if (n.getNodeType() != Node.ELEMENT_NODE) continue;
331             if (!getNamespaceURI().equals(n.getNamespaceURI())) continue;
332             Element JavaDoc e = (Element JavaDoc)n;
333
334             String JavaDoc ln = n.getLocalName();
335             if (ln.equals(BATIK_EXT_FLOW_DIV_TAG)) {
336                 return gatherFlowPara(ctx, e);
337             }
338         }
339         return null;
340     }
341
342     protected AttributedString JavaDoc gatherFlowPara
343         (BridgeContext ctx, Element JavaDoc div) {
344         AttributedStringBuffer asb = new AttributedStringBuffer();
345         List JavaDoc paraEnds = new ArrayList JavaDoc();
346         List JavaDoc paraElems = new ArrayList JavaDoc();
347         List JavaDoc lnLocs = new ArrayList JavaDoc();
348         for (Node n = div.getFirstChild();
349              n != null; n = n.getNextSibling()) {
350             if (n.getNodeType() != Node.ELEMENT_NODE) continue;
351             if (!getNamespaceURI().equals(n.getNamespaceURI())) continue;
352             Element JavaDoc e = (Element JavaDoc)n;
353
354             String JavaDoc ln = e.getLocalName();
355             if (ln.equals(BATIK_EXT_FLOW_PARA_TAG)) {
356                 fillAttributedStringBuffer(ctx, e, true, null, asb, lnLocs);
357
358                 paraElems.add(e);
359                 paraEnds.add(new Integer JavaDoc(asb.length()));
360             } else if (ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG)) {
361                 fillAttributedStringBuffer(ctx, e, true, null, asb, lnLocs);
362
363                 paraElems.add(e);
364                 paraEnds.add(new Integer JavaDoc(asb.length()));
365             }
366         }
367
368         // Layer in the PARAGRAPH/LINE_BREAK Attributes so we can
369
// break up text chunks.
370
AttributedString JavaDoc ret = asb.toAttributedString();
371
372         // Note: The Working Group (in conjunction with XHTML working
373
// group) has decided that multiple line elements collapse.
374
int prevLN = 0;
375         Iterator JavaDoc lnIter = lnLocs.iterator();
376         while (lnIter.hasNext()) {
377             int nextLN = ((Integer JavaDoc)lnIter.next()).intValue();
378             if (nextLN == prevLN) continue;
379
380             ret.addAttribute(FLOW_LINE_BREAK,
381                              new Object JavaDoc(),
382                              prevLN, nextLN);
383             // System.out.println("Attr: [" + prevLN + "," + nextLN + "]");
384
prevLN = nextLN;
385         }
386
387         int start=0;
388         int end;
389         List JavaDoc emptyPara = null;
390         for (int i=0; i<paraElems.size(); i++, start=end) {
391             Element JavaDoc elem = (Element JavaDoc)paraElems.get(i);
392             end = ((Integer JavaDoc)paraEnds.get(i)).intValue();
393             if (start == end) {
394                 if (emptyPara == null)
395                     emptyPara = new LinkedList JavaDoc();
396                 emptyPara.add(makeMarginInfo(elem));
397                 continue;
398             }
399             // System.out.println("Para: [" + start + ", " + end + "]");
400
ret.addAttribute(FLOW_PARAGRAPH, makeMarginInfo(elem), start, end);
401             if (emptyPara != null) {
402                 ret.addAttribute(FLOW_EMPTY_PARAGRAPH, emptyPara, start, end);
403                 emptyPara = null;
404             }
405         }
406
407         return ret;
408     }
409
410     protected List JavaDoc getRegions(BridgeContext ctx, Element JavaDoc element) {
411         List JavaDoc ret = new LinkedList JavaDoc();
412         for (Node n = element.getFirstChild();
413              n != null; n = n.getNextSibling()) {
414             
415             if (n.getNodeType() != Node.ELEMENT_NODE) continue;
416             if (!getNamespaceURI().equals(n.getNamespaceURI())) continue;
417
418             Element JavaDoc e = (Element JavaDoc)n;
419
420             String JavaDoc ln = e.getLocalName();
421             if (!BATIK_EXT_FLOW_REGION_TAG.equals(ln)) continue;
422
423             // our default alignment is to the top of the flow rect.
424
float verticalAlignment = 0.0f;
425             String JavaDoc verticalAlignmentAttribute
426                 = e.getAttribute(BATIK_EXT_VERTICAL_ALIGN_ATTRIBUTE);
427             
428             if ((verticalAlignmentAttribute != null) &&
429                 (verticalAlignmentAttribute.length() > 0)) {
430                 if (BATIK_EXT_ALIGN_TOP_VALUE.equals
431                     (verticalAlignmentAttribute)) {
432                     verticalAlignment = 0.0f;
433                 } else if (BATIK_EXT_ALIGN_MIDDLE_VALUE.equals
434                            (verticalAlignmentAttribute)) {
435                     verticalAlignment = 0.5f;
436                 } else if (BATIK_EXT_ALIGN_BOTTOM_VALUE.equals
437                            (verticalAlignmentAttribute)) {
438                     verticalAlignment = 1.0f;
439                 }
440             }
441             
442             gatherRegionInfo(ctx, e, verticalAlignment, ret);
443         }
444
445         return ret;
446     }
447     
448     protected void gatherRegionInfo(BridgeContext ctx, Element JavaDoc rgn,
449                                     float verticalAlign, List JavaDoc regions) {
450
451         for (Node n = rgn.getFirstChild();
452              n != null; n = n.getNextSibling()) {
453
454             if (n.getNodeType() != Node.ELEMENT_NODE) continue;
455             if (!getNamespaceURI().equals(n.getNamespaceURI())) continue;
456             Element JavaDoc e = (Element JavaDoc)n;
457             String JavaDoc ln = n.getLocalName();
458             if (ln.equals(SVGConstants.SVG_RECT_TAG)) {
459                 UnitProcessor.Context uctx;
460                 uctx = UnitProcessor.createContext(ctx, e);
461
462                 RegionInfo ri = buildRegion(uctx, e, verticalAlign);
463                 if (ri != null)
464                     regions.add(ri);
465             }
466         }
467     }
468
469     protected RegionInfo buildRegion(UnitProcessor.Context uctx,
470                                      Element JavaDoc e,
471                                      float verticalAlignment) {
472         String JavaDoc s;
473
474         // 'x' attribute - default is 0
475
s = e.getAttribute(BATIK_EXT_X_ATTRIBUTE);
476         float x = 0;
477         if (s.length() != 0) {
478             x = UnitProcessor.svgHorizontalCoordinateToUserSpace
479                 (s, BATIK_EXT_X_ATTRIBUTE, uctx);
480         }
481
482         // 'y' attribute - default is 0
483
s = e.getAttribute(BATIK_EXT_Y_ATTRIBUTE);
484         float y = 0;
485         if (s.length() != 0) {
486             y = UnitProcessor.svgVerticalCoordinateToUserSpace
487                 (s, BATIK_EXT_Y_ATTRIBUTE, uctx);
488         }
489
490         // 'width' attribute - required
491
s = e.getAttribute(BATIK_EXT_WIDTH_ATTRIBUTE);
492         float w;
493         if (s.length() != 0) {
494             w = UnitProcessor.svgHorizontalLengthToUserSpace
495                 (s, BATIK_EXT_WIDTH_ATTRIBUTE, uctx);
496         } else {
497             throw new BridgeException
498                 (e, ERR_ATTRIBUTE_MISSING,
499                  new Object JavaDoc[] {BATIK_EXT_WIDTH_ATTRIBUTE, s});
500         }
501     // A value of zero disables rendering of the element
502
if (w == 0) {
503         return null;
504     }
505
506         // 'height' attribute - required
507
s = e.getAttribute(BATIK_EXT_HEIGHT_ATTRIBUTE);
508         float h;
509         if (s.length() != 0) {
510             h = UnitProcessor.svgVerticalLengthToUserSpace
511                 (s, BATIK_EXT_HEIGHT_ATTRIBUTE, uctx);
512         } else {
513             throw new BridgeException
514                 (e, ERR_ATTRIBUTE_MISSING,
515                  new Object JavaDoc[] {BATIK_EXT_HEIGHT_ATTRIBUTE, s});
516         }
517     // A value of zero disables rendering of the element
518
if (h == 0) {
519         return null;
520     }
521
522         return new RegionInfo(x,y,w,h,verticalAlignment);
523     }
524
525     /**
526      * Fills the given AttributedStringBuffer.
527      */

528     protected void fillAttributedStringBuffer(BridgeContext ctx,
529                                               Element JavaDoc element,
530                                               boolean top,
531                                               Integer JavaDoc bidiLevel,
532                                               AttributedStringBuffer asb,
533                                               List JavaDoc lnLocs) {
534         // 'requiredFeatures', 'requiredExtensions', 'systemLanguage' &
535
// 'display="none".
536
if ((!SVGUtilities.matchUserAgent(element, ctx.getUserAgent())) ||
537             (!CSSUtilities.convertDisplay(element))) {
538             return;
539         }
540
541         String JavaDoc s = XMLSupport.getXMLSpace(element);
542         boolean preserve = s.equals(SVG_PRESERVE_VALUE);
543         boolean prevEndsWithSpace;
544         Element JavaDoc nodeElement = element;
545
546         if (top)
547             endLimit = 0;
548         if (preserve)
549             endLimit = asb.length();
550         
551     Map JavaDoc map = getAttributeMap(ctx, element, null, bidiLevel);
552     Object JavaDoc o = map.get(TextAttribute.BIDI_EMBEDDING);
553         Integer JavaDoc subBidiLevel = bidiLevel;
554     if (o != null)
555         subBidiLevel = (Integer JavaDoc)o;
556
557         for (Node n = element.getFirstChild();
558              n != null;
559              n = n.getNextSibling()) {
560             
561             if (preserve) {
562                 prevEndsWithSpace = false;
563             } else {
564                 if (asb.length() == 0)
565                     prevEndsWithSpace = true;
566                 else
567                     prevEndsWithSpace = (asb.getLastChar() == ' ');
568             }
569
570             switch (n.getNodeType()) {
571             case Node.ELEMENT_NODE:
572                 // System.out.println("Element: " + n);
573
if ((!getNamespaceURI().equals(n.getNamespaceURI())) &&
574                     (!SVG_NAMESPACE_URI.equals(n.getNamespaceURI())))
575                     break;
576                 
577                 nodeElement = (Element JavaDoc)n;
578
579                 String JavaDoc ln = n.getLocalName();
580
581                 if (ln.equals(BATIK_EXT_FLOW_LINE_TAG)) {
582                     fillAttributedStringBuffer(ctx, nodeElement,
583                                                false, subBidiLevel,
584                            asb, lnLocs);
585                     // System.out.println("Line: " + asb.length() +
586
// " - '" + asb + "'");
587
lnLocs.add(new Integer JavaDoc(asb.length()));
588                 } else if (ln.equals(BATIK_EXT_FLOW_SPAN_TAG) ||
589                            ln.equals(SVG_ALT_GLYPH_TAG)) {
590                     fillAttributedStringBuffer(ctx, nodeElement,
591                                                false, subBidiLevel,
592                            asb, lnLocs);
593                 } else if (ln.equals(SVG_A_TAG)) {
594                     if (ctx.isInteractive()) {
595                         EventTarget JavaDoc target = (EventTarget JavaDoc)nodeElement;
596                         UserAgent ua = ctx.getUserAgent();
597                         target.addEventListener
598                             (SVG_EVENT_CLICK,
599                              new SVGAElementBridge.AnchorListener(ua),
600                              false);
601                     
602                         target.addEventListener
603                             (SVG_EVENT_MOUSEOVER,
604                              new SVGAElementBridge.CursorMouseOverListener(ua),
605                              false);
606                     
607                         target.addEventListener
608                             (SVG_EVENT_MOUSEOUT,
609                              new SVGAElementBridge.CursorMouseOutListener(ua),
610                              false);
611                     }
612                     fillAttributedStringBuffer(ctx,
613                                                nodeElement,
614                                                false, subBidiLevel,
615                                                asb, lnLocs);
616                 } else if (ln.equals(SVG_TREF_TAG)) {
617                     String JavaDoc uriStr = XLinkSupport.getXLinkHref((Element JavaDoc)n);
618                     Element JavaDoc ref = ctx.getReferencedElement((Element JavaDoc)n, uriStr);
619                     s = TextUtilities.getElementContent(ref);
620                     s = normalizeString(s, preserve, prevEndsWithSpace);
621                     if (s != null) {
622                         Map JavaDoc m = getAttributeMap(ctx, nodeElement, null,
623                         bidiLevel);
624                         asb.append(s, m);
625                     }
626                 }
627                 break;
628                 
629             case Node.TEXT_NODE:
630             case Node.CDATA_SECTION_NODE:
631                 s = n.getNodeValue();
632                 s = normalizeString(s, preserve, prevEndsWithSpace);
633                 asb.append(s, map);
634                 if (preserve)
635                     endLimit = asb.length();
636             }
637         }
638
639         if (top) {
640             while ((endLimit < asb.length()) && (asb.getLastChar() == ' '))
641                 asb.stripLast();
642         }
643     }
644
645     /**
646      * Returns the map to pass to the current characters.
647      */

648     protected Map JavaDoc getAttributeMap(BridgeContext ctx,
649                                   Element JavaDoc element,
650                                   TextPath textPath,
651                                   Integer JavaDoc bidiLevel) {
652         Map JavaDoc result = super.getAttributeMap(ctx, element, textPath, bidiLevel);
653         String JavaDoc s;
654         s = element.getAttribute(BATIK_EXT_PREFORMATTED_ATTRIBUTE);
655         if (s.length() != 0) {
656             if (s.equals("true")) {
657                 result.put(PREFORMATTED, Boolean.TRUE);
658             }
659         }
660         return result;
661     }
662
663
664     protected void checkMap(Map JavaDoc attrs) {
665         if (attrs.containsKey(TEXTPATH)) {
666             return; // Problem, unsupported attr
667
}
668
669         if (attrs.containsKey(ANCHOR_TYPE)) {
670             return; // Problem, unsupported attr
671
}
672
673         if (attrs.containsKey(LETTER_SPACING)) {
674             return; // Problem, unsupported attr
675
}
676
677         if (attrs.containsKey(WORD_SPACING)) {
678             return; // Problem, unsupported attr
679
}
680
681         if (attrs.containsKey(KERNING)) {
682             return; // Problem, unsupported attr
683
}
684     }
685
686     protected final static
687         GVTAttributedCharacterIterator.TextAttribute TEXTPATH =
688         GVTAttributedCharacterIterator.TextAttribute.TEXTPATH;
689
690     protected final static
691         GVTAttributedCharacterIterator.TextAttribute ANCHOR_TYPE =
692         GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE;
693
694     protected final static
695         GVTAttributedCharacterIterator.TextAttribute LETTER_SPACING =
696         GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING;
697
698     protected final static
699         GVTAttributedCharacterIterator.TextAttribute WORD_SPACING =
700         GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING;
701
702     protected final static
703         GVTAttributedCharacterIterator.TextAttribute KERNING =
704         GVTAttributedCharacterIterator.TextAttribute.KERNING;
705
706     public static class LineBreakInfo {
707         int breakIdx;
708         float lineAdvAdj;
709         boolean relative;
710         /**
711          * @param breakIdx The character after which to break.
712          * @param lineAdvAdj The line advance adjustment.
713          * @param relative If true lineAdvAdj must be multiplied by
714          * the line height.
715          */

716         public LineBreakInfo(int breakIdx, float lineAdvAdj, boolean relative){
717             this.breakIdx = breakIdx;
718             this.lineAdvAdj = lineAdvAdj;
719             this.relative = relative;
720         }
721         public int getBreakIdx() { return breakIdx; }
722         public boolean isRelative() { return relative; }
723         public float getLineAdvAdj() { return lineAdvAdj; }
724     }
725
726     public MarginInfo makeMarginInfo(Element JavaDoc e) {
727         String JavaDoc s;
728         float top=0, right=0, bottom=0, left=0;
729
730         s = e.getAttribute(BATIK_EXT_MARGIN_ATTRIBUTE);
731         try {
732             if (s.length() != 0) {
733                 float f = Float.parseFloat(s);
734                 top=right=bottom=left=f;
735             }
736         } catch(NumberFormatException JavaDoc nfe) { /* nothing */ }
737
738         s = e.getAttribute(BATIK_EXT_TOP_MARGIN_ATTRIBUTE);
739         try {
740             if (s.length() != 0) {
741                 float f = Float.parseFloat(s);
742                 top = f;
743             }
744         } catch(NumberFormatException JavaDoc nfe) { /* nothing */ }
745         s = e.getAttribute(BATIK_EXT_RIGHT_MARGIN_ATTRIBUTE);
746         try {
747             if (s.length() != 0) {
748                 float f = Float.parseFloat(s);
749                 right = f;
750             }
751         } catch(NumberFormatException JavaDoc nfe) { /* nothing */ }
752         s = e.getAttribute(BATIK_EXT_BOTTOM_MARGIN_ATTRIBUTE);
753         try {
754             if (s.length() != 0) {
755                 float f = Float.parseFloat(s);
756                 bottom = f;
757             }
758         } catch(NumberFormatException JavaDoc nfe) { /* nothing */ }
759         s = e.getAttribute(BATIK_EXT_LEFT_MARGIN_ATTRIBUTE);
760         try {
761             if (s.length() != 0) {
762                 float f = Float.parseFloat(s);
763                 left = f;
764             }
765         } catch(NumberFormatException JavaDoc nfe) { /* nothing */ }
766
767         float indent = 0;
768         s = e.getAttribute(BATIK_EXT_INDENT_ATTRIBUTE);
769         try {
770             if (s.length() != 0) {
771                 float f = Float.parseFloat(s);
772                 indent = f;
773             }
774         } catch(NumberFormatException JavaDoc nfe) { /* nothing */ }
775
776         int justification = MarginInfo.JUSTIFY_START;
777         s = e.getAttribute(BATIK_EXT_JUSTIFICATION_ATTRIBUTE);
778         try {
779             if (s.length() != 0) {
780                 if (BATIK_EXT_JUSTIFICATION_START_VALUE.equals(s)) {
781                     justification = MarginInfo.JUSTIFY_START;
782                 } else if (BATIK_EXT_JUSTIFICATION_MIDDLE_VALUE.equals(s)) {
783                     justification = MarginInfo.JUSTIFY_MIDDLE;
784                 } else if (BATIK_EXT_JUSTIFICATION_END_VALUE.equals(s)) {
785                     justification = MarginInfo.JUSTIFY_END;
786                 } else if (BATIK_EXT_JUSTIFICATION_FULL_VALUE.equals(s)) {
787                     justification = MarginInfo.JUSTIFY_FULL;
788                 }
789             }
790         } catch(NumberFormatException JavaDoc nfe) { /* nothing */ }
791
792         String JavaDoc ln = e.getLocalName();
793         boolean rgnBr = ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG);
794         return new MarginInfo(top, right, bottom, left,
795                               indent, justification, rgnBr);
796     }
797
798
799 }
800
Popular Tags