pietsch     2003/02/02 13:17:41

  Modified:    src/org/apache/fop/fo Tag: fop-0_20_2-maintain FOText.java
               src/org/apache/fop/fo/flow Tag: fop-0_20_2-maintain
                        Leader.java
               src/org/apache/fop/layout Tag: fop-0_20_2-maintain
                        BlockArea.java LineArea.java
  Log:
  Fixed leader generation to be more conformant with common expectations.
  Everything assuming leaders automatically expand as much as possible
  is broken now, leaders expand ONLY due to text justification.
  Expanding multiple leaders on a line is simplistic.
  Fixed leader-alignment="reference" to some extend. Leaders may be
  still misaligned if text justification causes spaces to expand, i.e.
  slack space was not taken completely by leaders.
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.24.2.6  +1 -2      xml-fop/src/org/apache/fop/fo/FOText.java
  
  Index: FOText.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fo/FOText.java,v
  retrieving revision 1.24.2.5
  retrieving revision 1.24.2.6
  diff -u -r1.24.2.5 -r1.24.2.6
  --- FOText.java       22 Nov 2002 15:10:44 -0000      1.24.2.5
  +++ FOText.java       2 Feb 2003 21:17:40 -0000       1.24.2.6
  @@ -230,7 +230,6 @@
           ba.setupLinkSet(ls);
   
           start = la.addText(data, start, end, ls, textState);
  -        // this.hasLines = true;
   
           while ( start != -1) {
               la = ba.createNextLineArea();
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.13.2.5  +23 -12    xml-fop/src/org/apache/fop/fo/flow/Leader.java
  
  Index: Leader.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/fo/flow/Leader.java,v
  retrieving revision 1.13.2.4
  retrieving revision 1.13.2.5
  diff -u -r1.13.2.4 -r1.13.2.5
  --- Leader.java       22 Nov 2002 15:10:46 -0000      1.13.2.4
  +++ Leader.java       2 Feb 2003 21:17:41 -0000       1.13.2.5
  @@ -108,17 +108,29 @@
           // determines the pattern of leader; allowed values: space, rule,dots, 
use-content
           int leaderPattern = this.properties.get("leader-pattern").getEnum();
           // length of the leader
  -        int leaderLengthOptimum =
  -            this.properties.get("leader-length.optimum").getLength().mvalue();
  -        int leaderLengthMinimum =
  -            this.properties.get("leader-length.minimum").getLength().mvalue();
  -        Length maxlength = this.properties.get("leader-length.maximum").getLength();
  +        Length length = this.properties.get("leader-length.minimum").getLength();
  +        int leaderLengthMinimum;
  +        if (length instanceof PercentLength) {
  +            leaderLengthMinimum = (int)(((PercentLength)length).value()
  +                                        * area.getAllocationWidth());
  +        } else {
  +            leaderLengthMinimum = length.mvalue();
  +        }
  +        length = this.properties.get("leader-length.optimum").getLength();
  +        int leaderLengthOptimum;
  +        if (length instanceof PercentLength) {
  +            leaderLengthOptimum = (int)(((PercentLength)length).value()
  +                                      * area.getAllocationWidth());
  +        } else {
  +            leaderLengthOptimum = length.mvalue();
  +        }
  +        length = this.properties.get("leader-length.maximum").getLength();
           int leaderLengthMaximum;
  -        if(maxlength instanceof PercentLength) {
  -            leaderLengthMaximum = (int)(((PercentLength)maxlength).value()
  +        if (length instanceof PercentLength) {
  +            leaderLengthMaximum = (int)(((PercentLength)length).value()
                                         * area.getAllocationWidth());
           } else {
  -            leaderLengthMaximum = maxlength.mvalue();
  +            leaderLengthMaximum = length.mvalue();
           }
           // the following properties only apply for leader-pattern = "rule"
           int ruleThickness =
  @@ -177,7 +189,7 @@
           // in the xsl:fo spec: "User agents may choose to use the value of 
'leader-length.optimum'
           // to determine where to break the line" (7.20.4)
           // if leader is longer then create a new LineArea and put leader there
  -        if (leaderLengthOptimum <= (la.getRemainingWidth())) {
  +        if (leaderLengthOptimum <= la.getRemainingWidth()) {
               la.addLeader(leaderPattern, leaderLengthMinimum,
                            leaderLengthOptimum, leaderLengthMaximum, ruleStyle,
                            ruleThickness, leaderPatternWidth, leaderAlignment);
  @@ -200,12 +212,11 @@
               } else {
                   log.error("Leader doesn't fit into line, it will be clipped to 
fit.");
                   la.addLeader(leaderPattern, la.getRemainingWidth(),
  -                             leaderLengthOptimum, leaderLengthMaximum,
  +                             la.getRemainingWidth(), la.getRemainingWidth(),
                                ruleStyle, ruleThickness, leaderPatternWidth,
                                leaderAlignment);
               }
           }
  -        // this.hasLines = true;
           return 1;
       }
   
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.31.2.3  +15 -17    xml-fop/src/org/apache/fop/layout/Attic/BlockArea.java
  
  Index: BlockArea.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layout/Attic/BlockArea.java,v
  retrieving revision 1.31.2.2
  retrieving revision 1.31.2.3
  diff -u -r1.31.2.2 -r1.31.2.3
  --- BlockArea.java    19 Nov 2002 01:04:08 -0000      1.31.2.2
  +++ BlockArea.java    2 Feb 2003 21:17:41 -0000       1.31.2.3
  @@ -51,9 +51,6 @@
       protected LineArea currentLineArea;
       protected LinkSet currentLinkSet;
   
  -    /* have any line areas been used? */
  -    protected boolean hasLines = false;
  -
       /* hyphenation */
       protected HyphenationProps hyphProps;
   
  @@ -114,18 +111,23 @@
       /**
        * Get the current line area in this block area.
        * This is used to get the current line area for adding
  -     * inline objects to.
  +     * inline objects.
        * This will return null if there is not enough room left
        * in the block area to accomodate the line area.
        *
  -     * @return the line area to be used to add inlie objects
  +     * @return the line area to be used to add inline objects
        */
       public LineArea getCurrentLineArea() {
           if (currentHeight + lineHeight > maxHeight) {
               return null;
           }
  -        this.currentLineArea.changeHyphenation(hyphProps);
  -        this.hasLines = true;
  +        if (this.currentLineArea==null ) {
  +            this.currentLineArea = new LineArea(fontState, lineHeight,
  +                                                halfLeading, allocationWidth,
  +                                                startIndent + textIndent,
  +                                                endIndent, null);
  +            this.currentLineArea.changeHyphenation(hyphProps);
  +        }
           return this.currentLineArea;
       }
   
  @@ -140,18 +142,18 @@
        * @return the new current line area, which will be empty.
        */
       public LineArea createNextLineArea() {
  -        if (this.hasLines) {
  +        if (this.currentLineArea!=null) {
               this.currentLineArea.align(this.align);
               this.addLineArea(this.currentLineArea);
           }
  +        if (currentHeight + lineHeight > maxHeight) {
  +            return null;
  +        }
           this.currentLineArea = new LineArea(fontState, lineHeight,
                                               halfLeading, allocationWidth,
                                               startIndent, endIndent,
                                               currentLineArea);
           this.currentLineArea.changeHyphenation(hyphProps);
  -        if (currentHeight + lineHeight > maxHeight) {
  -            return null;
  -        }
           return this.currentLineArea;
       }
   
  @@ -168,7 +170,7 @@
        * add (if any) the current line area.
        */
       public void end() {
  -        if (this.hasLines) {
  +        if (this.currentLineArea!=null) {
               this.currentLineArea.addPending();
               this.currentLineArea.align(this.alignLastLine);
               this.addLineArea(this.currentLineArea);
  @@ -176,10 +178,6 @@
       }
   
       public void start() {
  -        currentLineArea = new LineArea(fontState, lineHeight, halfLeading,
  -                                       allocationWidth,
  -                                       startIndent + textIndent, endIndent,
  -                                       null);
       }
   
       public int getEndIndent() {
  
  
  
  1.53.2.13 +311 -200  xml-fop/src/org/apache/fop/layout/Attic/LineArea.java
  
  Index: LineArea.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layout/Attic/LineArea.java,v
  retrieving revision 1.53.2.12
  retrieving revision 1.53.2.13
  diff -u -r1.53.2.12 -r1.53.2.13
  --- LineArea.java     11 Jan 2003 18:43:04 -0000      1.53.2.12
  +++ LineArea.java     2 Feb 2003 21:17:41 -0000       1.53.2.13
  @@ -100,6 +100,172 @@
       protected boolean prevOlState = false;
       protected boolean prevLTState = false;
   
  +    public class Leader {
  +        int leaderPattern;
  +        int leaderLengthMinimum;
  +        int leaderLengthOptimum;
  +        int leaderLengthMaximum;
  +        int ruleStyle;
  +        int ruleThickness;
  +        int leaderPatternWidth;
  +        int leaderAlignment;
  +        FontState fontState;
  +        float red;
  +        float green;
  +        float blue;
  +        int placementOffset;
  +        int position;
  +
  +        Leader(int leaderPattern, int leaderLengthMinimum,
  +               int leaderLengthOptimum, int leaderLengthMaximum,
  +               int ruleStyle, int ruleThickness,
  +               int leaderPatternWidth, int leaderAlignment,
  +               FontState fontState,
  +               float red, float green, float blue,
  +               int placementOffset,
  +               int position) {
  +            this.leaderPattern=leaderPattern;
  +            this.leaderLengthMinimum=leaderLengthMinimum;
  +            this.leaderLengthOptimum=leaderLengthOptimum;
  +            this.leaderLengthMaximum=leaderLengthMaximum;
  +            this.ruleStyle=ruleStyle;
  +            this.ruleThickness=ruleThickness;
  +            this.leaderPatternWidth=leaderPatternWidth;
  +            this.leaderAlignment=leaderAlignment;
  +            this.fontState=fontState;
  +            this.red=red;
  +            this.green=green;
  +            this.blue=blue;
  +            this.placementOffset=placementOffset;
  +            this.position = position;
  +        }
  +        void expand(int leaderLength) {
  +            char dot = '.';
  +            int dotWidth =  getCharWidth(dot);
  +            char space = ' ';
  +            int spaceWidth = getCharWidth(space);
  +            int idx=children.indexOf(this);
  +            children.remove(this);
  +            switch (leaderPattern) {
  +            case LeaderPattern.SPACE:
  +                InlineSpace spaceArea = new InlineSpace(leaderLength,false);
  +                children.add(idx,spaceArea);
  +                break;
  +            case LeaderPattern.RULE:
  +                LeaderArea leaderArea = new LeaderArea(this.fontState, this.red, 
this.green,
  +                                                       this.blue, "", leaderLength,
  +                                                       this.leaderPattern,
  +                                                       this.ruleThickness, 
this.ruleStyle);
  +                leaderArea.setYOffset(this.placementOffset);
  +                children.add(idx,leaderArea);
  +                break;
  +            case LeaderPattern.DOTS:
  +                // if the width of a dot is larger than leader-pattern-width
  +                // ignore this property
  +                if (this.leaderPatternWidth < dotWidth) {
  +                    this.leaderPatternWidth = 0;
  +                }
  +                // if value of leader-pattern-width is 'use-font-metrics' (0)
  +                if (this.leaderPatternWidth == 0) {
  +                    if (dotWidth == 0) {
  +                        MessageHandler.errorln("char " + dot
  +                                               + " has width 0. Using width 100 
instead.");
  +                        dotWidth = 100;
  +                    }
  +                    // if leader-alignment is used, calculate space to
  +                    // insert before leader so that all dots will be
  +                    // parallel.
  +                    if (leaderAlignment == LeaderAlignment.REFERENCE_AREA) {
  +                        int nextRepeatedLeaderPatternCycle
  +                            = (int)Math.ceil((double)position/(double)dotWidth);
  +                        int spaceBeforeLeader =
  +                            dotWidth * nextRepeatedLeaderPatternCycle
  +                            - position;
  +                        // appending indent space leader-alignment setting
  +                        // InlineSpace to false, so it is not used in line
  +                        // justification
  +                        System.out.println("align, space="+spaceBeforeLeader);
  +                        if (spaceBeforeLeader > 0) {
  +                            children.add(idx, new InlineSpace(spaceBeforeLeader,
  +                                                              false));
  +                            idx++;
  +                            // shorten leaderLength, otherwise - in
  +                            // case of leaderLength=remaining length -
  +                            // it will cut off the end of leaderlength
  +                            leaderLength -= spaceBeforeLeader;
  +                        }
  +                    }
  +                    int factor = (int)Math.floor(leaderLength / dotWidth);
  +                    char[] leaderChars = new char[factor];
  +                    for (int i = 0; i < factor; i++) {
  +                        leaderChars[i] = dot;
  +                    }
  +                    WordArea leaderPatternArea =
  +                        new WordArea(currentFontState,
  +                                     this.red, this.green, this.blue,
  +                                     new String(leaderChars), leaderLength);
  +                    leaderPatternArea.setYOffset(this.placementOffset);
  +                    children.add(idx, leaderPatternArea);
  +                } else {
  +                    // if leader-alignment is used, calculate space to
  +                    // insert before leader so that all dots will be
  +                    // parallel.
  +                    if (leaderAlignment == LeaderAlignment.REFERENCE_AREA) {
  +                        int nextRepeatedLeaderPatternCycle
  +                            = 
(int)Math.ceil((double)position/(double)leaderPatternWidth);
  +                        int spaceBeforeLeader =
  +                            leaderPatternWidth * nextRepeatedLeaderPatternCycle
  +                            - position;
  +                        // appending indent space leader-alignment setting
  +                        // InlineSpace to false, so it is not used in line
  +                        // justification
  +                        System.out.println("align, space="+spaceBeforeLeader);
  +                        if (spaceBeforeLeader > 0) {
  +                            children.add(idx, new InlineSpace(spaceBeforeLeader,
  +                                                              false));
  +                            idx++;
  +                            // shorten leaderLength, otherwise - in
  +                            // case of leaderLength=remaining length -
  +                            // it will cut off the end of leaderlength
  +                            leaderLength -= spaceBeforeLeader;
  +                        }
  +                    }
  +                    // calculate the space to insert between the dots
  +                    // and create a inline area with this width
  +                    int dotsFactor =
  +                        (int)Math.floor(((double)leaderLength)
  +                                        / ((double)this.leaderPatternWidth));
  +                    // add combination of dot + space to fill leader
  +                    // is there a way to do this in a more effective way?
  +                    for (int i = 0; i < dotsFactor; i++) {
  +                        InlineSpace spaceBetweenDots =
  +                            new InlineSpace(this.leaderPatternWidth - dotWidth, 
false);
  +                        WordArea leaderPatternArea =
  +                            new WordArea(this.fontState,
  +                                         this.red, this.green, this.blue,
  +                                         new String("."), dotWidth);
  +                        leaderPatternArea.setYOffset(this.placementOffset);
  +                        children.add(idx,leaderPatternArea);
  +                        idx++;
  +                        children.add(idx,spaceBetweenDots);
  +                        idx++;
  +                    }
  +                    // append at the end some space to fill up to leader length
  +                    children.add(idx,new InlineSpace(leaderLength
  +                                                     - dotsFactor
  +                                                     * this.leaderPatternWidth));
  +                    idx++;
  +                }
  +                break;
  +                // leader pattern use-content not implemented.
  +            case LeaderPattern.USECONTENT:
  +                MessageHandler.errorln("leader-pattern=\"use-content\" not "
  +                                       + "supported by this version of Fop");
  +                return;
  +            }
  +        }
  +    }
  + 
       public LineArea(FontState fontState, int lineHeight, int halfLeading,
                       int allocationWidth, int startIndent, int endIndent,
                       LineArea prevLineArea) {
  @@ -109,11 +275,11 @@
           this.lineHeight = lineHeight;
           this.nominalFontSize = fontState.getFontSize();
           this.nominalGlyphHeight = fontState.getAscender()
  -                                  - fontState.getDescender();
  +            - fontState.getDescender();
   
           this.placementOffset = fontState.getAscender();
           this.contentRectangleWidth = allocationWidth - startIndent
  -                                     - endIndent;
  +            - endIndent;
           this.fontState = fontState;
   
           this.allocationHeight = this.nominalGlyphHeight;
  @@ -169,9 +335,11 @@
           int width = 3*getCharWidth(' ');
   
   
  -        PageNumberInlineArea pia = new PageNumberInlineArea(currentFontState,
  -                this.red, this.green, this.blue, refid, width);
  -
  +        PageNumberInlineArea pia
  +            = new PageNumberInlineArea(currentFontState,
  +                                       this.red, this.green, this.blue,
  +                                       refid, width);
  +        
           pia.setYOffset(placementOffset);
           pendingAreas.add(pia);
           pendingWidth += width;
  @@ -209,7 +377,7 @@
               /* get the character */
               char c = data[i];
               if (!(isSpace(c) || (c == '\n') || (c == '\r') || (c == '\t')
  -                    || (c == '\u2028'))) {
  +                  || (c == '\u2028'))) {
                   charWidth = getCharWidth(c);
                   isText = true;
                   isMultiByteChar = (c > 127);
  @@ -388,7 +556,7 @@
   
                       wordWidth = charWidth;
                       if ((finalWidth + spaceWidth + wordWidth)
  -                            > this.getContentWidth()) {
  +                        > this.getContentWidth()) {
                           if (overrun)
                               MessageHandler.log("area contents overflows area");
                           if (this.wrapOption == WrapOption.WRAP) {
  @@ -425,13 +593,13 @@
                           for (int j = 0; j < pendingAreas.size(); j++ ) {
                               Box box = (Box)pendingAreas.get(j);
                               if (box instanceof InlineArea) {
  -                              if (ls != null) {
  -                                  Rectangle lr =
  -                                    new Rectangle(finalWidth, 0,
  -                                                  
((InlineArea)box).getContentWidth(),
  -                                                  fontState.getFontSize());
  -                                  ls.addRect(lr, this, (InlineArea)box);
  -                              }
  +                                if (ls != null) {
  +                                    Rectangle lr =
  +                                        new Rectangle(finalWidth, 0,
  +                                                      
((InlineArea)box).getContentWidth(),
  +                                                      fontState.getFontSize());
  +                                    ls.addRect(lr, this, (InlineArea)box);
  +                                }
                               }
                               addChild(box);
                           }
  @@ -468,19 +636,19 @@
                   }
   
                   if ((finalWidth + spaceWidth + pendingWidth + wordWidth)
  -                        > this.getContentWidth()) {
  +                    > this.getContentWidth()) {
   
                       // BREAK MID WORD
   /*                    if (canBreakMidWord()) {
  -                        addSpacedWord(new String(data, wordStart, wordLength - 1),
  -                                      ls,
  -                                      finalWidth + spaceWidth
  -                                      + embeddedLinkStart, spaceWidth,
  -                                                           textState, false);
  -                        finalWidth += wordWidth;
  -                        wordWidth = 0;
  -                        return i;
  -                    }
  +                      addSpacedWord(new String(data, wordStart, wordLength - 1),
  +                      ls,
  +                      finalWidth + spaceWidth
  +                      + embeddedLinkStart, spaceWidth,
  +                      textState, false);
  +                      finalWidth += wordWidth;
  +                      wordWidth = 0;
  +                      return i;
  +                      }
   */
                       if (this.wrapOption == WrapOption.WRAP) {
   
  @@ -574,115 +742,29 @@
                             int leaderLengthOptimum, int leaderLengthMaximum,
                             int ruleStyle, int ruleThickness,
                             int leaderPatternWidth, int leaderAlignment) {
  -        WordArea leaderPatternArea;
  -        int leaderLength = 0;
  -        char dot = '.';
  -        int dotWidth =  getCharWidth(dot);
  -        char space = ' ';
  -        int spaceWidth = getCharWidth(space);
  -
  -        int remainingWidth = this.getRemainingWidth();
  -
  -        /**
  -         * checks whether leaderLenghtOptimum fits into rest of line;
  -         * should never overflow, as it has been checked already in BlockArea
  -         * first check: use remaining width if it smaller than optimum oder maximum
  -         */
  -        if ((remainingWidth <= leaderLengthOptimum)
  -                || (remainingWidth <= leaderLengthMaximum)) {
  -            leaderLength = remainingWidth;
  -        } else if ((remainingWidth > leaderLengthOptimum)
  -                   && (remainingWidth > leaderLengthMaximum)) {
  -            leaderLength = leaderLengthMaximum;
  -        } else if ((leaderLengthOptimum > leaderLengthMaximum)
  -                   && (leaderLengthOptimum < remainingWidth)) {
  -            leaderLength = leaderLengthOptimum;
  -        }
  -
  -        // stop if leader-length is too small
  -        if (leaderLength <= 0) {
  +        System.out.println(
  +            "min="+leaderLengthMinimum+
  +            " opt="+leaderLengthOptimum+
  +            " max="+leaderLengthMaximum+
  +            " th="+ruleThickness+
  +            " al="+leaderAlignment);
  +        if (leaderLengthMinimum>leaderLengthOptimum
  +            || leaderLengthOptimum>leaderLengthMaximum) {
  +            MessageHandler.errorln("leader sizes wrong");
               return;
           }
  -
  -        switch (leaderPattern) {
  -        case LeaderPattern.SPACE:
  -            InlineSpace spaceArea = new InlineSpace(leaderLength);
  -            pendingAreas.add(spaceArea);
  -            break;
  -        case LeaderPattern.RULE:
  -            LeaderArea leaderArea = new LeaderArea(fontState, red, green,
  -                                                   blue, "", leaderLength,
  -                                                   leaderPattern,
  -                                                   ruleThickness, ruleStyle);
  -            leaderArea.setYOffset(placementOffset);
  -            pendingAreas.add(leaderArea);
  -            break;
  -        case LeaderPattern.DOTS:
  -            // if the width of a dot is larger than leader-pattern-width
  -            // ignore this property
  -            if (leaderPatternWidth < dotWidth) {
  -                leaderPatternWidth = 0;
  -            }
  -            // if value of leader-pattern-width is 'use-font-metrics' (0)
  -            if (leaderPatternWidth == 0) {
  -                pendingAreas.add(this.buildSimpleLeader(dot, leaderLength));
  -            } else {
  -                // if leader-alignment is used, calculate space to
  -                // insert before leader so that all dots will be
  -                // parallel.
  -                if (leaderAlignment == LeaderAlignment.REFERENCE_AREA) {
  -                    int spaceBeforeLeader =
  -                        this.getLeaderAlignIndent(leaderLength,
  -                                                  leaderPatternWidth);
  -                    // appending indent space leader-alignment setting
  -                    // InlineSpace to false, so it is not used in line
  -                    // justification
  -                    if (spaceBeforeLeader != 0) {
  -                        pendingAreas.add(new InlineSpace(spaceBeforeLeader, false));
  -                        pendingWidth += spaceBeforeLeader;
  -                        // shorten leaderLength, otherwise - in case of
  -                        // leaderLength=remaining length - it will cut off the end 
of
  -                        // leaderlength
  -                        leaderLength -= spaceBeforeLeader;
  -                    }
  -                }
  -
  -                // calculate the space to insert between the dots and create a
  -                // inline area with this width
  -                InlineSpace spaceBetweenDots =
  -                    new InlineSpace(leaderPatternWidth - dotWidth, false);
  -
  -                leaderPatternArea = new WordArea(currentFontState, this.red,
  -                                                 this.green, this.blue,
  -                                                 new String("."), dotWidth);
  -                leaderPatternArea.setYOffset(placementOffset);
  -                int dotsFactor =
  -                    (int)Math.floor(((double)leaderLength)
  -                                    / ((double)leaderPatternWidth));
  -
  -                // add combination of dot + space to fill leader
  -                // is there a way to do this in a more effective way?
  -                for (int i = 0; i < dotsFactor; i++) {
  -                    pendingAreas.add(leaderPatternArea);
  -                    pendingAreas.add(spaceBetweenDots);
  -                }
  -                // append at the end some space to fill up to leader length
  -                pendingAreas.add(new InlineSpace(leaderLength
  -                                                        - dotsFactor
  -                                                          * leaderPatternWidth));
  -            }
  -            break;
  -        // leader pattern use-content not implemented.
  -        case LeaderPattern.USECONTENT:
  -            MessageHandler.errorln("leader-pattern=\"use-content\" not "
  -                                   + "supported by this version of Fop");
  +        if (leaderLengthOptimum>getRemainingWidth()) {
  +            MessageHandler.errorln("leader width assertion failed");
               return;
           }
  -        // adds leader length to length of pending inline areas
  -        pendingWidth += leaderLength;
  -        // sets prev to TEXT and makes so sure, that also blocks only
  -        // containing leaders are processed
  -        prev = TEXT;
  +        addPending();
  +        children.add(new LineArea.Leader(leaderPattern, leaderLengthMinimum,
  +                                         leaderLengthOptimum, leaderLengthMaximum,
  +                                         ruleStyle, ruleThickness,
  +                                         leaderPatternWidth, leaderAlignment,
  +                                         fontState, red, green, blue,
  +                                         placementOffset, getCurrentXPosition()));
  +        finalWidth += leaderLengthOptimum;
       }
   
       /**
  @@ -715,52 +797,103 @@
        */
       public void align(int type) {
           int padding = 0;
  +
           switch (type) {
           case TextAlign.START:      // left
               padding = this.getContentWidth() - finalWidth;
               endIndent += padding;
  +            for (int i = 0; i < children.size(); i++) {
  +                Object o = children.get(i);
  +                if (o instanceof LineArea.Leader) {
  +                    LineArea.Leader leader = (LineArea.Leader)o;
  +                    leader.expand(leader.leaderLengthOptimum);
  +                }
  +            }
               break;
           case TextAlign.END:        // right
               padding = this.getContentWidth() - finalWidth;
               startIndent += padding;
  +            for (int i = 0; i < children.size(); i++) {
  +                Object o = children.get(i);
  +                if (o instanceof LineArea.Leader) {
  +                    LineArea.Leader leader = (LineArea.Leader)o;
  +                    leader.expand(leader.leaderLengthOptimum);
  +                }
  +            }
               break;
           case TextAlign.CENTER:     // center
               padding = (this.getContentWidth() - finalWidth) / 2;
               startIndent += padding;
               endIndent += padding;
  +            for (int i = 0; i < children.size(); i++) {
  +                Object o = children.get(i);
  +                if (o instanceof LineArea.Leader) {
  +                    LineArea.Leader leader = (LineArea.Leader)o;
  +                    leader.expand(leader.leaderLengthOptimum);
  +                }
  +            }
               break;
           case TextAlign.JUSTIFY:    // justify
               // first pass - count the spaces
  +            int leaderCount = 0;
               int spaceCount = 0;
               for (int i = 0; i < children.size(); i++ ) {
  -                Box b = (Box)children.get(i);
  -                if (b instanceof InlineSpace) {
  -                    InlineSpace space = (InlineSpace)b;
  +                Object o = children.get(i);
  +                if (o instanceof InlineSpace) {
  +                    InlineSpace space = (InlineSpace)o;
                       if (space.getResizeable()) {
                           spaceCount++;
                       }
  +                } else if(o instanceof LineArea.Leader) {
  +                    leaderCount++;
                   }
               }
  -            if (spaceCount > 0) {
  -                padding = (this.getContentWidth() - finalWidth) / spaceCount;
  -            } else {               // no spaces
  -                padding = 0;
  -            }
  -            // second pass - add additional space
  -            spaceCount = 0;
  -            for (int i = 0; i < children.size(); i++) {
  -                Box b = (Box)children.get(i);
  -                if (b instanceof InlineSpace) {
  -                    InlineSpace space = (InlineSpace)b;
  -                    if (space.getResizeable()) {
  -                        space.setSize(space.getSize() + padding);
  -                        spaceCount++;
  +            padding = (this.getContentWidth() - finalWidth);
  +            if (padding>0) {
  +                if (leaderCount>0) {
  +                    int offset=0;
  +                    for (int i = 0; i < children.size(); i++) {
  +                        Object o = children.get(i);
  +                        if (o instanceof LineArea.Leader) {
  +                            LineArea.Leader leader = (LineArea.Leader)o;
  +                            int leaderExpansionMaximum=
  +                                leader.leaderLengthMaximum - 
leader.leaderLengthOptimum;
  +                            if (leaderExpansionMaximum < padding) {
  +                                leader.expand(leader.leaderLengthMaximum);
  +                                padding-=leaderExpansionMaximum;
  +                                offset+=leaderExpansionMaximum;
  +                            } else {
  +                                leader.expand(leader.leaderLengthOptimum + padding);
  +                                padding=0;
  +                                offset+=padding;
  +                            }
  +                        } else if (o instanceof InlineArea) {
  +                            ((InlineArea)o).setXOffset(((InlineArea)o).getXOffset() 
+ offset);
  +                        }
  +                    }
  +                }
  +                if (spaceCount > 0 && padding > 0) {
  +                    padding = padding/spaceCount;
  +                } else {               // no spaces
  +                    padding = 0;
  +                }
  +                spaceCount = 0;
  +                // second pass - add additional space
  +                for (int i = 0; i < children.size(); i++) {
  +                    Object o = children.get(i);
  +                    if (o instanceof InlineSpace) {
  +                        InlineSpace space = (InlineSpace)o;
  +                        if (space.getResizeable()) {
  +                            space.setSize(space.getSize() + padding);
  +                            spaceCount++;
  +                        }
  +                    } else if (o instanceof InlineArea) {
  +                        ((InlineArea)o).setXOffset(((InlineArea)o).getXOffset() + i 
* padding);
                       }
  -                } else if (b instanceof InlineArea) {
  -                    ((InlineArea)b).setXOffset(spaceCount * padding);
                   }
  -
               }
  +        default: 
  +            MessageHandler.errorln("bad align: "+type);
           }
       }
   
  @@ -873,27 +1006,6 @@
       }
   
       /**
  -     * calculates the width of space which has to be inserted before the
  -     * start of the leader, so that all leader characters are aligned.
  -     * is used if property leader-align is set. At the moment only the value
  -     * for leader-align="reference-area" is supported.
  -     *
  -     */
  -    private int getLeaderAlignIndent(int leaderLength,
  -                                     int leaderPatternWidth) {
  -        // calculate position of used space in line area
  -        double position = getCurrentXPosition();
  -        // calculate factor of next leader pattern cycle
  -        double nextRepeatedLeaderPatternCycle = Math.ceil(position
  -                / leaderPatternWidth);
  -        // calculate difference between start of next leader
  -        // pattern cycle and already used space
  -        double difference =
  -            (leaderPatternWidth * nextRepeatedLeaderPatternCycle) - position;
  -        return (int)difference;
  -    }
  -
  -    /**
        * calculates the used space in this line area
        */
       private int getCurrentXPosition() {
  @@ -974,7 +1086,7 @@
           if (getWordWidth(wordToHyphenate) < remainingWidth) {
               inwordPunctuation =
                   characters[wordStart + remainingString.length()
  -                    + wordToHyphenate.length()];
  +                           + wordToHyphenate.length()];
               if (inwordPunctuation == '-' || inwordPunctuation == '/') {
                   preString = new StringBuffer(wordToHyphenate);
                   preString = preString.append(inwordPunctuation);
  @@ -1083,7 +1195,7 @@
           } else {
               // if whitespace-collapse == true, discard character
               if (Character.isSpaceChar(data)
  -                    && whiteSpaceCollapse == WhiteSpaceCollapse.TRUE) {
  +                && whiteSpaceCollapse == WhiteSpaceCollapse.TRUE) {
                   return org.apache.fop.fo.flow.Character.OK;
               }
               // create new InlineArea
  @@ -1135,9 +1247,9 @@
               if (box instanceof InlineArea) {
                   if (ls != null) {
                       Rectangle lr =
  -                      new Rectangle(finalWidth, 0,
  -                                    ((InlineArea)box).getContentWidth(),
  -                                    fontState.getFontSize());
  +                        new Rectangle(finalWidth, 0,
  +                                      ((InlineArea)box).getContentWidth(),
  +                                      fontState.getFontSize());
                       ls.addRect(lr, this, (InlineArea)box);
                   }
               }
  @@ -1152,8 +1264,8 @@
           String word = (wordBuf != null) ? wordBuf.toString() : "";
           int wordWidth = this.getWordWidth(word);
           WordArea hia = new WordArea(currentFontState,
  -                          this.red, this.green, this.blue,
  -                          word, wordWidth);
  +                                    this.red, this.green, this.blue,
  +                                    word, wordWidth);
           hia.setYOffset(placementOffset);
           hia.setUnderlined(textState.getUnderlined());
           prevUlState = textState.getUnderlined();
  @@ -1165,10 +1277,10 @@
           this.addChild(hia);
   
           if (ls != null) {
  -           Rectangle lr = new Rectangle(startw, 0,
  -                                       hia.getContentWidth(),
  -                                       fontState.getFontSize());
  -           ls.addRect(lr, this, hia);
  +            Rectangle lr = new Rectangle(startw, 0,
  +                                         hia.getContentWidth(),
  +                                         fontState.getFontSize());
  +            ls.addRect(lr, this, hia);
           }
           // calculate the space needed
           finalWidth +=  wordWidth;
  @@ -1205,10 +1317,10 @@
       private boolean canBreakMidWord() {
           boolean ret = false;
           if (hyphProps != null && hyphProps.language != null
  -                &&!hyphProps.language.equals("NONE")) {
  +            &&!hyphProps.language.equals("NONE")) {
               String lang = hyphProps.language.toLowerCase();
               if ("zh".equals(lang) || "ja".equals(lang) || "ko".equals(lang)
  -                    || "vi".equals(lang))
  +                || "vi".equals(lang))
                   ret = true;
           }
           return ret;
  @@ -1230,7 +1342,7 @@
           // the mapping returns '#' for unmapped characters in standard fonts
           // what happens for other fonts?
           if (mappedChar != '#') {
  -          // should do something to discover non-proportional fonts
  +            // should do something to discover non-proportional fonts
               return (getEmWidth()*9)/10;
           } else {
               return currentFontState.width(mappedChar);
  @@ -1304,17 +1416,17 @@
        */
       private boolean isSpace(char c) {
           if (c == ' ' || c == '\u2000' ||    // en quad
  -        c == '\u2001' ||                    // em quad
  -        c == '\u2002' ||                    // en space
  -        c == '\u2003' ||                    // em space
  -        c == '\u2004' ||                    // three-per-em space
  -        c == '\u2005' ||                    // four--per-em space
  -        c == '\u2006' ||                    // six-per-em space
  -        c == '\u2007' ||                    // figure space
  -        c == '\u2008' ||                    // punctuation space
  -        c == '\u2009' ||                    // thin space
  -        c == '\u200A' ||                    // hair space
  -        c == '\u200B')                      // zero width space
  +            c == '\u2001' ||                    // em quad
  +            c == '\u2002' ||                    // en space
  +            c == '\u2003' ||                    // em space
  +            c == '\u2004' ||                    // three-per-em space
  +            c == '\u2005' ||                    // four--per-em space
  +            c == '\u2006' ||                    // six-per-em space
  +            c == '\u2007' ||                    // figure space
  +            c == '\u2008' ||                    // punctuation space
  +            c == '\u2009' ||                    // thin space
  +            c == '\u200A' ||                    // hair space
  +            c == '\u200B')                      // zero width space
               return true;
           else
               return false;
  @@ -1327,8 +1439,8 @@
        */
       private boolean isNBSP(char c) {
           if (c == '\u00A0' || c == '\u202F' ||    // narrow no-break space
  -        c == '\u3000' ||                    // ideographic space
  -        c == '\uFEFF') {                    // zero width no-break space
  +            c == '\u3000' ||                    // ideographic space
  +            c == '\uFEFF') {                    // zero width no-break space
               return true;
           } else
               return false;
  @@ -1355,7 +1467,7 @@
               String currentWord = st.nextToken();
   
               if (currentWord.length() == 1
  -                    && (isNBSP(currentWord.charAt(0)))) {
  +                && (isNBSP(currentWord.charAt(0)))) {
                   // Add an InlineSpace
                   int spaceWidth = getCharWidth(currentWord.charAt(0));
                   if (spaceWidth > 0) {
  @@ -1411,5 +1523,4 @@
       }
   
   }
  -
   
  
  
  

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

Reply via email to