aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Steiner <ssteiner@apache.org>2020-12-29 13:33:34 +0000
committerSimon Steiner <ssteiner@apache.org>2020-12-29 13:33:34 +0000
commit1f2a414bb711508e158f9704cb6b5320cfd848e3 (patch)
tree3008a5cd5a17b0172ec7db225516c3ad02d05447
parent899b3133b6133f13bc73ec1657a75e11feabfce8 (diff)
downloadxmlgraphics-fop-1f2a414bb711508e158f9704cb6b5320cfd848e3.tar.gz
xmlgraphics-fop-1f2a414bb711508e158f9704cb6b5320cfd848e3.zip
FOP-2536: Allow overpaint of PDF border
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
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java4
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java10
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FopFactory.java4
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java20
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java2
-rw-r--r--fop-core/src/main/java/org/apache/fop/layoutmgr/table/OverPaintBorders.java273
-rw-r--r--fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java5
-rw-r--r--fop-core/src/main/java/org/apache/fop/traits/BorderProps.java7
-rw-r--r--fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java4
-rw-r--r--fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java11
-rw-r--r--fop/test/layoutengine/standard-testcases/table-border-rendering-mode-overpaint.xml180
-rw-r--r--fop/test/layoutengine/standard-testcases/table-border-rendering-mode-standard.xml173
12 files changed, 693 insertions, 0 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java b/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java
index 9b1566d2e..ffb92b027 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java
@@ -831,4 +831,8 @@ public class FOUserAgent {
return true;
}
}
+
+ public boolean isTableBorderOverpaint() {
+ return factory.isTableBorderOverpaint();
+ }
}
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java b/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
index 04b020277..f125dc6a3 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
@@ -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);
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java b/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java
index 35a0bc373..6708f2113 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java
@@ -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.
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java
index 3fd8414fb..0e7498df2 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java
@@ -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;
+ }
}
}
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java
index 69b7b25e9..cda0d2c10 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java
@@ -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
index 000000000..d1ebbd595
--- /dev/null
+++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/OverPaintBorders.java
@@ -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);
+ }
+}
diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
index 453f169e1..b4b49b705 100644
--- a/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
+++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
@@ -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);
diff --git a/fop-core/src/main/java/org/apache/fop/traits/BorderProps.java b/fop-core/src/main/java/org/apache/fop/traits/BorderProps.java
index d230a02b2..06812ed84 100644
--- a/fop-core/src/main/java/org/apache/fop/traits/BorderProps.java
+++ b/fop-core/src/main/java/org/apache/fop/traits/BorderProps.java
@@ -121,6 +121,13 @@ public class BorderProps implements Serializable {
}
/**
+ * @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
*/
diff --git a/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java b/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java
index 2f70f4124..04b760e74 100644
--- a/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java
+++ b/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java
@@ -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();
}
diff --git a/fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java b/fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java
index d13f88959..4f56f9c7d 100644
--- a/fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java
+++ b/fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java
@@ -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
index 000000000..cd0f91395
--- /dev/null
+++ b/fop/test/layoutengine/standard-testcases/table-border-rendering-mode-overpaint.xml
@@ -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
index 000000000..397f0fe15
--- /dev/null
+++ b/fop/test/layoutengine/standard-testcases/table-border-rendering-mode-standard.xml
@@ -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>