]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugfix: Nested tables with headers and footers were not handled correctly and could...
authorJeremias Maerki <jeremias@apache.org>
Sat, 7 Oct 2006 13:25:32 +0000 (13:25 +0000)
committerJeremias Maerki <jeremias@apache.org>
Sat, 7 Oct 2006 13:25:32 +0000 (13:25 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@453900 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableStepper.java
status.xml
test/layoutengine/standard-testcases/table-header_table-footer_4.xml [new file with mode: 0644]

index 8b07f6956a71219624097f3b39ee6a5a6e54a350..e0eaf079e605cc498f1b9b93bc3ffa32399dbc6f 100644 (file)
@@ -619,6 +619,7 @@ public class TableContentLayoutManager implements PercentBaseContext {
         List positions = new java.util.ArrayList();
         List headerElements = null;
         List footerElements = null;
+        int nestedPenaltyArea = 0;
         Position firstPos = null;
         Position lastPos = null;
         Position lastCheckPos = null;
@@ -668,6 +669,7 @@ public class TableContentLayoutManager implements PercentBaseContext {
             if (penaltyPos.footerElements != null) {
                 footerElements = penaltyPos.footerElements; 
             }
+            nestedPenaltyArea = penaltyPos.nestedPenaltyLength;
         }
 
         Map markers = getTableLM().getTable().getMarkers();
@@ -689,6 +691,7 @@ public class TableContentLayoutManager implements PercentBaseContext {
         iterateAndPaintPositions(posIter, painter);
         painter.addAreasAndFlushRow(true);
 
+        painter.notifyNestedPenaltyArea(nestedPenaltyArea);
         if (footerElements != null) {
             //Positions for footers are simply added at the end
             PositionIterator nestedIter = new KnuthPossPosIter(footerElements);
@@ -792,6 +795,10 @@ public class TableContentLayoutManager implements PercentBaseContext {
             this.accumulatedBPD += lastRowHeight; //for last row
         }
         
+        public void notifyNestedPenaltyArea(int length) {
+            this.lastRowHeight += length;
+        }
+        
         public void handleTableContentPosition(TableContentPosition tcpos) {
             if (lastRow != tcpos.row && lastRow != null) {
                 addAreasAndFlushRow(false);
@@ -1208,6 +1215,8 @@ public class TableContentLayoutManager implements PercentBaseContext {
         protected List headerElements;
         /** Element list for the footer */
         protected List footerElements;
+        /** Penalty length to be respected for nested content */
+        protected int nestedPenaltyLength;
         
         /**
          * Creates a new TableHFPenaltyPosition
@@ -1225,6 +1234,8 @@ public class TableContentLayoutManager implements PercentBaseContext {
             sb.append(headerElements);
             sb.append(", footer:");
             sb.append(footerElements);
+            sb.append(", inner penalty length:");
+            sb.append(nestedPenaltyLength);
             sb.append(")");
             return sb.toString();
         }
index 9d77293ed708a2dd547dafdf429147b7ba9f421b..6763f8b082f6c05a3917fb31f862fe9b23443921 100644 (file)
@@ -65,6 +65,7 @@ public class TableStepper {
     private boolean skippedStep;
     private boolean[] keepWithNextSignals;
     private boolean[] forcedBreaks;
+    private int lastMaxPenalty;
     
     /**
      * Main constructor
@@ -261,7 +262,7 @@ public class TableStepper {
             int penaltyLen = step + getMaxRemainingHeight() - totalHeight;
             int boxLen = step - addedBoxLen - penaltyLen;
             addedBoxLen += boxLen;
-            
+
             //Put all involved grid units into a list
             List gridUnitParts = new java.util.ArrayList(maxColumnCount);
             for (int i = 0; i < start.length; i++) {
@@ -328,6 +329,18 @@ public class TableStepper {
                     penaltyPos.footerElements = tclm.getFooterElements();
                 }
             }
+            
+            //Handle a penalty length coming from nested content
+            //Example: nested table with header/footer
+            if (this.lastMaxPenalty != 0) {
+                penaltyPos.nestedPenaltyLength = this.lastMaxPenalty;
+                if (log.isDebugEnabled()) {
+                    log.debug("Additional penalty length from table-cell break: " 
+                            + this.lastMaxPenalty);
+                }
+            }
+            effPenaltyLen += this.lastMaxPenalty;
+            
             int p = 0;
             boolean allCellsHaveContributed = true;
             signalKeepWithNext = false;
@@ -359,13 +372,14 @@ public class TableStepper {
                 p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0)
                 clearBreakCondition();
             }
-            //returnList.add(new KnuthPenalty(effPenaltyLen, p, false, penaltyPos, false));
             returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, -1, context));
 
-            log.debug("step=" + step + " (+" + increase + ")"
-                    + " box=" + boxLen 
-                    + " penalty=" + penaltyLen
-                    + " effPenalty=" + effPenaltyLen);
+            if (log.isDebugEnabled()) {
+                log.debug("step=" + step + " (+" + increase + ")"
+                        + " box=" + boxLen 
+                        + " penalty=" + penaltyLen
+                        + " effPenalty=" + effPenaltyLen);
+            }
             
             laststep = step;
             if (rowBacktrackForLastStep) {
@@ -388,6 +402,7 @@ public class TableStepper {
     }
     
     private int getNextStep(int lastStep) {
+        this.lastMaxPenalty = 0;
         //Check for forced break conditions
         /*
         if (isBreakCondition()) {
@@ -452,6 +467,7 @@ public class TableStepper {
                 end[i]++;
                 KnuthElement el = (KnuthElement)elementLists[i].get(end[i]);
                 if (el.isPenalty()) {
+                    this.lastMaxPenalty = Math.max(this.lastMaxPenalty, el.getW());
                     if (el.getP() <= -KnuthElement.INFINITE) {
                         log.debug("FORCED break encountered!");
                         forcedBreaks[i] = true;
index 93894917ce3347b6cc13cbdc4b0169f5d7e07773..aad3e3d587b8ad2d848624f1ceaa6ae5eed08ead 100644 (file)
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Code" dev="JM" type="fix">
+        Bugfix: Nested tables with headers and footers were not handled correctly and could
+        overlap with the region-after.
+      </action>
       <action context="Code" dev="JM" type="add" fixes-bug="40519" due-to="Oliver Hernàndez Valls">
         Added support for CCITT compression in the TIFFRenderer by switching to the ImageWriter
         abstraction from XML Graphics Commons.
diff --git a/test/layoutengine/standard-testcases/table-header_table-footer_4.xml b/test/layoutengine/standard-testcases/table-header_table-footer_4.xml
new file mode 100644 (file)
index 0000000..26f3056
--- /dev/null
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks tables, especially headers and footers. Focus is on respect for after
+      regions when headers and footers are used.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="normal" page-width="5in" page-height="3in">
+          <fo:region-body margin-top="0.5in" margin-bottom="0.5in"/>
+          <fo:region-before extent="0.5in" background-color="lightgray"/>
+          <fo:region-after extent="0.5in" background-color="lightgray"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="normal" white-space-collapse="true">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:table table-layout="fixed" width="100%">
+            <fo:table-column/>
+            <fo:table-header color="red">
+              <fo:table-row>
+                <fo:table-cell id="outer-header">
+                  <fo:block>Outer header</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-header>
+            <fo:table-footer color="red">
+              <fo:table-row>
+                <fo:table-cell id="outer-footer">
+                  <fo:block>Outer footer</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-footer>
+            <fo:table-body>
+              <fo:table-row>
+                <fo:table-cell id="outer-table-cell">
+                  <fo:table table-layout="fixed" width="100%">
+                    <fo:table-column/>
+                    <fo:table-header color="orange">
+                      <fo:table-row>
+                        <fo:table-cell id="inner-header">
+                          <fo:block>Inner header</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                    </fo:table-header>
+                    <fo:table-footer color="orange">
+                      <fo:table-row>
+                        <fo:table-cell id="inner-footer">
+                          <fo:block>Inner footer</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                    </fo:table-footer>
+                    <fo:table-body>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                      <fo:table-row>
+                        <fo:table-cell>
+                          <fo:block>content content content</fo:block>
+                        </fo:table-cell>
+                      </fo:table-row>
+                    </fo:table-body>
+                  </fo:table>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <element-list category="breaker">
+      <box w="14400"/>
+      <penalty w="57600" p="0"/> <!-- outer and inner header/footer = 4 * 14400 = 57600 -->
+      <box w="14400"/>
+      <penalty w="57600" p="0"/>
+      <box w="14400"/>
+      <penalty w="57600" p="0"/>
+      <box w="14400"/>
+      <penalty w="57600" p="0"/>
+      <box w="14400"/>
+      <penalty w="57600" p="0"/>
+      <box w="14400"/>
+      <penalty w="57600" p="0"/>
+      <box w="14400"/>
+      <penalty w="57600" p="0"/>
+      <box w="14400"/>
+      <penalty w="57600" p="0"/>
+      <box w="14400"/>
+      <penalty w="57600" p="0"/>
+      <box w="14400"/>
+      <penalty w="57600" p="0"/>
+      <box w="43200"/> <!-- including nested header/footer -->
+      <box w="14400"/> <!--header-->
+      <box w="14400"/> <!--footer-->
+      <skip>3</skip>
+    </element-list>
+    
+    <!-- top-offset of outer table-cell on first page -->
+    <eval expected="14400" xpath="//pageViewport[@nr=1]//flow/block[1]/block[2]/@top-offset"/>
+    <!-- last row in nested table on first page -->
+    <eval expected="86400" xpath="//pageViewport[@nr=1]//flow/block[1]/block[2]/block[1]/block[7]/@top-offset"/>
+    <!-- top-offset of footer of nested tableon first page -->
+    <eval expected="100800" xpath="//pageViewport[@nr=1]//flow/block[1]/block[2]/block[1]/block[8]/@top-offset"/>
+    <!-- top-offset of outer footer on first page -->
+    <eval expected="129600" xpath="//pageViewport[@nr=1]//flow/block[1]/block[3]/@top-offset"/>
+    
+    <!-- content lengths of both pages -->
+    <eval expected="144000" xpath="//pageViewport[@nr=1]//flow/@bpd"/>
+    <eval expected="129600" xpath="//pageViewport[@nr=2]//flow/@bpd"/>
+  </checks>
+</testcase>