deweese     02/04/30 12:08:48

  Modified:    samples  batikLogo.svg
               samples/extensions flowText.svg
               sources/org/apache/batik/bridge SVGGVTFont.java
                        SVGTextElementBridge.java
               sources/org/apache/batik/extension/svg
                        BatikExtConstants.java
                        SVGFlowTextElementBridge.java
               sources/org/apache/batik/gvt/font AWTGVTGlyphVector.java
                        GVTGlyphVector.java MultiGlyphVector.java
                        SVGGVTGlyphVector.java
               sources/org/apache/batik/gvt/renderer
                        StrokingTextPainter.java
               sources/org/apache/batik/gvt/text GlyphIterator.java
                        GlyphLayout.java LineInfo.java MarginInfo.java
               test-resources/org/apache/batik/test samplesRendering.xml
  Log:
  1) Normal Text fixes:
    a) Fixed handling of some exotic text cases (text on a path with
       multiple following non text path text elements, text path using anchors
       with following non text path text).
    b) Now only create text chunks when coordinate in layout direction is
       absolute.
    c) Added isGlyphVisible method to GVTGlyphVector
    d) Fixed a bug in the caching of metrics in AWTGVTGlyphVector.
  
  2) flowText fixes:
    a) Added support for first-line-left/right-margin _attribute_ on flowPara
       element (only takes user space lengths).
    b) Now properly handles whitespace at start and end of a line that is
       flowed (also hides those spaces from display (although they will
       appear in the clipboard text).
    c) Fixed/Improved handling of flowLine element.
    d) Improved lineMetrics function in SVGGVTFont
  
  3) Added existing tests into sampleRendering.xml that were missing:
    a) Added colorSwitch, flowText, multi, solidColor, solidColor2 to
       "extensions" testGroup
    b) Added textLength.svg  to "tests.spec.text" testGroup.
  
  Revision  Changes    Path
  1.10      +8 -1      xml-batik/samples/batikLogo.svg
  
  Index: batikLogo.svg
  ===================================================================
  RCS file: /home/cvs/xml-batik/samples/batikLogo.svg,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- batikLogo.svg     30 Nov 2001 08:28:58 -0000      1.9
  +++ batikLogo.svg     30 Apr 2002 19:08:47 -0000      1.10
  @@ -17,7 +17,7 @@
   <!-- @author [EMAIL PROTECTED]                                              -->
   <!-- @author [EMAIL PROTECTED]                                       -->
   <!-- @author [EMAIL PROTECTED]                                   -->
  -<!-- @version $Id: batikLogo.svg,v 1.9 2001/11/30 08:28:58 vhardy Exp $    -->
  +<!-- @version $Id: batikLogo.svg,v 1.10 2002/04/30 19:08:47 deweese Exp $    -->
   <!-- ====================================================================== -->
   
   <svg xmlns="http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink"; 
id="body" width="450" height="500" viewBox="0 0 450 500">
  @@ -110,6 +110,13 @@
                         
c0,6.852,0.531,11.344,1.602,13.477c1.066,2.133,3.086,3.883,6.059,5.25c1.219,0.535,3.121,0.992,5.715,1.371c0.078,0.023,0.152,0.031,0.23,0.031c2.133,0.152,3.523,0.492,4.172,1.023s0.973,1.363,0.973,2.5c0,0.836-0.344,1.496-1.027,1.988
                         
s-1.594,0.738-2.734,0.738c-0.305,0-2.758-0.211-7.355-0.625c-4.602-0.414-8.992-0.625-13.172-0.625c-6.309,0-12.313,0.375-18.016,1.125c-0.914,0.082-1.445,0.125-1.594,0.125c-0.836,0-1.523-0.25-2.055-0.746s-0.797-1.09-0.797-1.777
                         
c0-0.766,0.262-1.473,0.789-2.121c0.523-0.648,1.613-1.434,3.27-2.355c0.375-0.227,0.789-0.492,1.242-0.797c1.273-0.758,2.215-1.445,2.816-2.055c1.277-1.367,2.16-3.074,2.648-5.129c0.488-2.051,0.734-5.926,0.734-11.629z"/>
  +               </glyph>
  +
  +               <glyph unicode="*" glyph-name="*" horiz-adv-x="120">
  +                <g transform="scale(1, -1)">
  +                  <use xlink:href="#Batik_Squiggle" 
  +                          transform="scale(2,2) translate(0,-67)" />
  +                </g>
                  </glyph>
             
                  <hkern g1="B"  g2="a"  k="5"/>
  
  
  
  1.6       +2 -2      xml-batik/samples/extensions/flowText.svg
  
  Index: flowText.svg
  ===================================================================
  RCS file: /home/cvs/xml-batik/samples/extensions/flowText.svg,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- flowText.svg      24 Apr 2002 12:33:29 -0000      1.5
  +++ flowText.svg      30 Apr 2002 19:08:47 -0000      1.6
  @@ -14,7 +14,7 @@
   <!-- Tests various text on a path                                           -->
   <!--                                                                        -->
   <!-- @author [EMAIL PROTECTED]                                   -->
  -<!-- @version $Id: flowText.svg,v 1.5 2002/04/24 12:33:29 deweese Exp $   -->
  +<!-- @version $Id: flowText.svg,v 1.6 2002/04/30 19:08:47 deweese Exp $   -->
   <!-- ====================================================================== -->
   
   <?xml-stylesheet type="text/css" href="extension.css" ?>
  @@ -41,7 +41,7 @@
            <batik:region x="233" y="80" width="200" height="400"/>
            </batik:flowRegion>
            <batik:flowDiv>
  -         <batik:flowPara bottom-margin="10" >This is an <batik:flowSpan 
font-size="40" fill="crimson">ex&#x00AD;ample</batik:flowSpan> of a very long string 
that is split &#x200D;across multi&#x00AD;ple lines via text 
wrap&#x0AD;ping.</batik:flowPara>
  +         <batik:flowPara first-line-left-margin="20" bottom-margin="10" >This is an 
<batik:flowSpan font-size="40" fill="crimson">ex&#x00AD;ample</batik:flowSpan> of a 
very long string that is split &#x200D;across multi&#x00AD;ple lines via text 
wrap&#x0AD;ping.</batik:flowPara>
            <batik:flowPara justification="middle" top-margin="10" left-margin="10" 
right-margin="10" bottom-margin="10"><batik:flowLine>Now check if text wrapping 
handles a number of tricky</batik:flowLine> situations: 
averylongrunonwordthatspansmultiplelines<batik:flowSpan 
font-weight="bold">with<batik:flowSpan 
fill="crimson">embedded</batik:flowSpan>span</batik:flowSpan>elements &amp; 
<batik:flowSpan fill="green" dy="-.3em" 
font-size="80%">super</batik:flowSpan><batik:flowSpan dy=".3em"> or 
</batik:flowSpan><batik:flowSpan fill="darkgreen" dy=".3em" 
font-size="80%">sub</batik:flowSpan><batik:flowSpan dy="-.3em"> 
scripts.</batik:flowSpan></batik:flowPara>
            <batik:flowPara top-margin="10" justification="end">Now we are just 
<batik:flowSpan font-size="30" fill="blue">about</batik:flowSpan> to go to the next 
flow rect <batik:flowSpan font-size="10">(note if the 'about' were included on the 
last line of the previous flow rect the line would not have fit and the whole line 
would have moved here).</batik:flowSpan></batik:flowPara>
            <batik:flowPara margin="10" justification="full">     I'll keep going 
because I want to make sure that it properly stops when it hits the end of all of the 
the flow regions defined. Also the last line includes text in a larger font size so it 
will not fit. Thus the end of this sentence will be cut off because the line size gets 
<batik:flowSpan font-size="35">tall</batik:flowSpan>er</batik:flowPara>
  
  
  
  1.10      +21 -17    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.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- SVGGVTFont.java   27 Apr 2002 22:41:57 -0000      1.9
  +++ SVGGVTFont.java   30 Apr 2002 19:08:47 -0000      1.10
  @@ -42,7 +42,7 @@
    * Represents an SVG font.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]";>Bella Robinson</a>
  - * @version $Id: SVGGVTFont.java,v 1.9 2002/04/27 22:41:57 deweese Exp $
  + * @version $Id: SVGGVTFont.java,v 1.10 2002/04/30 19:08:47 deweese Exp $
    */
   public final class SVGGVTFont implements GVTFont, SVGConstants {
   
  @@ -64,6 +64,8 @@
       private String language;
       private String orientation;
   
  +    private GVTLineMetrics lineMetrics=null;
  +
       /**
        * Constructs a new SVGGVTFont of the specified size.
        *
  @@ -767,6 +769,9 @@
        */
       public GVTLineMetrics getLineMetrics(CharacterIterator ci, int beginIndex,
                                            int limit, FontRenderContext frc) {
  +        if (lineMetrics != null) 
  +            return lineMetrics;
  +
           float fontHeight = fontFace.getUnitsPerEm();
           float scale = fontSize/fontHeight;
   
  @@ -778,22 +783,21 @@
           baselineOffsets[Font.CENTER_BASELINE]  = (ascent+descent)/2-ascent;
           baselineOffsets[Font.HANGING_BASELINE] = -ascent;
   
  -        float strikethroughOffset = fontFace.getStrikethroughPosition() *
  -            -scale;
  -        float strikethroughThickness = fontFace.getStrikethroughThickness() *
  -            scale;
  -        float underlineOffset    = fontFace.getUnderlinePosition()  * scale;
  -        float underlineThickness = fontFace.getUnderlineThickness() * scale;
  -        float overlineOffset     = fontFace.getOverlinePosition()   * -scale;
  -        float overlineThickness  = fontFace.getOverlineThickness()  * scale;
  -
  -
  -        return new GVTLineMetrics(ascent, Font.ROMAN_BASELINE,
  -                                  baselineOffsets, descent, fontHeight,
  -                                  fontHeight, limit-beginIndex, 
  -                                  strikethroughOffset, strikethroughThickness,
  -                                  underlineOffset, underlineThickness, 
  -                                  overlineOffset, overlineThickness);
  +        float stOffset    = fontFace.getStrikethroughPosition() * -scale;
  +        float stThickness = fontFace.getStrikethroughThickness() * scale;
  +        float ulOffset    = fontFace.getUnderlinePosition() * scale;
  +        float ulThickness = fontFace.getUnderlineThickness() * scale;
  +        float olOffset    = fontFace.getOverlinePosition() * -scale;
  +        float olThickness = fontFace.getOverlineThickness() * scale;
  +
  +
  +        lineMetrics = new GVTLineMetrics
  +            (ascent, Font.ROMAN_BASELINE, baselineOffsets, descent, 
  +             fontHeight, fontHeight, limit-beginIndex, 
  +             stOffset, stThickness, 
  +             ulOffset, ulThickness, 
  +             olOffset, olThickness);
  +        return lineMetrics;
       }
   
       /**
  
  
  
  1.66      +17 -1     
xml-batik/sources/org/apache/batik/bridge/SVGTextElementBridge.java
  
  Index: SVGTextElementBridge.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGTextElementBridge.java,v
  retrieving revision 1.65
  retrieving revision 1.66
  diff -u -r1.65 -r1.66
  --- SVGTextElementBridge.java 29 Apr 2002 13:20:18 -0000      1.65
  +++ SVGTextElementBridge.java 30 Apr 2002 19:08:47 -0000      1.66
  @@ -68,7 +68,7 @@
    *
    * @author <a href="[EMAIL PROTECTED]">Stephane Hillion</a>
    * @author <a href="[EMAIL PROTECTED]">Bill Haneman</a>
  - * @version $Id: SVGTextElementBridge.java,v 1.65 2002/04/29 13:20:18 tkormann Exp 
$
  + * @version $Id: SVGTextElementBridge.java,v 1.66 2002/04/30 19:08:47 deweese Exp $
    */
   public class SVGTextElementBridge extends AbstractGraphicsNodeBridge {
   
  @@ -904,6 +904,22 @@
               }
   
               return result;
  +        }
  +
  +        public String toString() {
  +            switch (count) {
  +            case 0:
  +                return "";
  +            case 1:
  +                return (String)strings.get(0);
  +            }
  +
  +            StringBuffer sb = new StringBuffer();
  +            Iterator it = strings.iterator();
  +            while (it.hasNext()) {
  +                sb.append((String)it.next());
  +            }
  +            return sb.toString();
           }
       }
   
  
  
  
  1.11      +11 -5     
xml-batik/sources/org/apache/batik/extension/svg/BatikExtConstants.java
  
  Index: BatikExtConstants.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/extension/svg/BatikExtConstants.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- BatikExtConstants.java    24 Apr 2002 12:33:29 -0000      1.10
  +++ BatikExtConstants.java    30 Apr 2002 19:08:47 -0000      1.11
  @@ -47,21 +47,27 @@
       public static final String BATIK_EXT_HEIGHT_ATTRIBUTE = 
           "height";
   
  -    /** Attribute name for margine psudo-attribute */
  +    /** Attribute name for margin psudo-attribute */
       public static final String BATIK_EXT_MARGIN_ATTRIBUTE = 
           "margin";
  -    /** Attribute name for margine psudo-attribute */
  +    /** Attribute name for top-margin attribute */
       public static final String BATIK_EXT_TOP_MARGIN_ATTRIBUTE = 
           "top-margin";
  -    /** Attribute name for margine psudo-attribute */
  +    /** Attribute name for right-margin attribute */
       public static final String BATIK_EXT_RIGHT_MARGIN_ATTRIBUTE = 
           "right-margin";
  -    /** Attribute name for margine psudo-attribute */
  +    /** Attribute name for bottom-margin attribute */
       public static final String BATIK_EXT_BOTTOM_MARGIN_ATTRIBUTE = 
           "bottom-margin";
  -    /** Attribute name for margine psudo-attribute */
  +    /** Attribute name for left-margin attribute */
       public static final String BATIK_EXT_LEFT_MARGIN_ATTRIBUTE = 
           "left-margin";
  +    /** Attribute name for first-line-left-margin attribute */
  +    public static final String BATIK_EXT_FIRST_LINE_LEFT_MARGIN_ATTRIBUTE = 
  +        "first-line-left-margin";
  +    /** Attribute name for first-line-right-margin attribute */
  +    public static final String BATIK_EXT_FIRST_LINE_RIGHT_MARGIN_ATTRIBUTE = 
  +        "first-line-right-margin";
       /** Attribute name for margine psudo-attribute */
       public static final String BATIK_EXT_JUSTIFICATION_ATTRIBUTE = 
           "justification";
  
  
  
  1.4       +41 -25    
xml-batik/sources/org/apache/batik/extension/svg/SVGFlowTextElementBridge.java
  
  Index: SVGFlowTextElementBridge.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/extension/svg/SVGFlowTextElementBridge.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SVGFlowTextElementBridge.java     24 Apr 2002 12:33:29 -0000      1.3
  +++ SVGFlowTextElementBridge.java     30 Apr 2002 19:08:47 -0000      1.4
  @@ -39,7 +39,7 @@
    * Bridge class for the &lt;flowText> element.
    *
    * @author <a href="[EMAIL PROTECTED]">Thomas DeWeese</a>
  - * @version $Id: SVGFlowTextElementBridge.java,v 1.3 2002/04/24 12:33:29 deweese 
Exp $
  + * @version $Id: SVGFlowTextElementBridge.java,v 1.4 2002/04/30 19:08:47 deweese 
Exp $
    */
   public class SVGFlowTextElementBridge extends SVGTextElementBridge 
       implements BatikExtConstants {
  @@ -289,34 +289,26 @@
           // Layer in the PARAGRAPH/LINE_BREAK Attributes so we can
           // break up text chunks.
           AttributedString ret = asb.toAttributedString();
  -        int start=0;
  -        List emptyPara = null;
  -        int prevLN = -1;
  -        Iterator lnIter = lnLocs.iterator();
   
  -        // The Working Group (in conjunction with XHTML working group
  -        // has decided that multiple line elements collapse so I don't
  -        // use the counting I do.
  +        // Note: The Working Group (in conjunction with XHTML working
  +        // group) has decided that multiple line elements collapse.
  +        int prevLN = 0;
           int lnCount = 0;
  +        Iterator lnIter = lnLocs.iterator();
           while (lnIter.hasNext()) {
               int nextLN = ((Integer)lnIter.next()).intValue();
  -            if (nextLN == prevLN) {
  -                lnCount++;
  -            } else {
  -                if (prevLN != -1)
  -                    ret.addAttribute(FLOW_LINE_BREAK, 
  -                                     new Integer(1), // new Integer(lnCount), 
  -                                     prevLN-1, prevLN);
  -                prevLN  = nextLN;
  -                lnCount = 1;
  -            }
  +            if (nextLN == prevLN) continue;
  +
  +            ret.addAttribute(FLOW_LINE_BREAK, 
  +                             new Object(),
  +                             prevLN, nextLN);
  +            // System.out.println("Attr: [" + prevLN + "," + nextLN + "]");
  +            prevLN  = nextLN;
           }
  -        if (prevLN != -1)
  -            ret.addAttribute(FLOW_LINE_BREAK,
  -                             new Integer(1), // new Integer(lnCount), 
  -                             prevLN-1, prevLN);
   
  +        int start=0;
           int end;
  +        List emptyPara = null;
           for (int i=0; i<paraElems.size(); i++, start=end) {
               Element elem = (Element)paraElems.get(i);
               end  = ((Integer)paraEnds.get(i)).intValue();
  @@ -326,7 +318,7 @@
                   emptyPara.add(makeMarginInfo(elem));
                   continue;
               }
  -            
  +            // System.out.println("Para: [" + start + ", " + end + "]");
               ret.addAttribute(FLOW_PARAGRAPH, makeMarginInfo(elem), start, end);
               if (emptyPara != null) {
                   ret.addAttribute(FLOW_EMPTY_PARAGRAPH, emptyPara, start, end);
  @@ -354,7 +346,6 @@
       
       protected List gatherRects(BridgeContext ctx, Element rgn) {
           List ret = new LinkedList();
  -        UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, rgn);
           for (Node n = rgn.getFirstChild(); 
                n != null; n = n.getNextSibling()) {
               if (n.getNodeType()     != Node.ELEMENT_NODE) continue;
  @@ -363,6 +354,8 @@
   
               String ln = n.getLocalName();
               if (ln.equals(BATIK_EXT_REGION_TAG)) {
  +                UnitProcessor.Context uctx;
  +                uctx = UnitProcessor.createContext(ctx, e);
                   Rectangle2D r2d = buildRect(uctx, e);
                   if (r2d != null)
                       ret.add(r2d);
  @@ -471,6 +464,8 @@
                   if (ln.equals(BATIK_EXT_FLOW_LINE_TAG)) {
                       fillAttributedStringBuffer(ctx, nodeElement, 
                                                  false, asb, lnLocs);
  +                    // System.out.println("Line: " + asb.length() + 
  +                    //                    " - '" +  asb + "'");
                       lnLocs.add(new Integer(asb.length()));
                   } else if (ln.equals(BATIK_EXT_FLOW_SPAN_TAG) ||
                       ln.equals(SVG_ALT_GLYPH_TAG) ||
  @@ -615,6 +610,26 @@
               }
           } catch(NumberFormatException nfe) { /* nothing */ }
   
  +        float flLeft  = left;
  +        float flRight = right;
  +
  +        s = e.getAttributeNS(null, BATIK_EXT_FIRST_LINE_LEFT_MARGIN_ATTRIBUTE);
  +        try {
  +            if (s.length() != 0) {
  +                float f = Float.parseFloat(s);
  +                flLeft = f;
  +            }
  +        } catch(NumberFormatException nfe) { /* nothing */ }
  +
  +        s = e.getAttributeNS(null,BATIK_EXT_FIRST_LINE_RIGHT_MARGIN_ATTRIBUTE);
  +        try {
  +            if (s.length() != 0) {
  +                float f = Float.parseFloat(s);
  +                flRight = f;
  +            }
  +        } catch(NumberFormatException nfe) { /* nothing */ }
  +
  +
           int justification = MarginInfo.JUSTIFY_START;
           s = e.getAttributeNS(null, BATIK_EXT_JUSTIFICATION_ATTRIBUTE);
           try {
  @@ -633,7 +648,8 @@
   
           String ln = e.getLocalName();
           boolean rgnBr = ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG);
  -        return new MarginInfo(top, right, bottom, left, justification, rgnBr);
  +        return new MarginInfo(top, right, bottom, left, flLeft, flRight,
  +                              justification, rgnBr);
       }
   
   
  
  
  
  1.18      +27 -15    
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.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- AWTGVTGlyphVector.java    7 Mar 2002 22:07:44 -0000       1.17
  +++ AWTGVTGlyphVector.java    30 Apr 2002 19:08:47 -0000      1.18
  @@ -34,7 +34,7 @@
    * This is a wrapper class for a java.awt.font.GlyphVector instance.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]";>Bella Robinson</a>
  - * @version $Id: AWTGVTGlyphVector.java,v 1.17 2002/03/07 22:07:44 deweese Exp $
  + * @version $Id: AWTGVTGlyphVector.java,v 1.18 2002/04/30 19:08:47 deweese Exp $
    */
   public class AWTGVTGlyphVector implements GVTGlyphVector {
   
  @@ -94,12 +94,12 @@
           outline       = null;
           logicalBounds = null;
           int numGlyphs = glyphVector.getNumGlyphs();
  -        glyphPositions     = new Point2D.Float[numGlyphs+1];
  +        glyphPositions     = new Point2D.Float  [numGlyphs+1];
           glyphTransforms    = new AffineTransform[numGlyphs];
  -        glyphOutlines      = new Shape[numGlyphs];
  -        glyphVisualBounds  = new Shape[numGlyphs];
  -        glyphLogicalBounds = new Shape[numGlyphs];
  -        glyphVisible       = new boolean[numGlyphs];
  +        glyphOutlines      = new Shape          [numGlyphs];
  +        glyphVisualBounds  = new Shape          [numGlyphs];
  +        glyphLogicalBounds = new Shape          [numGlyphs];
  +        glyphVisible       = new boolean        [numGlyphs];
           glyphMetrics       = new GVTGlyphMetrics[numGlyphs];
   
           for (int i = 0; i < numGlyphs; i++) {
  @@ -590,7 +590,7 @@
               glyphVisualBounds [i] = null;
               glyphLogicalBounds[i] = null;
               glyphOutlines     [i] = null;
  -
  +            glyphMetrics      [i] = null;
               Point2D glyphPos = defaultGlyphPositions[i];
               glyphPositions[i] = new Point2D.Float
                   ((float)((glyphPos.getX() * scaleFactor)-shiftLeft),
  @@ -621,9 +621,10 @@
           logicalBounds = null;
           visualBounds = null;
           if (glyphIndex != getNumGlyphs()) {
  -            glyphVisualBounds[glyphIndex] = null;
  +            glyphVisualBounds [glyphIndex] = null;
               glyphLogicalBounds[glyphIndex] = null;
  -            glyphOutlines[glyphIndex] = null;
  +            glyphOutlines     [glyphIndex] = null;
  +            glyphMetrics      [glyphIndex] = null;
           }
       }
   
  @@ -635,22 +636,33 @@
           outline = null;
           logicalBounds = null;
           visualBounds = null;
  -        glyphVisualBounds[glyphIndex] = null;
  +        glyphVisualBounds [glyphIndex] = null;
           glyphLogicalBounds[glyphIndex] = null;
  -        glyphOutlines[glyphIndex] = null;
  +        glyphOutlines     [glyphIndex] = null;
  +        glyphMetrics      [glyphIndex] = null;
       }
   
       /**
        * Tells the glyph vector whether or not to draw the specified glyph.
        */
       public void setGlyphVisible(int glyphIndex, boolean visible) {
  +        if (visible == glyphVisible[glyphIndex]) 
  +            return;
           glyphVisible[glyphIndex] = visible;
  -        outline = null;
  +        outline       = null;
           logicalBounds = null;
  -        visualBounds = null;
  -        glyphVisualBounds[glyphIndex] = null;
  +        visualBounds  = null;
  +        glyphVisualBounds [glyphIndex] = null;
           glyphLogicalBounds[glyphIndex] = null;
  -        glyphOutlines[glyphIndex] = null;
  +        glyphOutlines     [glyphIndex] = null;
  +        glyphMetrics      [glyphIndex] = null;
  +    }
  +
  +    /**
  +     * Returns true if specified glyph will be rendered.
  +     */
  +    public boolean isGlyphVisible(int glyphIndex) {
  +        return glyphVisible[glyphIndex];
       }
   
       /**
  
  
  
  1.8       +6 -1      xml-batik/sources/org/apache/batik/gvt/font/GVTGlyphVector.java
  
  Index: GVTGlyphVector.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/font/GVTGlyphVector.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- GVTGlyphVector.java       18 Sep 2001 21:19:00 -0000      1.7
  +++ GVTGlyphVector.java       30 Apr 2002 19:08:47 -0000      1.8
  @@ -25,7 +25,7 @@
    * An interface for all GVT GlyphVector classes.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]";>Bella Robinson</a>
  - * @version $Id: GVTGlyphVector.java,v 1.7 2001/09/18 21:19:00 deweese Exp $
  + * @version $Id: GVTGlyphVector.java,v 1.8 2002/04/30 19:08:47 deweese Exp $
    */
   public interface GVTGlyphVector {
   
  @@ -143,6 +143,11 @@
        * Tells the glyph vector whether or not to draw the specified glyph.
        */
       void setGlyphVisible(int glyphIndex, boolean visible);
  +
  +    /**
  +     * Returns true if specified glyph will be drawn.
  +     */
  +    public boolean isGlyphVisible(int glyphIndex);
   
       /**
        * Returns the number of chars represented by the glyphs within the
  
  
  
  1.2       +8 -0      
xml-batik/sources/org/apache/batik/gvt/font/MultiGlyphVector.java
  
  Index: MultiGlyphVector.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/gvt/font/MultiGlyphVector.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MultiGlyphVector.java     7 Mar 2002 22:07:44 -0000       1.1
  +++ MultiGlyphVector.java     30 Apr 2002 19:08:47 -0000      1.2
  @@ -184,6 +184,14 @@
       }
   
       /**
  +     * Returns true if specified glyph will be drawn.
  +     */
  +    public boolean isGlyphVisible(int glyphIndex) {
  +        int idx = getGVIdx(glyphIndex);
  +        return gvs[idx].isGlyphVisible(glyphIndex-off[idx]);
  +    }
  +
  +    /**
        * Returns an array of glyphcodes for the specified glyphs.
        */
       public int[] getGlyphCodes(int beginGlyphIndex, int numEntries, 
  
  
  
  1.12      +11 -1     
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.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- SVGGVTGlyphVector.java    25 Apr 2002 00:45:42 -0000      1.11
  +++ SVGGVTGlyphVector.java    30 Apr 2002 19:08:47 -0000      1.12
  @@ -29,7 +29,7 @@
    * A GVTGlyphVector class for SVG fonts.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]";>Bella Robinson</a>
  - * @version $Id: SVGGVTGlyphVector.java,v 1.11 2002/04/25 00:45:42 deweese Exp $
  + * @version $Id: SVGGVTGlyphVector.java,v 1.12 2002/04/30 19:08:47 deweese Exp $
    */
   public final class SVGGVTGlyphVector implements GVTGlyphVector {
   
  @@ -672,10 +672,20 @@
        * Tells the glyph vector whether or not to draw the specified glyph.
        */
       public void setGlyphVisible(int glyphIndex, boolean visible) {
  +        if (visible == glyphVisible[glyphIndex]) 
  +            return;
  +
           glyphVisible[glyphIndex] = visible;
           outline = null;
           logicalBounds = null;
           glyphLogicalBounds[glyphIndex] = null;
  +    }
  +
  +    /**
  +     * Returns true if specified glyph will be rendered.
  +     */
  +    public boolean isGlyphVisible(int glyphIndex) {
  +        return glyphVisible[glyphIndex];
       }
   
       /**
  
  
  
  1.34      +229 -168  
xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
  
  Index: StrokingTextPainter.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- StrokingTextPainter.java  29 Apr 2002 13:20:19 -0000      1.33
  +++ StrokingTextPainter.java  30 Apr 2002 19:08:48 -0000      1.34
  @@ -61,7 +61,7 @@
    * @see org.apache.batik.gvt.text.GVTAttributedCharacterIterator
    *
    * @author <a href="[EMAIL PROTECTED]>Bill Haneman</a>
  - * @version $Id: StrokingTextPainter.java,v 1.33 2002/04/29 13:20:19 tkormann Exp $
  + * @version $Id: StrokingTextPainter.java,v 1.34 2002/04/30 19:08:48 deweese Exp $
    */
   public class StrokingTextPainter extends BasicTextPainter {
   
  @@ -211,6 +211,8 @@
           textRuns = new ArrayList();
           TextChunk chunk, prevChunk=null;
           int currentChunk = 0;
  +
  +        Point2D location = node.getLocation();
           do {
            // Text Chunks contain one or more TextRuns, which they
            // create from the ACI.
  @@ -221,11 +223,11 @@
                                    chunkCharMaps[currentChunk],
                                    textRuns,
                                    prevChunk);
  -         
  +            
               // Adjust according to text-anchor property value
               chunkACIs[currentChunk].first();
               if (chunk != null) {
  -                adjustChunkOffsets(textRuns, chunk);
  +                location = adjustChunkOffsets(location, textRuns, chunk);
               }
               prevChunk = chunk;
               currentChunk++;
  @@ -273,6 +275,10 @@
   
           List aciList = new ArrayList();
           int chunkStartIndex = aci.getBeginIndex();
  +        aci.first();
  +        Object writingMode = aci.getAttribute(WRITING_MODE);
  +        boolean vertical = (writingMode == WRITING_MODE_TTB);
  +
           while (aci.setIndex(chunkStartIndex) != CharacterIterator.DONE) {
               TextPath prevTextPath = null;
               for (int start=chunkStartIndex, end=0; 
  @@ -283,13 +289,17 @@
                   if (start != chunkStartIndex) {
                       // If we aren't the first composite in a chunck see
                       // if we need to form a new TextChunk...
  -                    Float runX = (Float) aci.getAttribute(XPOS);
  -                    Float runY = (Float) aci.getAttribute(YPOS);
  -
  -                    // Check if we have an absolute location
  -                    if (  ((runX != null) && !runX.isNaN())
  -                        ||((runY != null) && !runY.isNaN()))
  -                        break; // If so end of chunk...
  +                    if (vertical) {
  +                        Float runY = (Float) aci.getAttribute(YPOS);
  +                        // Check for absolute location in layout direction.
  +                        if ((runY != null) && !runY.isNaN())
  +                            break; // If so end of chunk...
  +                    } else {
  +                        Float runX = (Float) aci.getAttribute(XPOS);
  +                        // Check for absolute location in layout direction.
  +                        if ((runX != null) && !runX.isNaN())
  +                            break; // If so end of chunk...
  +                    }
   
                       // do additional check for the start of a textPath
                       if ((prevTextPath == null) && (textPath != null))
  @@ -328,28 +338,39 @@
                   // (technically we have to do this for
                   // text-anchor:start as well but since that is the
                   // default layout it doesn't matter in that case.
  -                Float runX = (Float) aci.getAttribute(XPOS);
  -                Float runY = (Float) aci.getAttribute(YPOS);
  -                if (((runX == null) || runX.isNaN()) &&
  -                    ((runY == null) || runY.isNaN()))
  -                    // No absolute positioning in this compound so continue.
  -                    continue;
  +                if (vertical) {
  +                    Float runY = (Float) aci.getAttribute(YPOS);
  +                    // Check for absolute location in layout direction.
  +                    if ((runY == null) || runY.isNaN())
  +                        // No absolute positioning in text direction continue
  +                        continue;
  +                } else {
  +                    Float runX = (Float) aci.getAttribute(XPOS);
  +                    // Check for absolute location in layout direction.
  +                    if ((runX == null) || runX.isNaN())
  +                        // No absolute positioning in text direction continue
  +                        continue;
  +                }
   
                   // Splitting the compound into one char chunks until
                   // we run out of Xs.
                   for (int i=start+1; i< end; i++) {
                       aci.setIndex(i);
  -                    runX = (Float) aci.getAttribute(XPOS);
  -                    runY = (Float) aci.getAttribute(YPOS);
  -                    if (((runX == null) || runX.isNaN()) &&
  -                        ((runY == null) || runY.isNaN()))
  -                        break;
  -                    aciList.add 
  -                        (new AttributedCharacterSpanIterator(aci, i-1, i));
  +                    if (vertical) {
  +                        Float runY = (Float) aci.getAttribute(YPOS);
  +                        if ((runY == null) || runY.isNaN())
  +                            break;
  +                    } else {
  +                        Float runX = (Float) aci.getAttribute(XPOS);
  +                        if ((runX == null) || runX.isNaN())
  +                            break;
  +                    }
  +                    aciList.add(new AttributedCharacterSpanIterator
  +                        (aci, i-1, i));
                       chunkStartIndex = i;
                   }
               }
  -
  +            
               // found the end of a text chunck
               int chunkEndIndex = aci.getIndex();
               // System.out.println("Bounds: " + chunkStartIndex + 
  @@ -370,113 +391,6 @@
           return aciArray;
       }
   
  -    private TextChunk getTextChunk(TextNode node,
  -                                   AttributedCharacterIterator aci,
  -                                   int [] charMap,
  -                                   List textRuns,
  -                                   TextChunk prevChunk) {
  -        int beginChunk = 0;
  -        if (prevChunk != null)
  -            beginChunk = prevChunk.end;
  -        int endChunk = beginChunk;
  -        int begin = aci.getIndex();
  -        // System.out.println("New Chunk");
  -        if (aci.current() == CharacterIterator.DONE) 
  -            return null;
  -
  -        Point2D advance = new Point2D.Float(0,0);
  -        Point2D location;
  -        if (prevChunk == null) {
  -            location = node.getLocation();
  -        } else {
  -            location = new Point2D.Float
  -                ((float)(prevChunk.absLoc.getX()+prevChunk.advance.getX()),
  -                 (float)(prevChunk.absLoc.getY()+prevChunk.advance.getY()));
  -        }
  -        boolean  isChunkStart        = true;
  -        TextPath prevTextPath        = null;
  -        Point2D  prevTextPathAdvance = null;
  -        do {
  -            int start = aci.getRunStart(extendedAtts);
  -            int end   = aci.getRunLimit(extendedAtts);
  -
  -            AttributedCharacterIterator runaci;
  -            runaci = new AttributedCharacterSpanIterator(aci, start, end);
  -            runaci.first();
  -
  -            boolean vertical = 
  -                (aci.getAttribute(WRITING_MODE) == WRITING_MODE_TTB);
  -            Float runX = (Float) runaci.getAttribute(XPOS);
  -            Float runY = (Float) runaci.getAttribute(YPOS);
  -
  -            TextPath textPath =  (TextPath) runaci.getAttribute(TEXTPATH);
  -             
  -            Point2D.Float offset;
  -            if (textPath == null) {
  -                if ((prevTextPath != null) && 
  -                    (prevTextPathAdvance != null)) {
  -                    // this text is directly after some text on a path
  -                    offset = new Point2D.Float
  -                        ((float)prevTextPathAdvance.getX(),
  -                         (float)prevTextPathAdvance.getY());
  -                } else {
  -                    offset = new Point2D.Float
  -                        ((float) (location.getX()+advance.getX()),
  -                         (float) (location.getY()+advance.getY()));
  -                }
  -
  -                // Of course X and Y override all that...
  -                if ((runX != null) && (!runX.isNaN()))
  -                    offset.x = runX.floatValue();
  -
  -                if ((runY != null) && (!runY.isNaN()))
  -                    offset.y = runY.floatValue();
  -            } else {
  -                // is on a text path so ignore the text node's location
  -                offset = new Point2D.Float((float)advance.getX(),
  -                                           (float)advance.getY());
  -                // Only use the x or y in writing direction...
  -                if (vertical) {
  -                    if ((runY != null) && (!runY.isNaN()))
  -                        offset.y = runY.floatValue();
  -                } else {
  -                    if ((runX != null) && (!runX.isNaN()))
  -                        offset.x = runX.floatValue();
  -                }
  -            }
  -                    
  -            int [] subCharMap = new int[end-start];
  -            for (int i=0; i<subCharMap.length; i++) {
  -                subCharMap[i] = charMap[i+start-begin];
  -            }
  -            TextSpanLayout layout = getTextLayoutFactory().
  -                createTextLayout(runaci, subCharMap, 
  -                                 offset, fontRenderContext);
  -            // System.out.println("TextRun: " + start +  "->" + end + 
  -            //                    " Start: " + isChunkStart);
  -            TextRun run = new TextRun(layout, runaci, isChunkStart);
  -            textRuns.add(run);
  -            Point2D layoutAdvance = layout.getAdvance2D();
  -            if (isChunkStart)
  -                location = layout.getOffset();
  -
  -            // System.out.println("layoutAdv: " + layoutAdvance);
  -
  -            advance = new Point2D.Float
  -                ((float) (advance.getX()+layoutAdvance.getX()),
  -                 (float) (advance.getY()+layoutAdvance.getY()));
  -            ++endChunk;
  -            prevTextPath = textPath;
  -            prevTextPathAdvance = layout.getTextPathAdvance();
  -            if (aci.setIndex(end) == CharacterIterator.DONE) break;
  -            isChunkStart = false;
  -        } while (true);
  -        // System.out.println("Adv: " + advance);
  -        return new TextChunk(beginChunk, endChunk, location, advance);
  -    }
  -
  -
  -
       /**
        * Returns a new AttributedCharacterIterator that contains resolved GVTFont
        * attributes. This is then used when creating the text runs so that the
  @@ -675,18 +589,74 @@
       }
   
   
  +    private TextChunk getTextChunk(TextNode node,
  +                                   AttributedCharacterIterator aci,
  +                                   int [] charMap,
  +                                   List textRuns,
  +                                   TextChunk prevChunk) {
  +        int beginChunk = 0;
  +        if (prevChunk != null)
  +            beginChunk = prevChunk.end;
  +        int endChunk = beginChunk;
  +        int begin    = aci.getIndex();
  +        // System.out.println("New Chunk");
  +        if (aci.current() == CharacterIterator.DONE) 
  +            return null;
  +
  +        Point2D  advance      = new Point2D.Float(0,0);
  +        boolean  isChunkStart = true;
  +        TextSpanLayout layout = null;
  +        do {
  +            int start = aci.getRunStart(extendedAtts);
  +            int end   = aci.getRunLimit(extendedAtts);
  +
  +            AttributedCharacterIterator runaci;
  +            runaci = new AttributedCharacterSpanIterator(aci, start, end);
  +
  +            int [] subCharMap = new int[end-start];
  +            for (int i=0; i<subCharMap.length; i++) {
  +                subCharMap[i] = charMap[i+start-begin];
  +            }
  +
  +            Point2D.Float offset;
  +            offset = new Point2D.Float((float)advance.getX(),
  +                                       (float)advance.getY());
  +
  +            layout = getTextLayoutFactory().createTextLayout
  +                (runaci, subCharMap, offset, fontRenderContext);
  +            textRuns.add(new TextRun(layout, runaci, isChunkStart));
  +            // System.out.println("TextRun: " + start +  "->" + end + 
  +            //                    " Start: " + isChunkStart);
  +
  +            Point2D layoutAdvance = layout.getAdvance2D();
  +            // System.out.println("layoutAdv: " + layoutAdvance);
  +            advance = new Point2D.Float
  +                ((float) (advance.getX()+layoutAdvance.getX()),
  +                 (float) (advance.getY()+layoutAdvance.getY()));
  +            ++endChunk;
  +            if (aci.setIndex(end) == CharacterIterator.DONE) break;
  +            isChunkStart = false;
  +        } while (true);
  +        
  +        // System.out.println("Adv: " + advance);
  +        // System.out.println("Chunks: [" + beginChunk + ", " + 
  +        //                    endChunk + "]");
  +        return new TextChunk(beginChunk, endChunk, advance);
  +    }
  +
  +
   
       /**
        * Adjusts the position of the text runs within the specified text chunk
        * to account for any text anchor properties.
        */
  -    private void adjustChunkOffsets(List textRuns, 
  +    private Point2D adjustChunkOffsets(Point2D location,
  +                                    List textRuns, 
                                       TextChunk chunk) {
           TextRun r          = (TextRun) textRuns.get(chunk.begin);
           int     anchorType = r.getAnchorType();
           Float   length     = r.getLength();
           Integer lengthAdj  = r.getLengthAdjust();
  -        Point2D advance    = chunk.advance;
   
           boolean doAdjust = true;
           if ((length == null) || length.isNaN())
  @@ -705,17 +675,28 @@
   
           float xScale = 1;
           float yScale = 1;
  -        if (doAdjust) {
  +
  +        r = (TextRun)textRuns.get(chunk.end-1);
  +        TextSpanLayout  layout          = r.getLayout();
  +        GVTGlyphMetrics lastMetrics = 
  +            layout.getGlyphMetrics(layout.getGlyphCount()-1);
  +        Rectangle2D     lastBounds  = lastMetrics.getBounds2D();
  +        
  +        Point2D visualAdvance;
  +        
  +        if (!doAdjust) {
  +            visualAdvance = new Point2D.Float
  +            ((float)(chunk.advance.getX() + lastBounds.getWidth() -
  +                     lastMetrics.getHorizontalAdvance()),
  +             (float)(chunk.advance.getY() + lastBounds.getHeight() -
  +                     lastMetrics.getVerticalAdvance()));
  +        } else {
  +            Point2D advance    = chunk.advance;
  +
               // We have to do this here since textLength needs to be
               // handled at the text chunk level. Otherwise tspans get
               // messed up.
               float delta = 0;
  -            r = (TextRun)textRuns.get(chunk.end-1);
  -            TextSpanLayout  layout          = r.getLayout();
  -            GVTGlyphMetrics lastMetrics = 
  -                layout.getGlyphMetrics(layout.getGlyphCount()-1);
  -            Rectangle2D     lastBounds  = lastMetrics.getBounds2D();
  -
               if (layout.isVertical()) {
                   if (lengthAdj == ADJUST_SPACING) {
                       yScale = (float)
  @@ -725,19 +706,20 @@
                       double adv = (advance.getY()-
                                     lastMetrics.getVerticalAdvance() +
                                     lastBounds.getHeight());
  -                    xScale = (float)(length.floatValue()/adv);
  +                    yScale = (float)(length.floatValue()/adv);
                   }
  +                visualAdvance = new Point2D.Float(0, length.floatValue());
               } else {
                   if (lengthAdj == ADJUST_SPACING) {
                       xScale = (float)
                           ((length.floatValue()-lastBounds.getWidth())/
                            (advance.getX()-lastMetrics.getHorizontalAdvance()));
                   } else {
  -                    double adv = (advance.getX()-
  -                                  lastMetrics.getHorizontalAdvance() +
  -                                  lastBounds.getWidth());
  +                    double adv = (advance.getX() + lastBounds.getWidth() -
  +                                  lastMetrics.getHorizontalAdvance());
                       xScale = (float)(length.floatValue()/adv);
                   }
  +                visualAdvance = new Point2D.Float(length.floatValue(), 0);
               }
   
               // System.out.println("Adv: " + advance + " Len: " + length +
  @@ -748,52 +730,135 @@
                   layout = r.getLayout();
                   layout.setScale(xScale, yScale, lengthAdj==ADJUST_SPACING);
                   Point2D lAdv = layout.getAdvance2D();
  -                adv.x += lAdv.getX();
  -                adv.y += lAdv.getY();
  +                adv.x += (float)lAdv.getX();
  +                adv.y += (float)lAdv.getY();
               }
               chunk.advance = adv;
           }
  -
  -        advance = chunk.advance;
  +        if (true) {
  +            visualAdvance = chunk.advance;
  +        }
   
           float dx = 0f;
           float dy = 0f;
           switch(anchorType){
           case TextNode.Anchor.ANCHOR_MIDDLE:
  -            dx = (float) (-advance.getX()/2d);
  -            dy = (float) (-advance.getY()/2d);
  +            dx = (float) (-visualAdvance.getX()/2d);
  +            dy = (float) (-visualAdvance.getY()/2d);
               break;
           case TextNode.Anchor.ANCHOR_END:
  -            dx = (float) (-advance.getX());
  -            dy = (float) (-advance.getY());
  +            dx = (float) (-visualAdvance.getX());
  +            dy = (float) (-visualAdvance.getY());
               break;
           default:
               break;
               // leave untouched
           }
   
  +        // System.out.println("DX/DY: [" + dx + ", " + dy + "]");
           
           r = (TextRun) textRuns.get(chunk.begin);
  -            TextSpanLayout layout = r.getLayout();
  -            Point2D        offset = layout.getOffset();
  -        float initX = (float)offset.getX();
  -        float initY = (float)offset.getY();
  +        layout = r.getLayout();
  +        AttributedCharacterIterator runaci = r.getACI();
  +        runaci.first();
  +        boolean vertical = layout.isVertical();
  +        Float runX = (Float) runaci.getAttribute(XPOS);
  +        Float runY = (Float) runaci.getAttribute(YPOS);
  +        TextPath textPath =  (TextPath) runaci.getAttribute(TEXTPATH);
  +
  +        float absX = (float)location.getX();
  +        float absY = (float)location.getY();
  +        float advX = 0;
  +        float advY = 0;
  +        float tpShiftX = 0;
  +        float tpShiftY = 0;
  +        float shiftX = 0;
  +        float shiftY = 0;
  +
  +        if (textPath == null) {
  +            // Of course X and Y override all that...
  +            if ((runX != null) && (!runX.isNaN()))
  +                absX = runX.floatValue();
  +
  +            if ((runY != null) && (!runY.isNaN()))
  +                absY = runY.floatValue();
  +        } else {
  +            absX = 0;
  +            absY = 0;
  +            // Only use the x or y in writing direction...
  +            if (vertical) {
  +                if ((runY != null) && (!runY.isNaN())) {
  +                    absY = runY.floatValue();
  +                    tpShiftY = absY;
  +                }
  +            } else {
  +                if ((runX != null) && (!runX.isNaN())) {
  +                    absX = runX.floatValue();
  +                    tpShiftX = absX;
  +                }
  +            }
  +        }
  +        // System.out.println("ABS: [" + absX + "," + absY + "]");
   
  +        float retX = absX;
  +        float retY = absY;
           for (int n=chunk.begin; n<chunk.end; ++n) {
               r = (TextRun) textRuns.get(n);
               layout = r.getLayout();
  -            offset = layout.getOffset();
  +            runaci = r.getACI();
  +            runaci.first();
  +            textPath =  (TextPath) runaci.getAttribute(TEXTPATH);
  +
  +            Point2D offset = layout.getOffset();
  +            // System.out.println("Offset1: " + offset);
  +            // System.out.println("Shift: [" + shiftX + "," + shiftY + "]");
  +            if (textPath != null) {
  +                // For text path use relative values.
  +                absX = tpShiftX;
  +                absY = tpShiftY;
  +
  +                shiftX = 0;
  +                shiftY = 0;
  +            }
               if (layout.isVertical()) {
  -                float adj = (float)((offset.getY()-initY)*yScale);
  -                offset = new Point2D.Float((float) offset.getX(),
  -                                           (float)initY+adj+dy);
  +                float adj = (float)((offset.getY()-shiftY)*yScale);
  +                offset = new Point2D.Float((float)absX,
  +                                           (float)absY+adj+dy);
               } else {
  -                float adj = (float)((offset.getX()-initX)*xScale);
  -                offset = new Point2D.Float((float)initX+adj+dx,
  -                                           (float) offset.getY());
  +                float adj = (float)((offset.getX()-shiftX)*xScale);
  +                offset = new Point2D.Float((float)absX+adj+dx,
  +                                           (float)absY);
               }
  +            // System.out.println("Offset2: " + offset);
               layout.setOffset(offset);
  +
  +            if (textPath == null) {
  +                Point2D ladv = layout.getAdvance2D();
  +                retX = (float)(offset.getX()+ladv.getX());
  +                retY = (float)(offset.getY()+ladv.getY());
  +                if (vertical)
  +                    absX += ladv.getX();
  +                else
  +                    absY += ladv.getY();
  +            } else {
  +                Point2D ladv = layout.getAdvance2D();
  +                advX += (float)ladv.getX();
  +                advY += (float)ladv.getY();
  +                shiftX = advX;
  +                shiftY = advY;
  +                if (vertical)
  +                    tpShiftX += (float)ladv.getX();
  +                else
  +                    tpShiftY += (float)ladv.getY();
  +
  +                ladv = layout.getTextPathAdvance();
  +                absX = (float)ladv.getX();
  +                absY = (float)ladv.getY();
  +                retX = absX;
  +                retY = absY;
  +            }
           }
  +        return new Point2D.Float(retX, retY);
       }
   
       /**
  @@ -1543,14 +1608,10 @@
           public int begin;
           public int end;
           public Point2D advance;
  -        public Point2D absLoc;
   
  -        public TextChunk(int begin, int end, 
  -                         Point2D absLoc, Point2D advance) {
  +        public TextChunk(int begin, int end, Point2D advance) {
               this.begin = begin;
               this.end = end;
  -            this.absLoc  = new Point2D.Float((float) absLoc.getX(),
  -                                             (float) absLoc.getY());
               this.advance = new Point2D.Float((float) advance.getX(),
                                                (float) advance.getY());
           }
  
  
  
  1.5       +122 -55   xml-batik/sources/org/apache/batik/gvt/text/GlyphIterator.java
  
  Index: GlyphIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/GlyphIterator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- GlyphIterator.java        25 Apr 2002 00:45:42 -0000      1.4
  +++ GlyphIterator.java        30 Apr 2002 19:08:48 -0000      1.5
  @@ -41,12 +41,21 @@
   
       // The ACI index of current glyph.
       int   aciIdx      = -1;
  +    // The number of characters in ACI for current Glyph.
  +    int   charCount   = -1;
  +
       // The total advance for line including last non-space glyph
       float adv         =  0;
       // The total advance for line including spaces at end of line.
       float adj         =  0;
  -    // The runLimit (for current font)
  +    // The runLimit for current font
       int     runLimit   = 0;
  +
  +    // The runLimit for current line element (need a line break at end).
  +    int     lineBreakRunLimit = 0;
  +    int     lineBreakCount    = 0;
  +
  +
       GVTFont font       = null;
       int     fontStart  = 0;
       float   maxAscent  = 0;
  @@ -74,20 +83,21 @@
       // The current left shift (inherited from previous line).
       int leftShift = 0;
   
  +    Point2D gvBase = null;
   
       
       public GlyphIterator(AttributedCharacterIterator aci,
                            GVTGlyphVector gv) {
  -        this.aci      = aci;
  -        this.gv       = gv;
  -
  -        this.idx      = 0;
  -        this.chIdx    = 0;
  -        this.lineIdx  = 0;
  -        this.aciIdx   = aci.getBeginIndex();
  -        this.ch       = aci.first();
  -        this.chIdx    = 0;
  -        this.frc      = gv.getFontRenderContext();
  +        this.aci       = aci;
  +        this.gv        = gv;
  + 
  +        this.idx       = 0;
  +        this.chIdx     = -1;
  +        this.lineIdx   = 0;
  +        this.aciIdx    = aci.getBeginIndex();
  +        this.charCount = gv.getCharacterCount(idx, idx);
  +        this.ch        = aci.first();
  +        this.frc       = gv.getFontRenderContext();
           
           this.font = (GVTFont)aci.getAttribute(GVT_FONT);
           if (font == null) {
  @@ -100,9 +110,15 @@
   
           // Figure out where the font size might change again...
           this.runLimit  = aci.getRunLimit(TEXT_COMPOUND_DELIMITER);
  +        
  +        this.lineBreakRunLimit = aci.getRunLimit(FLOW_LINE_BREAK);
  +        Object o = (Object)aci.getAttribute(FLOW_LINE_BREAK);
  +        this.lineBreakCount = (o == null)?0:1;
  +
   
           this.numGlyphs   = gv.getNumGlyphs();
           this.gp          = gv.getGlyphPositions(0, this.numGlyphs+1, null);
  +        this.gvBase      = new Point2D.Float(gp[0], gp[1]);
           this.adv = getCharWidth();
           this.adj = getCharAdvance();
       }
  @@ -122,13 +138,17 @@
           gi.idx        = this.idx;
           gi.chIdx      = this.chIdx;
           gi.aciIdx     = this.aciIdx;
  +        gi.charCount  = this.charCount;
           gi.adv        = this.adv;
           gi.adj        = this.adj;
           gi.runLimit   = this.runLimit;
           gi.ch         = this.ch;
  -        gi.chIdx      = this.chIdx;
           gi.numGlyphs  = this.numGlyphs;
           gi.gp         = this.gp;
  +        gi.gvBase     = this.gvBase;
  +
  +        gi.lineBreakRunLimit = this.lineBreakRunLimit;
  +        gi.lineBreakCount    = this.lineBreakCount;
   
           gi.frc         = this.frc;
           gi.font        = this.font;
  @@ -166,6 +186,12 @@
       public float getAdv() { return adv; }
   
       /**
  +     * @return The origin of the glyph vector (the point all glyphs are
  +     * layed out with respect to).
  +     */
  +    public Point2D getOrigin() { return gvBase; }
  +
  +    /**
        * @return The current adjustment for the line.  This is the ammount
        * that needs to be subracted from the following line to get it back
        * to the start of the next line.
  @@ -174,7 +200,7 @@
   
       public float getMaxFontSize()  {
           if (aciIdx >= fontStart) {
  -            int newFS = aciIdx + gv.getCharacterCount(idx,idx);
  +            int newFS = aciIdx + charCount;
               updateLineMetrics(newFS);
               fontStart = newFS;
           }
  @@ -183,7 +209,7 @@
   
       public float getMaxAscent()  { 
           if (aciIdx >= fontStart) {
  -            int newFS = aciIdx + gv.getCharacterCount(idx,idx);
  +            int newFS = aciIdx + charCount;
               updateLineMetrics(newFS);
               fontStart = newFS;
           }
  @@ -192,7 +218,7 @@
   
       public float getMaxDescent() { 
           if (aciIdx >= fontStart) {
  -            int newFS = aciIdx + gv.getCharacterCount(idx,idx);
  +            int newFS = aciIdx + charCount;
               updateLineMetrics(newFS);
               fontStart = newFS;
           }
  @@ -228,9 +254,22 @@
       }        
          
       public int getLineBreaks() {
  -        Integer i = (Integer)aci.getAttribute(FLOW_LINE_BREAK);
  -        if (i == null) return 0;
  -        return i.intValue();
  +        int ret = 0;
  +        if (aciIdx+charCount >= lineBreakRunLimit) {
  +            // Next char is outside this line element so break after
  +            // the current char.
  +            ret = lineBreakCount;
  +
  +            // Update the lineBreakRunLimit, this is a bit tricky since
  +            // The attribute doesn't change until the next glyph...
  +            aci.setIndex(aciIdx+charCount);
  +            lineBreakRunLimit = aci.getRunLimit(FLOW_LINE_BREAK);
  +            aci.setIndex(aciIdx);  // Restore location...
  +
  +            Object o = (Object)aci.getAttribute(FLOW_LINE_BREAK);
  +            lineBreakCount = (o == null)?0:1;
  +        }
  +        return ret;
       }
   
       /**
  @@ -243,32 +282,14 @@
               // Special handling for soft hyphens and zero-width spaces
               gv.setGlyphVisible(idx, false);
               float chAdv = getCharAdvance();
  -            float chW   = getCharWidth();
  -            adv -= chW;
               adj -= chAdv;
  -            if (leftShiftIdx == null) {
  -                leftShiftIdx = new int[1];
  -                leftShiftIdx[0] = idx;
  -                leftShiftAmt = new float[1];
  -                leftShiftAmt[0] = chAdv;
  -            } else {
  -                int [] newLeftShiftIdx = new int[leftShiftIdx.length+1];
  -                for (int i=0; i<leftShiftIdx.length; i++)
  -                    newLeftShiftIdx[i] = leftShiftIdx[i];
  -                newLeftShiftIdx[leftShiftIdx.length] = idx;
  -                leftShiftIdx = newLeftShiftIdx;
  -
  -                float [] newLeftShiftAmt = new float[leftShiftAmt.length+1];
  -                for (int i=0; i<leftShiftAmt.length; i++)
  -                    newLeftShiftAmt[i] = leftShiftAmt[i];
  -                newLeftShiftAmt[leftShiftAmt.length] = chAdv;
  -                leftShiftAmt = newLeftShiftAmt;
  -            }
  +            addLeftShift(idx, chAdv);
           }
   
  -        aciIdx += gv.getCharacterCount(idx,idx);
  +        aciIdx += charCount;
           ch = aci.setIndex(aciIdx);
           idx++;
  +        charCount = gv.getCharacterCount(idx,idx);
           if (idx == numGlyphs) return;
   
           if (aciIdx >= runLimit) {
  @@ -290,6 +311,27 @@
           }
       }
   
  +    protected void addLeftShift(int idx, float chAdv) {
  +        if (leftShiftIdx == null) {
  +            leftShiftIdx = new int[1];
  +            leftShiftIdx[0] = idx;
  +            leftShiftAmt = new float[1];
  +            leftShiftAmt[0] = chAdv;
  +        } else {
  +            int [] newLeftShiftIdx = new int[leftShiftIdx.length+1];
  +            for (int i=0; i<leftShiftIdx.length; i++)
  +                newLeftShiftIdx[i] = leftShiftIdx[i];
  +            newLeftShiftIdx[leftShiftIdx.length] = idx;
  +            leftShiftIdx = newLeftShiftIdx;
  +
  +            float [] newLeftShiftAmt = new float[leftShiftAmt.length+1];
  +            for (int i=0; i<leftShiftAmt.length; i++)
  +                newLeftShiftAmt[i] = leftShiftAmt[i];
  +            newLeftShiftAmt[leftShiftAmt.length] = chAdv;
  +            leftShiftAmt = newLeftShiftAmt;
  +        }
  +    }
  +
       protected void updateLineMetrics(int end) {
           GVTLineMetrics glm = font.getLineMetrics
               (aci, fontStart, end, frc);
  @@ -301,9 +343,9 @@
           if (fontSz >  maxFontSize) maxFontSize = fontSz;
       }
   
  -    public LineInfo getLineInfo(Point2D.Float loc, 
  -                                float lineWidth, 
  -                                boolean partial) {
  +    public LineInfo newLine(Point2D.Float loc, 
  +                            float lineWidth, 
  +                            boolean partial) {
           if (ch == SOFT_HYPHEN) {
               gv.setGlyphVisible(idx, true);
           }
  @@ -324,23 +366,48 @@
           leftShiftIdx = null;
           leftShiftAmt = null;
   
  -        return new LineInfo(aci, gv, lineIdx, idx+1, loc, adv, adj,
  -                            getCharWidth(chIdx), lineWidth, partial);
  -    }
  +        int   lineInfoIdx = idx+1;
  +        float lineInfoAdv = adv;
  +        float lineInfoAdj = adj;
  +        float lineInfoChW;
  +        int   hideIdx;
  +        if (chIdx != -1) {
  +            lineInfoChW = getCharWidth(chIdx);
  +            hideIdx     = chIdx+1;
  +        } else {
  +            lineInfoChW = 0;
  +            hideIdx     = 0;
  +        }
  +
  +        while (!done()) {
  +          adv=0;
  +          adj=0;
  +
  +          if ((ch == ZERO_WIDTH_SPACE) ||
  +              (ch == ZERO_WIDTH_JOINER))
  +            gv.setGlyphVisible(idx, false);
  +
  +          ch = 0;  // Disable soft-hyphen/ZWS advance adjustment.
  +          nextChar();
  +
  +          if (isPrinting()) break;
  +
  +          lineInfoIdx = idx+1;
  +          lineInfoAdj += adj;
  +        }
  +        // hide trailing spaces if any
  +        for (int i = hideIdx; i<lineInfoIdx; i++)
  +          gv.setGlyphVisible(i, false);
   
  -    public void newLine() {
  -        adv=0;
  -        adj=0;
           maxAscent   = -Float.MAX_VALUE;
           maxDescent  = -Float.MAX_VALUE;
           maxFontSize = -Float.MAX_VALUE;
   
  -        if ((ch == ZERO_WIDTH_SPACE) ||
  -            (ch == ZERO_WIDTH_JOINER))
  -            gv.setGlyphVisible(idx, false);
  -        ch = 0;  // Disable soft-hyphen/ZWS advance adjustment.
  -        nextChar();
           lineIdx = idx;
  +
  +        return new LineInfo(loc, aci, gv, lineIdx, lineInfoIdx, 
  +                            lineInfoAdj, lineInfoAdv, lineInfoChW, 
  +                            lineWidth, partial);
       }
   
       public boolean isPrinting() {
  @@ -376,8 +443,8 @@
        * the rightmost part of the glyph.
        */
       protected float getCharWidth(int gvIdx) {
  -        Rectangle2D lcBound = gv.getGlyphVisualBounds(chIdx).getBounds2D();
  -        Point2D     lcLoc   = gv.getGlyphPosition(chIdx);
  +        Rectangle2D lcBound = gv.getGlyphVisualBounds(gvIdx).getBounds2D();
  +        Point2D     lcLoc   = gv.getGlyphPosition(gvIdx);
           return (float)(lcBound.getX()+lcBound.getWidth()- lcLoc.getX());
       }
   }
  
  
  
  1.41      +74 -50    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.40
  retrieving revision 1.41
  diff -u -r1.40 -r1.41
  --- GlyphLayout.java  27 Apr 2002 22:41:57 -0000      1.40
  +++ GlyphLayout.java  30 Apr 2002 19:08:48 -0000      1.41
  @@ -47,7 +47,7 @@
    * @see org.apache.batik.gvt.text.TextSpanLayout
    *
    * @author <a href="[EMAIL PROTECTED]>Bill Haneman</a>
  - * @version $Id: GlyphLayout.java,v 1.40 2002/04/27 22:41:57 deweese Exp $
  + * @version $Id: GlyphLayout.java,v 1.41 2002/04/30 19:08:48 deweese Exp $
    */
   public class GlyphLayout implements TextSpanLayout {
   
  @@ -245,16 +245,17 @@
        * (e.g. if the aci has multiple X or Y values).
        */
       public void setOffset(Point2D offset) {
  -
  +        // System.out.println("SetOffset: " + offset + " - " + this.offset);
           if ((offset.getX() != this.offset.getX()) ||
               (offset.getY() != this.offset.getY())) {
  -            if (layoutApplied) {
  +            if ((layoutApplied)||(spacingApplied)) {
                   // Already layed out need to shift glyph positions to
                   // account for new offset.
                   float dx = (float)(offset.getX()-this.offset.getX());
                   float dy = (float)(offset.getY()-this.offset.getY());
                   int numGlyphs = gv.getNumGlyphs();
   
  +                // System.out.println("DXY: [" + dx +","+dy+"]");
                   float [] gp = gv.getGlyphPositions(0, numGlyphs+1, null);
                   for (int i=0; i<=numGlyphs; i++) {
                       gv.setGlyphPosition(i, new Point2D.Float(gp[2*i]+dx,
  @@ -358,7 +359,7 @@
        * of glyph layout.
        */
       public Point2D getAdvance2D() {
  -        syncLayout();
  +        adjustTextSpacing();
           return advance;
       }
   
  @@ -488,7 +489,9 @@
               char ch = aci.setIndex(currentChar);
               int glyphCharIndex = charMap[currentChar-start];
               if ((glyphCharIndex >= beginCharIndex) &&
  -                (glyphCharIndex <= endCharIndex)) {
  +                (glyphCharIndex <= endCharIndex) &&
  +                gv.isGlyphVisible(i)) {
  +                    
                   Shape gbounds = gv.getGlyphLogicalBounds(i);
                   if (gbounds != null) {
                       // We got something...
  @@ -1009,10 +1012,10 @@
           Float x=null, y=null, dx=null, dy=null, rotation=null;
           Object baseline=null;
   
  -        float init_x_pos = (float) offset.getX();
  -        float init_y_pos = (float) offset.getY();
  -        float curr_x_pos = init_x_pos;
  -        float curr_y_pos = init_y_pos;
  +        float shift_x_pos = 0;
  +        float shift_y_pos = 0;
  +        float curr_x_pos = (float)offset.getX();
  +        float curr_y_pos = (float)offset.getY();
   
           while (i < numGlyphs) {
               //System.out.println("limit: " + runLimit + ", " + aciIndex);
  @@ -1093,16 +1096,18 @@
                   }
   
                   if ((x != null) && !x.isNaN()) {
  -                    if (i != 0)  /// First x is factored into offset...
  -                        curr_x_pos = x.floatValue();
  +                    if (i == 0)  
  +                        shift_x_pos = (float)(x.floatValue()-offset.getX());
  +                    curr_x_pos = x.floatValue()-shift_x_pos;
                   } 
                   if (dx != null && !dx.isNaN()) {
                       curr_x_pos += dx.floatValue();
                   }
   
                   if ((y != null) && !y.isNaN()) {
  -                    if (i != 0)
  -                        curr_y_pos = y.floatValue();
  +                    if (i == 0)  
  +                        shift_y_pos = (float)(y.floatValue()-offset.getY());
  +                    curr_y_pos = y.floatValue()-shift_y_pos;
                   } 
                   if (dy != null && !dy.isNaN()) {
                       curr_y_pos += dy.floatValue();
  @@ -1208,9 +1213,8 @@
           // Update last glyph pos
           gv.setGlyphPosition(i, new Point2D.Float(curr_x_pos,curr_y_pos));
   
  -        offset  = new Point2D.Float(init_x_pos, init_y_pos);
  -        advance = new Point2D.Float(curr_x_pos - init_x_pos, 
  -                                    curr_y_pos - init_y_pos);
  +        advance = new Point2D.Float((float)(curr_x_pos - offset.getX()), 
  +                                    (float)(curr_y_pos - offset.getY()));
   
           layoutApplied  = true;
           spacingApplied = false;
  @@ -1925,9 +1929,6 @@
                       if (cRect == null) break;
                   }
               }
  -            aci.first();
  -            MarginInfo mi = (MarginInfo)aci.getAttribute(FLOW_PARAGRAPH);
  -            justification = mi.getJustification();
   
               List gvl = new LinkedList();
               List layouts = (List)clIter.next();
  @@ -1942,6 +1943,13 @@
   
               // System.out.println("Glyphs: " + numGlyphs);
   
  +            aci.first();
  +            MarginInfo mi = (MarginInfo)aci.getAttribute(FLOW_PARAGRAPH);
  +            if (mi == null) {
  +              continue;
  +            }
  +            justification = mi.getJustification();
  +
               if (cRect == null) {
                   for(int idx=0; idx <numGlyphs; idx++) 
                       gv.setGlyphVisible(idx, false);
  @@ -1967,10 +1975,12 @@
               }
               prevBotMargin = mi.getBottomMargin();
   
  -            x0    = (float)cRect.getX() + mi.getLeftMargin();
  +            float leftMargin = mi.getFirstLineLeftMargin();
  +            float rightMargin = mi.getFirstLineRightMargin();
  +
  +            x0    = (float)cRect.getX() + leftMargin;
               y0    = (float)cRect.getY();
  -            width = (float)(cRect.getWidth() - 
  -                            (mi.getLeftMargin()+mi.getRightMargin()));
  +            width = (float)(cRect.getWidth() - (leftMargin+rightMargin));
               height = (float)cRect.getHeight();
               
               List lineInfos = new LinkedList();
  @@ -1978,6 +1988,16 @@
               float prevDesc = 0.0f;
               GlyphIterator gi = new GlyphIterator(aci, gv);
               GlyphIterator breakGI  = null, newBreakGI = null;
  +
  +            if (!gi.done() && !gi.isPrinting()) {
  +              // This will place any preceeding whitespace on an imaginary
  +              // line that preceeds the real first line of the paragraph.
  +              lineInfos.add(gi.newLine
  +                            (new Point2D.Float(x0, y0+dy), 
  +                             width, true));
  +            }
  +
  +
               GlyphIterator lineGI   =  gi.copy();
               boolean firstLine = true;
               while (!gi.done()) {
  @@ -1995,11 +2015,10 @@
                           }
   
                           cRect = (Rectangle2D)flowRectsIter.next();
  -                        x0    = (float) cRect.getX() + mi.getLeftMargin();
  +                        x0    = (float) cRect.getX() + leftMargin;
                           y0    = (float) cRect.getY();
                           width = (float)(cRect.getWidth() - 
  -                                        (mi.getLeftMargin()+
  -                                         mi.getRightMargin()));
  +                                        (leftMargin+rightMargin));
                           height = (float)cRect.getHeight();
   
                           // New rect so no previous row to consider...
  @@ -2024,13 +2043,13 @@
                       if (doBreak)
                           nextLineMult -= 1;
                       nextLineMult += lnBreaks;
  -                    partial = true;
                       doBreak = true;
  +                    partial = true;
                   }
   
                   if (!doBreak) {
                       // System.out.println("No Brk Adv: " + gi.getAdv());
  -                    // We don't need to break the line because of this char
  +                    // We don't need to break the line because of this glyph
                       // So we just check if we need to update our break loc.
                       if ((gi.isBreakChar()) ||
                           (breakGI == null)  ||
  @@ -2055,7 +2074,7 @@
                   // System.out.println("   Brk Adv: " + gi.getAdv());
   
                   // We will now attempt to break the line just
  -                // after the breakGI.
  +                // after 'gi'.
   
                   // Note we are trying to figure out where the current
                   // line is going to be placed (not the next line).  We
  @@ -2098,10 +2117,10 @@
   
                       // Get info for new flow rect.
                       cRect = (Rectangle2D)flowRectsIter.next();
  -                    x0    = (float) cRect.getX() + mi.getLeftMargin();
  +                    x0    = (float) cRect.getX() + leftMargin;
                       y0    = (float) cRect.getY();
                       width = (float)(cRect.getWidth() - 
  -                                    (mi.getLeftMargin()+mi.getRightMargin()));
  +                                    (leftMargin+rightMargin));
                       height = (float)cRect.getHeight();
   
                       // New rect so no previous row to consider...
  @@ -2118,14 +2137,18 @@
   
                   prevDesc = newDesc + (nextLineMult-1)*lineBoxHeight;
                   nextLineMult = 0f;
  +                lineInfos.add(gi.newLine
  +                              (new Point2D.Float(x0, y0+dy), width, partial));
   
  -                
                   // System.out.println("Fit: " + dy);
  -                lineInfos.add(gi.getLineInfo
  -                              (new Point2D.Float(x0, y0+dy),
  -                               width,
  -                               partial));
  -                gi.newLine();
  +                x0    -= leftMargin;
  +                width += leftMargin+rightMargin;
  +
  +                leftMargin  = mi.getLeftMargin();
  +                rightMargin = mi.getRightMargin();
  +                x0    += leftMargin;
  +                width -= leftMargin+rightMargin;
  +
                   firstLine = false;
                   // The line fits in the current flow rectangle.
                   lineGI  = gi.copy(lineGI);
  @@ -2137,7 +2160,7 @@
               while(idx <numGlyphs) 
                   gv.setGlyphVisible(idx++, false);
   
  -            layoutChunk(aci, gv, justification, lineInfos);
  +            layoutChunk(aci, gv, gi.getOrigin(), justification, lineInfos);
   
               if (mi.isFlowRegionBreak()) {
                   // Move to next flow region..
  @@ -2152,17 +2175,18 @@
       }
   
       public static void layoutChunk(AttributedCharacterIterator aci,
  -                                   GVTGlyphVector gv, int justification,
  +                                   GVTGlyphVector gv, Point2D origin,
  +                                   int justification,
                                      List lineInfos) {
           Iterator lInfoIter = lineInfos.iterator();
           int numGlyphs      = gv.getNumGlyphs();
           float [] gp        = gv.getGlyphPositions(0, numGlyphs+1, null);
  -        Point2D.Float lineLoc = null;
  -        float         lineAdv = 0;
  -        float         lineAdj = 0;
  +        Point2D.Float lineLoc  = null;
  +        float         lineAdv  = 0;
  +        float         lineVAdv = 0;
   
  -        float xOrig=gp[0];
  -        float yOrig=gp[1];
  +        float xOrig=(float)origin.getX();
  +        float yOrig=(float)origin.getY();
   
           float xScale=1;
           float xAdj=0;
  @@ -2179,7 +2203,7 @@
                   // Always comes through here on first char...
   
                   // Update offset for new line based on last line length
  -                xOrig += lineAdj;
  +                xOrig += lineAdv;
   
                   // Get new values for everything...
                   if (!lInfoIter.hasNext())
  @@ -2188,7 +2212,7 @@
                   lineEnd   = li.getEndIdx();
                   lineLoc   = li.getLocation();
                   lineAdv   = li.getAdvance();
  -                lineAdj   = li.getOffset();
  +                lineVAdv  = li.getVisualAdvance();
                   charW     = li.getLastCharWidth();
                   lineWidth = li.getLineWidth();
                   partial   = li.isPartialLine();
  @@ -2198,13 +2222,13 @@
                   // Recalc justification info.
                   switch (justification) {
                   case 0: default: break;                  // Left
  -                case 1: xAdj = (lineWidth-lineAdv)/2; break; // Center
  -                case 2: xAdj =  lineWidth-lineAdv;    break; // Right
  +                case 1: xAdj = (lineWidth-lineVAdv)/2; break; // Center
  +                case 2: xAdj =  lineWidth-lineVAdv;    break; // Right
                   case 3:                                  // Full
                       if ((!partial) && (lineEnd != i+1)) {
                           // More than one char on line...
                           // Scale char spacing to fill line.
  -                        xScale = (lineWidth-charW)/(lineAdv-charW);
  +                        xScale = (lineWidth-charW)/(lineVAdv-charW);
                       }
                       break;
                   }
  @@ -2217,8 +2241,8 @@
           float x = xOrig;
           float y = yOrig;
           if (lineLoc != null) {
  -            x = lineLoc.x + (gp[2*i]  -xOrig)*xScale+xAdj;
  -            y = lineLoc.y + (gp[2*i+1]-yOrig);
  +          x = lineLoc.x + (gp[2*i]  -xOrig)*xScale+xAdj;
  +          y = lineLoc.y + (gp[2*i+1]-yOrig);
           }
           gv.setGlyphPosition(i, new Point2D.Float(x, y));
       }
  
  
  
  1.2       +18 -10    xml-batik/sources/org/apache/batik/gvt/text/LineInfo.java
  
  Index: LineInfo.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/LineInfo.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LineInfo.java     29 Mar 2002 20:00:55 -0000      1.1
  +++ LineInfo.java     30 Apr 2002 19:08:48 -0000      1.2
  @@ -12,46 +12,54 @@
   import java.text.AttributedCharacterIterator;
   import org.apache.batik.gvt.font.GVTGlyphVector;
   
  +/**
  + * This class encapsulates the layout information about a single line
  + * in a multi-line flow.
  + */
   public class LineInfo {
  +
  +    Point2D.Float               loc;
       AttributedCharacterIterator aci;
       GVTGlyphVector              gv;
       int                         startIdx;
       int                         endIdx;
  -    Point2D.Float               loc;
       float                       advance;
  -    float                       offset;
  +    float                       visualAdvance;
       float                       lastCharWidth;
       float                       lineWidth;
       boolean                     partial;
   
  -    public LineInfo(AttributedCharacterIterator aci,
  +    /**
  +     * 
  +     */
  +    public LineInfo(Point2D.Float loc,
  +                    AttributedCharacterIterator aci,
                       GVTGlyphVector gv,
                       int startIdx, int endIdx,
  -                    Point2D.Float loc,
                       float advance,
  -                    float offset,
  +                    float visualAdvance,
                       float lastCharWidth,
                       float lineWidth,
                       boolean partial) {
  +        this.loc           = loc;
           this.aci           = aci;
           this.gv            = gv;
           this.startIdx      = startIdx;
           this.endIdx        = endIdx;
  -        this.loc           = loc;
           this.advance       = advance;
  -        this.offset        = offset;
  +        this.visualAdvance = visualAdvance;
           this.lastCharWidth = lastCharWidth;
           this.lineWidth     = lineWidth;
           this.partial       = partial;
       }
  -                        
  +
  +    public Point2D.Float  getLocation()         { return loc; }
       public AttributedCharacterIterator getACI() { return aci; }
       public GVTGlyphVector getGlyphVector()      { return gv; }
       public int            getStartIdx()         { return startIdx; }
       public int            getEndIdx()           { return endIdx; }
  -    public Point2D.Float  getLocation()         { return loc; }
       public float          getAdvance()          { return advance; }
  -    public float          getOffset()           { return offset; }
  +    public float          getVisualAdvance()    { return visualAdvance; }
       public float          getLastCharWidth()    { return lastCharWidth; }
       public float          getLineWidth()        { return lineWidth; }
       public boolean        isPartialLine()       { return partial; }
  
  
  
  1.3       +23 -6     xml-batik/sources/org/apache/batik/gvt/text/MarginInfo.java
  
  Index: MarginInfo.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/MarginInfo.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- MarginInfo.java   12 Apr 2002 14:36:48 -0000      1.2
  +++ MarginInfo.java   30 Apr 2002 19:08:48 -0000      1.3
  @@ -18,22 +18,33 @@
       protected float   right;
       protected float   bottom;
       protected float   left;
  +
  +    protected float   firstLineLeft;
  +    protected float   firstLineRight;
  +
       protected int     justification;
       protected boolean flowRegionBreak;
   
   
       public MarginInfo(float top, float right, float bottom, float left,
  +                      float firstLineLeft, float firstLineRight,
                         int justification, boolean flowRegionBreak) {
           this.top    = top;
           this.right  = right;
           this.bottom = bottom;
           this.left   = left;
  +
  +        this.firstLineLeft = firstLineLeft;
  +        this.firstLineRight = firstLineRight;
  +
           this.justification = justification;
           this.flowRegionBreak = flowRegionBreak;
       }
   
       public MarginInfo(float margin, int justification) {
           setMargin(margin);
  +        this.justification = justification;
  +        this.flowRegionBreak = false;
       }
   
       public void setMargin(float margin) {
  @@ -41,11 +52,17 @@
           this.right  = margin;
           this.bottom = margin;
           this.left   = margin;
  +        this.firstLineLeft  = margin;
  +        this.firstLineRight = margin;
       }
  -    public float   getTopMargin()      { return top; }
  -    public float   getRightMargin()    { return right; }
  -    public float   getBottomMargin()   { return bottom; }
  -    public float   getLeftMargin()     { return left; }
  -    public int     getJustification()  { return justification; }
  -    public boolean isFlowRegionBreak() { return flowRegionBreak; }
  +    public float   getTopMargin()            { return top; }
  +    public float   getRightMargin()          { return right; }
  +    public float   getBottomMargin()         { return bottom; }
  +    public float   getLeftMargin()           { return left; }
  +
  +    public float   getFirstLineLeftMargin()  { return firstLineLeft; }
  +    public float   getFirstLineRightMargin() { return firstLineLeft; }
  +
  +    public int     getJustification()        { return justification; }
  +    public boolean isFlowRegionBreak()       { return flowRegionBreak; }
   }
  
  
  
  1.67      +22 -6     
xml-batik/test-resources/org/apache/batik/test/samplesRendering.xml
  
  Index: samplesRendering.xml
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/test-resources/org/apache/batik/test/samplesRendering.xml,v
  retrieving revision 1.66
  retrieving revision 1.67
  diff -u -r1.66 -r1.67
  --- samplesRendering.xml      29 Apr 2002 13:20:20 -0000      1.66
  +++ samplesRendering.xml      30 Apr 2002 19:08:48 -0000      1.67
  @@ -8,7 +8,7 @@
   
   <!-- ========================================================================= -->
   <!-- @author [EMAIL PROTECTED]                                         -->
  -<!-- @version $Id: samplesRendering.xml,v 1.66 2002/04/29 13:20:20 tkormann Exp $ 
-->
  +<!-- @version $Id: samplesRendering.xml,v 1.67 2002/04/30 19:08:48 deweese Exp $ -->
   <!-- ========================================================================= -->
   <testSuite id="samplesRendering" name="samples and samples/test Rendering" 
class="org.apache.batik.test.svg.SamplesRenderingTest">
   
  @@ -43,17 +43,32 @@
           <test id="samples/textRotateShadows.svg" />
       </testGroup>
   
  -    <!-- ======================================================================= -->
  -    <!-- Samples extensions files                                                -->
  -    <!-- ======================================================================= -->
  +    <!-- ================================================================== -->
  +    <!-- Samples extensions files                                           -->
  +    <!-- ================================================================== -->
       <testGroup id="extensions" name="extensions rendering">
  +        <test id="samples/extensions/colorSwitch.svg" >
  +            <property name="Validating" class="java.lang.Boolean" value="false" />
  +     </test>
  +        <test id="samples/extensions/histogramNormalization.svg" >
  +            <property name="Validating" class="java.lang.Boolean" value="false" />
  +     </test>
  +        <test id="samples/extensions/flowText.svg" >
  +            <property name="Validating" class="java.lang.Boolean" value="false" />
  +     </test>
  +        <test id="samples/extensions/multi.svg" >
  +            <property name="Validating" class="java.lang.Boolean" value="false" />
  +     </test>
           <test id="samples/extensions/regularPolygon.svg" >
               <property name="Validating" class="java.lang.Boolean" value="false" />
        </test>
  -        <test id="samples/extensions/star.svg" >
  +        <test id="samples/extensions/solidColor.svg" >
               <property name="Validating" class="java.lang.Boolean" value="false" />
        </test>
  -        <test id="samples/extensions/histogramNormalization.svg" >
  +        <test id="samples/extensions/solidColor2.svg" >
  +            <property name="Validating" class="java.lang.Boolean" value="false" />
  +     </test>
  +        <test id="samples/extensions/star.svg" >
               <property name="Validating" class="java.lang.Boolean" value="false" />
        </test>
       </testGroup>
  @@ -244,6 +259,7 @@
           <test id="samples/tests/spec/text/textFeatures.svg" />
           <test id="samples/tests/spec/text/textLayout.svg" />
           <test id="samples/tests/spec/text/textLayout2.svg" />
  +        <test id="samples/tests/spec/text/textLength.svg" />
           <test id="samples/tests/spec/text/textOnPath.svg" />
           <test id="samples/tests/spec/text/textOnPathSpaces.svg" />
           <test id="samples/tests/spec/text/textPCDATA.svg" />
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to