You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by de...@apache.org on 2004/09/06 02:02:00 UTC

cvs commit: xml-batik/test-references/samples/tests/spec/text textBiDi-arabic-5-40.png textBiDi-cyrillic-4-24.png textBiDi-greek-0-35.png textBiDi-hebrew-10-20.png textBiDi-latin-0-20.png textBiDi-latin-extended-0-15.png textBiDi.png

deweese     2004/09/05 17:02:00

  Modified:    sources/org/apache/batik/bridge SVGGVTFont.java
                        SVGGlyphElementBridge.java
               sources/org/apache/batik/dom/svg SVGDOMImplementation.java
               sources/org/apache/batik/ext/awt RenderingHintsKeyExt.java
               sources/org/apache/batik/ext/awt/image GraphicsUtil.java
               sources/org/apache/batik/gvt/font AWTGVTGlyphVector.java
                        Glyph.java SVGGVTGlyphVector.java
               sources/org/apache/batik/gvt/text GlyphLayout.java
               test-references/samples asf-logo.png sunRise.png
               test-references/samples/tests/spec/fonts fontArabic.png
               test-references/samples/tests/spec/painting
                        markersOrientB.png
               test-references/samples/tests/spec/scripting
                        text_content.png
               test-references/samples/tests/spec/text
                        textBiDi-arabic-5-40.png textBiDi-cyrillic-4-24.png
                        textBiDi-greek-0-35.png textBiDi-hebrew-10-20.png
                        textBiDi-latin-0-20.png
                        textBiDi-latin-extended-0-15.png textBiDi.png
  Added:       sources/org/apache/batik/dom GenericDocumentType.java
               sources/org/apache/batik/ext/awt AvoidTilingHintKey.java
  Log:
  1) Arabic diacritics are now positioned relative to the right edge
     of the base glyph. Bug 28429
  2) Basic DocumentType implementation.
  3) Control of tiled image rendering based on rendering hint.
     Thanks Jeremias.  Using this hint may greatly increase the
     amount of memory used.
  
  PR: 28429
  
  Revision  Changes    Path
  1.17      +13 -6     xml-batik/sources/org/apache/batik/bridge/SVGGVTFont.java
  
  Index: SVGGVTFont.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGGVTFont.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- SVGGVTFont.java	18 Aug 2004 07:12:34 -0000	1.16
  +++ SVGGVTFont.java	6 Sep 2004 00:01:58 -0000	1.17
  @@ -72,7 +72,7 @@
       private KerningTable vKerningTable;
       private String language;
       private String orientation;
  -
  +    private float  scale;
       private GVTLineMetrics lineMetrics=null;
   
       /**
  @@ -121,6 +121,7 @@
           this.missingGlyphElement = missingGlyphElement;
           this.hkernElements = hkernElements;
           this.vkernElements = vkernElements;
  +        this.scale         = fontSize/fontFace.getUnitsPerEm();
           this.textElement = textElement;
   
           this.language = XMLSupport.getXMLLang(textElement);
  @@ -182,8 +183,11 @@
               || glyphCode2 < 0 || glyphCode2 >= glyphUnicodes.length) {
               return 0f;
           }
  -        return hKerningTable.getKerningValue(glyphCode1, glyphCode2,
  -                glyphUnicodes[glyphCode1], glyphUnicodes[glyphCode2]);
  +        float ret;
  +        ret = hKerningTable.getKerningValue(glyphCode1, glyphCode2,
  +                                            glyphUnicodes[glyphCode1], 
  +                                            glyphUnicodes[glyphCode2]);
  +        return ret*scale;
       }
   
       /**
  @@ -201,8 +205,11 @@
               || glyphCode2 < 0 || glyphCode2 >= glyphUnicodes.length) {
               return 0f;
           }
  -        return vKerningTable.getKerningValue(glyphCode1, glyphCode2,
  -                glyphUnicodes[glyphCode1], glyphUnicodes[glyphCode2]);
  +        float ret;
  +        ret = vKerningTable.getKerningValue(glyphCode1, glyphCode2,
  +                                            glyphUnicodes[glyphCode1], 
  +                                            glyphUnicodes[glyphCode2]);
  +        return ret*scale;
       }
   
       /**
  
  
  
  1.14      +2 -2      xml-batik/sources/org/apache/batik/bridge/SVGGlyphElementBridge.java
  
  Index: SVGGlyphElementBridge.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGGlyphElementBridge.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- SVGGlyphElementBridge.java	18 Aug 2004 07:12:34 -0000	1.13
  +++ SVGGlyphElementBridge.java	6 Sep 2004 00:01:58 -0000	1.14
  @@ -322,7 +322,7 @@
           // return a new Glyph
           return new Glyph(unicode, names, orientation,
                            arabicForm, lang, horizOrigin, vertOrigin,
  -                         horizAdvX, vertAdvY, glyphCode, scale,
  +                         horizAdvX, vertAdvY, glyphCode, 
                            tpi, dShape, glyphContentNode);
       }
   }
  
  
  
  1.1                  xml-batik/sources/org/apache/batik/dom/GenericDocumentType.java
  
  Index: GenericDocumentType.java
  ===================================================================
  /*
  
     Copyright 2004 The Apache Software Foundation 
  
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at
  
         http://www.apache.org/licenses/LICENSE-2.0
  
     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
  
  */
  
  package org.apache.batik.dom;
  
  import org.w3c.dom.DocumentType;
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.Node;
  
  public class GenericDocumentType extends AbstractNode 
      implements DocumentType {
  
      protected String qualifiedName;
      protected String publicId;
      protected String systemId;
  
      public GenericDocumentType(String qualifiedName,
                                     String publicId,
                                     String systemId) {
          this.qualifiedName = qualifiedName;
          this.publicId      = publicId;
          this.systemId      = systemId;
      }
  
      /**
       * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getNodeName()}.
       * @return The name of the DTD.
       */
      public String getNodeName() { return qualifiedName; }
  
      public short getNodeType() { return DOCUMENT_TYPE_NODE; }
  
      public boolean isReadonly() { return true; }
      public void    setReadonly(boolean ro) {}
  
      /**
       * <b>DOM</b>: Implements {@link org.w3c.dom.DocumentType#getName()}.
       * @return The name of the DTD.
       */
      public String getName() { return null; }
  
      /**
       * <b>DOM</b>: Implements {@link org.w3c.dom.DocumentType#getEntities()}.
       * @return null.
       */
      public NamedNodeMap getEntities() {
          return null;
      }
  
      /**
       * <b>DOM</b>: Implements {@link org.w3c.dom.DocumentType#getNotations()}.
       * @return null.
       */
      public NamedNodeMap getNotations() {
          return null;
      }
  
      /**
       * <b>DOM</b>: Implements {@link org.w3c.dom.DocumentType#getPublicId()}.
       * @return The public id.
       */
      public String getPublicId() { return publicId; }
  
      /**
       * <b>DOM</b>: Implements {@link org.w3c.dom.DocumentType#getSystemId()}.
       * @return The public id.
       */
      public String getSystemId() { return systemId; }
  
      /**
       * <b>DOM</b>: Implements {@link org.w3c.dom.DocumentType#getInternalSubset()}.
       * @return The public id.
       */
      public String getInternalSubset() { return null; }
  
  
      protected Node newNode() { 
          return new GenericDocumentType(qualifiedName, publicId, systemId); }
  }
  
  
  1.27      +3 -3      xml-batik/sources/org/apache/batik/dom/svg/SVGDOMImplementation.java
  
  Index: SVGDOMImplementation.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/dom/svg/SVGDOMImplementation.java,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- SVGDOMImplementation.java	18 Aug 2004 07:13:13 -0000	1.26
  +++ SVGDOMImplementation.java	6 Sep 2004 00:01:58 -0000	1.27
  @@ -29,6 +29,7 @@
   import org.apache.batik.css.parser.ExtendedParserWrapper;
   import org.apache.batik.dom.AbstractDOMImplementation;
   import org.apache.batik.dom.AbstractDocument;
  +import org.apache.batik.dom.GenericDocumentType;
   import org.apache.batik.dom.GenericElement;
   import org.apache.batik.dom.GenericElementNS;
   import org.apache.batik.dom.StyleSheetFactory;
  @@ -157,8 +158,7 @@
       public DocumentType createDocumentType(String qualifiedName,
                                              String publicId,
                                              String systemId) {
  -        throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
  -                               formatMessage("doctype.not.supported", null));
  +        return new GenericDocumentType(qualifiedName, publicId, systemId);
       }
   
       /**
  
  
  
  1.9       +22 -8     xml-batik/sources/org/apache/batik/ext/awt/RenderingHintsKeyExt.java
  
  Index: RenderingHintsKeyExt.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/RenderingHintsKeyExt.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- RenderingHintsKeyExt.java	20 Aug 2004 19:29:47 -0000	1.8
  +++ RenderingHintsKeyExt.java	6 Sep 2004 00:01:58 -0000	1.9
  @@ -1,6 +1,6 @@
   /*
   
  -   Copyright 2001-2002  The Apache Software Foundation 
  +   Copyright 2001-2002,2004  The Apache Software Foundation 
   
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
  @@ -65,9 +65,21 @@
        */
       public static final RenderingHints.Key KEY_COLORSPACE;
   
  +    /**
  +     * Hint for the org.apache.batik.ext.awt.image.GraphicsUtil class that
  +     * tiling of a bitmap during rendering is undesired. This is primarily
  +     * for the PDF and PostScript transcoders where tiling can lead to
  +     * suboptimal results due to overlaps in transparency and filter effects.
  +     */
  +    public static final RenderingHints.Key KEY_AVOID_TILE_PAINTING;
  +
  +    public static final Object VALUE_AVOID_TILE_PAINTING_ON = new Object();
  +    public static final Object VALUE_AVOID_TILE_PAINTING_OFF = new Object();
  +    public static final Object VALUE_AVOID_TILE_PAINTING_DEFAULT = new Object();
  +
       static {
           int base = 10100;
  -        RenderingHints.Key trans=null, aoi=null, bi=null, cs=null;
  +        RenderingHints.Key trans=null, aoi=null, bi=null, cs=null, atp=null;
           while (true) {
               int val = base;
   
  @@ -76,6 +88,7 @@
                   aoi   = new AreaOfInterestHintKey(val++);
                   bi    = new BufferedImageHintKey (val++);
                   cs    = new ColorSpaceHintKey    (val++);
  +                atp   = new AvoidTilingHintKey   (val++);
               } catch (Exception e) {
                   System.err.println
                       ("You have loaded the Batik jar files more than once\n" +
  @@ -87,11 +100,12 @@
               }
               break;
           }
  -        KEY_BASE              = base;
  -        KEY_TRANSCODING       = trans;
  -        KEY_AREA_OF_INTEREST  = aoi;
  -        KEY_BUFFERED_IMAGE    = bi;
  -        KEY_COLORSPACE        = cs;
  +        KEY_BASE                = base;
  +        KEY_TRANSCODING         = trans;
  +        KEY_AREA_OF_INTEREST    = aoi;
  +        KEY_BUFFERED_IMAGE      = bi;
  +        KEY_COLORSPACE          = cs;
  +        KEY_AVOID_TILE_PAINTING = atp;
       }
   
       /**
  
  
  
  1.1                  xml-batik/sources/org/apache/batik/ext/awt/AvoidTilingHintKey.java
  
  Index: AvoidTilingHintKey.java
  ===================================================================
  /*
  
     Copyright 2004  The Apache Software Foundation
  
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at
  
         http://www.apache.org/licenses/LICENSE-2.0
  
     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
  
   */
  package org.apache.batik.ext.awt;
  
  import java.awt.RenderingHints;
  
  /**
   * A transcoding Key represented as a boolean to indicate whether tiling of
   * bitmaps is undesired by the destination.
   *
   * @version $Id: AvoidTilingHintKey.java,v 1.1 2004/09/06 00:01:58 deweese Exp $
   */
  public class AvoidTilingHintKey extends RenderingHints.Key {
  
      AvoidTilingHintKey(int number) { super(number); }
  
      public boolean isCompatibleValue(Object v) {
          if (v == null) return false;
          return ((v == RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_ON)  ||
                  (v == RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_OFF) ||
                  (v == RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_DEFAULT));
      }
  }
  
  
  
  1.34      +13 -3     xml-batik/sources/org/apache/batik/ext/awt/image/GraphicsUtil.java
  
  Index: GraphicsUtil.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/GraphicsUtil.java,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- GraphicsUtil.java	27 Aug 2004 00:42:06 -0000	1.33
  +++ GraphicsUtil.java	6 Sep 2004 00:01:58 -0000	1.34
  @@ -1,6 +1,6 @@
   /*
   
  -   Copyright 2001-2003  The Apache Software Foundation 
  +   Copyright 2001-2004  The Apache Software Foundation 
   
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
  @@ -238,9 +238,19 @@
               SampleModel srcSM = cr.getSampleModel();
               if ((srcSM.getWidth()*srcSM.getHeight()) >=
                   (clipR.width*clipR.height))
  -                // if srcSM tiles are larger than the clip size
  +                // if srcSM tiles are around the clip size
                   // then just draw the renderedImage 
                   useDrawRenderedImage = true;
  +
  +            Object atpHint = g2d.getRenderingHint
  +                (RenderingHintsKeyExt.KEY_AVOID_TILE_PAINTING);
  +
  +            if (atpHint == RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_ON)
  +                useDrawRenderedImage = true; //for PDF and PS transcoders
  +
  +            if (atpHint == RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_OFF)
  +                useDrawRenderedImage = false;
  +
   
               WritableRaster wr;
               if (useDrawRenderedImage) {
  
  
  
  1.32      +85 -61    xml-batik/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java
  
  Index: AWTGVTGlyphVector.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -u -r1.31 -r1.32
  --- AWTGVTGlyphVector.java	18 Aug 2004 07:14:35 -0000	1.31
  +++ AWTGVTGlyphVector.java	6 Sep 2004 00:01:58 -0000	1.32
  @@ -243,7 +243,6 @@
   
           double maxWidth = -1;
           double maxHeight = -1;
  -
           for (int i = 0; i < getNumGlyphs(); i++) {
   
               if (!glyphVisible[i]) {
  @@ -261,7 +260,6 @@
                                    scaleFactor);
               float glyphHeight = (glyphMetrics.getVerticalAdvance()/
                                    scaleFactor);
  -
               Rectangle2D glyphBounds = new Rectangle2D.Double(glyphX,
                                                                glyphY,
                                                                glyphWidth,
  @@ -285,9 +283,9 @@
                   Point2D p3 = new Point2D.Double(glyphBounds.getMinX(),
                                                   glyphBounds.getMaxY());
   
  +                Point2D gpos = getGlyphPosition(i);
                   AffineTransform tr = AffineTransform.getTranslateInstance
  -                    (getGlyphPosition(i).getX(),
  -                     getGlyphPosition(i).getY());
  +                    (gpos.getX(), gpos.getY());
   
                   if (glyphTransform != null)
                       tr.concatenate(glyphTransform);
  @@ -343,28 +341,26 @@
   
                   Rectangle2D glyphBounds = tempLogicalBounds[i].getBounds2D();
   
  -                double x = glyphBounds.getMinX();
  +                double x     = glyphBounds.getMinX();
                   double width = glyphBounds.getWidth();
   
                   if ((i < getNumGlyphs()-1) &&
                       (tempLogicalBounds[i+1] != null)) {
                       // make this glyph extend to the start of the next one
  -                    Rectangle2D nextGlyphBounds =
  -                        tempLogicalBounds[i+1].getBounds2D();
  +                    Rectangle2D ngb = tempLogicalBounds[i+1].getBounds2D();
   
  -                    if (nextGlyphBounds.getX() > x) {
  -                        // going left to right (this is pretty hoky)
  -                        width = nextGlyphBounds.getX() - x;
  -                    } else {
  -                        double newGlyphX = (nextGlyphBounds.getX() +
  -                                            nextGlyphBounds.getWidth());
  -                        width += (x - newGlyphX);
  -                        x = newGlyphX;
  +                    if (ngb.getX() > x) {
  +                        double nw = ngb.getX() - x;
  +                        if ((nw < width*1.15) && (nw > width*.85)) {
  +                            double delta = (nw-width)*.5;
  +                            width += delta;
  +                            ngb.setRect(ngb.getX()-delta, ngb.getY(),
  +                                        ngb.getWidth()+delta, ngb.getHeight());
  +                        }
                       }
                   }
  -
                   tempLogicalBounds[i] = new Rectangle2D.Double
  -                    (x, logicalBounds.getMinY(),
  +                    (x,     logicalBounds.getMinY(),
                        width, logicalBounds.getHeight());
               }
           } else if (logicalBounds.getWidth() < maxWidth*1.5) {
  @@ -382,18 +378,17 @@
                   if ((i < getNumGlyphs()-1) &&
                       (tempLogicalBounds[i+1] != null)) {
                       // make this glyph extend to the start of the next one
  -                    Rectangle2D nextGlyphBounds =
  -                        tempLogicalBounds[i+1].getBounds2D();
  -                    if (nextGlyphBounds.getY() > y) { // going top to bottom
  -                        height = nextGlyphBounds.getY() - y;
  -                    } else {
  -                        double newGlyphY = (nextGlyphBounds.getY() +
  -                                            nextGlyphBounds.getHeight());
  -                        height += (y - newGlyphY);
  -                        y = newGlyphY;
  +                    Rectangle2D ngb = tempLogicalBounds[i+1].getBounds2D();
  +                    if (ngb.getY() > y) { // going top to bottom
  +                        double nh = ngb.getY() - y;
  +                        if ((nh < height*1.15) && (nh > height*.85)) {
  +                            double delta = (nh-height)*.5;
  +                            height += delta;
  +                            ngb.setRect(ngb.getX(), ngb.getY()-delta,
  +                                        ngb.getWidth(), ngb.getHeight()+delta);
  +                        }
                       }
                   }
  -
                   tempLogicalBounds[i] = new Rectangle2D.Double
                       (logicalBounds.getMinX(),  y,
                        logicalBounds.getWidth(), height);
  @@ -410,33 +405,31 @@
        * GVTGlyphVector.
        */
       public GVTGlyphMetrics getGlyphMetrics(int glyphIndex) {
  -        if (glyphMetrics[glyphIndex] == null) {
  -/*
  -            GlyphMetrics gm = awtGlyphVector.getGlyphMetrics(glyphIndex);
  -            Rectangle2D gmB = gm.getBounds2D();
  -*/
  -            // -- start glyph cache code --
  -            Point2D glyphPos = defaultGlyphPositions[glyphIndex];
  -            char c = ci.setIndex(ci.getBeginIndex()+glyphIndex);
  -            ci.setIndex(ci.getBeginIndex());
  -            AWTGlyphGeometryCache.Value v = AWTGVTFont.getGlyphGeometry
  -                (gvtFont, c, awtGlyphVector, glyphIndex, glyphPos);
  -            Rectangle2D gmB = v.getBounds2D();
  -           // -- end glyph cache code --
  +        if (glyphMetrics[glyphIndex] != null) 
  +            return glyphMetrics[glyphIndex];
  +
  +        // -- start glyph cache code --
  +        Point2D glyphPos = defaultGlyphPositions[glyphIndex];
  +        char c = ci.setIndex(ci.getBeginIndex()+glyphIndex);
  +        ci.setIndex(ci.getBeginIndex());
  +        AWTGlyphGeometryCache.Value v = AWTGVTFont.getGlyphGeometry
  +            (gvtFont, c, awtGlyphVector, glyphIndex, glyphPos);
  +        Rectangle2D gmB = v.getBounds2D();
  +        // -- end glyph cache code --
  +
  +        Rectangle2D bounds = new Rectangle2D.Double
  +            (gmB.getX()     * scaleFactor, gmB.getY()      * scaleFactor,
  +             gmB.getWidth() * scaleFactor, gmB.getHeight() * scaleFactor);
  +
  +        // defaultGlyphPositions has one more entry than glyphs
  +        // the last entry stores the total advance for the
  +        // glyphVector.
  +        float adv = (float)(defaultGlyphPositions[glyphIndex+1].getX()-
  +                            defaultGlyphPositions[glyphIndex]  .getX());
  +        glyphMetrics[glyphIndex] =  new GVTGlyphMetrics
  +            (adv*scaleFactor, (ascent+descent),
  +             bounds, GlyphMetrics.STANDARD);
   
  -            Rectangle2D bounds = new Rectangle2D.Double
  -                (gmB.getX()     * scaleFactor, gmB.getY()      * scaleFactor,
  -                 gmB.getWidth() * scaleFactor, gmB.getHeight() * scaleFactor);
  -
  -            // defaultGlyphPositions has one more entry than glyphs
  -            // the last entry stores the total advance for the
  -            // glyphVector.
  -            float adv = (float)(defaultGlyphPositions[glyphIndex+1].getX()-
  -                                defaultGlyphPositions[glyphIndex]  .getX());
  -            glyphMetrics[glyphIndex] =  new GVTGlyphMetrics
  -                (adv*scaleFactor, (ascent+descent),
  -                 bounds, GlyphMetrics.STANDARD);
  -        }
           return glyphMetrics[glyphIndex];
       }
   
  @@ -671,19 +664,50 @@
               Point2D glyphPos = defaultGlyphPositions[i];
               float x = (float)((glyphPos.getX() * scaleFactor)-shiftLeft);
               float y = (float) (glyphPos.getY() * scaleFactor);
  -            if (glyphPositions[i] == null) {
  -                glyphPositions[i] = new Point2D.Float(x,y);
  -            } else {
  -                glyphPositions[i].x = x;
  -                glyphPositions[i].y = y;
  -            }
   
               // if c is a transparent arabic char then need to shift the
               // following glyphs left so that the current glyph is overwritten
               char c = ci.setIndex(i + ci.getBeginIndex());
  +            /*
               if (ArabicTextHandler.arabicCharTransparent(c)) {
  +                int j;
                   shiftLeft += getGlyphMetrics(i).getHorizontalAdvance();
  -            }
  +                for (j=i+1; j<getNumGlyphs(); j++) {
  +                    char c2 = ci.setIndex(j+ci.getBeginIndex());
  +                    if (!ArabicTextHandler.arabicCharTransparent(c2)) break;
  +                    shiftLeft += getGlyphMetrics(j).getHorizontalAdvance();
  +                }
  +                if (j != getNumGlyphs()) {
  +                    Point2D glyphPosBase = defaultGlyphPositions[j];
  +                    double rEdge = glyphPosBase.getX()+getGlyphMetrics(j).getHorizontalAdvance();
  +                    rEdge -= shiftLeft;
  +                    for (int k=i; k<j; k++) {
  +                        glyphTransforms   [k] = null;
  +                        glyphVisualBounds [k] = null;
  +                        glyphLogicalBounds[k] = null;
  +                        glyphOutlines     [k] = null;
  +                        glyphMetrics      [k] = null;
  +                        x = (float)rEdge-getGlyphMetrics(k).getHorizontalAdvance();
  +                        y = (float) (defaultGlyphPositions[k].getY() * scaleFactor);
  +                        if (glyphPositions[k] == null) {
  +                            glyphPositions[k] = new Point2D.Float(x,y);
  +                        } else {
  +                            glyphPositions[k].x = x;
  +                            glyphPositions[k].y = y;
  +                        }
  +                    }
  +                    i = j-1;
  +                }
  +            } else {
  +            */
  +                if (glyphPositions[i] == null) {
  +                    glyphPositions[i] = new Point2D.Float(x,y);
  +                } else {
  +                    glyphPositions[i].x = x;
  +                    glyphPositions[i].y = y;
  +                }
  +                // }
  +
           }
   
           // Need glyph pos for point after last char...
  
  
  
  1.16      +4 -15     xml-batik/sources/org/apache/batik/gvt/font/Glyph.java
  
  Index: Glyph.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/font/Glyph.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- Glyph.java	18 Aug 2004 07:14:35 -0000	1.15
  +++ Glyph.java	6 Sep 2004 00:01:58 -0000	1.16
  @@ -55,7 +55,6 @@
       private AffineTransform transform;
       private Point2D.Float position;
       private GVTGlyphMetrics metrics;
  -    private float kernScale;
   
       private Shape outline; // cache the glyph outline
       private Rectangle2D bounds; // cache the glyph bounds
  @@ -72,7 +71,7 @@
       public Glyph(String unicode, Vector names,
                    String orientation, String arabicForm, String lang,
                    Point2D horizOrigin, Point2D vertOrigin, float horizAdvX,
  -                 float vertAdvY, int glyphCode, float kernScale,
  +                 float vertAdvY, int glyphCode,
                    TextPaintInfo tpi,
                    Shape dShape, GraphicsNode glyphChildrenNode) {
   
  @@ -95,16 +94,6 @@
           this.vertOrigin = vertOrigin;
           this.horizAdvX = horizAdvX;
           this.vertAdvY = vertAdvY;
  -        if (this.unicode != null) {
  -            if (this.unicode.length() > 0
  -                && ArabicTextHandler.arabicCharTransparent(this.unicode.charAt(0))) {
  -                // if this glyph is arabic and transparent,
  -                // then it doesn't cause any advance
  -                this.horizAdvX = 0;
  -                this.vertAdvY = 0;
  -            }
  -        }
  -        this.kernScale = kernScale;
           this.glyphCode = glyphCode;
           this.position = new Point2D.Float(0,0);
           this.outline = null;
  @@ -281,8 +270,8 @@
        * @return The kerned glyph metics
        */
       public GVTGlyphMetrics getGlyphMetrics(float hkern, float vkern) {
  -        return new GVTGlyphMetrics(getHorizAdvX() - (hkern * kernScale),
  -                                   getVertAdvY() - (vkern * kernScale),
  +        return new GVTGlyphMetrics(getHorizAdvX() - hkern,
  +                                   getVertAdvY() - vkern,
                                      getGeometryBounds(), 
                                      GlyphMetrics.COMPONENT);
   
  
  
  
  1.20      +72 -131   xml-batik/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java
  
  Index: SVGGVTGlyphVector.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- SVGGVTGlyphVector.java	1 Sep 2004 09:35:23 -0000	1.19
  +++ SVGGVTGlyphVector.java	6 Sep 2004 00:01:58 -0000	1.20
  @@ -27,6 +27,7 @@
   import java.awt.geom.Rectangle2D;
   import java.text.AttributedCharacterIterator;
   
  +import org.apache.batik.gvt.text.ArabicTextHandler;
   import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
   import org.apache.batik.gvt.text.TextPaintInfo;
   
  @@ -193,8 +194,6 @@
   
           Shape[] tempLogicalBounds = new Shape[getNumGlyphs()];
           boolean[] rotated = new boolean[getNumGlyphs()];
  -        boolean[] flippedH = new boolean[getNumGlyphs()];
  -        boolean[] flippedV = new boolean[getNumGlyphs()];
   
           double maxWidth = -1;
           double maxHeight = -1;
  @@ -218,12 +217,8 @@
                   // the same as the previous glyph, if we have one...
                   if (i > 0) {
                       rotated[i] = rotated[i-1];
  -                    flippedH[i] = flippedH[i-1];
  -                    flippedV[i] = flippedV[i-1];
                   } else {
                       rotated [i] = true;
  -                    flippedH[i] = false;
  -                    flippedV[i] = false;
                   }
               } else {
                   // get three corner points so we can determine
  @@ -234,10 +229,9 @@
                                                   glyphBounds.getMinY());
                   Point2D p3 = new Point2D.Double(glyphBounds.getMinX(), 
                                                   glyphBounds.getMaxY());
  -                    
  +                Point2D gpos = getGlyphPosition(i);
                   AffineTransform tr = AffineTransform.getTranslateInstance
  -                    (getGlyphPosition(i).getX(),
  -                     getGlyphPosition(i).getY());
  +                    (gpos.getX(), gpos.getY());
                       
                   if (glyphTransform != null)
                       tr.concatenate(glyphTransform);
  @@ -263,8 +257,6 @@
                       rotated[i] = false;
                       double dx13 = p1.getX()-p3.getX();
                       double dy12 = p1.getY()-p2.getY();
  -                    if (Math.abs(tdx13+dx13) < 0.001) flippedH[i] = true;
  -                    if (Math.abs(tdy12+dy12) < 0.001) flippedV[i] = true;
                           
                   } else if ((Math.abs(tdx13) < 0.001) &&
                              (Math.abs(tdy12) < 0.001)) {
  @@ -273,12 +265,8 @@
                       rotated[i] = false;
                       double dx12 = p1.getX()-p2.getX();
                       double dy13 = p1.getY()-p3.getY();
  -                    if (Math.abs(tdx12+dx12) < 0.001) flippedH[i] = true;
  -                    if (Math.abs(tdy13+dy13) < 0.001) flippedV[i] = true;
                   } else {
                       rotated [i] = true;
  -                    flippedH[i] = false;
  -                    flippedV[i] = false;
                   }
                       
                   Rectangle2D rectBounds;
  @@ -317,58 +305,22 @@
                       // make this glyph extend to the start of the next one
                       Rectangle2D nextGlyphBounds = 
                           tempLogicalBounds[i+1].getBounds2D();
  +                    // make this glyph extend to the start of the next one
  +                    Rectangle2D ngb = tempLogicalBounds[i+1].getBounds2D();
   
  -                    if (nextGlyphBounds.getX() > x) { 
  -                        // going left to right (this is pretty hoky)
  -                        width = nextGlyphBounds.getX() - x;
  -                    } else {
  -                        double newGlyphX = (nextGlyphBounds.getX() + 
  -                                            nextGlyphBounds.getWidth());
  -                        width += (x - newGlyphX);
  -                        x = newGlyphX;
  -                    }
  -                }
  -
  -                float x0 = (float)x;
  -                float x1 = (float)(x0+width);
  -                float y0 = (float)fullBounds.getMinY();
  -                float y1 = (float)(y0+fullBounds.getHeight());
  -                // Build the bounds rect the way things expect to see it...
  -                if (flippedH[i]) {
  -                    if (flippedV[i]) {
  -                        GeneralPath gp = new GeneralPath();
  -                        gp.moveTo(x1,y1);
  -                        gp.lineTo(x0,y1);
  -                        gp.lineTo(x0,y0);
  -                        gp.lineTo(x1,y0);
  -                        gp.lineTo(x1,y1);
  -                        gp.closePath();
  -                        tempLogicalBounds[i] = gp;
  -                    } else {
  -                        GeneralPath gp = new GeneralPath();
  -                        gp.moveTo(x1,y0);
  -                        gp.lineTo(x0,y0);
  -                        gp.lineTo(x0,y1);
  -                        gp.lineTo(x1,y1);
  -                        gp.lineTo(x1,y0);
  -                        gp.closePath();
  -                        tempLogicalBounds[i] = gp;
  -                    }
  -                } else {
  -                    if (flippedV[i]) {
  -                        GeneralPath gp = new GeneralPath();
  -                        gp.moveTo(x0,y1);
  -                        gp.lineTo(x1,y1);
  -                        gp.lineTo(x1,y0);
  -                        gp.lineTo(x0,y0);
  -                        gp.lineTo(x0,y1);
  -                        gp.closePath();
  -                        tempLogicalBounds[i] = gp;
  -                    } else {
  -                        tempLogicalBounds[i] = new Rectangle2D.Double
  -                            (x0, y0, x1-x0, y1-y0);
  +                    if (ngb.getX() > x) {
  +                        double nw = ngb.getX() - x;
  +                        if ((nw < width*1.15) && (nw > width*.85)) {
  +                            double delta = (nw-width)*.5;
  +                            width += delta;
  +                            ngb.setRect(ngb.getX()-delta, ngb.getY(),
  +                                        ngb.getWidth()+delta, ngb.getHeight());
  +                        }
                       }
                   }
  +                tempLogicalBounds[i] = new Rectangle2D.Double
  +                    (x,     fullBounds.getMinY(),
  +                     width, fullBounds.getHeight());
               }
           } else if (fullBounds.getWidth() < maxWidth*1.5) {
               // make all glyphs left and right edges the same as the full bounds
  @@ -385,58 +337,20 @@
                   if ((i < getNumGlyphs()-1) && 
                       (tempLogicalBounds[i+1] != null)) {
                       // make this glyph extend to the start of the next one
  -                    Rectangle2D nextGlyphBounds = 
  -                        tempLogicalBounds[i+1].getBounds2D();
  -                    if (nextGlyphBounds.getY() > y) { // going top to bottom
  -                        height = nextGlyphBounds.getY() - y;
  -                    } else {
  -                        double newGlyphY = (nextGlyphBounds.getY() + 
  -                                            nextGlyphBounds.getHeight());
  -                        height += (y - newGlyphY);
  -                        y = newGlyphY;
  -                    }
  -                }
  -
  -                float x0 = (float)fullBounds.getMinX();
  -                float x1 = (float)(x0+fullBounds.getWidth());
  -                float y0 = (float)y;
  -                float y1 = (float)(y0+height);
  -                // Build the rect the way things expect to see it...
  -                if (flippedH[i]) {
  -                    if (flippedV[i]) {
  -                        GeneralPath gp = new GeneralPath();
  -                        gp.moveTo(x1,y1);
  -                        gp.lineTo(x0,y1);
  -                        gp.lineTo(x0,y0);
  -                        gp.lineTo(x1,y0);
  -                        gp.lineTo(x1,y1);
  -                        gp.closePath();
  -                        tempLogicalBounds[i] = gp;
  -                    } else {
  -                        GeneralPath gp = new GeneralPath();
  -                        gp.moveTo(x1,y0);
  -                        gp.lineTo(x0,y0);
  -                        gp.lineTo(x0,y1);
  -                        gp.lineTo(x1,y1);
  -                        gp.lineTo(x1,y0);
  -                        gp.closePath();
  -                        tempLogicalBounds[i] = gp;
  -                    }
  -                } else {
  -                    if (flippedV[i]) {
  -                        GeneralPath gp = new GeneralPath();
  -                        gp.moveTo(x0,y1);
  -                        gp.lineTo(x1,y1);
  -                        gp.lineTo(x1,y0);
  -                        gp.lineTo(x0,y0);
  -                        gp.lineTo(x0,y1);
  -                        gp.closePath();
  -                        tempLogicalBounds[i] = gp;
  -                    } else {
  -                        tempLogicalBounds[i] = new Rectangle2D.Double
  -                            (x0, y0, x1-x0, y1-y0);
  +                    Rectangle2D ngb = tempLogicalBounds[i+1].getBounds2D();
  +                    if (ngb.getY() > y) { // going top to bottom
  +                        double nh = ngb.getY() - y;
  +                        if ((nh < height*1.15) && (nh > height*.85)) {
  +                            double delta = (nh-height)*.5;
  +                            height += delta;
  +                            ngb.setRect(ngb.getX(), ngb.getY()-delta,
  +                                        ngb.getWidth(), ngb.getHeight()+delta);
  +                        }
                       }
                   }
  +                tempLogicalBounds[i] = new Rectangle2D.Double
  +                    (fullBounds.getMinX(),  y,
  +                     fullBounds.getWidth(), height);
               }
           }
   
  @@ -449,31 +363,30 @@
        * Returns the metrics of the glyph at the specified index into this
        * GlyphVector.
        */
  -    public GVTGlyphMetrics getGlyphMetrics(int glyphIndex) {
  +    public GVTGlyphMetrics getGlyphMetrics(int idx) {
   
  -        if (glyphIndex < 0 || (glyphIndex > glyphs.length-1)) {
  -            throw new IndexOutOfBoundsException("glyphIndex: " + glyphIndex
  -            + ", is out of bounds. Should be between 0 and " + (glyphs.length-1) + ".");
  -        }
  +        if (idx < 0 || (idx > glyphs.length-1))
  +            throw new IndexOutOfBoundsException
  +                ("idx: " + idx + ", is out of bounds. Should be between 0 and "
  +                 + (glyphs.length-1) + ".");
   
           // check to see if we should kern this glyph
           // I return the kerning information in the glyph metrics
           // as a first pass at implementation (I don't want to
           // fiddle with layout too much right now).
  -
  -        if (glyphIndex < glyphs.length - 1) {
  +        if (idx < glyphs.length - 1) {
               // check for kerning
               if (font != null) {
  -                float hkern = font.getHKern(glyphs[glyphIndex].getGlyphCode(),
  -                                            glyphs[glyphIndex+1].getGlyphCode());
  -                float vkern = font.getVKern(glyphs[glyphIndex].getGlyphCode(),
  -                                            glyphs[glyphIndex+1].getGlyphCode());
  -                return glyphs[glyphIndex].getGlyphMetrics(hkern, vkern);
  +                float hkern = font.getHKern(glyphs[idx].getGlyphCode(),
  +                                            glyphs[idx+1].getGlyphCode());
  +                float vkern = font.getVKern(glyphs[idx].getGlyphCode(),
  +                                            glyphs[idx+1].getGlyphCode());
  +                return glyphs[idx].getGlyphMetrics(hkern, vkern);
               }
           }
   
           // get a normal metrics
  -        return glyphs[glyphIndex].getGlyphMetrics();
  +        return glyphs[idx].getGlyphMetrics();
       }
   
       /**
  @@ -670,10 +583,38 @@
           float currentX = 0;
           float currentY = 0;
           for (int i = 0; i < glyphs.length; i++) {
  -            glyphs[i].setPosition(new Point2D.Float(currentX, currentY));
  -            glyphs[i].setTransform(null);
  +            Glyph g = glyphs[i];
  +            g.setTransform(null);
               glyphLogicalBounds[i] = null;
  -            currentX += glyphs[i].getHorizAdvX();
  +
  +            String uni = g.getUnicode();
  +            if ((uni != null)  && (uni.length() != 0) &&
  +                ArabicTextHandler.arabicCharTransparent(uni.charAt(0))) {
  +                int j;
  +                for (j=i+1; j<glyphs.length; j++) {
  +                    uni = glyphs[j].getUnicode();
  +                    if ((uni == null)  || (uni.length() == 0)) break;
  +                    char ch = uni.charAt(0);
  +                    if (!ArabicTextHandler.arabicCharTransparent(ch))
  +                        break;
  +                }
  +                if (j != glyphs.length) {
  +                    Glyph bg = glyphs[j];
  +                    float rEdge = (float)(currentX + bg.getHorizAdvX());
  +                    for (int k=i; k<j; k++) {
  +                        g = glyphs[k];
  +                        g.setTransform(null);
  +                        glyphLogicalBounds[i] = null;
  +                        g.setPosition(new Point2D.Float(rEdge-g.getHorizAdvX(),
  +                                                        currentY));
  +                    }
  +                    i = j;
  +                    g = bg;
  +                }
  +            }
  +
  +            g.setPosition(new Point2D.Float(currentX, currentY));
  +            currentX += g.getHorizAdvX();
           }
           endPos = new Point2D.Float(currentX, currentY);
       }
  
  
  
  1.60      +101 -8    xml-batik/sources/org/apache/batik/gvt/text/GlyphLayout.java
  
  Index: GlyphLayout.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/GlyphLayout.java,v
  retrieving revision 1.59
  retrieving revision 1.60
  diff -u -r1.59 -r1.60
  --- GlyphLayout.java	18 Aug 2004 07:14:41 -0000	1.59
  +++ GlyphLayout.java	6 Sep 2004 00:01:58 -0000	1.60
  @@ -1059,7 +1059,6 @@
                              logicalBounds.getMaxX() - strikethroughThickness/2.0, offset.getY()+y));
       }
   
  -
       /**
        * Explicitly lays out each of the glyphs in the glyph
        * vector. This will handle any glyph position adjustments such as
  @@ -1104,6 +1103,7 @@
           float curr_y_pos = (float)offset.getY();
   
           Point2D.Float pos = new Point2D.Float();
  +        boolean hasArabicTransparent = false;
   
           while (i < numGlyphs) {
               //System.out.println("limit: " + runLimit + ", " + aciIndex);
  @@ -1281,8 +1281,10 @@
               gv.setGlyphPosition(i, pos);
   
               // calculte the position of the next glyph
  -            if (!ArabicTextHandler.arabicCharTransparent(ch)) {
  -                // only apply the advance if the current char is not transparen
  +            if (ArabicTextHandler.arabicCharTransparent(ch)) {
  +                hasArabicTransparent = true;
  +            } else {
  +                // Apply the advance if the current char is not transparent
                   if (vertical) {
                       float advanceY = 0;
                       if (glyphOrientationAuto) {
  @@ -1362,6 +1364,96 @@
           advance = new Point2D.Float((float)(curr_x_pos - offset.getX()), 
                                       (float)(curr_y_pos - offset.getY()));
   
  +
  +        // Do a last pass positioning the transparent/mark glyphs on the
  +        // base glyphs.
  +        if (hasArabicTransparent) {
  +            ch = aci.first();
  +            aciIndex = 0;
  +            i=0;
  +            int transparentStart = -1;
  +            while (i < numGlyphs) {
  +                if (ArabicTextHandler.arabicCharTransparent(ch)) {
  +                    if (transparentStart == -1) transparentStart = i;
  +                } else {
  +                    if (transparentStart != -1) {
  +                        Point2D         loc   = gv.getGlyphPosition(i);
  +                        GVTGlyphMetrics gm    = gv.getGlyphMetrics(i);
  +                        int tyS=0, txS=0;
  +                        float advX=0, advY=0;
  +                        if (vertical) {
  +                            if (glyphOrientationAuto || 
  +                                (glyphOrientationAngle == 90))
  +                                advY = gm.getHorizontalAdvance();
  +                            else if (glyphOrientationAngle == 270)
  +                                advY = 0;
  +                            else if (glyphOrientationAngle == 0)
  +                                advX = gm.getHorizontalAdvance();
  +                            else // 180
  +                                advX = -gm.getHorizontalAdvance();
  +                        } else {
  +                            if (glyphOrientationAngle ==   0)
  +                                advX = gm.getHorizontalAdvance();
  +                            else if (glyphOrientationAngle == 90)
  +                                advY = gm.getHorizontalAdvance();
  +                            else if (glyphOrientationAngle == 180)
  +                                advX = 0;
  +                            else // 270
  +                                advY = -gm.getHorizontalAdvance();
  +                        }
  +                        float baseX = (float)(loc.getX()+advX);
  +                        float baseY = (float)(loc.getY()+advY);
  +                        for (int j=transparentStart; j<i; j++) {
  +                            Point2D         locT = gv.getGlyphPosition(j);
  +                            GVTGlyphMetrics gmT  = gv.getGlyphMetrics(j);
  +                            float           locX = (float)locT.getX();
  +                            float           locY = (float)locT.getY();
  +                            float           tx=0, ty=0;
  +                            float           advT = gmT.getHorizontalAdvance();
  +                            if (vertical) {
  +                                if (glyphOrientationAuto || 
  +                                    (glyphOrientationAngle == 90))
  +                                    locY = baseY-advT;
  +                                else if (glyphOrientationAngle == 270)
  +                                    locY = baseY+advT;
  +                                else if (glyphOrientationAngle == 0)
  +                                    locX = baseX-advT;
  +                                else // 180deg
  +                                    locX = baseX+advT;
  +                            } else {
  +                                if (glyphOrientationAngle ==   0)
  +                                    locX = baseX-advT;
  +                                else if (glyphOrientationAngle == 90)
  +                                    locY = baseY-advT;
  +                                else if (glyphOrientationAngle == 180)
  +                                    locX = baseX+advT;
  +                                else // 270
  +                                    locY = baseY+advT;
  +                            }
  +                            
  +                            locT = new Point2D.Double(locX, locY);
  +                            gv.setGlyphPosition(j, locT);
  +                            if ((txS != 0) || (tyS != 0)) {
  +                                AffineTransform at;
  +                                at = AffineTransform.getTranslateInstance
  +                                    (tx,ty);
  +                                at.concatenate(gv.getGlyphTransform(i));
  +                                gv.setGlyphTransform(i, at);
  +                            }
  +                        }
  +                        transparentStart = -1;
  +                    }
  +                }
  +                aciIndex += gv.getCharacterCount(i,i);
  +                if (aciIndex >= charMap.length)
  +                    aciIndex = charMap.length-1;
  +                ch = aci.setIndex(aciIndex+aciStart);
  +                i++;
  +            }
  +            
  +        }
  +
  +
           layoutApplied  = true;
           spacingApplied = false;
           glyphAdvances  = null;
  @@ -1894,12 +1986,13 @@
               block == Character.UnicodeBlock.LATIN_1_SUPPLEMENT ||
               block == Character.UnicodeBlock.LATIN_EXTENDED_ADDITIONAL ||
               block == Character.UnicodeBlock.LATIN_EXTENDED_A ||
  -            block == Character.UnicodeBlock.LATIN_EXTENDED_B) {
  +            block == Character.UnicodeBlock.LATIN_EXTENDED_B ||
  +            block == Character.UnicodeBlock.ARABIC ||
  +            block == Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_A ||
  +            block == Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_B) {
               return true;
  -        } else {
  -            return false;
           }
  -
  +        return false;
       }
   
       /**
  
  
  
  1.7       +55 -50    xml-batik/test-references/samples/asf-logo.png
  
  	<<Binary file>>
  
  
  1.7       +699 -730  xml-batik/test-references/samples/sunRise.png
  
  	<<Binary file>>
  
  
  1.8       +241 -220  xml-batik/test-references/samples/tests/spec/fonts/fontArabic.png
  
  	<<Binary file>>
  
  
  1.8       +71 -93    xml-batik/test-references/samples/tests/spec/painting/markersOrientB.png
  
  	<<Binary file>>
  
  
  1.3       +91 -98    xml-batik/test-references/samples/tests/spec/scripting/text_content.png
  
  	<<Binary file>>
  
  
  1.4       +61 -66    xml-batik/test-references/samples/tests/spec/text/textBiDi-arabic-5-40.png
  
  	<<Binary file>>
  
  
  1.4       +75 -71    xml-batik/test-references/samples/tests/spec/text/textBiDi-cyrillic-4-24.png
  
  	<<Binary file>>
  
  
  1.3       +87 -70    xml-batik/test-references/samples/tests/spec/text/textBiDi-greek-0-35.png
  
  	<<Binary file>>
  
  
  1.3       +49 -51    xml-batik/test-references/samples/tests/spec/text/textBiDi-hebrew-10-20.png
  
  	<<Binary file>>
  
  
  1.4       +63 -65    xml-batik/test-references/samples/tests/spec/text/textBiDi-latin-0-20.png
  
  	<<Binary file>>
  
  
  1.4       +64 -85    xml-batik/test-references/samples/tests/spec/text/textBiDi-latin-extended-0-15.png
  
  	<<Binary file>>
  
  
  1.14      +71 -86    xml-batik/test-references/samples/tests/spec/text/textBiDi.png
  
  	<<Binary file>>
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org