diff options
author | Simon Steiner <ssteiner@apache.org> | 2020-12-29 13:33:34 +0000 |
---|---|---|
committer | Simon Steiner <ssteiner@apache.org> | 2020-12-29 13:33:34 +0000 |
commit | 1f2a414bb711508e158f9704cb6b5320cfd848e3 (patch) | |
tree | 3008a5cd5a17b0172ec7db225516c3ad02d05447 | |
parent | 899b3133b6133f13bc73ec1657a75e11feabfce8 (diff) | |
download | xmlgraphics-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
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> |