klease      02/05/22 13:20:50

  Modified:    src/org/apache/fop/layoutmgr AbstractBPLayoutManager.java
                        BPLayoutManager.java BreakPoss.java
                        BreakPossPosIter.java
                        InlineStackingBPLayoutManager.java
                        LayoutContext.java LineBPLayoutManager.java
                        PositionIterator.java TextBPLayoutManager.java
  Added:       src/org/apache/fop/layoutmgr HyphContext.java
  Log:
  Add support for hyphenation and some space distribution among inline areas
  
  Revision  Changes    Path
  1.3       +7 -14     
xml-fop/src/org/apache/fop/layoutmgr/AbstractBPLayoutManager.java
  
  Index: AbstractBPLayoutManager.java
  ===================================================================
  RCS file: 
/home/cvs/xml-fop/src/org/apache/fop/layoutmgr/AbstractBPLayoutManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- AbstractBPLayoutManager.java      10 May 2002 12:38:15 -0000      1.2
  +++ AbstractBPLayoutManager.java      22 May 2002 20:20:50 -0000      1.3
  @@ -1,5 +1,5 @@
   /*
  - * $Id: AbstractBPLayoutManager.java,v 1.2 2002/05/10 12:38:15 klease Exp $
  + * $Id: AbstractBPLayoutManager.java,v 1.3 2002/05/22 20:20:50 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -134,18 +134,6 @@
       }
   
   
  -//     /**
  -//      * Get the BreakPoss at the start of the next "area".
  -//      * @param lc The LayoutContext for this LayoutManager.
  -//      * @param bpPrevEnd The Position returned by the previous call
  -//      * to getNextBreakPoss, or null if none.
  -//      */
  -//     public BreakPoss getStartBreakPoss(LayoutContext lc,
  -//                                  BreakPoss.Position bpPrevEnd) {
  -//   return null;
  -//     }
  -
  -
       /**
        * Generate and return the next break possibility.
        * Each layout manager must implement this.
  @@ -179,7 +167,12 @@
       }
   
   
  -    public void addAreas(PositionIterator parentIter) {
  +    public void addAreas(PositionIterator parentIter, double dSpaceAdjust) {
  +    }
  +
  +    
  +    public void getWordChars(StringBuffer sbChars,
  +                          BreakPoss.Position bp1, BreakPoss.Position bp2) {
       }
   
       /* ---------------------------------------------------------
  
  
  
  1.3       +5 -6      xml-fop/src/org/apache/fop/layoutmgr/BPLayoutManager.java
  
  Index: BPLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/BPLayoutManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BPLayoutManager.java      10 May 2002 12:38:15 -0000      1.2
  +++ BPLayoutManager.java      22 May 2002 20:20:50 -0000      1.3
  @@ -1,5 +1,5 @@
   /*
  - * $Id: BPLayoutManager.java,v 1.2 2002/05/10 12:38:15 klease Exp $
  + * $Id: BPLayoutManager.java,v 1.3 2002/05/22 20:20:50 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -39,10 +39,6 @@
   
       public BreakPoss getNextBreakPoss(LayoutContext context);
   
  -    /** CURRENTLY NOT USED
  -    public BreakPoss getStartBreakPoss(LayoutContext lc,
  -                                    BreakPoss.Position bpPrevEnd);
  -    **/
   
       /**
        * Return a value indicating whether this LayoutManager has laid out
  @@ -62,10 +58,13 @@
        * by BreakPoss.Position objectw which will be returned by the
        * Iterator.
        */
  -    public void addAreas(PositionIterator posIter) ;
  +    public void addAreas(PositionIterator posIter, double dSpaceAdjust) ;
   
       public void init() ;
   
       public void resetPosition(BreakPoss.Position position);
  +
  +    public void getWordChars(StringBuffer sbChars,
  +                          BreakPoss.Position bp1, BreakPoss.Position bp2);
   
   }
  
  
  
  1.3       +3 -1      xml-fop/src/org/apache/fop/layoutmgr/BreakPoss.java
  
  Index: BreakPoss.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/BreakPoss.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BreakPoss.java    10 May 2002 12:38:15 -0000      1.2
  +++ BreakPoss.java    22 May 2002 20:20:50 -0000      1.3
  @@ -1,5 +1,5 @@
   /*
  - * $Id: BreakPoss.java,v 1.2 2002/05/10 12:38:15 klease Exp $
  + * $Id: BreakPoss.java,v 1.3 2002/05/22 20:20:50 klease Exp $
    * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -40,6 +40,8 @@
       // Set this flag if all fo:character generated Areas would
       // suppressed at the end or beginning of a line
       public static final int ALL_ARE_SUPPRESS_AT_LB =    0x80;
  +    /** This break possibility is a hyphenation */
  +    public static final int HYPHENATED =    0x100;
   
   
       /** The top-level layout manager which generated this BreakPoss. */
  
  
  
  1.3       +5 -1      xml-fop/src/org/apache/fop/layoutmgr/BreakPossPosIter.java
  
  Index: BreakPossPosIter.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/BreakPossPosIter.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BreakPossPosIter.java     10 May 2002 12:38:15 -0000      1.2
  +++ BreakPossPosIter.java     22 May 2002 20:20:50 -0000      1.3
  @@ -1,5 +1,5 @@
   /*
  - * $Id: BreakPossPosIter.java,v 1.2 2002/05/10 12:38:15 klease Exp $
  + * $Id: BreakPossPosIter.java,v 1.3 2002/05/22 20:20:50 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -33,6 +33,10 @@
       public Object next() {
        --m_iterCount;
        return super.next();
  +    }
  +
  +    public BreakPoss getBP() {
  +     return (BreakPoss)peekNext();
       }
   
       protected BPLayoutManager getLM(Object nextObj) {
  
  
  
  1.3       +31 -63    
xml-fop/src/org/apache/fop/layoutmgr/InlineStackingBPLayoutManager.java
  
  Index: InlineStackingBPLayoutManager.java
  ===================================================================
  RCS file: 
/home/cvs/xml-fop/src/org/apache/fop/layoutmgr/InlineStackingBPLayoutManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- InlineStackingBPLayoutManager.java        13 May 2002 06:12:42 -0000      1.2
  +++ InlineStackingBPLayoutManager.java        22 May 2002 20:20:50 -0000      1.3
  @@ -1,5 +1,5 @@
   /*
  - * $Id: InlineStackingBPLayoutManager.java,v 1.2 2002/05/13 06:12:42 klease Exp $
  + * $Id: InlineStackingBPLayoutManager.java,v 1.3 2002/05/22 20:20:50 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -15,6 +15,7 @@
   import org.apache.fop.area.MinOptMax;
   import org.apache.fop.area.inline.InlineArea;
   import org.apache.fop.area.inline.InlineParent;
  +import org.apache.fop.area.inline.Space;
   
   import java.util.Iterator;
   import java.util.ListIterator;
  @@ -92,7 +93,6 @@
   
       protected void initProperties(PropertyManager propMgr) {
        // super.initProperties(propMgr);
  -     System.err.println("InlineStackingBPLayoutManager.initProperties called");
           m_inlineProps = propMgr.getInlineProps();
           m_borderProps = propMgr.getBorderAndPadding();
        // Calculdate border and padding size in BPD
  @@ -140,7 +140,6 @@
        }
        else {
            // Backup to start of first child layout manager
  -         System.err.println("InlineStackingBPLM: resetPosition(null)");
            m_prevBP = null;
            super.resetPosition(prevPos);
        }
  @@ -172,6 +171,7 @@
        return (MinOptMax)m_hmPrevIPD.get(lm);
       }
   
  +
       protected void clearPrevIPD() {
        m_hmPrevIPD.clear();
       }
  @@ -210,8 +210,12 @@
   
            initChildLC(m_childLC, m_prevBP, lc.startsNewArea(), bFirstChildBP,
                        leadingSpace);
  +         if (lc.tryHyphenate()) {
  +             m_childLC.setHyphContext(lc.getHyphContext());
  +         }
   
  -         if (((bp = curLM.getNextBreakPoss(m_childLC)) != null)) {
  +         if (((bp = curLM.getNextBreakPoss(m_childLC)) != null) ||
  +             (lc.tryHyphenate() && !lc.getHyphContext().hasMoreHyphPoints())) {
                break;
            }
            // If LM has no content, should it generate any area? If not,
  @@ -251,26 +255,6 @@
   
       }
   
  -//     protected boolean couldEndLine(BreakPoss bp) {
  -//   if (bp.canBreakAfter()) {
  -//       return true; // no keep, ends on break char
  -//   }
  -//   else if (bp.isSuppressible()) {
  -//       // NOTE: except at end of content for this LM!!
  -//       // Never break after only space chars or any other sequence
  -//       // of areas which would be suppressed at the end of the line.
  -//       return false; 
  -//   }
  -//   else {
  -//       // See if could break before next area
  -//       LayoutContext lc=new LayoutContext();
  -//       BPLayoutManager nextLM = getChildLM();
  -//       return (nextLM == null || 
  -//               nextLM.canBreakBefore(lc));
  -//   }
  -//     }
  -
  -
   
       private BreakPoss makeBreakPoss(BreakPoss bp, LayoutContext lc,
                                   boolean bIsLast) {
  @@ -295,39 +279,9 @@
            myBP.setLeadingSpace(lc.getPendingSpace());
        }
   
  -//   if (lc.startsNewArea()) {
  -//       if (hasLeadingFence(!lc.isFirstArea())) {
  -//           // Space-start before first child area placed
  -//           prevIPD.add(bp.resolveLeadingSpace());
  -//       }
  -//       // Space-start sequence passed to ancestors
  -//       myBP.setLeadingSpace(lc.getPendingSpace());
  -//       m_hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
  -//   }
  -//   else {
  -//       // In case of reset to a previous position, it may already
  -//       // be calculated
  -//       prevIPD = (MinOptMax)m_hmPrevIPD.get(bp.getLayoutManager());
  -//       if (prevIPD == null) {
  -//           // ASSERT(m_prevBP.getLayoutManager() != bp.getLayoutManager());
  -//           /* This is first bp generated by child (in this parent area).
  -//            * Calculate space-start on this area in combination with any
  -//            * pending space-end with previous break.
  -//            * Corresponds to Space between two child areas.
  -//            */
  -//           prevIPD = 
  -//               (MinOptMax)m_hmPrevIPD.get(m_prevBP.getLayoutManager());
  -//           prevIPD = MinOptMax.add(prevIPD,  bp.resolveLeadingSpace());
  -//           prevIPD.add(m_prevBP.getStackingSize());
  -//           m_hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
  -//       }
  -//   }
  +
        // Add size of previous child areas which are finished
        bpDim.add(prevIPD);
  -//         if (bp.isLastArea()) {
  -//       m_childLC.setPendingSpace((SpaceSpecifier)bp.getTrailingSpace().
  -//                                 clone());
  -//         }
   
        SpaceSpecifier trailingSpace = bp.getTrailingSpace();
        if (hasTrailingFence(!bIsLast)) {
  @@ -362,8 +316,6 @@
                // Space-start before first child area placed
                prevIPD.add(bp.resolveLeadingSpace());
            }
  -         // Space-start sequence passed to ancestors
  -         // myBP.setLeadingSpace(lc.getPendingSpace());
            m_hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
        }
        else {
  @@ -377,8 +329,7 @@
                 * pending space-end with previous break.
                 * Corresponds to Space between two child areas.
                 */
  -             prevIPD = 
  -                 (MinOptMax)m_hmPrevIPD.get(prevBP.getLayoutManager());
  +             prevIPD = (MinOptMax)m_hmPrevIPD.get(prevBP.getLayoutManager());
                prevIPD = MinOptMax.add(prevIPD,  bp.resolveLeadingSpace());
                prevIPD.add(prevBP.getStackingSize());
                m_hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
  @@ -387,15 +338,32 @@
        return prevIPD;
       }
   
  +    public void getWordChars(StringBuffer sbChars,
  +                             BreakPoss.Position bp1, BreakPoss.Position bp2) {
  +     WrappedPosition endPos = (WrappedPosition)bp2;
  +     if (bp1 != null) {
  +         WrappedPosition prevPos = (WrappedPosition)bp1;
  +         if (prevPos.m_childLM == endPos.m_childLM) {
  +             bp1 = prevPos.m_childPosition;
  +         }
  +     }
  +     endPos.m_childLM.getWordChars(sbChars, bp1, endPos.m_childPosition);
  +    }
   
       /******
       protected BreakableText getText(BreakPoss prevBP, BreakPoss lastBP) {
       }
       *****/
   
  -    // Generate and add areas to parent area
  -    // Set size etc
  -    public void addAreas(PositionIterator parentIter) {
  +    /**
  +     * Generate and add areas to parent area.
  +     * Set size of each area.
  +     * @param parentIter Iterator over BreakPoss.Position information returned
  +     * by this LayoutManager.
  +     * @param dSpaceAdjust Factor controlling how much extra space to add
  +     * in order to justify the line.
  +     */
  +    public void addAreas(PositionIterator parentIter, double dSpaceAdjust) {
           // Make areas from start to end
           // Update childLM based on bpEnd
           // It might be a previous sibling of the current one!
  @@ -410,7 +378,7 @@
        StackingIter childPosIter = new StackingIter(parentIter);
        BPLayoutManager childLM ;
        while  ((childLM = childPosIter.getNextChildLM())!= null) {
  -         childLM.addAreas(childPosIter);
  +         childLM.addAreas(childPosIter, dSpaceAdjust);
        }
        
        parentLM.addChild(m_inlineArea);
  
  
  
  1.3       +18 -1     xml-fop/src/org/apache/fop/layoutmgr/LayoutContext.java
  
  Index: LayoutContext.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/LayoutContext.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LayoutContext.java        13 May 2002 06:12:42 -0000      1.2
  +++ LayoutContext.java        22 May 2002 20:20:50 -0000      1.3
  @@ -1,5 +1,5 @@
   /*
  - * $Id: LayoutContext.java,v 1.2 2002/05/13 06:12:42 klease Exp $
  + * $Id: LayoutContext.java,v 1.3 2002/05/22 20:20:50 klease Exp $
    * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -34,6 +34,7 @@
        */
       public static final int SUPPRESS_LEADING_SPACE =       0x10;
       public static final int FIRST_AREA =                   0x20;
  +    public static final int TRY_HYPHENATE =                0x40;
   
   
       public int flags;  // Contains some set of flags defined above
  @@ -56,11 +57,15 @@
       /** Current pending space-after or space-end from preceding area */
       SpaceSpecifier m_pendingSpace;
   
  +    /** Current hyphenation context. May be null. */
  +    private HyphContext m_hyphContext=null;
  +
       public LayoutContext(LayoutContext parentLC) {
           this.flags = parentLC.flags;
           this.refIPD = parentLC.refIPD;
           this.m_stackLimit = null; // Don't reference parent MinOptMax!
        this.m_pendingSpace = parentLC.m_pendingSpace; //???
  +     this.m_hyphContext = parentLC.m_hyphContext;
           // Copy other fields as necessary. Use clone???
       }
   
  @@ -118,5 +123,17 @@
   
       public MinOptMax getStackLimit() {
        return m_stackLimit ;
  +    }
  +
  +    public void setHyphContext(HyphContext hyphContext) {
  +     m_hyphContext = hyphContext;
  +    }
  +
  +    public HyphContext getHyphContext() {
  +     return m_hyphContext;
  +    }
  +
  +    public boolean tryHyphenate() {
  +     return ((this.flags & TRY_HYPHENATE) != 0);
       }
   }
  
  
  
  1.5       +138 -58   xml-fop/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java
  
  Index: LineBPLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- LineBPLayoutManager.java  17 May 2002 08:56:03 -0000      1.4
  +++ LineBPLayoutManager.java  22 May 2002 20:20:50 -0000      1.5
  @@ -1,5 +1,5 @@
   /*
  - * $Id: LineBPLayoutManager.java,v 1.4 2002/05/17 08:56:03 keiron Exp $
  + * $Id: LineBPLayoutManager.java,v 1.5 2002/05/22 20:20:50 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -12,6 +12,9 @@
   import org.apache.fop.fo.TextInfo;
   import org.apache.fop.fo.PropertyManager;
   import org.apache.fop.layout.MarginProps;
  +import org.apache.fop.layout.HyphenationProps;
  +import org.apache.fop.layout.hyphenation.Hyphenation;
  +import org.apache.fop.layout.hyphenation.Hyphenator;
   import org.apache.fop.traits.BlockProps;
   import org.apache.fop.area.Area;
   import org.apache.fop.area.LineArea;
  @@ -62,6 +65,7 @@
       private boolean m_bJustify = false; // True if fo:block text-align=JUSTIFY
       private int m_iTextIndent = 0;
       private int m_iIndents = 0;
  +    private HyphenationProps m_hyphProps;
   
       private int lineHeight;
       private int lead;
  @@ -77,13 +81,12 @@
       }
   
       protected void initProperties(PropertyManager propMgr) {
  -     // super.initProperties(propMgr);
  -     System.err.println("LineBPLayoutManager.initProperties called");
           MarginProps marginProps = propMgr.getMarginProps();
           m_iIndents = marginProps.startIndent + marginProps.endIndent;
        BlockProps blockProps = propMgr.getBlockProps();
        m_bJustify = (blockProps.textAlign == TextAlign.JUSTIFY);
        m_iTextIndent = blockProps.firstIndent;
  +     m_hyphProps = propMgr.getHyphenationProps();
       }
       
   
  @@ -120,6 +123,7 @@
        LayoutContext inlineLC = new LayoutContext(context);
   
        clearPrevIPD();
  +     int iPrevLineEnd = m_vecInlineBreaks.size();
   
           while ((curLM = getChildLM()) != null) {
            // INITIALIZE LAYOUT CONTEXT FOR CALL TO CHILD LM
  @@ -129,39 +133,31 @@
                 (((BreakPoss)m_vecInlineBreaks.lastElement()).
                  getLayoutManager() != curLM));
   
  -         initChildLC(inlineLC, bp, (bp==null), bFirstBPforLM,
  +         // Need previous breakpoint! ATTENTION when backing up for hyphenation!
  +         prevBP =  (m_vecInlineBreaks.isEmpty())? null:
  +             (BreakPoss)m_vecInlineBreaks.lastElement();     
  +         initChildLC(inlineLC, prevBP,
  +                     (m_vecInlineBreaks.size()==iPrevLineEnd), bFirstBPforLM,
                        new SpaceSpecifier(true));
   
  -//       if (bp == null) {
  -//           // Start of a new line area
  -//           inlineLC.setFlags(LayoutContext.FIRST_AREA, bFirstBPforLM );
  -//           inlineLC.setPendingSpace(new SpaceSpecifier(true));
  -//       }
  -//       else if (bFirstBPforLM) {
  -//           // Space-after sequence from previous "area"
  -//           inlineLC.setFlags(LayoutContext.FIRST_AREA, true);
  -//           inlineLC.setPendingSpace(bp.getTrailingSpace());
  -//       }
  -//       else {
  -//           inlineLC.setPendingSpace(null);
  -//       }
  -
   
               /* If first BP in this line but line is not first in this
                * LM and previous line end decision was not forced (LINEFEED),
                * then set the SUPPRESS_LEADING_SPACE flag.
                */
            inlineLC.setFlags(LayoutContext.SUPPRESS_LEADING_SPACE,
  -                           (bp == null && !m_vecInlineBreaks.isEmpty() &&
  +                           (prevBP == null && !m_vecInlineBreaks.isEmpty() &&
                               ((BreakPoss)m_vecInlineBreaks.lastElement()).
                               isForcedBreak()==false));
   
            // GET NEXT POSSIBLE BREAK FROM CHILD LM
  -         prevBP = bp;
  +         // prevBP = bp;
               if ((bp = curLM.getNextBreakPoss(inlineLC, null)) != null) {
                // Add any space before and previous content dimension
  -             MinOptMax prevIPD = updatePrevIPD(bp, prevBP, (prevBP==null),
  -                                               inlineLC.isFirstArea());
  +             MinOptMax prevIPD =
  +                 updatePrevIPD(bp, prevBP,
  +                               (m_vecInlineBreaks.size()==iPrevLineEnd),
  +                               inlineLC.isFirstArea());
                MinOptMax bpDim = MinOptMax.add(bp.getStackingSize(), prevIPD);
   
                // check if this bp fits in line
  @@ -175,41 +171,40 @@
                // TODO: stop if linebreak is forced (NEWLINE)
                // PROBLEM: interaction with wrap which can be set
                // at lower levels!
  -             System.err.println("BPdim=" + bpDim.opt);
  +             // System.err.println("BPdim=" + bpDim.opt);
   
                // Check if proposed area would fit in line
                if (bpDim.min > availIPD.max) {
                    // See if we have already found a potential break
  -                 if (vecPossEnd.size() > 0) break;
  +                 //if (vecPossEnd.size() > 0) break;
   
                    // This break position doesn't fit
                    // TODO: If we are in nowrap, we use it as is!
                    if (m_bJustify || m_prevBP == null) {
  -                     // try to find a hyphenation point in the word
  -                     // which spans the queued breaks and the proposed bp
  -                     // Even if not justified, we must try to hyphenate if
  -                     // there is no breakpoint at all up to this point!
  -                     do {
  -                         bp = findHyphenPoss(m_prevBP, bp);
  -                     } while (bp != null &&
  -                              (bp.getStackingSize().min > availIPD.max));
  -                     if (bp == null) {
  -                         // Couldn't find a hyphenation point. The line
  -                         // will be "short".
  +                     // If we are already in a hyphenation loop, then stop.
  +
  +                     if (inlineLC.tryHyphenate()) {
  +                         break;
                        }
  -                     else {
  -                         m_prevBP = bp;
  +                     // Otherwise, prepare to try hyphenation
  +                     if (!bBreakOK) {
  +                         // Make sure we collect the entire word!
  +                         m_vecInlineBreaks.add(bp);
  +                         continue;
                        }
  -                     // Handle pendingIPD if any. The hyphenation point
  -                     // may be within the "pending" content or after it.
  -                        /* Make sure child LM are updated concerning the actual
  -                         * hyphenation BreakPoss for their next call!
  -                         */
  +                     
  +                     inlineLC.setHyphContext(getHyphenContext(m_prevBP, bp));
  +                     if (inlineLC.getHyphContext()==null) break;
  +                     inlineLC.setFlags(LayoutContext.TRY_HYPHENATE, true);
  +                     // Reset to previous acceptable break
  +                     reset();
                    }
                    /* If we are not in justified text, we can end the line at
                     * prevBP.
                     */
  -                 break;
  +                 else {
  +                     break;
  +                 }
                }
                else {
                    // Add the BP to the list whether or not we can break
  @@ -229,7 +224,6 @@
                             * (ie, bpDim.opt closes to availIPD.opt), keeps
                             * and hyphenation.
                             */
  -                         System.err.println("Found potential linebreak");
                            vecPossEnd.add(new BreakCost(bp,
                             Math.abs(availIPD.opt - bpDim.opt )));
                        }
  @@ -246,13 +240,17 @@
                 * up. Just try the next child LM.
                 */
            }
  +         if (inlineLC.tryHyphenate() &&
  +             !inlineLC.getHyphContext().hasMoreHyphPoints()) {
  +             break;
  +         }
        } // end of while on child LM
        if ((curLM = getChildLM())== null) {
            // No more content to layout!
            setFinished(true);
        }
   
  -if(bp == null) return null;
  +     if(bp == null) return null;
   
        // Choose the best break
        if (!bp.isForcedBreak() && vecPossEnd.size()>0) {
  @@ -260,11 +258,7 @@
        }
        // Backup child LM if necessary
        if (bp != m_prevBP) {
  -         // Remove any pending breaks from the vector
  -         while (m_vecInlineBreaks.lastElement()!=m_prevBP) {
  -             m_vecInlineBreaks.remove(m_vecInlineBreaks.size()-1);
  -         }
  -         reset(m_prevBP.getLayoutManager(), m_prevBP.getPosition());
  +         reset();
        }
        // Distribute space in the line
        MinOptMax actual = MinOptMax.add(m_prevBP.getStackingSize(),
  @@ -282,6 +276,14 @@
           return makeLineBreak(m_prevBP, availIPD, actual, bJustify);
       }
   
  +
  +    private void reset() {
  +     while (m_vecInlineBreaks.lastElement()!=m_prevBP) {
  +         m_vecInlineBreaks.remove(m_vecInlineBreaks.size()-1);
  +     }
  +     reset(m_prevBP.getLayoutManager(), m_prevBP.getPosition());
  +    }
  +
       protected boolean couldEndLine(BreakPoss bp) {
        if (bp.canBreakAfter()) {
            return true; // no keep, ends on break char
  @@ -303,6 +305,7 @@
       }
   
   
  +
       private BreakPoss getBestBP(Vector vecPossEnd) {
        if (vecPossEnd.size()==1) {
            return ((BreakCost)vecPossEnd.elementAt(0)).getBP();
  @@ -333,13 +336,62 @@
       
   
   
  -    private BreakPoss findHyphenPoss(BreakPoss prevBP, BreakPoss newBP) {
  +    private HyphContext getHyphenContext(BreakPoss prevBP, BreakPoss newBP) {
        // Get a "word" to hyphenate by getting characters from all
        // pending break poss which are in m_vecInlineBreaks, starting
  -     // with the position just AFTER prevBP.getPosition()
  -     return null;
  +     // with the position just AFTER prevBP.getPosition() 
  +
  +     m_vecInlineBreaks.add(newBP);
  +     ListIterator bpIter = m_vecInlineBreaks.
  +         listIterator(m_vecInlineBreaks.size());
  +     while (bpIter.hasPrevious() && bpIter.previous() != prevBP);
  +     if (bpIter.next() != prevBP) {
  +         System.err.println("findHyphenPoss: problem!");
  +         return null;
  +     }
  +     StringBuffer sbChars = new StringBuffer(30);
  +     while (bpIter.hasNext()) {
  +         BreakPoss bp = (BreakPoss)bpIter.next();
  +         if (bp.getLayoutManager() == prevBP.getLayoutManager()) {
  +             bp.getLayoutManager().getWordChars(sbChars, prevBP.getPosition(),
  +                                                bp.getPosition());
  +         }
  +         else {
  +             bp.getLayoutManager().getWordChars(sbChars, null, bp.getPosition());
  +         }
  +         prevBP = bp;
  +     }
  +     m_vecInlineBreaks.remove(m_vecInlineBreaks.size()-1); // remove last
  +     System.err.println("Word to hyphenate: " + sbChars.toString());
  +
  +     // Now find all hyphenation points in this word (get in an array of offsets)
  +     // hyphProps are from the block level?. Note that according to the spec,
  +     // they also "apply to" fo:character. I don't know what that means, since
  +     // if we change language in the middle of a "word", the effect would seem
  +     // quite strange! Or perhaps in that case, we say that it's several words.
  +     // We probably should bring the hyphenation props up from the actual
  +     // TextLM which generate the hyphenation buffer, since these properties
  +     // inherit and could be specified on an inline or wrapper below the block
  +     // level.
  +     Hyphenation hyph =
  +            Hyphenator.hyphenate(m_hyphProps.language, m_hyphProps.country,
  +                                 sbChars.toString(),
  +                                 m_hyphProps.hyphenationRemainCharacterCount,
  +                                 m_hyphProps.hyphenationPushCharacterCount);
  +     // They hyph structure contains the information we need
  +     // Now start from prevBP: reset to that position, ask that LM to get
  +     // a Position for the first hyphenation offset. If the offset isn't in
  +     // its characters, it returns null, but must tell how many chars it had.
  +     // Keep looking at currentBP using next hyphenation point until the
  +     // returned size is greater than the available size or no more hyphenation
  +     // points remain. Choose the best break.
  +     if (hyph != null) {
  +         return new HyphContext(hyph.getHyphenationPoints());
  +     }
  +     else return null;
       }
   
  +
       private BreakPoss makeLineBreak(BreakPoss inlineBP, MinOptMax target,
                                    MinOptMax actual, boolean bJustify) {
           // make a new BP
  @@ -377,20 +429,28 @@
   
       // Generate and add areas to parent area
       // Set size etc
  -    public void addAreas(PositionIterator parentIter) {
  +    // dSpaceAdjust should reference extra space in the BPD
  +    public void addAreas(PositionIterator parentIter, double dSpaceAdjust) {
        BPLayoutManager childLM ;
        int iStartPos = 0;
        while  (parentIter.hasNext()) {
            LineBreakPosition lbp  = (LineBreakPosition)parentIter.next();
  -         System.err.println("lbp.endpos=" + lbp.m_iPos);
            m_lineArea = new LineArea();
            // Add the inline areas to lineArea
  -         PositionIterator inlinePosIter =
  +         BreakPossPosIter inlinePosIter =
                new BreakPossPosIter(m_vecInlineBreaks,
                                     iStartPos, lbp.m_iPos+1);
            iStartPos = lbp.m_iPos+1;
            while  ((childLM = inlinePosIter.getNextChildLM())!= null) {
  -             childLM.addAreas(inlinePosIter);
  +             BreakPoss bp = inlinePosIter.getBP();
  +             int iSpaceSize = getLeadingSpace(bp,  lbp.m_dAdjust);
  +             if (iSpaceSize != 0) {
  +                 System.err.println("Add leading space: " + iSpaceSize);
  +                 Space ls = new Space();
  +                 ls.setWidth(iSpaceSize);
  +                 addChild(ls);
  +             }
  +             childLM.addAreas(inlinePosIter, lbp.m_dAdjust);
            }
            m_lineArea.verticalAlign(lineHeight, lead, follow);
            parentLM.addChild(m_lineArea);
  @@ -398,6 +458,26 @@
        m_lineArea = null;
       }
   
  +    protected int getLeadingSpace(BreakPoss bp, double dSpaceAdjust) {
  +     MinOptMax leadSpace = bp.resolveLeadingSpace();
  +     if (leadSpace != null) {
  +         int iAdjust=0;
  +         if (dSpaceAdjust > 0.0) {
  +             // Stretch by factor
  +             iAdjust = (int)((double)(leadSpace.max - leadSpace.opt) *
  +                             dSpaceAdjust);
  +         }
  +         else if (dSpaceAdjust < 0.0)  {
  +             // Shrink by factor
  +             iAdjust = (int)((double)(leadSpace.opt - leadSpace.min) *
  +                             dSpaceAdjust);
  +         }
  +         return leadSpace.opt + iAdjust;
  +     }
  +     else return 0;
  +   }
  +
  +
       public boolean addChild(Area childArea) {
        // Make sure childArea is inline area
        if (childArea instanceof InlineArea) {
  @@ -440,7 +520,7 @@
                }
            }
           }
  -     addAreas(new BreakPossPosIter(vecBreakPoss, 0, vecBreakPoss.size()));
  +     addAreas(new BreakPossPosIter(vecBreakPoss, 0, vecBreakPoss.size()), 0.0);
           return false;
       }
   
  
  
  
  1.2       +5 -1      xml-fop/src/org/apache/fop/layoutmgr/PositionIterator.java
  
  Index: PositionIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/PositionIterator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PositionIterator.java     28 Apr 2002 21:31:00 -0000      1.1
  +++ PositionIterator.java     22 May 2002 20:20:50 -0000      1.2
  @@ -1,5 +1,5 @@
   /*
  - * $Id: PositionIterator.java,v 1.1 2002/04/28 21:31:00 klease Exp $
  + * $Id: PositionIterator.java,v 1.2 2002/05/22 20:20:50 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -81,6 +81,10 @@
        else {
            throw new NoSuchElementException("PosIter");
        }
  +    }
  +
  +    protected Object peekNext() {
  +     return m_nextObj;
       }
   
       public void remove() throws UnsupportedOperationException {
  
  
  
  1.4       +188 -116  xml-fop/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java
  
  Index: TextBPLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TextBPLayoutManager.java  13 May 2002 06:12:42 -0000      1.3
  +++ TextBPLayoutManager.java  22 May 2002 20:20:50 -0000      1.4
  @@ -1,5 +1,5 @@
   /*
  - * $Id: TextBPLayoutManager.java,v 1.3 2002/05/13 06:12:42 klease Exp $
  + * $Id: TextBPLayoutManager.java,v 1.4 2002/05/22 20:20:50 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -52,10 +52,13 @@
       private class AreaInfo {
        short m_iStartIndex;
        short m_iBreakIndex;
  +     short m_iWScount;
        MinOptMax m_ipdArea;
  -     AreaInfo(short iStartIndex, short iBreakIndex, MinOptMax ipdArea) {
  +     AreaInfo(short iStartIndex, short iBreakIndex, short iWScount,
  +              MinOptMax ipdArea) {
            m_iStartIndex = iStartIndex;
            m_iBreakIndex = iBreakIndex;
  +         m_iWScount = iWScount;
            m_ipdArea = ipdArea;
        }
       }
  @@ -71,19 +74,13 @@
       private TextInfo textInfo;
   
       private static final char NEWLINE = '\n';
  -    private static final char RETURN = '\r';
  -    private static final char TAB = '\t';
  -    private static final char SPACE = ' ';
  +    private static final char SPACE = '\u0020';   // Normal space
  +    private static final char NBSPACE = '\u00A0'; // Non-breaking space
       private static final char LINEBREAK = '\u2028';
       private static final char ZERO_WIDTH_SPACE = '\u200B';
       // byte order mark
       private static final char ZERO_WIDTH_NOBREAK_SPACE = '\uFEFF';
   
  -    /* values that prev (below) may take */
  -    protected static final int NOTHING = 0;
  -    protected static final int WHITESPACE = 1;
  -    protected static final int TEXT = 2;
  -
       /** Start index of first character in this parent Area */
       private short m_iAreaStart = 0;
       /** Start index of next "word" */
  @@ -94,6 +91,8 @@
       // private MinOptMax m_nextIPD= new MinOptMax(0);
       /** size of a space character (U+0020) glyph in current font */
       private int m_spaceIPD;
  +    /** size of the hyphen character glyph in current font */
  +    private int m_hyphIPD;
       /** 1/2 of word-spacing value */
       private SpaceVal m_halfWS;
       /** Number of space characters after previous possible break position. */
  @@ -109,6 +108,8 @@
   
           // With CID fonts, space isn't neccesary currentFontState.width(32)
           m_spaceIPD = CharUtilities.getCharWidth(' ', textInfo.fs);
  +     // Use hyphenationChar property
  +        m_hyphIPD = CharUtilities.getCharWidth('-', textInfo.fs);
        // Make half-space: <space> on either side of a word-space)
        SpaceVal ws = textInfo.wordSpacing;
        m_halfWS = new SpaceVal(MinOptMax.multiply(ws.space, 0.5),
  @@ -145,42 +146,17 @@
       }
   
   
  -    // NOTE: currently not used. Remove if decide it isn't necessary!
  -//     /**
  -//      * Get the BreakPoss at the start of the next line.
  -//      * @param bpPrevEnd The BreakPoss at the end of the previous line
  -//      * or null if we should return the point at the beginning of this
  -//      * text run.
  -//      */
  -//     public BreakPoss getStartBreakPoss(LayoutContext lc,
  -//                                  BreakPoss.Position bpPrevEnd) {
  -//   BreakPoss bp = null;
  -//   if (bpPrevEnd == null) {
  -//       bp = new BreakPoss(this, new TextBreakPosition(0));
  -//       // Set minimum bpd (character ascent and descent)
  -//       // Or do this at the line level???
  -//   }
  -//   else {
  -//       // Skip suppressible white-space
  -//       // ASSERT (((TextBreakPosition)bpPrevEnd).m_iAreaIndex =
  -//       //         m_iNextStart)
  -//       if ((lc.flags & LayoutContext.SUPPRESS_LEADING_SPACE)!=0) {
  -//           /* Skip any leading word-space characters. */
  -//           for (; m_iNextStart < chars.length &&
  -//                chars[m_iNextStart]==SPACE; m_iNextStart++);
  -//       }
  -//       // If now at end, nothing to compose here!
  -//       if (m_iNextStart >= chars.length) {
  -//           return null; // Or an "empty" BreakPoss?
  -//       }
  -//       else {
  -//           bp = new BreakPoss(this,
  -//                              new TextBreakPosition(m_iNextStart));
  -//       }
  -//   }
  -//   return bp;
  -//     }
  -
  +    public void getWordChars(StringBuffer sbChars,
  +                          BreakPoss.Position bp1, BreakPoss.Position bp2) {
  +     TextBreakPosition endPos = (TextBreakPosition)bp2;
  +     AreaInfo ai =
  +         (AreaInfo) m_vecAreaInfo.elementAt(endPos.m_iAreaIndex);
  +     // Skip all leading spaces for hyphenation
  +     int i;
  +        for (i=ai.m_iStartIndex;i < ai.m_iBreakIndex && 
  +              CharUtilities.isAnySpace(chars[i])==true ;i++);
  +     sbChars.append(new String(chars, i, ai.m_iBreakIndex-i));
  +    }
   
       /**
        * Return value indicating whether the next area to be generated could
  @@ -204,13 +180,14 @@
            if (ai.m_iBreakIndex != m_iNextStart) {
                m_iNextStart = ai.m_iBreakIndex;
                m_vecAreaInfo.setSize(tbp.m_iAreaIndex+1);
  -             System.err.println("Discarded previous text break pos");
  +             // TODO: reset or recalculate total IPD = sum of all word IPD
  +             // up to the break position
  +             m_ipdTotal = ai.m_ipdArea;
                setFinished(false);
            }
        }
        else {
            // Reset to beginning!
  -         System.err.println("TextBPLM: resetPosition(null)");
            m_vecAreaInfo.setSize(0);
            m_iNextStart = 0;
            setFinished(false);
  @@ -218,6 +195,30 @@
       }
   
   
  +    // TODO: see if we can use normal getNextBreakPoss for this with
  +    // extra hyphenation information in LayoutContext
  +    private boolean getHyphenIPD(HyphContext hc, MinOptMax hyphIPD) {
  +     // Skip leading word-space before calculating count?
  +     boolean bCanHyphenate = true;
  +     int iStopIndex =  m_iNextStart + hc.getNextHyphPoint();
  +
  +     if (chars.length < iStopIndex || textInfo.bCanHyphenate==false ) {
  +         iStopIndex = chars.length;
  +         bCanHyphenate = false;
  +     }
  +     hc.updateOffset(iStopIndex - m_iNextStart);
  +
  +        for (; m_iNextStart < iStopIndex; m_iNextStart++) {
  +            char c = chars[m_iNextStart];
  +         hyphIPD.opt += CharUtilities.getCharWidth(c, textInfo.fs);
  +         // letter-space?
  +     }
  +     // Need to include hyphen size too, but don't count it in the
  +     // stored running total, since it would be double counted
  +     // with later hyphenation points
  +     return bCanHyphenate;
  +    }
  +
       /**
        * Return the next break possibility that fits the constraints.
        * @param context An object specifying the flags and input information
  @@ -250,15 +251,17 @@
             */
            m_ipdTotal = new MinOptMax(0);
            iFlags |= BreakPoss.ISFIRST;
  -         // May have leading space too which can combine with a
  -         // leading word-space or letter-space
        }
   
   
  -        // HANDLE SUPPRESSED LEADING SPACES
  +        /* HANDLE SUPPRESSED LEADING SPACES
  +      * See W3C XSL Rec. 7.16.3.
  +      * Suppress characters whose "suppress-at-line-break" property = "suppress"
  +      * This can only be set on an explicit fo:character object. The default
  +      * behavior is that U+0020 is suppressed; all other character codes are
  +      * retained.
  +      */
        if (context.suppressLeadingSpace()) {
  -         /* If any leading space characters, ignore them. */ 
  -         // NOTE: Skips word-space chars only, not other white-space!
            for (; m_iNextStart < chars.length &&
                     chars[m_iNextStart]==SPACE; m_iNextStart++);
            // If now at end, nothing to compose here!
  @@ -269,23 +272,33 @@
        }
   
   
  -     // Start of this "word", plus any non-suppressed leading space
  -     // This is any kind of white-space, not just word spaces
  +     /* Start of this "word", plus any non-suppressed leading space.
  +      * Collapse any remaining word-space with leading space from
  +      * ancestor FOs.
  +      * Add up other leading space which is counted in the word IPD.
  +      */
   
  -        short iThisStart = m_iNextStart;
  -        MinOptMax spaceIPD = new MinOptMax(0); // Variable IPD
  -        int wordIPD = 0;  // Non-stretching IPD (length in base units)
  -
  -     // Handle inter-character spacing (word-space + letter-space)
  -     // What about context.getPendingSpace() on first char in word?
  -     SpaceSpecifier pendingSpace = new SpaceSpecifier(false);
  +     SpaceSpecifier pendingSpace= new SpaceSpecifier(false);
  +        short iThisStart = m_iNextStart; // Index of first character counted
  +        MinOptMax spaceIPD = new MinOptMax(0); // Extra IPD from word-spacing
  +     // Sum of glyph IPD of all characters in a word, inc. leading space
  +        int wordIPD = 0;
  +     short iWScount=0; // Count of word spaces
   
           for (; m_iNextStart < chars.length; m_iNextStart++) {
               char c = chars[m_iNextStart];
            if (CharUtilities.isAnySpace(c)==false) break;
  -            if (c==SPACE) {
  -             pendingSpace.addSpace(m_halfWS);
  -             spaceIPD.add(pendingSpace.resolve(false));
  +            if (c==SPACE || c==NBSPACE) {
  +             ++iWScount;
  +             // Counted as word-space
  +             if (m_iNextStart == iThisStart &&
  +                 (iFlags & BreakPoss.ISFIRST) !=0 ) {
  +                 context.getPendingSpace().addSpace(m_halfWS);
  +             }
  +             else {
  +                 pendingSpace.addSpace(m_halfWS);
  +                 spaceIPD.add(pendingSpace.resolve(false));
  +             }
                wordIPD += m_spaceIPD; // Space glyph IPD
                pendingSpace.clear();
                pendingSpace.addSpace(m_halfWS);
  @@ -305,64 +318,79 @@
        else {
            // This FO ended with spaces. Return the BP
            iFlags |= BreakPoss.ALL_ARE_SUPPRESS_AT_LB;
  -         // lc.trailingSpaceSeq.addSpace(m_halfWS);
  -         // Need to make SpaceSpecifier from m_halfWS!
  -         // Or at least a spaceval
  -         return makeBreakPoss(iThisStart, spaceIPD, 0, pendingSpace,
  -                              iFlags);
  +         return makeBreakPoss(iThisStart, spaceIPD, wordIPD, 
  +                              context.getPendingSpace(), pendingSpace,
  +                              iFlags, iWScount);
        }
   
  +     if (context.tryHyphenate()) {
  +         // Get the size of the next syallable
  +         MinOptMax hyphIPD = new MinOptMax(0);
  +         if (getHyphenIPD(context.getHyphContext(), hyphIPD)) {
  +             iFlags |= (BreakPoss.CAN_BREAK_AFTER | BreakPoss.HYPHENATED);
  +         }
  +         wordIPD += hyphIPD.opt;
  +     }
  +     else {
           // Look for a legal line-break: breakable white-space and certain
           // characters such as '-' which can serve as word breaks.
           // Don't look for hyphenation points here though
  -
  -        for (; m_iNextStart < chars.length; m_iNextStart++) {
  -            char c = chars[m_iNextStart];
  -            if ((c == NEWLINE) ||
  -             // Include any breakable white-space as break char
  -             //  even if fixed width
  -                (textInfo.bWrap &&
  -              (CharUtilities.isSpace(c) ||
  -               s_breakChars.indexOf(c)>=0))) {
  -             iFlags |= BreakPoss.CAN_BREAK_AFTER;
  -                if (c != SPACE) {
  -                    m_iNextStart++;
  -                    if (c != NEWLINE) {
  -                        wordIPD += CharUtilities.getCharWidth(c, textInfo.fs);
  -                    }
  -                 else {
  -                     iFlags |= BreakPoss.FORCE;
  +         for (; m_iNextStart < chars.length; m_iNextStart++) {
  +             char c = chars[m_iNextStart];
  +             if ((c == NEWLINE) ||
  +                 // Include any breakable white-space as break char
  +                 //  even if fixed width
  +                 (textInfo.bWrap &&
  +                  (CharUtilities.isSpace(c) ||
  +                   s_breakChars.indexOf(c)>=0))) {
  +                 iFlags |= BreakPoss.CAN_BREAK_AFTER;
  +                 if (c != SPACE) {
  +                     m_iNextStart++;
  +                     if (c != NEWLINE) {
  +                         wordIPD += CharUtilities.getCharWidth(c, textInfo.fs);
  +                     }
  +                     else {
  +                         iFlags |= BreakPoss.FORCE;
  +                     }
                    }
  -                }
  -             return makeBreakPoss(iThisStart, spaceIPD, wordIPD, null,
  -                                  iFlags);
  -            }
  -         wordIPD += CharUtilities.getCharWidth(c, textInfo.fs);
  -         // Note, if a normal non-breaking space, is it stretchable???
  -         // If so, keep a count of these embedded spaces.
  -        }
  -     return makeBreakPoss(iThisStart, spaceIPD, wordIPD, null, iFlags);
  +                 return makeBreakPoss(iThisStart, spaceIPD, wordIPD,
  +                                      context.getPendingSpace(), null,
  +                                      iFlags, iWScount);
  +             }
  +             wordIPD += CharUtilities.getCharWidth(c, textInfo.fs);
  +             // Note, if a normal non-breaking space, is it stretchable???
  +             // If so, keep a count of these embedded spaces.
  +         }
  +     }
  +     return makeBreakPoss(iThisStart, spaceIPD, wordIPD, 
  +                          context.getPendingSpace(), null, iFlags, iWScount);
       }
   
   
       private BreakPoss makeBreakPoss(short iWordStart, MinOptMax spaceIPD,
  -                                 int wordDim,
  +                                 int wordDim, SpaceSpecifier leadingSpace,
                                    SpaceSpecifier trailingSpace,
  -                                 int flags)
  +                                 int flags, short iWScount)
       {
        MinOptMax ipd = new MinOptMax(wordDim);
        ipd.add(spaceIPD);
  +     ipd.add(m_ipdTotal); // sum of all words so far in line
  +     // Note: break position now stores total size to here
   
        // Position is the index of the info for this word in the vector
  -     m_vecAreaInfo.add(new AreaInfo(iWordStart, m_iNextStart, ipd));
  +     m_vecAreaInfo.add(new AreaInfo(iWordStart, m_iNextStart, iWScount, ipd));
           BreakPoss bp =
            new BreakPoss(this,
                          new TextBreakPosition(m_vecAreaInfo.size()-1));
  -
  -     ipd.add(m_ipdTotal); // sum of all words so far in line
  -     bp.setStackingSize(ipd);
        m_ipdTotal = ipd;
  -     // TODO: make this correct (see Keiron's code below!)
  +     if ((flags & BreakPoss.HYPHENATED)!=0) {
  +         // Add the hyphen size, but don't change total IPD!
  +         bp.setStackingSize(MinOptMax.add(ipd, new MinOptMax(m_hyphIPD)));
  +     }
  +     else {
  +         bp.setStackingSize(ipd);
  +     }
  +     // TODO: make this correct (see Keiron's vertical alignment code)
        bp.setNonStackingSize(new MinOptMax(textInfo.lineHeight));
   
        /* Set max ascender and descender (offset from baseline),
  @@ -382,28 +410,72 @@
        else {
            bp.setTrailingSpace(new SpaceSpecifier(false));
        }
  -     bp.setLeadingSpace(new SpaceSpecifier(false));
  +     if (leadingSpace != null) {
  +         bp.setLeadingSpace(leadingSpace);
  +     }
  +     else {
  +         bp.setLeadingSpace(new SpaceSpecifier(false));
  +     }
           return bp;
       }
   
   
       /**
  -     * Add an area for each word and space (or one big one????)
  +     * Generate and add areas to parent area.
  +     * This can either generate an area for each "word" and each space, or
  +     * an area containing all text with a parameter controlling the size of
  +     * the word space. The latter is most efficient for PDF generation.
  +     * Set size of each area.
  +     * @param parentIter Iterator over BreakPoss.Position information returned
  +     * by this LayoutManager.
  +     * @param dSpaceAdjust Factor controlling how much extra space to add
  +     * in order to justify the line.
        */
  -    public void addAreas(PositionIterator posIter) {
  +    public void addAreas(PositionIterator posIter, double dSpaceAdjust) {
        // Add word areas
  -     TextBreakPosition tbpStart, tbpNext;
  +     AreaInfo ai=null ;
  +     int iStart = -1;
  +     int iWScount = 0;
  +
  +     /* On first area created, add any leading space.
  +      * Calculate word-space stretch value.
  +      */
        while (posIter.hasNext()) {
  -         tbpNext = (TextBreakPosition)posIter.next();
  -         // System.err.println("tbp.pos = " + tbpNext.m_iAreaIndex);
  -         AreaInfo ai = (AreaInfo)m_vecAreaInfo.
  -             elementAt(tbpNext.m_iAreaIndex);
  -         // Make an area containing all characters between start and end.
  -         Word word = createWord(new String(chars, ai.m_iStartIndex, 
  -                                   ai.m_iBreakIndex- ai.m_iStartIndex),
  -                                ai.m_ipdArea.opt);
  -         parentLM.addChild(word);
  +         TextBreakPosition tbpNext = (TextBreakPosition)posIter.next();
  +         ai = (AreaInfo)m_vecAreaInfo.elementAt(tbpNext.m_iAreaIndex);
  +         if (iStart == -1) {
  +             iStart = ai.m_iStartIndex;
  +         }
  +         iWScount += ai.m_iWScount;
  +     }
  +     // Calculate total adjustment
  +     int iAdjust = 0;
  +     if (dSpaceAdjust > 0.0) {
  +         // Stretch by factor
  +         System.err.println("Potential stretch = " +
  +                            (ai.m_ipdArea.max - ai.m_ipdArea.opt));
  +         iAdjust = (int)((double)(ai.m_ipdArea.max - ai.m_ipdArea.opt) *
  +             dSpaceAdjust);
  +     }
  +     else if (dSpaceAdjust < 0.0)  {
  +         // Shrink by factor
  +         System.err.println("Potential shrink = " +
  +                            (ai.m_ipdArea.opt - ai.m_ipdArea.min));
  +         iAdjust = (int)((double)(ai.m_ipdArea.opt - ai.m_ipdArea.min) *
  +             dSpaceAdjust);
  +     }
  +     System.err.println("Text adjustment factor = " + dSpaceAdjust +
  +                        " total=" + iAdjust);
  +     if (iWScount > 0) {
  +         System.err.println("Adjustment per word-space= " + iAdjust/iWScount);
  +     }
  +     // Make an area containing all characters between start and end.
  +     Word word = createWord(new String(chars, iStart, ai.m_iBreakIndex - iStart),
  +                            ai.m_ipdArea.opt + iAdjust);
  +     if (chars[iStart] == SPACE || chars[iStart] == NBSPACE ) {
  +         // word.setLeadingSpace(m_halfWS);
        }
  +     parentLM.addChild(word);
       }
   
   
  
  
  
  1.1                  xml-fop/src/org/apache/fop/layoutmgr/HyphContext.java
  
  Index: HyphContext.java
  ===================================================================
  /*
   * $Id: HyphContext.java,v 1.1 2002/05/22 20:20:50 klease Exp $
   * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
   * For details on use and redistribution please refer to the
   * LICENSE file included with these sources.
   */
  package org.apache.fop.layoutmgr;
  
  
  /**
   * This class is used to pass information to the getNextBreakPoss()
   * method concerning hyphenation. A reference to an instance of the
   * class is contained in the LayoutContext object passed to each
   * LayoutManager. It contains information concerning the hyphenation
   * points in a word and the how many of those have previously been
   * processed by a Layout Manager to generate size information.
   */
  public class HyphContext {
      private int[] m_hyphPoints;
      private int m_iCurOffset=0;
      private int m_iCurIndex=0;
  
      public HyphContext(int[] hyphPoints) {
        m_hyphPoints = hyphPoints;
      }
  
      public int getNextHyphPoint() {
        for (; m_iCurIndex < m_hyphPoints.length; m_iCurIndex++) {
            if (m_hyphPoints[m_iCurIndex] > m_iCurOffset) {
                return (m_hyphPoints[m_iCurIndex] - m_iCurOffset);
            }
        }
        return -1; // AT END!
      }
  
      public boolean hasMoreHyphPoints() {
        for (; m_iCurIndex < m_hyphPoints.length; m_iCurIndex++) {
            if (m_hyphPoints[m_iCurIndex] > m_iCurOffset) {
                return true;
            }
        }
        return false;
      }
  
      public void updateOffset(int iCharsProcessed) {
        m_iCurOffset += iCharsProcessed;
      }
  }
  
  
  

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

Reply via email to