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 ga...@apache.org on 2014/08/23 05:38:55 UTC

svn commit: r1619958 - in /xmlgraphics/batik/trunk/sources/org/apache/batik/gvt: font/ renderer/ text/

Author: gadams
Date: Sat Aug 23 03:38:55 2014
New Revision: 1619958

URL: http://svn.apache.org/r1619958
Log:
Improve support for external text painters for dealing with Bidi text.

Modified:
    xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java Sat Aug 23 03:38:55 2014
@@ -815,6 +815,15 @@ public class AWTGVTGlyphVector implement
         return charCount;
     }
 
+    @Override
+    public boolean isReversed() {
+        return false;
+    }
+
+    @Override
+    public void maybeReverse(boolean mirror) {
+    }
+
     /**
      * Draws this glyph vector.
      */

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java Sat Aug 23 03:38:55 2014
@@ -184,6 +184,17 @@ public interface GVTGlyphVector {
     int getCharacterCount(int startGlyphIndex, int endGlyphIndex);
 
     /**
+     * Return true if glyphs have been reversed.
+     */
+    boolean isReversed();
+
+    /**
+     * Reverse (and optionally mirror) glyphs if not
+     * already reversed.
+     */
+    void maybeReverse(boolean mirror);
+
+    /**
      * Draws the glyph vector.
      */
     void draw(Graphics2D graphics2D,

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java Sat Aug 23 03:38:55 2014
@@ -387,6 +387,15 @@ public class MultiGlyphVector implements
         return ret;
     }
 
+    @Override
+    public boolean isReversed() {
+        return false;
+    }
+
+    @Override
+    public void maybeReverse(boolean mirror) {
+    }
+
     /**
      * Draws the glyph vector.
      */

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java Sat Aug 23 03:38:55 2014
@@ -707,6 +707,15 @@ public final class SVGGVTGlyphVector imp
         return numChars;
     }
 
+    @Override
+    public boolean isReversed() {
+        return false;
+    }
+
+    @Override
+    public void maybeReverse(boolean mirror) {
+    }
+
     /**
      * Draws this glyph vector.
      */

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java Sat Aug 23 03:38:55 2014
@@ -232,8 +232,8 @@ public class StrokingTextPainter extends
             chunkStart += (chunkACIs[i].getEndIndex() - chunkACIs[i].getBeginIndex());
         }
 
-        // create text runs for each chunk and add them to the list
-        List textRuns = new ArrayList();
+        // Create text runs for each chunk and add them to the list.
+        List perNodeRuns = new ArrayList();
         TextChunk chunk, prevChunk=null;
         int currentChunk = 0;
 
@@ -243,23 +243,46 @@ public class StrokingTextPainter extends
             // create from the ACI.
             chunkACIs[currentChunk].first();
 
+            List perChunkRuns = new ArrayList();
             chunk = getTextChunk(node,
                                  chunkACIs[currentChunk],
                                  chunkCharMaps != null ? chunkCharMaps[currentChunk] : null,
-                                 textRuns,
+                                 perChunkRuns,
                                  prevChunk);
 
-            // Adjust according to text-anchor property value
+            // Perform bidi reordering on chunk's runs. Must be performed before
+            // adjusting chunk offsets.
+            perChunkRuns = reorderTextRuns(chunk, perChunkRuns);
+
+            // Adjust according to text-anchor property value.
             chunkACIs[currentChunk].first();
             if (chunk != null) {
-                location = adjustChunkOffsets(location, textRuns, chunk);
+                location = adjustChunkOffsets(location, perChunkRuns, chunk);
             }
+            
+            // Append per chunk runs to overall node runs.
+            perNodeRuns.addAll(perChunkRuns);
+
             prevChunk = chunk;
             currentChunk++;
 
         } while (chunk != null && currentChunk < chunkACIs.length);
 
-        return textRuns;
+        return perNodeRuns;
+    }
+
+    /**
+     * Reorder text runs as required by bidi algorithm.
+     * @param runs - unordered runs
+     * @return reordered runs
+     */
+    protected List reorderTextRuns(TextChunk chunk, List runs) {
+        // NOP here since they were previous reordered (by batik's
+        // BidiAttributedCharacterIterator); derived painters (e.g., FOP) may
+        // use a different strategy.
+        // N.B. batik doesn't sub-divide a text chunk at bidi level
+        // boundaries; however, derived painters may do so.
+        return runs;
     }
 
     /**
@@ -577,6 +600,10 @@ public class StrokingTextPainter extends
         return DefaultFontFamilyResolver.SINGLETON;
     }
 
+    protected Set getTextRunBoundaryAttributes() {
+        return extendedAtts;
+    }
+
     protected TextChunk getTextChunk(TextNode node,
                                      AttributedCharacterIterator aci,
                                      int [] charMap,
@@ -596,9 +623,10 @@ public class StrokingTextPainter extends
         Point2D.Float advance       = new Point2D.Float(0,0);
         boolean isChunkStart  = true;
         TextSpanLayout layout = null;
+        Set textRunBoundaryAttributes = getTextRunBoundaryAttributes();
         do {
-            int start = aci.getRunStart(extendedAtts);
-            int end   = aci.getRunLimit(extendedAtts);
+            int start = aci.getRunStart(textRunBoundaryAttributes);
+            int end   = aci.getRunLimit(textRunBoundaryAttributes);
 
             AttributedCharacterIterator runaci;
             runaci = new AttributedCharacterSpanIterator(aci, start, end);
@@ -691,8 +719,8 @@ public class StrokingTextPainter extends
             visualAdvance = new Point2D.Float
             ((float)(chunk.advance.getX() + lastW -
                      lastMetrics.getHorizontalAdvance()),
-             (float)(chunk.advance.getY() - lastMetrics.getVerticalAdvance() +
-                     lastH));
+             (float)(chunk.advance.getY() + lastH -
+                     lastMetrics.getVerticalAdvance()));
         } else {
             Point2D advance    = chunk.advance;
 
@@ -702,19 +730,19 @@ public class StrokingTextPainter extends
             if (layout.isVertical()) {
                 if (lengthAdj == ADJUST_SPACING) {
                     yScale = (float)
-                        ((length.floatValue()-lastH)/
-                         (advance.getY()-lastMetrics.getVerticalAdvance()));
+                        ((length.floatValue() - lastH) /
+                         (advance.getY() - lastMetrics.getVerticalAdvance()));
                 } else {
-                    double adv =(advance.getY()-
-                                 lastMetrics.getVerticalAdvance() + lastH);
+                    double adv =(advance.getY() + lastH -
+                                 lastMetrics.getVerticalAdvance());
                     yScale = (float)(length.floatValue()/adv);
                 }
                 visualAdvance = new Point2D.Float(0, length.floatValue());
             } else {
                 if (lengthAdj == ADJUST_SPACING) {
                     xScale = (float)
-                        ((length.floatValue()-lastW)/
-                         (advance.getX()-lastMetrics.getHorizontalAdvance()));
+                        ((length.floatValue() - lastW) /
+                         (advance.getX() - lastMetrics.getHorizontalAdvance()));
                 } else {
                     double adv = (advance.getX() + lastW -
                                   lastMetrics.getHorizontalAdvance());
@@ -1587,11 +1615,16 @@ public class StrokingTextPainter extends
 
     // inner classes
 
-    class TextChunk {
+    public class TextChunk {
 
+        // the following denote indices of text runs over all chunks of text node,
+        // where index 0 is first run of first chunk of text node; the begin index
+        // of the first chunk is 0; for subsequent chunks, the begin index is the
+        // end index of its immediately previous chunk; the end index is exclusive
         public int begin;
         public int end;
-        public Point2D advance;
+
+        public Point2D advance; // sum of advances of runs in chunk
 
         public TextChunk(int begin, int end, Point2D advance) {
             this.begin = begin;
@@ -1608,12 +1641,14 @@ public class StrokingTextPainter extends
      */
     public class TextRun {
 
-        protected AttributedCharacterIterator aci;
-        protected TextSpanLayout layout;
-        protected int anchorType;
-        protected boolean firstRunInChunk;
-        protected Float length;
-        protected Integer lengthAdjust;
+        protected AttributedCharacterIterator aci;      // source aci
+        protected TextSpanLayout layout;                // layout object
+        protected int anchorType;                       // text-anchor attribute
+        protected boolean firstRunInChunk;              // first run in chunk flag
+        protected Float length;                         // textLength attribute
+        protected Integer lengthAdjust;                 // lengthAdjust attribute
+        private int level;                              // resolved bidi level of run
+        private int reversals;                          // reversal count
 
         public TextRun(TextSpanLayout layout,
                        AttributedCharacterIterator aci,
@@ -1646,6 +1681,13 @@ public class StrokingTextPainter extends
                 (GVTAttributedCharacterIterator.TextAttribute.BBOX_WIDTH);
             lengthAdjust = (Integer) aci.getAttribute
                 (GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
+
+            Integer level = (Integer) aci.getAttribute(BIDI_LEVEL);
+            if (level != null) {
+                this.level = level.intValue();
+            } else {
+                this.level = -1;
+            }
         }
 
         public AttributedCharacterIterator getACI() {
@@ -1672,5 +1714,19 @@ public class StrokingTextPainter extends
             return firstRunInChunk;
         }
 
+        public int getBidiLevel() {
+            return level;
+        }
+
+        public void reverse() {
+            reversals++;
+        }
+
+        public void maybeReverseGlyphs(boolean mirror) {
+            if ((reversals & 1) == 1) {
+                layout.maybeReverse(mirror);
+            }
+        }
+
     }
 }

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java Sat Aug 23 03:38:55 2014
@@ -2030,4 +2030,14 @@ public class GlyphLayout implements Text
     public boolean isAltGlyph(){
         return this.isAltGlyph;
     }
+
+    @Override
+    public boolean isReversed(){
+        return gv.isReversed();
+    }
+
+    @Override
+    public void maybeReverse(boolean mirror){
+        gv.maybeReverse(mirror);
+    }
 }

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java Sat Aug 23 03:38:55 2014
@@ -227,4 +227,15 @@ public interface TextSpanLayout {
      * an alt glyph.
      */
     boolean isAltGlyph();
+
+    /**
+     * Return true if this text has been reversed.
+     */
+    boolean isReversed();
+
+    /**
+     * Reverse (and optionally mirror) glyphs if not
+     * already reversed.
+     */
+    void maybeReverse(boolean mirror);
 }