diff options
author | Simon Pepping <spepping@apache.org> | 2011-04-19 09:01:37 +0000 |
---|---|---|
committer | Simon Pepping <spepping@apache.org> | 2011-04-19 09:01:37 +0000 |
commit | a174a27add225d21a59d41b2b6296ea7dcdf51ca (patch) | |
tree | 7a8e4b427da9fa67170c2c4b3582c77d9ce7c426 | |
parent | f79d47245ad99bd879ca9f7b867f641dccd60549 (diff) | |
parent | 427df0fa7d2f67a4d21740cbf7264d3b11739a41 (diff) | |
download | xmlgraphics-fop-a174a27add225d21a59d41b2b6296ea7dcdf51ca.tar.gz xmlgraphics-fop-a174a27add225d21a59d41b2b6296ea7dcdf51ca.zip |
Merged /xmlgraphics/fop/trunk:r1080139-1094916
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ComplexScripts@1094946 13f79535-47bb-0310-9956-ffa450edef68
91 files changed, 3175 insertions, 657 deletions
@@ -956,7 +956,12 @@ list of possible build targets. testsuite="org.apache.fop.intermediate.AreaTreeXMLFormatTestSuite" outfile="TEST-area-tree-xml-format"/> </target> - <target name="junit-intermediate-format" depends="junit-compile" + <target name="junit-intermediate-layout" depends="junit-compile" if="xmlunit.present"> + <junit-run title="intermediate format from layout tests" + testsuite="org.apache.fop.intermediate.LayoutIFTestSuite" + outfile="TEST-intermediate-format-from-layout"/> + </target> + <target name="junit-intermediate-format" depends="junit-compile,junit-intermediate-layout" description="Runs FOP's intermediate format JUnit tests" if="xmlunit.present"> <junit-run title="intermediate format" testsuite="org.apache.fop.intermediate.IntermediateFormatTestSuite" diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml index ead88a04d..561fdfc73 100644 --- a/src/documentation/content/xdocs/team.xml +++ b/src/documentation/content/xdocs/team.xml @@ -31,28 +31,12 @@ <title>Active Committers</title> <note label="Important">Please don't write to any developer directly if you need help on using FOP. Only if you submit questions to the <link href="maillist.html#fop-user">FOP User Mailing List</link> will other FOP users be able to profit from answers given to your question. Another point is that a developer may have gone inactive or is on holidays in which case you may not get an answer in time.</note> <ul> - <li id="mb"><link href="mailto:max AT berger DOT name">Max Berger</link> (MB) is currently a - PostDoc pursuing an academic career in computer science. His main interest in FOP is to - improve the DocBook to PDF tool-chain to produce high quality output, while still - conforming to given style-guides. See his <link href="http://max.berger.name">home - page</link> for more information.</li> <li id="cb"><link href="mailto:bowditch_chris@hotmail.com">Chris Bowditch</link> (CB) is a Java/VB Programmer from England.</li> - <li id="jb"><link href="mailto:jay@bryantcs.com">Jay Bryant</link> (JB) is a - freelance information architect in Austin, TX.</li> <li id="ac"><link href="mailto:acumiskey AT apache.org">Adrian Cumiskey</link> (AC) is an XP/Agile practitioner with interests in open source content management and electronic document generation. He is a UK expat now residing in Singapore.</li> <li id="ad"><link href="mailto:adelmelle@apache.org">Andreas Delmelle</link> (AD)</li> - <!-- Luca prefers the mail address with "AT", to stop spam, etc. --> - <li id="lf"><link href="mailto:lfurini AT cs.unibo.it">Luca Furini</link> (LF) - is a student of Computer Studies at the University of Bologna (Italy)</li> - <li id="cg"><link href="mailto:chrisg@apache.org">Christian Geisert</link> (CG) - is a software engineer from Stutensee, Germany. He is working at - <fork href="http://www.isu-gmbh.de">ISU GmbH</fork>, a provider of ERP solutions, - where amongst lots of other things he is using FOP to produce nice looking - business documents like order confirmations, quotes, invoices etc. - </li> <li id="vh"><link href="mailto:vhennebert@apache.org">Vincent Hennebert</link> (VH), a Java developer from France; with an interest in typography, and in using Fop as a pdf renderer for book-like documents.</li> @@ -61,14 +45,6 @@ recent XML/XSL-FO convert, he has been nit-picking FAQs & assorted web pages since his first webmaster position @brain.com in 1996. Most important creation? He's got a couple of cool kids.</li> - <li id="mm"><link href="mailto:manuel@apache.org">Manuel Mall</link> (MM) - is an independant software engineer resident in Perth, Australia. Born a long time - ago in Germany he has been involved in Software Engineering (Informatik) since the - early 70's. Over the last years he has used FOP very successfully in commercial - projects for his customers (currently generating roughly 15000 PDF files each - working day through FOP) and has decided to put some effort back into FOP to - make it even better. - </li> <li id="jm"><link href="mailto:jeremias@apache.org">Jeremias Märki</link> (JM) is an independent software engineer and consultant from Lucerne, Switzerland. He's also the creator of <fork href="http://barcode4j.sourceforge.net">Barcode4J</fork>. @@ -79,10 +55,6 @@ from the TeX/LaTeX world. See his <fork href="http://www.leverkruid.eu">home page</fork> for some of his private projects.</li> <li id="jp"><link href="mailto:pietsch@apache.org">Jörg Pietschmann</link> (JP)</li> - <li id="ps"><link href="mailto:tcho@club-internet.fr">Pascal Sancho</link> (PS) - is an XML developper from Aix-en-Provence (France). He works on software solutions for - rendering various kind of documents on various supports, more specifically taking care - of PDF generation with FOP.</li> </ul> </section> <section id="contribute-active"> @@ -91,17 +63,10 @@ <li id="gd">Georg Datterl is a software developer from Austria, currently working for Geneon media solutions gmbh in Nuremberg, Germany. He needs FOP to wrestle gigabytes of electronic data into thousands of printed pages.</li> - <li id="ak">Alexander Kiel is a Java developer from Leipzig, Germany. Beside Java he is - interested in XML and Web technologies. He used FOP as part of the Docbook/XML toolchain - for various documentation projects. He decided to contribute to FOP in order to help - making it more feature complete.</li> <li id="lm">Louis Masters</li> <li id="mh">Mehdi Houshmand, Young developer from the UK with a background in Physics. Worked on Flow Cytometry for research and military uses, Telecoms systems and CMS software. Programmed in C/C++, Java and currently learning Python</li> - <li id="rr"><link href="mailto:renaud.richardet AT gmail DOT com">Renaud Richardet</link> (RR) - is a Java Programmer interested in XML technologies. See his - <fork href="http://www.oslutions.com">home page</fork> for more information about him.</li> <li id="vr">Vanukuri Venkat Reddy is a Senior Software Engineer in UK, using XML Graphics Project and FOP for his work, and is committed to contributing more to the Apache to be part a great team.</li> @@ -125,22 +90,26 @@ <section id="commit-inactive"> <title>Inactive Committers</title> <ul> + <li id="mb"><link href="mailto:max AT berger DOT name">Max Berger</link> (MB)</li> <li id="fb"><link href="mailto:bckfnn@worldonline.dk">Finn Bock</link> (FB)</li> + <li id="jb"><link href="mailto:jay@bryantcs.com">Jay Bryant</link> (JB)</li> <li id="kc"><link href="mailto:kellyc@apache.org">Kelly Campbell</link></li> <li id="sc"><link href="mailto:gears@apache.org">Steven Coffman</link></li> <li id="bd"><link href="mailto:bdelacretaz@apache.org">Bertrand Delacretaz</link></li> <li id="te"><link href="mailto:tore@apache.org">Tore Engvig</link></li> + <!-- Luca prefers the mail address with "AT", to stop spam, etc. --> + <li id="lf"><link href="mailto:lfurini AT cs.unibo.it">Luca Furini</link> (LF)</li> + <li id="cg"><link href="mailto:chrisg@apache.org">Christian Geisert</link> (CG)</li> <li id="sg"><link href="mailto:stanislav@apache.org">Stanislav Gorkhover</link></li> - <li id="ph"><link href="mailto:pherweg@web.de">Peter Herweg</link> (PH)<!-- is helping to - integrate the jfor project's RTF support into the upcoming FOP 1.0 version. - Born in 1978, he has been serving as an application developer for a small - industrial company in Germany since 1999.--></li> + <li id="ph"><link href="mailto:pherweg@web.de">Peter Herweg</link> (PH)</li> <li id="fj"><link href="mailto:fotis@apache.org">Fotis Jannidis</link></li> <li id="kl"><link href="mailto:klease@apache.org">Karen Lease</link></li> <li id="kll"><link href="mailto:keiron@apache.org">Keiron Liddle</link></li> + <li id="mm"><link href="mailto:manuel@apache.org">Manuel Mall</link> (MM)</li> <li id="gm"><link href="mailto:gmazza@apache.org">Glen Mazza</link></li> <li id="wvm"><link href="mailto:vmote@apache.org">Victor Mote</link></li> <li id="jn"><link href="mailto:jordan@apache.org">Jordan Naftolin</link></li> + <li id="ps"><link href="mailto:tcho@club-internet.fr">Pascal Sancho</link> (PS)</li> <li id="as"><link href="mailto:arved@apache.org">Arved Sandstrom</link></li> <li id="es"><link href="mailto:eschaeffer@apache.org">Eric Schaeffer</link></li> <li id="ot"><link href="mailto:olegt@apache.org">Oleg Tkachenko</link> (OT)</li> diff --git a/src/documentation/content/xdocs/trunk/hyphenation.xml b/src/documentation/content/xdocs/trunk/hyphenation.xml index ed97c6868..699534ee1 100644 --- a/src/documentation/content/xdocs/trunk/hyphenation.xml +++ b/src/documentation/content/xdocs/trunk/hyphenation.xml @@ -219,15 +219,15 @@ languages and dialects, especially ancient ones, may pose a real problem though.</p> <p>If you want to generate your own patterns, an open-source utility called - patgen is available on many Unix/Linux distributions and every TeX - distribution which can be used to assist in - creating pattern files from dictionaries. Pattern creation for languages like - english or german is an art. If you can, read Frank Liang's original paper - "Word Hy-phen-a-tion by Com-pu-ter" (yes, with hyphens). It is not available - online. The original patgen.web source, included in the TeX source distributions, - contains valuable comments, unfortunately technical details obscure often the - high level issues. Another important source is - <a class="fork" href="http://www.ctan.org/tex-archive/systems/knuth/tex/texbook.tex">The + patgen can be used to assist in creating pattern files from dictionaries. + It is available in many Unix/Linux distributions and every TeX distribution. + Pattern creation for languages like english or german is an art. Read + Frank Liang's original paper <a class="fork" href="http://www.tug.org/docs/liang/">"Word + Hy-phen-a-tion by Com-pu-ter"</a> (yes, with hyphens) for details. + The original patgen.web source, included in the TeX source distributions, + contains valuable comments, unfortunately technical details often obscure the + high level issues. Another important source of information is + <a class="fork" href="http://mirrors.ctan.org/systems/knuth/dist/tex/texbook.tex">The TeX Book</a>, appendix H (either read the TeX source, or run it through TeX to typeset it). Secondary articles, for example the works by Petr Sojka, may also give some much needed insight into problems arising in automated diff --git a/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd b/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd index 4e0b7d115..ac7357f8c 100644 --- a/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd +++ b/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd @@ -42,6 +42,11 @@ </xs:complexContent> </xs:complexType> </xs:element> + <xs:element name="id"> + <xs:complexType> + <xs:attribute name="name" use="required" type="xs:string"/> + </xs:complexType> + </xs:element> <xs:element name="font"> <xs:complexType> <xs:attribute name="family" type="xs:string"/> diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java index 0e2b8bf71..f45245bfe 100644 --- a/src/java/org/apache/fop/area/AreaTreeHandler.java +++ b/src/java/org/apache/fop/area/AreaTreeHandler.java @@ -336,7 +336,7 @@ public class AreaTreeHandler extends FOEventHandler { String[] ids = res.getIDRefs(); for (String id : ids) { List<PageViewport> pageVPList = idTracker.getPageViewportsContainingID(id); - if (pageVPList != null) { + if (pageVPList != null && !pageVPList.isEmpty()) { res.resolveIDRef(id, pageVPList); } else { AreaEventProducer eventProducer = AreaEventProducer.Provider.get( diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index caf25081e..627635531 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -73,7 +73,7 @@ import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.Space; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.area.inline.Viewport; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.ElementMappingRegistry; import org.apache.fop.fo.expr.PropertyException; @@ -217,7 +217,7 @@ public class AreaTreeParser { makers.put("word", new WordMaker()); makers.put("space", new SpaceMaker()); makers.put("leader", new LeaderMaker()); - makers.put("viewport", new ViewportMaker()); + makers.put("viewport", new InlineViewportMaker()); makers.put("image", new ImageMaker()); makers.put("foreignObject", new ForeignObjectMaker()); makers.put("bookmarkTree", new BookmarkTreeMaker()); @@ -265,8 +265,8 @@ public class AreaTreeParser { return (AbstractTextArea)findAreaType(AbstractTextArea.class); } - private Viewport getCurrentViewport() { - return (Viewport)findAreaType(Viewport.class); + private InlineViewport getCurrentViewport() { + return (InlineViewport)findAreaType(InlineViewport.class); } /** {@inheritDoc} */ @@ -909,10 +909,10 @@ public class AreaTreeParser { } } - private class ViewportMaker extends AbstractMaker { + private class InlineViewportMaker extends AbstractMaker { public void startElement(Attributes attributes) { - Viewport viewport = new Viewport(null); + InlineViewport viewport = new InlineViewport(null); transferForeignObjects(attributes, viewport); setAreaAttributes(attributes, viewport); setTraits(attributes, viewport, SUBSET_COMMON); @@ -929,7 +929,7 @@ public class AreaTreeParser { } public void endElement() { - assertObjectOfClass(areaStack.pop(), Viewport.class); + assertObjectOfClass(areaStack.pop(), InlineViewport.class); } } diff --git a/src/java/org/apache/fop/area/BlockViewport.java b/src/java/org/apache/fop/area/BlockViewport.java index 032b39f95..066f2f9e8 100644 --- a/src/java/org/apache/fop/area/BlockViewport.java +++ b/src/java/org/apache/fop/area/BlockViewport.java @@ -19,12 +19,14 @@ package org.apache.fop.area; +import java.awt.Rectangle; + /** * A BlockViewport. * This is used for block level Viewport/reference pairs. * The block-container creates this area. */ -public class BlockViewport extends Block { +public class BlockViewport extends Block implements Viewport { private static final long serialVersionUID = -7840580922580735157L; @@ -78,14 +80,18 @@ public class BlockViewport extends Block { clip = cl; } - /** - * Get the clipping for this viewport. - * - * @return the clipping for the viewport - * true if the contents should be clipped for this viewport - */ - public boolean getClip() { + /** {@inheritDoc} */ + public boolean hasClip() { return clip; } + + /** {@inheritDoc} */ + public Rectangle getClipRectangle() { + if (clip) { + return new Rectangle(getIPD(), getBPD()); + } else { + return null; + } + } } diff --git a/src/java/org/apache/fop/area/RegionViewport.java b/src/java/org/apache/fop/area/RegionViewport.java index 8720dc877..6975bd30b 100644 --- a/src/java/org/apache/fop/area/RegionViewport.java +++ b/src/java/org/apache/fop/area/RegionViewport.java @@ -19,6 +19,7 @@ package org.apache.fop.area; +import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.util.HashMap; @@ -29,7 +30,7 @@ import java.util.HashMap; * region-reference-area as its child. These areas are described * in the fo:region-body description in the XSL Recommendation. */ -public class RegionViewport extends Area implements Cloneable { +public class RegionViewport extends Area implements Cloneable, Viewport { private static final long serialVersionUID = 505781815165102572L; @@ -75,11 +76,20 @@ public class RegionViewport extends Area implements Cloneable { clip = c; } - /** @return true if the viewport should be clipped. */ - public boolean isClip() { + /** {@inheritDoc} */ + public boolean hasClip() { return this.clip; } + /** {@inheritDoc} */ + public Rectangle getClipRectangle() { + if (clip) { + return new Rectangle(getIPD(), getBPD()); + } else { + return null; + } + } + /** * Get the view area of this viewport. * diff --git a/src/java/org/apache/fop/area/Viewport.java b/src/java/org/apache/fop/area/Viewport.java new file mode 100644 index 000000000..a92d826cc --- /dev/null +++ b/src/java/org/apache/fop/area/Viewport.java @@ -0,0 +1,44 @@ +/* + * 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.area; + +import java.awt.Rectangle; + +/** + * A viewport-area that may clip its content. + */ +public interface Viewport { + + /** + * Returns true if this area will clip overflowing content. + * + * @return {@code true} if the overflow trait has the value "hidden", "scroll" or + * "error-if-overflow" + */ + boolean hasClip(); + + /** + * Returns the clipping rectangle of this viewport area. + * + * @return the clipping rectangle expressed in the viewport's coordinate system, or + * null if clipping is disabled + */ + Rectangle getClipRectangle(); +} diff --git a/src/java/org/apache/fop/area/inline/AbstractTextArea.java b/src/java/org/apache/fop/area/inline/AbstractTextArea.java index 08997a817..348820939 100644 --- a/src/java/org/apache/fop/area/inline/AbstractTextArea.java +++ b/src/java/org/apache/fop/area/inline/AbstractTextArea.java @@ -185,4 +185,15 @@ public abstract class AbstractTextArea extends InlineParent { public void setBaselineOffset(int baselineOffset) { this.baselineOffset = baselineOffset; } + + @Override + int getVirtualOffset() { + return getBlockProgressionOffset(); + } + + @Override + int getVirtualBPD() { + /* Word and space areas don't have a properly set bpd; return this area's bpd instead. */ + return getBPD(); + } } diff --git a/src/java/org/apache/fop/area/inline/BasicLinkArea.java b/src/java/org/apache/fop/area/inline/BasicLinkArea.java new file mode 100644 index 000000000..1fedf5624 --- /dev/null +++ b/src/java/org/apache/fop/area/inline/BasicLinkArea.java @@ -0,0 +1,53 @@ +/* + * 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.area.inline; + +import org.apache.fop.area.Area; + +/** + * An inline area produced by an fo:basic-link element. This class implements a different + * behavior to what is prescribed by the XSL-FO 1.1 Recommendation. With the standard + * behavior, there is no easy way to make a link cover e.g. a whole image. + * + * <p>See following bug report at W3C's: + * http://www.w3.org/Bugs/Public/show_bug.cgi?id=11672</p> + */ +public class BasicLinkArea extends InlineParent { + + private static final long serialVersionUID = 5183753430412208151L; + + @Override + public void setParentArea(Area parentArea) { + super.setParentArea(parentArea); + /* + * Perform necessary modifications to make this area encompass all of its children + * elements, so as to have a useful active area. We assume that this method is + * called after all of the children areas have been added to this area. + */ + /* Make this area start at its beforest child. */ + setBlockProgressionOffset(getBlockProgressionOffset() + minChildOffset); + /* Update children offsets accordingly. */ + for (InlineArea inline : inlines) { + inline.setBlockProgressionOffset(inline.getBlockProgressionOffset() - minChildOffset); + } + setBPD(getVirtualBPD()); + } + +} diff --git a/src/java/org/apache/fop/area/inline/FilledArea.java b/src/java/org/apache/fop/area/inline/FilledArea.java index 2b586b680..b34796e56 100644 --- a/src/java/org/apache/fop/area/inline/FilledArea.java +++ b/src/java/org/apache/fop/area/inline/FilledArea.java @@ -19,10 +19,10 @@ package org.apache.fop.area.inline; -import java.util.List; -import java.util.ListIterator; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; /** * Filled area. @@ -60,7 +60,7 @@ public class FilledArea extends InlineParent { InlineArea child = (InlineArea) childrenIterator.next(); if (child instanceof InlineParent) { setChildOffset(((InlineParent) child).getChildAreas().listIterator(), v); - } else if (child instanceof org.apache.fop.area.inline.Viewport) { + } else if (child instanceof InlineViewport) { // nothing } else { child.setBlockProgressionOffset(v); diff --git a/src/java/org/apache/fop/area/inline/InlineArea.java b/src/java/org/apache/fop/area/inline/InlineArea.java index caafab5a5..c17bd4b3d 100644 --- a/src/java/org/apache/fop/area/inline/InlineArea.java +++ b/src/java/org/apache/fop/area/inline/InlineArea.java @@ -268,4 +268,31 @@ public class InlineArea extends Area { storedIPDVariation += ipdVariation; } } + + /** + * Returns the offset that this area would have if its offset and size were taking + * children areas into account. The bpd of an inline area is taken from its nominal + * font and doesn't depend on the bpds of its children elements. However, in the case + * of a basic-link element we want the active area to cover all of the children + * elements. + * + * @return the offset that this area would have if the before-edge of its + * content-rectangle were coinciding with the <q>beforest</q> before-edge of its + * children allocation-rectangles. + * @see #getVirtualBPD() + * @see BasicLinkArea + */ + int getVirtualOffset() { + return getBlockProgressionOffset(); + } + + /** + * Returns the block-progression-dimension that this area would have if it were taking + * its children elements into account. See {@linkplain #getVirtualOffset()}. + * + * @return the bpd + */ + int getVirtualBPD() { + return getBPD(); + } } diff --git a/src/java/org/apache/fop/area/inline/InlineParent.java b/src/java/org/apache/fop/area/inline/InlineParent.java index f2d218dae..7419ff066 100644 --- a/src/java/org/apache/fop/area/inline/InlineParent.java +++ b/src/java/org/apache/fop/area/inline/InlineParent.java @@ -40,32 +40,43 @@ public class InlineParent extends InlineArea { /** Controls whether the IPD is automatically adjusted based on the area's children. */ protected transient boolean autoSize; - /** - * Create a new inline parent to add areas to. - */ - public InlineParent() { - } + /** The offset of the <q>beforest</q> child area of this area. */ + protected int minChildOffset; /** - * Override generic Area method. - * - * @param childArea the child area to add + * The offset of the <q>afterest</q> child area of this area. Offset from the + * before-edge of this area's content-rectangle and the after-edge of the child area's + * allocation-rectangle. */ + private int maxAfterEdge; + @Override - public void addChildArea(Area childArea) { + public void addChildArea(Area c) { + assert c instanceof InlineArea; if (inlines.size() == 0) { autoSize = (getIPD() == 0); } - if (childArea instanceof InlineArea) { - InlineArea inlineChildArea = (InlineArea) childArea; - inlines.add(inlineChildArea); - // set the parent area for the child area - inlineChildArea.setParentArea(this); - if (autoSize) { - increaseIPD(inlineChildArea.getAllocIPD()); - } + InlineArea childArea = (InlineArea) c; + inlines.add(childArea); + // set the parent area for the child area + childArea.setParentArea(this); + if (autoSize) { + increaseIPD(childArea.getAllocIPD()); updateLevel ( childArea.getBidiLevel() ); } + int childOffset = childArea.getVirtualOffset(); + minChildOffset = Math.min(minChildOffset, childOffset); + maxAfterEdge = Math.max(maxAfterEdge, childOffset + childArea.getVirtualBPD()); + } + + @Override + int getVirtualOffset() { + return getBlockProgressionOffset() + minChildOffset; + } + + @Override + int getVirtualBPD() { + return maxAfterEdge - minChildOffset; } /** diff --git a/src/java/org/apache/fop/area/inline/InlineViewport.java b/src/java/org/apache/fop/area/inline/InlineViewport.java new file mode 100644 index 000000000..bc32a92d0 --- /dev/null +++ b/src/java/org/apache/fop/area/inline/InlineViewport.java @@ -0,0 +1,141 @@ +/* + * 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.area.inline; + +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.util.HashMap; + +import org.apache.fop.area.Area; +import org.apache.fop.area.Viewport; + +/** + * Inline viewport area. + * This is an inline-level viewport area for inline container, + * external graphic and instream foreign object. This viewport + * holds the area and positions it. + */ +public class InlineViewport extends InlineArea implements Viewport { + + private static final long serialVersionUID = 813338534627918689L; + + // contents could be container, foreign object or image + private Area content; + // clipping for the viewport + private boolean clip = false; + // position of the child area relative to this area + private Rectangle2D contentPosition; + + /** + * Create a new viewport area with the content area. + * + * @param child the child content area of this viewport + */ + public InlineViewport(Area child) { + this.content = child; + } + + /** + * Set the clip of this viewport. + * + * @param c true if this viewport should clip + */ + public void setClip(boolean c) { + this.clip = c; + } + + /** {@inheritDoc} */ + public boolean hasClip() { + return this.clip; + } + + /** {@inheritDoc} */ + public Rectangle getClipRectangle() { + if (clip) { + return new Rectangle(getIPD(), getBPD()); + } else { + return null; + } + } + + /** + * Set the position and size of the content of this viewport. + * + * @param cp the position and size to place the content + */ + public void setContentPosition(Rectangle2D cp) { + this.contentPosition = cp; + } + + /** + * Get the position and size of the content of this viewport. + * + * @return the position and size to place the content + */ + public Rectangle2D getContentPosition() { + return this.contentPosition; + } + + /** + * Sets the content area. + * @param content the content area + */ + public void setContent(Area content) { + this.content = content; + } + + /** + * Get the content area for this viewport. + * + * @return the content area + */ + public Area getContent() { + return this.content; + } + + private void writeObject(java.io.ObjectOutputStream out) + throws IOException { + out.writeBoolean(contentPosition != null); + if (contentPosition != null) { + out.writeFloat((float) contentPosition.getX()); + out.writeFloat((float) contentPosition.getY()); + out.writeFloat((float) contentPosition.getWidth()); + out.writeFloat((float) contentPosition.getHeight()); + } + out.writeBoolean(clip); + out.writeObject(traits); + out.writeObject(content); + } + + private void readObject(java.io.ObjectInputStream in) + throws IOException, ClassNotFoundException { + if (in.readBoolean()) { + contentPosition = new Rectangle2D.Float(in.readFloat(), + in.readFloat(), + in.readFloat(), + in.readFloat()); + } + this.clip = in.readBoolean(); + this.traits = (HashMap) in.readObject(); + this.content = (Area) in.readObject(); + } + +} diff --git a/src/java/org/apache/fop/fo/FObjMixed.java b/src/java/org/apache/fop/fo/FObjMixed.java index 5dc5dd49d..d4867fb4a 100644 --- a/src/java/org/apache/fop/fo/FObjMixed.java +++ b/src/java/org/apache/fop/fo/FObjMixed.java @@ -50,6 +50,7 @@ public abstract class FObjMixed extends FObj { } /** {@inheritDoc} */ + @Override protected void characters(char[] data, int start, int length, PropertyList pList, Locator locator) throws FOPException { @@ -64,6 +65,7 @@ public abstract class FObjMixed extends FObj { } /** {@inheritDoc} */ + @Override protected void endOfNode() throws FOPException { super.endOfNode(); @@ -150,6 +152,7 @@ public abstract class FObjMixed extends FObj { } /** {@inheritDoc} */ + @Override protected void addChildNode(FONode child) throws FOPException { flushText(); @@ -169,6 +172,17 @@ public abstract class FObjMixed extends FObj { } /** {@inheritDoc} */ + @Override + public void removeChild(FONode child) { + super.removeChild(child); + if (child == this.currentTextNode) { + // reset to following sibling + this.currentTextNode = child.siblings != null ? child.siblings[1] : null; + } + } + + /** {@inheritDoc} */ + @Override public void finalizeNode() throws FOPException { flushText(); @@ -183,6 +197,7 @@ public abstract class FObjMixed extends FObj { * * @return iterator for this object */ + @Override public CharIterator charIterator() { return new RecursiveCharIterator(this); } diff --git a/src/java/org/apache/fop/fo/properties/TextDecorationMaker.java b/src/java/org/apache/fop/fo/properties/TextDecorationMaker.java index de26934a0..fad48ed0c 100644 --- a/src/java/org/apache/fop/fo/properties/TextDecorationMaker.java +++ b/src/java/org/apache/fop/fo/properties/TextDecorationMaker.java @@ -59,14 +59,16 @@ public class TextDecorationMaker extends ListProperty.Maker { boolean over = false; boolean through = false; boolean blink = false; - int enumValue; + int enumValue = -1; for (int i = lst.size(); --i >= 0;) { Property prop = (Property)lst.get(i); if (prop instanceof NCnameProperty) { prop = checkEnumValues(prop.getString()); lst.set(i, prop); } - enumValue = prop.getEnum(); + if (prop != null) { + enumValue = prop.getEnum(); + } switch (enumValue) { case Constants.EN_NONE: if (under | over | through | blink) { @@ -115,7 +117,7 @@ public class TextDecorationMaker extends ListProperty.Maker { throw new PropertyException("Invalid combination of values"); } default: - throw new PropertyException("Invalid value specified: " + prop); + throw new PropertyException("Invalid value specified: " + p); } } return listProp; diff --git a/src/java/org/apache/fop/fonts/BFEntry.java b/src/java/org/apache/fop/fonts/BFEntry.java index 2ae978b26..d3c7956ba 100644 --- a/src/java/org/apache/fop/fonts/BFEntry.java +++ b/src/java/org/apache/fop/fonts/BFEntry.java @@ -65,8 +65,9 @@ public class BFEntry { } /** {@inheritDoc} */ + @Override public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder("BFEntry: "); sb.append ( "{ UC[" ); sb.append ( unicodeStart ); sb.append ( ',' ); diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 7b29db895..95b7f8a39 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -346,6 +346,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager updateContentAreaIPDwithOverconstrainedAdjust(contentWidth); } + contentRectOffsetX = 0; + contentRectOffsetY = 0; + contentRectOffsetX += fo.getCommonMarginBlock().startIndent.getValue(this); contentRectOffsetY += fo.getCommonBorderPaddingBackground().getBorderBeforeWidth(false); contentRectOffsetY += fo.getCommonBorderPaddingBackground().getPaddingBefore(false, this); diff --git a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java index 111f8e3ed..533e5ac1b 100644 --- a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java @@ -45,7 +45,7 @@ import org.apache.fop.area.PageSequence; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.inline.Image; -import org.apache.fop.area.inline.Viewport; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.Constants; @@ -185,7 +185,7 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan TraitSetter.setProducerID(imageArea, fobj.getId()); transferForeignAttributes(imageArea); - Viewport vp = new Viewport(imageArea); + InlineViewport vp = new InlineViewport(imageArea); TraitSetter.setProducerID(vp, fobj.getId()); vp.setIPD(imageSize.width); vp.setBPD(imageSize.height); diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index 969c4a25b..4cd06b973 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -24,7 +24,7 @@ import java.awt.Rectangle; import java.util.List; import org.apache.fop.area.Area; -import org.apache.fop.area.inline.Viewport; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.fo.FObj; import org.apache.fop.fo.flow.AbstractGraphics; @@ -54,7 +54,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage * * @return the viewport inline area */ - private Viewport getInlineArea() { + private InlineViewport getInlineArea() { final AbstractGraphics fobj = (AbstractGraphics)this.fobj; Dimension intrinsicSize = new Dimension( fobj.getIntrinsicWidth(), @@ -84,7 +84,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage TraitSetter.setProducerID(viewportArea, fobj.getId()); transferForeignAttributes(viewportArea); - Viewport vp = new Viewport(viewportArea); + InlineViewport vp = new InlineViewport(viewportArea); TraitSetter.addPtr(vp, fobj.getPtr()); // used for accessibility TraitSetter.setProducerID(vp, fobj.getId()); vp.setIPD(imageLayout.getViewportSize().width); @@ -106,7 +106,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage /** {@inheritDoc} */ public List getNextKnuthElements(LayoutContext context, int alignment) { - Viewport areaCurrent = getInlineArea(); + InlineViewport areaCurrent = getInlineArea(); setCurrentArea(areaCurrent); return super.getNextKnuthElements(context, alignment); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java index eef649c97..40c9a324e 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java @@ -21,7 +21,9 @@ package org.apache.fop.layoutmgr.inline; import org.apache.fop.area.LinkResolver; import org.apache.fop.area.Trait; +import org.apache.fop.area.inline.BasicLinkArea; import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.InlineParent; import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.BasicLink; @@ -77,4 +79,10 @@ public class BasicLinkLayoutManager extends InlineLayoutManager { } } } + + @Override + protected InlineParent createInlineParent() { + return new BasicLinkArea(); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 7b4b36ecc..fb5bd393a 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -198,13 +198,13 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { /** * Create and initialize an <code>InlineArea</code> * - * @param hasInlineParent true if the parent is an inline + * @param isInline true if the parent is an inline * @return the area */ - protected InlineArea createArea(boolean hasInlineParent) { + protected InlineArea createArea(boolean isInline) { InlineArea area; - if (hasInlineParent) { - area = new InlineParent(); + if (isInline) { + area = createInlineParent(); area.setBlockProgressionOffset(0); } else { area = new InlineBlockParent(); @@ -215,6 +215,16 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { return area; } + /** + * Creates the inline area that will contain the areas returned by the + * children of this layout manager. + * + * @return a new inline area + */ + protected InlineParent createInlineParent() { + return new InlineParent(); + } + /** {@inheritDoc} */ @Override protected void setTraits(boolean isNotFirst, boolean isNotLast) { diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 7347eb3af..ea92eb53a 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -27,6 +27,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.LineArea; import org.apache.fop.area.Trait; @@ -157,7 +158,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager private final int follow; private AlignmentContext alignmentContext; - private List knuthParagraphs; + private List<KnuthSequence> knuthParagraphs; private LineLayoutPossibilities lineLayouts; private LineLayoutPossibilities[] lineLayoutsList; @@ -402,7 +403,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager // true if this line contains only zero-height, auxiliary boxes // and the actual line width is 0; in this case, the line "collapses" // i.e. the line area will have bpd = 0 - boolean bZeroHeightLine = (difference == ipd); + boolean isZeroHeightLine = (difference == ipd); // if line-stacking-strategy is "font-height", the line height // is not affected by its content @@ -438,9 +439,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager } lastAC = ac; } - if (bZeroHeightLine + if (isZeroHeightLine && (!element.isAuxiliary() || ac != null && ac.getHeight() > 0)) { - bZeroHeightLine = false; + isZeroHeightLine = false; } } } @@ -452,7 +453,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager constantLineHeight = lineLead + lineFollow; - if (bZeroHeightLine) { + if (isZeroHeightLine) { return new LineBreakPosition(thisLLM, knuthParagraphs.indexOf(par), firstElementIndex, lastElementIndex, @@ -583,7 +584,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager //PHASE 1: Create Knuth elements if (knuthParagraphs == null) { // it's the first time this method is called - knuthParagraphs = new ArrayList(); + knuthParagraphs = new ArrayList<KnuthSequence>(); // here starts Knuth's algorithm collectInlineKnuthElements(context); @@ -615,12 +616,10 @@ public class LineLayoutManager extends InlineStackingLayoutManager LeafPosition restartPosition) { log.trace("Restarting line breaking from index " + restartPosition.getIndex()); int parIndex = restartPosition.getLeafPos(); - Paragraph paragraph = (Paragraph) knuthParagraphs.get(parIndex); - for (int i = 0; i <= restartPosition.getIndex(); i++) { - paragraph.remove(0); - } - Iterator iter = paragraph.iterator(); - while (iter.hasNext() && !((KnuthElement) iter.next()).isBox()) { + KnuthSequence paragraph = knuthParagraphs.get(parIndex); + paragraph.subList(0, restartPosition.getIndex() + 1).clear(); + Iterator<KnuthElement> iter = paragraph.iterator(); + while (iter.hasNext() && !iter.next().isBox()) { iter.remove(); } if (!iter.hasNext()) { @@ -653,8 +652,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager Paragraph lastPar = null; - InlineLevelLayoutManager curLM; - while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) { + InlineLevelLayoutManager curLM = (InlineLevelLayoutManager) getChildLM(); + while (curLM != null) { List inlineElements = curLM.getNextKnuthElements(inlineLC, effectiveAlignment); if (inlineElements == null || inlineElements.size() == 0) { /* curLM.getNextKnuthElements() returned null or an empty list; @@ -751,7 +750,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager } } } // end of loop over returnedList + curLM = (InlineLevelLayoutManager) getChildLM(); } + if (lastPar != null) { lastPar.endParagraph(); ElementListObserver.observe(lastPar, "line", fobj.getId()); @@ -768,13 +769,13 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param context the layout context * @return a list of Knuth elements representing broken lines */ - private List createLineBreaks(int alignment, LayoutContext context) { + private List<ListElement> createLineBreaks(int alignment, LayoutContext context) { // find the optimal line breaking points for each paragraph - Iterator paragraphsIterator = knuthParagraphs.iterator(); + Iterator<KnuthSequence> paragraphsIterator = knuthParagraphs.iterator(); lineLayoutsList = new LineLayoutPossibilities[knuthParagraphs.size()]; LineLayoutPossibilities llPoss; for (int i = 0; paragraphsIterator.hasNext(); i++) { - KnuthSequence seq = (KnuthSequence) paragraphsIterator.next(); + KnuthSequence seq = paragraphsIterator.next(); if (!seq.isInlineSequence()) { // This set of line layout possibilities does not matter; // we only need an entry in lineLayoutsList. @@ -810,7 +811,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager lineHeight.getValue(this), lead, follow, (knuthParagraphs.indexOf(currPar) == 0), hyphenationLadderCount.getEnum() == EN_NO_LIMIT - ? 0 : hyphenationLadderCount.getValue(), + ? 0 : hyphenationLadderCount.getValue(), this); alg.setConstantLineWidth(ipd); boolean canWrap = (wrapOption != EN_NO_WRAP); @@ -876,7 +877,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param context the layout context * @return the newly built element list */ - private List postProcessLineBreaks(int alignment, LayoutContext context) { + private List<ListElement> postProcessLineBreaks(int alignment, LayoutContext context) { List<ListElement> returnList = new LinkedList<ListElement>(); @@ -893,7 +894,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } LineLayoutPossibilities llPoss = lineLayoutsList[p]; - KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(p); + KnuthSequence seq = knuthParagraphs.get(p); if (!seq.isInlineSequence()) { List<ListElement> targetList = new LinkedList<ListElement>(); @@ -1152,7 +1153,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager /** {@inheritDoc} */ public List getChangedKnuthElements(List oldList, int alignment) { - List returnList = new LinkedList(); + List<KnuthElement> returnList = new LinkedList<KnuthElement>(); for (int p = 0; p < knuthParagraphs.size(); p++) { LineLayoutPossibilities llPoss = lineLayoutsList[p]; //log.debug("demerits of the chosen layout: " + llPoss.getChosenDemerits()); @@ -1395,7 +1396,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager public void addAreas(PositionIterator parentIter, LayoutContext context) { while (parentIter.hasNext()) { - Position pos = (Position) parentIter.next(); + Position pos = parentIter.next(); boolean isLastPosition = !parentIter.hasNext(); if (pos instanceof LineBreakPosition) { addInlineArea(context, (LineBreakPosition) pos, isLastPosition); @@ -1429,13 +1430,13 @@ public class LineLayoutManager extends InlineStackingLayoutManager (lbp.getLeafPos() < seq.size() - 1 ? textAlignment : textAlignmentLast), lbp.difference, lbp.availableStretch, lbp.availableShrink); if (lbp.startIndent != 0) { - lineArea.addTrait(Trait.START_INDENT, new Integer(lbp.startIndent)); + lineArea.addTrait(Trait.START_INDENT, lbp.startIndent); } lineArea.setBPD(lbp.lineHeight); lineArea.setIPD(lbp.lineWidth); lineArea.setBidiLevel(bidiLevel); - lineArea.addTrait(Trait.SPACE_BEFORE, new Integer(lbp.spaceBefore)); - lineArea.addTrait(Trait.SPACE_AFTER, new Integer(lbp.spaceAfter)); + lineArea.addTrait(Trait.SPACE_BEFORE, lbp.spaceBefore); + lineArea.addTrait(Trait.SPACE_AFTER, lbp.spaceAfter); alignmentContext.resizeLine(lbp.lineHeight, lbp.baseline); if (seq instanceof Paragraph) { diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index ded18384d..d5f259b38 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -553,12 +553,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public Keep getKeepTogether() { - Keep keep = Keep.KEEP_AUTO; - if (primaryGridUnit.getRow() != null) { - keep = Keep.getKeep(primaryGridUnit.getRow().getKeepTogether()); - } - keep = keep.compare(getParentKeepTogether()); - return keep; + // keep-together does not apply to fo:table-cell + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 92e8ba5dd..7e37eeb59 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -239,7 +239,7 @@ public class TableStepper { } } - Keep keep = Keep.KEEP_AUTO; + Keep keep = getTableLM().getKeepTogether(); int stepPenalty = 0; for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); @@ -248,8 +248,6 @@ public class TableStepper { } if (!rowFinished) { keep = keep.compare(rowGroup[activeRowIndex].getKeepTogether()); - //The above call doesn't take the penalty from the table into account, so... - keep = keep.compare(getTableLM().getKeepTogether()); } else if (activeRowIndex < rowGroup.length - 1) { keep = keep.compare(rowGroup[activeRowIndex].getKeepWithNext()); keep = keep.compare(rowGroup[activeRowIndex + 1].getKeepWithPrevious()); diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 9f10a3b61..0256c05c4 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -44,7 +44,7 @@ import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.InlineArea; -import org.apache.fop.area.inline.Viewport; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.FontMetrics; @@ -542,7 +542,7 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { } //Clipping - if (bv.getClip()) { + if (bv.hasClip()) { clipRect(0f, 0f, width, height); } @@ -593,8 +593,8 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { //Now adjust for border/padding currentBPPosition += borderPaddingBefore; - Rectangle2D clippingRect = null; - if (bv.getClip()) { + Rectangle clippingRect = null; + if (bv.hasClip()) { clippingRect = new Rectangle(currentIPPosition, currentBPPosition, bv.getIPD(), bv.getBPD()); } @@ -685,7 +685,7 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { * This renders an inline viewport by clipping if necessary. * @param viewport the viewport to handle */ - public void renderViewport(Viewport viewport) { + public void renderInlineViewport(InlineViewport viewport) { float x = currentIPPosition / 1000f; float y = (currentBPPosition + viewport.getBlockProgressionOffset()) / 1000f; @@ -701,14 +701,14 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { drawBackAndBorders(viewport, x, y, width + bpwidth, height + bpheight); - if (viewport.getClip()) { + if (viewport.hasClip()) { saveGraphicsState(); clipRect(x + borderPaddingStart, y + borderPaddingBefore, width, height); } - super.renderViewport(viewport); + super.renderInlineViewport(viewport); - if (viewport.getClip()) { + if (viewport.hasClip()) { restoreGraphicsState(); } } diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 5660b7ec4..2c4dc84bd 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -65,7 +65,7 @@ import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.Space; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.area.inline.Viewport; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontInfo; @@ -278,7 +278,6 @@ public abstract class AbstractRenderer * @param port The region viewport to be rendered */ protected void renderRegionViewport(RegionViewport port) { - Rectangle2D view = port.getViewArea(); // The CTM will transform coordinates relative to // this region-reference area into page coords, so // set origin for the region to 0,0. @@ -289,7 +288,7 @@ public abstract class AbstractRenderer handleRegionTraits(port); // shouldn't the viewport have the CTM - startVParea(regionReference.getCTM(), port.isClip() ? view : null); + startVParea(regionReference.getCTM(), port.getClipRectangle()); // do after starting viewport area if (regionReference.getRegionClass() == FO_REGION_BODY) { renderBodyRegion((BodyRegion) regionReference); @@ -306,7 +305,7 @@ public abstract class AbstractRenderer * @param clippingRect the clipping rectangle if the viewport should be clipping, * null if no clipping is performed. */ - protected abstract void startVParea(CTM ctm, Rectangle2D clippingRect); + protected abstract void startVParea(CTM ctm, Rectangle clippingRect); /** * Signals exit from a viewport area. Subclasses can restore transformation matrices @@ -461,8 +460,8 @@ public abstract class AbstractRenderer int saveIP = currentIPPosition; int saveBP = currentBPPosition; - Rectangle2D clippingRect = null; - if (bv.getClip()) { + Rectangle clippingRect = null; + if (bv.hasClip()) { clippingRect = new Rectangle(saveIP, saveBP, bv.getIPD(), bv.getBPD()); } @@ -632,8 +631,8 @@ public abstract class AbstractRenderer renderInlineBlockParent((InlineBlockParent) inlineArea); } else if (inlineArea instanceof Space) { renderInlineSpace((Space) inlineArea); - } else if (inlineArea instanceof Viewport) { - renderViewport((Viewport) inlineArea); + } else if (inlineArea instanceof InlineViewport) { + renderInlineViewport((InlineViewport) inlineArea); } else if (inlineArea instanceof Leader) { renderLeader((Leader) inlineArea); } @@ -736,7 +735,7 @@ public abstract class AbstractRenderer * Render the given Viewport. * @param viewport the viewport to render */ - protected void renderViewport(Viewport viewport) { + protected void renderInlineViewport(InlineViewport viewport) { Area content = viewport.getContent(); int saveBP = currentBPPosition; currentBPPosition += viewport.getBlockProgressionOffset(); diff --git a/src/java/org/apache/fop/render/intermediate/IFConstants.java b/src/java/org/apache/fop/render/intermediate/IFConstants.java index 34fe2bd2c..2b16b343d 100644 --- a/src/java/org/apache/fop/render/intermediate/IFConstants.java +++ b/src/java/org/apache/fop/render/intermediate/IFConstants.java @@ -67,6 +67,8 @@ public interface IFConstants extends XMLConstants { String EL_FONT = "font"; /** element name text */ String EL_TEXT = "text"; + /** element name id */ + String EL_ID = "id"; /** Parent element of the logical structure tree. */ String EL_STRUCTURE_TREE = "structure-tree"; } diff --git a/src/java/org/apache/fop/render/intermediate/IFContext.java b/src/java/org/apache/fop/render/intermediate/IFContext.java index 804b353c1..b8be97253 100644 --- a/src/java/org/apache/fop/render/intermediate/IFContext.java +++ b/src/java/org/apache/fop/render/intermediate/IFContext.java @@ -48,6 +48,8 @@ public class IFContext { private String structurePointer; + private String id = ""; + /** * Main constructor. * @param ua the user agent @@ -155,4 +157,23 @@ public class IFContext { return this.structurePointer; } + /** + * Sets the ID of the object enclosing the content that will follow. + * + * @param id the ID of the nearest ancestor object for which the id property was set + */ + void setID(String id) { + assert id != null; + this.id = id; + } + + /** + * Returns the ID of the object enclosing the current content. + * + * @return the ID of the nearest ancestor object for which the id property was set + */ + String getID() { + return id; + } + } diff --git a/src/java/org/apache/fop/render/intermediate/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java index 3cebc4c31..54fc342ca 100644 --- a/src/java/org/apache/fop/render/intermediate/IFParser.java +++ b/src/java/org/apache/fop/render/intermediate/IFParser.java @@ -24,6 +24,7 @@ import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.AffineTransform; +import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -76,7 +77,7 @@ public class IFParser implements IFConstants { private static SAXTransformerFactory tFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); - private static Set handledNamespaces = new java.util.HashSet(); + private static Set<String> handledNamespaces = new java.util.HashSet<String>(); static { handledNamespaces.add(XMLNS_NAMESPACE_URI); @@ -132,7 +133,7 @@ public class IFParser implements IFConstants { private static class Handler extends DefaultHandler { - private Map elementHandlers = new java.util.HashMap(); + private Map<String, ElementHandler> elementHandlers = new HashMap<String, ElementHandler>(); private IFDocumentHandler documentHandler; private IFPainter painter; @@ -188,6 +189,7 @@ public class IFParser implements IFConstants { //Page content elementHandlers.put(EL_VIEWPORT, new ViewportHandler()); elementHandlers.put(EL_GROUP, new GroupHandler()); + elementHandlers.put(EL_ID, new IDHandler()); elementHandlers.put(EL_FONT, new FontHandler()); elementHandlers.put(EL_TEXT, new TextHandler()); elementHandlers.put(EL_CLIP_RECT, new ClipRectHandler()); @@ -202,7 +204,7 @@ public class IFParser implements IFConstants { } } - private void establishForeignAttributes(Map foreignAttributes) { + private void establishForeignAttributes(Map<QName, String> foreignAttributes) { documentHandler.getContext().setForeignAttributes(foreignAttributes); } @@ -300,7 +302,7 @@ public class IFParser implements IFConstants { private boolean startIFElement(String localName, Attributes attributes) throws SAXException { lastAttributes = new AttributesImpl(attributes); - ElementHandler elementHandler = (ElementHandler)elementHandlers.get(localName); + ElementHandler elementHandler = elementHandlers.get(localName); content.setLength(0); ignoreCharacters = true; if (elementHandler != null) { @@ -346,7 +348,7 @@ public class IFParser implements IFConstants { } } else { if (NAMESPACE.equals(uri)) { - ElementHandler elementHandler = (ElementHandler)elementHandlers.get(localName); + ElementHandler elementHandler = elementHandlers.get(localName); if (elementHandler != null) { try { elementHandler.endElement(); @@ -432,7 +434,7 @@ public class IFParser implements IFConstants { documentHandler.getContext().setLanguage( XMLUtil.convertRFC3066ToLocale(xmllang)); } - Map foreignAttributes = getForeignAttributes(lastAttributes); + Map<QName, String> foreignAttributes = getForeignAttributes(lastAttributes); establishForeignAttributes(foreignAttributes); documentHandler.startPageSequence(id); resetForeignAttributes(); @@ -453,7 +455,7 @@ public class IFParser implements IFConstants { String pageMasterName = attributes.getValue("page-master-name"); int width = Integer.parseInt(attributes.getValue("width")); int height = Integer.parseInt(attributes.getValue("height")); - Map foreignAttributes = getForeignAttributes(lastAttributes); + Map<QName, String> foreignAttributes = getForeignAttributes(lastAttributes); establishForeignAttributes(foreignAttributes); documentHandler.startPage(index, name, pageMasterName, new Dimension(width, height)); @@ -486,6 +488,7 @@ public class IFParser implements IFConstants { public void endElement() throws IFException { painter = null; + documentHandler.getContext().setID(""); documentHandler.endPageContent(); } @@ -536,6 +539,16 @@ public class IFParser implements IFConstants { } + private class IDHandler extends AbstractElementHandler { + + @Override + public void startElement(Attributes attributes) throws IFException, SAXException { + String id = attributes.getValue("name"); + documentHandler.getContext().setID(id); + } + + } + private class FontHandler extends AbstractElementHandler { public void startElement(Attributes attributes) throws IFException { @@ -666,7 +679,7 @@ public class IFParser implements IFConstants { int y = Integer.parseInt(lastAttributes.getValue("y")); int width = Integer.parseInt(lastAttributes.getValue("width")); int height = Integer.parseInt(lastAttributes.getValue("height")); - Map foreignAttributes = getForeignAttributes(lastAttributes); + Map<QName, String> foreignAttributes = getForeignAttributes(lastAttributes); establishForeignAttributes(foreignAttributes); setStructurePointer(lastAttributes); if (foreignObject != null) { @@ -718,8 +731,8 @@ public class IFParser implements IFConstants { } } - private static Map getForeignAttributes(Attributes atts) { - Map foreignAttributes = null; + private static Map<QName, String> getForeignAttributes(Attributes atts) { + Map<QName, String> foreignAttributes = null; for (int i = 0, c = atts.getLength(); i < c; i++) { String ns = atts.getURI(i); if (ns.length() > 0) { @@ -727,7 +740,7 @@ public class IFParser implements IFConstants { continue; } if (foreignAttributes == null) { - foreignAttributes = new java.util.HashMap(); + foreignAttributes = new java.util.HashMap<QName, String>(); } QName qname = new QName(ns, atts.getQName(i)); foreignAttributes.put(qname, atts.getValue(i)); diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java index a578b524e..c0991a552 100644 --- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java +++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java @@ -37,7 +37,6 @@ import java.util.Stack; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; - import org.xml.sax.SAXException; import org.apache.batik.parser.AWTTransformProducer; @@ -75,7 +74,7 @@ import org.apache.fop.area.inline.InlineParent; import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.area.inline.Viewport; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.extensions.ExtensionAttachment; @@ -155,6 +154,8 @@ public class IFRenderer extends AbstractPathOrientedRenderer { private TextUtil textUtil = new TextUtil(); + private Stack<String> ids = new Stack<String>(); + /** * Main constructor */ @@ -790,18 +791,11 @@ public class IFRenderer extends AbstractPathOrientedRenderer { contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); concatenateTransformationMatrixMpt(contentRectTransform, false); - //Clipping - Rectangle clipRect = null; - if (bv.getClip()) { - clipRect = new Rectangle(0, 0, dim.width, dim.height); - //clipRect(0f, 0f, width, height); - } - //saveGraphicsState(); //Set up coordinate system for content rectangle AffineTransform contentTransform = ctm.toAffineTransform(); //concatenateTransformationMatrixMpt(contentTransform); - startViewport(contentTransform, clipRect); + startViewport(contentTransform, bv.getClipRectangle()); currentIPPosition = 0; currentBPPosition = 0; @@ -833,13 +827,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer { //Now adjust for border/padding currentBPPosition += borderPaddingBefore; - Rectangle2D clippingRect = null; - if (bv.getClip()) { - clippingRect = new Rectangle(currentIPPosition, currentBPPosition, - bv.getIPD(), bv.getBPD()); - } - - startVParea(ctm, clippingRect); + startVParea(ctm, bv.getClipRectangle()); currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); @@ -854,30 +842,25 @@ public class IFRenderer extends AbstractPathOrientedRenderer { } /** {@inheritDoc} */ - public void renderViewport(Viewport viewport) { + public void renderInlineViewport(InlineViewport viewport) { String ptr = (String) viewport.getTrait(Trait.PTR); establishStructurePointer(ptr); + pushdID(viewport); Dimension dim = new Dimension(viewport.getIPD(), viewport.getBPD()); viewportDimensionStack.push(dim); - super.renderViewport(viewport); + super.renderInlineViewport(viewport); viewportDimensionStack.pop(); resetStructurePointer(); + popID(viewport); } /** {@inheritDoc} */ - protected void startVParea(CTM ctm, Rectangle2D clippingRect) { + protected void startVParea(CTM ctm, Rectangle clippingRect) { if (log.isTraceEnabled()) { log.trace("startVParea() ctm=" + ctm + ", clippingRect=" + clippingRect); } AffineTransform at = new AffineTransform(ctm.toArray()); - Rectangle clipRect = null; - if (clippingRect != null) { - clipRect = new Rectangle( - (int)clippingRect.getMinX() - currentIPPosition, - (int)clippingRect.getMinY() - currentBPPosition, - (int)clippingRect.getWidth(), (int)clippingRect.getHeight()); - } - startViewport(at, clipRect); + startViewport(at, clippingRect); if (log.isTraceEnabled()) { log.trace("startVPArea: " + at + " --> " + graphicContext.getTransform()); } @@ -911,7 +894,9 @@ public class IFRenderer extends AbstractPathOrientedRenderer { /** {@inheritDoc} */ protected void renderInlineArea(InlineArea inlineArea) { saveInlinePosIfTargetable(inlineArea); + pushdID(inlineArea); super.renderInlineArea(inlineArea); + popID(inlineArea); } /** {@inheritDoc} */ @@ -975,7 +960,25 @@ public class IFRenderer extends AbstractPathOrientedRenderer { log.trace("renderBlock() " + block); } saveBlockPosIfTargetable(block); + pushdID(block); super.renderBlock(block); + popID(block); + } + + private void pushdID(Area area) { + String prodID = (String) area.getTrait(Trait.PROD_ID); + if (prodID != null) { + ids.push(prodID); + documentHandler.getContext().setID(prodID); + } + } + + private void popID(Area area) { + String prodID = (String) area.getTrait(Trait.PROD_ID); + if (prodID != null) { + ids.pop(); + documentHandler.getContext().setID(ids.empty() ? "" : ids.peek()); + } } private Typeface getTypeface(String fontName) { diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializer.java b/src/java/org/apache/fop/render/intermediate/IFSerializer.java index f8dd9b40a..4d307217b 100644 --- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java +++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java @@ -69,6 +69,8 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler /** Holds the intermediate format state */ private IFState state; + private String currentID = ""; + /** * Default constructor. */ @@ -306,6 +308,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler public void endPageContent() throws IFException { try { this.state = null; + currentID = ""; handler.endElement(EL_PAGE_CONTENT); } catch (SAXException e) { throw new IFException("SAX error in endPageContent()", e); @@ -417,6 +420,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler /** {@inheritDoc} */ public void drawImage(String uri, Rectangle rect) throws IFException { try { + addID(); AttributesImpl atts = new AttributesImpl(); addAttribute(atts, XLINK_HREF, uri); addAttribute(atts, "x", Integer.toString(rect.x)); @@ -445,6 +449,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler /** {@inheritDoc} */ public void drawImage(Document doc, Rectangle rect) throws IFException { try { + addID(); AttributesImpl atts = new AttributesImpl(); addAttribute(atts, "x", Integer.toString(rect.x)); addAttribute(atts, "y", Integer.toString(rect.y)); @@ -534,6 +539,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler public void drawLine(Point start, Point end, int width, Color color, RuleStyle style) throws IFException { try { + addID(); AttributesImpl atts = new AttributesImpl(); addAttribute(atts, "x1", Integer.toString(start.x)); addAttribute(atts, "y1", Integer.toString(start.y)); @@ -552,6 +558,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text) throws IFException { try { + addID(); AttributesImpl atts = new AttributesImpl(); addAttribute(atts, "x", Integer.toString(x)); addAttribute(atts, "y", Integer.toString(y)); @@ -680,7 +687,16 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler } } - // ---=== IFDocumentNavigationHandler ===--- + private void addID() throws SAXException { + String id = getContext().getID(); + if (!currentID.equals(id)) { + AttributesImpl atts = new AttributesImpl(); + addAttribute(atts, "name", id); + handler.startElement(EL_ID, atts); + handler.endElement(EL_ID); + currentID = id; + } + } private Map incompleteActions = new java.util.HashMap(); private List completeActions = new java.util.LinkedList(); @@ -718,7 +734,9 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler Iterator iter = tree.getBookmarks().iterator(); while (iter.hasNext()) { Bookmark b = (Bookmark)iter.next(); - serializeBookmark(b); + if (b.getAction() != null) { + serializeBookmark(b); + } } handler.endElement(DocumentNavigationExtensionConstants.BOOKMARK_TREE); } catch (SAXException e) { @@ -738,10 +756,11 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler Iterator iter = bookmark.getChildBookmarks().iterator(); while (iter.hasNext()) { Bookmark b = (Bookmark)iter.next(); - serializeBookmark(b); + if (b.getAction() != null) { + serializeBookmark(b); + } } handler.endElement(DocumentNavigationExtensionConstants.BOOKMARK); - } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index b61a9b7a9..5e3073ea6 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -445,7 +445,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } /** {@inheritDoc} */ - protected void startVParea(CTM ctm, Rectangle2D clippingRect) { + protected void startVParea(CTM ctm, Rectangle clippingRect) { saveGraphicsState(); diff --git a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java index 7cc9b7003..7a6e4e3d2 100644 --- a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java +++ b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java @@ -270,10 +270,10 @@ public class PDFContentGenerator { /** Indicates the end of a text object. */ protected void endTextObject() { if (textutil.isInTextObject()) { + textutil.endTextObject(); if (this.inMarkedContentSequence) { endMarkedContentSequence(); } - textutil.endTextObject(); } } diff --git a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java index ba9584597..4fd66109a 100644 --- a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java @@ -291,12 +291,12 @@ class PDFLogicalStructureHandler { void addLinkContentItem(PDFLink link, String structurePointer) { int structParent = getNextParentTreeKey(); link.setStructParent(structParent); - parentTree.getNums().put(structParent, link); PDFDictionary contentItem = new PDFDictionary(); contentItem.put("Type", OBJR); contentItem.put("Pg", this.currentPage); contentItem.put("Obj", link); PDFStructElem parent = (PDFStructElem) structTreeMap.get(structurePointer); + parentTree.getNums().put(structParent, parent); parent.addKid(contentItem); } diff --git a/src/java/org/apache/fop/render/txt/TXTRenderer.java b/src/java/org/apache/fop/render/txt/TXTRenderer.java index aa36ea28f..386f95838 100644 --- a/src/java/org/apache/fop/render/txt/TXTRenderer.java +++ b/src/java/org/apache/fop/render/txt/TXTRenderer.java @@ -21,6 +21,7 @@ package org.apache.fop.render.txt; import java.awt.Color; import java.awt.Point; +import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.IOException; @@ -560,7 +561,7 @@ public class TXTRenderer extends AbstractPathOrientedRenderer { /** * {@inheritDoc} */ - protected void startVParea(CTM ctm, Rectangle2D clippingRect) { + protected void startVParea(CTM ctm, Rectangle clippingRect) { currentState.push(ctm); } diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 0d500d5a8..a36e6542b 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -21,6 +21,7 @@ package org.apache.fop.render.xml; // Java import java.awt.Color; +import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.OutputStream; @@ -78,7 +79,7 @@ import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.Space; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.area.inline.Viewport; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; @@ -519,7 +520,7 @@ public class XMLRenderer extends AbstractXMLRenderer { addAreaAttributes(port); addTraitAttributes(port); addAttribute("rect", port.getViewArea()); - if (port.isClip()) { + if (port.hasClip()) { addAttribute("clipped", "true"); } startElement("regionViewport", atts); @@ -559,9 +560,8 @@ public class XMLRenderer extends AbstractXMLRenderer { } } - /** {@inheritDoc} */ @Override - protected void startVParea(CTM ctm, Rectangle2D clippingRect) { + protected void startVParea(CTM ctm, Rectangle clippingRect) { //only necessary for graphical output } @@ -680,7 +680,7 @@ public class XMLRenderer extends AbstractXMLRenderer { addAttribute("top-position", bvp.getYOffset()); } addAttribute("ctm", bvp.getCTM().toString()); - if (bvp.getClip()) { + if (bvp.hasClip()) { addAttribute("clipped", "true"); } } else { @@ -746,17 +746,17 @@ public class XMLRenderer extends AbstractXMLRenderer { * {@inheritDoc} */ @Override - protected void renderViewport(Viewport viewport) { + protected void renderInlineViewport(InlineViewport viewport) { atts.clear(); addAreaAttributes(viewport); addTraitAttributes(viewport); addAttribute("offset", viewport.getBlockProgressionOffset()); addAttribute("pos", viewport.getContentPosition()); - if (viewport.getClip()) { + if (viewport.hasClip()) { addAttribute("clip", "true"); } startElement("viewport", atts); - super.renderViewport(viewport); + super.renderInlineViewport(viewport); endElement("viewport"); } diff --git a/status.xml b/status.xml index 73e6f6c0d..9378e627f 100644 --- a/status.xml +++ b/status.xml @@ -59,6 +59,39 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> <release version="FOP Trunk" date="TBD"> + <action context="Renderers" dev="VH" type="add"> + Added id element to intermediate format to track the origin of content. + </action> + <action context="Renderers" dev="AD" type="fix" fixes-bug="50987" due-to="Matthias Reischenbacher"> + Bugzilla 50988: Fixed a NullPointerException in case a white-space fo:character was removed + due to white-space handling. + </action> + <action context="Renderers" dev="AD" type="fix" fixes-bug="50987" due-to="Martin Koegler"> + Bugzilla 50987: Fixed an issue in PDF output where a link was added to the parent tree + instead of the related structure element. + </action> + <action context="Renderers" dev="AD" type="fix" fixes-bug="50986" due-to="Martin Koegler"> + Bugzilla 50986: Fixed an issue where invalid PDF page content was generated due to + incorrect ET/EMC sequences. + </action> + <action context="Code" dev="AD" type="fix" fixes-bug="50593"> + Fixed regression introduced by Bugzilla 50593: bookmarks pointing to a non-existing + internal destination should just trigger a warning. + </action> + <action context="Layout" dev="AD" type="fix" fixes-bug="50965" due-to="Martin Koegler"> + Bugzilla 50965: Fixed a regression in BlockContainerLayoutManager where margins were + no longer reset after forced breaks. + </action> + <action context="Layout" dev="VH" type="fix" fixex-bug="50763"> + Implemented non-standard behavior for basic-link areas, such that they take into account the + heights of their descendants areas. + </action> + <action context="Layout" dev="VH" type="fix"> + Bugfix: keep-together does not apply to fo:table-cell. + </action> + <action context="Layout" dev="VH" type="fix"> + Bugfix: keep-together on a table containing row-spanning cells was not honored. + </action> <action context="Layout" dev="VH" type="fix" fixes-bug="50196" due-to="Matthias Reischenbacher"> Bugzilla #50196: padding-start ignored when table-header/footer is repeated. </action> diff --git a/test/fotree/testcases/text-decoration_invalid_bug51032.fo b/test/fotree/testcases/text-decoration_invalid_bug51032.fo new file mode 100644 index 000000000..2a03bb62f --- /dev/null +++ b/test/fotree/testcases/text-decoration_invalid_bug51032.fo @@ -0,0 +1,32 @@ +<?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$ --> +<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="simple" page-height="5in" page-width="3in"> + <fo:region-body /> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="simple"> + <fo:flow flow-name="xsl-region-body"> + <fo:block> + <fo:inline text-decoration="italic">bap</fo:inline> + </fo:block> + </fo:flow> + </fo:page-sequence> +</fo:root> diff --git a/test/intermediate/block-container.xml b/test/intermediate/block-container.xml new file mode 100644 index 000000000..5749de28f --- /dev/null +++ b/test/intermediate/block-container.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" standalone="no"?> +<!-- + 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. +--> +<testcase> + <info> + <p> + This test checks that IDs coming from a block-container properly appear in the IF output. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="320pt" page-width="420pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body" text-align="justify"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. Vivamus porttitor sollicitudin tortor eu vulputate.</fo:block> + <fo:block-container id="block-container" space-before="10pt" color="purple" + font-family="serif"><fo:block>In vel libero libero, a semper est. Vivamus dapibus ante id + lorem mattis eget mattis urna sodales. Vestibulum nec dui urna, in porta + mi.</fo:block></fo:block-container> + <fo:block space-before="10pt">Proin varius egestas erat. Proin ante eros, consequat eget + semper a, molestie non arcu. Praesent hendrerit dolor vel leo luctus dapibus.</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"> + + <eval expected="8" xpath="count(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + + <eval expected="block-container" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][2]/@name"/> + </if-checks> +</testcase> diff --git a/test/intermediate/block-container_nested.xml b/test/intermediate/block-container_nested.xml new file mode 100644 index 000000000..40f9903ff --- /dev/null +++ b/test/intermediate/block-container_nested.xml @@ -0,0 +1,148 @@ +<?xml version="1.0" standalone="no"?> +<!-- + 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. +--> +<testcase> + <info> + <p> + This test checks that IDs coming from a block-container properly appear in the IF output. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="320pt" page-width="420pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. Vivamus porttitor sollicitudin tortor eu vulputate.</fo:block> + <fo:block-container space-before="10pt" id="block-container_outer_1" color="purple"> + <fo:block>In vel libero libero, a semper est. Vivamus dapibus ante id lorem mattis eget + mattis urna sodales. + <fo:block-container id="block-container_inner_1" color="blue" start-indent="2em"> + <fo:block start-indent="0">Vestibulum nec dui urna, in porta mi. Proin varius egestas + erat. Donec pharetra iaculis dolor, ut rutrum nunc facilisis + at.</fo:block> + </fo:block-container> + Proin ante eros, consequat eget semper a, molestie non arcu. Praesent hendrerit dolor vel + leo luctus dapibus.</fo:block> + </fo:block-container> + <fo:block space-before="10pt">Nullam quam nisl, iaculis ut fermentum et, vestibulum id elit. + Suspendisse fermentum fermentum ullamcorper.</fo:block> + <fo:block-container space-before="10pt" color="purple" id="block-container_1"> + <fo:block>Sed ultrices posuere posuere. Praesent vitae ligula odio.</fo:block> + </fo:block-container> + </fo:flow> + </fo:page-sequence> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. Vivamus porttitor sollicitudin tortor eu vulputate.</fo:block> + <fo:block-container space-before="10pt" id="block-container_outer_2" color="purple"> + <fo:block>In vel libero libero, a semper est. Vivamus dapibus ante id lorem mattis eget + mattis urna sodales. + <fo:block color="black" start-indent="2em">Mauris tincidunt, risus eget vulputate elementum, + turpis lorem aliquet purus, eu sagittis neque sapien vel lectus. + <fo:block-container id="block-container_inner_2" color="blue"> + <fo:block>Vestibulum nec dui urna, in porta mi. Proin varius egestas erat. Donec + pharetra iaculis dolor, ut rutrum nunc facilisis at.</fo:block> + </fo:block-container> + Proin ante eros, consequat eget semper a, molestie non arcu. Praesent hendrerit dolor vel + leo luctus dapibus.</fo:block> + Vivamus ut sollicitudin metus. Curabitur sit amet aliquam + enim.</fo:block> + </fo:block-container> + <fo:block space-before="10pt">Nullam quam nisl, iaculis ut fermentum et, vestibulum id elit. + Suspendisse fermentum fermentum ullamcorper.</fo:block> + <fo:block-container space-before="10pt" color="purple" id="block-container_2"> + <fo:block>Vivamus tellus libero, porttitor a lacinia a, tempor eu dui. Pellentesque + fermentum odio tempor lorem interdum pharetra.</fo:block> + </fo:block-container> + <fo:block space-before="10pt">Donec auctor venenatis convallis.</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"> + + <!-- Page 1 --> + <eval expected="16" xpath="count(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][9])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][10])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][11])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][12])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][13])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][14])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][15])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][16])"/> + + <eval expected="block-container_outer_1" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="block-container_inner_1" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][2]/@name"/> + <eval expected="block-container_outer_1" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][3]/@name"/> + <eval expected="" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][4]/@name"/> + <eval expected="block-container_1" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][5]/@name"/> + + <!-- Page 2 --> + <eval expected="22" xpath="count(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][9])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][10])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][11])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][12])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][13])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][14])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][15])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][16])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][17])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][18])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][19])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][20])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][21])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][22])"/> + + <eval expected="block-container_outer_2" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="block-container_inner_2" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][2]/@name"/> + <eval expected="block-container_outer_2" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][3]/@name"/> + <eval expected="" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][4]/@name"/> + <eval expected="block-container_2" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][5]/@name"/> + <eval expected="" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][6]/@name"/> + + </if-checks> +</testcase> diff --git a/test/intermediate/block.xml b/test/intermediate/block.xml new file mode 100644 index 000000000..1801bb7c6 --- /dev/null +++ b/test/intermediate/block.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" standalone="no"?> +<!-- + 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. +--> +<testcase> + <info> + <p> + This test checks that IDs coming from a block properly appear in the IF output. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="320pt" page-width="420pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body" text-align="justify"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. Vivamus porttitor sollicitudin tortor eu vulputate.</fo:block> + <fo:block id="block" space-before="10pt" color="purple" font-family="serif">In vel libero + libero, a semper est. Vivamus dapibus ante id lorem mattis eget mattis urna sodales. + Vestibulum nec dui urna, in porta mi.</fo:block> + <fo:block space-before="10pt">Proin varius egestas erat. Proin ante eros, consequat eget + semper a, molestie non arcu. Praesent hendrerit dolor vel leo luctus dapibus.</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"> + + <eval expected="8" xpath="count(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + + <eval expected="block" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][2]/@name"/> + </if-checks> +</testcase> diff --git a/test/intermediate/block_nested.xml b/test/intermediate/block_nested.xml new file mode 100644 index 000000000..5ec8af00f --- /dev/null +++ b/test/intermediate/block_nested.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" standalone="no"?> +<!-- + 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. +--> +<testcase> + <info> + <p> + This test checks that IDs coming from a block properly appear in the IF output. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="320pt" page-width="420pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. Vivamus porttitor sollicitudin tortor eu vulputate.</fo:block> + <fo:block space-before="10pt" id="outer-block_1" color="purple">In vel libero libero, a semper + est. Vivamus dapibus ante id lorem mattis eget mattis urna sodales. + <fo:block id="inner-block_1" color="blue" start-indent="2em">Vestibulum nec dui urna, in + porta mi. Proin varius egestas erat. Donec pharetra iaculis dolor, ut rutrum nunc + facilisis at.</fo:block> + Proin ante eros, consequat eget semper a, molestie non arcu. Praesent hendrerit dolor vel + leo luctus dapibus.</fo:block> + <fo:block space-before="10pt">Nullam quam nisl, iaculis ut fermentum et, vestibulum id elit. + Suspendisse fermentum fermentum ullamcorper.</fo:block> + <fo:block space-before="10pt" color="purple" id="block_1">Sed ultrices posuere posuere. + Praesent vitae ligula odio.</fo:block> + </fo:flow> + </fo:page-sequence> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. Vivamus porttitor sollicitudin tortor eu vulputate.</fo:block> + <fo:block space-before="10pt" id="outer-block_2" color="purple">In vel libero libero, a semper + est. Vivamus dapibus ante id lorem mattis eget mattis urna sodales. + <fo:block color="black" start-indent="2em">Mauris tincidunt, risus eget vulputate elementum, + turpis lorem aliquet purus, eu sagittis neque sapien vel lectus. + <fo:block id="inner-block_2" color="blue" start-indent="4em">Vestibulum nec dui urna, in + porta mi. Proin varius egestas erat. Donec pharetra iaculis dolor, ut rutrum nunc + facilisis at.</fo:block> + Proin ante eros, consequat eget semper a, molestie non arcu. Praesent hendrerit dolor vel + leo luctus dapibus.</fo:block> + Vivamus ut sollicitudin metus. Curabitur sit amet aliquam enim.</fo:block> + <fo:block space-before="10pt">Nullam quam nisl, iaculis ut fermentum et, vestibulum id elit. + Suspendisse fermentum fermentum ullamcorper.</fo:block> + <fo:block space-before="10pt" color="purple" id="block_2">Vivamus tellus libero, porttitor a + lacinia a, tempor eu dui. Pellentesque fermentum odio tempor lorem interdum + pharetra.</fo:block> + <fo:block space-before="10pt">Donec auctor venenatis convallis.</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"> + + <!-- Page 1 --> + <eval expected="16" xpath="count(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][9])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][10])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][11])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][12])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][13])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][14])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][15])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][16])"/> + + <eval expected="outer-block_1" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="inner-block_1" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][2]/@name"/> + <eval expected="outer-block_1" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][3]/@name"/> + <eval expected="" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][4]/@name"/> + <eval expected="block_1" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][5]/@name"/> + + <!-- Page 2 --> + <eval expected="22" xpath="count(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][9])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][10])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][11])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][12])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][13])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][14])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][15])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][16])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][17])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][18])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][19])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][20])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][21])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][22])"/> + + <eval expected="outer-block_2" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="inner-block_2" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][2]/@name"/> + <eval expected="outer-block_2" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][3]/@name"/> + <eval expected="" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][4]/@name"/> + <eval expected="block_2" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][5]/@name"/> + <eval expected="" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][6]/@name"/> + + </if-checks> +</testcase> diff --git a/test/intermediate/block_span_pages.xml b/test/intermediate/block_span_pages.xml new file mode 100644 index 000000000..43aff0ac4 --- /dev/null +++ b/test/intermediate/block_span_pages.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" standalone="no"?> +<!-- + 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. +--> +<testcase> + <info> + <p> + This test checks that IDs coming from a block that spans over different pages properly appear + in the IF output. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="120pt" page-width="270pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor.</fo:block> + <fo:block space-before="60pt" id="block" color="purple">In vel libero libero, a + semper est. Vivamus dapibus ante id lorem mattis eget mattis urna sodales. Proin ante + eros, consequat eget semper a, molestie non arcu. Praesent hendrerit dolor vel leo + luctus dapibus.</fo:block> + <fo:block space-before="10pt">Nullam quam nisl, iaculis ut fermentum et, vestibulum id elit. + Suspendisse fermentum fermentum ullamcorper.</fo:block> + </fo:flow> + </fo:page-sequence> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor.</fo:block> + <fo:block space-before="40pt" id="outer-block" color="purple">In vel libero libero, a semper + est. Vivamus dapibus ante id lorem mattis eget mattis urna sodales. + <fo:block id="inner-block" color="blue" start-indent="2em">Vestibulum nec dui urna, in + porta mi. Proin varius egestas erat. Donec pharetra iaculis dolor, ut rutrum nunc + facilisis at. Sed ultrices posuere posuere. Praesent vitae ligula odio. Vivamus + porttitor sollicitudin tortor eu vulputate.</fo:block> + Proin ante eros, consequat eget semper a, molestie non arcu. Praesent hendrerit dolor vel + leo luctus dapibus.</fo:block> + <fo:block space-before="10pt">Nullam quam nisl, iaculis ut fermentum et, vestibulum id elit. + Suspendisse fermentum fermentum ullamcorper.</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"> + + <!-- Page-sequence 1 Page 1 --> + <eval expected="5" xpath="count(//if:page-sequence[1]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence[1]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + + <eval expected="block" xpath="//if:page-sequence[1]/if:page[1]/descendant::*[local-name() = 'id'][1]/@name"/> + + <!-- Page-sequence 1 Page 2 --> + <eval expected="6" xpath="count(//if:page-sequence[1]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="id" xpath="local-name(//if:page-sequence[1]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + + <eval expected="block" xpath="//if:page-sequence[1]/if:page[2]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="" xpath="//if:page-sequence[1]/if:page[2]/descendant::*[local-name() = 'id'][2]/@name"/> + + + <!-- Page-sequence 2 Page 1 --> + <eval expected="8" xpath="count(//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + + <eval expected="outer-block" xpath="//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="inner-block" xpath="//if:page-sequence[2]/if:page[1]/descendant::*[local-name() = 'id'][2]/@name"/> + + <!-- Page-sequence 2 Page 2 --> + <eval expected="9" xpath="count(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="id" xpath="local-name(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'text' or local-name() = 'id'][9])"/> + + <eval expected="inner-block" xpath="//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="outer-block" xpath="//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'id'][2]/@name"/> + <eval expected="" xpath="//if:page-sequence[2]/if:page[2]/descendant::*[local-name() = 'id'][3]/@name"/> + + </if-checks> +</testcase> diff --git a/test/intermediate/images.xml b/test/intermediate/images.xml new file mode 100644 index 000000000..08ca83f5c --- /dev/null +++ b/test/intermediate/images.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" standalone="no"?> +<!-- + 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. +--> +<testcase> + <info> + <p> + This test checks that IDs coming from images properly appear in the IF output. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="320pt" page-width="420pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body" text-align="justify"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. <fo:external-graphic src="../resources/images/fop-logo-color-24bit.png" + id="external-graphic"/>Vivamus porttitor sollicitudin tortor eu vulputate. In vel + libero libero, a semper est.</fo:block> + </fo:flow> + </fo:page-sequence> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body" text-align="justify"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. <fo:instream-foreign-object id="instream-foreign-object" width="120pt" + display-align="center" content-width="scale-to-fit"> + <svg xmlns="http://www.w3.org/2000/svg" width="300" height="286.6"> + <g style="fill-opacity:0.7; stroke:black; stroke-width:3" + transform="translate(0, 286.6) scale(1, -1) translate(100, 100)"> + <circle cx="50" cy="86.6" r="80" style="fill:red;"/> + <circle cx="0" cy="0" r="80" style="fill:green;"/> + <circle cx="100" cy="0" r="80" style="fill:blue;"/> + </g> + </svg> + </fo:instream-foreign-object> Vivamus porttitor sollicitudin tortor eu vulputate. In vel + libero libero, a semper est.</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"> + + <!-- Page 1 --> + <eval expected="7" xpath="count(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][3])"/> + <eval expected="image" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][4])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][5])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[1]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][7])"/> + + <eval expected="external-graphic" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="" xpath="//if:page-sequence[1]/descendant::*[local-name() = 'id'][2]/@name"/> + + <!-- Page 2 --> + <eval expected="7" xpath="count(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][3])"/> + <eval expected="image" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][4])"/> + <eval expected="id" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][5])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence[2]/descendant::*[local-name() = 'text' or local-name() = 'image' or local-name() = 'id'][7])"/> + + <eval expected="instream-foreign-object" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="" xpath="//if:page-sequence[2]/descendant::*[local-name() = 'id'][2]/@name"/> + + </if-checks> +</testcase> diff --git a/test/intermediate/inlines.xml b/test/intermediate/inlines.xml new file mode 100644 index 000000000..eb588992a --- /dev/null +++ b/test/intermediate/inlines.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" standalone="no"?> +<!-- + 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. +--> +<testcase> + <info> + <p> + This test checks that IDs coming from various inline elements properly appear in the IF + output. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="320pt" page-width="420pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + + <fo:page-sequence master-reference="page" id="page-sequence"> + <fo:flow flow-name="xsl-region-body" text-align="justify"> + <fo:block font-family="sans-serif">Lorem ipsum dolor sit amet, <fo:character id="character" + font-size="150%" font-weight="bold" color="purple" character="C"/>onsectetur adipiscing + elit. <fo:inline id="inline" color="purple" font-family="serif">Fusce rutrum leo a diam + bibendum auctor.</fo:inline> Vivamus porttitor sollicitudin tortor eu vulputate. In vel + libero libero, a semper est. Vivamus<fo:leader id="leader" leader-length="50pt" + leader-pattern="rule" color="purple"/> dapibus ante id lorem mattis eget mattis urna + sodales. This is page number <fo:page-number id="page-number" color="purple"/>. Vestibulum + nec dui urna, in porta mi. The fo:character object is on page <fo:page-number-citation + id="page-number-citation" ref-id="character" color="purple"/>. Proin varius egestas erat. + Proin ante eros, consequat eget semper a, molestie non arcu. The last page of this document + is page <fo:page-number-citation-last id="page-number-citation-last" ref-id="page-sequence" + color="purple"/>. Praesent hendrerit dolor vel leo luctus dapibus.</fo:block> + + <fo:block break-before="page">Lorem ipsum dolor sit amet, consectetur adipiscing + elit.</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"> + + <eval expected="32" xpath="count(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][1])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][2])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][3])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][5])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][7])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][8])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][9])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][10])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][11])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][12])"/> + <eval expected="line" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][13])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][14])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][15])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][16])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][17])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][18])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][19])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][20])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][21])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][22])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][23])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][24])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][25])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][26])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][27])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][28])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][29])"/> + <eval expected="id" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][30])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][31])"/> + <eval expected="text" xpath="local-name(//if:page[1]/descendant::*[local-name() = 'text' or local-name() = 'line' or local-name() = 'id'][32])"/> + + <eval expected="character" xpath="//if:page[1]/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="" xpath="//if:page[1]/descendant::*[local-name() = 'id'][2]/@name"/> + <eval expected="inline" xpath="//if:page[1]/descendant::*[local-name() = 'id'][3]/@name"/> + <eval expected="" xpath="//if:page[1]/descendant::*[local-name() = 'id'][4]/@name"/> + <eval expected="leader" xpath="//if:page[1]/descendant::*[local-name() = 'id'][5]/@name"/> + <eval expected="" xpath="//if:page[1]/descendant::*[local-name() = 'id'][6]/@name"/> + <eval expected="page-number" xpath="//if:page[1]/descendant::*[local-name() = 'id'][7]/@name"/> + <eval expected="" xpath="//if:page[1]/descendant::*[local-name() = 'id'][8]/@name"/> + <eval expected="page-number-citation" xpath="//if:page[1]/descendant::*[local-name() = 'id'][9]/@name"/> + <eval expected="" xpath="//if:page[1]/descendant::*[local-name() = 'id'][10]/@name"/> + <eval expected="page-number-citation-last" xpath="//if:page[1]/descendant::*[local-name() = 'id'][11]/@name"/> + <eval expected="" xpath="//if:page[1]/descendant::*[local-name() = 'id'][12]/@name"/> + + </if-checks> +</testcase> diff --git a/test/intermediate/list.xml b/test/intermediate/list.xml new file mode 100644 index 000000000..81283ce5e --- /dev/null +++ b/test/intermediate/list.xml @@ -0,0 +1,112 @@ +<?xml version="1.0" standalone="no"?> +<!-- + 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. +--> +<testcase> + <info> + <p> + This test checks that IDs coming from the various elements of a list properly appear in the IF + output. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="320pt" page-width="420pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body" text-align="justify"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. Vivamus porttitor sollicitudin tortor eu vulputate.</fo:block> + <fo:list-block provisional-distance-between-starts="10pt" provisional-label-separation="5pt" + id="list-block" space-before="10pt"> + <fo:list-item id="list-item_1"> + <fo:list-item-label end-indent="label-end()" id="list-item-label"> + <fo:block>•</fo:block> + </fo:list-item-label> + <fo:list-item-body start-indent="body-start()" id="list-item-body"> + <fo:block>Item 1</fo:block> + <fo:block>id="list-item-body"</fo:block> + </fo:list-item-body> + </fo:list-item> + <fo:list-item id="list-item_2" space-before="5pt"> + <fo:list-item-label end-indent="label-end()"> + <fo:block>•</fo:block> + </fo:list-item-label> + <fo:list-item-body start-indent="body-start()"> + <fo:block>Item 2</fo:block> + <fo:block>id="list-item_2"</fo:block> + </fo:list-item-body> + </fo:list-item> + <fo:list-item space-before="5pt"> + <fo:list-item-label end-indent="label-end()"> + <fo:block>•</fo:block> + </fo:list-item-label> + <fo:list-item-body start-indent="body-start()"> + <fo:block>Item 3</fo:block> + <fo:block>id="list-block"</fo:block> + </fo:list-item-body> + </fo:list-item> + </fo:list-block> + <fo:block id="block" space-before="10pt" color="purple" font-family="serif">In vel libero + libero, a semper est. Vivamus dapibus ante id lorem mattis eget mattis urna sodales. + Vestibulum nec dui urna, in porta mi.</fo:block> + <fo:block space-before="10pt">Proin varius egestas erat. Proin ante eros, consequat eget + semper a, molestie non arcu. Praesent hendrerit dolor vel leo luctus dapibus.</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"> + + <eval expected="21" xpath="count(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][9])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][10])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][11])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][12])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][13])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][14])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][15])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][16])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][17])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][18])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][19])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][20])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][21])"/> + + <eval expected="list-item-label" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="list-item-body" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][2]/@name"/> + <eval expected="list-item_2" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][3]/@name"/> + <eval expected="list-block" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][4]/@name"/> + <eval expected="block" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][5]/@name"/> + <eval expected="" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][6]/@name"/> + + </if-checks> +</testcase> diff --git a/test/intermediate/table.xml b/test/intermediate/table.xml new file mode 100644 index 000000000..4e3d10cbf --- /dev/null +++ b/test/intermediate/table.xml @@ -0,0 +1,146 @@ +<?xml version="1.0" standalone="no"?> +<!-- + 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. +--> +<testcase> + <info> + <p> + This test checks that IDs coming from the various elements of a table properly appear in the IF output. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="320pt" page-width="420pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body" text-align="justify"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce rutrum leo a diam + bibendum auctor. Vivamus porttitor sollicitudin tortor eu vulputate.</fo:block> + <fo:table id="table" + table-layout="fixed" + border-collapse="separate" + space-before="10pt" + start-indent="10%" + width="80%" + border="4pt solid purple" + border-separation="2pt" + padding="1pt" + font-size="10pt"> + <fo:table-header id="table-header" start-indent="0"> + <fo:table-cell border="2pt solid black" padding="2pt" id="table-cell_header_1.1"> + <fo:block>Header 1.1</fo:block> + <fo:block>id="table-cell_header_1.1"</fo:block> + </fo:table-cell> + <fo:table-cell border="2pt solid black" padding="2pt"> + <fo:block>Header 1.2 id="table-header"</fo:block> + </fo:table-cell> + </fo:table-header> + <fo:table-body id="table-body_1" start-indent="0"> + <fo:table-row id="table-row_1"> + <fo:table-cell border="1pt solid black" padding="2pt" id="table-cell_1.1"> + <fo:block>Cell 1.1 id="table-cell_1.1"</fo:block> + </fo:table-cell> + <fo:table-cell border="1pt solid black" padding="2pt"> + <fo:block>Cell 1.2 id="table-row_1"</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell border="1pt solid black" padding="2pt"> + <fo:block>Cell 2.1 id="table-body_1"</fo:block> + </fo:table-cell> + <fo:table-cell border="1pt solid black" padding="2pt"> + <fo:block>Cell 2.2 id="table-body_1"</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + <fo:table-body start-indent="0"> + <fo:table-row id="table-row_3"> + <fo:table-cell border="1pt solid black" padding="2pt" id="table-cell_3.1"> + <fo:block>Cell 3.1 id="table-cell_3.1"</fo:block> + </fo:table-cell> + <fo:table-cell border="1pt solid black" padding="2pt"> + <fo:block>Cell 3.2 id="table-row_3"</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell border="1pt solid black" padding="2pt"> + <fo:block id="block">Cell 4.1 id="block"</fo:block> + </fo:table-cell> + <fo:table-cell border="1pt solid black" padding="2pt"> + <fo:block>Cell 4.2 id="table"</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + <fo:block space-before="10pt">Proin varius egestas erat. Proin ante eros, consequat eget + semper a, molestie non arcu. Praesent hendrerit dolor vel leo luctus dapibus.</fo:block> + <fo:block space-before="10pt" color="purple" id="block_outer">Mauris ac erat est, sit amet + dignissim elit. Ut pulvinar diam ut lorem pellentesque tempus.</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"> + + <eval expected="27" xpath="count(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'])"/> + + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][1])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][2])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][3])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][4])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][5])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][6])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][7])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][8])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][9])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][10])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][11])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][12])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][13])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][14])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][15])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][16])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][17])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][18])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][19])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][20])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][21])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][22])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][23])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][24])"/> + <eval expected="id" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][25])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][26])"/> + <eval expected="text" xpath="local-name(//if:page-sequence/descendant::*[local-name() = 'text' or local-name() = 'id'][27])"/> + + <eval expected="table-cell_header_1.1" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][1]/@name"/> + <eval expected="table" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][2]/@name"/> + <eval expected="table-cell_1.1" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][3]/@name"/> + <eval expected="table" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][4]/@name"/> + <eval expected="table-cell_3.1" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][5]/@name"/> + <eval expected="table" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][6]/@name"/> + <eval expected="block" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][7]/@name"/> + <eval expected="table" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][8]/@name"/> + <eval expected="" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][9]/@name"/> + <eval expected="block_outer" xpath="//if:page-sequence/descendant::*[local-name() = 'id'][10]/@name"/> + + </if-checks> +</testcase> diff --git a/test/java/org/apache/fop/StandardTestSuite.java b/test/java/org/apache/fop/StandardTestSuite.java index 61a9bdc5e..480ab8bd0 100644 --- a/test/java/org/apache/fop/StandardTestSuite.java +++ b/test/java/org/apache/fop/StandardTestSuite.java @@ -22,6 +22,7 @@ package org.apache.fop; import junit.framework.Test; import junit.framework.TestSuite; +import org.apache.fop.area.ViewportTestSuite; import org.apache.fop.fonts.DejaVuLGCSerifTest; import org.apache.fop.image.loader.batik.ImageLoaderTestCase; import org.apache.fop.image.loader.batik.ImagePreloaderTestCase; @@ -65,6 +66,7 @@ public class StandardTestSuite { suite.addTest(new TestSuite(PageBoundariesTest.class)); suite.addTest(new TestSuite(PageScaleTest.class)); suite.addTest(new TestSuite(MinOptMaxTest.class)); + suite.addTest(ViewportTestSuite.suite()); //$JUnit-END$ return suite; } diff --git a/test/java/org/apache/fop/area/BlockViewportTestCase.java b/test/java/org/apache/fop/area/BlockViewportTestCase.java new file mode 100644 index 000000000..a2a897322 --- /dev/null +++ b/test/java/org/apache/fop/area/BlockViewportTestCase.java @@ -0,0 +1,44 @@ +/* + * 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.area; + + +/** + * Tests the {@linkplain BlockViewport} class. + */ +public class BlockViewportTestCase extends ViewportTestCase { + + public void testNonClip() throws Exception { + BlockViewport bv = new BlockViewport(); + bv.setIPD(100); + bv.setBPD(50); + checkNonClip(bv); + } + + public void testClip() throws Exception { + BlockViewport bv = new BlockViewport(); + int ipd = 100; + int bpd = 50; + bv.setIPD(ipd); + bv.setBPD(bpd); + bv.setClip(true); + checkClip(bv, ipd, bpd); + } +} diff --git a/test/java/org/apache/fop/area/RegionViewportTestCase.java b/test/java/org/apache/fop/area/RegionViewportTestCase.java new file mode 100644 index 000000000..f55d08b66 --- /dev/null +++ b/test/java/org/apache/fop/area/RegionViewportTestCase.java @@ -0,0 +1,50 @@ +/* + * 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.area; + +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; + +/** + * Tests the {@linkplain RegionViewport} class. + */ +public class RegionViewportTestCase extends ViewportTestCase { + + private RegionViewport createRegionViewport(int x, int y, int ipd, int bpd) { + Rectangle2D v = new Rectangle(x, y, ipd, bpd); + RegionViewport viewport = new RegionViewport(v); + viewport.setIPD(ipd); + viewport.setBPD(bpd); + return viewport; + } + + public void testNonClip() throws Exception { + RegionViewport viewport = createRegionViewport(10, 10, 100, 20); + checkNonClip(viewport); + } + + public void testClip() throws Exception { + int ipd = 150; + int bpd = 20; + RegionViewport viewport = createRegionViewport(10, 10, ipd, bpd); + viewport.setClip(true); + checkClip(viewport, ipd, bpd); + } +} diff --git a/test/java/org/apache/fop/area/ViewportTestCase.java b/test/java/org/apache/fop/area/ViewportTestCase.java new file mode 100644 index 000000000..335ca2f8d --- /dev/null +++ b/test/java/org/apache/fop/area/ViewportTestCase.java @@ -0,0 +1,40 @@ +/* + * 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.area; + +import java.awt.Rectangle; + +import junit.framework.TestCase; + +/** + * Tests implementations of the {@linkplain Viewport} interface. + */ +public abstract class ViewportTestCase extends TestCase { + + protected void checkNonClip(Viewport v) throws Exception { + assertFalse(v.hasClip()); + assertNull(v.getClipRectangle()); + } + + protected void checkClip(Viewport v, int expectedWidth, int expectedHeight) throws Exception { + assertTrue(v.hasClip()); + assertEquals(new Rectangle(0, 0, expectedWidth, expectedHeight), v.getClipRectangle()); + } +} diff --git a/test/java/org/apache/fop/area/ViewportTestSuite.java b/test/java/org/apache/fop/area/ViewportTestSuite.java new file mode 100644 index 000000000..babbe8910 --- /dev/null +++ b/test/java/org/apache/fop/area/ViewportTestSuite.java @@ -0,0 +1,47 @@ +/* + * 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.area; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.apache.fop.area.inline.InlineViewportTestCase; + +/** + * A suite of all the tests relating to the {@linkplain Viewport} interface. + */ +public final class ViewportTestSuite { + + private ViewportTestSuite() { } + + /** + * Returns the suite of {@linkplain Viewport} implementation tests. + * + * @return the tests + */ + public static Test suite() { + TestSuite suite = new TestSuite("Tests for viewport-areas"); + suite.addTestSuite(RegionViewportTestCase.class); + suite.addTestSuite(BlockViewportTestCase.class); + suite.addTestSuite(InlineViewportTestCase.class); + return suite; + } + +} diff --git a/test/java/org/apache/fop/area/inline/InlineViewportTestCase.java b/test/java/org/apache/fop/area/inline/InlineViewportTestCase.java new file mode 100644 index 000000000..811158273 --- /dev/null +++ b/test/java/org/apache/fop/area/inline/InlineViewportTestCase.java @@ -0,0 +1,46 @@ +/* + * 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.area.inline; + +import org.apache.fop.area.ViewportTestCase; + +/** + * Tests the {@linkplain InlineViewport} class. + */ +public class InlineViewportTestCase extends ViewportTestCase { + + public void testNonClip() throws Exception { + InlineViewport v = new InlineViewport(null); + v.setIPD(50); + v.setBPD(25); + checkNonClip(v); + } + + public void testClip() throws Exception { + InlineViewport v = new InlineViewport(null); + int ipd = 50; + int bpd = 25; + v.setIPD(ipd); + v.setBPD(bpd); + v.setClip(true); + checkClip(v, ipd, bpd); + } + +} diff --git a/test/java/org/apache/fop/check/Check.java b/test/java/org/apache/fop/check/Check.java new file mode 100644 index 000000000..ffc7e3cbc --- /dev/null +++ b/test/java/org/apache/fop/check/Check.java @@ -0,0 +1,27 @@ +/* + * 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.check; + +/** + * A marker interface to identify checks in XML test cases. + */ +public interface Check { + +} diff --git a/test/java/org/apache/fop/check/ChecksFactory.java b/test/java/org/apache/fop/check/ChecksFactory.java new file mode 100644 index 000000000..a493c09f2 --- /dev/null +++ b/test/java/org/apache/fop/check/ChecksFactory.java @@ -0,0 +1,97 @@ +/* + * 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.check; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * A factory class for creating checks that belong to a same family. + * @param <C> a family of checks + */ +public abstract class ChecksFactory<C extends Check> { + + /** + * A factory to create a particular kind of check. + */ + protected static interface CheckFactory<C> { + + /** + * Creates a {@link Check} instance from the given XML element. + * + * @param element an element representing a check + * @return the corresponding check + */ + C createCheck(Element element); + } + + private final Map<String, CheckFactory<C>> checkFactories + = new HashMap<String, CheckFactory<C>>(); + + /** Default constructor. */ + protected ChecksFactory() { } + + /** + * Registers a factory for a new kind of check. + * + * @param elementName the name of the element under which the check is identified in + * the XML test case + * @param factory the corresponding factory + */ + protected void registerCheckFactory(String elementName, CheckFactory<C> factory) { + checkFactories.put(elementName, factory); + } + + /** + * Creates a new {@link Check} instance corresponding to the given element. + * + * @param element an element in the XML test case that identifies a particular check + * @return the corresponding check + * @throws IllegalArgumentException if not check corresponding to the given element + * has been found + */ + public final C createCheck(Element element) { + String name = element.getTagName(); + CheckFactory<C> factory = checkFactories.get(name); + if (factory == null) { + throw new IllegalArgumentException("No check class found for " + name); + } else { + return factory.createCheck(element); + } + } + + public final List<C> createCheckList(Element container) { + List<C> checks = new ArrayList<C>(); + NodeList nodes = container.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + if (node instanceof Element) { + checks.add(createCheck((Element) node)); + } + } + return checks; + } +} diff --git a/test/java/org/apache/fop/check/package-info.java b/test/java/org/apache/fop/check/package-info.java new file mode 100644 index 000000000..5785f7a4b --- /dev/null +++ b/test/java/org/apache/fop/check/package-info.java @@ -0,0 +1,25 @@ +/* + * 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$ */ + +/** + * A framework for creating checks from elements stored in an XML test case. The test case + * typically contains the XML document under test, along with a series of checks expressed + * as XML elements. + */ +package org.apache.fop.check; diff --git a/test/java/org/apache/fop/intermediate/AbstractIFTestCase.java b/test/java/org/apache/fop/intermediate/AbstractIFTestCase.java new file mode 100644 index 000000000..56d613e20 --- /dev/null +++ b/test/java/org/apache/fop/intermediate/AbstractIFTestCase.java @@ -0,0 +1,137 @@ +/* + * 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.intermediate; + +import java.io.File; +import java.io.IOException; + +import javax.xml.XMLConstants; +import javax.xml.transform.Result; +import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXResult; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.w3c.dom.Document; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.Fop; +import org.apache.fop.render.intermediate.IFContext; +import org.apache.fop.render.intermediate.IFDocumentHandler; +import org.apache.fop.render.intermediate.IFSerializer; + +/** + * A common super-class for intermediate format test cases. + */ +abstract class AbstractIFTestCase extends AbstractIntermediateTestCase { + + private static final Schema IF_SCHEMA; + + static { + Schema ifSchema = null; + try { + SchemaFactory sFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + File ifSchemaFile = new File( + "src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd"); + ifSchema = sFactory.newSchema(ifSchemaFile); + } catch (IllegalArgumentException iae) { + System.err.println("No suitable SchemaFactory for XML Schema validation found!"); + } catch (SAXException e) { + throw new ExceptionInInitializerError(e); + } + IF_SCHEMA = ifSchema; + } + + /** + * Creates a new test case. + * + * @param testFile the file containing the document and the tests + * @throws IOException if an I/O error occurs while loading the test case + */ + public AbstractIFTestCase(File testFile) throws IOException { + super(testFile); + } + + @Override + protected String getIntermediateFileExtension() { + return ".if.xml"; + } + + @Override + protected Document buildIntermediateDocument(Templates templates) throws Exception { + Transformer transformer = templates.newTransformer(); + setErrorListener(transformer); + + //Set up XMLRenderer to render to a DOM + DOMResult domResult = new DOMResult(); + + FOUserAgent userAgent = createUserAgent(); + + //Create an instance of the target renderer so the XMLRenderer can use its font setup + IFDocumentHandler targetHandler = userAgent.getRendererFactory().createDocumentHandler( + userAgent, getTargetMIME()); + + //Setup painter + IFSerializer serializer = new IFSerializer(); + serializer.setContext(new IFContext(userAgent)); + serializer.mimicDocumentHandler(targetHandler); + serializer.setResult(domResult); + + userAgent.setDocumentHandlerOverride(serializer); + + Fop fop = fopFactory.newFop(userAgent); + Result res = new SAXResult(fop.getDefaultHandler()); + transformer.transform(new DOMSource(testDoc), res); + + return (Document) domResult.getNode(); + } + + @Override + protected void validate(Document doc) throws SAXException, IOException { + if (IF_SCHEMA == null) { + return; //skip validation; + } + Validator validator = IF_SCHEMA.newValidator(); + validator.setErrorHandler(new ErrorHandler() { + + public void error(SAXParseException exception) throws SAXException { + throw exception; + } + + public void fatalError(SAXParseException exception) throws SAXException { + throw exception; + } + + public void warning(SAXParseException exception) throws SAXException { + //ignore + } + + }); + validator.validate(new DOMSource(doc)); + } + +} diff --git a/test/java/org/apache/fop/intermediate/AbstractIntermediateTestCase.java b/test/java/org/apache/fop/intermediate/AbstractIntermediateTestCase.java index 826a5c777..d16621382 100644 --- a/test/java/org/apache/fop/intermediate/AbstractIntermediateTestCase.java +++ b/test/java/org/apache/fop/intermediate/AbstractIntermediateTestCase.java @@ -44,7 +44,6 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; import org.apache.fop.events.model.EventSeverity; -import org.apache.fop.layoutengine.TestEnvironment; import org.apache.fop.util.ConsoleEventListenerForTests; /** @@ -53,15 +52,13 @@ import org.apache.fop.util.ConsoleEventListenerForTests; public abstract class AbstractIntermediateTestCase extends XMLTestCase { /** the test environment */ - protected static TestEnvironment env = new TestEnvironment(); + protected static TestAssistant testAssistant = new TestAssistant(); /** the FOP factory */ protected FopFactory fopFactory; - /** the main base directory for tests */ - protected File mainDir = new File("test/layoutengine"); /** the directory containing the tests */ - protected File testDir = new File(mainDir, "standard-testcases"); + protected File testDir = new File("test/layoutengine/standard-testcases"); /** the output directory for any files generated by the tests */ protected File outputDir; @@ -87,11 +84,11 @@ public abstract class AbstractIntermediateTestCase extends XMLTestCase { protected void setUp() throws Exception { super.setUp(); setupOutputDirectory(); - this.testDoc = env.loadTestCase(testFile); - this.fopFactory = env.getFopFactory(testDoc); - intermediate = buildIntermediateDocument(env.getTestcase2FOStylesheet()); + this.testDoc = testAssistant.loadTestCase(testFile); + this.fopFactory = testAssistant.getFopFactory(testDoc); + intermediate = buildIntermediateDocument(testAssistant.getTestcase2FOStylesheet()); if (outputDir != null) { - env.saveDOM(intermediate, new File(outputDir, + testAssistant.saveDOM(intermediate, new File(outputDir, getName() + ".1" + getIntermediateFileExtension())); } } @@ -148,7 +145,8 @@ public abstract class AbstractIntermediateTestCase extends XMLTestCase { userAgent.getEventBroadcaster().addEventListener( new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.FATAL)); } catch (MalformedURLException e) { - //ignore, won't happen + // Shouldn't happen + throw new AssertionError(); } return userAgent; } @@ -175,7 +173,7 @@ public abstract class AbstractIntermediateTestCase extends XMLTestCase { Document doc = parseAndRenderToIntermediateFormat(src); if (outputDir != null) { File tgtFile = new File(outputDir, getName() + ".2" + getIntermediateFileExtension()); - env.saveDOM(doc, tgtFile); + testAssistant.saveDOM(doc, tgtFile); } assertXMLEqual(intermediate, doc); diff --git a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java index 3d029778d..e3135c5a3 100644 --- a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java +++ b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java @@ -72,7 +72,7 @@ public class AreaTreeParserTestCase extends AbstractIntermediateTestCase { setErrorListener(transformer); //Set up XMLRenderer to render to a DOM - TransformerHandler handler = env.getTransformerFactory().newTransformerHandler(); + TransformerHandler handler = testAssistant.getTransformerFactory().newTransformerHandler(); DOMResult domResult = new DOMResult(); handler.setResult(domResult); @@ -113,7 +113,7 @@ public class AreaTreeParserTestCase extends AbstractIntermediateTestCase { AreaTreeParser parser = new AreaTreeParser(); //Set up XMLRenderer to render to a DOM - TransformerHandler handler = env.getTransformerFactory().newTransformerHandler(); + TransformerHandler handler = testAssistant.getTransformerFactory().newTransformerHandler(); DOMResult domResult = new DOMResult(); handler.setResult(domResult); XMLRenderer renderer = new XMLRenderer(); diff --git a/test/java/org/apache/fop/intermediate/IFCheck.java b/test/java/org/apache/fop/intermediate/IFCheck.java index dc5404818..dfd76f3b3 100644 --- a/test/java/org/apache/fop/intermediate/IFCheck.java +++ b/test/java/org/apache/fop/intermediate/IFCheck.java @@ -21,10 +21,12 @@ package org.apache.fop.intermediate; import org.w3c.dom.Document; +import org.apache.fop.check.Check; + /** * Check interface for intermediate format checks. */ -public interface IFCheck { +public interface IFCheck extends Check { /** * Called to perform the check. diff --git a/test/java/org/apache/fop/intermediate/IFChecksFactory.java b/test/java/org/apache/fop/intermediate/IFChecksFactory.java new file mode 100644 index 000000000..2eab74130 --- /dev/null +++ b/test/java/org/apache/fop/intermediate/IFChecksFactory.java @@ -0,0 +1,49 @@ +/* + * 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.intermediate; + +import org.w3c.dom.Element; + +import org.apache.fop.check.ChecksFactory; +import org.apache.fop.layoutengine.EvalCheck; +import org.apache.fop.layoutengine.TrueCheck; + +/** + * A factory class for creating {@link IFCheck} instances. + */ +final class IFChecksFactory extends ChecksFactory<IFCheck> { + + IFChecksFactory() { + registerCheckFactory("true", new CheckFactory<IFCheck>() { + + public IFCheck createCheck(Element element) { + return new TrueCheck(element); + } + + }); + registerCheckFactory("eval", new CheckFactory<IFCheck>() { + + public IFCheck createCheck(Element element) { + return new EvalCheck(element); + } + + }); + } +} diff --git a/test/java/org/apache/fop/intermediate/IFParserTestCase.java b/test/java/org/apache/fop/intermediate/IFParserTestCase.java index 15fc74bc9..afdd757c9 100644 --- a/test/java/org/apache/fop/intermediate/IFParserTestCase.java +++ b/test/java/org/apache/fop/intermediate/IFParserTestCase.java @@ -23,59 +23,23 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; -import javax.xml.XMLConstants; -import javax.xml.transform.Result; import javax.xml.transform.Source; -import javax.xml.transform.Templates; -import javax.xml.transform.Transformer; import javax.xml.transform.dom.DOMResult; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamResult; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import javax.xml.validation.Validator; import org.w3c.dom.Document; -import org.xml.sax.ErrorHandler; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.Fop; -import org.apache.fop.apps.MimeConstants; import org.apache.fop.fonts.FontInfo; -import org.apache.fop.layoutengine.TestEnvironment; import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFParser; -import org.apache.fop.render.intermediate.IFRenderer; import org.apache.fop.render.intermediate.IFSerializer; /** * Tests the intermediate format parser. */ -public class IFParserTestCase extends AbstractIntermediateTestCase { - - private static TestEnvironment env = new TestEnvironment(); - private static Schema ifSchema; - - private static Schema getIFSchema() throws SAXException { - if (ifSchema == null) { - SchemaFactory sFactory; - try { - sFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - } catch (IllegalArgumentException iae) { - System.out.println("No suitable SchemaFactory for XML Schema validation found!"); - return null; - } - File ifSchemaFile = new File( - "src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd"); - ifSchema = sFactory.newSchema(ifSchemaFile); - } - return ifSchema; - } +public class IFParserTestCase extends AbstractIFTestCase { /** * Constructor for the test suite that is used for each test file. @@ -87,76 +51,7 @@ public class IFParserTestCase extends AbstractIntermediateTestCase { } /** {@inheritDoc} */ - protected String getTargetMIME() { - return MimeConstants.MIME_PDF; - } - - /** {@inheritDoc} */ - protected String getIntermediateFileExtension() { - return ".if.xml"; - } - - /** {@inheritDoc} */ - protected Document buildIntermediateDocument(Templates templates) - throws Exception { - Transformer transformer = templates.newTransformer(); - setErrorListener(transformer); - - //Set up XMLRenderer to render to a DOM - DOMResult domResult = new DOMResult(); - - FOUserAgent userAgent = createUserAgent(); - - //Create an instance of the target renderer so the XMLRenderer can use its font setup - IFDocumentHandler targetHandler = userAgent.getRendererFactory().createDocumentHandler( - userAgent, getTargetMIME()); - - //Setup painter - IFSerializer serializer = new IFSerializer(); - serializer.setContext(new IFContext(userAgent)); - serializer.mimicDocumentHandler(targetHandler); - serializer.setResult(domResult); - - //Setup renderer - IFRenderer renderer = new IFRenderer(); - renderer.setUserAgent(userAgent); - - renderer.setDocumentHandler(serializer); - userAgent.setRendererOverride(renderer); - - Fop fop = fopFactory.newFop(userAgent); - Result res = new SAXResult(fop.getDefaultHandler()); - transformer.transform(new DOMSource(testDoc), res); - - return (Document)domResult.getNode(); - } - - /** {@inheritDoc} */ - protected void validate(Document doc) throws SAXException, IOException { - Schema schema = getIFSchema(); - if (schema == null) { - return; //skip validation; - } - Validator validator = schema.newValidator(); - validator.setErrorHandler(new ErrorHandler() { - - public void error(SAXParseException exception) throws SAXException { - throw exception; - } - - public void fatalError(SAXParseException exception) throws SAXException { - throw exception; - } - - public void warning(SAXParseException exception) throws SAXException { - //ignore - } - - }); - validator.validate(new DOMSource(doc)); - } - - /** {@inheritDoc} */ + @Override protected void parseAndRender(Source src, OutputStream out) throws Exception { IFParser parser = new IFParser(); @@ -170,6 +65,7 @@ public class IFParserTestCase extends AbstractIntermediateTestCase { } /** {@inheritDoc} */ + @Override protected Document parseAndRenderToIntermediateFormat(Source src) throws Exception { IFParser parser = new IFParser(); @@ -185,4 +81,11 @@ public class IFParserTestCase extends AbstractIntermediateTestCase { return (Document)domResult.getNode(); } + /** {@inheritDoc} */ + @Override + public void runTest() throws Exception { + testParserToIntermediateFormat(); + testParserToPDF(); + } + } diff --git a/test/java/org/apache/fop/intermediate/IFTestCase.java b/test/java/org/apache/fop/intermediate/IFTestCase.java new file mode 100644 index 000000000..30cb56b07 --- /dev/null +++ b/test/java/org/apache/fop/intermediate/IFTestCase.java @@ -0,0 +1,77 @@ +/* + * 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.intermediate; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; + +import javax.xml.transform.Source; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + + +/** + * Test case for the IF output. + */ +public class IFTestCase extends AbstractIFTestCase { + + private final IFTester ifTester; + + /** + * Creates a new test case. + * + * @param test the file containing the test case + * @param ifTester the helper instance that will perform checks + * @throws IOException if an I/O error occurs while loading the test case + */ + public IFTestCase(File test, IFTester ifTester) throws IOException { + super(test); + this.ifTester = ifTester; + this.testDir = test.getParentFile(); + } + + /** {@inheritDoc} */ + @Override + protected void runTest() throws Exception { + Element testRoot = testAssistant.getTestRoot(testFile); + NodeList nodes = testRoot.getElementsByTagName("if-checks"); + if (nodes.getLength() == 0) { + throw new RuntimeException("No IF check found"); + } + Element ifChecks = (Element) nodes.item(0); + + Document doc = buildIntermediateDocument(testAssistant.getTestcase2FOStylesheet()); + ifTester.doIFChecks(getName(), ifChecks, doc); + } + + @Override + protected void parseAndRender(Source src, OutputStream out) throws Exception { + throw new IllegalStateException("Not applicable to this test"); + } + + @Override + protected Document parseAndRenderToIntermediateFormat(Source src) throws Exception { + throw new IllegalStateException("Not applicable to this test"); + } + +} diff --git a/test/java/org/apache/fop/intermediate/IFTester.java b/test/java/org/apache/fop/intermediate/IFTester.java index 7534309e7..46303d874 100644 --- a/test/java/org/apache/fop/intermediate/IFTester.java +++ b/test/java/org/apache/fop/intermediate/IFTester.java @@ -20,182 +20,63 @@ package org.apache.fop.intermediate; import java.io.File; -import java.lang.reflect.Constructor; -import java.util.Iterator; import java.util.List; -import java.util.Map; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; -import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.sax.SAXResult; -import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.FopFactory; -import org.apache.fop.area.AreaTreeModel; -import org.apache.fop.area.AreaTreeParser; -import org.apache.fop.area.RenderPagesModel; -import org.apache.fop.events.model.EventSeverity; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.layoutengine.EvalCheck; -import org.apache.fop.layoutengine.TrueCheck; -import org.apache.fop.render.intermediate.IFContext; -import org.apache.fop.render.intermediate.IFRenderer; -import org.apache.fop.render.intermediate.IFSerializer; -import org.apache.fop.util.ConsoleEventListenerForTests; -import org.apache.fop.util.DelegatingContentHandler; /** * Does tests on the intermediate format. */ public class IFTester { - private static final Map IF_CHECK_CLASSES = new java.util.HashMap(); - - static { - IF_CHECK_CLASSES.put("true", TrueCheck.class); - IF_CHECK_CLASSES.put("eval", EvalCheck.class); - } - - private FopFactory fopFactory = FopFactory.newInstance(); + private final IFChecksFactory ifChecksFactory = new IFChecksFactory(); - private SAXTransformerFactory tfactory - = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + private final TransformerFactory tfactory; private File backupDir; /** - * Main constructor + * Main constructor. + * + * @param transformerFactory the factory used to serialize the intermediate format files * @param backupDir an optional directory in which to write the serialized - * intermediate format file (may be null) + * IF files (may be null) */ - public IFTester(File backupDir) { + public IFTester(TransformerFactory transformerFactory, File backupDir) { + this.tfactory = transformerFactory; this.backupDir = backupDir; } /** - * Factory method to create IF checks from DOM elements. - * @param el DOM element to create the check from - * @return The newly create check - */ - protected IFCheck createIFCheck(Element el) { - String name = el.getTagName(); - Class clazz = (Class)IF_CHECK_CLASSES.get(name); - if (clazz != null) { - try { - Constructor c = clazz.getDeclaredConstructor(new Class[] {Node.class}); - IFCheck instance = (IFCheck)c.newInstance(new Object[] {el}); - return instance; - } catch (Exception e) { - throw new RuntimeException("Error while instantiating check '" - + name + "': " + e.getMessage()); - } - } else { - throw new IllegalArgumentException("No check class found: " + name); - } - } - - private Document createIF(File testFile, Document areaTreeXML) throws TransformerException { - try { - FOUserAgent ua = fopFactory.newFOUserAgent(); - ua.setBaseURL(testFile.getParentFile().toURI().toURL().toExternalForm()); - ua.getEventBroadcaster().addEventListener( - new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN)); - - IFRenderer ifRenderer = new IFRenderer(); - ifRenderer.setUserAgent(ua); - - IFSerializer serializer = new IFSerializer(); - serializer.setContext(new IFContext(ua)); - DOMResult result = new DOMResult(); - serializer.setResult(result); - ifRenderer.setDocumentHandler(serializer); - - ua.setRendererOverride(ifRenderer); - FontInfo fontInfo = new FontInfo(); - //Construct the AreaTreeModel that will received the individual pages - final AreaTreeModel treeModel = new RenderPagesModel(ua, - null, fontInfo, null); - - //Iterate over all intermediate files - AreaTreeParser parser = new AreaTreeParser(); - ContentHandler handler = parser.getContentHandler(treeModel, ua); - - DelegatingContentHandler proxy = new DelegatingContentHandler() { - - public void endDocument() throws SAXException { - super.endDocument(); - //Signal the end of the processing. - //The renderer can finalize the target document. - treeModel.endDocument(); - } - - }; - proxy.setDelegateContentHandler(handler); - - Transformer transformer = tfactory.newTransformer(); - transformer.transform(new DOMSource(areaTreeXML), new SAXResult(proxy)); - - return (Document)result.getNode(); - } catch (Exception e) { - throw new TransformerException( - "Error while generating intermediate format file: " + e.getMessage(), e); - } - } - - /** * Runs the intermediate format checks. - * @param testFile the original test file + * @param testName the name of the test case * @param checksRoot the root element containing the IF checks - * @param areaTreeXML the area tree XML + * @param ifDocument the IF XML * @throws TransformerException if an error occurs while transforming the content */ - public void doIFChecks(File testFile, Element checksRoot, Document areaTreeXML) - throws TransformerException { - Document ifDocument = createIF(testFile, areaTreeXML); + public void doIFChecks(String testName, Element checksRoot, Document ifDocument) + throws TransformerException { if (this.backupDir != null) { Transformer transformer = tfactory.newTransformer(); Source src = new DOMSource(ifDocument); - File targetFile = new File(this.backupDir, testFile.getName() + ".if.xml"); + File targetFile = new File(this.backupDir, testName + ".if.xml"); Result res = new StreamResult(targetFile); transformer.transform(src, res); } - - //First create check before actually running them - List checks = new java.util.ArrayList(); - NodeList nodes = checksRoot.getChildNodes(); - for (int i = 0; i < nodes.getLength(); i++) { - Node node = nodes.item(i); - if (node instanceof Element) { - checks.add(createIFCheck((Element)node)); - } - } - + List<IFCheck> checks = ifChecksFactory.createCheckList(checksRoot); if (checks.size() == 0) { - throw new RuntimeException("No checks are available!"); + throw new RuntimeException("No available IF check"); } - - //Run the actual tests now that we know that the checks themselves are ok - doIFChecks(checks, ifDocument); - } - - private void doIFChecks(List checks, Document ifDocument) { - Iterator i = checks.iterator(); - while (i.hasNext()) { - IFCheck check = (IFCheck)i.next(); + for (IFCheck check : checks) { check.check(ifDocument); } } diff --git a/test/java/org/apache/fop/intermediate/IntermediateFormatTestSuite.java b/test/java/org/apache/fop/intermediate/IntermediateFormatTestSuite.java index 438ff7672..824fee6fd 100644 --- a/test/java/org/apache/fop/intermediate/IntermediateFormatTestSuite.java +++ b/test/java/org/apache/fop/intermediate/IntermediateFormatTestSuite.java @@ -20,52 +20,48 @@ package org.apache.fop.intermediate; import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; -import java.util.Collection; -import java.util.Iterator; + +import javax.xml.transform.TransformerFactory; import junit.framework.Test; import junit.framework.TestSuite; -import org.apache.fop.layoutengine.LayoutEngineTestSuite; - /** - * JUnit test suite for the intermediate format + * A test suite for testing the Intermediate Format output. */ -public class IntermediateFormatTestSuite { +public final class IntermediateFormatTestSuite { + + private IntermediateFormatTestSuite() { + // This is a utility class + } /** - * @return the test suite with all the tests (one for each XML file) - * @throws IOException in case of an I/O problem + * Creates a suite of Intermediate Format tests. + * + * @return the test suite + * @throws IOException if an I/O error occurs while loading one of the tests */ public static Test suite() throws IOException { - TestSuite suite = new TestSuite(); - Collection files = LayoutEngineTestSuite.getTestFiles(); + File backupDir = new File("build/test-results/intermediate"); + backupDir.mkdirs(); - Iterator i = files.iterator(); - while (i.hasNext()) { - File f = (File)i.next(); - addIFTestCase(suite, f); - } + IFTester ifTester = new IFTester(TransformerFactory.newInstance(), backupDir); - return suite; - } + TestSuite suite = new TestSuite(); + File testDir = new File("test/intermediate"); + String[] tests = testDir.list(new FilenameFilter() { - private static void addIFTestCase(TestSuite suite, - final File f) throws IOException { - suite.addTest(new IFParserTestCase(f) { - public void runTest() throws Exception { - try { - testParserToIntermediateFormat(); - testParserToPDF(); - } catch (Exception e) { - org.apache.commons.logging.LogFactory.getLog( - this.getClass()).error("Error on " + f.getName()); - throw e; - } + public boolean accept(File dir, String name) { + return name.endsWith(".xml"); } }); + for (String test : tests) { + File testFile = new File(testDir, test); + suite.addTest(new IFTestCase(testFile, ifTester)); + } + return suite; } - } diff --git a/test/java/org/apache/fop/intermediate/LayoutIFTestSuite.java b/test/java/org/apache/fop/intermediate/LayoutIFTestSuite.java new file mode 100644 index 000000000..720556a6b --- /dev/null +++ b/test/java/org/apache/fop/intermediate/LayoutIFTestSuite.java @@ -0,0 +1,64 @@ +/* + * 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.intermediate; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.apache.fop.layoutengine.LayoutEngineTestSuite; + +/** + * JUnit test suite for the intermediate format + */ +public final class LayoutIFTestSuite { + + private LayoutIFTestSuite() { + // This is a utility class + } + + /** + * @return the test suite with all the tests (one for each XML file) + * @throws IOException in case of an I/O problem + */ + public static Test suite() throws IOException { + TestSuite suite = new TestSuite(); + + Collection files = LayoutEngineTestSuite.getTestFiles(); + + Iterator i = files.iterator(); + while (i.hasNext()) { + File f = (File)i.next(); + addIFTestCase(suite, f); + } + + return suite; + } + + private static void addIFTestCase(TestSuite suite, + final File f) throws IOException { + suite.addTest(new IFParserTestCase(f)); + } + +} diff --git a/test/java/org/apache/fop/layoutengine/TestEnvironment.java b/test/java/org/apache/fop/intermediate/TestAssistant.java index ad976ff8c..7fd08dc3d 100644 --- a/test/java/org/apache/fop/layoutengine/TestEnvironment.java +++ b/test/java/org/apache/fop/intermediate/TestAssistant.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.layoutengine; +package org.apache.fop.intermediate; import java.io.File; import java.io.IOException; @@ -30,12 +30,14 @@ import javax.xml.transform.Templates; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; +import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.apache.xpath.XPathAPI; import org.apache.xpath.objects.XObject; @@ -43,9 +45,9 @@ import org.apache.xpath.objects.XObject; import org.apache.fop.apps.FopFactory; /** - * Test environment and helper code for running FOP tests. + * Helper class for running FOP tests. */ -public class TestEnvironment { +public class TestAssistant { // configure fopFactory as desired private FopFactory fopFactory = FopFactory.newInstance(); @@ -62,7 +64,7 @@ public class TestEnvironment { /** * Main constructor. */ - public TestEnvironment() { + public TestAssistant() { fopFactory.getFontManager().setBase14KerningEnabled(false); fopFactoryWithBase14Kerning.getFontManager().setBase14KerningEnabled(true); domBuilderFactory = DocumentBuilderFactory.newInstance(); @@ -89,7 +91,7 @@ public class TestEnvironment { * @return the stylesheet * @throws TransformerConfigurationException if an error occurs loading the stylesheet */ - public Templates getTestcase2ChecksStylesheet() throws TransformerConfigurationException { + private Templates getTestcase2ChecksStylesheet() throws TransformerConfigurationException { if (testcase2checks == null) { //Load and cache stylesheet Source src = new StreamSource(new File("test/layoutengine/testcase2checks.xsl")); @@ -98,6 +100,21 @@ public class TestEnvironment { return testcase2checks; } + /** + * Returns the element from the given XML file that encloses the tests. + * + * @param testFile a test case + * @return the parent element of the group(s) of checks + * @throws TransformerException if an error occurs while extracting the test element + */ + public Element getTestRoot(File testFile) throws TransformerException { + Transformer transformer = getTestcase2ChecksStylesheet().newTransformer(); + DOMResult res = new DOMResult(); + transformer.transform(new StreamSource(testFile), res); + Document doc = (Document) res.getNode(); + return doc.getDocumentElement(); + } + public FopFactory getFopFactory(boolean base14KerningEnabled) { FopFactory effFactory = (base14KerningEnabled ? fopFactoryWithBase14Kerning : fopFactory); return effFactory; diff --git a/test/java/org/apache/fop/layoutengine/EvalCheck.java b/test/java/org/apache/fop/layoutengine/EvalCheck.java index 32d9e689b..8065512a7 100644 --- a/test/java/org/apache/fop/layoutengine/EvalCheck.java +++ b/test/java/org/apache/fop/layoutengine/EvalCheck.java @@ -42,16 +42,6 @@ public class EvalCheck implements LayoutEngineCheck, IFCheck { private PrefixResolver prefixResolver; /** - * Creates a new instance - * @param expected expected value - * @param xpath XPath statement that needs to be evaluated - */ - public EvalCheck(String expected, String xpath) { - this.expected = expected; - this.xpath = xpath; - } - - /** * Creates a new instance from a DOM node. * @param node DOM node that defines this check */ diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineCheck.java b/test/java/org/apache/fop/layoutengine/LayoutEngineCheck.java index 155db2263..ca979efe5 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineCheck.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineCheck.java @@ -19,10 +19,12 @@ package org.apache.fop.layoutengine; +import org.apache.fop.check.Check; + /** * Defines the interface for check operations. */ -public interface LayoutEngineCheck { +public interface LayoutEngineCheck extends Check { /** * Called to perform the check. diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineChecksFactory.java b/test/java/org/apache/fop/layoutengine/LayoutEngineChecksFactory.java new file mode 100644 index 000000000..bea54c5f8 --- /dev/null +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineChecksFactory.java @@ -0,0 +1,62 @@ +/* + * 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.layoutengine; + +import org.w3c.dom.Element; + +import org.apache.fop.check.ChecksFactory; + +/** + * A factory class for creating {@link LayoutEngineCheck} instances. + */ +final class LayoutEngineChecksFactory extends ChecksFactory<LayoutEngineCheck> { + + LayoutEngineChecksFactory() { + registerCheckFactory("true", new CheckFactory<LayoutEngineCheck>() { + + public LayoutEngineCheck createCheck(Element element) { + return new TrueCheck(element); + } + + }); + registerCheckFactory("eval", new CheckFactory<LayoutEngineCheck>() { + + public LayoutEngineCheck createCheck(Element element) { + return new EvalCheck(element); + } + + }); + registerCheckFactory("element-list", new CheckFactory<LayoutEngineCheck>() { + + public LayoutEngineCheck createCheck(Element element) { + return new ElementListCheck(element); + } + + }); + registerCheckFactory("result", new CheckFactory<LayoutEngineCheck>() { + + public LayoutEngineCheck createCheck(Element element) { + return new ResultCheck(element); + } + + }); + } + +} diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java index 32a48fb0b..397374657 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java @@ -56,12 +56,16 @@ import org.apache.fop.DebugHelper; /** * JUnit test suit for running layout engine test under JUnit control. */ -public class LayoutEngineTestSuite { +public final class LayoutEngineTestSuite { static { DebugHelper.registerStandardElementListObservers(); } + private LayoutEngineTestSuite() { + // This is a utility class + } + public static String[] readDisabledTestcases(File f) throws IOException { List lines = new java.util.ArrayList(); Source stylesheet = new StreamSource( @@ -178,45 +182,33 @@ public class LayoutEngineTestSuite { Iterator i = files.iterator(); while (i.hasNext()) { File f = (File)i.next(); - addTestCase(suite, tester, f); + suite.addTest(new LayoutEngineTestCase(f, tester)); } return suite; } - private static void addTestCase(TestSuite suite, - final LayoutEngineTester tester, final File f) { - suite.addTest(new LayoutEngineTestCase(f.getName()) { - public void runTest() throws Exception { - try { - prepare(tester, f); - testMain(); - } catch (Exception e) { - org.apache.commons.logging.LogFactory.getLog( - this.getClass()).error("Error on " + f.getName()); - throw e; - } - } - }); - } - private static class LayoutEngineTestCase extends TestCase { - private LayoutEngineTester tester; - private File testFile; + private final File testFile; - public LayoutEngineTestCase(String name) { - super(name); - } + private final LayoutEngineTester tester; - public void prepare(LayoutEngineTester tester, File testFile) { - //super(testFile.getName()); - this.tester = tester; + LayoutEngineTestCase(File testFile, LayoutEngineTester tester) { + super(testFile.getName()); this.testFile = testFile; + this.tester = tester; } - public void testMain() throws Exception { - tester.runTest(testFile); + @Override + protected void runTest() throws Throwable { + try { + tester.runTest(testFile); + } catch (Exception e) { + org.apache.commons.logging.LogFactory.getLog( + this.getClass()).error("Error on " + getName()); + throw e; + } } } } diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java index 2c0cf8504..51c05a95f 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java @@ -21,37 +21,42 @@ package org.apache.fop.layoutengine; import java.io.File; import java.io.IOException; -import java.lang.reflect.Constructor; -import java.util.Iterator; import java.util.List; -import java.util.Map; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.TransformerHandler; -import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.Node; import org.w3c.dom.NodeList; - +import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.FormattingResults; +import org.apache.fop.area.AreaTreeModel; +import org.apache.fop.area.AreaTreeParser; +import org.apache.fop.area.RenderPagesModel; import org.apache.fop.events.model.EventSeverity; +import org.apache.fop.fonts.FontInfo; import org.apache.fop.intermediate.IFTester; +import org.apache.fop.intermediate.TestAssistant; import org.apache.fop.layoutmgr.ElementListObserver; +import org.apache.fop.render.intermediate.IFContext; +import org.apache.fop.render.intermediate.IFRenderer; +import org.apache.fop.render.intermediate.IFSerializer; import org.apache.fop.render.xml.XMLRenderer; import org.apache.fop.util.ConsoleEventListenerForTests; +import org.apache.fop.util.DelegatingContentHandler; /** * Class for testing the FOP's layout engine using testcases specified in XML @@ -59,19 +64,13 @@ import org.apache.fop.util.ConsoleEventListenerForTests; */ public class LayoutEngineTester { - private static final Map AT_CHECK_CLASSES = new java.util.HashMap(); - - private TestEnvironment env = new TestEnvironment(); + private TestAssistant testAssistant = new TestAssistant(); + private LayoutEngineChecksFactory layoutEngineChecksFactory = new LayoutEngineChecksFactory(); private File areaTreeBackupDir; private IFTester ifTester; - static { - AT_CHECK_CLASSES.put("true", TrueCheck.class); - AT_CHECK_CLASSES.put("eval", EvalCheck.class); - AT_CHECK_CLASSES.put("element-list", ElementListCheck.class); - AT_CHECK_CLASSES.put("result", ResultCheck.class); - } + private TransformerFactory tfactory = TransformerFactory.newInstance(); /** * Constructs a new instance. @@ -80,7 +79,7 @@ public class LayoutEngineTester { */ public LayoutEngineTester(File areaTreeBackupDir) { this.areaTreeBackupDir = areaTreeBackupDir; - this.ifTester = new IFTester(areaTreeBackupDir); + this.ifTester = new IFTester(tfactory, areaTreeBackupDir); } /** @@ -100,18 +99,18 @@ public class LayoutEngineTester { ElementListObserver.addObserver(elCollector); Fop fop; - + FopFactory effFactory; try { - Document testDoc = env.loadTestCase(testFile); - FopFactory effFactory = env.getFopFactory(testDoc); + Document testDoc = testAssistant.loadTestCase(testFile); + effFactory = testAssistant.getFopFactory(testDoc); //Setup Transformer to convert the testcase XML to XSL-FO - Transformer transformer = env.getTestcase2FOStylesheet().newTransformer(); + Transformer transformer = testAssistant.getTestcase2FOStylesheet().newTransformer(); Source src = new DOMSource(testDoc); //Setup Transformer to convert the area tree to a DOM TransformerHandler athandler; - athandler = env.getTransformerFactory().newTransformerHandler(); + athandler = testAssistant.getTransformerFactory().newTransformerHandler(); athandler.setResult(domres); //Setup FOP for area tree rendering @@ -134,91 +133,96 @@ public class LayoutEngineTester { Document doc = (Document)domres.getNode(); if (this.areaTreeBackupDir != null) { - env.saveDOM(doc, + testAssistant.saveDOM(doc, new File(this.areaTreeBackupDir, testFile.getName() + ".at.xml")); } FormattingResults results = fop.getResults(); LayoutResult result = new LayoutResult(doc, elCollector, results); - checkAll(testFile, result); + checkAll(effFactory, testFile, result); } /** - * Factory method to create AT checks from DOM elements. - * @param el DOM element to create the check from - * @return The newly create check - */ - protected LayoutEngineCheck createATCheck(Element el) { - String name = el.getTagName(); - Class clazz = (Class)AT_CHECK_CLASSES.get(name); - if (clazz != null) { - try { - Constructor c = clazz.getDeclaredConstructor(new Class[] {Node.class}); - LayoutEngineCheck instance = (LayoutEngineCheck)c.newInstance(new Object[] {el}); - return instance; - } catch (Exception e) { - throw new RuntimeException("Error while instantiating check '" - + name + "': " + e.getMessage()); - } - } else { - throw new IllegalArgumentException("No check class found: " + name); - } - } - - - /** * Perform all checks on the area tree and, optionally, on the intermediate format. * @param testFile Test case XML file * @param result The layout results * @throws TransformerException if a problem occurs in XSLT/JAXP */ - protected void checkAll(File testFile, LayoutResult result) throws TransformerException { - Transformer transformer = env.getTestcase2ChecksStylesheet().newTransformer(); - Source src = new StreamSource(testFile); - DOMResult res = new DOMResult(); - transformer.transform(src, res); - - Document doc = (Document)res.getNode(); - Element root = doc.getDocumentElement(); + protected void checkAll(FopFactory fopFactory, File testFile, LayoutResult result) + throws TransformerException { + Element testRoot = testAssistant.getTestRoot(testFile); NodeList nodes; //AT tests only when checks are available - nodes = root.getElementsByTagName("at-checks"); + nodes = testRoot.getElementsByTagName("at-checks"); if (nodes.getLength() > 0) { Element atChecks = (Element)nodes.item(0); doATChecks(atChecks, result); } //IF tests only when checks are available - nodes = root.getElementsByTagName("if-checks"); + nodes = testRoot.getElementsByTagName("if-checks"); if (nodes.getLength() > 0) { Element ifChecks = (Element)nodes.item(0); - ifTester.doIFChecks(testFile, ifChecks, result.getAreaTree()); + Document ifDocument = createIF(fopFactory, testFile, result.getAreaTree()); + ifTester.doIFChecks(testFile.getName(), ifChecks, ifDocument); } } - private void doATChecks(Element checksRoot, LayoutResult result) { - //First create check before actually running them - List checks = new java.util.ArrayList(); - NodeList nodes = checksRoot.getChildNodes(); - for (int i = 0; i < nodes.getLength(); i++) { - Node node = nodes.item(i); - if (node instanceof Element) { - checks.add(createATCheck((Element)node)); - } - } + private Document createIF(FopFactory fopFactory, File testFile, Document areaTreeXML) + throws TransformerException { + try { + FOUserAgent ua = fopFactory.newFOUserAgent(); + ua.setBaseURL(testFile.getParentFile().toURI().toURL().toExternalForm()); + ua.getEventBroadcaster().addEventListener( + new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN)); - if (checks.size() == 0) { - throw new RuntimeException("No checks are available!"); - } + IFRenderer ifRenderer = new IFRenderer(); + ifRenderer.setUserAgent(ua); + + IFSerializer serializer = new IFSerializer(); + serializer.setContext(new IFContext(ua)); + DOMResult result = new DOMResult(); + serializer.setResult(result); + ifRenderer.setDocumentHandler(serializer); + + ua.setRendererOverride(ifRenderer); + FontInfo fontInfo = new FontInfo(); + //Construct the AreaTreeModel that will received the individual pages + final AreaTreeModel treeModel = new RenderPagesModel(ua, + null, fontInfo, null); + + //Iterate over all intermediate files + AreaTreeParser parser = new AreaTreeParser(); + ContentHandler handler = parser.getContentHandler(treeModel, ua); + + DelegatingContentHandler proxy = new DelegatingContentHandler() { - //Run the actual tests now that we know that the checks themselves are ok - doATChecks(checks, result); + public void endDocument() throws SAXException { + super.endDocument(); + //Signal the end of the processing. + //The renderer can finalize the target document. + treeModel.endDocument(); + } + + }; + proxy.setDelegateContentHandler(handler); + + Transformer transformer = tfactory.newTransformer(); + transformer.transform(new DOMSource(areaTreeXML), new SAXResult(proxy)); + + return (Document)result.getNode(); + } catch (Exception e) { + throw new TransformerException( + "Error while generating intermediate format file: " + e.getMessage(), e); + } } - private void doATChecks(List checks, LayoutResult result) { - Iterator i = checks.iterator(); - while (i.hasNext()) { - LayoutEngineCheck check = (LayoutEngineCheck)i.next(); + private void doATChecks(Element checksRoot, LayoutResult result) { + List<LayoutEngineCheck> checks = layoutEngineChecksFactory.createCheckList(checksRoot); + if (checks.size() == 0) { + throw new RuntimeException("No available area tree check"); + } + for (LayoutEngineCheck check : checks) { check.check(result); } } diff --git a/test/java/org/apache/fop/layoutengine/ResultCheck.java b/test/java/org/apache/fop/layoutengine/ResultCheck.java index 54af77a43..ce95c5024 100644 --- a/test/java/org/apache/fop/layoutengine/ResultCheck.java +++ b/test/java/org/apache/fop/layoutengine/ResultCheck.java @@ -19,9 +19,10 @@ package org.apache.fop.layoutengine; -import org.apache.fop.apps.FormattingResults; import org.w3c.dom.Node; +import org.apache.fop.apps.FormattingResults; + /** * Simple check that requires a result property to evaluate to the expected value */ @@ -31,16 +32,6 @@ public class ResultCheck implements LayoutEngineCheck { private String property; /** - * Creates a new instance - * @param expected expected value - * @param property property of which the value needs to be evaluated - */ - public ResultCheck(String expected, String property) { - this.expected = expected; - this.property = property; - } - - /** * Creates a new instance from a DOM node. * @param node DOM node that defines this check */ diff --git a/test/java/org/apache/fop/layoutengine/TrueCheck.java b/test/java/org/apache/fop/layoutengine/TrueCheck.java index 94ae942de..77d76b91d 100644 --- a/test/java/org/apache/fop/layoutengine/TrueCheck.java +++ b/test/java/org/apache/fop/layoutengine/TrueCheck.java @@ -42,14 +42,6 @@ public class TrueCheck implements LayoutEngineCheck, IFCheck { private PrefixResolver prefixResolver; /** - * Creates a new instance - * @param xpath XPath statement that needs to be evaluated - */ - public TrueCheck(String xpath) { - this.xpath = xpath; - } - - /** * Creates a new instance from a DOM node. * @param node DOM node that defines this check */ diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index 8a317a696..db66455d7 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -20,13 +20,6 @@ <!--DOCTYPE disabled-testcases SYSTEM "disabled-testcases.dtd"--> <disabled-testcases> <testcase> - <name>External link around an SVG not properly sized</name> - <file>basic-link_external-destination_2.xml</file> - <description>The bpd trait of the inlineparent area for the basic-link - is not sized correctly if it wraps an image that is higher than the - nominal line.</description> - </testcase> - <testcase> <name>Auto-height block-containers produce fences</name> <file>block-container_space-before_space-after_3.xml</file> <description>Block-containers with no height currently don't diff --git a/test/layoutengine/standard-testcases/basic-link_external-destination_2.xml b/test/layoutengine/standard-testcases/basic-link_external-destination_2.xml index f804893ac..0f00da82c 100644 --- a/test/layoutengine/standard-testcases/basic-link_external-destination_2.xml +++ b/test/layoutengine/standard-testcases/basic-link_external-destination_2.xml @@ -47,10 +47,12 @@ </fo:root> </fo> <checks> - <eval expected="192000" xpath="//inlineparent[@prod-id='link']/viewport/@ipd"/> - <eval expected="192000" xpath="//inlineparent[@prod-id='link']/viewport/@bpd"/> - - <eval expected="192000" xpath="//inlineparent[@prod-id='link']/@ipd"/> - <eval expected="192000" xpath="//inlineparent[@prod-id='link']/@bpd"/> + <eval expected="144000" xpath="//inlineparent[@prod-id='link']/@ipd"/> + <eval expected="144000" xpath="//inlineparent[@prod-id='link']/@bpd"/> + <eval expected="0" xpath="//inlineparent[@prod-id='link']/@offset"/> + + <eval expected="144000" xpath="//inlineparent[@prod-id='link']/viewport/@ipd"/> + <eval expected="144000" xpath="//inlineparent[@prod-id='link']/viewport/@bpd"/> + <eval expected="0" xpath="//inlineparent[@prod-id='link']/viewport/@offset"/> </checks> </testcase> diff --git a/test/layoutengine/standard-testcases/basic-link_height.xml b/test/layoutengine/standard-testcases/basic-link_height.xml new file mode 100644 index 000000000..cb56f7f00 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height.xml @@ -0,0 +1,53 @@ +<?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 the height of an fo:basic-link wrapping a bigger element. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="420pt" page-width="320pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In in <fo:basic-link + id="link" color="blue" + external-destination="url(http://xmlgraphics.apache.org/fop/)"><fo:inline id="inline" + font-size="24pt" baseline-shift="12pt">egestas</fo:inline></fo:basic-link> nisi. + Etiam at ante eget velit placerat ullamcorper.</fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="84048" xpath="//inlineparent[@prod-id='link']/@ipd"/> + <eval expected="22200" xpath="//inlineparent[@prod-id='link']/@bpd"/> + <eval expected="0" xpath="//inlineparent[@prod-id='link']/@offset"/> + + <eval expected="84048" xpath="//inlineparent[@prod-id='link']/inlineparent/@ipd"/> + <eval expected="22200" xpath="//inlineparent[@prod-id='link']/inlineparent/@bpd"/> + <eval expected="0" xpath="//inlineparent[@prod-id='link']/inlineparent/@offset"/> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/basic-link_height_baseline-shift.xml b/test/layoutengine/standard-testcases/basic-link_height_baseline-shift.xml new file mode 100644 index 000000000..582ef6143 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height_baseline-shift.xml @@ -0,0 +1,62 @@ +<?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 the height of an fo:basic-link with baseline-shift. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="420pt" page-width="320pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block font-size="40pt">Lorem ipsum dolor <fo:basic-link id="link" color="blue" + font-size="12pt" external-destination="url(http://xmlgraphics.apache.org/fop/)" + baseline-shift="-5pt">sit <fo:inline baseline-shift="5pt">amet,</fo:inline> <fo:inline + font-size="24pt" baseline-shift="-10pt">consectetur</fo:inline> + adipiscing</fo:basic-link>elit.</fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <!-- First line --> + <eval expected="28584" xpath="//lineArea[2]//inlineparent[@prod-id='link']/@bpd"/> + <eval expected="20104" xpath="//lineArea[2]//inlineparent[@prod-id='link']/@offset"/> + + <eval expected="11100" xpath="//lineArea[2]//inlineparent[@prod-id='link']/text[1]/@bpd"/> + <eval expected="5000" xpath="//lineArea[2]//inlineparent[@prod-id='link']/text[1]/@offset"/> + + <eval expected="11100" xpath="//lineArea[2]//inlineparent[@prod-id='link']/inlineparent[1]/@bpd"/> + <eval expected="0" xpath="//lineArea[2]//inlineparent[@prod-id='link']/inlineparent[1]/@offset"/> + + <eval expected="22200" xpath="//lineArea[2]//inlineparent[@prod-id='link']/inlineparent[2]/@bpd"/> + <eval expected="6384" xpath="//lineArea[2]//inlineparent[@prod-id='link']/inlineparent[2]/@offset"/> + + <!-- Second line --> + <eval expected="11100" xpath="//lineArea[3]//inlineparent[@prod-id='link']/@bpd"/> + <eval expected="25104" xpath="//lineArea[3]//inlineparent[@prod-id='link']/@offset"/> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/basic-link_height_inline-child.xml b/test/layoutengine/standard-testcases/basic-link_height_inline-child.xml new file mode 100644 index 000000000..3b74781d8 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height_inline-child.xml @@ -0,0 +1,62 @@ +<?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 the height of an fo:basic-link having several child elements wrapped into a + single fo:inline element. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="420pt" page-width="320pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. <fo:basic-link + id="link" color="blue" + external-destination="url(http://xmlgraphics.apache.org/fop/)"><fo:inline>In + <fo:inline baseline-shift="12pt">in</fo:inline> <fo:inline font-size="24pt" + baseline-shift="-20pt">egestas</fo:inline> nisi</fo:inline></fo:basic-link>. Etiam + at ante eget velit placerat ullamcorper.</fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="45584" xpath="//inlineparent[@prod-id='link']/@bpd"/> + <eval expected="0" xpath="//inlineparent[@prod-id='link']/@offset"/> + + <eval expected="11100" xpath="//inlineparent[@prod-id='link']/inlineparent/@bpd"/> + <eval expected="12000" xpath="//inlineparent[@prod-id='link']/inlineparent/@offset"/> + + <eval expected="11100" xpath="//inlineparent[@prod-id='link']/inlineparent/text[1]/@bpd"/> + <eval expected="0" xpath="//inlineparent[@prod-id='link']/inlineparent/text[1]/@offset"/> + + <eval expected="11100" xpath="//inlineparent[@prod-id='link']/inlineparent/inlineparent[1]/@bpd"/> + <eval expected="-12000" xpath="//inlineparent[@prod-id='link']/inlineparent/inlineparent[1]/@offset"/> + + <eval expected="22200" xpath="//inlineparent[@prod-id='link']/inlineparent/inlineparent[2]/@bpd"/> + <eval expected="11384" xpath="//inlineparent[@prod-id='link']/inlineparent/inlineparent[2]/@offset"/> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/basic-link_height_multi-child.xml b/test/layoutengine/standard-testcases/basic-link_height_multi-child.xml new file mode 100644 index 000000000..845a1d130 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height_multi-child.xml @@ -0,0 +1,58 @@ +<?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 the height of an fo:basic-link having several child elements. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="420pt" page-width="320pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. <fo:basic-link + id="link" color="blue" + external-destination="url(http://xmlgraphics.apache.org/fop/)">In <fo:inline + baseline-shift="12pt">in</fo:inline> <fo:inline font-size="24pt" + baseline-shift="-20pt">egestas</fo:inline> nisi</fo:basic-link>. Etiam at ante eget + velit placerat ullamcorper.</fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="45584" xpath="//inlineparent[@prod-id='link']/@bpd"/> + <eval expected="0" xpath="//inlineparent[@prod-id='link']/@offset"/> + + <eval expected="11100" xpath="//inlineparent[@prod-id='link']/text[1]/@bpd"/> + <eval expected="12000" xpath="//inlineparent[@prod-id='link']/text[1]/@offset"/> + + <eval expected="11100" xpath="//inlineparent[@prod-id='link']/inlineparent[1]/@bpd"/> + <eval expected="0" xpath="//inlineparent[@prod-id='link']/inlineparent[1]/@offset"/> + + <eval expected="22200" xpath="//inlineparent[@prod-id='link']/inlineparent[2]/@bpd"/> + <eval expected="23384" xpath="//inlineparent[@prod-id='link']/inlineparent[2]/@offset"/> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/basic-link_height_multi-line.xml b/test/layoutengine/standard-testcases/basic-link_height_multi-line.xml new file mode 100644 index 000000000..9a52d0128 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height_multi-line.xml @@ -0,0 +1,67 @@ +<?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 the height of an fo:basic-link spanning over several lines. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="420pt" page-width="320pt" margin="10pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer quis neque + vitae lectus condimentum. <fo:basic-link id="link" color="blue" + external-destination="url(http://xmlgraphics.apache.org/fop/)">In <fo:inline + baseline-shift="12pt">in</fo:inline> <fo:inline font-size="24pt" + baseline-shift="-20pt">egestas</fo:inline> nisi</fo:basic-link>. Etiam at ante eget + velit placerat ullamcorper.</fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <!-- First line --> + <eval expected="23100" xpath="//lineArea[2]//inlineparent[@prod-id='link']/@bpd"/> + <eval expected="0" xpath="//lineArea[2]//inlineparent[@prod-id='link']/@offset"/> + + <eval expected="11100" xpath="//lineArea[2]//inlineparent[@prod-id='link']/text[1]/@bpd"/> + <eval expected="12000" xpath="//lineArea[2]//inlineparent[@prod-id='link']/text[1]/@offset"/> + + <eval expected="11100" xpath="//lineArea[2]//inlineparent[@prod-id='link']/inlineparent/@bpd"/> + <eval expected="0" xpath="//lineArea[2]//inlineparent[@prod-id='link']/inlineparent/@offset"/> + + <!-- Second line --> + <eval expected="33584" xpath="//lineArea[3]//inlineparent[@prod-id='link']/@bpd"/> + <eval expected="0" xpath="//lineArea[3]//inlineparent[@prod-id='link']/@offset"/> + + <eval expected="22200" xpath="//lineArea[3]//inlineparent[@prod-id='link']/inlineparent/@bpd"/> + <eval expected="11384" xpath="//lineArea[3]//inlineparent[@prod-id='link']/inlineparent/@offset"/> + + <eval expected="11100" xpath="//lineArea[3]//inlineparent[@prod-id='link']/text[1]/@bpd"/> + <eval expected="0" xpath="//lineArea[3]//inlineparent[@prod-id='link']/text[1]/@offset"/> + + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/block-container_bugzilla50965.xml b/test/layoutengine/standard-testcases/block-container_bugzilla50965.xml new file mode 100644 index 000000000..200a77242 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_bugzilla50965.xml @@ -0,0 +1,56 @@ +<?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 for a regression in block-container layout, where margins + were counted twice, leading to an incorrect CTM for the block area. + See also Bugzilla 50965. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" page-height="100mm" + page-width="100mm"> + <fo:region-body/> + </fo:simple-page-master> + <fo:page-sequence-master master-name="ps"> + <fo:repeatable-page-master-alternatives> + <fo:conditional-page-master-reference master-reference="page" page-position="first"/> + <fo:conditional-page-master-reference master-reference="page" page-position="rest"/> + <fo:conditional-page-master-reference master-reference="page" page-position="last"/> + </fo:repeatable-page-master-alternatives> + </fo:page-sequence-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="ps"> + <fo:flow flow-name="xsl-region-body"> + <fo:block-container margin-left="20mm"> + <fo:block-container page-break-before="always"> + <fo:block>A</fo:block> + </fo:block-container> + </fo:block-container> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="[1.0 0.0 0.0 1.0 56692.0 0.0]" xpath="//flow[1]/block[1]/@ctm" /> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/block_white-space_bug50988.xml b/test/layoutengine/standard-testcases/block_white-space_bug50988.xml new file mode 100644 index 000000000..9954b9e20 --- /dev/null +++ b/test/layoutengine/standard-testcases/block_white-space_bug50988.xml @@ -0,0 +1,43 @@ +<?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 for a potential NullPointerException due to white-space removal. + See also: https://issues.apache.org/bugzilla/show_bug.cgi?id=50988 + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="even" page-height="210mm" page-width="148mm"> + <fo:region-body margin="20mm"/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="even"> + <fo:flow flow-name="xsl-region-body"> + <fo:block><fo:character character=" " hyphenate="false"/></fo:block> + <fo:block><fo:character character=" " hyphenate="false"/><fo:character character="A" hyphenate="false"/></fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <!-- Default checks only; should just not throw a NPE --> + <checks /> +</testcase>
\ No newline at end of file diff --git a/test/layoutengine/standard-testcases/bookmarks_1.xml b/test/layoutengine/standard-testcases/bookmarks_1.xml index b4aa0990d..85cb80cc3 100644 --- a/test/layoutengine/standard-testcases/bookmarks_1.xml +++ b/test/layoutengine/standard-testcases/bookmarks_1.xml @@ -25,7 +25,7 @@ <fo> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <fo:layout-master-set> - <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in" + <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in" margin="20pt"> <fo:region-body background-color="yellow"/> </fo:simple-page-master> @@ -42,6 +42,12 @@ <fo:bookmark internal-destination="chapter2-sec2"> <fo:bookmark-title>Section 2</fo:bookmark-title> </fo:bookmark> + <!-- add a reference to a non-existing id; should only trigger a warning + see Bugzilla 50593 + --> + <fo:bookmark internal-destination="chapterX-secX"> + <fo:bookmark-title>Section X</fo:bookmark-title> + </fo:bookmark> </fo:bookmark> <fo:bookmark internal-destination="bc"> <fo:bookmark-title>Fixed Block Container</fo:bookmark-title> @@ -68,7 +74,7 @@ </fo> <checks> <eval expected="2" xpath="count(//pageViewport)"/> - + <eval expected="Chapter 1" xpath="//bookmarkTree/bookmark[1]/@title"/> <eval expected="true" xpath="//bookmarkTree/bookmark[1]/@show-children"/> <eval expected="Chapter 2" xpath="//bookmarkTree/bookmark[2]/@title"/> @@ -76,7 +82,7 @@ <eval expected="Section 2" xpath="//bookmarkTree/bookmark[2]/bookmark[2]/@title"/> <eval expected="true" xpath="//bookmarkTree/bookmark[2]/bookmark[2]/@show-children"/> - + <eval expected="(P1,chapter1)" xpath="//bookmarkTree/bookmark[1]/@internal-link"/> <eval expected="(P2,chapter2)" xpath="//bookmarkTree/bookmark[2]/@internal-link"/> <eval expected="(P2,chapter2-sec1)" xpath="//bookmarkTree/bookmark[2]/bookmark[1]/@internal-link"/> @@ -100,7 +106,7 @@ <eval expected="1" xpath="//n:bookmark-tree/n:bookmark[2]/n:bookmark[1]/n:goto-xy/@page-index"/> <eval expected="20000" xpath="//n:bookmark-tree/n:bookmark[2]/n:bookmark[1]/n:goto-xy/@x"/> <eval expected="51680" xpath="//n:bookmark-tree/n:bookmark[2]/n:bookmark[1]/n:goto-xy/@y"/> - + <eval expected="show" xpath="//n:bookmark-tree/n:bookmark[3]/@starting-state"/> <eval expected="Fixed Block Container" xpath="//n:bookmark-tree/n:bookmark[3]/@title"/> <eval expected="1" xpath="//n:bookmark-tree/n:bookmark[3]/n:goto-xy/@page-index"/> diff --git a/test/layoutengine/standard-testcases/table-row_keep-together.xml b/test/layoutengine/standard-testcases/table-row_keep-together.xml index 73da10fb8..73a334c6d 100644 --- a/test/layoutengine/standard-testcases/table-row_keep-together.xml +++ b/test/layoutengine/standard-testcases/table-row_keep-together.xml @@ -32,9 +32,9 @@ <fo:page-sequence master-reference="normal"> <fo:flow flow-name="xsl-region-body"> <fo:block>block1</fo:block> - <fo:table table-layout="fixed"> - <fo:table-column/> - <fo:table-column/> + <fo:table table-layout="fixed" width="100%"> + <fo:table-column column-width="proportional-column-width(1)"/> + <fo:table-column column-width="proportional-column-width(1)"/> <fo:table-body> <fo:table-row keep-together.within-page="always"> <fo:table-cell id="cell1"> @@ -55,7 +55,7 @@ <checks> <element-list category="table-cell" id="cell1"> <box w="14400"/> - <penalty w="0" p="INF"/> <!-- the keep-together on the table-row has to result in an INFINITE penalty here --> + <penalty w="0" p="0"/> <box w="14400"/> </element-list> <element-list category="table-cell" id="cell2"> diff --git a/test/layoutengine/standard-testcases/table-row_keep-together_2.xml b/test/layoutengine/standard-testcases/table-row_keep-together_2.xml index 0e2867b2e..db75e4063 100644 --- a/test/layoutengine/standard-testcases/table-row_keep-together_2.xml +++ b/test/layoutengine/standard-testcases/table-row_keep-together_2.xml @@ -128,6 +128,38 @@ </fo:flow> </fo:page-sequence> + <!-- table 4 --> + <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt"> + <fo:flow flow-name="xsl-region-body"> + <fo:block space-after="110pt">4. Before the table</fo:block> + <fo:table width="100%" table-layout="fixed" + border-collapse="collapse" border="4pt solid black"> + <fo:table-column number-columns-repeated="2" + column-width="proportional-column-width(1)"/> + <fo:table-body> + <fo:table-row keep-together.within-page="always"> + <fo:table-cell border="2pt solid blue" number-rows-spanned="2"> + <fo:block>Cell 1.1 Line 1</fo:block> + <fo:block>Cell 1.1 Line 2</fo:block> + <fo:block>Cell 1.1 Line 3</fo:block> + </fo:table-cell> + <fo:table-cell border="2pt solid teal"> + <fo:block>Cell 1.2 Line 1</fo:block> + <fo:block>Cell 1.2 Line 2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell border="2pt solid olive"> + <fo:block>Cell 2.2 Line 1</fo:block> + <fo:block>Cell 2.2 Line 2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + <fo:block>After the table</fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> </fo> <checks> @@ -199,5 +231,47 @@ <eval expected="(solid,#808000,2000,collapse-outer)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@border-before"/> <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@border-after"/> + <!-- table 4 --> + <eval expected="2" xpath="count(//pageSequence[4]/pageViewport)"/> + <!-- page 1 --> + <eval expected="2" xpath="count(//pageViewport[@nr=7]//flow/block)"/> + <eval expected="4. Before the table" xpath="//pageViewport[@nr=7]//flow/block[1]/lineArea"/> + <eval expected="23000" xpath="//pageViewport[@nr=7]//flow/block[2]/@bpd"/> + <eval expected="23000" xpath="//pageViewport[@nr=7]//flow/block[2]/@bpda"/> + <!-- cell 1.1 --> + <eval expected="21000" xpath="//pageViewport[@nr=7]//flow/block[2]/block[1]/@bpd"/> + <eval expected="25000" xpath="//pageViewport[@nr=7]//flow/block[2]/block[1]/@bpda"/> + <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=7]//flow/block[2]/block[1]/@border-before"/> + <eval expected="" xpath="//pageViewport[@nr=7]//flow/block[2]/block[1]/@border-after"/> + <eval expected="21000" xpath="//pageViewport[@nr=7]//flow/block[2]/block[2]/@bpd"/> + <eval expected="21000" xpath="//pageViewport[@nr=7]//flow/block[2]/block[2]/@bpda"/> + <eval expected="2" xpath="count(//pageViewport[@nr=7]//flow/block[2]/block[2]/block)"/> + <eval expected="Cell 1.1 Line 1" xpath="//pageViewport[@nr=7]//flow/block[2]/block[2]/block[1]/lineArea"/> + <eval expected="Cell 1.1 Line 2" xpath="//pageViewport[@nr=7]//flow/block[2]/block[2]/block[2]/lineArea"/> + <!-- cell 1.2 --> + <eval expected="20000" xpath="//pageViewport[@nr=7]//flow/block[2]/block[3]/@bpd"/> + <eval expected="26000" xpath="//pageViewport[@nr=7]//flow/block[2]/block[3]/@bpda"/> + <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=7]//flow/block[2]/block[3]/@border-before"/> + <eval expected="(solid,#008080,2000,collapse-outer)" xpath="//pageViewport[@nr=7]//flow/block[2]/block[3]/@border-after"/> + <!-- page 2 --> + <eval expected="2" xpath="count(//pageViewport[@nr=8]//flow/block)"/> + <eval expected="After the table" xpath="//pageViewport[@nr=8]//flow/block[2]/lineArea"/> + <eval expected="23000" xpath="//pageViewport[@nr=8]//flow/block[1]/@bpd"/> + <eval expected="23000" xpath="//pageViewport[@nr=8]//flow/block[1]/@bpda"/> + <!-- cell 1.1 --> + <eval expected="21000" xpath="//pageViewport[@nr=8]//flow/block[1]/block[1]/@bpd"/> + <eval expected="25000" xpath="//pageViewport[@nr=8]//flow/block[1]/block[1]/@bpda"/> + <eval expected="" xpath="//pageViewport[@nr=8]//flow/block[1]/block[1]/@border-before"/> + <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=8]//flow/block[1]/block[1]/@border-after"/> + <eval expected="21000" xpath="//pageViewport[@nr=8]//flow/block[1]/block[2]/@bpd"/> + <eval expected="21000" xpath="//pageViewport[@nr=8]//flow/block[1]/block[2]/@bpda"/> + <eval expected="1" xpath="count(//pageViewport[@nr=8]//flow/block[1]/block[2]/block)"/> + <eval expected="Cell 1.1 Line 3" xpath="//pageViewport[@nr=8]//flow/block[1]/block[2]/block[1]/lineArea"/> + <!-- cell 2.2 --> + <eval expected="20000" xpath="//pageViewport[@nr=8]//flow/block[1]/block[3]/@bpd"/> + <eval expected="26000" xpath="//pageViewport[@nr=8]//flow/block[1]/block[3]/@bpda"/> + <eval expected="(solid,#808000,2000,collapse-outer)" xpath="//pageViewport[@nr=8]//flow/block[1]/block[3]/@border-before"/> + <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=8]//flow/block[1]/block[3]/@border-after"/> + </checks> </testcase> diff --git a/test/layoutengine/standard-testcases/table-row_keep-with-next2.xml b/test/layoutengine/standard-testcases/table-row_keep-with-next2.xml index 3b3b89384..845744e85 100644 --- a/test/layoutengine/standard-testcases/table-row_keep-with-next2.xml +++ b/test/layoutengine/standard-testcases/table-row_keep-with-next2.xml @@ -60,7 +60,9 @@ <element-list category="breaker"> <box w="14400"/> <penalty w="0" p="INF"/> - <box w="28800"/> + <box w="14400"/> + <penalty w="0" p="INF"/> + <box w="14400"/> <penalty w="0" p="0"/> <box w="14400"/> <skip>3</skip> diff --git a/test/layoutengine/standard-testcases/table_keep-together.xml b/test/layoutengine/standard-testcases/table_keep-together.xml index a904a144a..927ea64e6 100644 --- a/test/layoutengine/standard-testcases/table_keep-together.xml +++ b/test/layoutengine/standard-testcases/table_keep-together.xml @@ -92,7 +92,7 @@ <checks> <element-list category="table-cell" id="cell1"> <box w="14400"/> - <penalty w="0" p="INF"/> <!-- the keep-together on the table-row has to result in an INFINITE penalty here --> + <penalty w="0" p="0"/> <box w="14400"/> </element-list> <element-list category="table-cell" id="cell2"> @@ -114,7 +114,7 @@ <!-- the same again but this time with keep="1" --> <element-list category="table-cell" id="cell1b"> <box w="14400"/> - <penalty w="0" p="999"/> + <penalty w="0" p="0"/> <box w="14400"/> </element-list> <element-list category="table-cell" id="cell2b"> diff --git a/test/layoutengine/standard-testcases/table_keep-together_row-span.xml b/test/layoutengine/standard-testcases/table_keep-together_row-span.xml new file mode 100644 index 000000000..b751fcaee --- /dev/null +++ b/test/layoutengine/standard-testcases/table_keep-together_row-span.xml @@ -0,0 +1,69 @@ +<?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 that keep-together works on tables that have a cell spanning several rows. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" + page-height="320pt" page-width="420pt" margin="10pt"> + <fo:region-body background-color="#F0F0F0"/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt"> + <fo:block>Block</fo:block> + <fo:block space-before="245pt">Before the table</fo:block> + <fo:table table-layout="fixed" width="100%" id="table" keep-together.within-page="always"> + <fo:table-body> + <fo:table-row> + <fo:table-cell id="Cell 1.1" border="1pt solid black" number-rows-spanned="2"> + <fo:block>Cell 1.1</fo:block> + </fo:table-cell> + <fo:table-cell id="Cell 1.2" border="1pt solid black"> + <fo:block>Cell 1.2</fo:block> + <fo:block>Cell 1.2</fo:block> + <fo:block>Cell 1.2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell id="Cell 2.2" border="1pt solid black"> + <fo:block>Cell 2.2</fo:block> + <fo:block>Cell 2.2</fo:block> + <fo:block>Cell 2.2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="0" xpath="count(//pageViewport[1]//block[@prod-id='table'])"/> + <eval expected="62000" xpath="//pageViewport[2]//block[@prod-id='table']/@bpd"/> + <eval expected="61000" xpath="//pageViewport[2]//block[@prod-id='Cell 1.1']/@bpd"/> + <eval expected="30000" xpath="//pageViewport[2]//block[@prod-id='Cell 1.2']/@bpd"/> + <eval expected="30000" xpath="//pageViewport[2]//block[@prod-id='Cell 2.2']/@bpd"/> + </checks> +</testcase> |