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 vh...@apache.org on 2013/08/29 18:26:13 UTC

svn commit: r1518691 - in /xmlgraphics/fop/branches/Temp_WhitespaceManagement: src/java/org/apache/fop/fo/ src/java/org/apache/fop/fo/extensions/ src/java/org/apache/fop/layoutmgr/ test/java/org/apache/fop/

Author: vhennebert
Date: Thu Aug 29 16:26:12 2013
New Revision: 1518691

URL: http://svn.apache.org/r1518691
Log:
FOP-2292: First bits of a whitespace management extension
Patch by Seifeddine Dridi, applied with some modifications (mainly, Java compliance and Checkstyle)

Added:
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/AlternativeBlock.java   (with props)
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/BestFit.java   (with props)
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeBlockLayoutManager.java   (with props)
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeManager.java   (with props)
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitLayoutManager.java   (with props)
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitPenalty.java   (with props)
Modified:
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/Constants.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/FOPropertyMapping.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/ElementListUtils.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutContext.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
    xmlgraphics/fop/branches/Temp_WhitespaceManagement/test/java/org/apache/fop/KnuthAlgorithmTestCase.java

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/Constants.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/Constants.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/Constants.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/Constants.java Thu Aug 29 16:26:12 2013
@@ -815,9 +815,12 @@ public interface Constants {
 
     /** Scope for table header */
     int PR_X_HEADER_COLUMN = 290;
+    
+    /** Property constant - FOP proprietary*/
+    int PR_X_FITTING_STRATEGY = 291;
 
     /** Number of property constants defined */
-    int PROPERTY_COUNT = 290;
+    int PROPERTY_COUNT = 291;
 
     // compound property constants
 

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/FOPropertyMapping.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/FOPropertyMapping.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/FOPropertyMapping.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/FOPropertyMapping.java Thu Aug 29 16:26:12 2013
@@ -2613,7 +2613,12 @@ public final class FOPropertyMapping imp
         m.setInherited(false);
         m.setDefault("");
         addPropertyMaker("fox:alt-text", m);
-
+        
+        //fox:fitting-strategy, used only in fox:best-fit
+        m = new StringProperty.Maker(PR_X_FITTING_STRATEGY);
+        m.setInherited(false);
+        m.setDefault("first-fit");
+        addPropertyMaker("fox:fitting-strategy", m);
 
         // fox:border-*-radius-*
         m = new CondLengthProperty.Maker(PR_X_BORDER_BEFORE_RADIUS_START);

Added: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/AlternativeBlock.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/AlternativeBlock.java?rev=1518691&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/AlternativeBlock.java (added)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/AlternativeBlock.java Thu Aug 29 16:26:12 2013
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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$ */
+
+package org.apache.fop.fo.extensions;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.ValidationException;
+
+/**
+ * A class modeling fox:alternative-block
+ */
+
+public class AlternativeBlock extends FObj {
+
+    public static final String OBJECT_NAME = "alternative-block";
+
+    public AlternativeBlock(FONode parent) {
+        super(parent);
+    }
+
+    public void processNode(String elementName, Locator locator,
+            Attributes attlist, PropertyList pList) throws FOPException {
+        if (log.isDebugEnabled()) {
+            log.debug("org.apache.fop.fo.extensions.AlternativeBlock: " + elementName
+                    + (locator != null ? " at " + getLocatorString(locator) : ""));
+        }
+    }
+
+    public void startOfNode() throws FOPException {
+        if (log.isDebugEnabled())
+            log.debug("AlternativeBlock.startOfNode()");
+    }
+
+    public void endOfNode() throws FOPException {
+        if (log.isDebugEnabled())
+            log.debug("AlternativeBlock.endOfNode()");
+    }
+
+    /**
+     * Content model: see {@link Block}
+     */
+    protected void validateChildNode(Locator loc, String nsURI, String localName)
+            throws ValidationException {
+        if (FOX_URI.equals(nsURI)) {
+            if ("best-fit".equals(localName) || "alternative-block".equals(localName)) {
+                invalidChildError(loc, FOX_URI, localName);
+            }
+        }
+        else if (FO_URI.equals(nsURI)) {
+            if (!isBlockOrInlineItem(nsURI, localName)) {
+                invalidChildError(loc, FO_URI, localName);
+            }
+        }
+    }
+
+    @Override
+    public String getLocalName() {
+        return OBJECT_NAME;
+    }
+
+    @Override
+    public String getNormalNamespacePrefix() {
+        return ExtensionElementMapping.STANDARD_PREFIX;
+    }
+
+    public String getNamespaceURI() {
+        return ExtensionElementMapping.URI;
+    }
+
+}

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/AlternativeBlock.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/AlternativeBlock.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Added: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/BestFit.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/BestFit.java?rev=1518691&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/BestFit.java (added)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/BestFit.java Thu Aug 29 16:26:12 2013
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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$ */
+
+package org.apache.fop.fo.extensions;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.ValidationException;
+import org.apache.fop.layoutmgr.AlternativeManager.FittingStrategy;
+
+/**
+ *  A class that holds a set of <fox:alternative-block> blocks where each one is examined,
+ *  and the one that best matches the fitting strategy is selected.
+ *  The selected alternative should have an occupied BPD that is less than
+ *  the remaining BPD of the current page.
+ */
+public class BestFit extends FObj {
+
+    public static final String OBJECT_NAME = "best-fit";
+    private FittingStrategy strategy = FittingStrategy.FIRST_FIT;
+
+    public BestFit(FONode parent) {
+        super(parent);
+
+    }
+
+    /** {@inheritDoc} */
+    public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
+        String strategyName = pList.get(PR_X_FITTING_STRATEGY).getString();
+        if (strategyName.equals("first-fit"))
+            strategy = FittingStrategy.FIRST_FIT;
+        else if (strategyName.equals("smallest-fit"))
+            strategy = FittingStrategy.SMALLEST_FIT;
+        else if (strategyName.equals("biggest-fit"))
+            strategy = FittingStrategy.BIGGEST_FIT;
+        else {
+            log.warn("Unrecognized strategy name => " + strategyName + ". Using default strategy (first-fit");
+            strategy = FittingStrategy.FIRST_FIT;
+        }
+
+    }
+
+    public void processNode(String elementName, Locator locator,
+            Attributes attlist, PropertyList pList) throws FOPException {
+        if (log.isDebugEnabled()) {
+            log.debug("org.apache.fop.fo.extensions.BestFit: " + elementName
+                    + (locator != null ? " at " + getLocatorString(locator) : ""));
+        }
+        pList.addAttributesToList(attlist);
+        bind(pList);
+    }
+
+    public void startOfNode() throws FOPException {
+        if (log.isDebugEnabled())
+            log.debug("BestFit.startOfNode()");
+    }
+
+    public void endOfNode() throws FOPException {
+        if (log.isDebugEnabled())
+            log.debug("BestFit.endOfNode()");
+    }
+
+    /**
+     * {@inheritDoc}
+     * Content model: (fox:alternative-block)+
+     */
+    protected void validateChildNode(Locator loc, String nsURI, String localName)
+            throws ValidationException {
+        if (FO_URI.equals(nsURI)) {
+            if (!"alternative-block".equals(localName)) {
+                invalidChildError(loc, FO_URI, localName);
+            }
+        }
+    }
+
+    @Override
+    public String getLocalName() {
+        return OBJECT_NAME;
+    }
+
+    @Override
+    public String getNormalNamespacePrefix() {
+        return ExtensionElementMapping.STANDARD_PREFIX;
+    }
+
+    public String getNamespaceURI() {
+        return ExtensionElementMapping.URI;
+    }
+
+    public FittingStrategy getStrategy() {
+        return strategy;
+    }
+
+}

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/BestFit.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/BestFit.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java Thu Aug 29 16:26:12 2013
@@ -49,6 +49,7 @@ public class ExtensionElementMapping ext
         PROPERTY_ATTRIBUTES.add("orphan-content-limit");
         PROPERTY_ATTRIBUTES.add("internal-destination");
         PROPERTY_ATTRIBUTES.add("disable-column-balancing");
+        PROPERTY_ATTRIBUTES.add("fitting-strategy");
         //These are FOP's extension properties for accessibility
         PROPERTY_ATTRIBUTES.add("alt-text");
         PROPERTY_ATTRIBUTES.add("header");
@@ -85,6 +86,8 @@ public class ExtensionElementMapping ext
             foObjs.put("label", new UnknownXMLObj.Maker(URI));
             foObjs.put("destination", new DestinationMaker());
             foObjs.put("external-document", new ExternalDocumentMaker());
+            foObjs.put("best-fit", new BestFitMaker());
+            foObjs.put("alternative-block", new AlternativeBlockMaker());
         }
     }
 
@@ -99,6 +102,18 @@ public class ExtensionElementMapping ext
             return new ExternalDocument(parent);
         }
     }
+    
+    static class BestFitMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new BestFit(parent);
+        }
+    }
+    
+    static class AlternativeBlockMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new AlternativeBlock(parent);
+        }
+    }
 
     /** {@inheritDoc} */
     public String getStandardPrefix() {

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java Thu Aug 29 16:26:12 2013
@@ -611,7 +611,7 @@ public abstract class AbstractBreaker {
                 // Handle SpaceHandling(Break)Positions, see SpaceResolver!
                 SpaceResolver.performConditionalsNotification(effectiveList,
                         startElementIndex, notificationEndElementIndex, lastBreak);
-
+                childLC.setAlternativeManager(alg.getAlternativeManager());
                 // Add areas now!
                 addAreas(new KnuthPossPosIter(effectiveList,
                         startElementIndex, endElementIndex + 1), childLC);

Added: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeBlockLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeBlockLayoutManager.java?rev=1518691&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeBlockLayoutManager.java (added)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeBlockLayoutManager.java Thu Aug 29 16:26:12 2013
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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$ */
+
+package org.apache.fop.layoutmgr;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Stack;
+
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.LineArea;
+import org.apache.fop.fo.extensions.AlternativeBlock;
+
+/**
+ * Layout manager for {@link AlternativeBlock}
+ */
+
+public class AlternativeBlockLayoutManager extends AbstractLayoutManager {
+
+    private Block curBlockArea;
+
+    public AlternativeBlockLayoutManager(AlternativeBlock node) {
+        super(node);
+        setGeneratesBlockArea(true);
+    }
+
+    /**
+     * Creates and initializes a {@link LayoutContext} to pass to the child LM
+     *
+     * @param context the parent {@link LayoutContext}
+     * @return a new child layout context
+     */
+    protected LayoutContext makeChildLayoutContext(LayoutContext context) {
+        LayoutContext childLC = LayoutContext.newInstance();
+        childLC.copyPendingMarksFrom(context);
+        childLC.setStackLimitBP(context.getStackLimitBP());
+        childLC.setRefIPD(context.getRefIPD());
+        childLC.setWritingMode(context.getWritingMode());
+        return childLC;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public List getNextKnuthElements(LayoutContext context, int alignment) {
+        return getNextKnuthElements(context, alignment, null, null, null);
+    }
+
+    /** {@inheritDoc} */
+    public List getNextKnuthElements(LayoutContext context, int alignment,
+            Stack lmStack, Position positionAtIPDChange,
+            LayoutManager restartAtLM) {
+        LayoutManager curLM;
+        List<ListElement> returnList = new LinkedList<ListElement>();
+        while ((curLM = getChildLM()) != null) {
+            LayoutContext childLC = makeChildLayoutContext(context);
+
+            List returnedList = null;
+            if (!curLM.isFinished()) {
+                returnedList = curLM.getNextKnuthElements(childLC, alignment);
+            }
+            if (returnedList != null) {
+                wrapPositionElements(returnedList, returnList);
+            }
+        }
+        setFinished(true);
+        return returnList;
+    }
+
+    /**
+     * "wrap" the Position inside each element moving the elements from SourceList to targetList
+     *
+     * @param sourceList source list
+     * @param targetList target list receiving the wrapped position elements
+     */
+    protected void wrapPositionElements(List sourceList, List targetList) {
+        wrapPositionElements(sourceList, targetList, false);
+    }
+
+    /**
+     * "wrap" the Position inside each element moving the elements from
+     * SourceList to targetList
+     *
+     * @param sourceList source list
+     * @param targetList target list receiving the wrapped position elements
+     * @param force if true, every Position is wrapped regardless of its LM of origin
+     */
+    protected void wrapPositionElements(List sourceList, List targetList,
+            boolean force) {
+
+        ListIterator listIter = sourceList.listIterator();
+        Object tempElement;
+        while (listIter.hasNext()) {
+            tempElement = listIter.next();
+            if (tempElement instanceof ListElement) {
+                wrapPositionElement((ListElement) tempElement, targetList,
+                        force);
+            } else if (tempElement instanceof List) {
+                wrapPositionElements((List) tempElement, targetList, force);
+            }
+        }
+    }
+
+    /**
+     * "wrap" the Position inside the given element and add it to the target list.
+     *
+     * @param el the list element
+     * @param targetList target list receiving the wrapped position elements
+     * @param force if true, every Position is wrapped regardless of its LM of origin
+     */
+    protected void wrapPositionElement(ListElement el, List targetList,
+            boolean force) {
+        if (force || el.getLayoutManager() != this) {
+            el.setPosition(notifyPos(new NonLeafPosition(this, el.getPosition())));
+        }
+        targetList.add(el);
+    }
+
+    @Override
+    public Area getParentArea(Area childArea) {
+        if (curBlockArea == null) {
+            curBlockArea = new Block();
+            // Set up dimensions
+            // Must get dimensions from parent area
+            /*Area parentArea = */parentLayoutManager.getParentArea(curBlockArea);
+        }
+        return curBlockArea;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void addChildArea(Area childArea) {
+        if (curBlockArea != null) {
+            if (childArea instanceof LineArea) {
+                curBlockArea.addLineArea((LineArea) childArea);
+            } else {
+                curBlockArea.addBlock((Block) childArea);
+            }
+        }
+    }
+
+    /**
+     * Force current area to be added to parent area.
+     */
+    protected void flush() {
+        if (getCurrentArea() != null) {
+            parentLayoutManager.addChildArea(getCurrentArea());
+        }
+    }
+
+    private Area getCurrentArea() {
+        return curBlockArea;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void addAreas(PositionIterator parentIter,
+            LayoutContext layoutContext) {
+
+        getParentArea(null);
+
+        addId();
+
+        LayoutManager childLM;
+        LayoutContext lc = LayoutContext.offspringOf(layoutContext);
+        LayoutManager firstLM = null;
+        LayoutManager lastLM = null;
+        Position firstPos = null;
+        Position lastPos = null;
+
+        // "unwrap" the NonLeafPositions stored in parentIter
+        // and put them in a new list;
+        LinkedList<Position> positionList = new LinkedList<Position>();
+        Position pos;
+        while (parentIter.hasNext()) {
+            pos = parentIter.next();
+            if (pos.getIndex() >= 0) {
+                if (firstPos == null) {
+                    firstPos = pos;
+                }
+                lastPos = pos;
+            }
+            if (pos instanceof NonLeafPosition && (pos.getPosition() != null)
+                    && pos.getPosition().getLM() != this) {
+                // pos was created by a child of this BestFitBlockLM
+                positionList.add(pos.getPosition());
+                lastLM = pos.getPosition().getLM();
+                if (firstLM == null) {
+                    firstLM = lastLM;
+                }
+            }
+        }
+
+        registerMarkers(true, isFirst(firstPos), isLast(lastPos));
+
+        PositionIterator childPosIter = new PositionIterator(
+                positionList.listIterator());
+        while ((childLM = childPosIter.getNextChildLM()) != null) {
+            // Add the block areas to Area
+            // set the space adjustment ratio
+            lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
+            lc.setFlags(LayoutContext.FIRST_AREA, childLM == firstLM);
+            lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM);
+            lc.setStackLimitBP(layoutContext.getStackLimitBP());
+            childLM.addAreas(childPosIter, lc);
+        }
+
+        registerMarkers(false, isFirst(firstPos), isLast(lastPos));
+
+        flush();
+
+        curBlockArea = null;
+
+        checkEndOfLayout(lastPos);
+    }
+
+    /** {@inheritDoc} */
+    public boolean isRestartable() {
+        return true;
+    }
+
+}

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeBlockLayoutManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeBlockLayoutManager.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Added: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeManager.java?rev=1518691&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeManager.java (added)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeManager.java Thu Aug 29 16:26:12 2013
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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$ */
+
+package org.apache.fop.layoutmgr;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A simple alternative manager that holds a set of {@link Alternative}
+ */
+public class AlternativeManager {
+
+    public static class Alternative {
+
+        /** remaining BPD after inserting the alternative */
+        private int remainingBPD;
+        /** width of the alternative in block-progressing-dimension */
+        private int width;
+        /** Knuth element list */
+        private List<ListElement> knuthList;
+
+        public Alternative(List<ListElement> knuthList, int width) {
+            this.knuthList = knuthList;
+            this.width = width;
+            this.remainingBPD = 0;
+        }
+        public List<ListElement> getKnuthList() {
+            return knuthList;
+        }
+        public int getRemainingBPD() {
+            return remainingBPD;
+        }
+        public int getWidth() {
+            return width;
+        }
+        public void setRemainingBPD(int remainingBPD) {
+            this.remainingBPD = remainingBPD;
+        }
+    }
+
+    public static enum FittingStrategy {
+
+        FIRST_FIT {
+
+            @Override
+            public Alternative filter(List<Alternative> alternatives) {
+                for (Alternative alt : alternatives) {
+                    if (alt.getRemainingBPD() > 0) {
+                        return alt;
+                    }
+                }
+                return null;
+            }
+        },
+
+        SMALLEST_FIT {
+
+            @Override
+            public Alternative filter(List<Alternative> alternatives) {
+                Iterator<Alternative> iter = alternatives.iterator();
+                int biggestDiff = -Integer.MAX_VALUE;
+                Alternative bestAlt = null;
+
+                while (iter.hasNext()) {
+                    Alternative alt = iter.next();
+                    if (alt.getRemainingBPD() > biggestDiff) {
+                        biggestDiff = alt.getRemainingBPD();
+                        bestAlt = alt;
+                    }
+                }
+                return bestAlt;
+            }
+        },
+
+        BIGGEST_FIT {
+
+            @Override
+            public Alternative filter(List<Alternative> alternatives) {
+                Iterator<Alternative> iter = alternatives.iterator();
+                int smallestDiff = Integer.MAX_VALUE;
+                Alternative bestAlt = null;
+
+                while (iter.hasNext()) {
+                    Alternative alt = iter.next();
+                    if (alt.getRemainingBPD() < smallestDiff) {
+                        smallestDiff = alt.getRemainingBPD();
+                        bestAlt = alt;
+                    }
+                }
+                return bestAlt;
+            }
+        };
+
+        public abstract Alternative filter(List<Alternative> alternatives);
+
+    }
+
+    private LinkedList<Alternative> alternatives;
+    private LinkedList<Alternative> bestAlternatives;
+
+    public AlternativeManager() {
+        alternatives = new LinkedList<Alternative>();
+        bestAlternatives = new LinkedList<Alternative>();
+    }
+
+    public void addAlternative(Alternative alt) {
+        alternatives.add(alt);
+    }
+
+    public boolean hasAny() {
+        return bestAlternatives.size() > 0;
+    }
+
+    public Alternative getNextBestAlternative() {
+        return bestAlternatives.removeFirst();
+    }
+
+    public Alternative getBestAlternative(FittingStrategy strategy) {
+        try {
+            Alternative bestAlt = strategy.filter(alternatives);
+            if (bestAlt != null) {
+                bestAlternatives.add(bestAlt);
+            }
+            return bestAlt;
+        } catch (NullPointerException e) {
+            return null;
+        } finally {
+            // We don't need the store alternatives anymore
+            alternatives.clear();
+        }
+    }
+}

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/AlternativeManager.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Added: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitLayoutManager.java?rev=1518691&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitLayoutManager.java (added)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitLayoutManager.java Thu Aug 29 16:26:12 2013
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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$ */
+
+package org.apache.fop.layoutmgr;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Stack;
+
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.LineArea;
+import org.apache.fop.fo.extensions.BestFit;
+import org.apache.fop.layoutmgr.AlternativeManager.Alternative;
+import org.apache.fop.layoutmgr.AlternativeManager.FittingStrategy;
+
+/**
+ * LayoutManager for a fox:best-fit. It selects the "best" alternative
+ * to render based on the chosen fitting strategy.
+ */
+public class BestFitLayoutManager extends AbstractLayoutManager {
+
+    private Block curBlockArea;
+
+    private static class BestFitPosition extends Position {
+
+        public BestFitPosition(LayoutManager lm) {
+            super(lm);
+        }
+
+    }
+
+    private FittingStrategy fittingStrategy;
+
+    public BestFitLayoutManager(BestFit node) {
+        super(node);
+        fittingStrategy = node.getStrategy();
+        setGeneratesBlockArea(true);
+    }
+
+    /**
+     * Creates and initializes a {@link LayoutContext} to pass to the child LM
+     *
+     * @param context the parent {@link LayoutContext}
+     * @return a new child layout context
+     */
+    protected LayoutContext makeChildLayoutContext(LayoutContext context) {
+        LayoutContext childLC = LayoutContext.newInstance();
+        childLC.copyPendingMarksFrom(context);
+        childLC.setStackLimitBP(context.getStackLimitBP());
+        childLC.setRefIPD(context.getRefIPD());
+        childLC.setWritingMode(context.getWritingMode());
+        return childLC;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public List getNextKnuthElements(LayoutContext context, int alignment) {
+        return getNextKnuthElements(context, alignment, null, null, null);
+    }
+
+    /** {@inheritDoc} */
+    public List getNextKnuthElements(LayoutContext context, int alignment,
+            Stack lmStack, Position positionAtIPDChange,
+            LayoutManager restartAtLM) {
+        LayoutManager curLM; // currently active LM
+        BestFitPenalty bestFitPenalty =
+                new BestFitPenalty(fittingStrategy, new BestFitPosition(this));
+        while ((curLM = getChildLM()) != null) {
+            LayoutContext childLC = makeChildLayoutContext(context);
+
+            List returnedList = null;
+            if (!curLM.isFinished()) {
+                returnedList = curLM.getNextKnuthElements(childLC, alignment);
+            }
+            if (returnedList != null) {
+                List<ListElement> returnList = new LinkedList<ListElement>();
+                this.wrapPositionElements(returnedList, returnList);
+                int contentLength = ElementListUtils.calcFullContentLength(returnList);
+                // Add a new variant
+                bestFitPenalty.addAlternative(new Alternative(returnList, contentLength));
+            }
+        }
+        setFinished(true);
+        List<ListElement> finalList = new LinkedList<ListElement>();
+        // Insert an empty Knuth box to prevent the layout engine from ignoring our penalty
+        finalList.add(new KnuthBox(0, new Position(this), false));
+        finalList.add(bestFitPenalty);
+        return finalList;
+    }
+
+    /**
+     * "wrap" the Position inside each element moving the elements from
+     * SourceList to targetList
+     *
+     * @param sourceList source list
+     * @param targetList target list receiving the wrapped position elements
+     */
+    protected void wrapPositionElements(List sourceList, List targetList) {
+        wrapPositionElements(sourceList, targetList, false);
+    }
+
+    /**
+     * "wrap" the Position inside each element moving the elements from
+     * SourceList to targetList
+     *
+     * @param sourceList source list
+     * @param targetList target list receiving the wrapped position elements
+     * @param force if true, every Position is wrapped regardless of its LM of origin
+     */
+    protected void wrapPositionElements(List sourceList, List targetList,
+            boolean force) {
+
+        ListIterator listIter = sourceList.listIterator();
+        Object tempElement;
+        while (listIter.hasNext()) {
+            tempElement = listIter.next();
+            if (tempElement instanceof ListElement) {
+                wrapPositionElement((ListElement) tempElement, targetList,
+                        force);
+            } else if (tempElement instanceof List) {
+                wrapPositionElements((List) tempElement, targetList, force);
+            }
+        }
+    }
+
+    /**
+     * "wrap" the Position inside the given element and add it to the target list.
+     *
+     * @param el the list element
+     * @param targetList target list receiving the wrapped position elements
+     * @param force if true, every Position is wrapped regardless of its LM of origin
+     */
+    protected void wrapPositionElement(ListElement el, List targetList,
+            boolean force) {
+        if (force || el.getLayoutManager() != this) {
+            el.setPosition(notifyPos(new NonLeafPosition(this, el.getPosition())));
+        }
+        targetList.add(el);
+    }
+
+    @Override
+    public Area getParentArea(Area childArea) {
+        if (curBlockArea == null) {
+            curBlockArea = new Block();
+            // Set up dimensions
+            // Must get dimensions from parent area
+            /*Area parentArea = */parentLayoutManager.getParentArea(curBlockArea);
+        }
+        return curBlockArea;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void addChildArea(Area childArea) {
+        if (curBlockArea != null) {
+            if (childArea instanceof LineArea) {
+                curBlockArea.addLineArea((LineArea) childArea);
+            } else {
+                curBlockArea.addBlock((Block) childArea);
+            }
+        }
+    }
+
+    /**
+     * Force current area to be added to parent area.
+     */
+    protected void flush() {
+        if (getCurrentArea() != null) {
+            parentLayoutManager.addChildArea(getCurrentArea());
+        }
+    }
+
+    private Area getCurrentArea() {
+        return curBlockArea;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void addAreas(PositionIterator parentIter,
+            LayoutContext layoutContext) {
+
+        getParentArea(null);
+
+        addId();
+
+        LayoutManager childLM;
+        LayoutContext lc = LayoutContext.offspringOf(layoutContext);
+        LayoutManager firstLM = null;
+        LayoutManager lastLM = null;
+        Position firstPos = null;
+        Position lastPos = null;
+
+        // "unwrap" the NonLeafPositions stored in parentIter
+        // and put them in a new list;
+        LinkedList<Position> positionList = new LinkedList<Position>();
+        Position pos;
+        AlternativeManager altManager = layoutContext.getAlternativeManager();
+        while (parentIter.hasNext()) {
+            pos = parentIter.next();
+            if (pos.getIndex() >= 0) {
+                if (firstPos == null) {
+                    firstPos = pos;
+                }
+                lastPos = pos;
+            }
+            if (pos instanceof NonLeafPosition && (pos.getPosition() != null)
+                    && pos.getPosition().getLM() != this) {
+                // pos was created by a child of this BestFitBlockLM
+                positionList.add(pos.getPosition());
+                lastLM = pos.getPosition().getLM();
+                if (firstLM == null) {
+                    firstLM = lastLM;
+                }
+            }
+            else if (pos instanceof BestFitPosition) {
+                if (altManager.hasAny()) {
+                    Alternative bestAlt = altManager.getNextBestAlternative();
+                    Iterator<ListElement> it = bestAlt.getKnuthList().iterator();
+                    while (it.hasNext()) {
+                        positionList.add(it.next().getPosition());
+                    }
+                }
+                lastLM = pos.getLM();
+                if (firstLM == null) {
+                    firstLM = lastLM;
+                }
+            }
+        }
+
+        //registerMarkers(true, isFirst(firstPos), isLast(lastPos));
+
+        PositionIterator childPosIter = new PositionIterator(
+                positionList.listIterator());
+        while ((childLM = childPosIter.getNextChildLM()) != null) {
+            // Add the block areas to Area
+            // set the space adjustment ratio
+            lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
+            lc.setFlags(LayoutContext.FIRST_AREA, childLM == firstLM);
+            lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM);
+            lc.setStackLimitBP(layoutContext.getStackLimitBP());
+            childLM.addAreas(childPosIter, lc);
+        }
+
+        //registerMarkers(false, isFirst(firstPos), isLast(lastPos));
+
+        flush();
+
+        curBlockArea = null;
+
+        checkEndOfLayout(lastPos);
+    }
+
+    /** {@inheritDoc} */
+    public boolean isRestartable() {
+        return true;
+    }
+
+}

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitLayoutManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitLayoutManager.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Added: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitPenalty.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitPenalty.java?rev=1518691&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitPenalty.java (added)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitPenalty.java Thu Aug 29 16:26:12 2013
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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$ */
+
+package org.apache.fop.layoutmgr;
+
+import java.util.LinkedList;
+
+import org.apache.fop.layoutmgr.AlternativeManager.Alternative;
+import org.apache.fop.layoutmgr.AlternativeManager.FittingStrategy;
+
+/**
+ * A dummy penalty used in {@link BestFitLayoutManager} to store
+ * the different alternatives in {@link fox:best-fit}
+ */
+
+public class BestFitPenalty extends KnuthPenalty {
+
+    private LinkedList<Alternative> alternatives;
+    private FittingStrategy strategy;
+
+    public BestFitPenalty(FittingStrategy strategy, Position pos) {
+        super(0, 0, false, pos, false);
+        this.strategy = strategy;
+        alternatives = new LinkedList<Alternative>();
+    }
+
+    public void addAlternative(Alternative alternative) {
+        alternatives.add(alternative);
+    }
+
+    public Alternative getAlternative(int index) {
+        return alternatives.get(index);
+    }
+
+    public int getAlternativeCount() {
+        return alternatives.size();
+    }
+
+    public FittingStrategy getStrategyType() {
+        return strategy;
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        String str = super.toString();
+        StringBuffer buffer = new StringBuffer(64);
+        buffer.append(" number of alternatives = " + getAlternativeCount());
+        buffer.append(" fitting-strategy = " + strategy);
+        return str + buffer.toString();
+    }
+
+}

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitPenalty.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BestFitPenalty.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java Thu Aug 29 16:26:12 2013
@@ -23,6 +23,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.apache.fop.fo.Constants;
+import org.apache.fop.layoutmgr.AlternativeManager.Alternative;
 
 /**
  * The set of nodes is sorted into lines indexed into activeLines.
@@ -192,6 +193,8 @@ public abstract class BreakingAlgorithm 
     private boolean partOverflowRecoveryActivated = true;
     private KnuthNode lastRecovered;
 
+    private AlternativeManager altManager = new AlternativeManager();
+
     /**
      * Create a new instance.
      *
@@ -822,6 +825,30 @@ public abstract class BreakingAlgorithm 
         }
     }
 
+    private int handleBestFitPenalty(BestFitPenalty penalty, KnuthNode node,
+            int elementIdx) {
+        int difference;
+        // Find the alternatives that can be fitted inside the remaining space
+        for (int i = 0; i < penalty.getAlternativeCount(); ++i) {
+            Alternative alt = penalty.getAlternative(i);
+            difference = computeDifference(node, new KnuthPenalty(alt.getWidth(),
+                    0, false, null, false), elementIdx);
+            if (difference > 0) {
+                alt.setRemainingBPD(difference);
+                altManager.addAlternative(alt);
+            }
+        }
+        Alternative bestAlt = altManager.getBestAlternative(penalty.getStrategyType());
+        if (bestAlt != null) {
+            difference = bestAlt.getRemainingBPD();
+            return difference;
+        } else {
+            // No alternative can be fitted inside the remaining space
+            return computeDifference(node, new KnuthPenalty(0,
+                    0, false, null, false), elementIdx);
+        }
+    }
+
     /**
      * Replace the last too-long or too-short node by the last deactivated
      * node, if applicable.
@@ -930,7 +957,13 @@ public abstract class BreakingAlgorithm 
                 if (node.position == elementIdx) {
                     continue;
                 }
-                int difference = computeDifference(node, element, elementIdx);
+                int difference;
+                if (element instanceof BestFitPenalty) {
+                    BestFitPenalty penalty = (BestFitPenalty)element;
+                    difference = handleBestFitPenalty(penalty, node, elementIdx);
+                } else {
+                    difference = computeDifference(node, element, elementIdx);
+                }
                 if (!elementCanEndLine(element, endLine, difference)) {
                     log.trace("Skipping legal break");
                     break;
@@ -1451,4 +1484,9 @@ public abstract class BreakingAlgorithm 
         return this.alignmentLast;
     }
 
+    /** @return the alternative manager (used by fox:best-fit) */
+    public AlternativeManager getAlternativeManager() {
+        return altManager;
+    }
+
 }

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/ElementListUtils.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/ElementListUtils.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/ElementListUtils.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/ElementListUtils.java Thu Aug 29 16:26:12 2013
@@ -163,6 +163,37 @@ public final class ElementListUtils {
     }
 
     /**
+     * Calculates the full content length of the given element list. Warning: It doesn't take any
+     * stretch and shrink possibilities into account.
+     * @param elems the element list
+     * @return the content length
+     */
+    public static int calcFullContentLength(List elems) {
+        ListIterator iter = elems.listIterator(0);
+        int count = elems.size();
+        int len = 0;
+        while (iter.hasNext()) {
+            ListElement el = (ListElement)iter.next();
+            if (el.isBox()) {
+                len += ((KnuthElement)el).getWidth();
+            } else if (el.isGlue()) {
+                len += ((KnuthElement)el).getWidth();
+            }
+            else if (el.isUnresolvedElement() && (el instanceof BreakElement) == false) {
+                // Handle properties space-before and space-after
+                UnresolvedListElementWithLength uresolvedEl = (UnresolvedListElementWithLength)el;
+                if (uresolvedEl.isLast() || uresolvedEl.isFirst())
+                    len += uresolvedEl.getLength().getOpt();
+            }
+            count--;
+            if (count == 0) {
+                break;
+            }
+        }
+        return len;
+    }
+
+    /**
      * Calculates the content length of the given element list. Warning: It doesn't take any
      * stretch and shrink possibilities into account.
      * @param elems the element list
@@ -201,7 +232,7 @@ public final class ElementListUtils {
         if (last.isPenalty() && ((KnuthPenalty)last).getPenalty() < KnuthElement.INFINITE) {
             return true;
         } else if (last instanceof BreakElement
-                        && ((BreakElement)last).getPenaltyValue() < KnuthElement.INFINITE) {
+                && ((BreakElement)last).getPenaltyValue() < KnuthElement.INFINITE) {
             return true;
         }
         return false;

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java Thu Aug 29 16:26:12 2013
@@ -204,6 +204,7 @@ public class FlowLayoutManager extends B
         childLC.setStackLimitBP(context.getStackLimitBP());
         childLC.setRefIPD(context.getRefIPD());
         childLC.setWritingMode(getCurrentPage().getSimplePageMaster().getWritingMode());
+        childLC.setAlternativeManager(context.getAlternativeManager());
         return childLC;
     }
 

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutContext.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutContext.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutContext.java Thu Aug 29 16:26:12 2013
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.extensions.AlternativeBlock;
 import org.apache.fop.layoutmgr.inline.AlignmentContext;
 import org.apache.fop.layoutmgr.inline.HyphContext;
 import org.apache.fop.traits.MinOptMax;
@@ -35,6 +36,9 @@ import org.apache.fop.traits.WritingMode
  */
 public final class LayoutContext {
 
+    /** Manager of @{link {@link AlternativeBlock} and only used by {@link BestFitLayoutManager}*/
+    private AlternativeManager altManager;
+
     /** Generated break possibility is first in a new area */
     public static final int NEW_AREA = 0x01;
 
@@ -142,6 +146,7 @@ public final class LayoutContext {
     public static LayoutContext offspringOf(LayoutContext parent) {
         LayoutContext offspring = new LayoutContext(0);
         offspring.setTreatAsArtifact(parent.treatAsArtifact());
+        offspring.setAlternativeManager(parent.getAlternativeManager());
         return offspring;
     }
 
@@ -646,24 +651,24 @@ public final class LayoutContext {
     /** {@inheritDoc} */
     public String toString() {
         return "Layout Context:"
-        + "\nStack Limit BPD: \t"
-            + (getStackLimitBP() == null ? "null" : getStackLimitBP().toString())
-        + "\nTrailing Space: \t"
-            + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString())
-        + "\nLeading Space: \t"
-            + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString())
-        + "\nReference IPD: \t" + getRefIPD()
-        + "\nSpace Adjust: \t" + getSpaceAdjust()
-        + "\nIPD Adjust: \t" + getIPDAdjust()
-        + "\nResolve Leading Space: \t" + resolveLeadingSpace()
-        + "\nSuppress Break Before: \t" + suppressBreakBefore()
-        + "\nIs First Area: \t" + isFirstArea()
-        + "\nStarts New Area: \t" + startsNewArea()
-        + "\nIs Last Area: \t" + isLastArea()
-        + "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending()
+                + "\nStack Limit BPD: \t"
+                + (getStackLimitBP() == null ? "null" : getStackLimitBP().toString())
+                + "\nTrailing Space: \t"
+                + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString())
+                + "\nLeading Space: \t"
+                + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString())
+                + "\nReference IPD: \t" + getRefIPD()
+                + "\nSpace Adjust: \t" + getSpaceAdjust()
+                + "\nIPD Adjust: \t" + getIPDAdjust()
+                + "\nResolve Leading Space: \t" + resolveLeadingSpace()
+                + "\nSuppress Break Before: \t" + suppressBreakBefore()
+                + "\nIs First Area: \t" + isFirstArea()
+                + "\nStarts New Area: \t" + startsNewArea()
+                + "\nIs Last Area: \t" + isLastArea()
+                + "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending()
                 + "][keep-with-previous=" + getKeepWithPreviousPending() + "] pending"
-        + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "]["
-        + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]";
+                + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "]["
+                + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]";
     }
 
     /**
@@ -692,5 +697,13 @@ public final class LayoutContext {
     public void setTreatAsArtifact(boolean treatAsArtifact) {
         setFlags(TREAT_AS_ARTIFACT, treatAsArtifact);
     }
+
+    public void setAlternativeManager(AlternativeManager altManager) {
+        this.altManager = altManager;
+    }
+
+    public AlternativeManager getAlternativeManager() {
+        return altManager;
+    }
 }
 

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java Thu Aug 29 16:26:12 2013
@@ -34,6 +34,8 @@ import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.FONode.FONodeIterator;
 import org.apache.fop.fo.FOText;
 import org.apache.fop.fo.FObjMixed;
+import org.apache.fop.fo.extensions.AlternativeBlock;
+import org.apache.fop.fo.extensions.BestFit;
 import org.apache.fop.fo.extensions.ExternalDocument;
 import org.apache.fop.fo.flow.BasicLink;
 import org.apache.fop.fo.flow.BidiOverride;
@@ -142,6 +144,8 @@ public class LayoutManagerMapping implem
         registerMaker(TableHeader.class, new Maker());
         registerMaker(Wrapper.class, new WrapperLayoutManagerMaker());
         registerMaker(Title.class, new InlineLayoutManagerMaker());
+        registerMaker(BestFit.class, new BestFitLayoutManagerMaker());
+        registerMaker(AlternativeBlock.class, new AlternativeBlockLayoutManagerMaker());
     }
 
     /**
@@ -445,4 +449,20 @@ public class LayoutManagerMapping implem
         }
     }
 
+    /** a layout manager maker */
+    public class BestFitLayoutManagerMaker extends Maker {
+        /** {@inheritDoc} */
+        public void make(FONode node, List lms) {
+            lms.add(new BestFitLayoutManager((BestFit) node));
+        }
+    }
+
+    /** a layout manager maker */
+    public class AlternativeBlockLayoutManagerMaker extends Maker {
+        /** {@inheritDoc} */
+        public void make(FONode node, List lms) {
+            lms.add(new AlternativeBlockLayoutManager((AlternativeBlock) node));
+        }
+    }
+
 }

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java Thu Aug 29 16:26:12 2013
@@ -26,7 +26,6 @@ import java.util.ListIterator;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.FObj;
 import org.apache.fop.layoutmgr.AbstractBreaker.PageBreakPosition;

Modified: xmlgraphics/fop/branches/Temp_WhitespaceManagement/test/java/org/apache/fop/KnuthAlgorithmTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_WhitespaceManagement/test/java/org/apache/fop/KnuthAlgorithmTestCase.java?rev=1518691&r1=1518690&r2=1518691&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_WhitespaceManagement/test/java/org/apache/fop/KnuthAlgorithmTestCase.java (original)
+++ xmlgraphics/fop/branches/Temp_WhitespaceManagement/test/java/org/apache/fop/KnuthAlgorithmTestCase.java Thu Aug 29 16:26:12 2013
@@ -19,10 +19,16 @@
 
 package org.apache.fop;
 
-import static org.junit.Assert.assertEquals;
-
 import java.util.List;
 
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.fop.layoutmgr.AlternativeManager.Alternative;
+import org.apache.fop.layoutmgr.AlternativeManager.FittingStrategy;
+import org.apache.fop.layoutmgr.BestFitPenalty;
 import org.apache.fop.layoutmgr.BlockKnuthSequence;
 import org.apache.fop.layoutmgr.BreakingAlgorithm;
 import org.apache.fop.layoutmgr.ElementListObserver;
@@ -30,8 +36,6 @@ import org.apache.fop.layoutmgr.KnuthBox
 import org.apache.fop.layoutmgr.KnuthGlue;
 import org.apache.fop.layoutmgr.KnuthPenalty;
 import org.apache.fop.layoutmgr.KnuthSequence;
-import org.junit.Before;
-import org.junit.Test;
 
 /**
  * Tests the Knuth algorithm implementation.
@@ -63,6 +67,27 @@ public class KnuthAlgorithmTestCase {
         return seq;
     }
 
+    private static class BestFitPenaltyTestCase {
+
+        private static KnuthSequence getKnuthSequence() {
+            KnuthSequence seq = new BlockKnuthSequence();
+            FittingStrategy strategies[] = {FittingStrategy.FIRST_FIT,
+                    FittingStrategy.SMALLEST_FIT,
+                    FittingStrategy.BIGGEST_FIT};
+            for (int i = 0; i < 3; ++i) {
+                BestFitPenalty bestFitPenalty = new BestFitPenalty(strategies[i], null);
+                bestFitPenalty.addAlternative(new Alternative(null, 25000));
+                bestFitPenalty.addAlternative(new Alternative(null, 5000));
+                bestFitPenalty.addAlternative(new Alternative(null, 29000));
+                seq.add(new KnuthBox(0, null, false));
+                seq.add(bestFitPenalty);
+                seq.add(new KnuthPenalty(0, -KnuthPenalty.INFINITE, false, null, false));
+            }
+            return seq;
+        }
+
+    }
+
     /**
      * Tests a special condition where a negative-length glue occurs directly after a break
      * possibility.
@@ -79,6 +104,22 @@ public class KnuthAlgorithmTestCase {
         assertEquals(5000, parts[0].difference);
         assertEquals(5000, parts[1].difference);
     }
+    /**
+     * Testcase for BestFitPenalty
+     * @throws Exception if an error occurs
+     */
+    @Test
+    public void test2() throws Exception {
+        MyBreakingAlgorithm algo = new MyBreakingAlgorithm(0, 0, true, true, 0);
+        algo.setConstantLineWidth(30000);
+        KnuthSequence seq = BestFitPenaltyTestCase.getKnuthSequence();
+        algo.findBreakingPoints(seq, 1, true, BreakingAlgorithm.ALL_BREAKS);
+        Part[] parts = algo.getParts();
+        assertEquals("Sequence must produce 3 parts", 3, parts.length);
+        assertEquals(5000, 	parts[0].difference);
+        assertEquals(25000, parts[1].difference);
+        assertEquals(1000, 	parts[2].difference);
+    }
 
     private class Part {
         private int difference;
@@ -88,7 +129,7 @@ public class KnuthAlgorithmTestCase {
 
     private class MyBreakingAlgorithm extends BreakingAlgorithm {
 
-        private List parts = new java.util.ArrayList();
+        private List<Part> parts = new java.util.ArrayList<Part>();
 
         public MyBreakingAlgorithm(int align, int alignLast, boolean first,
                     boolean partOverflowRecovery, int maxFlagCount) {
@@ -96,7 +137,7 @@ public class KnuthAlgorithmTestCase {
         }
 
         public Part[] getParts() {
-            return (Part[])parts.toArray(new Part[parts.size()]);
+            return parts.toArray(new Part[parts.size()]);
         }
 
         public void updateData1(int total, double demerits) {



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