]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Attach the selected variant to KnuthPageNode in order to propagate the information...
authorVincent Hennebert <vhennebert@apache.org>
Fri, 13 Dec 2013 23:04:04 +0000 (23:04 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Fri, 13 Dec 2013 23:04:04 +0000 (23:04 +0000)
Patch by Seifeddine Dridi, applied with some modifications.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_WhitespaceManagement@1550847 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/layoutmgr/BestFitLayoutUtils.java
src/java/org/apache/fop/layoutmgr/BestFitPenalty.java
src/java/org/apache/fop/layoutmgr/MultiSwitchLayoutManager.java
src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java

index 352a876d478387b9f96c34e5b514118507c354b4..17dddc2394e562b3c24299b2b3643d579c06c20c 100644 (file)
@@ -17,7 +17,6 @@
 
 package org.apache.fop.layoutmgr;
 
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -36,10 +35,12 @@ public final class BestFitLayoutUtils {
         public BestFitPosition(LayoutManager lm) {
             super(lm);
         }
+
         public BestFitPosition(LayoutManager lm, List<ListElement> knuthList) {
             super(lm);
             this.knuthList = knuthList;
         }
+
         public List<Position> getPositionList() {
             List<Position> positions = new LinkedList<Position>();
             if (knuthList != null) {
@@ -62,17 +63,16 @@ public final class BestFitLayoutUtils {
 
         List<ListElement> knuthList = new LinkedList<ListElement>();
 
-        Iterator<List<ListElement>> iter = childrenLists.iterator();
-        while (iter.hasNext()) {
-
-            List<ListElement> childList = iter.next();
+        BestFitPenalty bestFitPenalty = new BestFitPenalty(new BestFitPosition(lm));
+        for (List<ListElement> childList : childrenLists) {
             SpaceResolver.resolveElementList(childList);
             int contentLength = ElementListUtils.calcContentLength(childList);
-            BestFitPenalty bestFitPenalty =
-                    new BestFitPenalty(contentLength, childList,
-                    new BestFitPosition(lm));
-            knuthList.add(bestFitPenalty);
+            bestFitPenalty.addVariant(childList, contentLength);
         }
+        // TODO Adding the two enclosing boxes is definitely a dirty hack.
+        // Let's leave it like that for now, until I find a proper fix.
+        knuthList.add(new KnuthBox(0, new Position(lm), false));
+        knuthList.add(bestFitPenalty);
         knuthList.add(new KnuthBox(0, new Position(lm), false));
         return knuthList;
     }
index 13c88e82c81e23ccec0fa0aa460ac22684a3adc5..0f77edc8dbaffa07171f4651c20edc1b41c85f85 100644 (file)
 
 package org.apache.fop.layoutmgr;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.fop.layoutmgr.BestFitLayoutUtils.BestFitPosition;
 
 /**
- * A penalty class used to specify a set of alternatives for the layout engine
+ * A type of penalty used to specify a set of alternatives for the layout engine
  * to choose from. The chosen alternative must have an occupied size
- * that is less than the available BPD of the current page
- * and it must also be the best match when it is evaluated by {@link FittingStrategy}.
+ * that is less than the available BPD of the current page.
  */
 public class BestFitPenalty extends KnuthPenalty {
 
-    private final List<ListElement> knuthList;
-    public boolean ignorePenalty;
+    public class Variant {
 
-    public BestFitPenalty(int width, List<ListElement> knuthList, Position pos) {
-        super(width, 0, false, pos, false);
-        this.knuthList = knuthList;
+        public final List<ListElement> knuthList;
+        public final int width;
+
+        public Variant(List<ListElement> knuthList, int width) {
+            this.knuthList = knuthList;
+            this.width = width;
+        }
+        public KnuthElement toPenalty() {
+            return new KnuthPenalty(width, 0, false, null, false);
+        }
     }
 
-    public void activateContent() {
-        BestFitPosition pos = getBestFitPosition();
-        pos.setKnuthList(knuthList);
+    private final BestFitPosition bestFitPosition;
+
+    private final List<Variant> variantList;
+
+    public BestFitPenalty(BestFitPosition pos) {
+        super(0, 0, false, pos, false);
+        this.bestFitPosition = pos;
+        variantList = new ArrayList<Variant>();
     }
 
-    public int getWidth() {
-        if (ignorePenalty) {
-            return 0;
-        }
-        return super.getWidth();
+    public void addVariant(List<ListElement> knuthList, int width) {
+        variantList.add(new Variant(knuthList, width));
     }
 
-    public BestFitPosition getBestFitPosition() {
-        Position pos = super.getPosition();
-        while (pos != null) {
-            if (pos instanceof BestFitPosition) {
-                return (BestFitPosition) pos;
-            }
-            pos = pos.getPosition();
-        }
-        return null;
+    public void activatePenalty(Variant bestVariant) {
+        bestFitPosition.setKnuthList(bestVariant.knuthList);
+    }
+
+    public List<Variant> getVariantList() {
+        return variantList;
     }
 
     @Override
     public String toString() {
         String str = super.toString();
         StringBuffer buffer = new StringBuffer(64);
-//        buffer.append(" number of alternatives = " + alternatives.size());
-//        buffer.append(" fitting-strategy = " + strategy.getStrategyName());
+        buffer.append(" number of variants = " + variantList.size());
         return str + buffer.toString();
     }
 
index 50dee48b4fbc224046d4ca06a0fc0398ecde4aff..386aba39b24d0433be01fb5b95bd209ef72443ab 100644 (file)
@@ -137,7 +137,7 @@ public class MultiSwitchLayoutManager extends BlockStackingLayoutManager {
      */
     @Override
     protected void flush() {
-        if (getCurrentArea() != null) {
+        if (curBlockArea != null) {
             parentLayoutManager.addChildArea(getCurrentArea());
         }
     }
@@ -151,6 +151,7 @@ public class MultiSwitchLayoutManager extends BlockStackingLayoutManager {
 
         AreaAdditionUtil.addAreas(this, newPosIter, context);
         flush();
+        curBlockArea = null;
     }
 
 }
index b7e2413bbb2b063258e8e0c2b41eae8e69a3adde..6db928ee89cc77c4e91e5def25fd2acac8b284f1 100644 (file)
@@ -30,6 +30,7 @@ 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;
+import org.apache.fop.layoutmgr.BestFitPenalty.Variant;
 import org.apache.fop.traits.MinOptMax;
 import org.apache.fop.util.ListUtil;
 
@@ -98,6 +99,9 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
     private int currentKeepContext = Constants.EN_AUTO;
     private KnuthNode lastBeforeKeepContextSwitch;
 
+    /** Holds the variant that should be assigned to the next node to be created */
+    private Variant variant;
+
     /**
      * Construct a page breaking algorithm.
      * @param topLevelLM the top level layout manager
@@ -149,12 +153,14 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
         /** Index of the last inserted element of the last inserted footnote. */
         public int footnoteElementIndex;
 
+        public final Variant variant;
+
         public KnuthPageNode(int position,
                              int line, int fitness,
                              int totalWidth, int totalStretch, int totalShrink,
                              int totalFootnotes, int footnoteListIndex, int footnoteElementIndex,
                              double adjustRatio, int availableShrink, int availableStretch,
-                             int difference, double totalDemerits, KnuthNode previous) {
+                             int difference, double totalDemerits, KnuthNode previous, Variant variant) {
             super(position, line, fitness,
                   totalWidth, totalStretch, totalShrink,
                   adjustRatio, availableShrink, availableStretch,
@@ -162,6 +168,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
             this.totalFootnotes = totalFootnotes;
             this.footnoteListIndex = footnoteListIndex;
             this.footnoteElementIndex = footnoteElementIndex;
+            this.variant = variant;
         }
 
     }
@@ -175,6 +182,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
         private final int[] bestFootnotesLength = new int[4];
         private final int[] bestFootnoteListIndex = new int[4];
         private final int[] bestFootnoteElementIndex = new int[4];
+        private final Variant[] bestVariant = new Variant[4];
 
         @Override
         public void addRecord(double demerits, KnuthNode node, double adjust,
@@ -186,6 +194,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
             bestFootnotesLength[fitness] = insertedFootnotesLength;
             bestFootnoteListIndex[fitness] = footnoteListIndex;
             bestFootnoteElementIndex[fitness] = footnoteElementIndex;
+            bestVariant[fitness] = variant;
         }
 
         public int getFootnotesLength(int fitness) {
@@ -199,6 +208,10 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
         public int getFootnoteElementIndex(int fitness) {
             return bestFootnoteElementIndex[fitness];
         }
+
+        public Variant getVariant(int fitness) {
+            return bestVariant[fitness];
+        }
     }
 
     /** {@inheritDoc} */
@@ -290,7 +303,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
                                  totalWidth, totalStretch, totalShrink,
                                  insertedFootnotesLength, footnoteListIndex, footnoteElementIndex,
                                  adjustRatio, availableShrink, availableStretch,
-                                 difference, totalDemerits, previous);
+                                 difference, totalDemerits, previous, variant);
     }
 
     /** {@inheritDoc} */
@@ -304,7 +317,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
                                  ((BestPageRecords) best).getFootnoteElementIndex(fitness),
                                  best.getAdjust(fitness), best.getAvailableShrink(fitness),
                                  best.getAvailableStretch(fitness), best.getDifference(fitness),
-                                 best.getDemerits(fitness), best.getNode(fitness));
+                                 best.getDemerits(fitness), best.getNode(fitness),
+                                 ((BestPageRecords) best).getVariant(fitness));
     }
 
     /**
@@ -432,6 +446,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
     /** {@inheritDoc} */
     @Override
     protected void considerLegalBreak(KnuthElement element, int elementIdx) {
+        variant = null;
         if (element.isPenalty()) {
             int breakClass = ((KnuthPenalty) element).getBreakClass();
             switch (breakClass) {
@@ -500,7 +515,11 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
         int footnoteSplit;
         boolean canDeferOldFN;
         if (element.isPenalty()) {
-            actualWidth += element.getWidth();
+            if (element instanceof BestFitPenalty) {
+                actualWidth += handleBestFitPenalty(activeNode, (BestFitPenalty) element, elementIndex);
+            } else {
+                actualWidth += element.getWidth();
+            }
         }
         if (footnotesPending) {
             // compute the total length of the footnotes not yet inserted
@@ -560,6 +579,18 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
         }
     }
 
+    private int handleBestFitPenalty(KnuthNode activeNode, BestFitPenalty penalty, int elementIndex) {
+        for (Variant var : penalty.getVariantList()) {
+            int difference = computeDifference(activeNode, var.toPenalty(), elementIndex);
+            double r = computeAdjustmentRatio(activeNode, difference);
+            if (r >= -1.0) {
+                variant = var;
+                return variant.width;
+            }
+        }
+        return 0;
+    }
+
     /**
      * Checks whether footnotes from preceding pages may be deferred to the page after
      * the given element.
@@ -970,6 +1001,12 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
                             int total) {
         //int difference = (bestActiveNode.line < total)
         //      ? bestActiveNode.difference : bestActiveNode.difference + fillerMinWidth;
+        // Check if the given node has an attached dynamic content
+        KnuthPageNode pageNode = (KnuthPageNode) bestActiveNode;
+        if (pageNode.variant != null) {
+            BestFitPenalty penalty = (BestFitPenalty) par.get(pageNode.position);
+            penalty.activatePenalty(pageNode.variant);
+        }
         int difference = bestActiveNode.difference;
         if (difference + bestActiveNode.availableShrink < 0) {
             if (!autoHeight) {