]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
FOP-2536: Allow overpaint of PDF border
authorSimon Steiner <ssteiner@apache.org>
Tue, 29 Dec 2020 13:33:34 +0000 (13:33 +0000)
committerSimon Steiner <ssteiner@apache.org>
Tue, 29 Dec 2020 13:33:34 +0000 (13:33 +0000)
Thanks to Jan Tošovský and Matthias Reischenbacher

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

12 files changed:
fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java
fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
fop-core/src/main/java/org/apache/fop/apps/FopFactory.java
fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java
fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java
fop-core/src/main/java/org/apache/fop/layoutmgr/table/OverPaintBorders.java [new file with mode: 0644]
fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
fop-core/src/main/java/org/apache/fop/traits/BorderProps.java
fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java
fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java
fop/test/layoutengine/standard-testcases/table-border-rendering-mode-overpaint.xml [new file with mode: 0644]
fop/test/layoutengine/standard-testcases/table-border-rendering-mode-standard.xml [new file with mode: 0644]

index 9b1566d2e0196656ad39ac05afb6bcd0b6b1a0a0..ffb92b0276fb143628934c1427a68bdad16bfab7 100644 (file)
@@ -831,4 +831,8 @@ public class FOUserAgent {
             return true;
         }
     }
+
+    public boolean isTableBorderOverpaint() {
+        return factory.isTableBorderOverpaint();
+    }
 }
index 04b0202775f47c4172853279e3de944cc9ee3338..f125dc6a37290315f7f921147f5a2fa37e93e583 100644 (file)
@@ -56,6 +56,7 @@ import org.apache.fop.util.LogUtil;
 public class FopConfParser {
 
     private static final String PREFER_RENDERER = "prefer-renderer";
+    private static final String TABLE_BORDER_OVERPAINT = "table-border-overpaint";
 
     private final Log log = LogFactory.getLog(FopConfParser.class);
 
@@ -265,6 +266,15 @@ public class FopConfParser {
             }
         }
 
+        if (cfg.getChild(TABLE_BORDER_OVERPAINT, false) != null) {
+            try {
+                fopFactoryBuilder.setTableBorderOverpaint(
+                        cfg.getChild(TABLE_BORDER_OVERPAINT).getValueAsBoolean());
+            } catch (ConfigurationException e) {
+                LogUtil.handleException(log, e, false);
+            }
+        }
+
         // configure font manager
         new FontManagerConfigurator(cfg, baseURI, fopFactoryBuilder.getBaseURI(), resourceResolver)
                 .configure(fopFactoryBuilder.getFontManager(), strict);
index 35a0bc3733aef332e14b73932879758bd408d063..6708f211328e9474c2ee9de61c37a55c791bfd81 100644 (file)
@@ -207,6 +207,10 @@ public final class FopFactory implements ImageContext {
         return userAgent.newFop(outputFormat, null);
     }
 
+    boolean isTableBorderOverpaint() {
+        return config.isTableBorderOverpaint();
+    }
+
     /**
      * Returns a new {@link Fop} instance. FOP will be configured with a default user agent
      * instance. Use this factory method if your output type requires an output stream.
index 3fd8414fbf1f0704301c8fc78df5f1fa11056596..0e7498df25a122fd97c0117eafa7c1cbb49ae185 100644 (file)
@@ -327,6 +327,11 @@ public final class FopFactoryBuilder {
         return this;
     }
 
+    public FopFactoryBuilder setTableBorderOverpaint(boolean b) {
+        fopFactoryConfigBuilder.setTableBorderOverpaint(b);
+        return this;
+    }
+
     public static class FopFactoryConfigImpl implements FopFactoryConfig {
 
         private final EnvironmentProfile enviro;
@@ -368,6 +373,8 @@ public final class FopFactoryBuilder {
 
         private Map<String, String> hyphPatNames;
 
+        private boolean tableBorderOverpaint;
+
         private static final class ImageContextImpl implements ImageContext {
 
             private final FopFactoryConfig config;
@@ -484,6 +491,10 @@ public final class FopFactoryBuilder {
             return isComplexScript;
         }
 
+        public boolean isTableBorderOverpaint() {
+            return tableBorderOverpaint;
+        }
+
         public Map<String, String> getHyphenationPatternNames() {
             return hyphPatNames;
         }
@@ -529,6 +540,8 @@ public final class FopFactoryBuilder {
         void setComplexScriptFeaturesEnabled(boolean csf);
 
         void setHyphPatNames(Map<String, String> hyphPatNames);
+
+        void setTableBorderOverpaint(boolean b);
     }
 
     private static final class CompletedFopFactoryConfigBuilder implements FopFactoryConfigBuilder {
@@ -613,6 +626,9 @@ public final class FopFactoryBuilder {
             throwIllegalStateException();
         }
 
+        public void setTableBorderOverpaint(boolean b) {
+            throwIllegalStateException();
+        }
     }
 
     private static final class ActiveFopFactoryConfigBuilder implements FopFactoryConfigBuilder {
@@ -697,6 +713,10 @@ public final class FopFactoryBuilder {
         public void setHyphPatNames(Map<String, String> hyphPatNames) {
             config.hyphPatNames = hyphPatNames;
         }
+
+        public void setTableBorderOverpaint(boolean b) {
+            config.tableBorderOverpaint = b;
+        }
     }
 
 }
index 69b7b25e9f3829c311ccc21e8effa2ac1d2dd34b..cda0d2c10a6ecec6c66bec7f7ae77c9361faf6a2 100644 (file)
@@ -163,6 +163,8 @@ public interface FopFactoryConfig {
 
     boolean isComplexScriptFeaturesEnabled();
 
+    boolean isTableBorderOverpaint();
+
     /** @return the hyphenation pattern names */
     Map<String, String> getHyphenationPatternNames();
 
diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/OverPaintBorders.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/OverPaintBorders.java
new file mode 100644 (file)
index 0000000..d1ebbd5
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * 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.table;
+
+import java.awt.Point;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.xmlgraphics.java2d.color.ColorUtil;
+
+import org.apache.fop.area.Block;
+import org.apache.fop.area.Trait;
+import org.apache.fop.traits.BorderProps;
+
+public class OverPaintBorders {
+    protected OverPaintBorders(Block curBlockArea) {
+        List<Block> newBlocks = new ArrayList<Block>();
+        List<Object> childAreas = new ArrayList<Object>(curBlockArea.getChildAreas());
+        Collections.sort(childAreas, new SortBlocksByXOffset());
+        mergeBordersOfType(newBlocks, childAreas, new int[]{Trait.BORDER_BEFORE, Trait.BORDER_AFTER});
+        Collections.sort(childAreas, new SortBlocksByYOffset());
+        mergeBordersOfType(newBlocks, childAreas, new int[]{Trait.BORDER_START, Trait.BORDER_END});
+        for (Block borderBlock : newBlocks) {
+            curBlockArea.addBlock(borderBlock);
+        }
+    }
+
+     static class SortBlocksByXOffset implements Comparator<Object>, Serializable {
+         private static final long serialVersionUID = 5368454957520223766L;
+         public int compare(Object o1, Object o2) {
+            Block b1 = (Block) o1;
+            Block b2 = (Block) o2;
+            Integer paddingStart1 = (Integer) b1.getTrait(Trait.PADDING_START);
+            Integer paddingStart2 = (Integer) b2.getTrait(Trait.PADDING_START);
+            int x1 = b1.getXOffset() - (paddingStart1 != null ? paddingStart1 : 0);
+            int x2 = b2.getXOffset() - (paddingStart2 != null ? paddingStart2 : 0);
+            if (x1 > x2) {
+                return 1;
+            } else if (x1 < x2) {
+                return -1;
+            } else {
+                return Integer.compare(b1.getYOffset(), b2.getYOffset());
+            }
+        }
+    }
+
+    static class SortBlocksByYOffset implements Comparator<Object>, Serializable {
+        private static final long serialVersionUID = -1166133555737149237L;
+        public int compare(Object o1, Object o2) {
+            Block b1 = (Block) o1;
+            Block b2 = (Block) o2;
+            Integer paddingStart1 = (Integer) b1.getTrait(Trait.PADDING_START);
+            Integer paddingStart2 = (Integer) b2.getTrait(Trait.PADDING_START);
+            int x1 = b1.getXOffset() - (paddingStart1 != null ? paddingStart1 : 0);
+            int x2 = b2.getXOffset() - (paddingStart2 != null ? paddingStart2 : 0);
+            if (b1.getYOffset() > b2.getYOffset()) {
+                return 1;
+            } else if (b1.getYOffset() < b2.getYOffset()) {
+                return -1;
+            } else {
+                return Integer.compare(x1, x2);
+            }
+        }
+    }
+
+    private void mergeBordersOfType(List<Block> newBlocks, List<?> childAreas, int[] borderTraits) {
+        Map<Integer, Map<Point, Block>> mergeMap = new HashMap<Integer, Map<Point, Block>>();
+        for (int traitType : borderTraits) {
+            mergeMap.put(traitType, null);
+        }
+        for (Object child : childAreas) {
+            Block childBlock = (Block) child;
+            BorderProps startBps = (BorderProps) childBlock.getTrait(Trait.BORDER_START);
+            BorderProps endBps = (BorderProps) childBlock.getTrait(Trait.BORDER_END);
+            BorderProps beforeBps = (BorderProps) childBlock.getTrait(Trait.BORDER_BEFORE);
+            BorderProps afterBps = (BorderProps) childBlock.getTrait(Trait.BORDER_AFTER);
+            for (int traitType : borderTraits) {
+                Block currBlock = childBlock;
+                BorderProps borderProps = (BorderProps) currBlock.getTrait(traitType);
+                if (borderProps == null) {
+                    continue;
+                }
+                Map<Point, Block> currTraitMap = mergeMap.get(traitType);
+                Point endPoint = getEndMiddlePoint(currBlock, traitType, startBps, endBps, beforeBps, afterBps);
+                BorderProps bpsCurr = (BorderProps) currBlock.getTrait(traitType);
+                Block prevBlock = null;
+                if (currTraitMap == null) {
+                    currTraitMap = new HashMap<Point, Block>();
+                    mergeMap.put(traitType, currTraitMap);
+                } else {
+                    Point startPoint = getStartMiddlePoint(currBlock, traitType, startBps, endBps, beforeBps, afterBps);
+                    for (Map.Entry<Point, Block> entry : currTraitMap.entrySet()) {
+                        Point prevEndPoint = entry.getKey();
+                        boolean isVertical = traitType == Trait.BORDER_START || traitType == Trait.BORDER_END;
+                        boolean isHorizontal = traitType == Trait.BORDER_BEFORE || traitType == Trait.BORDER_AFTER;
+                        if ((isHorizontal && prevEndPoint.y == startPoint.y && prevEndPoint.x >= startPoint.x)
+                                || (isVertical && prevEndPoint.x == startPoint.x && prevEndPoint.y >= startPoint.y)) {
+                            Block prevBlockCurr = entry.getValue();
+                            currTraitMap.remove(prevEndPoint);
+                            BorderProps bpsPrev = (BorderProps) prevBlockCurr.getTrait(traitType);
+                            if (canMergeBorders(bpsPrev, bpsCurr)) {
+                                prevBlock = prevBlockCurr;
+                            }
+                            break;
+                        }
+                    }
+                }
+                Block borderBlock;
+                if (prevBlock != null && newBlocks.contains(prevBlock)) {
+                    borderBlock = prevBlock;
+                } else {
+                    borderBlock = new Block();
+                    borderBlock.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
+                    borderBlock.setPositioning(Block.ABSOLUTE);
+                    borderBlock.setBidiLevel(currBlock.getBidiLevel());
+                    newBlocks.add(borderBlock);
+                    BorderProps prevBeforeBps = (BorderProps) currBlock.getTrait(Trait.BORDER_BEFORE);
+                    int prevBefore = prevBeforeBps != null ? prevBeforeBps.width : 0;
+                    Integer prevPaddingStart = (Integer) currBlock.getTrait(Trait.PADDING_START);
+                    Integer prevPaddingEnd = (Integer) currBlock.getTrait(Trait.PADDING_END);
+                    Integer prevPaddingBefore = (Integer) currBlock.getTrait(Trait.PADDING_BEFORE);
+                    Integer prevPaddingAfter = (Integer) currBlock.getTrait(Trait.PADDING_AFTER);
+                    if (traitType == Trait.BORDER_START) {
+                        borderBlock.setYOffset(currBlock.getYOffset() + prevBefore);
+                        borderBlock.setXOffset(currBlock.getXOffset()
+                                - (prevPaddingStart != null ? prevPaddingStart : 0));
+                    } else if (traitType == Trait.BORDER_END) {
+                        borderBlock.setYOffset(currBlock.getYOffset() + prevBefore);
+                        borderBlock.setXOffset(currBlock.getXOffset()
+                                - (prevPaddingStart != null ? prevPaddingStart : 0));
+                        borderBlock.setIPD(currBlock.getIPD()
+                                + (prevPaddingStart != null ? prevPaddingStart : 0)
+                                + (prevPaddingEnd != null ? prevPaddingEnd : 0));
+                    } else if (traitType == Trait.BORDER_BEFORE) {
+                        borderBlock.setYOffset(currBlock.getYOffset());
+                        borderBlock.setXOffset(currBlock.getXOffset()
+                                - (prevPaddingStart != null ? prevPaddingStart : 0));
+                    } else if (traitType == Trait.BORDER_AFTER) {
+                        borderBlock.setYOffset(currBlock.getYOffset() + prevBefore);
+                        borderBlock.setXOffset(currBlock.getXOffset()
+                                - (prevPaddingStart != null ? prevPaddingStart : 0));
+                        borderBlock.setBPD(currBlock.getBPD()
+                                + (prevPaddingBefore != null ? prevPaddingBefore : 0)
+                                + (prevPaddingAfter != null ? prevPaddingAfter : 0));
+                    }
+                }
+                Integer paddingEnd = (Integer) currBlock.getTrait(Trait.PADDING_END);
+                Integer paddingAfter = (Integer) currBlock.getTrait(Trait.PADDING_AFTER);
+                if (traitType == Trait.BORDER_BEFORE || traitType == Trait.BORDER_AFTER) {
+                    int newEndPoint = currBlock.getXOffset() + currBlock.getIPD()
+                            + (paddingEnd != null ? paddingEnd : 0);
+                    borderBlock.setIPD(newEndPoint - borderBlock.getXOffset());
+                } else if (traitType == Trait.BORDER_START || traitType == Trait.BORDER_END) {
+                    int newEndPoint = currBlock.getYOffset() + currBlock.getBPD()
+                            + currBlock.getBorderAndPaddingWidthBefore()
+                            + (paddingAfter != null ? paddingAfter : 0);
+                    borderBlock.setBPD(newEndPoint - borderBlock.getYOffset());
+                }
+                BorderProps newBps = new BorderProps(bpsCurr.style, bpsCurr.width, 0, 0,
+                        bpsCurr.color, bpsCurr.getMode());
+                borderBlock.addTrait(traitType, newBps);
+                currBlock = borderBlock;
+                currTraitMap.put(endPoint, currBlock);
+            }
+        }
+    }
+
+    private boolean canMergeBorders(BorderProps bpsPrev, BorderProps bpsCurr) {
+        return bpsPrev.style == bpsCurr.style
+                && ColorUtil.isSameColor(bpsPrev.color, bpsCurr.color)
+                && bpsPrev.width == bpsCurr.width
+                && bpsPrev.getMode() == bpsPrev.getMode()
+                && bpsPrev.getRadiusEnd() == 0
+                && bpsCurr.getRadiusStart() == 0;
+    }
+
+    private Point getEndMiddlePoint(Block block, int borderTrait, BorderProps startBps,
+                                    BorderProps endBps, BorderProps beforeBps, BorderProps afterBps) {
+        int x;
+        int y;
+        if (borderTrait == Trait.BORDER_START) {
+            Integer paddingStart = (Integer) block.getTrait(Trait.PADDING_START);
+            x = block.getXOffset()
+                    - (paddingStart != null ? paddingStart : 0)
+                    - BorderProps.getClippedWidth(startBps);
+            y = block.getYOffset() + block.getBPD()
+                    + block.getBorderAndPaddingWidthBefore()
+                    + block.getBorderAndPaddingWidthAfter();
+        } else if (borderTrait == Trait.BORDER_END) {
+            Integer paddingEnd = (Integer) block.getTrait(Trait.PADDING_END);
+            x = block.getXOffset() + block.getIPD()
+                    + (paddingEnd != null ? paddingEnd : 0)
+                    + BorderProps.getClippedWidth(endBps);
+            y = block.getYOffset() + block.getBPD()
+                    + block.getBorderAndPaddingWidthBefore()
+                    + block.getBorderAndPaddingWidthAfter();
+        } else if (borderTrait == Trait.BORDER_AFTER) {
+            Integer paddingEnd = (Integer) block.getTrait(Trait.PADDING_END);
+            x = block.getXOffset() + block.getIPD()
+                    + (paddingEnd != null ? paddingEnd : 0)
+                    + BorderProps.getClippedWidth(endBps);
+            Integer paddingAfter = (Integer) block.getTrait(Trait.PADDING_AFTER);
+            y = block.getYOffset() + block.getBPD()
+                    + block.getBorderAndPaddingWidthBefore()
+                    + (paddingAfter != null ? paddingAfter : 0)
+                    + BorderProps.getClippedWidth(afterBps);
+        } else if (borderTrait == Trait.BORDER_BEFORE) {
+            Integer paddingEnd = (Integer) block.getTrait(Trait.PADDING_END);
+            x = block.getXOffset() + block.getIPD()
+                    + (paddingEnd != null ? paddingEnd : 0)
+                    + BorderProps.getClippedWidth(endBps);
+            y = block.getYOffset()
+                    + BorderProps.getClippedWidth(beforeBps);
+        } else {
+            throw new IllegalArgumentException("Invalid trait: " + borderTrait);
+        }
+        return new Point(x, y);
+    }
+
+    private Point getStartMiddlePoint(Block block, int borderTrait, BorderProps startBps, BorderProps endBps,
+                                      BorderProps beforeBps, BorderProps afterBps) {
+        int x;
+        int y;
+        if (borderTrait == Trait.BORDER_START) {
+            Integer paddingStart = (Integer) block.getTrait(Trait.PADDING_START);
+            x = block.getXOffset()
+                    - (paddingStart != null ? paddingStart : 0)
+                    - BorderProps.getClippedWidth(startBps);
+            y = block.getYOffset();
+        } else if (borderTrait == Trait.BORDER_BEFORE) {
+            x = block.getXOffset() - block.getBorderAndPaddingWidthStart();
+            y = block.getYOffset()
+                    + BorderProps.getClippedWidth(beforeBps);
+        } else if (borderTrait == Trait.BORDER_END) {
+            Integer paddingEnd = (Integer) block.getTrait(Trait.PADDING_END);
+            x = block.getXOffset() + block.getIPD()
+                    + (paddingEnd != null ? paddingEnd : 0)
+                    + BorderProps.getClippedWidth(endBps);
+            y = block.getYOffset();
+        } else if (borderTrait == Trait.BORDER_AFTER) {
+            x = block.getXOffset() - block.getBorderAndPaddingWidthStart();
+            Integer paddingAfter = (Integer) block.getTrait(Trait.PADDING_AFTER);
+            y = block.getYOffset() + block.getBorderAndPaddingWidthBefore()
+                    + block.getBPD()
+                    + (paddingAfter != null ? paddingAfter : 0)
+                    + BorderProps.getClippedWidth(afterBps);
+        } else {
+            throw new IllegalArgumentException("Invalid trait: " + borderTrait);
+        }
+        return new Point(x, y);
+    }
+}
index 453f169e121f59396a4c5ffc8d66751e6ec42428..b4b49b705ec12fafeed836440b4f8c6759fb495f 100644 (file)
@@ -381,6 +381,11 @@ public class TableLayoutManager extends SpacedBorderedPaddedBlockLayoutManager
         lc.setRefIPD(getContentAreaIPD());
         contentLM.setStartXOffset(startXOffset);
         contentLM.addAreas(parentIter, lc);
+
+        if (fobj.getUserAgent().isTableBorderOverpaint()) {
+            new OverPaintBorders(curBlockArea);
+        }
+
         tableHeight += contentLM.getUsedBPD();
 
         curBlockArea.setBPD(tableHeight);
index d230a02b2cca8168ac07b4c4c4171b17d2f3e251..06812ed84448dea6ae8e0b2c43c51fd264341e43 100644 (file)
@@ -120,6 +120,13 @@ public class BorderProps implements Serializable {
         return radiusEnd;
     }
 
+    /**
+     * @return the border mode ((one of SEPARATE, COLLAPSE_INNER and COLLAPSE_OUTER)
+     */
+    public Mode getMode() {
+        return mode;
+    }
+
     /**
      * @param bp the border properties or null
      * @return the effective width of the clipped part of the border
index 2f70f41245cc05578560e685b044541acbe482a8..04b760e7457ba048f698be2a921b4695e04d6a1f 100644 (file)
@@ -133,6 +133,10 @@ public final class MutableConfig implements FopFactoryConfig {
         return delegate.isComplexScriptFeaturesEnabled();
     }
 
+    public boolean isTableBorderOverpaint() {
+        return delegate.isTableBorderOverpaint();
+    }
+
     public Map<String, String> getHyphenationPatternNames() {
         return delegate.getHyphenationPatternNames();
     }
index d13f88959b360766bba762decff43407b73ac2ca..4f56f9c7df473d0635702793b89d83da524b72b9 100644 (file)
@@ -122,6 +122,7 @@ public class TestAssistant {
         FopFactoryBuilder builder = new FopFactoryBuilder(envProfile);
         builder.setStrictFOValidation(isStrictValidation(testDoc));
         builder.getFontManager().setBase14KerningEnabled(isBase14KerningEnabled(testDoc));
+        builder.setTableBorderOverpaint(isTableBorderOverpaint(testDoc));
         return builder.build();
     }
 
@@ -144,6 +145,16 @@ public class TestAssistant {
         }
     }
 
+    private boolean isTableBorderOverpaint(Document testDoc) {
+        try {
+            XObject xo = XPathAPI.eval(testDoc, "/testcase/cfg/table-border-overpaint");
+            String s = xo.str();
+            return "true".equalsIgnoreCase(s);
+        } catch (TransformerException e) {
+            throw new RuntimeException("Error while evaluating XPath expression", e);
+        }
+    }
+
     /**
      * Loads a test case into a DOM document.
      * @param testFile the test file
diff --git a/fop/test/layoutengine/standard-testcases/table-border-rendering-mode-overpaint.xml b/fop/test/layoutengine/standard-testcases/table-border-rendering-mode-overpaint.xml
new file mode 100644 (file)
index 0000000..cd0f913
--- /dev/null
@@ -0,0 +1,180 @@
+<?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 if table borders are overpainted.
+    </p>
+  </info>
+  <cfg>
+    <table-border-overpaint>true</table-border-overpaint>
+  </cfg>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="body">
+          <fo:region-body margin="15mm"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="body">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:table border-before-width.conditionality="retain" border-collapse="collapse" text-align="start" border="none" table-layout="fixed" width="100%">
+            <fo:table-column column-number="1"/>
+            <fo:table-column column-number="2"/>
+            <fo:table-column column-number="3"/>
+            <fo:table-column column-number="4"/>
+            <fo:table-column column-number="5"/>
+            <fo:table-column column-number="6"/>
+            <fo:table-column column-number="7"/>
+            <fo:table-column column-number="8"/>
+            <fo:table-header start-indent="0pt" end-indent="0pt" border-top="0.5pt solid green" border-right="0.5pt solid green" border-left="0.5pt solid green">
+              <fo:table-row keep-with-next.within-column="always" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white" number-rows-spanned="3">
+                  <fo:block font-weight="bold">Color Name</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" background-color="green" color="white" number-columns-spanned="7">
+                  <fo:block font-weight="bold">Color Value</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-next.within-column="always" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white" number-columns-spanned="3">
+                  <fo:block font-weight="bold">RGB</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" background-color="green" color="white" number-columns-spanned="4">
+                  <fo:block font-weight="bold">CMYK</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-next.within-column="always" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">R</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">G</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">B</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">C</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">M</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">Y</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">K</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-header>
+            <fo:table-body start-indent="0pt" end-indent="0pt" border-bottom="0.5pt solid green" border-right="0.5pt solid green" border-left="0.5pt solid green">
+              <fo:table-row keep-with-next.within-column="always" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>Red</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>255</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-next.within-column="auto" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>Green</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>255</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-next.within-column="auto" keep-with-previous.within-column="always">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>Blue</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>255</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="130" xpath="count(//block)"/>
+    <eval expected="52" xpath="count(//block/@border-start)"/>
+    <eval expected="(solid,#008000,500,collapse-inner)" xpath="//flow/block/block[91]/@border-end"/>
+    <eval expected="(solid,#008000,500,collapse-inner)" xpath="//flow/block/block[92]/@border-start"/>
+    <eval expected="(solid,#008000,500,collapse-inner)" xpath="//flow/block/block[93]/@border-end"/>
+    <eval expected="(solid,#008000,500,collapse-inner)" xpath="//flow/block/block[94]/@border-start"/>
+  </checks>
+</testcase>
diff --git a/fop/test/layoutengine/standard-testcases/table-border-rendering-mode-standard.xml b/fop/test/layoutengine/standard-testcases/table-border-rendering-mode-standard.xml
new file mode 100644 (file)
index 0000000..397f0fe
--- /dev/null
@@ -0,0 +1,173 @@
+<?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 if table borders are rendered without overpainting.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="body">
+          <fo:region-body margin="15mm"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="body">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:table border-before-width.conditionality="retain" border-collapse="collapse" text-align="start" border="none" table-layout="fixed" width="100%">
+            <fo:table-column column-number="1"/>
+            <fo:table-column column-number="2"/>
+            <fo:table-column column-number="3"/>
+            <fo:table-column column-number="4"/>
+            <fo:table-column column-number="5"/>
+            <fo:table-column column-number="6"/>
+            <fo:table-column column-number="7"/>
+            <fo:table-column column-number="8"/>
+            <fo:table-header start-indent="0pt" end-indent="0pt" border-top="0.5pt solid green" border-right="0.5pt solid green" border-left="0.5pt solid green">
+              <fo:table-row keep-with-next.within-column="always" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white" number-rows-spanned="3">
+                  <fo:block font-weight="bold">Color Name</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" background-color="green" color="white" number-columns-spanned="7">
+                  <fo:block font-weight="bold">Color Value</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-next.within-column="always" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white" number-columns-spanned="3">
+                  <fo:block font-weight="bold">RGB</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" background-color="green" color="white" number-columns-spanned="4">
+                  <fo:block font-weight="bold">CMYK</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-next.within-column="always" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">R</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">G</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">B</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">C</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">M</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" border-right="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">Y</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid white" background-color="green" color="white">
+                  <fo:block font-weight="bold">K</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-header>
+            <fo:table-body start-indent="0pt" end-indent="0pt" border-bottom="0.5pt solid green" border-right="0.5pt solid green" border-left="0.5pt solid green">
+              <fo:table-row keep-with-next.within-column="always" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>Red</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>255</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-next.within-column="auto" keep-with-previous.within-column="auto">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>Green</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>255</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-bottom="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-next.within-column="auto" keep-with-previous.within-column="always">
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>Blue</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>0</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>255</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>1.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm" border-right="0.5pt solid green">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+                <fo:table-cell padding-top="1.3mm" padding-bottom="1.3mm" padding-left="2.5mm" padding-right="2.5mm">
+                  <fo:block>0.00</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="88" xpath="count(//block)"/>
+    <eval expected="37" xpath="count(//block/@border-start)"/>
+  </checks>
+</testcase>