You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by de...@apache.org on 2005/10/17 12:52:40 UTC

svn commit: r325875 - in /xmlgraphics/batik/trunk/sources/org/apache/batik: bridge/SVGTextElementBridge.java bridge/svg12/SVGFlowRootElementBridge.java dom/AbstractParentNode.java gvt/TextNode.java gvt/flow/FlowGlyphLayout.java

Author: deweese
Date: Mon Oct 17 03:52:26 2005
New Revision: 325875

URL: http://svn.apache.org/viewcvs?rev=325875&view=rev
Log:
Fix for NPE when flowPara is empty.
Now generates null ACI for TextNode (instead of unadorned
'space').

Modified:
    xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGTextElementBridge.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVGFlowRootElementBridge.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractParentNode.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/TextNode.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGTextElementBridge.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGTextElementBridge.java?rev=325875&r1=325874&r2=325875&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGTextElementBridge.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGTextElementBridge.java Mon Oct 17 03:52:26 2005
@@ -544,12 +544,17 @@
     protected void computeLaidoutText(BridgeContext ctx, 
                                       Element e,
                                       GraphicsNode node) {
+        TextNode tn = (TextNode)node;
         AttributedString as = buildAttributedString(ctx, e);
+        if (as == null) {
+            tn.setAttributedCharacterIterator(null);
+            return;
+        }
+
         addGlyphPositionAttributes(as, e, ctx);
         if (ctx.isDynamic()) {
             laidoutText = new AttributedString(as.getIterator());
         }
-        TextNode tn = (TextNode)node;
         elemTPI.clear();
         // Add null TPI objects to the text (after we set it on the
         // Text we will swap in the correct values.
@@ -756,6 +761,8 @@
             return;
 
         TextNode tn = (TextNode)node;
+        if (tn.getAttributedCharacterIterator() == null)
+            return;
 
         TextPaintInfo pi, oldPI;
         if ( cssProceedElement == e ){
@@ -785,6 +792,8 @@
 
     int getElementStartIndex
         (AttributedCharacterIterator aci, Element element) {
+        if (aci == null) return -1;
+
         // calculate which chars in the string belong to this element
         for (int i = 0; i < aci.getEndIndex();) {
             aci.setIndex(i);
@@ -799,6 +808,8 @@
 
     int getElementEndIndex
         (AttributedCharacterIterator aci, Element element) {
+        if (aci == null) return -1;
+
         // calculate which chars in the string belong to this element
         for (int i = aci.getEndIndex()-1; i >= 0;) {
             aci.setIndex(i);
@@ -1138,7 +1149,7 @@
         public AttributedString toAttributedString() {
             switch (count) {
             case 0:
-                return new AttributedString(" ");
+                return null;
             case 1:
                 return new AttributedString((String)strings.get(0),
                                             (Map)attributes.get(0));
@@ -1710,8 +1721,10 @@
      */
     protected TextPaintInfo getParentTextPaintInfo
         (AttributedCharacterIterator aci, Element child) {
-        Element parent = null;
+        if (aci == null)
+            return new TextPaintInfo();
 
+        Element parent = null;
         // calculate which chars in the string belong to the parent
         int firstChar = -1;
         for (int i = 0; i < aci.getEndIndex();) {
@@ -2210,7 +2223,10 @@
      */
     protected int getNumberOfChars(Element element){
 
-        AttributedCharacterIterator aci = ((TextNode)node).getAttributedCharacterIterator();
+        AttributedCharacterIterator aci;
+        aci = ((TextNode)node).getAttributedCharacterIterator();
+        if (aci == null)
+            return 0;
 
         //get the index in the aci for the first character
         //of the element
@@ -2233,6 +2249,7 @@
 
         AttributedCharacterIterator aci;
         aci = ((TextNode)node).getAttributedCharacterIterator();
+        if (aci == null) return null;
 
         int firstChar = getElementStartIndex(aci,element);
 
@@ -2287,10 +2304,12 @@
      */
     protected Point2D getStartPositionOfChar(Element element,int charnum){
 
-        AttributedCharacterIterator aci = ((TextNode)node).getAttributedCharacterIterator();
+        AttributedCharacterIterator aci;
+        aci = ((TextNode)node).getAttributedCharacterIterator();
+        if (aci == null) 
+            return null;
 
         int firstChar = getElementStartIndex(aci,element);
-
         if ( firstChar == -1 )
             return null;
 
@@ -2338,9 +2357,10 @@
 
         AttributedCharacterIterator aci;
         aci = ((TextNode)node).getAttributedCharacterIterator();
+        if (aci == null)
+            return null;
 
         int firstChar = getElementStartIndex(aci,element);
-
         if ( firstChar == -1 )
             return null;
 
@@ -2389,9 +2409,11 @@
 
         AttributedCharacterIterator aci;
         aci = ((TextNode)node).getAttributedCharacterIterator();
+        if (aci == null)
+            return 0;
+
         //first the first character for the element
         int firstChar = getElementStartIndex(aci,element);
-
         if ( firstChar == -1 )
             return 0;
 
@@ -2468,8 +2490,10 @@
 
         AttributedCharacterIterator aci;
         aci = ((TextNode)node).getAttributedCharacterIterator();
-        TextNode textNode = (TextNode)node;
+        if (aci == null)
+            return -1;
 
+        TextNode textNode = (TextNode)node;
         int firstChar = getElementStartIndex(aci,element);
 
         if ( firstChar == -1 )
@@ -2602,8 +2626,10 @@
     protected void selectSubString(Element element, int charnum, int nchars) {
         AttributedCharacterIterator aci;
         aci = ((TextNode)node).getAttributedCharacterIterator();
-        TextNode textNode = (TextNode)node;
+        if (aci == null)
+            return;
 
+        TextNode textNode = (TextNode)node;
         int firstChar = getElementStartIndex(aci,element);
 
         if ( firstChar == -1 )
@@ -2633,6 +2659,10 @@
     protected int getCharNumAtPosition(Element e, float x, float y){
         
         TextNode textNode = (TextNode)node;
+        AttributedCharacterIterator aci;
+        aci = textNode.getAttributedCharacterIterator();
+        if (aci == null)
+            return -1;
 
         //check if there is an hit
         List list = getTextRuns(textNode);
@@ -2642,15 +2672,14 @@
         TextHit hit = null;
 
         for( int i = list.size()-1 ; i>= 0 && hit == null; i-- ){
-
-            hit = ((StrokingTextPainter.TextRun)list.get(i)).getLayout().hitTestChar(x,y);
+            StrokingTextPainter.TextRun textRun;
+            textRun = (StrokingTextPainter.TextRun)list.get(i);
+            hit = textRun.getLayout().hitTestChar(x,y);
         }
 
-        if ( hit == null ){
+        if ( hit == null )
             return -1;
-        }
 
-        AttributedCharacterIterator aci = ((TextNode)node).getAttributedCharacterIterator();
 
         //found an hit, check if it belong to the element
         int first = getElementStartIndex( aci, e );
@@ -2658,13 +2687,10 @@
 
         int hitIndex = hit.getCharIndex();
 
-        if ( hitIndex >= first && hitIndex <= last ){
-            
+        if ( hitIndex >= first && hitIndex <= last )
             return hitIndex - first;
-        }
-        else{
-            return -1;
-        }
+
+        return -1;
     }
 
     /**
@@ -2706,34 +2732,35 @@
         info.characterIndex = startIndex+charnum;
 
         for (int i = 0; i < list.size(); i++) {
-            StrokingTextPainter.TextRun run = 
-                (StrokingTextPainter.TextRun)list.get(i);
-
-            if ( run.getLayout().hasCharacterIndex(info.characterIndex) ){
-                info.layout = run.getLayout();
+            StrokingTextPainter.TextRun run;
+            run = (StrokingTextPainter.TextRun)list.get(i);
 
-                aci.setIndex(info.characterIndex);
+            if (!run.getLayout().hasCharacterIndex(info.characterIndex) )
+                continue;
 
-                //check is it is a altGlyph
-                if (aci.getAttribute(ALT_GLYPH_HANDLER) != null){
+            info.layout = run.getLayout();
+            
+            aci.setIndex(info.characterIndex);
+            
+            //check is it is a altGlyph
+            if (aci.getAttribute(ALT_GLYPH_HANDLER) != null){
+                info.glyphIndexStart = 0;
+                info.glyphIndexEnd = info.layout.getGlyphCount()-1;
+            } else {
+                info.glyphIndexStart = info.layout.getGlyphIndex
+                    (info.characterIndex);
+                
+                //special case when the glyph does not have a unicode
+                //associated to it, it will return -1
+                if ( info.glyphIndexStart == -1 ){
                     info.glyphIndexStart = 0;
                     info.glyphIndexEnd = info.layout.getGlyphCount()-1;
-                } else {
-                    info.glyphIndexStart = info.layout.getGlyphIndex
-                        (info.characterIndex);
-
-                    //special case when the glyph does not have a unicode
-                    //associated to it, it will return -1
-                    if ( info.glyphIndexStart == -1 ){
-                        info.glyphIndexStart = 0;
-                        info.glyphIndexEnd = info.layout.getGlyphCount()-1;
-                    }
-                    else{
-                        info.glyphIndexEnd = info.glyphIndexStart;
-                    }
                 }
-                return info;
+                else{
+                    info.glyphIndexEnd = info.glyphIndexStart;
+                }
             }
+            return info;
         }
         return null;
     }
@@ -2766,9 +2793,13 @@
 
     public Set getTextIntersectionSet(AffineTransform at,
                                        Rectangle2D rect) {
+        Set elems = new HashSet();
+
         TextNode tn  = (TextNode)node;
         List list = tn.getTextRuns();
-        Set elems = new HashSet();
+        if (list == null)
+            return elems;
+
         for (int i = 0 ; i < list.size(); i++) {
             StrokingTextPainter.TextRun run;
             run = (StrokingTextPainter.TextRun)list.get(i);
@@ -2809,8 +2840,11 @@
         TextNode tn = (TextNode)node;
 
         Set elems = new HashSet();
-        Set reject = new HashSet();
         List list = tn.getTextRuns();
+        if (list == null)
+            return elems;
+
+        Set reject = new HashSet();
         for (int i = 0 ; i < list.size(); i++) {
             StrokingTextPainter.TextRun run;
             run = (StrokingTextPainter.TextRun)list.get(i);
@@ -2863,6 +2897,10 @@
         if (txtBridge == null) return false;
 
         TextNode tn      = (TextNode)txtBridge.node;
+        List list = tn.getTextRuns();
+        if (list == null) 
+            return false;
+
         Element  txtElem = txtBridge.e;
 
         AffineTransform at = tn.getGlobalTransform();
@@ -2873,7 +2911,6 @@
         tnRect = at.createTransformedShape(tnRect).getBounds2D();
         if (!rect.intersects(tnRect)) return false;
 
-        List list = tn.getTextRuns();
         for (int i = 0 ; i < list.size(); i++) {
             StrokingTextPainter.TextRun run;
             run = (StrokingTextPainter.TextRun)list.get(i);
@@ -2931,11 +2968,13 @@
         if (txtBridge == null) return null;
 
         TextNode tn      = (TextNode)txtBridge.node;
-        Element  txtElem = txtBridge.e;
+        List list = tn.getTextRuns();
+        if (list == null) 
+            return null;
 
+        Element  txtElem = txtBridge.e;
         Rectangle2D ret = null;
-        List list = tn.getTextRuns();
-        if (list == null) return null;
+
         for (int i = 0 ; i < list.size(); i++) {
             StrokingTextPainter.TextRun run;
             run = (StrokingTextPainter.TextRun)list.get(i);

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVGFlowRootElementBridge.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVGFlowRootElementBridge.java?rev=325875&r1=325874&r2=325875&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVGFlowRootElementBridge.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVGFlowRootElementBridge.java Mon Oct 17 03:52:26 2005
@@ -81,21 +81,45 @@
  */
 public class SVGFlowRootElementBridge extends SVG12TextElementBridge {
 
-    public static final AttributedCharacterIterator.Attribute FLOW_PARAGRAPH
-        = GVTAttributedCharacterIterator.TextAttribute.FLOW_PARAGRAPH;
+    public static final 
+        AttributedCharacterIterator.Attribute FLOW_PARAGRAPH =
+        GVTAttributedCharacterIterator.TextAttribute.FLOW_PARAGRAPH;
+
+    public static final 
+        AttributedCharacterIterator.Attribute FLOW_EMPTY_PARAGRAPH =
+        GVTAttributedCharacterIterator.TextAttribute.FLOW_EMPTY_PARAGRAPH;
+
+    public static final 
+        AttributedCharacterIterator.Attribute FLOW_LINE_BREAK =
+        GVTAttributedCharacterIterator.TextAttribute.FLOW_LINE_BREAK;
+    
+    public static final 
+        AttributedCharacterIterator.Attribute FLOW_REGIONS =
+        GVTAttributedCharacterIterator.TextAttribute.FLOW_REGIONS;
+
+    public static final 
+        AttributedCharacterIterator.Attribute LINE_HEIGHT =
+        GVTAttributedCharacterIterator.TextAttribute.LINE_HEIGHT;
 
-    public static final AttributedCharacterIterator.Attribute 
-        FLOW_EMPTY_PARAGRAPH
-        = GVTAttributedCharacterIterator.TextAttribute.FLOW_EMPTY_PARAGRAPH;
+    public final static 
+        GVTAttributedCharacterIterator.TextAttribute TEXTPATH = 
+        GVTAttributedCharacterIterator.TextAttribute.TEXTPATH;
 
-    public static final AttributedCharacterIterator.Attribute FLOW_LINE_BREAK
-        = GVTAttributedCharacterIterator.TextAttribute.FLOW_LINE_BREAK;
-    
-    public static final AttributedCharacterIterator.Attribute FLOW_REGIONS
-        = GVTAttributedCharacterIterator.TextAttribute.FLOW_REGIONS;
+    public final static 
+        GVTAttributedCharacterIterator.TextAttribute ANCHOR_TYPE = 
+        GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE;
+
+    public final static 
+        GVTAttributedCharacterIterator.TextAttribute LETTER_SPACING = 
+        GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING;
 
-    public static final AttributedCharacterIterator.Attribute LINE_HEIGHT
-        = GVTAttributedCharacterIterator.TextAttribute.LINE_HEIGHT;
+    public final static 
+        GVTAttributedCharacterIterator.TextAttribute WORD_SPACING = 
+        GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING;
+
+    public final static 
+        GVTAttributedCharacterIterator.TextAttribute KERNING = 
+        GVTAttributedCharacterIterator.TextAttribute.KERNING;
 
     /**
      * Map of flowRegion elements to their graphics nodes.
@@ -268,6 +292,9 @@
         // build text node
         GraphicsNode tn = (GraphicsNode) cgn.get(1);
         super.buildGraphicsNode(ctx, e, tn);
+
+        // Drop references once static build is completed.
+        flowRegionNodes = null;  
     }
 
     protected void computeLaidoutText(BridgeContext ctx, 
@@ -314,6 +341,7 @@
                                                      Element element) {
         List rgns = getRegions(ctx, element);
         AttributedString ret = getFlowDiv(ctx, element);
+        if (ret == null) return ret;
         ret.addAttribute(FLOW_REGIONS, rgns, 0, 1);
         TextLineBreaks.findLineBrk(ret);
         // dumpACIWord(ret);
@@ -321,6 +349,8 @@
     }
 
     protected void dumpACIWord(AttributedString as) {
+        if (as == null) return;
+
         String chars = "";
         String brkStr = "";
         AttributedCharacterIterator aci = as.getIterator();
@@ -401,6 +431,8 @@
         // Layer in the PARAGRAPH/LINE_BREAK Attributes so we can
         // break up text chunks.
         AttributedString ret = asb.toAttributedString();
+        if (ret == null) 
+            return null;
 
         // Note: The Working Group (in conjunction with XHTML working
         // group) has decided that multiple line elements collapse.
@@ -522,11 +554,11 @@
         if (preserve)
             endLimit = startLen;
         
-	Map map = getAttributeMap(ctx, element, null, bidiLevel);
-	Object o = map.get(TextAttribute.BIDI_EMBEDDING);
+        Map map = getAttributeMap(ctx, element, null, bidiLevel);
+        Object o = map.get(TextAttribute.BIDI_EMBEDDING);
         Integer subBidiLevel = bidiLevel;
-	if (o != null)
-	    subBidiLevel = (Integer)o;
+        if (o != null)
+            subBidiLevel = (Integer)o;
 
         int lineBreak = -1;
         if (lnLocs.size() != 0)
@@ -535,7 +567,7 @@
         for (Node n = getFirstChild(element);
              n != null;
              n = getNextSibling(n)) {
-            
+
             if (preserve) {
                 prevEndsWithSpace = false;
             } else {
@@ -566,7 +598,7 @@
                 if (ln.equals(SVG12Constants.SVG_FLOW_LINE_TAG)) {
                     fillAttributedStringBuffer(ctx, nodeElement, 
                                                false, subBidiLevel, 
-					       asb, lnLocs);
+                                               asb, lnLocs);
                     // System.out.println("Line: " + asb.length() + 
                     //                    " - '" +  asb + "'");
                     lineBreak = asb.length();
@@ -575,7 +607,7 @@
                            ln.equals(SVG12Constants.SVG_ALT_GLYPH_TAG)) {
                     fillAttributedStringBuffer(ctx, nodeElement,
                                                false, subBidiLevel, 
-					       asb, lnLocs);
+                                               asb, lnLocs);
                 } else if (ln.equals(SVG_A_TAG)) {
                     if (ctx.isInteractive()) {
                         NodeEventTarget target = (NodeEventTarget)nodeElement;
@@ -609,7 +641,7 @@
                     s = normalizeString(s, preserve, prevEndsWithSpace);
                     if (s != null) {
                         Map m = getAttributeMap(ctx, nodeElement, null, 
-						bidiLevel);
+                                                bidiLevel);
                         asb.append(s, m);
                     }
                 }
@@ -664,26 +696,6 @@
         
         return result;
     }
-
-    protected final static 
-        GVTAttributedCharacterIterator.TextAttribute TEXTPATH = 
-        GVTAttributedCharacterIterator.TextAttribute.TEXTPATH;
-
-    protected final static 
-        GVTAttributedCharacterIterator.TextAttribute ANCHOR_TYPE = 
-        GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE;
-
-    protected final static 
-        GVTAttributedCharacterIterator.TextAttribute LETTER_SPACING = 
-        GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING;
-
-    protected final static 
-        GVTAttributedCharacterIterator.TextAttribute WORD_SPACING = 
-        GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING;
-
-    protected final static 
-        GVTAttributedCharacterIterator.TextAttribute KERNING = 
-        GVTAttributedCharacterIterator.TextAttribute.KERNING;
 
     protected void checkMap(Map attrs) {
         if (attrs.containsKey(TEXTPATH)) {

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractParentNode.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractParentNode.java?rev=325875&r1=325874&r2=325875&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractParentNode.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractParentNode.java Mon Oct 17 03:52:26 2005
@@ -218,7 +218,7 @@
 	    ExtendedNode n = childNodes.append((ExtendedNode)newChild);
 	    n.setParentNode(this);
 
-            nodeAdded(n);
+        nodeAdded(n);
 
 	    // Mutation event
 	    fireDOMNodeInsertedEvent(n);

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/TextNode.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/TextNode.java?rev=325875&r1=325874&r2=325875&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/TextNode.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/TextNode.java Mon Oct 17 03:52:26 2005
@@ -147,7 +147,13 @@
      * Returns the text of this <tt>TextNode</tt> as a string.
      */
     public String getText() {
-        if (text == null) {
+
+        if (text != null) 
+            return text;
+
+        if (aci == null) {
+            text = "";
+        } else {
             StringBuffer buf = new StringBuffer(aci.getEndIndex());
             for (char c = aci.first();
                  c != CharacterIterator.DONE;
@@ -344,6 +350,7 @@
 
         int[] ranges = textPainter.getSelected(beginMark, endMark);
         Object o = null;
+        if (aci == null) return o;
 
         // TODO: later we can return more complex things like
         // noncontiguous selections

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java?rev=325875&r1=325874&r2=325875&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java Mon Oct 17 03:52:26 2005
@@ -63,7 +63,7 @@
 
         int numChunks = acis.length;
         // System.out.println("Len: " + acis.length + " Size: " + 
-        //                    chunkLayouts.size());
+        //                     chunkLayouts.size());
 
         // Make a list of the GlyphVectors so we can construct a
         // multiGlyphVector that makes them all look like one big
@@ -77,7 +77,7 @@
         BlockInfo [] blockInfos = new BlockInfo[acis.length];
         float      [] topSkip   = new float[acis.length];
         for (int chunk=0; clIter.hasNext(); chunk++) {
-            // System.out.println("Chunk: " + chunk);
+            // System.err.print("Chunk: " + chunk + " Str: '");
             AttributedCharacterIterator aci = acis[chunk];
             List gvl = new LinkedList();
             List layouts = (List)clIter.next();
@@ -296,7 +296,10 @@
         
         int aciWordStart = aciIdx;
         GVTFont gvtFont = (GVTFont)aci.getAttribute(GVT_FONT);
-        float lineHeight = ((Float)aci.getAttribute(LINE_HEIGHT)).floatValue();
+        float lineHeight = 1.f;
+        Float lineHeightFloat = (Float)aci.getAttribute(LINE_HEIGHT);
+        if (lineHeightFloat != null) 
+            lineHeight = lineHeightFloat.floatValue();
         int runLimit = aci.getRunLimit(szAtts);
         WordInfo prevWI = null;
         float   [] lastAdvAdj = new float  [numGlyphs];