]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Improved handling of explicit height/block-progression-dimension on table-cell and...
authorJeremias Maerki <jeremias@apache.org>
Fri, 13 May 2005 14:28:45 +0000 (14:28 +0000)
committerJeremias Maerki <jeremias@apache.org>
Fri, 13 May 2005 14:28:45 +0000 (14:28 +0000)
Some helper methods moved to a utility class: ElementListUtils.

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

src/java/org/apache/fop/layoutmgr/ElementListUtils.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/table/EffRow.java
src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableStepper.java

diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java
new file mode 100644 (file)
index 0000000..c1100d0
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.layoutmgr;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.fop.traits.MinOptMax;
+
+/**
+ * Utilities for Knuth element lists.
+ */
+public class ElementListUtils {
+
+    /**
+     * Removes all legal breaks in an element list.
+     * @param elements the element list
+     */
+    public static void removeLegalBreaks(LinkedList elements) {
+        ListIterator i = elements.listIterator();
+        while (i.hasNext()) {
+            KnuthElement el = (KnuthElement)i.next();
+            if (el.isPenalty()) {
+                KnuthPenalty penalty = (KnuthPenalty)el;
+                //Convert all penalties no break inhibitors
+                if (penalty.getP() < KnuthPenalty.INFINITE) {
+                    i.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE, 
+                            penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary()));
+                }
+            } else if (el.isGlue()) {
+                i.previous();
+                if (el.isBox()) {
+                    i.next();
+                    i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, 
+                            /*new Position(getTableLM())*/null, false));
+                }
+            }
+        }
+    }
+    
+    /**
+     * Removes all legal breaks in an element list. A constraint can be specified to limit the
+     * range in which the breaks are removed. Legal breaks occuring before at least 
+     * constraint.opt space is filled will be removed.
+     * @param elements the element list
+     * @param constraint min/opt/max value to restrict the range in which the breaks are removed.
+     * @return true if the opt constraint is bigger than the list contents
+     */
+    public static boolean removeLegalBreaks(LinkedList elements, MinOptMax constraint) {
+        int len = 0;
+        ListIterator i = elements.listIterator();
+        while (i.hasNext()) {
+            KnuthElement el = (KnuthElement)i.next();
+            if (el.isPenalty()) {
+                KnuthPenalty penalty = (KnuthPenalty)el;
+                //Convert all penalties no break inhibitors
+                if (penalty.getP() < KnuthPenalty.INFINITE) {
+                    i.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE, 
+                            penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary()));
+                }
+            } else if (el.isGlue()) {
+                len += el.getW();
+                i.previous();
+                if (el.isBox()) {
+                    i.next();
+                    i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, 
+                            /*new Position(getTableLM())*/null, false));
+                }
+            } else {
+                len += el.getW();
+            }
+            if (len > constraint.opt) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * 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
+     * @param start element at which to start
+     * @param end element at which to stop
+     * @return the content length
+     */
+    public static int calcContentLength(List elems, int start, int end) {
+        ListIterator iter = elems.listIterator(start);
+        int count = end - start + 1;
+        int len = 0;
+        while (iter.hasNext()) {
+            KnuthElement el = (KnuthElement)iter.next();
+            if (el.isBox()) {
+                len += el.getW();
+            } else if (el.isGlue()) {
+                len += el.getW();
+            } else {
+                //log.debug("Ignoring penalty: " + el);
+                //ignore penalties
+            }
+            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
+     * @return the content length
+     */
+    public static int calcContentLength(List elems) {
+        return calcContentLength(elems, 0, elems.size() - 1);
+    }
+    
+}
index 9cde5881086b1b259fe5ee91bc46e9fd06c8e8b2..675c29061b4c2ab755eabb9252b226875dc524a1 100644 (file)
@@ -32,7 +32,8 @@ public class EffRow {
     private List gridUnits = new java.util.ArrayList();
     private int index;
     private int bodyType;
-    private MinOptMax height = new MinOptMax(0);
+    private MinOptMax height;
+    private MinOptMax explicitHeight;
     
     public EffRow(int index, int bodyType) {
         this.index = index;
@@ -52,8 +53,16 @@ public class EffRow {
         return this.height;
     }
     
-    public void setHeight(MinOptMax height) {
-        this.height = height;
+    public void setHeight(MinOptMax mom) {
+        this.height = mom;
+    }
+    
+    public MinOptMax getExplicitHeight() {
+        return this.explicitHeight;
+    }
+    
+    public void setExplicitHeight(MinOptMax mom) {
+        this.explicitHeight = mom;
     }
     
     public List getGridUnits() {
@@ -104,6 +113,7 @@ public class EffRow {
             sb.append(" in footer");
         }
         sb.append(", ").append(height);
+        sb.append(", ").append(explicitHeight);
         sb.append(", ").append(gridUnits.size()).append(" gu");
         sb.append("}");
         return sb.toString();
index 85e4932951f8df636158a29c7b1c34cdfcfb94c5..d359dfa9b819b40d7d0d997c84446126e7442940 100644 (file)
@@ -33,6 +33,7 @@ import org.apache.fop.fo.flow.Table;
 import org.apache.fop.fo.flow.TableRow;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.fo.properties.LengthRangeProperty;
+import org.apache.fop.layoutmgr.ElementListUtils;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthPenalty;
@@ -133,8 +134,8 @@ public class TableContentLayoutManager {
         if (headerIter != null) {
             this.headerList = getKnuthElementsForRowIterator(
                     headerIter, context, alignment, TableRowIterator.HEADER);
-            removeLegalBreaks(this.headerList);
-            this.headerNetHeight = calcCellHeightFromContents(this.headerList);
+            ElementListUtils.removeLegalBreaks(this.headerList);
+            this.headerNetHeight = ElementListUtils.calcContentLength(this.headerList);
             if (log.isDebugEnabled()) {
                 log.debug("==> Header: " + headerNetHeight + " - " + this.headerList);
             }
@@ -153,8 +154,8 @@ public class TableContentLayoutManager {
         if (footerIter != null) {
             this.footerList = getKnuthElementsForRowIterator(
                     footerIter, context, alignment, TableRowIterator.FOOTER);
-            removeLegalBreaks(this.footerList);
-            this.footerNetHeight = calcCellHeightFromContents(this.footerList);
+            ElementListUtils.removeLegalBreaks(this.footerList);
+            this.footerNetHeight = ElementListUtils.calcContentLength(this.footerList);
             if (log.isDebugEnabled()) {
                 log.debug("==> Footer: " + footerNetHeight + " - " + this.footerList);
             }
@@ -180,28 +181,6 @@ public class TableContentLayoutManager {
         return returnList;
     }
     
-    private void removeLegalBreaks(LinkedList elements) {
-        ListIterator i = elements.listIterator();
-        while (i.hasNext()) {
-            KnuthElement el = (KnuthElement)i.next();
-            if (el.isPenalty()) {
-                KnuthPenalty penalty = (KnuthPenalty)el;
-                //Convert all penalties no break inhibitors
-                if (penalty.getP() < KnuthPenalty.INFINITE) {
-                    i.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE, 
-                            penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary()));
-                }
-            } else if (el.isGlue()) {
-                i.previous();
-                if (el.isBox()) {
-                    i.next();
-                    i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, 
-                            new Position(getTableLM()), false));
-                }
-            }
-        }
-    }
-    
     /**
      * Creates Knuth elements by iterating over a TableRowIterator.
      * @param iter TableRowIterator instance to fetch rows from
@@ -351,12 +330,14 @@ public class TableContentLayoutManager {
             EffRow[] rowGroup) {
         log.debug("Handling row group with " + rowGroup.length + " rows...");
         MinOptMax[] rowHeights = new MinOptMax[rowGroup.length];
+        MinOptMax[] explicitRowHeights = new MinOptMax[rowGroup.length];
         EffRow row;
         int maxColumnCount = 0;
         List pgus = new java.util.ArrayList(); //holds a list of a row's primary grid units
         for (int rgi = 0; rgi < rowGroup.length; rgi++) {
             row = rowGroup[rgi];
             rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE);
+            explicitRowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE);
             
             pgus.clear();
             TableRow tableRow = null;
@@ -382,6 +363,8 @@ public class TableContentLayoutManager {
                                 minContentHeight = Math.max(minContentHeight, 
                                         bpd.getMinimum().getLength().getValue());
                             }
+                            MinOptMaxUtil.restrict(explicitRowHeights[rgi], bpd);
+                            
                         }
 
                         //Calculate width of cell
@@ -404,7 +387,8 @@ public class TableContentLayoutManager {
 
                     
                     //Calculate height of cell contents
-                    primary.setContentLength(calcCellHeightFromContents(primary.getElements()));
+                    primary.setContentLength(ElementListUtils.calcContentLength(
+                            primary.getElements()));
                     maxCellHeight = Math.max(maxCellHeight, primary.getContentLength());
 
                     //Calculate height of row, see CSS21, 17.5.3 Table height algorithms
@@ -415,6 +399,10 @@ public class TableContentLayoutManager {
                             effCellContentHeight = Math.max(effCellContentHeight,
                                     bpd.getMinimum().getLength().getValue());
                         }
+                        if (gu.getRowSpanIndex() == 0) {
+                            //TODO ATM only non-row-spanned cells are taken for this
+                            MinOptMaxUtil.restrict(explicitRowHeights[rgi], bpd);
+                        }
                         effCellContentHeight = Math.max(effCellContentHeight, 
                                 primary.getContentLength());
                         int borderWidths;
@@ -445,23 +433,19 @@ public class TableContentLayoutManager {
                     }
                 }
             }
-            
-            log.debug("row: " + row);
-            
-            PrimaryGridUnit[] pguArray = new PrimaryGridUnit[pgus.size()];
-            pguArray = (PrimaryGridUnit[])pgus.toArray(pguArray);
 
-            /*
-            LinkedList returnedList = getCombinedKnuthElementsForRow(pguArray, row, 
-                    isHeaderFooter);
-            if (returnedList != null) {
-                returnList.addAll(returnedList);
-            }*/
+            row.setExplicitHeight(explicitRowHeights[rgi]);
+            if (row.getHeight().opt > row.getExplicitHeight().max) {
+                log.warn("Contents of row " + row.getIndex() + " violate a maximum constraint "
+                        + "in block-progression-dimension. Due to its contents the row grows "
+                        + "to " + row.getHeight().opt + " millipoints. The row constraint resolve "
+                        + "to " + row.getExplicitHeight());
+            }
         }
         if (log.isDebugEnabled()) {
             log.debug("rowGroup:");
             for (int i = 0; i < rowHeights.length; i++) {
-                log.debug("  " + rowHeights[i]);
+                log.debug("  height=" + rowHeights[i] + " explicit=" + explicitRowHeights[i]);
             }
         }
         TableStepper stepper = new TableStepper(this);
@@ -473,32 +457,6 @@ public class TableContentLayoutManager {
         
     }
 
-    private int calcCellHeightFromContents(List elems, int start, int end) {
-        ListIterator iter = elems.listIterator(start);
-        int count = end - start + 1;
-        int len = 0;
-        while (iter.hasNext()) {
-            KnuthElement el = (KnuthElement)iter.next();
-            if (el.isBox()) {
-                len += el.getW();
-            } else if (el.isGlue()) {
-                len += el.getW();
-            } else {
-                //log.debug("Ignoring penalty: " + el);
-                //ignore penalties
-            }
-            count--;
-            if (count == 0) {
-                break;
-            }
-        }
-        return len;
-    }
-    
-    private int calcCellHeightFromContents(List elems) {
-        return calcCellHeightFromContents(elems, 0, elems.size() - 1);
-    }
-    
     protected int getXOffsetOfGridUnit(GridUnit gu) {
         int col = gu.getStartCol();
         return startXOffset + getTableLM().getColumns().getXOffset(col + 1);
@@ -676,8 +634,11 @@ public class TableContentLayoutManager {
                     log.debug("getting len for " + i + " " 
                             + start[i] + "-" + end[i]);
                     readyCount++;
-                    int len = calcCellHeightFromContents(
+                    int len = ElementListUtils.calcContentLength(
                             gridUnits[i].getElements(), start[i], end[i]);
+                    if (start[i] == 0 && lastRow.getExplicitHeight().min > 0) {
+                        len = Math.max(len, lastRow.getExplicitHeight().opt);
+                    }
                     partLength[i] = len;
                     log.debug("len of part: " + len);
                     
index b43b67c04c3af8f2d48d537dd5d0afb0eebfc4ba..9600053abb82f97a347c85078b8a146f7ebe6cb5 100644 (file)
@@ -25,6 +25,7 @@ import java.util.List;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.layoutmgr.ElementListUtils;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthPenalty;
@@ -127,13 +128,22 @@ public class TableStepper {
 
     private void setupElementList(int column) {
         GridUnit gu = getActiveGridUnit(column);
+        EffRow row = getActiveRow();
         if (gu.isPrimary() && !gu.isEmpty()) {
             PrimaryGridUnit pgu = (PrimaryGridUnit)gu;
-            if (pgu.hasBPD()) {
-                List list = new java.util.ArrayList(1);
-                list.add(new KnuthBoxCellWithBPD(
-                        pgu.getEffectiveContentLength(), pgu));
-                elementLists[column] = list;
+            if (row.getExplicitHeight().min > 0) {
+                boolean contentsSmaller = ElementListUtils.removeLegalBreaks(
+                        pgu.getElements(), row.getExplicitHeight());
+                if (contentsSmaller) {
+                    List list = new java.util.ArrayList(1);
+                    list.add(new KnuthBoxCellWithBPD(
+                            row.getExplicitHeight().opt, pgu));
+                    elementLists[column] = list;
+                } else {
+                    //Copy elements (LinkedList) to array lists to improve 
+                    //element access performance
+                    elementLists[column] = new java.util.ArrayList(pgu.getElements());
+                }
             } else {
                 //Copy elements (LinkedList) to array lists to improve 
                 //element access performance