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 kl...@apache.org on 2002/05/13 08:12:43 UTC

cvs commit: xml-fop/src/org/apache/fop/layoutmgr BreakCost.java InlineStackingBPLayoutManager.java LayoutContext.java LineBPLayoutManager.java TextBPLayoutManager.java

klease      02/05/12 23:12:43

  Modified:    src/org/apache/fop/layoutmgr BreakCost.java
                        InlineStackingBPLayoutManager.java
                        LayoutContext.java LineBPLayoutManager.java
                        TextBPLayoutManager.java
  Log:
  Refactor Line and InlineStacking; correct and extend space-handling code
  
  Revision  Changes    Path
  1.3       +16 -2     xml-fop/src/org/apache/fop/layoutmgr/BreakCost.java
  
  Index: BreakCost.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/BreakCost.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BreakCost.java	8 Jan 2002 09:52:17 -0000	1.2
  +++ BreakCost.java	13 May 2002 06:12:42 -0000	1.3
  @@ -1,5 +1,5 @@
   /*
  - * $Id: BreakCost.java,v 1.2 2002/01/08 09:52:17 keiron Exp $
  + * $Id: BreakCost.java,v 1.3 2002/05/13 06:12:42 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -15,6 +15,7 @@
    */
   public class BreakCost {
       private Area breakArea;
  +    private BreakPoss bp;
   
       private int cost; // Will be more complicated than this!
   
  @@ -23,8 +24,21 @@
           this.cost = cost;
       }
   
  +    public BreakCost(BreakPoss bp, int cost) {
  +        this.bp = bp;
  +        this.cost = cost;
  +    }
  +
  +    BreakPoss getBP() {
  +        return this.bp;
  +    }
  +
       Area getArea() {
  -        return breakArea;
  +        return this.breakArea;
  +    }
  +
  +    int getCost() {
  +        return this.cost;
       }
   
       public BreakCost chooseLowest(BreakCost otherCost) {
  
  
  
  1.2       +179 -99   xml-fop/src/org/apache/fop/layoutmgr/InlineStackingBPLayoutManager.java
  
  Index: InlineStackingBPLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/InlineStackingBPLayoutManager.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InlineStackingBPLayoutManager.java	10 May 2002 12:38:15 -0000	1.1
  +++ InlineStackingBPLayoutManager.java	13 May 2002 06:12:42 -0000	1.2
  @@ -1,5 +1,5 @@
   /*
  - * $Id: InlineStackingBPLayoutManager.java,v 1.1 2002/05/10 12:38:15 klease Exp $
  + * $Id: InlineStackingBPLayoutManager.java,v 1.2 2002/05/13 06:12:42 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -18,6 +18,7 @@
   
   import java.util.Iterator;
   import java.util.ListIterator;
  +import java.util.HashMap;
   
   /**
    * LayoutManager for objects which stack children in the inline direction,
  @@ -58,12 +59,6 @@
   
   
       /**
  -     * Holds IPD of all areas which would be generated by previously
  -     * complete childLM since last area was generated.
  -     */
  -    private MinOptMax m_prevContentIPD = new MinOptMax(0);
  -
  -    /**
        * Size of any start or end borders and padding.
        */
       private MinOptMax m_allocIPD = new MinOptMax(0);
  @@ -73,23 +68,20 @@
        */
       private MinOptMax m_extraBPD;
   
  -    /** Holds IPD of a child BP which had no break-after flag. We don't
  -     * add this to m_previousIPD until we are sure that the next break
  -     * position can really fit.
  -     */
  -    private MinOptMax m_pendingIPD = new MinOptMax(0);
   
       private InlineProps m_inlineProps = null;
       private BorderAndPadding m_borderProps = null;
   
       private InlineParent m_inlineArea;
   
  -    private boolean m_bFirstArea;
       private BreakPoss m_prevBP;
  +    private LayoutContext m_childLC ;
  +
  +    /** Used to store previous content IPD for each child LM. */
  +    private HashMap m_hmPrevIPD = new HashMap();
   
       public InlineStackingBPLayoutManager(FObj fobj, ListIterator childLMiter) {
   	super(fobj, childLMiter);
  -	m_bFirstArea = true;
   	// Initialize inline properties (borders, padding, space)
   	// initProperties();
       }
  @@ -119,13 +111,13 @@
   	return new MinOptMax(iBP);
       }
   
  -    private boolean hasLeadingFence(boolean bNotFirst) {
  +    protected boolean hasLeadingFence(boolean bNotFirst) {
   	int iBP = m_borderProps.getPadding(BorderAndPadding.START, bNotFirst);
   	iBP += m_borderProps.getBorderWidth(BorderAndPadding.START, bNotFirst);
   	return (iBP > 0);
       }
       
  -    private boolean hasTrailingFence(boolean bNotLast) {
  +    protected boolean hasTrailingFence(boolean bNotLast) {
   	int iBP = m_borderProps.getPadding(BorderAndPadding.END, bNotLast);
   	iBP += m_borderProps.getBorderWidth(BorderAndPadding.END, bNotLast);
   	return (iBP > 0);
  @@ -139,13 +131,21 @@
   	if (wrappedPos != null) {
   	    // Back up the layout manager iterator
   	    reset(wrappedPos.m_childLM, wrappedPos.m_childPosition);
  +	    if (m_prevBP != null && 
  +		m_prevBP.getLayoutManager() !=wrappedPos.m_childLM) {
  +		m_childLC = null;
  +	    }
  +	    m_prevBP = new BreakPoss(wrappedPos.m_childLM,
  +				     wrappedPos.m_childPosition);
   	}
   	else {
  -	    // Backup to first child layout manager
  +	    // Backup to start of first child layout manager
   	    System.err.println("InlineStackingBPLM: resetPosition(null)");
  +	    m_prevBP = null;
   	    super.resetPosition(prevPos);
   	}
   	// Do we need to reset some context like pending or prevContent?
  +	// What about m_prevBP?
       }
   
   
  @@ -168,99 +168,119 @@
   	else return false; // ??? NO child LM?
       }
   
  +    protected MinOptMax getPrevIPD(LayoutManager lm) {
  +	return (MinOptMax)m_hmPrevIPD.get(lm);
  +    }
  +
  +    protected void clearPrevIPD() {
  +	m_hmPrevIPD.clear();
  +    }
  +
   
       public BreakPoss getNextBreakPoss(LayoutContext lc,
   				      BreakPoss.Position pbp) {
           // Get a break from currently active child LM
           BreakPoss bp =null;
   	BPLayoutManager curLM ;
  -	// Handle space before
  -	boolean bIncludeStartSpace=false;
  -	LayoutContext childLC = new LayoutContext(lc);
  -	if (lc.isStart()) {
  -	    // First call to this LM in new parent "area", ie, this may
  +	SpaceSpecifier leadingSpace = lc.getPendingSpace();
  +
  +	if (lc.startsNewArea()) {
  +	    // First call to this LM in new parent "area", but this may
   	    // not be the first area created by this inline
  +	    m_childLC = new LayoutContext(lc);
   	    lc.getPendingSpace().addSpace(m_inlineProps.spaceStart);
   	    // Check for "fence"
  -	    if (hasLeadingFence(!m_bFirstArea)) {
  -		bIncludeStartSpace=true;
  +	    if (hasLeadingFence(!lc.isFirstArea())) {
   		// Reset leading space sequence for child areas
  -		childLC.setPendingSpace(new SpaceSpecifier(false));
  +		leadingSpace = new SpaceSpecifier(false);
   	    }
   	    // Reset state variables
  -	    m_pendingIPD = new MinOptMax(0);
  -	    m_prevContentIPD = new MinOptMax(0);
  +	    clearPrevIPD(); // Clear stored prev content dimensions
   	}
  -	else {
  -	    // Handle pending IPD: if we are called again, we assume previous
  -	    // break was OK
  -	    m_prevContentIPD.add(m_pendingIPD);
  -	    m_pendingIPD = new MinOptMax(0);
  -	}
  -// 	    if (m_prevChildLM != curLM && m_prevChildLM != null) {
  -// 		// Change child LM
  -// 		m_prevContentIPD.add(m_pendingIPD);
  -// 	    }
   
  +	// We only do this loop more than once if a childLM returns
  +	// a null BreakPoss, meaning it has nothing (more) to layout.
           while ((curLM = getChildLM()) != null) {
  -	    // ????
  -	    /* If first break for this child, set START_AREA flag */
  -	    if (m_prevBP == null || m_prevBP.getLayoutManager()!=curLM) {
  -		childLC.setFlags(LayoutContext.START_AREA);
  -		if (m_prevBP != null) {
  -		    childLC.setPendingSpace(m_prevBP.getTrailingSpace());
  -		}
  -	    }
  +	    /* If first break for this child LM, set START_AREA flag 
  +	     * and initialize pending space from previous LM sibling's
  +	     * trailing space specifiers.
  +	     */
  +	    boolean bFirstChildBP = (m_prevBP == null ||
  +				     m_prevBP.getLayoutManager()!=curLM);
   
  -	    if (((bp = curLM.getNextBreakPoss(childLC)) != null)) {
  -		// && couldEndLine(bp)) {
  +	    initChildLC(m_childLC, m_prevBP, lc.startsNewArea(), bFirstChildBP,
  +			leadingSpace);
  +
  +	    if (((bp = curLM.getNextBreakPoss(m_childLC)) != null)) {
   		break;
   	    }
  -// 	    if (bp.isLastArea()) {
  -// 		// NORMALLY IT MUST BE!
  -// 		m_pendingIPD.add(bp.getStackingSize());
  -// 		m_prevBP = bp;
  -// 	    }
  +	    // If LM has no content, should it generate any area? If not,
  +	    // should trailing space from a previous area interact with
  +	    // leading space from a following area?
           }
           if (bp==null) {
   	    setFinished(true);
  -            return null; // There was no childLM
  +            return null; // There was no childLM with anything to layout
               // Alternative is to return a BP with the isLast flag set
           }
           else {
  -	    // TODO! need to know whether this BP is in the first area for FO!
  -            return makeBreakPoss(bp, lc.isStart(),
  -				 (getChildLM() == null), lc);
  +            return makeBreakPoss(bp, lc, (getChildLM() == null));
           }
       }
   
  -    protected boolean couldEndLine(BreakPoss bp) {
  -	if (bp.canBreakAfter()) {
  -	    return true; // no keep, ends on break char
  -	}
  -	else if (bp.isSuppressible()) {
  -	    // NOTE: except at end of content for this LM!!
  -	    // Never break after only space chars or any other sequence
  -	    // of areas which would be suppressed at the end of the line.
  -	    return false; 
  +    /** ATTENTION: ALSO USED BY LineBPLayoutManager! */
  +    protected void initChildLC(LayoutContext childLC, BreakPoss prevBP,
  +			       boolean bStartParent, boolean bFirstChildBP,
  +			       SpaceSpecifier leadingSpace) {
  +
  +	childLC.setFlags(LayoutContext.NEW_AREA,
  +			 (bFirstChildBP || bStartParent));
  +	if (bStartParent) {
  +	    // Start of a new line area or inline parent area
  +	    childLC.setFlags(LayoutContext.FIRST_AREA, bFirstChildBP );
  +	    childLC.setPendingSpace(leadingSpace);
  +	}
  +	else if (bFirstChildBP) {
  +	    // Space-after sequence from previous "area"
  +	    childLC.setFlags(LayoutContext.FIRST_AREA, true);
  +	    childLC.setPendingSpace(prevBP.getTrailingSpace());
   	}
   	else {
  -	    // See if could break before next area
  -	    LayoutContext lc=new LayoutContext();
  -	    BPLayoutManager nextLM = getChildLM();
  -	    return (nextLM == null || 
  -		    nextLM.canBreakBefore(lc));
  +	    childLC.setPendingSpace(null);
   	}
  +
       }
   
  +//     protected boolean couldEndLine(BreakPoss bp) {
  +// 	if (bp.canBreakAfter()) {
  +// 	    return true; // no keep, ends on break char
  +// 	}
  +// 	else if (bp.isSuppressible()) {
  +// 	    // NOTE: except at end of content for this LM!!
  +// 	    // Never break after only space chars or any other sequence
  +// 	    // of areas which would be suppressed at the end of the line.
  +// 	    return false; 
  +// 	}
  +// 	else {
  +// 	    // See if could break before next area
  +// 	    LayoutContext lc=new LayoutContext();
  +// 	    BPLayoutManager nextLM = getChildLM();
  +// 	    return (nextLM == null || 
  +// 		    nextLM.canBreakBefore(lc));
  +// 	}
  +//     }
   
   
  -    protected BreakPoss makeBreakPoss(BreakPoss bp, boolean bIsFirst, 
  -				   boolean bIsLast, LayoutContext lc) {
  +
  +    private BreakPoss makeBreakPoss(BreakPoss bp, LayoutContext lc,
  +				   boolean bIsLast) {
           WrappedPosition inlbp =
               new WrappedPosition(bp.getLayoutManager(), bp.getPosition());
   	BreakPoss myBP = new BreakPoss(this, inlbp, bp.getFlags());
   
  +	myBP.setFlag(BreakPoss.ISFIRST, lc.isFirstArea());
  +	myBP.setFlag(BreakPoss.ISLAST, bIsLast);
  +
           // Update dimension information for our allocation area,
   	// including child areas
           // generated by previous childLM which have completed layout
  @@ -268,44 +288,104 @@
           // This includes all previous breakinfo
   	
   	MinOptMax bpDim = (MinOptMax)bp.getStackingSize().clone();
  +	MinOptMax prevIPD = updatePrevIPD(bp, m_prevBP,
  +					  lc.startsNewArea(), lc.isFirstArea()); 
   
  -        if (m_prevBP == null ||
  -	    m_prevBP.getLayoutManager() != bp.getLayoutManager()) {
  -	    /* This is first bp generated by child (in this parent area).
  -	     * Calculate space-start on this area in combination with any
  -	     * pending space-end on previously generated break possibilities.
  -	     * Can also have leading space if this FO has fence-preceding.
  -	     */
  -	    bpDim.add(bp.resolveLeadingSpace());
  -        }
  -        if (bp.isLastArea()) {
  -	    m_pendingIPD.add(bpDim);
  -	    // See if our area is also done
  -	    
  -        }
  +	if (lc.startsNewArea()) {
  +	    myBP.setLeadingSpace(lc.getPendingSpace());
  +	}
  +
  +// 	if (lc.startsNewArea()) {
  +// 	    if (hasLeadingFence(!lc.isFirstArea())) {
  +// 		// Space-start before first child area placed
  +// 		prevIPD.add(bp.resolveLeadingSpace());
  +// 	    }
  +// 	    // Space-start sequence passed to ancestors
  +// 	    myBP.setLeadingSpace(lc.getPendingSpace());
  +// 	    m_hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
  +// 	}
  +// 	else {
  +// 	    // In case of reset to a previous position, it may already
  +// 	    // be calculated
  +// 	    prevIPD = (MinOptMax)m_hmPrevIPD.get(bp.getLayoutManager());
  +// 	    if (prevIPD == null) {
  +// 		// ASSERT(m_prevBP.getLayoutManager() != bp.getLayoutManager());
  +// 		/* This is first bp generated by child (in this parent area).
  +// 		 * Calculate space-start on this area in combination with any
  +// 		 * pending space-end with previous break.
  +// 		 * Corresponds to Space between two child areas.
  +// 		 */
  +// 		prevIPD = 
  +// 		    (MinOptMax)m_hmPrevIPD.get(m_prevBP.getLayoutManager());
  +// 		prevIPD = MinOptMax.add(prevIPD,  bp.resolveLeadingSpace());
  +// 		prevIPD.add(m_prevBP.getStackingSize());
  +// 		m_hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
  +// 	    }
  +// 	}
  +	// Add size of previous child areas which are finished
  +	bpDim.add(prevIPD);
  +//         if (bp.isLastArea()) {
  +// 	    m_childLC.setPendingSpace((SpaceSpecifier)bp.getTrailingSpace().
  +// 				      clone());
  +//         }
  +
  +	SpaceSpecifier trailingSpace = bp.getTrailingSpace();
  +	if (hasTrailingFence(!bIsLast)) {
  +	    bpDim.add(bp.resolveTrailingSpace(false));
  +	    trailingSpace = new SpaceSpecifier(false);
  +	}
  +	trailingSpace.addSpace(m_inlineProps.spaceEnd);
  +	myBP.setTrailingSpace(trailingSpace);
   
  -	// Start and end borders and padding
  -	bpDim.add(m_prevContentIPD);
  -	bpDim.add(getExtraIPD(!bIsFirst, !bIsLast));
  +	// Add start and end borders and padding
  +	bpDim.add(getExtraIPD(!lc.isFirstArea(), !bIsLast));
   	myBP.setStackingSize(bpDim);
   	myBP.setNonStackingSize(MinOptMax.add(bp.getNonStackingSize(),
   					      m_extraBPD));
  +
  +	m_prevBP = bp;
           if (bIsLast) {
   	    setFinished(true);  // Our last area, so indicate done
  -            myBP.setFlag(BreakPoss.ISLAST, true);
           }
  -	else {
  -            myBP.setFlag(BreakPoss.ISLAST, false);
  -	}
  -	myBP.setTrailingSpace((SpaceSpecifier)bp.getTrailingSpace().clone());
  -	myBP.getTrailingSpace().addSpace(m_inlineProps.spaceEnd);
  -	// If this FO doesn't have fence-start, then this value should
  -	// come from the lower level BP!
  -	myBP.setLeadingSpace(new SpaceSpecifier(false));
  -	m_prevBP = bp;
   	return myBP;
       }
   
  +
  +    /** ATTENTION: ALSO USED BY LineBPLayoutManager! */
  +    protected MinOptMax updatePrevIPD(BreakPoss bp, BreakPoss prevBP,
  +				      boolean bStartParent, boolean bFirstArea)
  +    {
  +	MinOptMax prevIPD = new MinOptMax(0);
  +
  +	if (bStartParent) {
  +	    if (hasLeadingFence(!bFirstArea)) {
  +		// Space-start before first child area placed
  +		prevIPD.add(bp.resolveLeadingSpace());
  +	    }
  +	    // Space-start sequence passed to ancestors
  +	    // myBP.setLeadingSpace(lc.getPendingSpace());
  +	    m_hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
  +	}
  +	else {
  +	    // In case of reset to a previous position, it may already
  +	    // be calculated
  +	    prevIPD = (MinOptMax)m_hmPrevIPD.get(bp.getLayoutManager());
  +	    if (prevIPD == null) {
  +		// ASSERT(prevBP.getLayoutManager() != bp.getLayoutManager());
  +		/* This is first bp generated by child (in this parent area).
  +		 * Calculate space-start on this area in combination with any
  +		 * pending space-end with previous break.
  +		 * Corresponds to Space between two child areas.
  +		 */
  +		prevIPD = 
  +		    (MinOptMax)m_hmPrevIPD.get(prevBP.getLayoutManager());
  +		prevIPD = MinOptMax.add(prevIPD,  bp.resolveLeadingSpace());
  +		prevIPD.add(prevBP.getStackingSize());
  +		m_hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
  +	    }
  +	}
  +	return prevIPD;
  +    }
   
   
       /******
  
  
  
  1.2       +38 -20    xml-fop/src/org/apache/fop/layoutmgr/LayoutContext.java
  
  Index: LayoutContext.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/LayoutContext.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LayoutContext.java	28 Apr 2002 21:31:00 -0000	1.1
  +++ LayoutContext.java	13 May 2002 06:12:42 -0000	1.2
  @@ -1,5 +1,5 @@
   /*
  - * $Id: LayoutContext.java,v 1.1 2002/04/28 21:31:00 klease Exp $
  + * $Id: LayoutContext.java,v 1.2 2002/05/13 06:12:42 klease Exp $
    * Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -17,8 +17,8 @@
        * Values for flags.
        */
       public static final int LINEBREAK_AT_LF_ONLY = 0x01;
  -    public static final int START_BLOCK =          0x02;
  -    public static final int START_AREA =          0x02; // inline too
  +    /** Generated break possibility is first in a new area */
  +    public static final int NEW_AREA =          0x02;
       public static final int IPD_UNKNOWN =          0x04;
       /** Signal to a Line LM that a higher level LM may provoke a change
        *  in the reference area, thus ref area IPD. The LineLM should return
  @@ -33,6 +33,7 @@
        * except the first.
        */
       public static final int SUPPRESS_LEADING_SPACE =       0x10;
  +    public static final int FIRST_AREA =                   0x20;
   
   
       public int flags;  // Contains some set of flags defined above
  @@ -43,13 +44,8 @@
        * These LM <b>may</b> wish to pass this information down to lower
        * level LM to allow them to optimize returned break possibilities.
        */
  -    MinOptMax stackLimit;
  +    MinOptMax m_stackLimit;
   
  -    /** Current stacking dimension, either IPD or BPD, depending on
  -     * caller. This is generally the value returned by a previous call
  -     * to getNextBreakPoss().
  -     */
  -    MinOptMax m_stackSize;
   
       /** True if current top-level reference area is spanning. */
       boolean bIsSpan;
  @@ -63,27 +59,49 @@
       public LayoutContext(LayoutContext parentLC) {
           this.flags = parentLC.flags;
           this.refIPD = parentLC.refIPD;
  -        this.stackLimit = null; // Don't reference parent MinOptMax!
  +        this.m_stackLimit = null; // Don't reference parent MinOptMax!
   	this.m_pendingSpace = parentLC.m_pendingSpace; //???
           // Copy other fields as necessary. Use clone???
       }
   
  -    public LayoutContext() {
  -        this.flags = 0;
  +    public LayoutContext(int flags) {
  +        this.flags = flags;
           this.refIPD = 0;
  -	stackLimit = new MinOptMax(0);
  +	m_stackLimit = new MinOptMax(0);
  +	m_pendingSpace = null;
       }
   
       public void setFlags(int flags) {
  -	this.flags |= flags;
  +	setFlags(flags, true);
  +    }
  +
  +    public void setFlags(int flags, boolean bSet) {
  +	if (bSet) {
  +	    this.flags |= flags;
  +	}
  +	else {
  +	    this.flags &= ~flags;
  +	}
       }
   
       public void unsetFlags(int flags) {
  -	this.flags &= ~flags;
  +	setFlags(flags, false);
       }
   
       public boolean isStart() {
  -	return ((this.flags & START_BLOCK) != 0);
  +	return ((this.flags & NEW_AREA) != 0);
  +    }
  +
  +    public boolean startsNewArea() {
  +	return ((this.flags & NEW_AREA) != 0 && m_pendingSpace != null);
  +    }
  +
  +    public boolean isFirstArea() {
  +	return ((this.flags & FIRST_AREA) != 0);
  +    }
  +
  +    public boolean suppressLeadingSpace() {
  +	return ((this.flags & SUPPRESS_LEADING_SPACE) != 0);
       }
   
       public void setPendingSpace(SpaceSpecifier space) {
  @@ -94,11 +112,11 @@
   	return m_pendingSpace;
       }
   
  -    public void setStackSize(MinOptMax stackSize) {
  -	m_stackSize = stackSize;
  +    public void setStackLimit(MinOptMax stackLimit) {
  +	m_stackLimit = stackLimit;
       }
   
  -    public MinOptMax getStackSize() {
  -	return m_stackSize ;
  +    public MinOptMax getStackLimit() {
  +	return m_stackLimit ;
       }
   }
  
  
  
  1.3       +190 -107  xml-fop/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java
  
  Index: LineBPLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LineBPLayoutManager.java	10 May 2002 12:38:15 -0000	1.2
  +++ LineBPLayoutManager.java	13 May 2002 06:12:42 -0000	1.3
  @@ -1,5 +1,5 @@
   /*
  - * $Id: LineBPLayoutManager.java,v 1.2 2002/05/10 12:38:15 klease Exp $
  + * $Id: LineBPLayoutManager.java,v 1.3 2002/05/13 06:12:42 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -24,6 +24,7 @@
   import org.apache.fop.area.inline.Character;
   
   import java.util.ListIterator;
  +import java.util.Iterator;
   import java.util.List;
   import java.util.Vector;
   import java.util.ArrayList;
  @@ -34,7 +35,7 @@
    * inline areas generated by its sub layout managers.
    */
   public class LineBPLayoutManager extends 
  -      InlineStackingBPLayoutManager {
  +     InlineStackingBPLayoutManager {
   
       /**
        * Private class to store information about inline breaks.
  @@ -43,9 +44,11 @@
        */
       private static class LineBreakPosition implements BreakPoss.Position {
           int m_iPos;
  +	double m_dAdjust; // Percentage to adjust (stretch or shrink)
   
  -        LineBreakPosition(int iBreakIndex) {
  +        LineBreakPosition(int iBreakIndex, double dAdjust) {
               m_iPos = iBreakIndex;
  +	    m_dAdjust = dAdjust;
           }
       }
   
  @@ -55,7 +58,6 @@
       /** Break positions returned by inline content. */
       private Vector m_vecInlineBreaks = new Vector(100);
   
  -    private SpaceSpecifier m_pendingSpace;
       private BreakPoss m_prevBP = null; // Last confirmed break position
       private boolean m_bJustify = false; // True if fo:block text-align=JUSTIFY
       private int m_iTextIndent = 0;
  @@ -63,9 +65,9 @@
   
   
       public LineBPLayoutManager(FObj fobj, List lms, int lh, int l, int f) {
  -	//super(fobj, lms, lh, l, f);
  +	//super(fobj, lms.listIterator(), lh, l, f);
   	super(fobj, lms.listIterator());
  -	// initProperties();
  +	init(); // Normally done when started by parent!
       }
   
       protected void initProperties(PropertyManager propMgr) {
  @@ -79,7 +81,6 @@
       }
       
   
  -
       /**
        * Call child layout managers to generate content as long as they
        * generate inline areas. If a block-level generating LM is found,
  @@ -98,105 +99,85 @@
   	    return new BreakPoss(this, null, BreakPoss.NEED_IPD);
           }
   
  -	BPLayoutManager prevLM = null; // previous active LM
   	BPLayoutManager curLM ;        // currently active LM
  +	BreakPoss prevBP=null;
           BreakPoss bp=null;           // proposed BreakPoss
   
  -	// IPD remaining in line
  -        MinOptMax availIPD = context.stackLimit;
  +	Vector vecPossEnd = new Vector();
   
  -	// IPD of any unbreakable finished FO content
  -        MinOptMax pendingIPD = null;
  +	// IPD remaining in line
  +        MinOptMax availIPD = context.getStackLimit();
   
   	// QUESTION: maybe LayoutContext holds the Properties which
   	// come from block-level?
   
   	LayoutContext inlineLC = new LayoutContext(context);
  -	inlineLC.setPendingSpace(new SpaceSpecifier(true));
  +
  +	clearPrevIPD();
   
           while ((curLM = getChildLM()) != null) {
  -	    // INITIALIZE FLAGS FOR CALL TO CHILD LM
  -	    boolean bFirstBPforLM = (prevLM != curLM);
  -	    if (bFirstBPforLM) {
  -		prevLM = curLM;
  -		inlineLC.setFlags(LayoutContext.START_AREA);
  -		if (bp != null) {
  -		    inlineLC.setPendingSpace(bp.getTrailingSpace());
  -		}
  -	    }
  -	    else {
  -		inlineLC.unsetFlags(LayoutContext.START_AREA);
  -		inlineLC.setPendingSpace(null);
  -	    }
  +	    // INITIALIZE LAYOUT CONTEXT FOR CALL TO CHILD LM
  +	    // First break for the child LM in each of its areas
  +	    boolean bFirstBPforLM =
  +		(m_vecInlineBreaks.isEmpty() ||
  +		 (((BreakPoss)m_vecInlineBreaks.lastElement()).
  +		  getLayoutManager() != curLM));
  +
  +	    initChildLC(inlineLC, bp, (bp==null), bFirstBPforLM,
  +			new SpaceSpecifier(true));
  +
  +// 	    if (bp == null) {
  +// 		// Start of a new line area
  +// 		inlineLC.setFlags(LayoutContext.FIRST_AREA, bFirstBPforLM );
  +// 		inlineLC.setPendingSpace(new SpaceSpecifier(true));
  +// 	    }
  +// 	    else if (bFirstBPforLM) {
  +// 		// Space-after sequence from previous "area"
  +// 		inlineLC.setFlags(LayoutContext.FIRST_AREA, true);
  +// 		inlineLC.setPendingSpace(bp.getTrailingSpace());
  +// 	    }
  +// 	    else {
  +// 		inlineLC.setPendingSpace(null);
  +// 	    }
  +
  +
               /* If first BP in this line but line is not first in this
  -             * LM and previous possible linebreak was not forced (LINEFEED),
  +             * LM and previous line end decision was not forced (LINEFEED),
                * then set the SUPPRESS_LEADING_SPACE flag.
                */
  -            if (bp == null && !m_vecInlineBreaks.isEmpty() &&
  -                ((BreakPoss)m_vecInlineBreaks.lastElement()).
  -		                            isForcedBreak()==false) {
  -		inlineLC.setFlags(LayoutContext.SUPPRESS_LEADING_SPACE);
  -            }
  -            else {
  -                inlineLC.unsetFlags(LayoutContext.SUPPRESS_LEADING_SPACE);
  -            }
  +	    inlineLC.setFlags(LayoutContext.SUPPRESS_LEADING_SPACE,
  +			      (bp == null && !m_vecInlineBreaks.isEmpty() &&
  +			       ((BreakPoss)m_vecInlineBreaks.lastElement()).
  +			       isForcedBreak()==false));
  +
   	    // GET NEXT POSSIBLE BREAK FROM CHILD LM
  +	    prevBP = bp;
               if ((bp = curLM.getNextBreakPoss(inlineLC, null)) != null) {
  +		// Add any space before and previous content dimension
  +		MinOptMax prevIPD = updatePrevIPD(bp, prevBP, (prevBP==null),
  +						  inlineLC.isFirstArea());
  +		MinOptMax bpDim = MinOptMax.add(bp.getStackingSize(), prevIPD);
  +
   		// check if this bp fits in line
  -		MinOptMax bpDim = (MinOptMax)bp.getStackingSize().clone();
  -		/* If first BP for this LM (in this call)
  -		 * add any leading space.
  -		 */
  -		if (bFirstBPforLM) {
  -		    if (pendingIPD != null) {
  -			bpDim.add(pendingIPD);
  -		    }
  -		    bpDim.add(bp.resolveLeadingSpace());
  -		}
   		boolean bBreakOK = couldEndLine(bp);
   		if (bBreakOK) {
  -		    /* Add any non-conditional trailing space. */
  +		    /* Add any non-conditional trailing space, assuming we
  +		     * end the line here. If we can't break here, we just
  +		     * check if the content fits. */
   		    bpDim.add(bp.resolveTrailingSpace(true));
   		}
  +		// TODO: stop if linebreak is forced (NEWLINE)
  +		// PROBLEM: interaction with wrap which can be set
  +		// at lower levels!
  +		System.err.println("BPdim=" + bpDim.opt);
  +
   		// Check if proposed area would fit in line
  -		if (bpDim.max < availIPD.min) {
  -		    // Break fits buts is short
  -		    if (bBreakOK) {
  -			if (pendingIPD != null) {
  -			    availIPD.subtract(pendingIPD);
  -			    // Subtract space-start for this area, since
  -			    // we know at least part of it fits.
  -			    availIPD.subtract(bp.getLeadingSpace().
  -					      resolve(false));
  -			    pendingIPD = null;
  -			    // Add all pending BP list members to BP list
  -			}
  -			m_prevBP = bp; // Save reference to this BP
  -			m_vecInlineBreaks.add(bp);
  -			// Handle end of this LM's areas
  -			if (bp.isLastArea()) {
  -			    /* NOTE: this doesn't include space-end since
  -			     * it may combine with space-start on the
  -			     * following FO's first area.
  -			     */
  -			    availIPD.subtract(bp.getStackingSize());
  -			}
  -		    }
  -		    else { 
  -			/* Can't end line here, so mark size pending.
  -			 * This includes any previosly pending size,
  -			 * already calculated above.
  -			 */
  -			if (bp.isLastArea()) {
  -			    pendingIPD = bpDim;
  -			}
  -			// Add BP to the list even though we can't break here
  -			// We need to keep it for area generation
  -			m_vecInlineBreaks.add(bp);
  -		    }
  -		}
  -		else if (bpDim.min > availIPD.max) {
  +		if (bpDim.min > availIPD.max) {
  +		    // See if we have already found a potential break
  +		    if (vecPossEnd.size() > 0) break;
  +
   		    // This break position doesn't fit
  +		    // TODO: If we are in nowrap, we use it as is!
   		    if (m_bJustify || m_prevBP == null) {
   			// try to find a hyphenation point in the word
   			// which spans the queued breaks and the proposed bp
  @@ -225,23 +206,38 @@
   		    break;
   		}
   		else {
  -		    /* This is a possible line BP (line could be filled)
  -		     * bpDim.max >= availIPD.min
  -		     * Keep this as a possible break, depending on "cost".
  -		     * We will choose lowest cost. Cost depends on stretch
  -		     * (ie, bpDim.opt closes to availIPD.opt), keeps
  -		     * and hyphenation.
  -		     */
  -		    m_prevBP = bp;
  -		    break; //???
  -		}
  +		    // Add the BP to the list whether or not we can break
  +		    m_vecInlineBreaks.add(bp);
  +		    // Handle end of this LM's areas
  +		    if (bBreakOK) {
  +			m_prevBP = bp; // Save reference to this BP
  +			if (bp.isForcedBreak()) {
  +			    break;
  +			}
  +			if (bpDim.max >= availIPD.min) {
  +			    /* This is a possible line BP (line could be filled)
  +			     * bpDim.max >= availIPD.min
  +			     * Keep this as a possible break, depending on 
  +			     * "cost". We will choose lowest cost.
  +			     * Cost depends on stretch
  +			     * (ie, bpDim.opt closes to availIPD.opt), keeps
  +			     * and hyphenation.
  +			     */
  +			    System.err.println("Found potential linebreak");
  +			    vecPossEnd.add(new BreakCost(bp,
  +			     Math.abs(availIPD.opt - bpDim.opt )));
  +			}
  +			// Otherwise it's short
  +		    }
  +		    else { 
  +			/* Can't end line here. */
  +		    }
  +		} // end of bpDim.min <= availIPD.max
   	    } // end of getNextBreakPoss!=null on current child LM
   	    else {
  -		/* What if the childLM returns null?
  -		 * No further break possibility in current sequence of
  -		 * inline LM. Previous break or end of area will be the
  -		 * ending for the current line.
  -		 * Otherwise we have filled the current line.
  +		/* The child LM can return a null BreakPoss if it has
  +		 * nothing (more) to layout. This can happen when backing
  +		 * up. Just try the next child LM.
   		 */
   	    }
   	} // end of while on child LM
  @@ -249,6 +245,10 @@
   	    // No more content to layout!
   	    setFinished(true);
   	}
  +	// Choose the best break
  +	if (!bp.isForcedBreak() && vecPossEnd.size()>0) {
  +	    m_prevBP = getBestBP(vecPossEnd);
  +	}
   	// Backup child LM if necessary
   	if (bp != m_prevBP) {
   	    // Remove any pending breaks from the vector
  @@ -257,20 +257,104 @@
   	    }
   	    reset(m_prevBP.getLayoutManager(), m_prevBP.getPosition());
   	}
  -        return makeLineBreak(m_prevBP);
  +	// Distribute space in the line
  +	MinOptMax actual = MinOptMax.add(m_prevBP.getStackingSize(),
  +					 getPrevIPD(m_prevBP.getLayoutManager()));
  +	// ATTENTION: make sure this hasn't gotten start space for next
  +	// LM added onto it!
  +	actual.add(m_prevBP.resolveTrailingSpace(true));
  +	System.err.println("Target opt=" + availIPD.opt + 
  +			  " bp.opt=" + actual.opt + " bp.max=" + actual.max
  +			   + " bm.min=" + actual.min);
  +
  +	// Don't justify last line in the sequence or if forced line-end
  +	boolean bJustify = (m_bJustify && !m_prevBP.isForcedBreak() &&
  +			    !isFinished());
  +        return makeLineBreak(m_prevBP, availIPD, actual, bJustify);
       }
   
  +    protected boolean couldEndLine(BreakPoss bp) {
  +	if (bp.canBreakAfter()) {
  +	    return true; // no keep, ends on break char
  +	}
  +	else if (bp.isSuppressible()) {
  +	    // NOTE: except at end of content for this LM!!
  +	    // Never break after only space chars or any other sequence
  +	    // of areas which would be suppressed at the end of the line.
  +	    return false; 
  +	}
  +	else {
  +	    // See if could break before next area
  +	    // TODO: do we need to set anything on the layout context?
  +	    LayoutContext lc=new LayoutContext(0);
  +	    BPLayoutManager nextLM = getChildLM();
  +	    return (nextLM == null || 
  +		    nextLM.canBreakBefore(lc));
  +	}
  +    }
  +
  +
  +    private BreakPoss getBestBP(Vector vecPossEnd) {
  +	if (vecPossEnd.size()==1) {
  +	    return ((BreakCost)vecPossEnd.elementAt(0)).getBP();
  +	}
  +	// Choose the best break (use a sort on cost!)
  +	Iterator iter = vecPossEnd.iterator();
  +	int minCost= Integer.MAX_VALUE;
  +	BreakPoss bestBP = null;
  +	while (iter.hasNext()) {
  +	    BreakCost bc = (BreakCost)iter.next();
  +	    if (bc.getCost() < minCost) {
  +		minCost = bc.getCost();
  +		bestBP = bc.getBP();
  +	    }
  +	}
  +	return bestBP;
  +    }
  +
  +    /** Line area is always considered to act as a fence. */
  +    protected boolean hasLeadingFence(boolean bNotFirst) {
  +	return true;
  +    }
  +    
  +    /** Line area is always considered to act as a fence. */
  +    protected boolean hasTrailingFence(boolean bNotLast) {
  +	return true;
  +    }
  +    
   
   
       private BreakPoss findHyphenPoss(BreakPoss prevBP, BreakPoss newBP) {
  +	// Get a "word" to hyphenate by getting characters from all
  +	// pending break poss which are in m_vecInlineBreaks, starting
  +	// with the position just AFTER prevBP.getPosition()
   	return null;
       }
   
  -    private BreakPoss makeLineBreak(BreakPoss inlineBP) {
  +    private BreakPoss makeLineBreak(BreakPoss inlineBP, MinOptMax target,
  +				    MinOptMax actual, boolean bJustify) {
           // make a new BP
  +	// Store information needed to make areas in the LineBreakPosition!
  +	// Calculate stretch or shrink factor
  +
  +	double dAdjust=0.0;
  +	if (bJustify) {
  +	    if (actual.opt < target.opt) {
  +		// Stretch
  +		dAdjust = (double)(target.opt - actual.opt)/
  +		    (double)(actual.max - actual.opt);
  +	    }
  +	    else {
  +		// Shrink
  +		dAdjust = (double)(target.opt - actual.opt)/
  +		    (double)( actual.opt - actual.min);
  +	    }
  +	}
  +	System.err.println("Adjustment factor=" + dAdjust);
           BreakPoss curLineBP =
               new BreakPoss(this,
  -			  new LineBreakPosition(m_vecInlineBreaks.size()-1));
  +			  new LineBreakPosition(m_vecInlineBreaks.size()-1,
  +			  dAdjust));
   
   	/* FIX ME!! 
   	 * Need to calculate line height based on all inline BP info
  @@ -321,10 +405,9 @@
   	BreakPoss bp;
   	Vector vecBreakPoss = new Vector(20);
   
  -	LayoutContext childLC = new LayoutContext();
   	// Force area creation on first call
  -	// NOTE: normally not necessary
  -	childLC.flags |= LayoutContext.CHECK_REF_AREA;
  +	// NOTE: normally not necessary when fully integrated!
  +	LayoutContext childLC = new LayoutContext(LayoutContext.CHECK_REF_AREA);
   
   	while (!isFinished()) {
   	    if ((bp = getNextBreakPoss(childLC, null)) != null) {
  @@ -338,13 +421,13 @@
   		    parentLM.getParentArea(null);
   		    ipd = parentLM.getContentIPD();
   		    childLC.flags &= ~LayoutContext.CHECK_REF_AREA;
  -		    childLC.stackLimit = new MinOptMax(ipd - m_iIndents -
  -						       m_iTextIndent);
  +		    childLC.setStackLimit(new MinOptMax(ipd - m_iIndents -
  +						       m_iTextIndent));
   		}
   		else {
   		    vecBreakPoss.add(bp);
   		    // Reset stackLimit for non-first lines
  -		    childLC.stackLimit = new MinOptMax(ipd - m_iIndents);
  +		    childLC.setStackLimit(new MinOptMax(ipd - m_iIndents));
   		}
   	    }
           }
  
  
  
  1.3       +6 -5      xml-fop/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java
  
  Index: TextBPLayoutManager.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TextBPLayoutManager.java	10 May 2002 12:38:16 -0000	1.2
  +++ TextBPLayoutManager.java	13 May 2002 06:12:42 -0000	1.3
  @@ -1,5 +1,5 @@
   /*
  - * $Id: TextBPLayoutManager.java,v 1.2 2002/05/10 12:38:16 klease Exp $
  + * $Id: TextBPLayoutManager.java,v 1.3 2002/05/13 06:12:42 klease Exp $
    * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
    * For details on use and redistribution please refer to the
    * LICENSE file included with these sources.
  @@ -190,8 +190,7 @@
        */
       public boolean canBreakBefore(LayoutContext context) {
   	char c = chars[m_iNextStart];
  -	return ((c == NEWLINE) ||
  -		((context.flags & LayoutContext.LINEBREAK_AT_LF_ONLY)==0 &&
  +	return ((c == NEWLINE) || (textInfo.bWrap &&
   		 (CharUtilities.isSpace(c) || s_breakChars.indexOf(c)>=0)));
       }
   
  @@ -245,17 +244,19 @@
   
   	int iFlags = 0;
   
  -	if ((context.flags & LayoutContext.START_AREA)!=0) {
  +	if (context.startsNewArea()) {
   	    /* This could be first call on this LM, or the first call
   	     * in a new (possible) LineArea.
   	     */
   	    m_ipdTotal = new MinOptMax(0);
   	    iFlags |= BreakPoss.ISFIRST;
  +	    // May have leading space too which can combine with a
  +	    // leading word-space or letter-space
   	}
   
   
           // HANDLE SUPPRESSED LEADING SPACES
  -	if ((context.flags & LayoutContext.SUPPRESS_LEADING_SPACE)!=0) {
  +	if (context.suppressLeadingSpace()) {
   	    /* If any leading space characters, ignore them. */ 
   	    // NOTE: Skips word-space chars only, not other white-space!
   	    for (; m_iNextStart < chars.length &&
  
  
  

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