]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Streamlined the recording of row offsets, by replacing Map with a List. Fixed bug...
authorVincent Hennebert <vhennebert@apache.org>
Tue, 18 Dec 2007 18:58:29 +0000 (18:58 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Tue, 18 Dec 2007 18:58:29 +0000 (18:58 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@605295 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/layoutmgr/table/RowPainter.java
status.xml
test/layoutengine/standard-testcases/table_row-span_missing-cell_bug43633.xml [new file with mode: 0644]

index 490f999cd0f5be213f3b705d82113bc68add416d..0b90bf9d8afe5eaf86df47b24dec19b9b503863f 100644 (file)
 
 package org.apache.fop.layoutmgr.table;
 
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Map;
+import java.util.List;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -56,7 +56,7 @@ class RowPainter {
      * This is particularly needed for spanned cells where you need to know the y-offset
      * of the starting row when the area is generated at the time the cell is closed.
      */
-    private Map rowOffsets = new HashMap();
+    private List rowOffsets = new ArrayList();
 
     //These three variables are our buffer to recombine the individual steps into cells
     /** Primary grid units corresponding to the currently handled grid units, per row. */
@@ -154,7 +154,7 @@ class RowPainter {
         if (log.isDebugEnabled()) {
             log.debug("Remembering yoffset for row " + lastRow.getIndex() + ": " + yoffset);
         }
-        rowOffsets.put(new Integer(lastRow.getIndex()), new Integer(yoffset));
+        recordRowOffset(lastRow.getIndex(), yoffset);
 
         for (int i = 0; i < primaryGridUnits.length; i++) {
             if ((primaryGridUnits[i] != null)
@@ -292,15 +292,8 @@ class RowPainter {
             len += pgu.getHalfMaxBeforeBorderWidth();
             len += pgu.getHalfMaxAfterBorderWidth();
         }
-        int startRow = Math.max(pgu.getStartRow(), firstRowIndex);
-        Integer storedOffset = (Integer)rowOffsets.get(new Integer(startRow));
-        int effYOffset;
-        if (storedOffset != null) {
-            effYOffset = storedOffset.intValue();
-        } else {
-            effYOffset = yoffset;
-        }
-        len -= yoffset - effYOffset;
+        int cellOffset = getRowOffset(Math.max(pgu.getStartRow(), firstRowIndex));
+        len -= yoffset - cellOffset;
         return len;
     }
 
@@ -317,37 +310,28 @@ class RowPainter {
         int[] spannedGridRowHeights = null;
         if (!tclm.getTableLM().getTable().isSeparateBorderModel() && pgu.hasSpanning()) {
             spannedGridRowHeights = new int[lastRowIndex - startRowIndex + 1];
-            int prevOffset = ((Integer)rowOffsets.get(new Integer(startRowIndex))).intValue();
+            int prevOffset = getRowOffset(startRowIndex);
             for (int i = 0; i < lastRowIndex - startRowIndex; i++) {
-                int newOffset = ((Integer) rowOffsets.get(new Integer(startRowIndex + i + 1)))
-                        .intValue();
+                int newOffset = getRowOffset(startRowIndex + i + 1);
                 spannedGridRowHeights[i] = newOffset - prevOffset;
                 prevOffset = newOffset;
             }
             spannedGridRowHeights[lastRowIndex - startRowIndex] = rowHeight;
         }
 
-        //Determine y offset for the cell
-        Integer offset = (Integer)rowOffsets.get(new Integer(startRowIndex));
-        while (offset == null) {
-            //TODO Figure out what this does and when it's triggered
-            //This block is probably never used, at least it's not triggered by any of our tests
-            startRowIndex--;
-            offset = (Integer)rowOffsets.get(new Integer(startRowIndex));
-        }
-        int effYOffset = offset.intValue();
+        int cellOffset = getRowOffset(startRowIndex);
         int effCellHeight = rowHeight;
-        effCellHeight += yoffset - effYOffset;
+        effCellHeight += yoffset - cellOffset;
         if (log.isDebugEnabled()) {
             log.debug("Creating area for cell:");
             log.debug("  current row: " + row.getIndex());
-            log.debug("  start row: " + pgu.getStartRow() + " " + yoffset + " " + effYOffset);
+            log.debug("  start row: " + pgu.getStartRow() + " " + yoffset + " " + cellOffset);
             log.debug("  contentHeight: " + contentHeight + " rowHeight=" + rowHeight
                     + " effCellHeight=" + effCellHeight);
         }
         TableCellLayoutManager cellLM = pgu.getCellLM();
         cellLM.setXOffset(tclm.getXOffsetOfGridUnit(pgu));
-        cellLM.setYOffset(effYOffset);
+        cellLM.setYOffset(cellOffset);
         cellLM.setContentHeight(contentHeight);
         cellLM.setRowHeight(effCellHeight);
         //cellLM.setRowHeight(row.getHeight().opt);
@@ -361,6 +345,40 @@ class RowPainter {
                 lastRowIndex - pgu.getStartRow() + 1);
     }
 
+    /**
+     * Records the y-offset of the row with the given index.
+     * 
+     * @param rowIndex index of the row
+     * @param offset y-offset of the row on the page
+     */
+    private void recordRowOffset(int rowIndex, int offset) {
+        /*
+         * In some very rare cases a row may be skipped. See for example Bugzilla #43633:
+         * in a two-column table, a row contains a row-spanning cell and a missing cell.
+         * In TableStepper#goToNextRowIfCurrentFinished this row will immediately be
+         * considered as finished, since it contains no cell ending on this row. Thus no
+         * TableContentPosition will be created for this row. Thus its index will never be
+         * recorded by the #handleTableContentPosition method.
+         * 
+         * The yoffset for such a row is the same as the next non-empty row. It's needed
+         * to correctly offset blocks for cells starting on this row. Hence the loop
+         * below.
+         */
+        for (int i = rowOffsets.size(); i <= rowIndex - firstRowIndex; i++) {
+            rowOffsets.add(new Integer(offset));
+        }
+    }
+
+    /**
+     * Returns the offset of the row with the given index.
+     * 
+     * @param rowIndex index of the row
+     * @return its y-offset on the page
+     */
+    private int getRowOffset(int rowIndex) {
+        return ((Integer) rowOffsets.get(rowIndex - firstRowIndex)).intValue();
+    }
+
     void endPart() {
         firstRowIndex = -1;
         rowOffsets.clear();
index 46942d796300bd9d033a9d0e848efd62defad610..77f4dcb869822a431315c0465d37fc2a82baae43 100644 (file)
@@ -28,6 +28,9 @@
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Code" dev="VH" type="fix" fixes-bug="43633">
+        Bugfix: content of a row with zero height overriding the previous row
+      </action>
       <action context="Code" dev="AC" type="add">
        Added SVG support for AFP (GOCA).
       </action>
diff --git a/test/layoutengine/standard-testcases/table_row-span_missing-cell_bug43633.xml b/test/layoutengine/standard-testcases/table_row-span_missing-cell_bug43633.xml
new file mode 100644 (file)
index 0000000..5cf793b
--- /dev/null
@@ -0,0 +1,96 @@
+<?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>
+      Check for bug #43633: the second row of the table has only a spanning cell, and the second
+      cell is missing. This was leading to the spanning cell overlapping cell 1.1, because no
+      offset was recorded for the second row.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="normal" page-width="20cm" page-height="15cm" margin="20pt">
+          <fo:region-body/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="normal">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block>Before the table</fo:block>
+
+          <fo:table table-layout="fixed" width="200pt" border="1pt solid black"
+            border-collapse="separate">
+            <fo:table-column column-width="proportional-column-width(1)"
+              number-columns-repeated="2"/>
+            <fo:table-body>
+              <fo:table-row>
+                <fo:table-cell border="1pt solid black" background-color="#FFC0C0">
+                  <fo:block>Cell 1.1</fo:block>
+                  <fo:block>Cell 1.1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="1pt solid black" background-color="#FFC0C0">
+                  <fo:block>Cell 1.2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="1pt solid black" background-color="#C0C0FF"
+                  number-rows-spanned="2">
+                  <fo:block>Cell 2.1</fo:block>
+                  <fo:block>Cell 2.1</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="1pt solid black" background-color="#C0C0FF">
+                  <fo:block>Cell 3.2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+          <fo:block>After the table</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+
+    <!-- cell 1.1 -->
+    <eval expected="" xpath="//flow/block[2]/block[1]/@top-offset"/>
+    <eval expected="1000" xpath="//flow/block[2]/block[1]/@left-offset"/>
+    <eval expected="28800" xpath="//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="30800" xpath="//flow/block[2]/block[1]/@bpda"/>
+    <!-- cell 1.2 -->
+    <eval expected="" xpath="//flow/block[2]/block[2]/@top-offset"/>
+    <eval expected="101000" xpath="//flow/block[2]/block[2]/@left-offset"/>
+    <eval expected="28800" xpath="//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="30800" xpath="//flow/block[2]/block[2]/@bpda"/>
+
+    <!-- cell 2.1 -->
+    <eval expected="30800" xpath="//flow/block[2]/block[3]/@top-offset"/>
+    <eval expected="1000" xpath="//flow/block[2]/block[3]/@left-offset"/>
+    <eval expected="28800" xpath="//flow/block[2]/block[3]/@bpd"/>
+    <eval expected="30800" xpath="//flow/block[2]/block[3]/@bpda"/>
+    <!-- cell 3.2 -->
+    <eval expected="30800" xpath="//flow/block[2]/block[4]/@top-offset"/>
+    <eval expected="101000" xpath="//flow/block[2]/block[4]/@left-offset"/>
+    <eval expected="28800" xpath="//flow/block[2]/block[4]/@bpd"/>
+    <eval expected="30800" xpath="//flow/block[2]/block[4]/@bpda"/>
+
+  </checks>
+</testcase>