You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by sp...@apache.org on 2004/11/13 21:37:18 UTC

cvs commit: xml-fop/src/java/org/apache/fop/layoutmgr InlineLevelLayoutManager.java AbstractLayoutManager.java BasicLinkLayoutManager.java BlockLayoutManager.java CharacterLayoutManager.java ContentLayoutManager.java InlineLayoutManager.java InlineStackingLayoutManager.java LayoutContext.java LayoutManager.java LeaderLayoutManager.java LeafNodeLayoutManager.java LineLayoutManager.java RetrieveMarkerLayoutManager.java TextLayoutManager.java

spepping    2004/11/13 12:37:18

  Modified:    src/java/org/apache/fop/area/inline FilledArea.java
               src/java/org/apache/fop/fo/flow Character.java Inline.java
                        Leader.java
               src/java/org/apache/fop/layoutmgr AbstractLayoutManager.java
                        BasicLinkLayoutManager.java BlockLayoutManager.java
                        CharacterLayoutManager.java
                        ContentLayoutManager.java InlineLayoutManager.java
                        InlineStackingLayoutManager.java LayoutContext.java
                        LayoutManager.java LeaderLayoutManager.java
                        LeafNodeLayoutManager.java LineLayoutManager.java
                        RetrieveMarkerLayoutManager.java
                        TextLayoutManager.java
  Added:       src/java/org/apache/fop/layoutmgr
                        InlineLevelLayoutManager.java
  Log:
  Patch 31206 by Luca Furini:
  
  - A new interface InlineLevelLayoutManager, implemented by LeafNodeLM,
    InlineLM, TextLM, BasicLinkLM and ContentLM
  
  - Leaders with pattern "use-content" and "dots" now works
  
  - Better handling of preserved linefeeds
  
  - Correct calculation of the lineheight, according to the value of the
    property vertical-align
  
  For a few points which may need further work, see the bugzilla page.
  
  Revision  Changes    Path
  1.4       +24 -0     xml-fop/src/java/org/apache/fop/area/inline/FilledArea.java
  
  Index: FilledArea.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/area/inline/FilledArea.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- FilledArea.java	22 Sep 2004 08:18:42 -0000	1.3
  +++ FilledArea.java	13 Nov 2004 20:37:17 -0000	1.4
  @@ -19,6 +19,7 @@
   package org.apache.fop.area.inline;
   
   import java.util.List;
  +import java.util.ListIterator;
   import java.util.ArrayList;
   
   /**
  @@ -37,6 +38,29 @@
        * Create a new filled area.
        */
       public FilledArea() {
  +    }
  +
  +    /**
  +     * Set the offset of the descendant TextAreas,
  +     * instead of the offset of the FilledArea itself.
  +     *
  +     * @param v the offset
  +     */
  +    public void setOffset(int v) {
  +        setChildOffset(inlines.listIterator(), v);
  +    }
  +
  +    private void setChildOffset(ListIterator childrenIterator, int v) {
  +        while (childrenIterator.hasNext()) {
  +            InlineArea child = (InlineArea) childrenIterator.next();
  +            if (child instanceof InlineParent) {
  +                setChildOffset(((InlineParent) child).getChildAreas().listIterator(), v);
  +            } else if (child instanceof org.apache.fop.area.inline.Viewport) {
  +                // nothing
  +            } else {
  +                child.setOffset(v);
  +            }
  +        }
       }
   
       /**
  
  
  
  1.30      +9 -0      xml-fop/src/java/org/apache/fop/fo/flow/Character.java
  
  Index: Character.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/flow/Character.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- Character.java	29 Oct 2004 11:19:36 -0000	1.29
  +++ Character.java	13 Nov 2004 20:37:17 -0000	1.30
  @@ -84,6 +84,7 @@
       private int textDecoration;
       // private ToBeImplementedProperty textShadow;
       private int textTransform;
  +    private int verticalAlign;
       private int visibility;
       private Property wordSpacing;
       // End of property values
  @@ -132,6 +133,7 @@
           textDecoration = pList.get(PR_TEXT_DECORATION).getEnum();
           // textShadow = pList.get(PR_TEXT_SHADOW);
           textTransform = pList.get(PR_TEXT_TRANSFORM).getEnum();
  +        verticalAlign = pList.get(PR_VERTICAL_ALIGN).getEnum();
           visibility = pList.get(PR_VISIBILITY).getEnum();
           wordSpacing = pList.get(PR_WORD_SPACING);
       }
  @@ -222,6 +224,13 @@
        */
       public Property getWordSpacing() {
           return wordSpacing; 
  +    }
  +
  +    /**
  +     * Return the "vertical-align" property.
  +     */
  +    public int getVerticalAlign() {
  +        return verticalAlign; 
       }
   
       /**
  
  
  
  1.35      +9 -0      xml-fop/src/java/org/apache/fop/fo/flow/Inline.java
  
  Index: Inline.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/flow/Inline.java,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- Inline.java	29 Oct 2004 11:19:36 -0000	1.34
  +++ Inline.java	13 Nov 2004 20:37:17 -0000	1.35
  @@ -66,6 +66,7 @@
       private KeepProperty keepWithPrevious;
       private Length lineHeight;
       private int textDecoration;
  +    private int verticalAlign;
       private int visibility;
       private Length width;
       private int wrapOption;
  @@ -106,6 +107,7 @@
           keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep();
           lineHeight = pList.get(PR_LINE_HEIGHT).getLength();
           textDecoration = pList.get(PR_TEXT_DECORATION).getEnum();
  +        verticalAlign = pList.get(PR_VERTICAL_ALIGN).getEnum();
           visibility = pList.get(PR_VISIBILITY).getEnum();
           width = pList.get(PR_WIDTH).getLength();
           wrapOption = pList.get(PR_WRAP_OPTION).getEnum();
  @@ -212,6 +214,13 @@
        */
       public int getTextDecoration() {
           return textDecoration; 
  +    }
  +
  +    /**
  +     * Return the "vertical-align" property.
  +     */
  +    public int getVerticalAlign() {
  +        return verticalAlign; 
       }
   
       /**
  
  
  
  1.48      +24 -1     xml-fop/src/java/org/apache/fop/fo/flow/Leader.java
  
  Index: Leader.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/flow/Leader.java,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- Leader.java	29 Oct 2004 11:19:36 -0000	1.47
  +++ Leader.java	13 Nov 2004 20:37:17 -0000	1.48
  @@ -54,6 +54,7 @@
       private CommonRelativePosition commonRelativePosition;
       private Length alignmentAdjust;
       private int alignmentBaseline;
  +    private int verticalAlign;
       private Length baselineShift;
       private ColorType color;
       private int dominantBaseline;
  @@ -94,6 +95,7 @@
           commonRelativePosition = pList.getRelativePositionProps();
           alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
           alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
  +        verticalAlign = pList.get(PR_VERTICAL_ALIGN).getEnum();
           baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
           color = pList.get(PR_COLOR).getColorType();
           dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
  @@ -136,7 +138,21 @@
       protected void startOfNode() throws FOPException {
           checkId(id);
       }
  - 
  +
  +    /**
  +     * Return the Common Margin Properties-Inline.
  +     */
  +    public CommonMarginInline getCommonMarginInline() {
  +        return commonMarginInline;
  +    }
  +
  +    /**
  +     * Return the Common Border, Padding, and Background Properties.
  +     */
  +    public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
  +        return commonBorderPaddingBackground;
  +    } 
  +
       /**
        * Return the Common Font Properties.
        */
  @@ -191,6 +207,13 @@
        */
       public Length getLeaderPatternWidth() {
           return leaderPatternWidth;
  +    }
  +
  +    /**
  +     * Return the "vertical-align" property.
  +     */
  +    public int getVerticalAlign() {
  +        return verticalAlign; 
       }
   
       /**
  
  
  
  1.31      +0 -37     xml-fop/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
  
  Index: AbstractLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- AbstractLayoutManager.java	24 Oct 2004 00:03:50 -0000	1.30
  +++ AbstractLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.31
  @@ -275,43 +275,6 @@
        * interface which are declared abstract in AbstractLayoutManager.
        * ---------------------------------------------------------*/
   
  -    public LinkedList getNextKnuthElements(LayoutContext context,
  -                                           int alignment) {
  -        log.debug("null implementation of getNextKnuthElements() called!");
  -        setFinished(true);
  -        return null;
  -    }
  -
  -    public KnuthElement addALetterSpaceTo(KnuthElement element) {
  -        log.debug("null implementation of addALetterSpaceTo() called!");
  -        return element;
  -    }
  -
  -    public void getWordChars(StringBuffer sbChars, Position pos) {
  -        log.debug("null implementation of getWordChars() called!");
  -    }
  -
  -    public void hyphenate(Position pos, HyphContext hc) {
  -        log.debug("null implementation of hyphenate called!");
  -    }
  -
  -    public boolean applyChanges(List oldList) {
  -        log.debug("null implementation of applyChanges() called!");
  -        return false;
  -    }
  -
  -    public LinkedList getChangedKnuthElements(List oldList,
  -                                              int flaggedPenalty,
  -                                              int alignment) {
  -        log.debug("null implementation of getChangeKnuthElement() called!");
  -        return null;
  -    }
  -
  -    public int getWordSpaceIPD() {
  -        log.debug("null implementation of getWordSpaceIPD() called!");
  -        return 0;
  -    }
  -
       public Area getParentArea(Area childArea) {
           return null;
       }
  
  
  
  1.6       +2 -2      xml-fop/src/java/org/apache/fop/layoutmgr/BasicLinkLayoutManager.java
  
  Index: BasicLinkLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/BasicLinkLayoutManager.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- BasicLinkLayoutManager.java	24 Oct 2004 00:03:50 -0000	1.5
  +++ BasicLinkLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.6
  @@ -27,7 +27,7 @@
   /**
    * LayoutManager for the fo:basic-link formatting object
    */
  -public class BasicLinkLayoutManager extends InlineStackingLayoutManager {
  +public class BasicLinkLayoutManager extends InlineLayoutManager {
       private BasicLink fobj;
       
       /**
  
  
  
  1.33      +3 -1      xml-fop/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
  
  Index: BlockLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- BlockLayoutManager.java	20 Oct 2004 11:55:32 -0000	1.32
  +++ BlockLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.33
  @@ -57,6 +57,7 @@
       private int lead = 12000;
       private int lineHeight = 14000;
       private int follow = 2000;
  +    private int middleShift = 0;
   
       private int iStartPos = 0;
   
  @@ -71,6 +72,7 @@
           
           lead = fs.getAscender();
           follow = -fs.getDescender();
  +        middleShift = -fs.getXHeight() / 2;
           lineHeight = fobj.getLineHeight().getOptimum().getLength().getValue();
       }
   
  @@ -141,7 +143,7 @@
        */
       private LineLayoutManager createLineManager(LayoutManager firstlm) {
           LineLayoutManager llm;
  -        llm = new LineLayoutManager(fobj, lineHeight, lead, follow);
  +        llm = new LineLayoutManager(fobj, lineHeight, lead, follow, middleShift);
           List inlines = new ArrayList();
           inlines.add(firstlm);
           while (proxyLMiter.hasNext()) {
  
  
  
  1.8       +11 -11    xml-fop/src/java/org/apache/fop/layoutmgr/CharacterLayoutManager.java
  
  Index: CharacterLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/CharacterLayoutManager.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- CharacterLayoutManager.java	20 Oct 2004 13:19:24 -0000	1.7
  +++ CharacterLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.8
  @@ -48,6 +48,7 @@
           fobj = node;
           InlineArea inline = getCharacterInlineArea(node);
           setCurrentArea(inline);
  +        setAlignment(fobj.getVerticalAlign());
           fs = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo());
   
           SpaceVal ls = SpaceVal.makeLetterSpacing(fobj.getLetterSpacing());
  @@ -71,15 +72,15 @@
        */
       protected void offsetArea(LayoutContext context) {
           int bpd = curArea.getBPD();
  -        switch (alignment) {
  +        switch (verticalAlignment) {
               case VerticalAlign.MIDDLE:
  -                curArea.setOffset(context.getBaseline() - bpd / 2 /* - fontLead/2 */);
  +                curArea.setOffset(context.getMiddleBaseline() + fs.getXHeight() / 2);
               break;
               case VerticalAlign.TOP:
  -                //curArea.setOffset(0);
  +                curArea.setOffset(fs.getAscender());
               break;
               case VerticalAlign.BOTTOM:
  -                curArea.setOffset(context.getLineHeight() - bpd);
  +                curArea.setOffset(context.getLineHeight() - bpd + fs.getAscender());
               break;
               case VerticalAlign.BASELINE:
               default:
  @@ -116,16 +117,15 @@
           int lead = 0;
           int total = 0;
           int middle = 0;
  -        switch (alignment) {
  +        switch (verticalAlignment) {
               case VerticalAlign.MIDDLE  : middle = bpd / 2 ;
  -                                         lead = bpd / 2 ;
  -                                         break;
  -            case VerticalAlign.TOP     : total = bpd;
                                            break;
  +            case VerticalAlign.TOP     : // fall through
               case VerticalAlign.BOTTOM  : total = bpd;
                                            break;
  -            case VerticalAlign.BASELINE:
  -            default:                     lead = bpd;
  +            case VerticalAlign.BASELINE: // fall through
  +            default                    : lead = fs.getAscender();
  +                                         total = bpd;
                                            break;
           }
   
  
  
  
  1.16      +38 -11    xml-fop/src/java/org/apache/fop/layoutmgr/ContentLayoutManager.java
  
  Index: ContentLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/ContentLayoutManager.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- ContentLayoutManager.java	24 Oct 2004 00:03:50 -0000	1.15
  +++ ContentLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.16
  @@ -22,6 +22,7 @@
   import org.apache.fop.apps.FOUserAgent;
   import org.apache.fop.fo.flow.Marker;
   import org.apache.fop.area.Area;
  +import org.apache.fop.area.inline.InlineArea;
   import org.apache.fop.area.Resolvable;
   import org.apache.fop.area.PageViewport;
   
  @@ -40,12 +41,12 @@
    * For use with objects that contain inline areas such as
    * leader use-content and title.
    */
  -public class ContentLayoutManager implements LayoutManager {
  +public class ContentLayoutManager implements InlineLevelLayoutManager {
       private FOUserAgent userAgent;
       private Area holder;
       private int stackSize;
       private LayoutManager parentLM;
  -    private List childLMs = new ArrayList(1);
  +    private InlineLevelLayoutManager childLM = null;
   
       /**
        * logging instance
  @@ -137,6 +138,19 @@
           stackSize = stack.opt;
       }
   
  +    public void addAreas(PositionIterator posIter, LayoutContext context) {
  +        // add the content areas
  +        // the area width has already been adjusted, and it must remain unchanged
  +        // so save its value before calling addAreas, and set it again afterwards
  +        int savedIPD = ((InlineArea)holder).getIPD();
  +        // set to zero the ipd adjustment ratio, to avoid spaces in the pattern
  +        // to be modified
  +        LayoutContext childContext = new LayoutContext(context);
  +        childContext.setIPDAdjust(0.0);
  +        childLM.addAreas(posIter, childContext);
  +        ((InlineArea)holder).setIPD(savedIPD);
  +    }
  +
       public int getStackingSize() {
           return stackSize;
       }
  @@ -202,9 +216,6 @@
       }
   
       /** @see org.apache.fop.layoutmgr.LayoutManager */
  -    public void addAreas(PositionIterator posIter, LayoutContext context) { }
  -
  -    /** @see org.apache.fop.layoutmgr.LayoutManager */
       public void initialize() {
           //to be done
       }
  @@ -259,6 +270,8 @@
        * @see org.apache.fop.layoutmgr.LayoutManager#getChildLMs
        */
       public List getChildLMs() {
  +        List childLMs = new ArrayList(1);
  +        childLMs.add(childLM);
           return childLMs;
       }
   
  @@ -271,7 +284,7 @@
           }
           lm.setParent(this);
           lm.initialize();
  -        childLMs.add(lm);
  +        childLM = (InlineLevelLayoutManager)lm;
           log.trace(this.getClass().getName()
                     + ": Adding child LM " + lm.getClass().getName());
       }
  @@ -292,8 +305,26 @@
   
       public LinkedList getNextKnuthElements(LayoutContext context,
                                              int alignment) {
  +        LinkedList contentList = new LinkedList();
  +        LinkedList returnedList;
  +
  +        while (!childLM.isFinished()) {
  +            // get KnuthElements from childLM
  +            returnedList = childLM.getNextKnuthElements(context, alignment);
  +
  +            if (returnedList != null) {
  +                // move elements to contentList, and accumulate their size
  +               KnuthElement contentElement;
  +               while (returnedList.size() > 0) {
  +                    contentElement = (KnuthElement)returnedList.removeFirst();
  +                    stackSize += contentElement.getW();
  +                    contentList.add(contentElement);
  +                }
  +            }
  +        }
  +
           setFinished(true);
  -        return null;
  +        return contentList;
       }
   
       public KnuthElement addALetterSpaceTo(KnuthElement element) {
  @@ -314,10 +345,6 @@
                                                 int flaggedPenalty,
                                                 int alignment) {
           return null;
  -    }
  -
  -    public int getWordSpaceIPD() {
  -        return 0;
       }
   }
   
  
  
  
  1.3       +228 -6    xml-fop/src/java/org/apache/fop/layoutmgr/InlineLayoutManager.java
  
  Index: InlineLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/InlineLayoutManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- InlineLayoutManager.java	11 Nov 2004 06:51:58 -0000	1.2
  +++ InlineLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.3
  @@ -18,8 +18,13 @@
   
   package org.apache.fop.layoutmgr;
   
  +import java.util.List;
  +import java.util.ListIterator;
  +import java.util.LinkedList;
   
  +import org.apache.fop.fo.FObj;
   import org.apache.fop.fo.flow.Inline;
  +import org.apache.fop.fo.flow.Leader;
   import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
   import org.apache.fop.fo.properties.CommonMarginInline;
   import org.apache.fop.fo.properties.SpaceProperty;
  @@ -30,8 +35,9 @@
    * LayoutManager for objects which stack children in the inline direction,
    * such as Inline or Line
    */
  -public class InlineLayoutManager extends InlineStackingLayoutManager {
  -    private Inline fobj;
  +public class InlineLayoutManager extends InlineStackingLayoutManager 
  +                                         implements InlineLevelLayoutManager {
  +    private FObj fobj;
   
       private CommonMarginInline inlineProps = null;
       private CommonBorderPaddingBackground borderProps = null;
  @@ -47,13 +53,31 @@
           super(node);
           fobj = node;
       }
  +
  +    /**
  +     * Create an inline layout manager.
  +     * This is used for fo's that create areas that
  +     * contain inline areas.
  +     *
  +     * @param node the formatting object that creates the area
  +     */
  +    public InlineLayoutManager(Leader node) {
  +        super(node);
  +        fobj = node;
  +    }
       
       /**
        * @see org.apache.fop.layoutmgr.AbstractLayoutManager#initProperties()
        */
       protected void initProperties() {
  -        inlineProps = fobj.getCommonMarginInline();
  -        borderProps = fobj.getCommonBorderPaddingBackground();
  +        // fobj can be either an Inline or a Leader
  +        if (fobj instanceof Inline) {
  +            inlineProps = ((Inline) fobj).getCommonMarginInline();
  +            borderProps = ((Inline) fobj).getCommonBorderPaddingBackground();
  +        } else {
  +            inlineProps = ((Leader) fobj).getCommonMarginInline();
  +            borderProps = ((Leader) fobj).getCommonBorderPaddingBackground();
  +        }
           int iPad = borderProps.getPadding(CommonBorderPaddingBackground.BEFORE, false);
           iPad += borderProps.getBorderWidth(CommonBorderPaddingBackground.BEFORE,
                                                false);
  @@ -94,7 +118,6 @@
           return inlineProps.spaceEnd;
       }
       
  -
       /**
        * Return value indicating whether the next area to be generated could
        * start a new line. This should only be called in the "START" condition
  @@ -121,5 +144,204 @@
           }
       }
   
  +    public LinkedList getNextKnuthElements(LayoutContext lc, int alignment) {
  +        InlineLevelLayoutManager curLM;
  +
  +        // the list returned by child LM
  +        LinkedList returnedList;
  +        KnuthElement returnedElement;
  +
  +        // the list which will be returned to the parent LM
  +        LinkedList returnList = new LinkedList();
  +
  +        SpaceSpecifier leadingSpace = lc.getLeadingSpace();
  +
  +        if (lc.startsNewArea()) {
  +            // First call to this LM in new parent "area", but this may
  +            // not be the first area created by this inline
  +            childLC = new LayoutContext(lc);
  +            if (getSpaceStart() != null) {
  +                lc.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart()));
  +            }
  +
  +            // Check for "fence"
  +            if (hasLeadingFence(!lc.isFirstArea())) {
  +                // Reset leading space sequence for child areas
  +                leadingSpace = new SpaceSpecifier(false);
  +            }
  +            // Reset state variables
  +            clearPrevIPD(); // Clear stored prev content dimensions
  +        }
  +
  +        while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
  +            // get KnuthElements from curLM
  +            returnedList = curLM.getNextKnuthElements(lc, alignment);
  +            if (returnedList != null) {
  +                // "wrap" the Position stored in each element of returnedList
  +                ListIterator listIter = returnedList.listIterator();
  +                while (listIter.hasNext()) {
  +                    returnedElement = (KnuthElement) listIter.next();
  +                    returnedElement.setPosition
  +                        (new NonLeafPosition(this,
  +                                             returnedElement.getPosition()));
  +                    returnList.add(returnedElement);
  +                }
  +                return returnList;
  +            } else {
  +                // curLM returned null because it finished;
  +                // just iterate once more to see if there is another child
  +            }
  +        }
  +        setFinished(true);
  +        return null;
  +    }
  +
  +    public KnuthElement addALetterSpaceTo(KnuthElement element) {
  +        NonLeafPosition savedPos = (NonLeafPosition) element.getPosition();
  +        element.setPosition(savedPos.getPosition());
  +
  +        KnuthElement newElement
  +            = ((InlineLevelLayoutManager)
  +               element.getLayoutManager()).addALetterSpaceTo(element);
  +        newElement.setPosition
  +            (new NonLeafPosition(this, newElement.getPosition()));
  +        element.setPosition(savedPos);
  +        return newElement;
  +    }
  +
  +    public void getWordChars(StringBuffer sbChars, Position pos) {
  +        Position newPos = ((NonLeafPosition) pos).getPosition();
  +        ((InlineLevelLayoutManager)
  +         newPos.getLM()).getWordChars(sbChars, newPos);
  +    }
  +
  +    public void hyphenate(Position pos, HyphContext hc) {
  +        Position newPos = ((NonLeafPosition) pos).getPosition();
  +        ((InlineLevelLayoutManager)
  +         newPos.getLM()).hyphenate(newPos, hc);
  +    }
  +
  +    public boolean applyChanges(List oldList) {
  +        // "unwrap" the Positions stored in the elements
  +        ListIterator oldListIterator = oldList.listIterator();
  +        KnuthElement oldElement;
  +        while (oldListIterator.hasNext()) {
  +            oldElement = (KnuthElement) oldListIterator.next();
  +            oldElement.setPosition
  +                (((NonLeafPosition) oldElement.getPosition()).getPosition());
  +        }
  +        // reset the iterator
  +        oldListIterator = oldList.listIterator();
  +
  +        InlineLevelLayoutManager prevLM = null;
  +        InlineLevelLayoutManager currLM;
  +        int fromIndex = 0;
  +
  +        boolean bSomethingChanged = false;
  +        while(oldListIterator.hasNext()) {
  +            oldElement = (KnuthElement) oldListIterator.next();
  +            currLM = (InlineLevelLayoutManager) oldElement.getLayoutManager();
  +            // initialize prevLM
  +            if (prevLM == null) {
  +                prevLM = currLM;
  +            }
  +
  +            if (currLM != prevLM || !oldListIterator.hasNext()) {
  +                if (oldListIterator.hasNext()) {
  +                    bSomethingChanged
  +                        = prevLM.applyChanges(oldList.subList(fromIndex, oldListIterator.previousIndex()))
  +                        || bSomethingChanged;
  +                    prevLM = currLM;
  +                    fromIndex = oldListIterator.previousIndex();
  +                } else if (currLM == prevLM) {
  +                    bSomethingChanged
  +                        = prevLM.applyChanges(oldList.subList(fromIndex, oldList.size()))
  +                        || bSomethingChanged;
  +                } else {
  +                    bSomethingChanged
  +                        = prevLM.applyChanges(oldList.subList(fromIndex, oldListIterator.previousIndex()))
  +                        || bSomethingChanged;
  +                    bSomethingChanged
  +                        = currLM.applyChanges(oldList.subList(oldListIterator.previousIndex(), oldList.size()))
  +                        || bSomethingChanged;
  +                }
  +            }
  +        }
  +
  +        // "wrap" again the Positions stored in the elements
  +        oldListIterator = oldList.listIterator();
  +        while (oldListIterator.hasNext()) {
  +            oldElement = (KnuthElement) oldListIterator.next();
  +            oldElement.setPosition
  +                (new NonLeafPosition(this, oldElement.getPosition()));
  +        }
  +        return bSomethingChanged;
  +    }
  +
  +    public LinkedList getChangedKnuthElements(List oldList, int flaggedPenalty, int alignment) {
  +        // "unwrap" the Positions stored in the elements
  +        ListIterator oldListIterator = oldList.listIterator();
  +        KnuthElement oldElement;
  +        while (oldListIterator.hasNext()) {
  +            oldElement = (KnuthElement) oldListIterator.next();
  +            oldElement.setPosition
  +                (((NonLeafPosition) oldElement.getPosition()).getPosition());
  +        }
  +        // reset the iterator
  +        oldListIterator = oldList.listIterator();
  +
  +        KnuthElement returnedElement;
  +        LinkedList returnedList = new LinkedList();
  +        LinkedList returnList = new LinkedList();
  +        InlineLevelLayoutManager prevLM = null;
  +        InlineLevelLayoutManager currLM;
  +        int fromIndex = 0;
  +
  +        while(oldListIterator.hasNext()) {
  +            oldElement = (KnuthElement) oldListIterator.next();
  +            currLM = (InlineLevelLayoutManager) oldElement.getLayoutManager();
  +            if (prevLM == null) {
  +                prevLM = currLM;
  +            }
  +
  +            if (currLM != prevLM || !oldListIterator.hasNext()) {
  +                if (oldListIterator.hasNext()) {
  +                    returnedList.addAll
  +                        (prevLM.getChangedKnuthElements
  +                         (oldList.subList(fromIndex,
  +                                          oldListIterator.previousIndex()),
  +                          flaggedPenalty, alignment));
  +                    prevLM = currLM;
  +                    fromIndex = oldListIterator.previousIndex();
  +                } else if (currLM == prevLM) {
  +                    returnedList.addAll
  +                        (prevLM.getChangedKnuthElements
  +                         (oldList.subList(fromIndex, oldList.size()),
  +                          flaggedPenalty, alignment));
  +                } else {
  +                    returnedList.addAll
  +                        (prevLM.getChangedKnuthElements
  +                         (oldList.subList(fromIndex,
  +                                          oldListIterator.previousIndex()),
  +                          flaggedPenalty, alignment));
  +                    returnedList.addAll
  +                        (currLM.getChangedKnuthElements
  +                         (oldList.subList(oldListIterator.previousIndex(),
  +                                          oldList.size()),
  +                          flaggedPenalty, alignment));
  +                }
  +            }
  +        }
  +
  +        // "wrap" the Position stored in each element of returnedList
  +        ListIterator listIter = returnedList.listIterator();
  +        while (listIter.hasNext()) {
  +            returnedElement = (KnuthElement) listIter.next();
  +            returnedElement.setPosition
  +                (new NonLeafPosition(this, returnedElement.getPosition()));
  +            returnList.add(returnedElement);
  +        }
  +        return returnList;
  +    }
   }
   
  
  
  
  1.17      +4 -209    xml-fop/src/java/org/apache/fop/layoutmgr/InlineStackingLayoutManager.java
  
  Index: InlineStackingLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/InlineStackingLayoutManager.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- InlineStackingLayoutManager.java	11 Nov 2004 06:38:11 -0000	1.16
  +++ InlineStackingLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.17
  @@ -69,7 +69,7 @@
       private Area currentArea; // LineArea or InlineParent
   
       private BreakPoss prevBP;
  -    private LayoutContext childLC ;
  +    protected LayoutContext childLC ;
   
       private LayoutManager lastChildLM = null; // Set when return last breakposs
       private boolean bAreaCreated = false;
  @@ -462,8 +462,9 @@
               = new StackingIter(positionList.listIterator());
   
           LayoutManager prevLM = null;
  -        LayoutManager childLM ;
  -        while ((childLM = childPosIter.getNextChildLM()) != null) {
  +        InlineLevelLayoutManager childLM ;
  +        while ((childLM = (InlineLevelLayoutManager) childPosIter.getNextChildLM())
  +               != null) {
               getContext().setFlags(LayoutContext.LAST_AREA,
                                     context.isLastArea() && childLM == lastLM);
               childLM.addAreas(childPosIter, getContext());
  @@ -555,212 +556,6 @@
                   ls.setIPD(iAdjust);
                   parentArea.addChild(ls);
               }
  -        }
  -    }
  -
  -    public LinkedList getNextKnuthElements(LayoutContext lc, int alignment) {
  -        LayoutManager curLM;
  -
  -        // the list returned by child LM
  -        LinkedList returnedList;
  -        KnuthElement returnedElement;
  -
  -        // the list which will be returned to the parent LM
  -        LinkedList returnList = new LinkedList();
  -
  -        SpaceSpecifier leadingSpace = lc.getLeadingSpace();
  -
  -        if (lc.startsNewArea()) {
  -            // First call to this LM in new parent "area", but this may
  -            // not be the first area created by this inline
  -            childLC = new LayoutContext(lc);
  -            if (getSpaceStart() != null) {
  -                lc.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart()));
  -            }
  -
  -            // Check for "fence"
  -            if (hasLeadingFence(!lc.isFirstArea())) {
  -                // Reset leading space sequence for child areas
  -                leadingSpace = new SpaceSpecifier(false);
  -            }
  -            // Reset state variables
  -            clearPrevIPD(); // Clear stored prev content dimensions
  -        }
  -
  -        while ((curLM = getChildLM()) != null) {
  -            // get KnuthElements from curLM
  -            returnedList = curLM.getNextKnuthElements(lc, alignment);
  -            if (returnedList != null) {
  -                // "wrap" the Position stored in each element of returnedList
  -                ListIterator listIter = returnedList.listIterator();
  -                while (listIter.hasNext()) {
  -                    returnedElement = (KnuthElement) listIter.next();
  -                    returnedElement.setPosition
  -                        (new NonLeafPosition(this,
  -                                             returnedElement.getPosition()));
  -                    returnList.add(returnedElement);
  -                }
  -                return returnList;
  -            } else {
  -                // curLM returned null because it finished;
  -                // just iterate once more to see if there is another child
  -            }
  -        }
  -        setFinished(true);
  -        return null;
  -    }
  -
  -    public KnuthElement addALetterSpaceTo(KnuthElement element) {
  -        NonLeafPosition savedPos = (NonLeafPosition) element.getPosition();
  -        element.setPosition(savedPos.getPosition());
  -
  -        KnuthElement newElement
  -            = element.getLayoutManager().addALetterSpaceTo(element);
  -        newElement.setPosition
  -            (new NonLeafPosition(this, newElement.getPosition()));
  -        element.setPosition(savedPos);
  -        return newElement;
  -    }
  -
  -    public void getWordChars(StringBuffer sbChars, Position pos) {
  -        Position newPos = ((NonLeafPosition) pos).getPosition();
  -        newPos.getLM().getWordChars(sbChars, newPos);
  -    }
  -
  -    public void hyphenate(Position pos, HyphContext hc) {
  -        Position newPos = ((NonLeafPosition) pos).getPosition();
  -        newPos.getLM().hyphenate(newPos, hc);
  -    }
  -
  -    public boolean applyChanges(List oldList) {
  -        // "unwrap" the Positions stored in the elements
  -        ListIterator oldListIterator = oldList.listIterator();
  -        KnuthElement oldElement;
  -        while (oldListIterator.hasNext()) {
  -            oldElement = (KnuthElement) oldListIterator.next();
  -            oldElement.setPosition
  -                (((NonLeafPosition) oldElement.getPosition()).getPosition());
  -        }
  -        // reset the iterator
  -        oldListIterator = oldList.listIterator();
  -
  -        LayoutManager prevLM = null;
  -        LayoutManager currLM;
  -        int fromIndex = 0;
  -
  -        boolean bSomethingChanged = false;
  -        while(oldListIterator.hasNext()) {
  -            oldElement = (KnuthElement) oldListIterator.next();
  -            currLM = oldElement.getLayoutManager();
  -            // initialize prevLM
  -            if (prevLM == null) {
  -                prevLM = currLM;
  -            }
  -
  -            if (currLM != prevLM || !oldListIterator.hasNext()) {
  -                if (oldListIterator.hasNext()) {
  -                    bSomethingChanged
  -                        = prevLM.applyChanges(oldList.subList(fromIndex, oldListIterator.previousIndex()))
  -                        || bSomethingChanged;
  -                    prevLM = currLM;
  -                    fromIndex = oldListIterator.previousIndex();
  -                } else if (currLM == prevLM) {
  -                    bSomethingChanged
  -                        = prevLM.applyChanges(oldList.subList(fromIndex, oldList.size()))
  -                        || bSomethingChanged;
  -                } else {
  -                    bSomethingChanged
  -                        = prevLM.applyChanges(oldList.subList(fromIndex, oldListIterator.previousIndex()))
  -                        || bSomethingChanged;
  -                    bSomethingChanged
  -                        = currLM.applyChanges(oldList.subList(oldListIterator.previousIndex(), oldList.size()))
  -                        || bSomethingChanged;
  -                }
  -            }
  -        }
  -
  -        // "wrap" again the Positions stored in the elements
  -        oldListIterator = oldList.listIterator();
  -        while (oldListIterator.hasNext()) {
  -            oldElement = (KnuthElement) oldListIterator.next();
  -            oldElement.setPosition
  -                (new NonLeafPosition(this, oldElement.getPosition()));
  -        }
  -        return bSomethingChanged;
  -    }
  -
  -    public LinkedList getChangedKnuthElements(List oldList, int flaggedPenalty, int alignment) {
  -        // "unwrap" the Positions stored in the elements
  -        ListIterator oldListIterator = oldList.listIterator();
  -        KnuthElement oldElement;
  -        while (oldListIterator.hasNext()) {
  -            oldElement = (KnuthElement) oldListIterator.next();
  -            oldElement.setPosition
  -                (((NonLeafPosition) oldElement.getPosition()).getPosition());
  -        }
  -        // reset the iterator
  -        oldListIterator = oldList.listIterator();
  -
  -        KnuthElement returnedElement;
  -        LinkedList returnedList = new LinkedList();
  -        LinkedList returnList = new LinkedList();
  -        LayoutManager prevLM = null;
  -        LayoutManager currLM;
  -        int fromIndex = 0;
  -
  -        while(oldListIterator.hasNext()) {
  -            oldElement = (KnuthElement) oldListIterator.next();
  -            currLM = oldElement.getLayoutManager();
  -            if (prevLM == null) {
  -                prevLM = currLM;
  -            }
  -
  -            if (currLM != prevLM || !oldListIterator.hasNext()) {
  -                if (oldListIterator.hasNext()) {
  -                    returnedList.addAll
  -                        (prevLM.getChangedKnuthElements
  -                         (oldList.subList(fromIndex,
  -                                          oldListIterator.previousIndex()),
  -                          flaggedPenalty, alignment));
  -                    prevLM = currLM;
  -                    fromIndex = oldListIterator.previousIndex();
  -                } else if (currLM == prevLM) {
  -                    returnedList.addAll
  -                        (prevLM.getChangedKnuthElements
  -                         (oldList.subList(fromIndex, oldList.size()),
  -                          flaggedPenalty, alignment));
  -                } else {
  -                    returnedList.addAll
  -                        (prevLM.getChangedKnuthElements
  -                         (oldList.subList(fromIndex,
  -                                          oldListIterator.previousIndex()),
  -                          flaggedPenalty, alignment));
  -                    returnedList.addAll
  -                        (currLM.getChangedKnuthElements
  -                         (oldList.subList(oldListIterator.previousIndex(),
  -                                          oldList.size()),
  -                          flaggedPenalty, alignment));
  -                }
  -            }
  -        }
  -
  -        // "wrap" the Position stored in each element of returnedList
  -        ListIterator listIter = returnedList.listIterator();
  -        while (listIter.hasNext()) {
  -            returnedElement = (KnuthElement) listIter.next();
  -            returnedElement.setPosition
  -                (new NonLeafPosition(this, returnedElement.getPosition()));
  -            returnList.add(returnedElement);
  -        }
  -        return returnList;
  -    }
  -
  -    public int getWordSpaceIPD() {
  -        LayoutManager firstChild = getChildLM();
  -        if (firstChild != null) {
  -            return firstChild.getWordSpaceIPD();
  -        } else {
  -            return 0;
           }
       }
   }
  
  
  
  1.7       +11 -0     xml-fop/src/java/org/apache/fop/layoutmgr/LayoutContext.java
  
  Index: LayoutContext.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/LayoutContext.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- LayoutContext.java	5 Sep 2004 18:16:32 -0000	1.6
  +++ LayoutContext.java	13 Nov 2004 20:37:17 -0000	1.7
  @@ -86,6 +86,7 @@
   
       private int iLineHeight;
       private int iBaseline;
  +    private int iMiddleShift;
   
       public LayoutContext(LayoutContext parentLC) {
           this.flags = parentLC.flags;
  @@ -98,6 +99,7 @@
           this.ipdAdjust = parentLC.ipdAdjust;
           this.iLineHeight = parentLC.iLineHeight;
           this.iBaseline = parentLC.iBaseline;
  +        this.iMiddleShift = parentLC.iMiddleShift;
           // Copy other fields as necessary. Use clone???
       }
   
  @@ -225,6 +227,14 @@
           return iBaseline;
       }
       
  +    public void setMiddleShift(int ms) {
  +        iMiddleShift = ms;
  +    }
  +
  +    public int getMiddleBaseline() {
  +        return iBaseline + iMiddleShift;
  +    }
  +    
       public String toString() {
           return "Layout Context:" +
           "\nStack Limit: \t" + (getStackLimit() == null ? "null" : getStackLimit().toString()) +
  @@ -235,6 +245,7 @@
           "\nIPD Adjust: \t" + getIPDAdjust() +
           "\nLine Height: \t" + getLineHeight() +
           "\nBaseline: \t" + getBaseline() +
  +        "\nMiddle Baseline: \t" + getMiddleBaseline() +
           "\nResolve Leading Space: \t" + resolveLeadingSpace() +
           "\nSuppress Leading Space: \t" + suppressLeadingSpace() +
           "\nIs First Area: \t" + isFirstArea() + 
  
  
  
  1.15      +0 -15     xml-fop/src/java/org/apache/fop/layoutmgr/LayoutManager.java
  
  Index: LayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/LayoutManager.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- LayoutManager.java	24 Oct 2004 00:03:50 -0000	1.14
  +++ LayoutManager.java	13 Nov 2004 20:37:17 -0000	1.15
  @@ -237,19 +237,4 @@
        * @param newLMs the list of LMs to be added
        */
       void addChildLMs(List newLMs);
  -
  -    LinkedList getNextKnuthElements(LayoutContext context, int alignment);
  -
  -    KnuthElement addALetterSpaceTo(KnuthElement element);
  -
  -    void getWordChars(StringBuffer sbChars, Position pos);
  -
  -    void hyphenate(Position pos, HyphContext hc);
  -
  -    boolean applyChanges(List oldList);
  -
  -    LinkedList getChangedKnuthElements(List oldList, int flaggedPenalty,
  -                                       int alignment);
  -
  -    int getWordSpaceIPD();
   }
  
  
  
  1.12      +103 -13   xml-fop/src/java/org/apache/fop/layoutmgr/LeaderLayoutManager.java
  
  Index: LeaderLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/LeaderLayoutManager.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- LeaderLayoutManager.java	20 Oct 2004 21:07:02 -0000	1.11
  +++ LeaderLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.12
  @@ -23,7 +23,10 @@
   import org.apache.fop.area.inline.InlineArea;
   import org.apache.fop.area.inline.Space;
   import org.apache.fop.area.inline.TextArea;
  +import org.apache.fop.datatypes.Length;
   import org.apache.fop.datatypes.PercentBase;
  +import org.apache.fop.fo.Constants;
  +import org.apache.fop.fo.flow.Inline;
   import org.apache.fop.fo.flow.Leader;
   import org.apache.fop.fonts.Font;
   import org.apache.fop.traits.MinOptMax;
  @@ -38,6 +41,9 @@
       private Leader fobj;
       Font font = null;
       
  +    private LinkedList contentList = null;
  +    private ContentLayoutManager clm = null;
  +
       /**
        * Constructor
        *
  @@ -48,7 +54,10 @@
           super(node);
           fobj = node;
           font = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo());
  -        setAlignment(node.getLeaderAlignment());
  +        // the property leader-alignment does not affect vertical positioning
  +        // (see section 7.21.1 in the XSL Recommendation)
  +        // setAlignment(node.getLeaderAlignment());
  +        setAlignment(fobj.getVerticalAlign());
       }
   
       public InlineArea get(LayoutContext context) {
  @@ -84,10 +93,9 @@
               char dot = '.'; // userAgent.getLeaderDotCharacter();
   
               t.setTextArea("" + dot);
  +            t.setIPD(font.getCharWidth(dot));
               t.addTrait(Trait.FONT_NAME, font.getFontName());
               t.addTrait(Trait.FONT_SIZE, new Integer(font.getFontSize()));
  -            // set offset of dot within inline parent
  -            t.setOffset(font.getAscender());
               int width = font.getCharWidth(dot);
               Space spacer = null;
               if (fobj.getLeaderPatternWidth().getValue() > width) {
  @@ -116,15 +124,15 @@
               // get breaks then add areas to FilledArea
               FilledArea fa = new FilledArea();
   
  -            ContentLayoutManager clm = new ContentLayoutManager(fa);
  +            clm = new ContentLayoutManager(fa);
               clm.setUserAgent(fobj.getUserAgent());
               addChildLM(clm);
   
  -            InlineStackingLayoutManager lm;
  -            lm = new InlineStackingLayoutManager(fobj);
  +            InlineLayoutManager lm;
  +            lm = new InlineLayoutManager(fobj);
               clm.addChildLM(lm);
   
  -            clm.fillArea(lm);
  +            contentList = clm.getNextKnuthElements(new LayoutContext(0), 0);
               int width = clm.getStackingSize();
               Space spacer = null;
               if (fobj.getLeaderPatternWidth().getValue() > width) {
  @@ -141,6 +149,90 @@
           return leaderArea;
        }
   
  +    protected void offsetArea(LayoutContext context) {
  +        int pattern = fobj.getLeaderPattern();
  +        int bpd = curArea.getBPD();
  +
  +        switch (pattern) {
  +            case LeaderPattern.RULE: 
  +                switch (verticalAlignment) {
  +                    case VerticalAlign.TOP:
  +                        curArea.setOffset(0);
  +                    break;
  +                    case VerticalAlign.MIDDLE:
  +                        curArea.setOffset(context.getMiddleBaseline() - bpd / 2);
  +                    break;
  +                    case VerticalAlign.BOTTOM:
  +                        curArea.setOffset(context.getLineHeight() - bpd);
  +                    break;
  +                    case VerticalAlign.BASELINE: // fall through
  +                    default:
  +                        curArea.setOffset(context.getBaseline() - bpd);
  +                    break;
  +                }
  +            break;
  +            case LeaderPattern.DOTS: 
  +                switch (verticalAlignment) {
  +                    case VerticalAlign.TOP:
  +                        curArea.setOffset(0);
  +                    break;
  +                    case VerticalAlign.MIDDLE:
  +                        curArea.setOffset(context.getMiddleBaseline());
  +                    break;
  +                    case VerticalAlign.BOTTOM:
  +                        curArea.setOffset(context.getLineHeight() - bpd + font.getAscender());
  +                    break;
  +                    case VerticalAlign.BASELINE: // fall through
  +                    default:
  +                        curArea.setOffset(context.getBaseline());
  +                    break;
  +                }
  +            break;
  +            case LeaderPattern.SPACE: 
  +                // nothing to do
  +            break;
  +            case LeaderPattern.USECONTENT: 
  +                switch (verticalAlignment) {
  +                    case VerticalAlign.TOP:
  +                        curArea.setOffset(0);
  +                    break;
  +                    case VerticalAlign.MIDDLE:
  +                        curArea.setOffset(context.getMiddleBaseline());
  +                    break;
  +                    case VerticalAlign.BOTTOM:
  +                        curArea.setOffset(context.getLineHeight() - bpd);
  +                    break;
  +                    case VerticalAlign.BASELINE: // fall through
  +                    default:
  +                        curArea.setOffset(context.getBaseline());
  +                    break;
  +                }
  +            break;
  +        }
  +    }
  +
  +    public void addAreas(PositionIterator posIter, LayoutContext context) {
  +        if (fobj.getLeaderPattern() != LeaderPattern.USECONTENT) {
  +            // use LeafNodeLayoutManager.addAreas()
  +            super.addAreas(posIter, context);
  +        } else {
  +            addId();
  +
  +            widthAdjustArea(context);
  +
  +            // add content areas
  +            KnuthPossPosIter contentIter = new KnuthPossPosIter(contentList, 0, contentList.size());
  +            clm.addAreas(contentIter, context);
  +            offsetArea(context);
  +
  +            parentLM.addChild(curArea);
  +
  +            while (posIter.hasNext()) {
  +                posIter.next();
  +            }
  +        }
  +    }
  +
       public LinkedList getNextKnuthElements(LayoutContext context,
                                              int alignment) {
           MinOptMax ipd;
  @@ -158,15 +250,13 @@
           int lead = 0;
           int total = 0;
           int middle = 0;
  -        switch (alignment) {
  +        switch (verticalAlignment) {
               case VerticalAlign.MIDDLE  : middle = bpd / 2 ;
  -                                         lead = bpd / 2 ;
  -                                         break;
  -            case VerticalAlign.TOP     : total = bpd;
                                            break;
  +            case VerticalAlign.TOP     : // fall through
               case VerticalAlign.BOTTOM  : total = bpd;
                                            break;
  -            case VerticalAlign.BASELINE:
  +            case VerticalAlign.BASELINE: // fall through
               default:                     lead = bpd;
                                            break;
           }
  
  
  
  1.11      +10 -64    xml-fop/src/java/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java
  
  Index: LeafNodeLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- LeafNodeLayoutManager.java	20 Oct 2004 13:41:06 -0000	1.10
  +++ LeafNodeLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.11
  @@ -33,12 +33,13 @@
    * This class can be extended to handle the creation and adding of the
    * inline area.
    */
  -public class LeafNodeLayoutManager extends AbstractLayoutManager {
  +public class LeafNodeLayoutManager extends AbstractLayoutManager 
  +                                   implements InlineLevelLayoutManager {
       /**
        * The inline area that this leafnode will add.
        */
       protected InlineArea curArea = null;
  -    protected int alignment;
  +    protected int verticalAlignment;
       private int lead;
       private MinOptMax ipd;
   
  @@ -116,7 +117,7 @@
        * @param al the vertical alignment positioning
        */
       public void setAlignment(int al) {
  -        alignment = al;
  +        verticalAlignment = al;
       }
   
       /**
  @@ -147,49 +148,6 @@
       }
   
       /**
  -     * Get the next break position.
  -     * Since this holds an inline area it will return a single
  -     * break position.
  -     * @param context the layout context for this inline area
  -     * @return the break poisition for adding this inline area
  -     */
  -    public BreakPoss getNextBreakPoss(LayoutContext context) {
  -        curArea = get(context);
  -        if (curArea == null) {
  -            setFinished(true);
  -            return null;
  -        }
  -        BreakPoss bp = new BreakPoss(new LeafPosition(this, 0),
  -                                     BreakPoss.CAN_BREAK_AFTER
  -                                     | BreakPoss.CAN_BREAK_BEFORE | BreakPoss.ISFIRST
  -                                     | BreakPoss.ISLAST);
  -        ipd = getAllocationIPD(context.getRefIPD());
  -        bp.setStackingSize(ipd);
  -        bp.setNonStackingSize(new MinOptMax(curArea.getBPD()));
  -        bp.setTrailingSpace(new SpaceSpecifier(false));
  -
  -        int bpd = curArea.getBPD();
  -        switch (alignment) {
  -            case VerticalAlign.MIDDLE:
  -                bp.setMiddle(bpd / 2 /* - fontLead/2 */);
  -                bp.setLead(bpd / 2 /* + fontLead/2 */);
  -            break;
  -            case VerticalAlign.TOP:
  -                bp.setTotal(bpd);
  -            break;
  -            case VerticalAlign.BOTTOM:
  -                bp.setTotal(bpd);
  -            break;
  -            case VerticalAlign.BASELINE:
  -            default:
  -                bp.setLead(bpd);
  -            break;
  -        }
  -        setFinished(true);
  -        return bp;
  -    }
  -
  -    /**
        * Get the allocation ipd of the inline area.
        * This method may be overridden to handle percentage values.
        * @param refIPD the ipd of the parent reference area
  @@ -200,19 +158,6 @@
       }
   
       /**
  -     * Reset the position.
  -     * If the reset position is null then this inline area should be
  -     * restarted.
  -     * @param resetPos the position to reset.
  -     */
  -    public void resetPosition(Position resetPos) {
  -        // only reset if setting null, start again
  -        if (resetPos == null) {
  -            setFinished(false);
  -        }
  -    }
  -
  -    /**
        * Add the area for this layout manager.
        * This adds the single inline area to the parent.
        * @param posIter the position iterator
  @@ -244,9 +189,9 @@
        */
       protected void offsetArea(LayoutContext context) {
           int bpd = curArea.getBPD();
  -        switch (alignment) {
  +        switch (verticalAlignment) {
               case VerticalAlign.MIDDLE:
  -                curArea.setOffset(context.getBaseline() - bpd / 2 /* - fontLead/2 */);
  +                curArea.setOffset(context.getMiddleBaseline() - bpd / 2);
               break;
               case VerticalAlign.TOP:
                   //curArea.setOffset(0);
  @@ -305,7 +250,7 @@
           int lead = 0;
           int total = 0;
           int middle = 0;
  -        switch (alignment) {
  +        switch (verticalAlignment) {
               case VerticalAlign.MIDDLE  : middle = bpd / 2 ;
                                            lead = bpd / 2 ;
                                            break;
  @@ -331,6 +276,9 @@
           return returnList;
       }
   
  +    public void getWordChars(StringBuffer sbChars, Position bp) {
  +    }
  +
       public KnuthElement addALetterSpaceTo(KnuthElement element) {
           // return the unchanged box object
           return new KnuthBox(areaInfo.ipdArea.opt, areaInfo.lead,
  @@ -339,8 +287,6 @@
       }
   
       public void hyphenate(Position pos, HyphContext hc) {
  -        // use the AbstractLayoutManager.hyphenate() null implementation
  -        super.hyphenate(pos, hc);
       }
   
       public boolean applyChanges(List oldList) {
  
  
  
  1.33      +107 -127  xml-fop/src/java/org/apache/fop/layoutmgr/LineLayoutManager.java
  
  Index: LineLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/LineLayoutManager.java,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- LineLayoutManager.java	11 Nov 2004 08:11:07 -0000	1.32
  +++ LineLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.33
  @@ -58,7 +58,7 @@
        * @param l the default lead, from top to baseline
        * @param f the default follow, from baseline to bottom
        */
  -    public LineLayoutManager(Block node, int lh, int l, int f) {
  +    public LineLayoutManager(Block node, int lh, int l, int f, int ms) {
           super(node);
           fobj = node;
           // the child FObj are owned by the parent BlockLM
  @@ -67,6 +67,7 @@
           lineHeight = lh;
           lead = l;
           follow = f;
  +        middleShift = ms;
           initialize(); // Normally done when started by parent!
       }
   
  @@ -126,6 +127,8 @@
       private int lineHeight;
       private int lead;
       private int follow;
  +    // offset of the middle baseline with respect to the main baseline
  +    private int middleShift;
   
       // inline start pos when adding areas
       private int iStartPos = 0;
  @@ -151,6 +154,11 @@
       // suggested modification to the "optimum" number of lines
       private int looseness = 0;
   
  +    // this constant is used to create elements when text-align is center:
  +    // every TextLM descendant of LineLM must use the same value, 
  +    // otherwise the line breaking algorithm does not find the right
  +    // break point
  +    public static final int DEFAULT_SPACE_WIDTH = 3336;
       private static final int INFINITE_RATIO = 1000;
   
       // this class represent a feasible breaking point
  @@ -272,10 +280,10 @@
       // which was the first element in the paragraph
       // returned by each LM
       private class Update {
  -        private LayoutManager inlineLM;
  +        private InlineLevelLayoutManager inlineLM;
           private int iFirstIndex;
   
  -        public Update(LayoutManager lm, int index) {
  +        public Update(InlineLevelLayoutManager lm, int index) {
               inlineLM = lm;
               iFirstIndex = index;
           }
  @@ -288,28 +296,19 @@
           public int ignoreAtEnd = 0;
           // minimum space at the end of the last line (in millipoints)
           public int lineFillerWidth;
  -        // word space dimension (in millipoints)
  -        private int wordSpaceIPD;
   
           public void startParagraph(int lineWidth) {
  -            // get the word space dimension, which needs to be known
  -            // in order to center text
  -            LayoutManager lm;
  -            if ((lm = getChildLM()) != null) {
  -                wordSpaceIPD = lm.getWordSpaceIPD();
  -            }
  -
               // set the minimum amount of empty space at the end of the
               // last line
               if (bTextAlignment == CENTER) {
                   lineFillerWidth = 0; 
               } else {
  -                lineFillerWidth = (int)(lineWidth / 6); 
  +                lineFillerWidth = (int)(lineWidth / 12); 
               }
   
               // add auxiliary elements at the beginning of the paragraph
               if (bTextAlignment == CENTER && bTextAlignmentLast != JUSTIFY) {
  -                this.add(new KnuthGlue(0, 3 * wordSpaceIPD, 0,
  +                this.add(new KnuthGlue(0, 3 * DEFAULT_SPACE_WIDTH, 0,
                                          null, false));
                   ignoreAtStart ++;
               }
  @@ -333,7 +332,7 @@
               if (this.size() > ignoreAtStart) {
                   if (bTextAlignment == CENTER
                       && bTextAlignmentLast != JUSTIFY) {
  -                    this.add(new KnuthGlue(0, 3 * wordSpaceIPD, 0,
  +                    this.add(new KnuthGlue(0, 3 * DEFAULT_SPACE_WIDTH, 0,
                                              null, false));
                       this.add(new KnuthPenalty(0, -KnuthElement.INFINITE,
                                                 false, null, false));
  @@ -371,7 +370,7 @@
       public BreakPoss getNextBreakPoss(LayoutContext context) {
           // Get a break from currently active child LM
           // Set up constraints for inline level managers
  -        LayoutManager curLM ; // currently active LM
  +        InlineLevelLayoutManager curLM ; // currently active LM
           BreakPoss prev = null;
           BreakPoss bp = null; // proposed BreakPoss
   
  @@ -407,57 +406,66 @@
   
               Paragraph knuthPar = new Paragraph();
               knuthPar.startParagraph(availIPD.opt);
  -            while ((curLM = getChildLM()) != null) {
  +            while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
                   if ((returnedList
                        = curLM.getNextKnuthElements(inlineLC,
                                                     effectiveAlignment))
                       != null) {
  -                    // if there are two consecutive KnuthBox, the first one 
  -                    // does not represent a whole word, so it must be given
  -                    // one more letter space
  +                    // look at the first element
                       thisElement = (KnuthElement) returnedList.getFirst();
  -                    if (returnedList.size() > 1
  -                        || !(thisElement.isPenalty()
  -                             && ((KnuthPenalty) thisElement).getP()
  -                             == -KnuthElement.INFINITE)) {
  -                        if (thisElement.isBox() && !thisElement.isAuxiliary()
  -                            && bPrevWasKnuthBox) {
  -                            prevBox = (KnuthBox) knuthPar.removeLast();
  -                            if (!prevBox.isAuxiliary()) {
  -                                // if letter spacing is constant,
  -                                // only prevBox needs to be replaced;
  -                                knuthPar.addLast(prevBox.getLayoutManager()
  -                                                 .addALetterSpaceTo(prevBox));
  -                            } else {
  -                                // prevBox is the last element
  -                                // in the sub-sequence
  -                                //   <box> <aux penalty> <aux glue> <aux box>
  -                                // the letter space is added to <aux glue>,
  -                                // while the other elements are not changed
  -                                KnuthBox auxBox = prevBox;
  -                                KnuthGlue auxGlue
  -                                    = (KnuthGlue) knuthPar.removeLast();
  -                                KnuthPenalty auxPenalty
  -                                    = (KnuthPenalty) knuthPar.removeLast();
  -                                prevBox = (KnuthBox) knuthPar.getLast();
  -                                knuthPar.addLast(auxPenalty);
  -                                knuthPar.addLast(prevBox.getLayoutManager()
  -                                                 .addALetterSpaceTo(prevBox));
  -                                knuthPar.addLast(auxBox);
  -                }
  -                        }
  -                        if (((KnuthElement) returnedList.getLast()).isBox()) {
  -                            bPrevWasKnuthBox = true;
  +                    if (thisElement.isBox() && !thisElement.isAuxiliary()
  +                        && bPrevWasKnuthBox) {
  +                        prevBox = (KnuthBox) knuthPar.removeLast();
  +                        // if there are two consecutive KnuthBoxes the
  +                        // first one does not represent a whole word,
  +                        // so it must be given one more letter space
  +                        if (!prevBox.isAuxiliary()) {
  +                            // if letter spacing is constant,
  +                            // only prevBox needs to be replaced;
  +                            knuthPar.addLast(((InlineLevelLayoutManager)
  +                                              prevBox.getLayoutManager())
  +                                             .addALetterSpaceTo(prevBox));
                           } else {
  -                            bPrevWasKnuthBox = false;
  +                            // prevBox is the last element
  +                            // in the sub-sequence
  +                            //   <box> <aux penalty> <aux glue> <aux box>
  +                            // the letter space is added to <aux glue>,
  +                            // while the other elements are not changed
  +                            KnuthBox auxBox = prevBox;
  +                            KnuthGlue auxGlue
  +                                = (KnuthGlue) knuthPar.removeLast();
  +                            KnuthPenalty auxPenalty
  +                                = (KnuthPenalty) knuthPar.removeLast();
  +                            prevBox = (KnuthBox) knuthPar.getLast();
  +                            knuthPar.addLast(auxPenalty);
  +                            knuthPar.addLast(((InlineLevelLayoutManager)
  +                                              prevBox.getLayoutManager())
  +                                             .addALetterSpaceTo(prevBox));
  +                            knuthPar.addLast(auxBox);
                           }
  -                        // add the new elements to the paragraph
  -                        knuthPar.addAll(returnedList);
  +                    }
  +
  +                    // look at the last element
  +                    KnuthElement lastElement = (KnuthElement) returnedList.getLast();
  +                    boolean bForceLinefeed = false;
  +                    if (lastElement.isBox()) {
  +                        bPrevWasKnuthBox = true;
                       } else {
  -                        // a list with a single penalty item
  -                        // whose value is -inf
  -                        // represents a preserved linefeed,
  -                        // wich forces a line break
  +                        bPrevWasKnuthBox = false;
  +                        if (lastElement.isPenalty()
  +                            && ((KnuthPenalty) lastElement).getP()
  +                                == -KnuthPenalty.INFINITE) {
  +                            // a penalty item whose value is -inf
  +                            // represents a preserved linefeed,
  +                            // wich forces a line break
  +                            bForceLinefeed = true;
  +                            returnedList.removeLast();
  +                        }
  +                    }
  +
  +                    // add the new elements to the paragraph
  +                    knuthPar.addAll(returnedList);
  +                    if (bForceLinefeed) {
                           knuthPar.endParagraph();
                           knuthPar = new Paragraph();
                           knuthPar.startParagraph(availIPD.opt);
  @@ -467,7 +475,7 @@
                       // curLM returned null; this can happen
                       // if it has nothing more to layout,
                       // so just iterate once more to see
  -                    // if there are other chilren
  +                    // if there are other children
                   }
               }
               knuthPar.endParagraph();
  @@ -647,53 +655,11 @@
               double ratio = (textAlign == JUSTIFY)
                   ? bestActiveNode.adjustRatio : 0;
   
  -            // lead to baseline is
  -            // max of: baseline fixed alignment and middle/2
  -            // after baseline is
  -            // max: top height-lead, middle/2 and bottom height-lead
  -            int halfLeading = (lineHeight - lead - follow) / 2;
  -            // height before baseline
  -            int lineLead = lead + halfLeading;
  -            // maximum size of top and bottom alignment
  -            int maxtb = follow + halfLeading;
  -            // max size of middle alignment below baseline
  -            int middlefollow = maxtb;
  -
  -            // index of the first KnuthElement in this line
  -            int firstElementIndex = 0;
  -            if (line > 1) {
  -                firstElementIndex = bestActiveNode.previous.position + 1;
  -            }
  -            ListIterator inlineIterator = par.listIterator(firstElementIndex);
  -            for (int j = 0;
  -                 j < (bestActiveNode.position - firstElementIndex + 1);
  -                 j++) {
  -                KnuthElement element = (KnuthElement) inlineIterator.next();
  -                if (element.isBox()) {
  -                    if (((KnuthBox) element).getLead() > lineLead) {
  -                        lineLead = ((KnuthBox) element).getLead();
  -                    }
  -                    if (((KnuthBox) element).getTotal() > maxtb) {
  -                        maxtb = ((KnuthBox) element).getTotal();
  -                    }
  -                    if (((KnuthBox) element).getMiddle() > middlefollow) {
  -                        middlefollow = ((KnuthBox) element).getMiddle();
  -                    }
  -                }
  -            }
  -
  -            if (maxtb - lineLead > middlefollow) {
  -                middlefollow = maxtb - lineLead;
  -            }
  -
  -            // add nodes at the beginning of the list, as they are found
  -            // backwards, from the last one to the first one
  -            breakpoints.add(0,
  -                            new LineBreakPosition(this,
  +            makeLineBreakPosition(par,
  +                                  (i > 1 ? bestActiveNode.previous.position + 1: 0),
                                                     bestActiveNode.position,
  -                                                  ratio, 0, indent,
  -                                                  lineLead + middlefollow,
  -                                                  lineLead));
  +                                  0, ratio, indent);
  +
               bestActiveNode = bestActiveNode.previous;
           }
           if (bForced) {
  @@ -705,22 +671,29 @@
       }
   
       private void fallback(Paragraph par, int line) {
  -        // lead to baseline is
  -        // max of: baseline fixed alignment and middle/2
  -        // after baseline is
  -        // max: top height-lead, middle/2 and bottom height-lead
  +        makeLineBreakPosition(par,
  +                              lastDeactivatedNode.position,
  +                              par.size() - 1,
  +                              line, 0, 0);
  +    }
  +
  +    private void makeLineBreakPosition(Paragraph par,
  +                                       int firstElementIndex, int lastElementIndex,
  +                                       int insertIndex, double ratio, int indent) {
  +        // line height calculation
  +
           int halfLeading = (lineHeight - lead - follow) / 2;
  -        // height before baseline
  +        // height above the main baseline
           int lineLead = lead + halfLeading;
           // maximum size of top and bottom alignment
           int maxtb = follow + halfLeading;
  -        // max size of middle alignment below baseline
  +        // max size of middle alignment above and below the middle baseline
           int middlefollow = maxtb;
   
           ListIterator inlineIterator
  -            = par.listIterator(lastDeactivatedNode.position);
  -        for (int j = lastDeactivatedNode.position;
  -             j < (par.size());
  +            = par.listIterator(firstElementIndex);
  +        for (int j = firstElementIndex;
  +             j <= lastElementIndex;
                j++) {
               KnuthElement element = (KnuthElement) inlineIterator.next();
               if (element.isBox()) {
  @@ -730,8 +703,13 @@
                   if (((KnuthBox) element).getTotal() > maxtb) {
                       maxtb = ((KnuthBox) element).getTotal();
                   }
  -                if (((KnuthBox) element).getMiddle() > middlefollow) {
  -                    middlefollow = ((KnuthBox) element).getMiddle();
  +                if (((KnuthBox) element).getMiddle() > lineLead + middleShift) {
  +                    lineLead += ((KnuthBox) element).getMiddle()
  +                                - lineLead - middleShift;
  +                }
  +                if (((KnuthBox) element).getMiddle() > middlefollow - middleShift) {
  +                    middlefollow += ((KnuthBox) element).getMiddle()
  +                                    - middlefollow + middleShift;
                   }
               }
           }
  @@ -740,14 +718,14 @@
                       middlefollow = maxtb - lineLead;
           }
   
  -        breakpoints.add(line,
  -                        new LineBreakPosition(this, par.size() - 1,
  -                                              0, 0, 0,
  +        breakpoints.add(insertIndex,
  +                        new LineBreakPosition(this,
  +                                              lastElementIndex ,
  +                                              ratio, 0, indent,
                                                 lineLead + middlefollow,
                                                 lineLead));
       }
   
  -
       private void considerLegalBreak(LinkedList par, int lineWidth,
                                       KnuthElement element,
                                       int totalWidth, int totalStretch,
  @@ -969,8 +947,8 @@
           LinkedList updateList = new LinkedList();
           KnuthElement firstElement = null;
           KnuthElement nextElement = null;
  -        // current TextLayoutManager
  -        LayoutManager currLM = null;
  +        // current InlineLevelLayoutManager
  +        InlineLevelLayoutManager currLM = null;
           // number of KnuthBox elements containing word fragments
           int boxCount;
           // number of auxiliary KnuthElements between KnuthBoxes
  @@ -982,7 +960,7 @@
               firstElement = (KnuthElement) currParIterator.next();
               // 
               if (firstElement.getLayoutManager() != currLM) {
  -                currLM = firstElement.getLayoutManager();
  +                currLM = (InlineLevelLayoutManager) firstElement.getLayoutManager();
                   if (currLM != null) { 
                       updateList.add(new Update(currLM, currParIterator.previousIndex()));
                   } else {
  @@ -1003,7 +981,7 @@
                       if (nextElement.isBox() && !nextElement.isAuxiliary()) {
                           // a non-auxiliary KnuthBox: append word chars
                           if (currLM != nextElement.getLayoutManager()) {
  -                            currLM = nextElement.getLayoutManager();
  +                            currLM = (InlineLevelLayoutManager) nextElement.getLayoutManager();
                               updateList.add(new Update(currLM, currParIterator.previousIndex()));
                           }
                           // append text to recreate the whole word
  @@ -1031,7 +1009,8 @@
                       for (int i = 0; i < (boxCount + auxCount); i++) {
                           element = (KnuthElement) currParIterator.next();
                           if (element.isBox() && !element.isAuxiliary()) {
  -                            element.getLayoutManager().hyphenate(element.getPosition(), hc);
  +                            ((InlineLevelLayoutManager)
  +                             element.getLayoutManager()).hyphenate(element.getPosition(), hc);
                           } else {
                               // nothing to do, element is an auxiliary KnuthElement
                           }
  @@ -1065,7 +1044,7 @@
   
               // applyChanges() returns true if the LM modifies its data,
               // so it must return new KnuthElements to replace the old ones
  -            if (currUpdate.inlineLM
  +            if (((InlineLevelLayoutManager) currUpdate.inlineLM)
                   .applyChanges(currPar.subList(fromIndex + iAddedElements,
                                                 toIndex + iAddedElements))) {
                   // insert the new KnuthElements
  @@ -1415,6 +1394,7 @@
               lineArea.setBPD(lbp.lineHeight);
               lc.setBaseline(lbp.baseline);
               lc.setLineHeight(lbp.lineHeight);
  +            lc.setMiddleShift(middleShift);
               setCurrentArea(lineArea);
   
               Paragraph currPar = (Paragraph) knuthParagraphs.get(iCurrParIndex);
  
  
  
  1.15      +2 -1      xml-fop/src/java/org/apache/fop/layoutmgr/RetrieveMarkerLayoutManager.java
  
  Index: RetrieveMarkerLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/RetrieveMarkerLayoutManager.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- RetrieveMarkerLayoutManager.java	28 Oct 2004 10:00:25 -0000	1.14
  +++ RetrieveMarkerLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.15
  @@ -73,7 +73,8 @@
           if (replaceLM == null) {
               return null;
           }
  -        return replaceLM.getNextKnuthElements(context, alignment);
  +        return ((InlineLevelLayoutManager) replaceLM)
  +               .getNextKnuthElements(context, alignment);
       }
   
       public void addAreas(PositionIterator parentIter,
  
  
  
  1.26      +80 -26    xml-fop/src/java/org/apache/fop/layoutmgr/TextLayoutManager.java
  
  Index: TextLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/TextLayoutManager.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- TextLayoutManager.java	20 Oct 2004 13:41:06 -0000	1.25
  +++ TextLayoutManager.java	13 Nov 2004 20:37:17 -0000	1.26
  @@ -24,6 +24,7 @@
   import java.util.ListIterator;
   
   import org.apache.fop.fo.FOText;
  +import org.apache.fop.fo.flow.Inline;
   import org.apache.fop.fonts.Font;
   import org.apache.fop.traits.SpaceVal;
   import org.apache.fop.area.Trait;
  @@ -36,7 +37,8 @@
    * LayoutManager for text (a sequence of characters) which generates one
    * or more inline areas.
    */
  -public class TextLayoutManager extends AbstractLayoutManager {
  +public class TextLayoutManager extends AbstractLayoutManager
  +                               implements InlineLevelLayoutManager {
   
       /**
        * Store information about each potential text area.
  @@ -117,6 +119,12 @@
       private short iTempStart = 0;
       private LinkedList changeList = null;
   
  +    private int textHeight;
  +    private int lead = 0;
  +    private int total = 0;
  +    private int middle = 0;
  +    private int verticalAlignment = VerticalAlign.BASELINE;
  +
       /**
        * Create a Text layout manager.
        *
  @@ -155,6 +163,26 @@
           // in the SpaceVal.makeWordSpacing() method
           letterSpaceIPD = ls.getSpace();
           wordSpaceIPD = MinOptMax.add(new MinOptMax(spaceCharIPD), ws.getSpace());
  +
  +        // set text height
  +        textHeight = fs.getAscender()
  +                     - fs.getDescender();
  +
  +        // if the text node is son of an inline, set vertical align
  +        if (foText.getParent() instanceof Inline) {
  +            setAlignment(((Inline) foText.getParent()).getVerticalAlign());
  +        }
  +        switch (verticalAlignment) {
  +            case VerticalAlign.MIDDLE  : middle = textHeight / 2 ;
  +                                         break;
  +            case VerticalAlign.TOP     : // fall through
  +            case VerticalAlign.BOTTOM  : total = textHeight;
  +                                         break;
  +            case VerticalAlign.BASELINE: // fall through
  +            default                    : lead = fs.getAscender();
  +                                         total = textHeight;
  +                                         break;
  +        }
       }
   
       /**
  @@ -458,8 +486,8 @@
            * used for calculating the bpd of the line area containing
            * this text.
            */
  -        //bp.setDescender(foText.textInfo.fs.getDescender());
  -        //bp.setAscender(foText.textInfo.fs.getAscender());
  +        //bp.setDescender(fs.getDescender());
  +        //bp.setAscender(fs.getAscender());
           if (iNextStart == textArray.length) {
               flags |= BreakPoss.ISLAST;
               setFinished(true);
  @@ -574,7 +602,7 @@
           iTotalAdjust += (iWordSpaceDim - wordSpaceIPD.opt) * iWScount;
   
           TextArea t = createTextArea(str, realWidth.opt + iTotalAdjust,
  -                                    context.getBaseline());
  +                                    context);
   
           // iWordSpaceDim is computed in relation to wordSpaceIPD.opt
           // but the renderer needs to know the adjustment in relation
  @@ -606,12 +634,26 @@
        * @param base the baseline position
        * @return the new word area
        */
  -    protected TextArea createTextArea(String str, int width, int base) {
  +    protected TextArea createTextArea(String str, int width, LayoutContext context) {
           TextArea textArea = new TextArea();
           textArea.setIPD(width);
           textArea.setBPD(fs.getAscender() - fs.getDescender());
  -        textArea.setOffset(fs.getAscender());
  -        textArea.setOffset(base);
  +        int bpd = textArea.getBPD();
  +        switch (verticalAlignment) {
  +            case VerticalAlign.MIDDLE:
  +                textArea.setOffset(context.getMiddleBaseline() + fs.getXHeight() / 2);
  +            break;
  +            case VerticalAlign.TOP:
  +                textArea.setOffset(fs.getAscender());
  +            break;
  +            case VerticalAlign.BOTTOM:
  +                textArea.setOffset(context.getLineHeight() - bpd + fs.getAscender());
  +            break;
  +            case VerticalAlign.BASELINE:
  +            default:
  +                textArea.setOffset(context.getBaseline());
  +            break;
  +        }
   
           textArea.setTextArea(str);
           textArea.addTrait(Trait.FONT_NAME, fs.getFontName());
  @@ -620,13 +662,29 @@
           return textArea;
       }
   
  +    /**
  +     * Set the alignment of the inline area.
  +     * @param al the vertical alignment positioning
  +     */
  +    public void setAlignment(int al) {
  +        verticalAlignment = al;
  +    }
  +
       public LinkedList getNextKnuthElements(LayoutContext context,
                                              int alignment) {
           LinkedList returnList = new LinkedList();
   
           while (iNextStart < textArray.length) {
  -            if (textArray[iNextStart] == SPACE) {
  +            if (textArray[iNextStart] == SPACE
  +                || textArray[iNextStart] == NBSPACE) {
                   // normal, breaking space
  +                // or non-breaking space
  +                if (textArray[iNextStart] == NBSPACE) {
  +                    returnList.add
  +                        (new KnuthPenalty(0, KnuthElement.INFINITE, false,
  +                                          new LeafPosition(this, vecAreaInfo.size() - 1),
  +                                          false));
  +                }
                   switch (alignment) {
                   case CENTER :
                       vecAreaInfo.add
  @@ -634,14 +692,14 @@
                                         (short) 1, (short) 0,
                                         wordSpaceIPD, false));
                       returnList.add
  -                        (new KnuthGlue(0, 3 * wordSpaceIPD.opt, 0,
  +                        (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
                                          new LeafPosition(this, vecAreaInfo.size() - 1), false));
                       returnList.add
                           (new KnuthPenalty(0, 0, false,
                                             new LeafPosition(this, -1), true));
                       returnList.add
                           (new KnuthGlue(wordSpaceIPD.opt,
  -                                       - 6 * wordSpaceIPD.opt, 0,
  +                                       - 6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
                                          new LeafPosition(this, -1), true));
                       returnList.add
                           (new KnuthBox(0, 0, 0, 0,
  @@ -650,7 +708,7 @@
                           (new KnuthPenalty(0, KnuthElement.INFINITE, false,
                                             new LeafPosition(this, -1), true));
                       returnList.add
  -                        (new KnuthGlue(0, 3 * wordSpaceIPD.opt, 0,
  +                        (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
                                          new LeafPosition(this, -1), true));
                       iNextStart ++;
                       break;
  @@ -715,8 +773,7 @@
                   iNextStart ++;
               } else if (textArray[iNextStart] == NEWLINE) {
                   // linefeed; this can happen when linefeed-treatment="preserve"
  -                // the linefeed character is the first one in textArray,
  -                // so we can just return a list with a penalty item
  +                // add a penalty item to the list and return
                   returnList.add
                       (new KnuthPenalty(0, -KnuthElement.INFINITE,
                                         false, null, false));
  @@ -747,14 +804,15 @@
                       // constant letter space; simply return a box
                       // whose width includes letter spaces
                       returnList.add
  -                        (new KnuthBox(wordIPD.opt, 0, 0, 0,
  +                        (new KnuthBox(wordIPD.opt, lead, total, middle,
                                         new LeafPosition(this, vecAreaInfo.size() - 1), false));
                       iNextStart = iTempStart;
                   } else {
                       // adjustable letter space;
                       // some other KnuthElements are needed
                       returnList.add
  -                        (new KnuthBox(wordIPD.opt - (iTempStart - iThisStart - 1) * letterSpaceIPD.opt, 0, 0, 0,
  +                        (new KnuthBox(wordIPD.opt - (iTempStart - iThisStart - 1) * letterSpaceIPD.opt,
  +                                      lead, total, middle,
                                         new LeafPosition(this, vecAreaInfo.size() - 1), false));
                       returnList.add
                           (new KnuthPenalty(0, KnuthElement.INFINITE, false,
  @@ -765,7 +823,7 @@
                                          (iTempStart - iThisStart - 1) * (letterSpaceIPD.opt - letterSpaceIPD.min),
                                          new LeafPosition(this, -1), true));
                       returnList.add
  -                        (new KnuthBox(0, 0, 0, 0,
  +                        (new KnuthBox(0, lead, total, middle,
                                         new LeafPosition(this, -1), true));
                       iNextStart = iTempStart;
                   }
  @@ -779,17 +837,13 @@
           }
       }
   
  -    public int getWordSpaceIPD() {
  -        return wordSpaceIPD.opt;
  -    }
  -
       public KnuthElement addALetterSpaceTo(KnuthElement element) {
           LeafPosition pos = (LeafPosition) element.getPosition();
           AreaInfo ai = (AreaInfo) vecAreaInfo.get(pos.getLeafPos());
           ai.iLScount ++;
           ai.ipdArea.add(letterSpaceIPD);
           if (letterSpaceIPD.min == letterSpaceIPD.max) {
  -            return new KnuthBox(ai.ipdArea.opt, 0, 0, 0, pos, false);
  +            return new KnuthBox(ai.ipdArea.opt, lead, total, middle, pos, false);
           } else {
               return new KnuthGlue(ai.iLScount * letterSpaceIPD.opt,
                                    ai.iLScount * (letterSpaceIPD.max - letterSpaceIPD.opt),
  @@ -908,13 +962,13 @@
                   // ai refers either to a word or a word fragment
                   if (letterSpaceIPD.min == letterSpaceIPD.max) {
                       returnList.add
  -                        (new KnuthBox(ai.ipdArea.opt, 0, 0, 0,
  +                        (new KnuthBox(ai.ipdArea.opt, lead, total, middle,
                                         new LeafPosition(this, iReturnedIndex), false));
                   } else {
                       returnList.add
                           (new KnuthBox(ai.ipdArea.opt
                                         - ai.iLScount * letterSpaceIPD.opt,
  -                                      0, 0, 0, 
  +                                      lead, total, middle, 
                                         new LeafPosition(this, iReturnedIndex), false));
                       returnList.add
                           (new KnuthPenalty(0, KnuthElement.INFINITE, false,
  @@ -939,14 +993,14 @@
                   switch (alignment) {
                   case CENTER :
                       returnList.add
  -                        (new KnuthGlue(0, 3 * wordSpaceIPD.opt, 0,
  +                        (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
                                          new LeafPosition(this, iReturnedIndex), false));
                       returnList.add
                           (new KnuthPenalty(0, 0, false,
                                             new LeafPosition(this, -1), true));
                       returnList.add
                           (new KnuthGlue(wordSpaceIPD.opt,
  -                                       - 6 * wordSpaceIPD.opt, 0,
  +                                       - 6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
                                          new LeafPosition(this, -1), true));
                       returnList.add
                           (new KnuthBox(0, 0, 0, 0,
  @@ -955,7 +1009,7 @@
                           (new KnuthPenalty(0, KnuthElement.INFINITE, false,
                                             new LeafPosition(this, -1), true));
                       returnList.add
  -                        (new KnuthGlue(0, 3 * wordSpaceIPD.opt, 0,
  +                        (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
                                          new LeafPosition(this, -1), true));
                       iReturnedIndex ++;
                       break;
  
  
  
  1.1                  xml-fop/src/java/org/apache/fop/layoutmgr/InlineLevelLayoutManager.java
  
  Index: InlineLevelLayoutManager.java
  ===================================================================
  /*
   * Copyright 2004 The Apache Software Foundation.
   * 
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  /* $Id: InlineLevelLayoutManager.java,v 1.1 2004/11/13 20:37:17 spepping Exp $ */
   
  package org.apache.fop.layoutmgr;
  
  import java.util.LinkedList;
  import java.util.List;
  
  /**
   * The interface for LayoutManagers which generate inline areas
   */
  public interface InlineLevelLayoutManager extends LayoutManager {
  
      /**
       * Get a sequence of KnuthElements representing the content 
       * of the node assigned to the LM
       * 
       * @param context   the LayoutContext used to store layout information
       * @param alignment the desired text alignement
       * @return          the list of KnuthElements
       */
      LinkedList getNextKnuthElements(LayoutContext context, int alignment);
  
      /**
       * Tell the LM to modify its data, adding a letter space 
       * to the word fragment represented by the given element,
       * and returning a corrected element
       *
       * @param element the element which must be given one more letter space
       * @return        the new element replacing the old one
       */
      KnuthElement addALetterSpaceTo(KnuthElement element);
  
      /**
       * Get the word chars corresponding to the given position
       *
       * @param sbChars the StringBuffer used to append word chars
       * @param pos     the Position referring to the needed word chars
       */
      void getWordChars(StringBuffer sbChars, Position pos);
  
      /**
       * Tell the LM to hyphenate a word
       *
       * @param pos the Position referring to the word
       * @param hc  the HyphContext storing hyphenation information
       */
      void hyphenate(Position pos, HyphContext hc);
  
      /**
       * Tell the LM to apply the changes due to hyphenation
       *
       * @param oldList the list of the old elements the changes refer to
       * @return        true if the LM had to change its data, false otherwise
       */
      boolean applyChanges(List oldList);
  
      /**
       * Get a sequence of KnuthElements representing the content 
       * of the node assigned to the LM, after changes have been applied
       *
       * @param oldList        the elements to replace
       * @param flaggedPenalty the penalty value for hyphenated lines
       * @param alignment      the desired text alignment
       * @return               the updated list of KnuthElements
       */
      LinkedList getChangedKnuthElements(List oldList, int flaggedPenalty,
                                         int alignment);
  }
  
  
  

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