aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Pepping <spepping@apache.org>2007-09-25 08:26:02 +0000
committerSimon Pepping <spepping@apache.org>2007-09-25 08:26:02 +0000
commit6ff12c3d532811cbd0fdd7551fb9efd648f956b7 (patch)
tree9fd4bc4a7709f92a0818d9b0f415ffea73287e3f
parente4042453799b777ea879a55e9afd99a74a38aaf6 (diff)
downloadxmlgraphics-fop-6ff12c3d532811cbd0fdd7551fb9efd648f956b7.tar.gz
xmlgraphics-fop-6ff12c3d532811cbd0fdd7551fb9efd648f956b7.zip
Merged revisions 520001-530000 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r520797 | jeremias | 2007-03-21 09:13:21 +0100 (Wed, 21 Mar 2007) | 1 line Fixed a problem with the auto-rotate-landscape setting in the PostScript renderer. It didn't generate the right setpagedevice command. ........ r520886 | jeremias | 2007-03-21 14:48:24 +0100 (Wed, 21 Mar 2007) | 1 line Note about relative URLs ........ r520894 | jeremias | 2007-03-21 15:08:02 +0100 (Wed, 21 Mar 2007) | 1 line Updated the website deployment process. ........ r521185 | vhennebert | 2007-03-22 11:13:25 +0100 (Thu, 22 Mar 2007) | 4 lines Small improvements in the SpaceResolver class: - constructor made private as it shouldn't be called by other classes - inner classes made static; they are candidate for later becoming top-level classes ........ r521640 | jeremias | 2007-03-23 10:19:04 +0100 (Fri, 23 Mar 2007) | 1 line Avoid an IndexOutOfBoundsException when more columns are used than are specified even though this is illegal with fixed table layout. ........ r521713 | jeremias | 2007-03-23 14:08:32 +0100 (Fri, 23 Mar 2007) | 2 lines Better document some of the code in RowPainter. Added a check in table-cell_number-rows-spanned_bug38397.xml which is the reason for one of the if-branches in RowPainter. It wan't tested previously so that if-branch could easily be mistaken to be useless. ........ r521744 | jeremias | 2007-03-23 15:37:19 +0100 (Fri, 23 Mar 2007) | 2 lines Some more comments for RowPainter. Additional test that checks that no cell paints more than one area in that case. Because if you remove one or more of the checks now newly commented, you get multiple areas. ........ r522061 | jbryant | 2007-03-24 18:28:10 +0100 (Sat, 24 Mar 2007) | 1 line Added an Area of Expertise for Jay Bryant ........ r522907 | vhennebert | 2007-03-27 15:42:12 +0200 (Tue, 27 Mar 2007) | 3 lines - add border-collapse="separate" to the properties of tables in some testcases, in preparation for the soon-to-be-enabled border-collapsing model - fix svn keywords for region_display-align_table.xml ........ r522908 | vhennebert | 2007-03-27 15:46:22 +0200 (Tue, 27 Mar 2007) | 2 lines Factorize in a method the code handling TableContentPosition elements, in TableContentLayoutManager. ........ r523349 | vhennebert | 2007-03-28 16:49:58 +0200 (Wed, 28 Mar 2007) | 7 lines TableRowIterator: - bugfix: add the correct grid unit for a col span RowPainter.addAreasAndFlushRow: - substract a part of this method into another method - avoid calling it twice by properly resetting lastRow - simplify it thanks to the previous point and the bugfix above ........ r523353 | vhennebert | 2007-03-28 16:52:55 +0200 (Wed, 28 Mar 2007) | 2 lines Fix typo in RowPainter property: svn:kewords -> svn:keywords ........ r523374 | vhennebert | 2007-03-28 17:41:08 +0200 (Wed, 28 Mar 2007) | 2 lines Replace deprecated addBorders method with the new ones in addAreas ........ r523452 | jeremias | 2007-03-28 22:28:23 +0200 (Wed, 28 Mar 2007) | 2 lines Don't log a stacktrace when a JPEG is encountered that has a bad ICC profile and give a nicer warning message. Log the event when a CMYK JPEG with an APPE marker is encountered. ........ r523562 | clay | 2007-03-29 07:18:28 +0200 (Thu, 29 Mar 2007) | 1 line minor typo fix ........ r524014 | vhennebert | 2007-03-30 11:49:38 +0200 (Fri, 30 Mar 2007) | 2 lines Add explicit border-collapse="separate" property in preparation for the implementation of the border-collapsing model ........ r524062 | vhennebert | 2007-03-30 14:25:19 +0200 (Fri, 30 Mar 2007) | 4 lines - fix the painting of borders for spanning cells in collapsing model - rename gridUnit into primaryGridUnit in TableCellLM for clarity - fix some checkstyle issues ........ r524571 | jeremias | 2007-04-01 12:02:43 +0200 (Sun, 01 Apr 2007) | 2 lines Bugfix for keep-with-next inside tables: Once a keep-with-next was set inside a table, the FO following the table would always be glued to the previous table. ........ r524578 | jeremias | 2007-04-01 12:34:57 +0200 (Sun, 01 Apr 2007) | 1 line Removed misleading comment. ........ r524600 | jbryant | 2007-04-01 16:45:59 +0200 (Sun, 01 Apr 2007) | 1 line changes to support named destination ........ r524601 | jbryant | 2007-04-01 16:46:38 +0200 (Sun, 01 Apr 2007) | 1 line changes to support named destination ........ r524602 | jbryant | 2007-04-01 16:48:54 +0200 (Sun, 01 Apr 2007) | 1 line changes to support named destination ........ r524603 | jbryant | 2007-04-01 16:49:12 +0200 (Sun, 01 Apr 2007) | 1 line changes to support named destination ........ r524604 | jbryant | 2007-04-01 16:49:29 +0200 (Sun, 01 Apr 2007) | 1 line changes to support named destination ........ r524605 | jbryant | 2007-04-01 16:49:45 +0200 (Sun, 01 Apr 2007) | 1 line changes to support named destination ........ r524606 | jbryant | 2007-04-01 16:50:36 +0200 (Sun, 01 Apr 2007) | 1 line changes to support named destinations ........ r524607 | jbryant | 2007-04-01 16:50:58 +0200 (Sun, 01 Apr 2007) | 1 line changes to support named destinations ........ r524608 | jbryant | 2007-04-01 16:51:19 +0200 (Sun, 01 Apr 2007) | 1 line changes to support named destinations ........ r524759 | vhennebert | 2007-04-02 11:56:53 +0200 (Mon, 02 Apr 2007) | 2 lines In collapsing-border model, tables have no padding and borders are determined at the cell level. Disable addPendingMarks in such a case. ........ r524800 | jbryant | 2007-04-02 16:53:03 +0200 (Mon, 02 Apr 2007) | 1 line New class to support named destinations ........ r525078 | vhennebert | 2007-04-03 10:14:05 +0200 (Tue, 03 Apr 2007) | 4 lines - fix minor checkstyle issues - add missing headers - add an entry in status.xml for the new named destinations feature ........ r525081 | vhennebert | 2007-04-03 10:23:11 +0200 (Tue, 03 Apr 2007) | 2 lines No change; just add svn:keywords and svn:Id properties on new files ........ r525089 | vhennebert | 2007-04-03 10:48:23 +0200 (Tue, 03 Apr 2007) | 2 lines Add a "new committer" entry for Jay in the news file. A bit late, sorry Jay! ........ r525253 | spepping | 2007-04-03 21:40:14 +0200 (Tue, 03 Apr 2007) | 3 lines Allow for the case where a block-container occurs inside an inline FO. This solves bug 42024. ........ r525526 | jeremias | 2007-04-04 17:05:30 +0200 (Wed, 04 Apr 2007) | 4 lines Fixes for issues introduced with fox:destination: DestinationElementMapping masks ExtensionElementMapping. That caused the tests for widow/orphan extension on tables to fail. Improved Block child validation code (will need to be done for all FOs where fox:destination should be valid. Currently works only as child of fo:block or above fo:page-sequence where no layout managers are constructed. No LMMaker for fox:destination. Improved the handling there so adding the extension element to the list there isn't necessary. ........ r526315 | jbryant | 2007-04-07 01:20:19 +0200 (Sat, 07 Apr 2007) | 1 line Added a PDFGoTo to the PDFDestination handler, so that Destinations properly jump to the page referenced by the PDFGoTo. ........ r526711 | bdelacretaz | 2007-04-09 13:13:47 +0200 (Mon, 09 Apr 2007) | 1 line Marking myself inactive, new job means I'll most probably not work on FOP in the next few months ........ r527379 | jbryant | 2007-04-11 04:58:57 +0200 (Wed, 11 Apr 2007) | 1 line Created a comparator for named destinations, to enable sorting the list of destinations. ........ r527380 | jbryant | 2007-04-11 04:59:55 +0200 (Wed, 11 Apr 2007) | 1 line Added sorting of the list of named destinations (necessary to have more than one destination in a document, unless you get lucky and have them in the proper order by coincidence) ........ r529507 | vhennebert | 2007-04-17 08:58:26 +0200 (Tue, 17 Apr 2007) | 3 lines - add svn:keywords and svn:eol-style properties - style touch up ........ r529544 | vhennebert | 2007-04-17 11:44:47 +0200 (Tue, 17 Apr 2007) | 2 lines Style only: fix indentation ........ r529667 | vhennebert | 2007-04-17 18:21:45 +0200 (Tue, 17 Apr 2007) | 2 lines Make the fop.layoutengine.disabled property work with fop.layoutengine.starts-with ........ r529670 | vhennebert | 2007-04-17 18:44:57 +0200 (Tue, 17 Apr 2007) | 3 lines - add a columnCount field for clarity - remove unneeded parameter from the getNextStep method ........ r529920 | vhennebert | 2007-04-18 10:46:58 +0200 (Wed, 18 Apr 2007) | 2 lines Replace the array of forced breaks with a single boolean, which should be enough. ........ r529921 | vhennebert | 2007-04-18 10:48:58 +0200 (Wed, 18 Apr 2007) | 2 lines Replace the seqCount integer with a stepFound boolean in the getNextStep method ........ r529926 | vhennebert | 2007-04-18 10:52:56 +0200 (Wed, 18 Apr 2007) | 2 lines ... and correct the test for early returning if stepFound is false ........ r529930 | vhennebert | 2007-04-18 11:00:53 +0200 (Wed, 18 Apr 2007) | 2 lines Extract the logic for advancing to the next grid row, from the getNextStep method to a new one. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking@579118 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/documentation/content/xdocs/0.93/fonts.xml5
-rw-r--r--src/documentation/content/xdocs/0.93/output.xml4
-rw-r--r--src/documentation/content/xdocs/compliance.ihtml6
-rw-r--r--src/documentation/content/xdocs/dev/doc.xml36
-rw-r--r--src/documentation/content/xdocs/news.xml4
-rw-r--r--src/documentation/content/xdocs/team.xml21
-rw-r--r--src/documentation/content/xdocs/trunk/fonts.xml5
-rw-r--r--src/java/org/apache/fop/area/AreaTreeHandler.java12
-rw-r--r--src/java/org/apache/fop/area/DestinationData.java131
-rw-r--r--src/java/org/apache/fop/fo/ElementMappingRegistry.java1
-rw-r--r--src/java/org/apache/fop/fo/FONode.java1
-rw-r--r--src/java/org/apache/fop/fo/FOTreeBuilder.java9
-rw-r--r--src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java10
-rw-r--r--src/java/org/apache/fop/fo/extensions/destination/Destination.java102
-rw-r--r--src/java/org/apache/fop/fo/extensions/destination/package.html23
-rw-r--r--src/java/org/apache/fop/fo/flow/Block.java36
-rw-r--r--src/java/org/apache/fop/fo/pagination/Root.java24
-rw-r--r--src/java/org/apache/fop/image/JpegImage.java11
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java10
-rw-r--r--src/java/org/apache/fop/layoutmgr/KnuthPossPosIter.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java11
-rw-r--r--src/java/org/apache/fop/layoutmgr/SpaceResolver.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java10
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/GridUnit.java13
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/RowPainter.java272
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java185
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java51
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableStepper.java163
-rw-r--r--src/java/org/apache/fop/pdf/DestinationComparator.java41
-rw-r--r--src/java/org/apache/fop/pdf/PDFDestination.java138
-rw-r--r--src/java/org/apache/fop/pdf/PDFDests.java79
-rw-r--r--src/java/org/apache/fop/pdf/PDFDocument.java119
-rw-r--r--src/java/org/apache/fop/pdf/PDFFactory.java71
-rw-r--r--src/java/org/apache/fop/pdf/PDFLimits.java93
-rw-r--r--src/java/org/apache/fop/pdf/PDFRoot.java19
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRenderer.java16
-rw-r--r--src/java/org/apache/fop/render/ps/PSRenderer.java19
-rw-r--r--status.xml11
-rw-r--r--test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java1
-rw-r--r--test/layoutengine/standard-testcases/markers_9.xml8
-rw-r--r--test/layoutengine/standard-testcases/region_display-align_table.xml512
-rw-r--r--test/layoutengine/standard-testcases/table-cell_number-rows-spanned_bug38397.xml3
-rw-r--r--test/layoutengine/standard-testcases/table-cell_span-combinations.xml84
-rw-r--r--test/layoutengine/standard-testcases/table-column_missing.xml75
-rw-r--r--test/layoutengine/standard-testcases/table-row_keep-with-next2.xml69
-rw-r--r--test/layoutengine/standard-testcases/table_table-layout_fixed_2.xml2
48 files changed, 1872 insertions, 662 deletions
diff --git a/src/documentation/content/xdocs/0.93/fonts.xml b/src/documentation/content/xdocs/0.93/fonts.xml
index afe5a8558..ca6209c6d 100644
--- a/src/documentation/content/xdocs/0.93/fonts.xml
+++ b/src/documentation/content/xdocs/0.93/fonts.xml
@@ -249,6 +249,11 @@ It will display all of the font names and exit with an Exception.</p>
</li>
<li>The "kerning" and "embed-url" attributes are optional. Kerning is currently not used at all. If embedding is off, the output will position the text correctly (from the metrics file), but it will not be displayed or printed correctly unless the viewer has the applicable font available to their local system.</li>
<li>When setting the embed-url attribute for Type 1 fonts, be sure to specify the PFB (actual font data), not PFM (font metrics) file that you used to generate the XML font metrics file.</li>
+ <li>
+ If relative URLs are specified, they are evaluated relative to the value of the
+ "font-base" setting. If there is no "font-base" setting, the fonts are evaluated
+ relative to the base directory.
+ </li>
</ul>
<!--note>Cocoon users will need to setup the config, see FOPSerializer for more information.</note-->
</section>
diff --git a/src/documentation/content/xdocs/0.93/output.xml b/src/documentation/content/xdocs/0.93/output.xml
index 8c2c0213e..fdc37931d 100644
--- a/src/documentation/content/xdocs/0.93/output.xml
+++ b/src/documentation/content/xdocs/0.93/output.xml
@@ -662,8 +662,8 @@ out = proc.getOutputStream();]]></source>
<fonts><!-- described elsewhere --></fonts>
</renderer>]]></source>
<p>
- The default value for the "compression" setting is "PackBits" which
- which is a widely supported RLE compression scheme for TIFF. The set of compression
+ The default value for the "compression" setting is "PackBits" which is a
+ widely supported RLE compression scheme for TIFF. The set of compression
names to be used here matches the set that the Image I/O API uses. Note that
not all compression schemes may be available during runtime. This depends on the
actual codecs being available. Here is a list of possible values:
diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml
index 8dd4c6bb5..3e1bbd1c4 100644
--- a/src/documentation/content/xdocs/compliance.ihtml
+++ b/src/documentation/content/xdocs/compliance.ihtml
@@ -1184,11 +1184,7 @@
yes
</td>
<td align="left">
- <ul>
- <li>
- [0.20.5] must contain block-level FOs (cannot contain straight character data)
- </li>
- </ul>
+ &nbsp;
</td>
</tr>
<tr>
diff --git a/src/documentation/content/xdocs/dev/doc.xml b/src/documentation/content/xdocs/dev/doc.xml
index 742a2cc7a..a9d054316 100644
--- a/src/documentation/content/xdocs/dev/doc.xml
+++ b/src/documentation/content/xdocs/dev/doc.xml
@@ -28,7 +28,7 @@
<p>All raw documentation content is managed in the FOP SVN repository.
Updates should be committed to the repository, then the repository files are used to generate usable output.
The remaining discussions on this page assume that the SVN repository is the starting place for processing.
-The path to the documentation is xml-fop/src/documentation/content/xdocs.</p>
+The path to the documentation is src/documentation/content/xdocs.</p>
<note>All documentation is maintained on the trunk.
Although we are currently maintaining two sets of code (trunk and maintenance), there is only one set of documentation.
Most of the user and developer doc is common to the two environments, and differences are highlighted where necessary.
@@ -56,7 +56,7 @@ Maintenance branch releases either copy the trunk content to the maintenance bra
<title>Website</title>
<section id="web-background">
<title>Background</title>
- <p>The FOP web site and documentation are generated using <link href="http://xml.apache.org/forrest">Apache Forrest</link>.</p>
+ <p>The FOP web site and documentation are generated using <link href="http://forrest.apache.org">Apache Forrest</link>.</p>
<p>The following table summarizes the flow of data to the FOP website in chronological order:</p>
<table>
<tr>
@@ -69,11 +69,11 @@ Maintenance branch releases either copy the trunk content to the maintenance bra
<td>Developer commits code to FOP repository.</td>
<td>FOP repository (SVN)</td>
<td>Raw XML and other content</td>
- <td><link href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/src/documentation/content/xdocs/">ViewCVS</link></td>
+ <td><link href="http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/documentation/content/xdocs/">in SVN</link></td>
</tr>
<tr>
<td>Developer builds and uploads documentation using ForrestBot.</td>
- <td>/www/xmlgraphics.apache.org/fop on cvs.apache.org</td>
+ <td>/www/xmlgraphics.apache.org/fop on people.apache.org</td>
<td>sync-ready</td>
<td>n/a</td>
</tr>
@@ -93,18 +93,34 @@ Maintenance branch releases either copy the trunk content to the maintenance bra
The root directory of your FOP checkout contains the file "publish.xml" which is an Ant build file
that manages the build and the deployment of the FOP website. Please look into this file for
further instructions to set up ForrestBot on your machine. Basically, we're simply running ForrestBot
- manually by typing "ant -f publish.xml" once we're happy with our changes to the site. Be sure to set
- up the "deploy.settings" file as described in the "publish.xml" file. Step-by-step instructions for
- the deployment process again:
+ manually by typing "ant -f publish.xml" once we're happy with our changes to the site.
+ Step-by-step instructions for the deployment process again:
</p>
+ <note>
+ Please make sure you use Forrest from the 0.7 branch for the time being. You will need
+ to download it directly from SVN:
+ <link href="http://svn.apache.org/repos/asf/forrest/branches/forrest_07_branch">http://svn.apache.org/repos/asf/forrest/branches/forrest_07_branch</link>
+ </note>
<ul>
- <li>Modify the sources of the website and check locally with Forrest 0.7 (run "forrest run" or just "forrest").</li>
+ <li>Modify the sources of the website and check locally with Forrest (run "forrest run" or just "forrest").</li>
<li>
Once you're satisfied, run "ant -f publish.xml" to do a clean build of the website. If the build
- runs without problems, the website will be uploaded as a whole using SCP to cvs.apache.org.
+ runs without problems, the website will be uploaded as a whole using SVN to the
+ <link href="https://svn.apache.org/repos/asf/xmlgraphics/site/deploy/fop/">website staging directory in SVN</link>.
+ </li>
+ <li>
+ Then log into people.apache.org using SSH, go to the /www/xmlgraphics.apache.org
+ directory and run "svn up".
+ </li>
+ <li>
+ Wait for the next rsync cycle and check your changes in the live site.
+ (Sorry, no manual rsync available ATM)
</li>
- <li>Wait for the next rsync cycle and check your changes in the live site. (Sorry, no manual rsync available ATM)</li>
</ul>
+ <p>
+ The reason for putting the generated website in the SVN repository: The infrastructure
+ people want to be able to restore the websites themselves in case of a crash.
+ </p>
</section>
<section id="web-local-forrest">
<title>Using a Local Forrest</title>
diff --git a/src/documentation/content/xdocs/news.xml b/src/documentation/content/xdocs/news.xml
index 187a91337..efa380bb4 100644
--- a/src/documentation/content/xdocs/news.xml
+++ b/src/documentation/content/xdocs/news.xml
@@ -25,6 +25,10 @@
<version>$Revision$</version>
</header>
<body>
+ <section>
+ <title>26 January 2007 - New Committer</title>
+ <p>Welcome Jay Bryant!</p>
+ </section>
<section>
<title>9 January 2007 - Apache FOP 0.93 released</title>
<p>
diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml
index 81d7cc713..c8ab6fcc9 100644
--- a/src/documentation/content/xdocs/team.xml
+++ b/src/documentation/content/xdocs/team.xml
@@ -79,12 +79,6 @@
page</fork> for some of his private projects.</li>
<li id="jp"><link href="mailto:pietsch@apache.org">J&#x00F6;rg Pietschmann</link> (JP)</li>
<li id="ot"><link href="mailto:olegt@apache.org">Oleg Tkachenko</link> (OT)</li>
- <li id="bd">
- <link href="mailto:bdelacretaz@apache.org">Bertrand Delacretaz</link> (BD)
- is an independent consultant based in Lausanne, Switzerland, specialized in web-related
- and multimedia applications.
- See <fork href="http://www.codeconsult.ch">www.codeconsult.ch</fork> for more info.
- </li>
</ul>
</section>
<section id="contribute-active">
@@ -112,6 +106,7 @@
<ul>
<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>
<li id="sg"><link href="mailto:stanislav@apache.org">Stanislav Gorkhover</link></li>
<li id="fj"><link href="mailto:fotis@apache.org">Fotis Jannidis</link></li>
@@ -139,6 +134,7 @@
<th>JP</th>
<th>SP</th>
<th>LF</th>
+ <th>JB</th>
</tr>
<tr>
<td>Release manager</td>
@@ -151,6 +147,7 @@
<td/>
<td/>
<td/>
+ <td/>
</tr>
<tr>
<td>XSL-FO tree</td>
@@ -163,6 +160,7 @@
<td/>
<td>X</td>
<td/>
+ <td/>
</tr>
<tr>
<td>Properties</td>
@@ -175,6 +173,7 @@
<td/>
<td>X</td>
<td/>
+ <td/>
</tr>
<tr>
<td>Layout</td>
@@ -187,6 +186,7 @@
<td>X</td>
<td>X</td>
<td>X</td>
+ <td/>
</tr>
<tr>
<td>Fonts</td>
@@ -199,6 +199,7 @@
<td/>
<td/>
<td/>
+ <td/>
</tr>
<tr>
<td>SVG</td>
@@ -211,6 +212,7 @@
<td/>
<td/>
<td/>
+ <td/>
</tr>
<tr>
<td>Java2D (AWT)</td>
@@ -223,6 +225,7 @@
<td/>
<td/>
<td/>
+ <td/>
</tr>
<tr>
<td>PDF</td>
@@ -235,6 +238,7 @@
<td/>
<td/>
<td/>
+ <td>X</td>
</tr>
<tr>
<td>PostScript</td>
@@ -247,6 +251,7 @@
<td/>
<td/>
<td/>
+ <td/>
</tr>
<tr>
<td>PCL</td>
@@ -259,6 +264,7 @@
<td/>
<td/>
<td/>
+ <td/>
</tr>
<tr>
<td>RTF</td>
@@ -271,6 +277,7 @@
<td/>
<td/>
<td/>
+ <td/>
</tr>
<tr>
<td>MIF</td>
@@ -283,6 +290,7 @@
<td/>
<td/>
<td/>
+ <td/>
</tr>
<tr>
<td>Forrest</td>
@@ -295,6 +303,7 @@
<td/>
<td/>
<td/>
+ <td/>
</tr>
</table>
</section>
diff --git a/src/documentation/content/xdocs/trunk/fonts.xml b/src/documentation/content/xdocs/trunk/fonts.xml
index afe5a8558..ca6209c6d 100644
--- a/src/documentation/content/xdocs/trunk/fonts.xml
+++ b/src/documentation/content/xdocs/trunk/fonts.xml
@@ -249,6 +249,11 @@ It will display all of the font names and exit with an Exception.</p>
</li>
<li>The "kerning" and "embed-url" attributes are optional. Kerning is currently not used at all. If embedding is off, the output will position the text correctly (from the metrics file), but it will not be displayed or printed correctly unless the viewer has the applicable font available to their local system.</li>
<li>When setting the embed-url attribute for Type 1 fonts, be sure to specify the PFB (actual font data), not PFM (font metrics) file that you used to generate the XML font metrics file.</li>
+ <li>
+ If relative URLs are specified, they are evaluated relative to the value of the
+ "font-base" setting. If there is no "font-base" setting, the fonts are evaluated
+ relative to the base directory.
+ </li>
</ul>
<!--note>Cocoon users will need to setup the config, see FOPSerializer for more information.</note-->
</section>
diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java
index 91a5d603d..e7f6effe0 100644
--- a/src/java/org/apache/fop/area/AreaTreeHandler.java
+++ b/src/java/org/apache/fop/area/AreaTreeHandler.java
@@ -48,6 +48,9 @@ import org.apache.fop.layoutmgr.PageSequenceLayoutManager;
import org.apache.fop.layoutmgr.LayoutManagerMaker;
import org.apache.fop.layoutmgr.LayoutManagerMapping;
+import org.apache.fop.area.DestinationData;
+import org.apache.fop.fo.extensions.destination.Destination;
+
/**
* Area tree handler for formatting objects.
*
@@ -412,6 +415,15 @@ public class AreaTreeHandler extends FOEventHandler {
public void endDocument() throws SAXException {
finishPrevPageSequence(null);
+ // process fox:destination elements
+ ArrayList destinationList = rootFObj.getDestinationList();
+ if (destinationList != null) {
+ while(destinationList.size() > 0) {
+ Destination destination = (Destination)destinationList.remove(0);
+ DestinationData destinationData = new DestinationData(destination);
+ addOffDocumentItem(destinationData);
+ }
+ }
// process fo:bookmark-tree
BookmarkTree bookmarkTree = rootFObj.getBookmarkTree();
if (bookmarkTree != null) {
diff --git a/src/java/org/apache/fop/area/DestinationData.java b/src/java/org/apache/fop/area/DestinationData.java
new file mode 100644
index 000000000..7e59210e0
--- /dev/null
+++ b/src/java/org/apache/fop/area/DestinationData.java
@@ -0,0 +1,131 @@
+/*
+ * 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.util.List;
+
+import org.apache.fop.fo.extensions.destination.Destination;
+import org.apache.fop.area.PageViewport;
+/**
+ * An instance of this class is named destination from fox:destination
+ */
+public class DestinationData extends AbstractOffDocumentItem implements Resolvable {
+
+ // PDFReference (object reference) for this destination
+ private String goToReference;
+
+ // ID Reference for this bookmark
+ private String idRef;
+
+ // String Array to satisfy getIDRefs method
+ private String[] idRefs;
+
+ // PageViewport that the idRef item refers to
+ private PageViewport pageRef = null;
+
+ /**
+ * Create a new pdf destination data object.
+ * This is used by the destination to create a data object
+ * with a idref. During processing, this idref will be
+ * subsequently resolved to a particular PageViewport.
+ *
+ * @param destination the fo:bookmark object
+ */
+ public DestinationData(Destination destination) {
+ idRef = destination.getInternalDestination();
+ idRefs = new String[] {idRef};
+ }
+
+ /**
+ * Get the idref for this destination
+ *
+ * @return the idref for the destination
+ */
+ public String getIDRef() {
+ return idRef;
+ }
+
+ /**
+ * @see org.apache.fop.area.Resolvable#getIDRefs()
+ */
+ public String[] getIDRefs() {
+ return idRefs;
+ }
+
+ /**
+ * Get the PageViewport object that this destination refers to
+ *
+ * @return the PageViewport that this destination points to
+ */
+ public PageViewport getPageViewport() {
+ return pageRef;
+ }
+
+ /**
+ * Set the GoToReference for this destination
+ *
+ * @param goToReference the GoToReference to associate with this destination
+ */
+ public void setGoToReference(String goToReference) {
+ this.goToReference = goToReference;
+ }
+
+ /**
+ * Get the GoToReference for this destination
+ *
+ * @return the GoToReference associated with this destination
+ */
+ public String getGoToReference() {
+ return goToReference;
+ }
+
+ /**
+ * Check if this resolvable object has been resolved.
+ * For now, just return true.
+ * To do: Find a way to determine whether the destination has been resolved.
+ *
+ * @return true if this object has been resolved
+ */
+ public boolean isResolved() {
+ return true;
+ }
+
+ /**
+ * Resolves the idref of this object by getting the PageViewport
+ * object that corresponds to the IDRef
+ *
+ * @see org.apache.fop.area.Resolvable#resolveIDRef(String, List)
+ * @todo check to make sure it works if multiple bookmark-items
+ * have the same idref
+ */
+ public void resolveIDRef(String id, List pages) {
+ pageRef = (PageViewport) pages.get(0);
+ // TODO get rect area of id on page
+ }
+
+ /**
+ * @see org.apache.fop.area.OffDocumentItem#getName()
+ */
+ public String getName() {
+ return "Destination";
+ }
+
+}
+
diff --git a/src/java/org/apache/fop/fo/ElementMappingRegistry.java b/src/java/org/apache/fop/fo/ElementMappingRegistry.java
index 105a956a2..887fe8b55 100644
--- a/src/java/org/apache/fop/fo/ElementMappingRegistry.java
+++ b/src/java/org/apache/fop/fo/ElementMappingRegistry.java
@@ -90,7 +90,6 @@ public class ElementMappingRegistry {
*/
public void addElementMapping(String mappingClassName)
throws IllegalArgumentException {
-
try {
ElementMapping mapping
= (ElementMapping)Class.forName(mappingClassName).newInstance();
diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java
index 91817b87f..baf964935 100644
--- a/src/java/org/apache/fop/fo/FONode.java
+++ b/src/java/org/apache/fop/fo/FONode.java
@@ -45,6 +45,7 @@ public abstract class FONode implements Cloneable {
/** the XSL-FO namespace URI */
protected static final String FO_URI = FOElementMapping.URI;
+ protected static final String FOX_URI = ExtensionElementMapping.URI;
/** Parent FO node */
protected FONode parent;
diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java
index 4c754520d..2f1b53f1d 100644
--- a/src/java/org/apache/fop/fo/FOTreeBuilder.java
+++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java
@@ -23,6 +23,7 @@ import java.io.OutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FormattingResults;
@@ -296,9 +297,8 @@ public class FOTreeBuilder extends DefaultHandler {
+ " Please make sure you're producing a valid XSL-FO document.");
}
} else { // check that incoming node is valid for currentFObj
- if (namespaceURI.equals(FOElementMapping.URI)) {
- // currently no fox: elements to validate
- // || namespaceURI.equals(ExtensionElementMapping.URI) */) {
+ if (namespaceURI.equals(FOElementMapping.URI)
+ || namespaceURI.equals(ExtensionElementMapping.URI)) {
try {
currentFObj.validateChildNode(locator, namespaceURI, localName);
} catch (ValidationException e) {
@@ -368,7 +368,8 @@ public class FOTreeBuilder extends DefaultHandler {
throw new IllegalStateException(
"endElement() called for " + rawName
+ " where there is no current element.");
- } else if (!currentFObj.getLocalName().equals(localName)
+ } else
+ if (!currentFObj.getLocalName().equals(localName)
|| !currentFObj.getNamespaceURI().equals(uri)) {
log.warn("Mismatch: " + currentFObj.getLocalName()
+ " (" + currentFObj.getNamespaceURI()
diff --git a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
index 0b5ae827b..b5ed3e61c 100644
--- a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
+++ b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
@@ -20,7 +20,9 @@
package org.apache.fop.fo.extensions;
import org.apache.fop.fo.ElementMapping;
+import org.apache.fop.fo.FONode;
import org.apache.fop.fo.UnknownXMLObj;
+import org.apache.fop.fo.extensions.destination.Destination;
import org.apache.fop.util.QName;
import java.util.HashMap;
@@ -41,6 +43,7 @@ public class ExtensionElementMapping extends ElementMapping {
propertyAttributes.add("block-progression-unit");
propertyAttributes.add("widow-content-limit");
propertyAttributes.add("orphan-content-limit");
+ propertyAttributes.add("internal-destination");
}
/**
@@ -58,9 +61,16 @@ public class ExtensionElementMapping extends ElementMapping {
foObjs = new HashMap();
foObjs.put("outline", new UnknownXMLObj.Maker(URI));
foObjs.put("label", new UnknownXMLObj.Maker(URI));
+ foObjs.put("destination", new DestinationMaker());
}
}
+ static class DestinationMaker extends ElementMapping.Maker {
+ public FONode make(FONode parent) {
+ return new Destination(parent);
+ }
+ }
+
/** @see org.apache.fop.fo.ElementMapping#getStandardPrefix() */
public String getStandardPrefix() {
return "fox";
diff --git a/src/java/org/apache/fop/fo/extensions/destination/Destination.java b/src/java/org/apache/fop/fo/extensions/destination/Destination.java
new file mode 100644
index 000000000..b4611661e
--- /dev/null
+++ b/src/java/org/apache/fop/fo/extensions/destination/Destination.java
@@ -0,0 +1,102 @@
+/*
+ * 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.fo.extensions.destination;
+
+import org.apache.fop.fo.ValidationException;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.pagination.Root;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+/**
+ * Class for named destinations in PDF.
+ */
+public class Destination extends FONode {
+
+ private String internalDestination;
+ private Root root;
+
+ /**
+ * Constructs a Destination object (called by Maker).
+ *
+ * @param parent the parent formatting object
+ */
+ public Destination(FONode parent) {
+ super(parent);
+ root = parent.getRoot();
+ }
+
+ /**
+ * @see org.apache.fop.fo.FONode#processNode(java.lang.String, org.xml.sax.Locator,
+ * org.xml.sax.Attributes, org.apache.fop.fo.PropertyList)
+ */
+ public void processNode(String elementName, Locator locator,
+ Attributes attlist, PropertyList pList) throws FOPException {
+ internalDestination = attlist.getValue("internal-destination");
+ if (internalDestination == null || internalDestination.length() == 0) {
+ attributeError("Missing attribute: internal-destination must be specified.");
+ }
+ }
+
+ /**
+ * @see org.apache.fop.fo.FONode#endOfNode
+ */
+ protected void endOfNode() throws FOPException {
+ root.addDestination(this);
+ }
+
+ /**
+ * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
+ XSL/FOP: empty
+ */
+ protected void validateChildNode(Locator loc, String nsURI, String localName)
+ throws ValidationException {
+ invalidChildError(loc, nsURI, localName);
+ }
+
+ /**
+ * Returns the internal destination (an reference of the id property of any FO).
+ * @return the internal destination
+ */
+ public String getInternalDestination() {
+ return internalDestination;
+ }
+
+ /** @see org.apache.fop.fo.FONode#getNamespaceURI() */
+ public String getNamespaceURI() {
+ return ExtensionElementMapping.URI;
+ }
+
+ /** @see org.apache.fop.fo.FONode#getNormalNamespacePrefix() */
+ public String getNormalNamespacePrefix() {
+ return "fox";
+ }
+
+ /** @see org.apache.fop.fo.FONode#getLocalName() */
+ public String getLocalName() {
+ return "destination";
+ }
+
+}
+
diff --git a/src/java/org/apache/fop/fo/extensions/destination/package.html b/src/java/org/apache/fop/fo/extensions/destination/package.html
new file mode 100644
index 000000000..59cbb493d
--- /dev/null
+++ b/src/java/org/apache/fop/fo/extensions/destination/package.html
@@ -0,0 +1,23 @@
+<!--
+ 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$ -->
+<HTML>
+<TITLE>org.apache.fop.destination Package</TITLE>
+<BODY>
+<P>Classes to support named destinations (only relevant for PDF output)</P>
+</BODY>
+</HTML>
diff --git a/src/java/org/apache/fop/fo/flow/Block.java b/src/java/org/apache/fop/fo/flow/Block.java
index 48a8d3bdf..6beffdfe5 100644
--- a/src/java/org/apache/fop/fo/flow/Block.java
+++ b/src/java/org/apache/fop/fo/flow/Block.java
@@ -296,25 +296,27 @@ public class Block extends FObjMixed {
* fo:inline-container."
*/
protected void validateChildNode(Locator loc, String nsURI, String localName)
- throws ValidationException {
- if (FO_URI.equals(nsURI) && localName.equals("marker")) {
- if (blockOrInlineItemFound || initialPropertySetFound) {
- nodesOutOfOrderError(loc, "fo:marker",
- "initial-property-set? (#PCDATA|%inline;|%block;)");
- }
- } else if (FO_URI.equals(nsURI) && localName.equals("initial-property-set")) {
- if (initialPropertySetFound) {
- tooManyNodesError(loc, "fo:initial-property-set");
- } else if (blockOrInlineItemFound) {
- nodesOutOfOrderError(loc, "fo:initial-property-set",
- "(#PCDATA|%inline;|%block;)");
+ throws ValidationException {
+ if (FO_URI.equals(nsURI)) {
+ if (localName.equals("marker")) {
+ if (blockOrInlineItemFound || initialPropertySetFound) {
+ nodesOutOfOrderError(loc, "fo:marker",
+ "initial-property-set? (#PCDATA|%inline;|%block;)");
+ }
+ } else if (localName.equals("initial-property-set")) {
+ if (initialPropertySetFound) {
+ tooManyNodesError(loc, "fo:initial-property-set");
+ } else if (blockOrInlineItemFound) {
+ nodesOutOfOrderError(loc, "fo:initial-property-set",
+ "(#PCDATA|%inline;|%block;)");
+ } else {
+ initialPropertySetFound = true;
+ }
+ } else if (isBlockOrInlineItem(nsURI, localName)) {
+ blockOrInlineItemFound = true;
} else {
- initialPropertySetFound = true;
+ invalidChildError(loc, nsURI, localName);
}
- } else if (isBlockOrInlineItem(nsURI, localName)) {
- blockOrInlineItemFound = true;
- } else {
- invalidChildError(loc, nsURI, localName);
}
}
diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java
index 47ee3096a..23f9cd391 100644
--- a/src/java/org/apache/fop/fo/pagination/Root.java
+++ b/src/java/org/apache/fop/fo/pagination/Root.java
@@ -21,6 +21,7 @@ package org.apache.fop.fo.pagination;
// java
import java.util.List;
+import java.util.ArrayList;
import org.xml.sax.Locator;
@@ -31,6 +32,7 @@ import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.pagination.bookmarks.BookmarkTree;
+import org.apache.fop.fo.extensions.destination.Destination;
/**
* The fo:root formatting object. Contains page masters, page-sequences.
@@ -43,6 +45,7 @@ public class Root extends FObj {
private LayoutMasterSet layoutMasterSet;
private Declarations declarations;
private BookmarkTree bookmarkTree = null;
+ private ArrayList destinationList;
private List pageSequences;
// temporary until above list populated
@@ -64,7 +67,7 @@ public class Root extends FObj {
*/
public Root(FONode parent) {
super(parent);
- pageSequences = new java.util.ArrayList();
+ pageSequences = new ArrayList();
if (parent != null) {
//throw new FOPException("root must be root element");
}
@@ -252,6 +255,25 @@ public class Root extends FObj {
}
/**
+ * Add a Destination object to this FO
+ * @param destination the Destination object to add
+ */
+ public void addDestination(Destination destination) {
+ if (destinationList == null) {
+ destinationList = new ArrayList();
+ }
+ destinationList.add(destination);
+ }
+
+ /**
+ * Public accessor for the list of Destination objects for this FO
+ * @return the Destination object
+ */
+ public ArrayList getDestinationList() {
+ return destinationList;
+ }
+
+ /**
* Public accessor for the BookmarkTree object for this FO
* @return the BookmarkTree object
*/
diff --git a/src/java/org/apache/fop/image/JpegImage.java b/src/java/org/apache/fop/image/JpegImage.java
index 820a728f9..3ad745281 100644
--- a/src/java/org/apache/fop/image/JpegImage.java
+++ b/src/java/org/apache/fop/image/JpegImage.java
@@ -189,15 +189,20 @@ public class JpegImage extends AbstractFopImage {
}
try {
iccProfile = ICC_Profile.getInstance(iccStream.toByteArray());
- } catch (Exception e) {
- log.error("Invalid ICC profile: " + e, e);
- return false;
+ } catch (IllegalArgumentException iae) {
+ log.warn("An ICC profile is present but it is invalid ("
+ + iae.getMessage() + "). The color profile will be ignored. ("
+ + this.getOriginalURI() + ")");
}
} else if (this.colorSpace == null) {
log.error("ColorSpace not specified for JPEG image");
return false;
}
if (hasAPPEMarker && this.colorSpace.getType() == ColorSpace.TYPE_CMYK) {
+ if (log.isDebugEnabled()) {
+ log.debug("JPEG has an Adobe APPE marker. Note: CMYK Image will be inverted. ("
+ + this.getOriginalURI() + ")");
+ }
this.invertImage = true;
}
return true;
diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
index e63345f77..117893304 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
@@ -34,6 +34,7 @@ import org.apache.fop.area.Trait;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.BlockContainer;
import org.apache.fop.fo.properties.CommonAbsolutePosition;
+import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
import org.apache.fop.area.CTM;
import org.apache.fop.datatypes.FODimension;
import org.apache.fop.datatypes.Length;
@@ -989,9 +990,12 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
*/
public boolean mustKeepTogether() {
//TODO Keeps will have to be more sophisticated sooner or later
- return ((BlockLevelLayoutManager)getParent()).mustKeepTogether()
- || !getBlockContainerFO().getKeepTogether().getWithinPage().isAuto()
- || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto();
+ return (!getBlockContainerFO().getKeepTogether().getWithinPage().isAuto()
+ || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto()
+ || (getParent() instanceof BlockLevelLayoutManager
+ && ((BlockLevelLayoutManager) getParent()).mustKeepTogether())
+ || (getParent() instanceof InlineLayoutManager
+ && ((InlineLayoutManager) getParent()).mustKeepTogether()));
}
/**
diff --git a/src/java/org/apache/fop/layoutmgr/KnuthPossPosIter.java b/src/java/org/apache/fop/layoutmgr/KnuthPossPosIter.java
index a3b48c26a..9553959b0 100644
--- a/src/java/org/apache/fop/layoutmgr/KnuthPossPosIter.java
+++ b/src/java/org/apache/fop/layoutmgr/KnuthPossPosIter.java
@@ -28,8 +28,8 @@ public class KnuthPossPosIter extends PositionIterator {
/**
* Main constructor
* @param elementList List of Knuth elements
- * @param startPos starting position
- * @param endPos ending position
+ * @param startPos starting position, inclusive
+ * @param endPos ending position, exclusive
*/
public KnuthPossPosIter(List elementList, int startPos, int endPos) {
super(elementList.listIterator(startPos));
diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
index db4663df6..de779b011 100644
--- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
+++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
@@ -28,6 +28,7 @@ import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.fo.FOElementMapping;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.FObjMixed;
@@ -85,6 +86,8 @@ import org.apache.fop.layoutmgr.list.ListItemLayoutManager;
import org.apache.fop.layoutmgr.table.TableLayoutManager;
import org.apache.fop.util.CharUtilities;
+import org.apache.fop.fo.extensions.destination.Destination;
+
/**
* The default LayoutManager maker class
*/
@@ -146,7 +149,13 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
public void makeLayoutManagers(FONode node, List lms) {
Maker maker = (Maker) makers.get(node.getClass());
if (maker == null) {
- log.error("No LayoutManager maker for class " + node.getClass());
+ if (FOElementMapping.URI.equals(node.getNamespaceURI())) {
+ log.error("No LayoutManager maker for class " + node.getClass());
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping the creation of a layout manager for " + node.getClass());
+ }
+ }
} else {
maker.make(node, lms);
}
diff --git a/src/java/org/apache/fop/layoutmgr/SpaceResolver.java b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java
index 9fd7c9f21..c59911bf1 100644
--- a/src/java/org/apache/fop/layoutmgr/SpaceResolver.java
+++ b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java
@@ -57,7 +57,7 @@ public class SpaceResolver {
* @param isFirst Resolution at the beginning of a (full) element list
* @param isLast Resolution at the end of a (full) element list
*/
- public SpaceResolver(List first, BreakElement breakPoss, List second,
+ private SpaceResolver(List first, BreakElement breakPoss, List second,
boolean isFirst, boolean isLast) {
this.isFirst = isFirst;
this.isLast = isLast;
@@ -494,7 +494,7 @@ public class SpaceResolver {
* Position class for break possibilities. It is used to notify layout manager about the
* effective spaces and conditional lengths.
*/
- public class SpaceHandlingBreakPosition extends Position {
+ public static class SpaceHandlingBreakPosition extends Position {
private SpaceResolver resolver;
private Position originalPosition;
@@ -566,7 +566,7 @@ public class SpaceResolver {
* Position class for no-break situations. It is used to notify layout manager about the
* effective spaces and conditional lengths.
*/
- public class SpaceHandlingPosition extends Position {
+ public static class SpaceHandlingPosition extends Position {
private SpaceResolver resolver;
diff --git a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java
index b7f29a744..eb91f7175 100644
--- a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java
+++ b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java
@@ -221,8 +221,14 @@ public class ColumnSetup {
public int getXOffset(int col, PercentBaseContext context) {
int xoffset = 0;
for (int i = col; --i >= 0;) {
- if (colWidths.get(i) != null) {
- xoffset += ((Length) colWidths.get(i)).getValue(context);
+ int effCol;
+ if (i < colWidths.size()) {
+ effCol = i;
+ } else {
+ effCol = colWidths.size() - 1;
+ }
+ if (colWidths.get(effCol) != null) {
+ xoffset += ((Length) colWidths.get(effCol)).getValue(context);
}
}
return xoffset;
diff --git a/src/java/org/apache/fop/layoutmgr/table/GridUnit.java b/src/java/org/apache/fop/layoutmgr/table/GridUnit.java
index b472acf49..beb41f35b 100644
--- a/src/java/org/apache/fop/layoutmgr/table/GridUnit.java
+++ b/src/java/org/apache/fop/layoutmgr/table/GridUnit.java
@@ -345,11 +345,24 @@ public class GridUnit {
buffer.append("GridUnit:");
if (colSpanIndex > 0) {
buffer.append(" colSpan=").append(colSpanIndex);
+ if (isLastGridUnitColSpan()) {
+ buffer.append("(last)");
+ }
}
if (rowSpanIndex > 0) {
buffer.append(" rowSpan=").append(rowSpanIndex);
+ if (isLastGridUnitRowSpan()) {
+ buffer.append("(last)");
+ }
}
buffer.append(" startCol=").append(startCol);
+ if (!isPrimary() && getPrimary() != null) {
+ buffer.append(" primary=").append(getPrimary().getStartRow());
+ buffer.append("/").append(getPrimary().getStartCol());
+ if (getPrimary().getCell() != null) {
+ buffer.append(" id=" + getPrimary().getCell().getId());
+ }
+ }
buffer.append(" flags=").append(Integer.toBinaryString(flags));
return buffer.toString();
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
index d8c294a07..4eac98953 100644
--- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
+++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
@@ -42,12 +42,16 @@ class RowPainter {
/** Currently handled row (= last encountered row). */
private EffRow lastRow = null;
private LayoutContext layoutContext;
- private int lastRowHeight = 0;
/**
* For each part of the table (header, footer, body), index of the first row of that
* part present on the current page.
*/
private int[] firstRow = new int[3];
+ /**
+ * Keeps track of the y-offsets of each row on a page (for body, header and footer separately).
+ * This is particularly needed for spanned cells where you need to know the y-offset
+ * of the starting row when the area is generated at the time the cell is closed.
+ */
private Map[] rowOffsets = new Map[] {new java.util.HashMap(),
new java.util.HashMap(), new java.util.HashMap()};
@@ -66,9 +70,9 @@ class RowPainter {
private int[] end;
/**
* Length, for each column, of the elements from the current cell put on the
- * current page.
+ * current page. This is the corresponding area's bpd.
*/
- private int[] partLength;
+ private int[] partBPD;
private TableContentLayoutManager tclm;
public RowPainter(TableContentLayoutManager tclm, LayoutContext layoutContext) {
@@ -78,7 +82,7 @@ class RowPainter {
this.primaryGridUnits = new PrimaryGridUnit[colCount];
this.start = new int[colCount];
this.end = new int[colCount];
- this.partLength = new int[colCount];
+ this.partBPD = new int[colCount];
Arrays.fill(firstRow, -1);
Arrays.fill(end, -1);
}
@@ -87,12 +91,9 @@ class RowPainter {
return this.accumulatedBPD;
}
- public void notifyEndOfSequence() {
- this.accumulatedBPD += lastRowHeight; //for last row
- }
-
public void notifyNestedPenaltyArea(int length) {
- this.lastRowHeight += length;
+ yoffset += length;
+ accumulatedBPD += length;
}
/**
@@ -104,8 +105,6 @@ class RowPainter {
public void handleTableContentPosition(TableContentPosition tcpos) {
if (lastRow != tcpos.row && lastRow != null) {
addAreasAndFlushRow(false);
- yoffset += lastRowHeight;
- this.accumulatedBPD += lastRowHeight;
}
if (log.isDebugEnabled()) {
log.debug("===handleTableContentPosition(" + tcpos);
@@ -144,12 +143,12 @@ class RowPainter {
* lying on the current page must be drawn.
*
* @param forcedFlush true if the elements must be drawn even if the row isn't
- * finished yet (last row on the page)
+ * finished yet (last row on the page), or if the row is the last of the current table
+ * part
* @return the height of the (grid) row
*/
public int addAreasAndFlushRow(boolean forcedFlush) {
int actualRowHeight = 0;
- int readyCount = 0;
int bt = lastRow.getBodyType();
if (log.isDebugEnabled()) {
@@ -160,117 +159,142 @@ class RowPainter {
for (int i = 0; i < primaryGridUnits.length; i++) {
if ((primaryGridUnits[i] != null)
&& (forcedFlush || (end[i] == primaryGridUnits[i].getElements().size() - 1))) {
- if (log.isTraceEnabled()) {
- log.trace("getting len for " + i + " "
- + start[i] + "-" + end[i]);
- }
- readyCount++;
- int len = ElementListUtils.calcContentLength(
- primaryGridUnits[i].getElements(), start[i], end[i]);
- partLength[i] = len;
- if (log.isTraceEnabled()) {
- log.trace("len of part: " + len);
- }
-
- if (start[i] == 0) {
- LengthRangeProperty bpd = primaryGridUnits[i].getCell()
- .getBlockProgressionDimension();
- if (!bpd.getMinimum(tclm.getTableLM()).isAuto()) {
- int min = bpd.getMinimum(tclm.getTableLM())
- .getLength().getValue(tclm.getTableLM());
- if (min > 0) {
- len = Math.max(len, min);
- }
- }
- if (!bpd.getOptimum(tclm.getTableLM()).isAuto()) {
- int opt = bpd.getOptimum(tclm.getTableLM())
- .getLength().getValue(tclm.getTableLM());
- if (opt > 0) {
- len = Math.max(len, opt);
- }
- }
- if (primaryGridUnits[i].getRow() != null) {
- bpd = primaryGridUnits[i].getRow().getBlockProgressionDimension();
- if (!bpd.getMinimum(tclm.getTableLM()).isAuto()) {
- int min = bpd.getMinimum(tclm.getTableLM()).getLength()
- .getValue(tclm.getTableLM());
- if (min > 0) {
- len = Math.max(len, min);
- }
- }
- }
- }
-
- // Add the padding if any
- len += primaryGridUnits[i].getBorders()
- .getPaddingBefore(false, primaryGridUnits[i].getCellLM());
- len += primaryGridUnits[i].getBorders()
- .getPaddingAfter(false, primaryGridUnits[i].getCellLM());
-
- //Now add the borders to the contentLength
- if (tclm.isSeparateBorderModel()) {
- len += primaryGridUnits[i].getBorders().getBorderBeforeWidth(false);
- len += primaryGridUnits[i].getBorders().getBorderAfterWidth(false);
- } else {
- len += primaryGridUnits[i].getHalfMaxBeforeBorderWidth();
- len += primaryGridUnits[i].getHalfMaxAfterBorderWidth();
- }
- int startRow = Math.max(primaryGridUnits[i].getStartRow(), firstRow[bt]);
- Integer storedOffset = (Integer)rowOffsets[bt].get(new Integer(startRow));
- int effYOffset;
- if (storedOffset != null) {
- effYOffset = storedOffset.intValue();
- } else {
- effYOffset = yoffset;
- }
- len -= yoffset - effYOffset;
- actualRowHeight = Math.max(actualRowHeight, len);
+ actualRowHeight = Math.max(actualRowHeight, computeSpanHeight(
+ primaryGridUnits[i], start[i], end[i], i, bt));
}
}
- if (readyCount == 0) {
- return 0;
- }
actualRowHeight += 2 * tclm.getTableLM().getHalfBorderSeparationBPD();
- lastRowHeight = actualRowHeight;
//Add areas for row
tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(), yoffset);
for (int i = 0; i < primaryGridUnits.length; i++) {
GridUnit currentGU = lastRow.safelyGetGridUnit(i);
- if ((primaryGridUnits[i] != null)
- && (forcedFlush || (end[i] == primaryGridUnits[i].getElements().size() - 1)
- && (currentGU == null || currentGU.isLastGridUnitRowSpan()))
- || (primaryGridUnits[i] == null && currentGU != null)) {
- //the last line in the "if" above is to avoid a premature end of an
- //row-spanned cell because no GridUnitParts are generated after a cell is
- //finished with its content. currentGU can be null if there's no grid unit
- //at this place in the current row (empty cell and no borders to process)
- if (log.isDebugEnabled()) {
- log.debug((forcedFlush ? "FORCED " : "") + "flushing..." + i + " "
- + start[i] + "-" + end[i]);
- }
- PrimaryGridUnit gu = primaryGridUnits[i];
- if (gu == null
- && !currentGU.isEmpty()
- && currentGU.getColSpanIndex() == 0
- && currentGU.isLastGridUnitColSpan()
- && (forcedFlush || currentGU.isLastGridUnitRowSpan())) {
- gu = currentGU.getPrimary();
- }
- if (gu != null) {
- addAreasForCell(gu, start[i], end[i],
- lastRow,
- partLength[i], actualRowHeight);
+ //currentGU can be null if there's no grid unit
+ //at this place in the current row (empty cell and no borders to process)
+
+ if (primaryGridUnits[i] != null) {
+ if (forcedFlush || ((end[i] == primaryGridUnits[i].getElements().size() - 1)
+ && (currentGU == null || currentGU.isLastGridUnitRowSpan()))) {
+ //the last line in the "if" above is to avoid a premature end of a
+ //row-spanned cell because no GridUnitParts are generated after a cell is
+ //finished with its content.
+ //See table-cell_number-rows-spanned_bug38397.xml
+ addAreasForCell(primaryGridUnits[i], start[i], end[i], lastRow, partBPD[i],
+ actualRowHeight);
primaryGridUnits[i] = null;
start[i] = 0;
end[i] = -1;
- partLength[i] = 0;
+ partBPD[i] = 0;
}
+ } else if (currentGU != null && !currentGU.isEmpty()
+ && currentGU.getColSpanIndex() == 0
+ && (forcedFlush || currentGU.isLastGridUnitRowSpan())) {
+ //A row-spanned cell has finished contributing content on the previous page
+ //and now still has to cause grid units to be painted.
+ //See table-cell_page-break_span.xml
+ addAreasForCell(currentGU.getPrimary(), start[i], end[i], lastRow, partBPD[i],
+ actualRowHeight);
+ start[i] = 0;
+ end[i] = -1;
+ partBPD[i] = 0;
}
}
+ yoffset += actualRowHeight;
+ accumulatedBPD += actualRowHeight;
+ if (forcedFlush) {
+ // Either the end of the page is reached, then this was the last call of this
+ // method and we no longer care about lastRow; or the end of a table-part
+ // (header, footer, body) has been reached, and the next row will anyway be
+ // different from the current one, and this is unnecessary to recall this
+ // method in the first lines of handleTableContentPosition, so we may reset
+ // lastRow
+ lastRow = null;
+ }
return actualRowHeight;
}
+ /**
+ * Computes the total height of the part of the given cell spanning on the current
+ * active row, including borders and paddings. The bpd is also stored in partBPD, and
+ * it is ensured that the cell's or row's explicit height is respected. yoffset is
+ * updated accordingly.
+ *
+ * @param pgu primary grid unit corresponding to the cell
+ * @param start index of the first element of the cell occuring on the current page
+ * @param end index of the last element of the cell occuring on the current page
+ * @param columnIndex column index of the cell
+ * @param bodyType {@link TableRowIterator#HEADER}, {@link TableRowIterator#FOOTER}, or
+ * {@link TableRowIterator#BODY}
+ * @return the cell's height
+ */
+ private int computeSpanHeight(PrimaryGridUnit pgu, int start, int end, int columnIndex,
+ int bodyType) {
+ if (log.isTraceEnabled()) {
+ log.trace("getting len for " + columnIndex + " "
+ + start + "-" + end);
+ }
+ int len = ElementListUtils.calcContentLength(
+ pgu.getElements(), start, end);
+ partBPD[columnIndex] = len;
+ if (log.isTraceEnabled()) {
+ log.trace("len of part: " + len);
+ }
+
+ if (start == 0) {
+ LengthRangeProperty bpd = pgu.getCell()
+ .getBlockProgressionDimension();
+ if (!bpd.getMinimum(tclm.getTableLM()).isAuto()) {
+ int min = bpd.getMinimum(tclm.getTableLM())
+ .getLength().getValue(tclm.getTableLM());
+ if (min > 0) {
+ len = Math.max(len, min);
+ }
+ }
+ if (!bpd.getOptimum(tclm.getTableLM()).isAuto()) {
+ int opt = bpd.getOptimum(tclm.getTableLM())
+ .getLength().getValue(tclm.getTableLM());
+ if (opt > 0) {
+ len = Math.max(len, opt);
+ }
+ }
+ if (pgu.getRow() != null) {
+ bpd = pgu.getRow().getBlockProgressionDimension();
+ if (!bpd.getMinimum(tclm.getTableLM()).isAuto()) {
+ int min = bpd.getMinimum(tclm.getTableLM()).getLength()
+ .getValue(tclm.getTableLM());
+ if (min > 0) {
+ len = Math.max(len, min);
+ }
+ }
+ }
+ }
+
+ // Add the padding if any
+ len += pgu.getBorders()
+ .getPaddingBefore(false, pgu.getCellLM());
+ len += pgu.getBorders()
+ .getPaddingAfter(false, pgu.getCellLM());
+
+ //Now add the borders to the contentLength
+ if (tclm.isSeparateBorderModel()) {
+ len += pgu.getBorders().getBorderBeforeWidth(false);
+ len += pgu.getBorders().getBorderAfterWidth(false);
+ } else {
+ len += pgu.getHalfMaxBeforeBorderWidth();
+ len += pgu.getHalfMaxAfterBorderWidth();
+ }
+ int startRow = Math.max(pgu.getStartRow(), firstRow[bodyType]);
+ Integer storedOffset = (Integer)rowOffsets[bodyType].get(new Integer(startRow));
+ int effYOffset;
+ if (storedOffset != null) {
+ effYOffset = storedOffset.intValue();
+ } else {
+ effYOffset = yoffset;
+ }
+ len -= yoffset - effYOffset;
+ return len;
+ }
+
private void addAreasForCell(PrimaryGridUnit pgu, int startPos, int endPos,
EffRow row, int contentHeight, int rowHeight) {
int bt = row.getBodyType();
@@ -278,12 +302,33 @@ class RowPainter {
firstRow[bt] = row.getIndex();
}
//Determine the first row in this sequence
- int startRow = Math.max(pgu.getStartRow(), firstRow[bt]);
+ int startRowIndex = Math.max(pgu.getStartRow(), firstRow[bt]);
+ int lastRowIndex = lastRow.getIndex();
+
+ // In collapsing-border model, if the cell spans over several columns/rows then
+ // dedicated areas will be created for each grid unit to hold the corresponding
+ // borders. For that we need to know the height of each grid unit, that is of each
+ // grid row spanned over by the cell
+ int[] spannedGridRowHeights = null;
+ if (!tclm.getTableLM().getTable().isSeparateBorderModel() && pgu.hasSpanning()) {
+ spannedGridRowHeights = new int[lastRowIndex - startRowIndex + 1];
+ int prevOffset = ((Integer)rowOffsets[bt].get(new Integer(startRowIndex))).intValue();
+ for (int i = 0; i < lastRowIndex - startRowIndex; i++) {
+ int newOffset = ((Integer) rowOffsets[bt].get(new Integer(startRowIndex + i + 1)))
+ .intValue();
+ spannedGridRowHeights[i] = newOffset - prevOffset;
+ prevOffset = newOffset;
+ }
+ spannedGridRowHeights[lastRowIndex - startRowIndex] = rowHeight;
+ }
+
//Determine y offset for the cell
- Integer offset = (Integer)rowOffsets[bt].get(new Integer(startRow));
+ Integer offset = (Integer)rowOffsets[bt].get(new Integer(startRowIndex));
while (offset == null) {
- startRow--;
- offset = (Integer)rowOffsets[bt].get(new Integer(startRow));
+ //TODO Figure out what this does and when it's triggered
+ //This block is probably never used, at least it's not triggered by any of our tests
+ startRowIndex--;
+ offset = (Integer)rowOffsets[bt].get(new Integer(startRowIndex));
}
int effYOffset = offset.intValue();
int effCellHeight = rowHeight;
@@ -306,7 +351,8 @@ class RowPainter {
SpaceResolver.performConditionalsNotification(pgu.getElements(),
startPos, endPos, prevBreak);
}
- cellLM.addAreas(new KnuthPossPosIter(pgu.getElements(),
- startPos, endPos + 1), layoutContext);
+ cellLM.addAreas(new KnuthPossPosIter(pgu.getElements(), startPos, endPos + 1),
+ layoutContext, spannedGridRowHeights, startRowIndex - pgu.getStartRow(),
+ lastRowIndex - pgu.getStartRow() + 1);
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
index 223d80a7f..2f17a6a25 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
@@ -16,13 +16,14 @@
*/
/* $Id$ */
-
+
package org.apache.fop.layoutmgr.table;
import java.util.LinkedList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.Table;
import org.apache.fop.fo.flow.TableCell;
@@ -48,20 +49,20 @@ import org.apache.fop.traits.MinOptMax;
* LayoutManager for a table-cell FO.
* A cell contains blocks. These blocks fill the cell.
*/
-public class TableCellLayoutManager extends BlockStackingLayoutManager
+public class TableCellLayoutManager extends BlockStackingLayoutManager
implements BlockLevelLayoutManager {
/**
* logging instance
*/
private static Log log = LogFactory.getLog(TableCellLayoutManager.class);
-
- private PrimaryGridUnit gridUnit;
-
+
+ private PrimaryGridUnit primaryGridUnit;
+
private Block curBlockArea;
private int inRowIPDOffset;
-
+
private int xoffset;
private int yoffset;
private int cellIPD;
@@ -75,23 +76,23 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
/**
* Create a new Cell layout manager.
* @param node table-cell FO for which to create the LM
- * @param pgu primary grid unit for the cell
+ * @param pgu primary grid unit for the cell
*/
public TableCellLayoutManager(TableCell node, PrimaryGridUnit pgu) {
super(node);
fobj = node;
- this.gridUnit = pgu;
+ this.primaryGridUnit = pgu;
}
/** @return the table-cell FO */
public TableCell getTableCell() {
return (TableCell)this.fobj;
}
-
+
private boolean isSeparateBorderModel() {
return getTable().isSeparateBorderModel();
}
-
+
/** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */
public void initialize() {
borderAndPaddingBPD = 0;
@@ -107,7 +108,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
borderAndPaddingBPD += getTableCell().getCommonBorderPaddingBackground()
.getPaddingAfter(false, this);
}
-
+
/**
* @return the table owning this cell
*/
@@ -118,12 +119,12 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
}
return (Table)node;
}
-
+
/** @see org.apache.fop.layoutmgr.BlockStackingLayoutManager#getIPIndents() */
protected int getIPIndents() {
int iIndents = 0;
- int[] startEndBorderWidths = gridUnit.getStartEndBorderWidths();
+ int[] startEndBorderWidths = primaryGridUnit.getStartEndBorderWidths();
startBorderWidth += startEndBorderWidths[0];
endBorderWidth += startEndBorderWidths[1];
iIndents += startBorderWidth;
@@ -135,14 +136,14 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
iIndents += getTableCell().getCommonBorderPaddingBackground().getPaddingEnd(false, this);
return iIndents;
}
-
+
/**
* @see org.apache.fop.layoutmgr.LayoutManager
*/
public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
MinOptMax stackLimit = new MinOptMax(context.getStackLimit());
- referenceIPD = context.getRefIPD();
+ referenceIPD = context.getRefIPD();
cellIPD = referenceIPD;
cellIPD -= getIPIndents();
if (isSeparateBorderModel()) {
@@ -173,7 +174,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
}
-
+
if (returnedList.size() == 1
&& ((ListElement)returnedList.getFirst()).isForcedBreak()) {
// a descendant of this block has break-before
@@ -193,13 +194,13 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
//Space resolution
SpaceResolver.resolveElementList(returnList);
-
+
return returnList;
} else {
if (prevLM != null) {
// there is a block handled by prevLM
// before the one handled by curLM
- if (mustKeepTogether()
+ if (mustKeepTogether()
|| context.isKeepWithNextPending()
|| childLC.isKeepWithPreviousPending()) {
//Clear keep pending flag
@@ -242,7 +243,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
//Space resolution
SpaceResolver.resolveElementList(returnList);
-
+
return returnList;
}
}
@@ -256,16 +257,16 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
returnedList = new LinkedList();
wrapPositionElements(contentList, returnList);
-
+
//Space resolution
SpaceResolver.resolveElementList(returnList);
-
+
getPSLM().notifyEndOfLayout(((TableCell)getFObj()).getId());
-
+
setFinished(true);
return returnList;
}
-
+
/**
* Set the y offset of this cell.
* This offset is used to set the absolute position of the cell.
@@ -294,7 +295,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
public void setInRowIPDOffset(int off) {
this.inRowIPDOffset = off;
}
-
+
/**
* Set the content height for this cell. This method is used during
* addAreas() stage.
@@ -304,7 +305,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
public void setContentHeight(int h) {
usedBPD = h;
}
-
+
/**
* Set the row height that contains this cell. This method is used during
* addAreas() stage.
@@ -328,96 +329,107 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
} else {
bpd -= gu.getPrimary().getHalfMaxBorderWidth();
}
- CommonBorderPaddingBackground cbpb
- = gu.getCell().getCommonBorderPaddingBackground();
+ CommonBorderPaddingBackground cbpb
+ = gu.getCell().getCommonBorderPaddingBackground();
bpd -= cbpb.getPaddingBefore(false, this);
bpd -= cbpb.getPaddingAfter(false, this);
bpd -= 2 * ((TableLayoutManager)getParent()).getHalfBorderSeparationBPD();
return bpd;
}
-
+
/**
- * Add the areas for the break points.
- * The cell contains block stacking layout managers
- * that add block areas.
- *
+ * Add the areas for the break points. The cell contains block stacking layout
+ * managers that add block areas.
+ *
+ * <p>In the collapsing-border model, the borders of a cell that spans over several
+ * rows or columns are drawn separately for each grid unit. Therefore we must know the
+ * height of each grid row spanned over by the cell. Also, if the cell is broken over
+ * two pages we must know which spanned grid rows are present on the current page.</p>
+ *
* @param parentIter the iterator of the break positions
* @param layoutContext the layout context for adding the areas
+ * @param spannedGridRowHeights in collapsing-border model for a spanning cell, height
+ * of each spanned grid row
+ * @param startRow first grid row on the current page spanned over by the cell,
+ * inclusive
+ * @param endRow last grid row on the current page spanned over by the cell, exclusive
*/
public void addAreas(PositionIterator parentIter,
- LayoutContext layoutContext) {
+ LayoutContext layoutContext,
+ int[] spannedGridRowHeights,
+ int startRow,
+ int endRow) {
getParentArea(null);
getPSLM().addIDToPage(getTableCell().getId());
if (isSeparateBorderModel()) {
if (!emptyCell || getTableCell().showEmptyCells()) {
- TraitSetter.addBorders(curBlockArea,
- getTableCell().getCommonBorderPaddingBackground(), this);
+ TraitSetter.addBorders(curBlockArea, getTableCell().getCommonBorderPaddingBackground(),
+ false, false, false, false, this);
+ TraitSetter.addPadding(curBlockArea, getTableCell().getCommonBorderPaddingBackground(),
+ false, false, false, false, this);
}
} else {
- boolean[] outer = new boolean[] {
- gridUnit.getFlag(GridUnit.FIRST_IN_TABLE),
- gridUnit.getFlag(GridUnit.LAST_IN_TABLE),
- gridUnit.getFlag(GridUnit.IN_FIRST_COLUMN),
- gridUnit.getFlag(GridUnit.IN_LAST_COLUMN)};
- if (!gridUnit.hasSpanning()) {
+ if (!primaryGridUnit.hasSpanning()) {
//Can set the borders directly if there's no span
- TraitSetter.addCollapsingBorders(curBlockArea,
- gridUnit.getBorders(), outer, this);
+ boolean[] outer = new boolean[] {
+ primaryGridUnit.getFlag(GridUnit.FIRST_IN_TABLE),
+ primaryGridUnit.getFlag(GridUnit.LAST_IN_TABLE),
+ primaryGridUnit.getFlag(GridUnit.IN_FIRST_COLUMN),
+ primaryGridUnit.getFlag(GridUnit.IN_LAST_COLUMN)};
+ TraitSetter.addCollapsingBorders(curBlockArea,
+ primaryGridUnit.getBorders(), outer, this);
} else {
+ boolean[] outer = new boolean[4];
int dy = yoffset;
- for (int y = 0; y < gridUnit.getRows().size(); y++) {
- GridUnit[] gridUnits = (GridUnit[])gridUnit.getRows().get(y);
+ for (int y = startRow; y < endRow; y++) {
+ GridUnit[] gridUnits = (GridUnit[])primaryGridUnit.getRows().get(y);
int dx = xoffset;
- int lastRowHeight = 0;
for (int x = 0; x < gridUnits.length; x++) {
GridUnit gu = gridUnits[x];
if (!gu.hasBorders()) {
continue;
}
-
+
//Blocks for painting grid unit borders
Block block = new Block();
block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
block.setPositioning(Block.ABSOLUTE);
- int bpd = getContentHeight(gu);
- if (isSeparateBorderModel()) {
- bpd += (gu.getBorders().getBorderBeforeWidth(false));
- bpd += (gu.getBorders().getBorderAfterWidth(false));
- } else {
- bpd += gridUnit.getHalfMaxBeforeBorderWidth()
- - (gu.getBorders().getBorderBeforeWidth(false) / 2);
- bpd += gridUnit.getHalfMaxAfterBorderWidth()
- - (gu.getBorders().getBorderAfterWidth(false) / 2);
- }
+ int bpd = spannedGridRowHeights[y - startRow];
+ bpd -= gu.getBorders().getBorderBeforeWidth(false) / 2;
+ bpd -= gu.getBorders().getBorderAfterWidth(false) / 2;
block.setBPD(bpd);
- lastRowHeight = rowHeight;
- int ipd = gu.getColumn().getColumnWidth().getValue(this);
- int borderStartWidth = gu.getBorders().getBorderStartWidth(false) / 2;
+ if (log.isTraceEnabled()) {
+ log.trace("pgu: " + primaryGridUnit + "; gu: " + gu + "; yoffset: "
+ + (dy - gu.getBorders().getBorderBeforeWidth(false) / 2)
+ + "; bpd: " + bpd);
+ }
+ int ipd = gu.getColumn().getColumnWidth().getValue(
+ (PercentBaseContext) getParent());
+ int borderStartWidth = gu.getBorders().getBorderStartWidth(false) / 2;
ipd -= borderStartWidth;
ipd -= gu.getBorders().getBorderEndWidth(false) / 2;
block.setIPD(ipd);
block.setXOffset(dx + borderStartWidth);
- int halfCollapsingBorderHeight = 0;
- if (!isSeparateBorderModel()) {
- halfCollapsingBorderHeight
- += gu.getBorders().getBorderBeforeWidth(false) / 2;
- }
- block.setYOffset(dy - halfCollapsingBorderHeight);
+ block.setYOffset(dy - gu.getBorders().getBorderBeforeWidth(false) / 2);
+ outer[0] = gu.getFlag(GridUnit.FIRST_IN_TABLE);
+ outer[1] = gu.getFlag(GridUnit.LAST_IN_TABLE);
+ outer[2] = gu.getFlag(GridUnit.IN_FIRST_COLUMN);
+ outer[3] = gu.getFlag(GridUnit.IN_LAST_COLUMN);
TraitSetter.addCollapsingBorders(block, gu.getBorders(), outer, this);
parentLM.addChildArea(block);
- dx += gu.getColumn().getColumnWidth().getValue(this);
+ dx += gu.getColumn().getColumnWidth().getValue(
+ (PercentBaseContext) getParent());
}
- dy += lastRowHeight;
+ dy += spannedGridRowHeights[y - startRow];
}
- log.warn("TODO Add collapsed border painting for spanned cells");
}
}
//Handle display-align
- int contentBPD = getContentHeight(gridUnit);
+ int contentBPD = getContentHeight(primaryGridUnit);
if (usedBPD < contentBPD) {
if (getTableCell().getDisplayAlign() == EN_CENTER) {
Block space = new Block();
@@ -431,7 +443,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
}
AreaAdditionUtil.addAreas(this, parentIter, layoutContext);
-
+
curBlockArea.setBPD(contentBPD);
// Add background after we know the BPD
@@ -446,7 +458,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
getTableCell().getCommonBorderPaddingBackground(),
this);
}
-
+
flush();
curBlockArea = null;
@@ -471,8 +483,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
curBlockArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
TraitSetter.setProducerID(curBlockArea, getTableCell().getId());
curBlockArea.setPositioning(Block.ABSOLUTE);
- int indent = 0;
- indent += startBorderWidth;
+ int indent = startBorderWidth;
if (!isSeparateBorderModel()) {
indent /= 2;
}
@@ -481,18 +492,18 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
// set position
int borderAdjust = 0;
if (!isSeparateBorderModel()) {
- if (gridUnit.hasSpanning()) {
- borderAdjust -= gridUnit.getHalfMaxBeforeBorderWidth();
+ if (primaryGridUnit.hasSpanning()) {
+ borderAdjust -= primaryGridUnit.getHalfMaxBeforeBorderWidth();
} else {
- borderAdjust += gridUnit.getHalfMaxBeforeBorderWidth();
+ borderAdjust += primaryGridUnit.getHalfMaxBeforeBorderWidth();
}
} else {
- //borderAdjust += gridUnit.getBorders().getBorderBeforeWidth(false);
+ //borderAdjust += primaryGridUnit.getBorders().getBorderBeforeWidth(false);
}
TableLayoutManager tableLM = (TableLayoutManager)getParent();
- curBlockArea.setXOffset(xoffset + inRowIPDOffset
+ curBlockArea.setXOffset(xoffset + inRowIPDOffset
+ tableLM.getHalfBorderSeparationIPD() + indent);
- curBlockArea.setYOffset(yoffset - borderAdjust
+ curBlockArea.setYOffset(yoffset - borderAdjust
+ tableLM.getHalfBorderSeparationBPD());
curBlockArea.setIPD(cellIPD);
//curBlockArea.setHeight();
@@ -548,8 +559,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
public boolean mustKeepTogether() {
//TODO Keeps will have to be more sophisticated sooner or later
boolean keep = ((BlockLevelLayoutManager)getParent()).mustKeepTogether();
- if (gridUnit.getRow() != null) {
- keep |= gridUnit.getRow().mustKeepTogether();
+ if (primaryGridUnit.getRow() != null) {
+ keep |= primaryGridUnit.getRow().mustKeepTogether();
}
return keep;
}
@@ -575,9 +586,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
|| !fobj.getKeepWithNext().getWithinColumn().isAuto();
*/
}
-
+
// --------- Property Resolution related functions --------- //
-
+
/**
* Returns the IPD of the content area
* @return the IPD of the content area
@@ -585,7 +596,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
public int getContentAreaIPD() {
return cellIPD;
}
-
+
/**
* Returns the BPD of the content area
* @return the BPD of the content area
@@ -598,14 +609,14 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
return -1;
}
}
-
+
/**
* @see org.apache.fop.layoutmgr.LayoutManager#getGeneratesReferenceArea
*/
public boolean getGeneratesReferenceArea() {
return true;
}
-
+
/**
* @see org.apache.fop.layoutmgr.LayoutManager#getGeneratesBlockArea
*/
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
index f9d7c6397..c3e1a41da 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
@@ -235,6 +235,12 @@ public class TableContentLayoutManager implements PercentBaseContext {
if (!isSeparateBorderModel()) {
resolveNormalBeforeAfterBordersForRowGroup(rowGroup, iter);
}
+
+ //Reset keep-with-next when remaining inside the table.
+ //The context flag is only used to propagate keep-with-next to the outside.
+ //The clearing is ok here because createElementsForRowGroup already handles
+ //the keep when inside a table.
+ context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
//Element list creation
createElementsForRowGroup(context, alignment, bodyType,
@@ -691,7 +697,6 @@ public class TableContentLayoutManager implements PercentBaseContext {
iterateAndPaintPositions(nestedIter, painter);
}
- painter.notifyEndOfSequence();
this.usedBPD += painter.getAccumulatedBPD();
if (markers != null) {
@@ -701,15 +706,16 @@ public class TableContentLayoutManager implements PercentBaseContext {
}
/**
- * Iterates over a part of the table and paints the related elements.
+ * Iterates over a part of the table (header, footer, body) and paints the related
+ * elements.
*
- * @param iterator iterator over the table's header, body or footer elements
+ * @param iterator iterator over Position elements. Those positions correspond to the
+ * elements of the table present on the current page
* @param painter
*/
private void iterateAndPaintPositions(Iterator iterator, RowPainter painter) {
List lst = new java.util.ArrayList();
boolean firstPos = false;
- boolean lastPos = false;
TableBody body = null;
while (iterator.hasNext()) {
Position pos = (Position)iterator.next();
@@ -728,18 +734,9 @@ public class TableContentLayoutManager implements PercentBaseContext {
if (tcpos.getFlag(TableContentPosition.LAST_IN_ROWGROUP)
&& tcpos.row.getFlag(EffRow.LAST_IN_PART)) {
log.trace("LAST_IN_ROWGROUP + LAST_IN_PART");
- lastPos = true;
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
- true, firstPos, lastPos);
- int size = lst.size();
- for (int i = 0; i < size; i++) {
- painter.handleTableContentPosition((TableContentPosition)lst.get(i));
- }
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
- false, firstPos, lastPos);
+ handleMarkersAndPositions(lst, body, firstPos, true, painter);
//reset
firstPos = false;
- lastPos = false;
body = null;
lst.clear();
}
@@ -750,18 +747,26 @@ public class TableContentLayoutManager implements PercentBaseContext {
}
}
if (body != null) {
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
- true, firstPos, lastPos);
- int size = lst.size();
- for (int i = 0; i < size; i++) {
- painter.handleTableContentPosition((TableContentPosition)lst.get(i));
- }
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
- false, firstPos, lastPos);
+ // Entering this block means that the end of the current table-part hasn't
+ // been reached (otherwise it would have been caught by the test above). So
+ // lastPos is necessarily false
+ handleMarkersAndPositions(lst, body, firstPos, false, painter);
}
painter.addAreasAndFlushRow(true);
}
-
+
+ private void handleMarkersAndPositions(List positions, TableBody body, boolean firstPos,
+ boolean lastPos, RowPainter painter) {
+ getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
+ true, firstPos, lastPos);
+ int size = positions.size();
+ for (int i = 0; i < size; i++) {
+ painter.handleTableContentPosition((TableContentPosition)positions.get(i));
+ }
+ getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
+ false, firstPos, lastPos);
+ }
+
/**
* Get the area for a row for background.
* @param row the table-row object or null
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
index 1707ad422..00ecb01d2 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
@@ -215,10 +215,12 @@ public class TableLayoutManager extends BlockStackingLayoutManager
if (getTable().isSeparateBorderModel()) {
addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
firstVisibleMarkServed = true;
+ // Border and padding to be repeated at each break
+ // This must be done only in the separate-border model, as in collapsing
+ // tables have no padding and borders are determined at the cell level
+ addPendingMarks(context);
}
- //Spaces, border and padding to be repeated at each break
- addPendingMarks(context);
// Elements for the table-header/footer/body
LinkedList contentKnuthElements = null;
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
index 63d153584..f8cedd7de 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
@@ -477,7 +477,7 @@ public class TableRowIterator {
safelySetListItem(gridUnits, colnum - 1, guSpan);
if (hasRowSpanningLeft) {
pendingRowSpans++;
- safelySetListItem(previousRowsSpanningCells, colnum - 1, gu);
+ safelySetListItem(previousRowsSpanningCells, colnum - 1, guSpan);
}
horzSpan[j] = guSpan;
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
index 4459f9a3b..20b80c1bd 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
@@ -46,6 +46,8 @@ public class TableStepper {
private TableContentLayoutManager tclm;
private EffRow[] rowGroup;
+ /** Number of columns in the row group. */
+ private int columnCount;
private int totalHeight;
private int activeRowIndex;
/**
@@ -83,7 +85,7 @@ public class TableStepper {
private boolean rowBacktrackForLastStep;
private boolean skippedStep;
private boolean[] keepWithNextSignals;
- private boolean[] forcedBreaks;
+ private boolean forcedBreak;
private int lastMaxPenaltyLength;
/**
@@ -100,6 +102,7 @@ public class TableStepper {
* @param columnCount number of columns the row group has
*/
private void setup(int columnCount) {
+ this.columnCount = columnCount;
this.activeRowIndex = 0;
elementLists = new List[columnCount];
startRow = new int[columnCount];
@@ -112,21 +115,15 @@ public class TableStepper {
borderAfter = new int[columnCount];
paddingAfter = new int[columnCount];
keepWithNextSignals = new boolean[columnCount];
- forcedBreaks = new boolean[columnCount];
Arrays.fill(end, -1);
}
private void clearBreakCondition() {
- Arrays.fill(forcedBreaks, false);
+ forcedBreak = false;
}
private boolean isBreakCondition() {
- for (int i = 0; i < forcedBreaks.length; i++) {
- if (forcedBreaks[i]) {
- return true;
- }
- }
- return false;
+ return forcedBreak;
}
/**
@@ -171,7 +168,7 @@ public class TableStepper {
private int getMaxRemainingHeight() {
int maxW = 0;
if (!rowBacktrackForLastStep) {
- for (int i = 0; i < widths.length; i++) {
+ for (int i = 0; i < columnCount; i++) {
if (elementLists[i] == null) {
continue;
}
@@ -217,7 +214,6 @@ public class TableStepper {
widths[column] = 0;
startRow[column] = activeRowIndex;
keepWithNextSignals[column] = false;
- forcedBreaks[column] = false;
} else if (gu.isPrimary()) {
PrimaryGridUnit pgu = (PrimaryGridUnit)gu;
boolean makeBoxForWholeRow = false;
@@ -263,9 +259,6 @@ public class TableStepper {
widths[column] = 0;
startRow[column] = activeRowIndex;
keepWithNextSignals[column] = false;
- forcedBreaks[column] = false;
- } else {
- log.trace("TableStepper.setupElementList: not empty nor primary grid unit");
}
}
@@ -302,7 +295,7 @@ public class TableStepper {
int addedBoxLen = 0;
TableContentPosition lastTCPos = null;
LinkedList returnList = new LinkedList();
- while ((step = getNextStep(laststep)) >= 0) {
+ while ((step = getNextStep()) >= 0) {
int normalRow = activeRowIndex;
if (rowBacktrackForLastStep) {
//Even though we've already switched to the next row, we have to
@@ -316,7 +309,7 @@ public class TableStepper {
//Put all involved grid units into a list
List gridUnitParts = new java.util.ArrayList(maxColumnCount);
- for (int i = 0; i < start.length; i++) {
+ for (int i = 0; i < columnCount; i++) {
if (end[i] >= start[i]) {
PrimaryGridUnit pgu = rowGroup[startRow[i]].getGridUnit(i).getPrimary();
if (start[i] == 0 && end[i] == 0
@@ -395,7 +388,7 @@ public class TableStepper {
int p = 0;
boolean allCellsHaveContributed = true;
signalKeepWithNext = false;
- for (int i = 0; i < start.length; i++) {
+ for (int i = 0; i < columnCount; i++) {
if (start[i] == 0 && end[i] < 0 && elementLists[i] != null) {
allCellsHaveContributed = false;
}
@@ -455,10 +448,9 @@ public class TableStepper {
/**
* Finds the smallest increment leading to the next legal break inside the row-group.
*
- * @param lastStep used for log only
* @return the size of the increment, -1 if no next step is available (end of row-group reached)
*/
- private int getNextStep(int lastStep) {
+ private int getNextStep() {
log.trace("Entering getNextStep");
this.lastMaxPenaltyLength = 0;
//Check for forced break conditions
@@ -467,65 +459,15 @@ public class TableStepper {
return -1;
}*/
- int[] backupWidths = new int[start.length];
- System.arraycopy(widths, 0, backupWidths, 0, backupWidths.length);
+ int[] backupWidths = new int[columnCount];
+ System.arraycopy(widths, 0, backupWidths, 0, columnCount);
//set starting points
- // We assume that the current grid row is finished. If this is not the case this
- // boolean will be reset (see below)
- boolean currentGridRowFinished = true;
- for (int i = 0; i < start.length; i++) {
- // null element lists probably correspond to empty cells
- if (elementLists[i] == null) {
- continue;
- }
- if (end[i] < elementLists[i].size()) {
- start[i] = end[i] + 1;
- if (end[i] + 1 < elementLists[i].size()
- && getActiveGridUnit(i).isLastGridUnitRowSpan()) {
- // Ok, so this grid unit is the last in the row-spanning direction and
- // there are still unhandled Knuth elements. They /will/ have to be
- // put on the current grid row, which means that this row isn't
- // finished yet
- currentGridRowFinished = false;
- }
- } else {
- throw new IllegalStateException("end[i] overflows elementList[i].size()");
-// start[i] = -1; //end of list reached
-// end[i] = -1;
- }
- }
-
- if (currentGridRowFinished) {
- if (activeRowIndex < rowGroup.length - 1) {
- TableRow rowFO = getActiveRow().getTableRow();
- if (rowFO != null && rowFO.getBreakAfter() != Constants.EN_AUTO) {
- log.warn(FONode.decorateWithContextInfo(
- "break-after ignored on table-row because of row spanning "
- + "in progress (See XSL 1.0, 7.19.1)", rowFO));
- }
- activeRowIndex++;
- if (log.isDebugEnabled()) {
- log.debug("===> new row: " + activeRowIndex);
- }
- initializeElementLists();
- for (int i = 0; i < backupWidths.length; i++) {
- if (end[i] < 0) {
- backupWidths[i] = 0;
- }
- }
- rowFO = getActiveRow().getTableRow();
- if (rowFO != null && rowFO.getBreakBefore() != Constants.EN_AUTO) {
- log.warn(FONode.decorateWithContextInfo(
- "break-before ignored on table-row because of row spanning "
- + "in progress (See XSL 1.0, 7.19.2)", rowFO));
- }
- }
- }
+ goToNextRowIfCurrentFinished(backupWidths);
//Get next possible sequence for each cell
- int seqCount = 0;
- for (int i = 0; i < start.length; i++) {
+ boolean stepFound = false;
+ for (int i = 0; i < columnCount; i++) {
if (elementLists[i] == null) {
continue;
}
@@ -536,7 +478,7 @@ public class TableStepper {
this.lastMaxPenaltyLength = Math.max(this.lastMaxPenaltyLength, el.getW());
if (el.getP() <= -KnuthElement.INFINITE) {
log.debug("FORCED break encountered!");
- forcedBreaks[i] = true;
+ forcedBreak = true;
break;
} else if (el.getP() < KnuthElement.INFINITE) {
//First legal break point
@@ -562,7 +504,7 @@ public class TableStepper {
}
widths[i] = backupWidths[i];
} else {
- seqCount++;
+ stepFound = true;
}
//log.debug("part " + start[i] + "-" + end[i] + " " + widths[i]);
if (end[i] + 1 >= elementLists[i].size()) {
@@ -588,14 +530,14 @@ public class TableStepper {
log.trace("column " + (i+1) + ": padding before=" + paddingBefore[i] + " after=" + paddingAfter[i]);
}
}
- if (seqCount == 0) {
+ if (!stepFound) {
return -1;
}
//Determine smallest possible step
int minStep = Integer.MAX_VALUE;
StringBuffer sb = new StringBuffer();
- for (int i = 0; i < widths.length; i++) {
+ for (int i = 0; i < columnCount; i++) {
baseWidth[i] = 0;
for (int prevRow = 0; prevRow < startRow[i]; prevRow++) {
baseWidth[i] += rowGroup[prevRow].getHeight().opt;
@@ -610,12 +552,12 @@ public class TableStepper {
}
}
if (log.isDebugEnabled()) {
- log.debug("candidate steps: " + sb + " lastStep=" + lastStep);
+ log.debug("candidate steps: " + sb);
}
//Check for constellations that would result in overlapping borders
/*
- for (int i = 0; i < widths.length; i++) {
+ for (int i = 0; i < columnCount; i++) {
}*/
@@ -623,7 +565,7 @@ public class TableStepper {
//See http://people.apache.org/~jeremias/fop/NextStepAlgoNotes.pdf
rowBacktrackForLastStep = false;
skippedStep = false;
- for (int i = 0; i < widths.length; i++) {
+ for (int i = 0; i < columnCount; i++) {
int len = baseWidth[i] + widths[i];
if (len > minStep) {
widths[i] = backupWidths[i];
@@ -651,7 +593,7 @@ public class TableStepper {
}
if (log.isDebugEnabled()) {
/*StringBuffer*/ sb = new StringBuffer("[col nb: start-end(width)] ");
- for (int i = 0; i < widths.length; i++) {
+ for (int i = 0; i < columnCount; i++) {
if (end[i] >= start[i]) {
sb.append(i + ": " + start[i] + "-" + end[i] + "(" + widths[i] + "), ");
} else {
@@ -663,8 +605,61 @@ public class TableStepper {
return minStep;
}
-
-
+
+ private void goToNextRowIfCurrentFinished(int[] backupWidths) {
+ // We assume that the current grid row is finished. If this is not the case this
+ // boolean will be reset (see below)
+ boolean currentGridRowFinished = true;
+ for (int i = 0; i < columnCount; i++) {
+ // null element lists probably correspond to empty cells
+ if (elementLists[i] == null) {
+ continue;
+ }
+ if (end[i] < elementLists[i].size()) {
+ start[i] = end[i] + 1;
+ if (end[i] + 1 < elementLists[i].size()
+ && getActiveGridUnit(i).isLastGridUnitRowSpan()) {
+ // Ok, so this grid unit is the last in the row-spanning direction and
+ // there are still unhandled Knuth elements. They /will/ have to be
+ // put on the current grid row, which means that this row isn't
+ // finished yet
+ currentGridRowFinished = false;
+ }
+ } else {
+ throw new IllegalStateException("end[i] overflows elementList[i].size()");
+// start[i] = -1; //end of list reached
+// end[i] = -1;
+ }
+ }
+
+ if (currentGridRowFinished) {
+ if (activeRowIndex < rowGroup.length - 1) {
+ TableRow rowFO = getActiveRow().getTableRow();
+ if (rowFO != null && rowFO.getBreakAfter() != Constants.EN_AUTO) {
+ log.warn(FONode.decorateWithContextInfo(
+ "break-after ignored on table-row because of row spanning "
+ + "in progress (See XSL 1.0, 7.19.1)", rowFO));
+ }
+ activeRowIndex++;
+ if (log.isDebugEnabled()) {
+ log.debug("===> new row: " + activeRowIndex);
+ }
+ initializeElementLists();
+ for (int i = 0; i < columnCount; i++) {
+ if (end[i] < 0) {
+ backupWidths[i] = 0;
+ }
+ }
+ rowFO = getActiveRow().getTableRow();
+ if (rowFO != null && rowFO.getBreakBefore() != Constants.EN_AUTO) {
+ log.warn(FONode.decorateWithContextInfo(
+ "break-before ignored on table-row because of row spanning "
+ + "in progress (See XSL 1.0, 7.19.2)", rowFO));
+ }
+ }
+ }
+ }
+
/** @return true if the table uses the separate border model. */
private boolean isSeparateBorderModel() {
return getTableLM().getTable().isSeparateBorderModel();
diff --git a/src/java/org/apache/fop/pdf/DestinationComparator.java b/src/java/org/apache/fop/pdf/DestinationComparator.java
new file mode 100644
index 000000000..87d6a00ff
--- /dev/null
+++ b/src/java/org/apache/fop/pdf/DestinationComparator.java
@@ -0,0 +1,41 @@
+/*
+ * 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.pdf;
+
+import org.apache.fop.pdf.PDFDestination;
+
+/**
+ * Comparator class to enable comparing (and
+ * hence sorting) of PDFDestination objects.
+ */
+public class DestinationComparator implements java.util.Comparator {
+/* public int compare (PDFDestination dest1, PDFDestination dest2) {
+ return dest1.getIDRef().compareTo(dest2.getIDRef());
+ }*/
+
+ public int compare (Object obj1, Object obj2) {
+ if (obj1 instanceof PDFDestination && obj2 instanceof PDFDestination) {
+ PDFDestination dest1 = (PDFDestination)obj1;
+ PDFDestination dest2 = (PDFDestination)obj2;
+ return dest1.getIDRef().compareTo(dest2.getIDRef());
+ }
+ return 0;
+ }
+}
diff --git a/src/java/org/apache/fop/pdf/PDFDestination.java b/src/java/org/apache/fop/pdf/PDFDestination.java
new file mode 100644
index 000000000..97923e935
--- /dev/null
+++ b/src/java/org/apache/fop/pdf/PDFDestination.java
@@ -0,0 +1,138 @@
+/*
+ * 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.pdf;
+
+import org.apache.fop.area.DestinationData;
+import org.apache.fop.area.PageViewport;
+
+/**
+ * class representing a named destination
+ */
+public class PDFDestination extends PDFObject {
+
+ /**
+ * PDFReference (object reference) for this destination
+ */
+ private String goToReference;
+
+ /**
+ * ID Reference for this destination
+ */
+ private String idRef;
+
+ /**
+ * PageViewport to which the idRef item refers
+ */
+ private PageViewport pageViewport = null;
+
+ /**
+ * create a named destination
+ */
+ public PDFDestination(DestinationData destinationData) {
+ /* generic creation of PDF object */
+ super();
+ this.goToReference = destinationData.getGoToReference();
+ this.idRef = destinationData.getIDRef();
+ this.pageViewport = destinationData.getPageViewport();
+ }
+
+ /**
+ * @see org.apache.fop.pdf.PDFObject#toPDFString()
+ */
+ public String toPDFString() {
+ String s = getObjectID()
+ + "<<"
+ + "/Limits [(" + idRef + ") (" + idRef + ")]\n"
+ + "/Names [(" + idRef + ") " + goToReference + "]"
+ + "\n>>\nendobj\n";
+ return s;
+ }
+
+ /*
+ * example:
+ *
+ * 249 0 obj
+ * <<
+ * /Limits [(drivervariables) (drivervariables)]
+ * /Names [(drivervariables) 73 0 R]
+ * >>
+ * endobj
+ */
+
+ /**
+ * Sets the GoToReference in the associated DestinationData object.
+ *
+ * @param goToReference the reference to set in the associated DestinationData object.
+ */
+ public void setGoToReference(String goToReference) {
+ this.goToReference = goToReference;
+ }
+
+ /**
+ * Returns the GoToReference from the associated DestinationData object.
+ *
+ * @return the GoToReference from the associated DestinationData object.
+ */
+ public String getGoToReference() {
+ return this.goToReference;
+ }
+
+ /**
+ * Get the PageViewport object that this destination refers to
+ *
+ * @return the PageViewport that this destination points to
+ */
+ public PageViewport getPageViewport() {
+ return this.pageViewport;
+ }
+
+ /**
+ * Returns the RefID from the associated DestinationData object.
+ *
+ * @return the RefID from the associated DestinationData object.
+ */
+ public String getIDRef() {
+ return this.idRef;
+ }
+
+ /**
+ * Check if this equals another object.
+ *
+ * @param obj the object to compare
+ * @return true if this equals other object
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof PDFDestination)) {
+ return false;
+ }
+
+ PDFDestination dest = (PDFDestination)obj;
+ if (dest.getIDRef() == this.getIDRef()) {
+ return true;
+ }
+
+ return true;
+ }
+}
+
diff --git a/src/java/org/apache/fop/pdf/PDFDests.java b/src/java/org/apache/fop/pdf/PDFDests.java
new file mode 100644
index 000000000..96172c8e2
--- /dev/null
+++ b/src/java/org/apache/fop/pdf/PDFDests.java
@@ -0,0 +1,79 @@
+/*
+ * 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.pdf;
+
+import org.apache.fop.area.DestinationData;
+
+/**
+ * class representing an /Dests object (part of a name dictionary)
+ */
+public class PDFDests extends PDFObject {
+
+ private String limitsRef;
+
+ /**
+ * create a named destination
+ */
+ public PDFDests(String limitsRef) {
+ /* generic creation of PDF object */
+ super();
+ this.limitsRef = limitsRef;
+ }
+
+ /**
+ * @see org.apache.fop.pdf.PDFObject#toPDFString()
+ */
+ public String toPDFString() {
+ String s = getObjectID()
+ + "<<\n"
+ + "/Dests " + limitsRef
+ + "\n>>\nendobj\n";
+ return s;
+ }
+
+ /*
+ * example:
+ *
+ * 262 0 obj
+ * <<
+ * /Dests 260 0 R
+ * >>
+ * endobj
+ */
+
+ /**
+ * Check if this equals another object.
+ *
+ * @param obj the object to compare
+ * @return true if this equals other object
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof PDFDests)) {
+ return false;
+ }
+
+ return true;
+ }
+}
+
diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java
index 4ce82fab9..29cb88731 100644
--- a/src/java/org/apache/fop/pdf/PDFDocument.java
+++ b/src/java/org/apache/fop/pdf/PDFDocument.java
@@ -5,9 +5,9 @@
* 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.
@@ -19,7 +19,7 @@
package org.apache.fop.pdf;
-// Java
+/// Java
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -32,10 +32,14 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Collections;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.pdf.DestinationComparator;
+
/* image support modified from work of BoBoGi */
/* font support based on work by Takayuki Takeuchi */
@@ -63,13 +67,13 @@ import org.apache.commons.logging.LogFactory;
public class PDFDocument {
private static final Integer LOCATION_PLACEHOLDER = new Integer(0);
-
+
/** Integer constant to represent PDF 1.3 */
public static final int PDF_VERSION_1_3 = 3;
/** Integer constant to represent PDF 1.4 */
public static final int PDF_VERSION_1_4 = 4;
-
+
/**
* the encoding to use when converting strings to PDF commandos.
*/
@@ -85,7 +89,7 @@ public class PDFDocument {
/**
* the character position of each object
*/
- protected List location = new java.util.ArrayList();
+ protected List location = new ArrayList();
/** List of objects to write in the trailer */
private List trailerObjects = new java.util.ArrayList();
@@ -107,12 +111,12 @@ public class PDFDocument {
/** Indicates what PDF version is active */
protected int pdfVersion = PDF_VERSION_1_4;
-
+
/**
* Indicates which PDF profiles are active (PDF/A, PDF/X etc.)
*/
protected PDFProfile pdfProfile = new PDFProfile(this);
-
+
/**
* the /Root object
*/
@@ -202,6 +206,11 @@ public class PDFDocument {
protected List links = new java.util.ArrayList();
/**
+ * List of Destinations.
+ */
+ protected List destinations = new java.util.ArrayList();
+
+ /**
* List of FileSpecs.
*/
protected List filespecs = new java.util.ArrayList();
@@ -216,6 +225,25 @@ public class PDFDocument {
*/
protected List gotos = new java.util.ArrayList();
+ /**
+ * The PDFDests object for the name dictionary.
+ * Note: This object is not a list.
+ */
+ private PDFDests dests;
+
+ /**
+ * The PDFLimits object for the name dictionary.
+ * Note: This object is not a list.
+ */
+ private PDFLimits limits;
+
+ /**
+ * Whether this PDFDocument has named destinations
+ * (and thus needs PDFDestinations, PDFLimits, and
+ * PDFDests)
+ */
+ private boolean hasDestinations = false;
+
private PDFFactory factory;
private boolean encodingOnTheFly = true;
@@ -255,7 +283,7 @@ public class PDFDocument {
public int getPDFVersion() {
return this.pdfVersion;
}
-
+
/** @return the String representing the active PDF version */
public String getPDFVersionString() {
switch (getPDFVersion()) {
@@ -272,7 +300,7 @@ public class PDFDocument {
public PDFProfile getProfile() {
return this.pdfProfile;
}
-
+
/**
* Returns the factory for PDF objects.
* @return PDFFactory the factory
@@ -315,7 +343,7 @@ public class PDFDocument {
/**
* Set the creation date of the document.
- *
+ *
* @param date Date to be stored as creation date in the PDF.
*/
public void setCreationDate(Date date) {
@@ -460,6 +488,9 @@ public class PDFDocument {
if (obj instanceof PDFLink) {
this.links.add(obj);
}
+ if (obj instanceof PDFDestination) {
+ this.destinations.add(obj);
+ }
if (obj instanceof PDFFileSpec) {
this.filespecs.add(obj);
}
@@ -578,6 +609,15 @@ public class PDFDocument {
}
/**
+ * Finds a named destination.
+ * @param compare reference object to use as search template
+ * @return the link if found, null otherwise
+ */
+ protected PDFDestination findDestination(PDFDestination compare) {
+ return (PDFDestination)findPDFObject(destinations, compare);
+ }
+
+ /**
* Finds a link.
* @param compare reference object to use as search template
* @return the link if found, null otherwise
@@ -702,6 +742,51 @@ public class PDFDocument {
}
/**
+ * Gets the PDFDests object (which represents the /Dests entry).
+ *
+ * @return the PDFDests object (which represents the /Dests entry).
+ */
+ public PDFDests getDests() {
+ return dests;
+ }
+
+ /**
+ * Gets the list of named destinations.
+ *
+ * @return the list of named destinations.
+ */
+ public ArrayList getDestinationList() {
+ return (ArrayList)destinations;
+ }
+
+ /**
+ * Sets whether the document has named destinations.
+ *
+ * @param hasDestinations whether the document has named destinations.
+ */
+ public void setHasDestinations(boolean hasDestinations) {
+ this.hasDestinations = hasDestinations;
+ }
+
+ /**
+ * Gets whether the document has named destinations.
+ *
+ * @return whether the document has named destinations.
+ */
+ public boolean getHasDestinations() {
+ return this.hasDestinations;
+ }
+
+ /**
+ * Gets the PDFLimits object (part of the name dictionary).
+ *
+ * @return the PDFLimits object (part of the name dictionary).
+ */
+ public PDFLimits getLimits() {
+ return limits;
+ }
+
+ /**
* Add an image to the PDF document.
* This adds an image to the PDF objects.
* If an image with the same key already exists it will return the
@@ -848,7 +933,7 @@ public class PDFDocument {
this.position = 0;
getProfile().verifyPDFVersion();
-
+
byte[] pdf = ("%PDF-" + getPDFVersionString() + "\n").getBytes();
stream.write(pdf);
this.position += pdf.length;
@@ -885,7 +970,7 @@ public class PDFDocument {
}
}
}
-
+
/**
* write the trailer
*
@@ -893,6 +978,12 @@ public class PDFDocument {
* @throws IOException if there is an exception writing to the output stream
*/
public void outputTrailer(OutputStream stream) throws IOException {
+ if (hasDestinations) {
+ Collections.sort((ArrayList)destinations, new DestinationComparator());
+ limits = getFactory().makeLimits((ArrayList)destinations);
+ dests = getFactory().makeDests(limits.referencePDF());
+ this.root.setNames(dests.referencePDF());
+ }
output(stream);
for (int count = 0; count < trailerObjects.size(); count++) {
PDFObject o = (PDFObject)trailerObjects.get(count);
@@ -970,4 +1061,4 @@ public class PDFDocument {
return pdfBytes.length;
}
-}
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java
index 4ab6ebd7b..3005f2018 100644
--- a/src/java/org/apache/fop/pdf/PDFFactory.java
+++ b/src/java/org/apache/fop/pdf/PDFFactory.java
@@ -5,9 +5,9 @@
* 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.
@@ -31,6 +31,7 @@ import java.util.List;
import java.util.Map;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
+import java.util.ArrayList;
// Apache libs
import org.apache.commons.io.IOUtils;
@@ -52,6 +53,8 @@ import org.apache.fop.fonts.truetype.TTFSubSetFile;
import org.apache.fop.fonts.type1.PFBData;
import org.apache.fop.fonts.type1.PFBParser;
import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.area.DestinationData;
/**
* This class provides method to create and register PDF objects.
@@ -731,7 +734,7 @@ public class PDFFactory {
PDFPattern myPattern;
//PDFColorSpace theColorSpace;
double interpolation = (double)1.000;
- List theFunctions = new java.util.ArrayList();
+ List theFunctions = new ArrayList();
int currentPosition;
int lastPosition = theColors.size() - 1;
@@ -782,7 +785,7 @@ public class PDFFactory {
} else { // if the center x, center y, and radius specifiy
// the gradient, then assume the same center x, center y,
// and radius of zero for the other necessary component
- List newCoords = new java.util.ArrayList();
+ List newCoords = new ArrayList();
newCoords.add(theCoords.get(0));
newCoords.add(theCoords.get(1));
newCoords.add(theCoords.get(2));
@@ -809,6 +812,56 @@ public class PDFFactory {
return (myPattern);
}
+ /* ============= named destinations and the name dictionary ============ */
+
+ /**
+ * Make a named destination.
+ *
+ * @param destinationData the DestinationData object that holds the info about this named destination
+ * @return the new PDF named destination object
+ */
+ public PDFDestination makeDestination(DestinationData destinationData) {
+ PageViewport pv = destinationData.getPageViewport();
+ if (pv == null) {
+ log.warn("Unresolved destination item received: " + destinationData.getIDRef());
+ }
+ PDFDestination destination = new PDFDestination(destinationData);
+
+ PDFDestination oldDestination = getDocument().findDestination(destination);
+ if (destination == oldDestination) {
+ destination = oldDestination;
+ } else {
+ getDocument().registerObject(destination);
+ getDocument().setHasDestinations(true);
+ }
+
+ return destination;
+ }
+
+ /**
+ * Make a the head object of the name dictionary (the /Dests object).
+ *
+ * @return the new PDFDests object
+ */
+ public PDFDests makeDests(String limitsRef) {
+ PDFDests dests = new PDFDests(limitsRef);
+ getDocument().registerObject(dests);
+
+ return dests;
+ }
+
+ /**
+ * Make a the limits object of the name dictionary (the /Limits object).
+ *
+ * @return the new PDFLimits object
+ */
+ public PDFLimits makeLimits(ArrayList destinationList) {
+ PDFLimits limits = new PDFLimits(destinationList);
+ getDocument().registerObject(limits);
+
+ return limits;
+ }
+
/* ========================= links ===================================== */
/**
@@ -888,7 +941,7 @@ public class PDFFactory {
return link;
}
- private String getGoToReference(String destination, float yoffset) {
+ public String getGoToReference(String destination, float yoffset) {
getDocument().getProfile().verifyActionAllowed();
String goToReference = null;
PDFGoTo gt = new PDFGoTo(destination);
@@ -1153,9 +1206,9 @@ public class PDFFactory {
int value = 0;
for (int i = 0, c = cidSubset.length(); i < c; i++) {
int shift = i % 8;
- boolean b = cidSubset.get(i);
+ boolean b = cidSubset.get(i);
if (b) {
- value |= 1 << 7 - shift;
+ value |= 1 << 7 - shift;
}
if (shift == 7) {
baout.write(value);
@@ -1335,7 +1388,7 @@ public class PDFFactory {
public PDFICCBasedColorSpace makeICCBasedColorSpace(PDFResourceContext res,
String explicitName, PDFICCStream iccStream) {
PDFICCBasedColorSpace cs = new PDFICCBasedColorSpace(explicitName, iccStream);
-
+
getDocument().registerObject(cs);
if (res != null) {
@@ -1343,7 +1396,7 @@ public class PDFFactory {
} else {
getDocument().getResources().addColorSpace(cs);
}
-
+
return cs;
}
diff --git a/src/java/org/apache/fop/pdf/PDFLimits.java b/src/java/org/apache/fop/pdf/PDFLimits.java
new file mode 100644
index 000000000..97c097463
--- /dev/null
+++ b/src/java/org/apache/fop/pdf/PDFLimits.java
@@ -0,0 +1,93 @@
+/*
+ * 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.pdf;
+
+import java.util.ArrayList;
+
+import org.apache.fop.pdf.PDFDestination;
+
+/**
+ * class representing a Limits object (part of the names dictionary for named destinations)
+ */
+public class PDFLimits extends PDFObject {
+
+ private ArrayList destinationList;
+
+ /**
+ * create a named destination
+ */
+ public PDFLimits(ArrayList destinationList) {
+ /* generic creation of PDF object */
+ super();
+ this.destinationList = destinationList;
+ }
+
+ /**
+ * @see org.apache.fop.pdf.PDFObject#toPDFString()
+ */
+ public String toPDFString() {
+ String[] idRefs = new String[destinationList.size()];
+ String kidsString = "";
+ for (int i = 0; i < destinationList.size(); i++) {
+ PDFDestination dest = (PDFDestination)destinationList.get(i);
+ idRefs[i] = dest.getIDRef();
+ kidsString += dest.referencePDF();
+ if (!(i == destinationList.size() - 1)) {
+ kidsString += " ";
+ }
+ }
+ String s = getObjectID()
+ + "<<\n"
+ + "/Limits [(" + idRefs[0] + ") (" + idRefs[destinationList.size() - 1] + ")]\n"
+ + "/Kids [" + kidsString + "]"
+ + "\n>>\nendobj\n";
+ return s;
+ }
+
+ /*
+ * example:
+ *
+ * 260 0 obj
+ * <<
+ * /Limits [(Annotate) (thumbnails)]
+ * /Kids [248 0 R 253 0 R 254 0 R 259 0 R]
+ * >>
+ * endobj
+ */
+
+ /**
+ * Check if this equals another object.
+ *
+ * @param obj the object to compare
+ * @return true if this equals other object
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof PDFLimits)) {
+ return false;
+ }
+
+ return true;
+ }
+}
+
diff --git a/src/java/org/apache/fop/pdf/PDFRoot.java b/src/java/org/apache/fop/pdf/PDFRoot.java
index ffe9611ba..60fe6b390 100644
--- a/src/java/org/apache/fop/pdf/PDFRoot.java
+++ b/src/java/org/apache/fop/pdf/PDFRoot.java
@@ -20,6 +20,7 @@
package org.apache.fop.pdf;
import java.util.List;
+import java.util.ArrayList;
/**
* class representing a Root (/Catalog) object
@@ -62,6 +63,12 @@ public class PDFRoot extends PDFObject {
/** The array of OutputIntents */
private List outputIntents;
+ /**
+ * The referencePDF value of the /Dests object,
+ * if this PDF has a Name Dictionary
+ */
+ private String namesReferencePDF = null;
+
private int pageMode = PAGEMODE_USENONE;
/**
@@ -130,6 +137,15 @@ public class PDFRoot extends PDFObject {
* @param meta the Metadata object
* @since PDF 1.4
*/
+ public void setNames(String referencePDF) {
+ this.namesReferencePDF = referencePDF;
+ }
+
+ /**
+ * Set the optional Metadata object.
+ * @param meta the Metadata object
+ * @since PDF 1.4
+ */
public void setMetadata(PDFMetadata meta) {
this.metadata = meta;
}
@@ -181,6 +197,9 @@ public class PDFRoot extends PDFObject {
break;
}
}
+ if (getDocumentSafely().getHasDestinations() && namesReferencePDF != null) {
+ p.append(" /Names " + namesReferencePDF + "\n");
+ }
if (getMetadata() != null
&& getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) {
p.append("/Metadata " + getMetadata().referencePDF() + "\n");
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index 481ce844c..f64fa75aa 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -73,6 +73,7 @@ import org.apache.fop.pdf.PDFAMode;
import org.apache.fop.pdf.PDFAnnotList;
import org.apache.fop.pdf.PDFColor;
import org.apache.fop.pdf.PDFConformanceException;
+import org.apache.fop.pdf.PDFDestination;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFEncryptionManager;
import org.apache.fop.pdf.PDFEncryptionParams;
@@ -105,6 +106,8 @@ import org.apache.xmlgraphics.xmp.Metadata;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
+import org.apache.fop.area.DestinationData;
+
/**
* Renderer that renders areas to PDF.
*/
@@ -509,8 +512,19 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
* @see org.apache.fop.render.Renderer#processOffDocumentItem(OffDocumentItem)
*/
public void processOffDocumentItem(OffDocumentItem odi) {
+ // render Destinations
+ if (odi instanceof DestinationData) {
+ PDFDestination destination = pdfDoc.getFactory().makeDestination((DestinationData) odi);
+ PageViewport pv = destination.getPageViewport();
+ String dest = (String)pageReferences.get(pv.getKey());
+ Rectangle2D bounds = pv.getViewArea();
+ double h = bounds.getHeight();
+ float yoffset = (float)h / 1000f;
+ String gtRef = pdfDoc.getFactory().getGoToReference(dest, yoffset);
+ destination.setGoToReference(gtRef);
+ }
// render Bookmark-Tree
- if (odi instanceof BookmarkData) {
+ else if (odi instanceof BookmarkData) {
renderBookmarkTree((BookmarkData) odi);
} else if (odi instanceof OffDocumentExtensionAttachment) {
ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)odi).getAttachment();
diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java
index 24595368f..68c6cc86c 100644
--- a/src/java/org/apache/fop/render/ps/PSRenderer.java
+++ b/src/java/org/apache/fop/render/ps/PSRenderer.java
@@ -953,15 +953,22 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
}
if (rotate) {
+ gen.writeln("<<");
+ gen.writeln("/PageSize ["
+ + Math.round(pspageheight) + " "
+ + Math.round(pspagewidth) + "]");
+ gen.writeln("/ImagingBBox null");
+ gen.writeln(">> setpagedevice");
gen.writeln(Math.round(pspageheight) + " 0 translate");
gen.writeln("90 rotate");
+ } else {
+ gen.writeln("<<");
+ gen.writeln("/PageSize ["
+ + Math.round(pspagewidth) + " "
+ + Math.round(pspageheight) + "]");
+ gen.writeln("/ImagingBBox null");
+ gen.writeln(">> setpagedevice");
}
- gen.writeln("<<");
- gen.writeln("/PageSize ["
- + Math.round(pspagewidth) + " "
- + Math.round(pspageheight) + "]");
- gen.writeln("/ImagingBBox null");
- gen.writeln(">> setpagedevice");
concatMatrix(1, 0, 0, -1, 0, pageheight / 1000f);
gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
diff --git a/status.xml b/status.xml
index 2c662ef1f..1e281b91d 100644
--- a/status.xml
+++ b/status.xml
@@ -28,6 +28,17 @@
<changes>
<release version="FOP Trunk">
+ <action context="Code" dev="JB" type="add" importance="high">
+ Add support for named destinations in PDF.
+ </action>
+ <action context="Code" dev="JM" type="fix">
+ Fixed a problem with keep-with-next on table-rows. Once a keep-with-next was set
+ inside a table, the FO following the table would always be glued to the previous table.
+ </action>
+ <action context="Code" dev="JM" type="fix">
+ Fixed a problem with the auto-rotate-landscape setting in the PostScript renderer.
+ It didn't generate the right setpagedevice command.
+ </action>
<action context="Code" dev="JM" type="fix">
Fixed an IllegalArgumentException for absolutely positioned block-containers with a
border and no height/bpd set.
diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java
index a04fa8064..99a63f2b7 100644
--- a/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java
+++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java
@@ -140,6 +140,7 @@ public class LayoutEngineTestSuite {
} else if (startsWith != null) {
filter = new PrefixFileFilter(startsWith);
filter = new AndFileFilter(filter, new SuffixFileFilter(".xml"));
+ filter = decorateWithDisabledList(filter);
} else {
filter = new SuffixFileFilter(".xml");
filter = decorateWithDisabledList(filter);
diff --git a/test/layoutengine/standard-testcases/markers_9.xml b/test/layoutengine/standard-testcases/markers_9.xml
index 5197665e5..1629642f5 100644
--- a/test/layoutengine/standard-testcases/markers_9.xml
+++ b/test/layoutengine/standard-testcases/markers_9.xml
@@ -49,7 +49,7 @@
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
- <fo:table color="black" table-layout="fixed">
+ <fo:table color="black" table-layout="fixed" border-collapse="separate">
<fo:table-column number-columns-repeated="2"/>
<fo:table-body>
<fo:marker marker-class-name="test">body1</fo:marker>
@@ -77,7 +77,7 @@
</fo:table-row>
</fo:table-body>
</fo:table>
- <fo:table color="red" table-layout="fixed">
+ <fo:table color="red" table-layout="fixed" border-collapse="separate">
<fo:table-column number-columns-repeated="2"/>
<fo:table-body>
<fo:marker marker-class-name="test">body2</fo:marker>
@@ -99,7 +99,7 @@
</fo:table-row>
</fo:table-body>
</fo:table>
- <fo:table color="blue" table-layout="fixed">
+ <fo:table color="blue" table-layout="fixed" border-collapse="separate">
<fo:table-column number-columns-repeated="2"/>
<fo:table-body>
<fo:marker marker-class-name="test">body3</fo:marker>
@@ -130,7 +130,7 @@
</fo:table-row>
</fo:table-body>
</fo:table>
- <fo:table table-layout="fixed">
+ <fo:table table-layout="fixed" border-collapse="separate">
<fo:table-column number-columns-repeated="2"/>
<fo:table-body color="black">
<fo:marker marker-class-name="test">body5</fo:marker>
diff --git a/test/layoutengine/standard-testcases/region_display-align_table.xml b/test/layoutengine/standard-testcases/region_display-align_table.xml
index 5aea73ec0..be08e2b16 100644
--- a/test/layoutengine/standard-testcases/region_display-align_table.xml
+++ b/test/layoutengine/standard-testcases/region_display-align_table.xml
@@ -1,256 +1,256 @@
-<?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 implementation of display-align in all regions.
- </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="before" page-width="5in" page-height="5in" margin="10pt">
- <fo:region-body background-color="rgb(100%, 100%, 80%)" margin="30pt" display-align="before"/>
- <fo:region-before background-color="rgb(100%, 80%, 80%)" extent="30pt" display-align="before"/>
- <fo:region-after background-color="rgb(80%, 80%, 80%)" extent="30pt" display-align="before"/>
- <fo:region-start background-color="rgb(80%, 100%, 80%)" extent="30pt" display-align="before"/>
- <fo:region-end background-color="rgb(80%, 80%, 100%)" extent="30pt" display-align="before"/>
- </fo:simple-page-master>
- <fo:simple-page-master master-name="center" page-width="5in" page-height="5in" margin="10pt">
- <fo:region-body background-color="rgb(100%, 100%, 80%)" margin="30pt" display-align="center"/>
- <fo:region-before background-color="rgb(100%, 80%, 80%)" extent="30pt" display-align="center"/>
- <fo:region-after background-color="rgb(80%, 80%, 80%)" extent="30pt" display-align="center"/>
- <fo:region-start background-color="rgb(80%, 100%, 80%)" extent="30pt" display-align="center"/>
- <fo:region-end background-color="rgb(80%, 80%, 100%)" extent="30pt" display-align="center"/>
- </fo:simple-page-master>
- <fo:simple-page-master master-name="after" page-width="5in" page-height="5in" margin="10pt">
- <fo:region-body background-color="rgb(100%, 100%, 80%)" margin="30pt" display-align="after"/>
- <fo:region-before background-color="rgb(100%, 80%, 80%)" extent="30pt" display-align="after"/>
- <fo:region-after background-color="rgb(80%, 80%, 80%)" extent="30pt" display-align="after"/>
- <fo:region-start background-color="rgb(80%, 100%, 80%)" extent="30pt" display-align="after"/>
- <fo:region-end background-color="rgb(80%, 80%, 100%)" extent="30pt" display-align="after"/>
- </fo:simple-page-master>
- </fo:layout-master-set>
-
- <fo:page-sequence master-reference="before">
- <fo:static-content flow-name="xsl-region-before">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:static-content flow-name="xsl-region-after">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:static-content flow-name="xsl-region-start">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:static-content flow-name="xsl-region-end">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:flow flow-name="xsl-region-body">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:flow>
- </fo:page-sequence>
-
- <fo:page-sequence master-reference="center">
- <fo:static-content flow-name="xsl-region-before">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:static-content flow-name="xsl-region-after">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:static-content flow-name="xsl-region-start">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:static-content flow-name="xsl-region-end">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:flow flow-name="xsl-region-body">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:flow>
- </fo:page-sequence>
-
- <fo:page-sequence master-reference="after">
- <fo:static-content flow-name="xsl-region-before">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:static-content flow-name="xsl-region-after">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:static-content flow-name="xsl-region-start">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:static-content flow-name="xsl-region-end">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- </fo:static-content>
- <fo:flow flow-name="xsl-region-body">
- <fo:table width="20pt" table-layout="fixed" border="1pt solid red">
- <fo:table-column column-number="1" width="100%"/>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell column-number="1">
- <fo:block>X</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 0 360000 360000" xpath="//pageViewport[1]/@bounds"/>
- <!-- display-align="center" -->
- <eval expected="6800" xpath="//pageViewport[@nr='2']//regionBefore/block[1]/@bpd"/>
- <eval expected="161800" xpath="//pageViewport[@nr='2']//regionStart/block[1]/@bpd"/>
- <eval expected="161800" xpath="//pageViewport[@nr='2']//regionEnd/block[1]/@bpd"/>
- <eval expected="6800" xpath="//pageViewport[@nr='2']//regionAfter/block[1]/@bpd"/>
- <eval expected="131800" xpath="//pageViewport[@nr='2']//regionBody//block[1]/@bpd"/>
- <!-- display-align="after" -->
- <eval expected="13600" xpath="//pageViewport[@nr='3']//regionBefore/block[1]/@bpd"/>
- <eval expected="323600" xpath="//pageViewport[@nr='3']//regionStart/block[1]/@bpd"/>
- <eval expected="323600" xpath="//pageViewport[@nr='3']//regionEnd/block[1]/@bpd"/>
- <eval expected="13600" xpath="//pageViewport[@nr='3']//regionAfter/block[1]/@bpd"/>
- <eval expected="263600" xpath="//pageViewport[@nr='3']//regionBody//block[1]/@bpd"/>
- </checks>
-</testcase>
+<?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 implementation of display-align in all regions.
+ </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="before" page-width="5in" page-height="5in" margin="10pt">
+ <fo:region-body background-color="rgb(100%, 100%, 80%)" margin="30pt" display-align="before"/>
+ <fo:region-before background-color="rgb(100%, 80%, 80%)" extent="30pt" display-align="before"/>
+ <fo:region-after background-color="rgb(80%, 80%, 80%)" extent="30pt" display-align="before"/>
+ <fo:region-start background-color="rgb(80%, 100%, 80%)" extent="30pt" display-align="before"/>
+ <fo:region-end background-color="rgb(80%, 80%, 100%)" extent="30pt" display-align="before"/>
+ </fo:simple-page-master>
+ <fo:simple-page-master master-name="center" page-width="5in" page-height="5in" margin="10pt">
+ <fo:region-body background-color="rgb(100%, 100%, 80%)" margin="30pt" display-align="center"/>
+ <fo:region-before background-color="rgb(100%, 80%, 80%)" extent="30pt" display-align="center"/>
+ <fo:region-after background-color="rgb(80%, 80%, 80%)" extent="30pt" display-align="center"/>
+ <fo:region-start background-color="rgb(80%, 100%, 80%)" extent="30pt" display-align="center"/>
+ <fo:region-end background-color="rgb(80%, 80%, 100%)" extent="30pt" display-align="center"/>
+ </fo:simple-page-master>
+ <fo:simple-page-master master-name="after" page-width="5in" page-height="5in" margin="10pt">
+ <fo:region-body background-color="rgb(100%, 100%, 80%)" margin="30pt" display-align="after"/>
+ <fo:region-before background-color="rgb(100%, 80%, 80%)" extent="30pt" display-align="after"/>
+ <fo:region-after background-color="rgb(80%, 80%, 80%)" extent="30pt" display-align="after"/>
+ <fo:region-start background-color="rgb(80%, 100%, 80%)" extent="30pt" display-align="after"/>
+ <fo:region-end background-color="rgb(80%, 80%, 100%)" extent="30pt" display-align="after"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+
+ <fo:page-sequence master-reference="before">
+ <fo:static-content flow-name="xsl-region-before">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-after">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-start">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-end">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:flow>
+ </fo:page-sequence>
+
+ <fo:page-sequence master-reference="center">
+ <fo:static-content flow-name="xsl-region-before">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-after">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-start">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-end">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:flow>
+ </fo:page-sequence>
+
+ <fo:page-sequence master-reference="after">
+ <fo:static-content flow-name="xsl-region-before">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-after">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-start">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-region-end">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body">
+ <fo:table width="20pt" table-layout="fixed" border="1pt solid red" border-collapse="separate">
+ <fo:table-column column-number="1" width="100%"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell column-number="1">
+ <fo:block>X</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 0 360000 360000" xpath="//pageViewport[1]/@bounds"/>
+ <!-- display-align="center" -->
+ <eval expected="6800" xpath="//pageViewport[@nr='2']//regionBefore/block[1]/@bpd"/>
+ <eval expected="161800" xpath="//pageViewport[@nr='2']//regionStart/block[1]/@bpd"/>
+ <eval expected="161800" xpath="//pageViewport[@nr='2']//regionEnd/block[1]/@bpd"/>
+ <eval expected="6800" xpath="//pageViewport[@nr='2']//regionAfter/block[1]/@bpd"/>
+ <eval expected="131800" xpath="//pageViewport[@nr='2']//regionBody//block[1]/@bpd"/>
+ <!-- display-align="after" -->
+ <eval expected="13600" xpath="//pageViewport[@nr='3']//regionBefore/block[1]/@bpd"/>
+ <eval expected="323600" xpath="//pageViewport[@nr='3']//regionStart/block[1]/@bpd"/>
+ <eval expected="323600" xpath="//pageViewport[@nr='3']//regionEnd/block[1]/@bpd"/>
+ <eval expected="13600" xpath="//pageViewport[@nr='3']//regionAfter/block[1]/@bpd"/>
+ <eval expected="263600" xpath="//pageViewport[@nr='3']//regionBody//block[1]/@bpd"/>
+ </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table-cell_number-rows-spanned_bug38397.xml b/test/layoutengine/standard-testcases/table-cell_number-rows-spanned_bug38397.xml
index d326d87b3..e7aabd10e 100644
--- a/test/layoutengine/standard-testcases/table-cell_number-rows-spanned_bug38397.xml
+++ b/test/layoutengine/standard-testcases/table-cell_number-rows-spanned_bug38397.xml
@@ -39,7 +39,7 @@
<fo:table-column column-width="proportional-column-width(2)"/>
<fo:table-body>
<fo:table-row>
- <fo:table-cell number-rows-spanned="3" number-columns-spanned="2" display-align="center" border="solid 0.5pt">
+ <fo:table-cell id="cell1" number-rows-spanned="3" number-columns-spanned="2" display-align="center" border="solid 0.5pt">
<fo:block>cell1</fo:block>
</fo:table-cell>
<fo:table-cell number-rows-spanned="2" display-align="center" border="solid 0.5pt">
@@ -94,5 +94,6 @@
</fo>
<checks>
<eval expected="1" xpath="count(//pageViewport)"/>
+ <eval expected="45200" xpath="//block[@prod-id = 'cell1']/@bpd"/>
</checks>
</testcase>
diff --git a/test/layoutengine/standard-testcases/table-cell_span-combinations.xml b/test/layoutengine/standard-testcases/table-cell_span-combinations.xml
new file mode 100644
index 000000000..fc2357e9f
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table-cell_span-combinations.xml
@@ -0,0 +1,84 @@
+<?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 spanned cells (especially that no cell generates more than one area).
+ </p>
+ </info>
+ <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:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="normal" white-space-collapse="true">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:table table-layout="fixed" width="100%" border-collapse="separate">
+ <fo:table-column column-width="proportional-column-width(1)"/>
+ <fo:table-column column-width="proportional-column-width(1)"/>
+ <fo:table-column column-width="proportional-column-width(1)"/>
+ <fo:table-column column-width="proportional-column-width(1)"/>
+ <fo:table-column column-width="proportional-column-width(1)"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell id="cell1" number-columns-spanned="4" border="solid 0.5pt">
+ <fo:block>cell1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell id="cell2" number-rows-spanned="3" display-align="center" border="solid 0.5pt">
+ <fo:block text-align="center">cell2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell id="cell3" number-rows-spanned="3" border="solid 0.5pt">
+ <fo:block>cell3</fo:block>
+ </fo:table-cell>
+ <fo:table-cell id="cell4" number-columns-spanned="2" number-rows-spanned="2" border="solid 0.5pt" background-color="lightgray">
+ <fo:block>cell4</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell id="cell5" border="solid 0.5pt">
+ <fo:block>cell5</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell id="cell6" number-columns-spanned="4" border="solid 0.5pt">
+ <fo:block text-align="end">cell6</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="1" xpath="count(//pageViewport)"/>
+ <eval expected="1" xpath="count(//block[@prod-id = 'cell1'])"/>
+ <eval expected="1" xpath="count(//block[@prod-id = 'cell2'])"/>
+ <eval expected="1" xpath="count(//block[@prod-id = 'cell3'])"/>
+ <eval expected="1" xpath="count(//block[@prod-id = 'cell4'])"/>
+ <eval expected="1" xpath="count(//block[@prod-id = 'cell5'])"/>
+ <eval expected="1" xpath="count(//block[@prod-id = 'cell6'])"/>
+ <eval expected="45200" xpath="//block[@prod-id = 'cell2']/@bpd"/>
+ <eval expected="29800" xpath="//block[@prod-id = 'cell4']/@bpd"/>
+ </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table-column_missing.xml b/test/layoutengine/standard-testcases/table-column_missing.xml
new file mode 100644
index 000000000..01521bf7b
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table-column_missing.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+ <info>
+ <p>
+ This test checks if FOP can handle the case where more columns are actually used than
+ specified.
+ </p>
+ <p>
+ Note: This test case is technically wrong since in fixed table layout all
+ column-widths must be specified. But we don't want to have FOP crash
+ with an IndexOutOfBoundsException either.
+ </p>
+ </info>
+ <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:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="normal">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:table table-layout="fixed" width="100%" border-collapse="separate">
+ <fo:table-column width="2cm"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell>
+ <fo:block>cell 1/1</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell>
+ <fo:block>cell 2/1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell>
+ <fo:block>cell 2/2</fo:block>
+ </fo:table-cell>
+ <fo:table-cell>
+ <fo:block>cell 2/3</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="14400" xpath="//flow/block/block[2]/@top-offset"/>
+ <eval expected="14400" xpath="//flow/block/block[3]/@top-offset"/>
+ <eval expected="14400" xpath="//flow/block/block[4]/@top-offset"/>
+
+ <eval expected="360000" xpath="//flow/block/block[3]/@left-offset"/>
+ <eval expected="720000" xpath="//flow/block/block[4]/@left-offset"/>
+ <eval expected="360000" xpath="//flow/block/block[3]/@ipd"/>
+ <eval expected="360000" xpath="//flow/block/block[4]/@ipd"/>
+ </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
new file mode 100644
index 000000000..55086e577
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table-row_keep-with-next2.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 keep-with-next behaviour on a table-row.
+ </p>
+ <p>
+ There used to be a bug where the keep-with-next signal wouldn't get cleared and
+ resulted in too little break possibilities.
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" widows="0" orphans="0">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="normal" page-width="5in" page-height="4.5 * 14.4pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="normal">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:table table-layout="fixed" width="100%" id="A">
+ <fo:table-column column-width="proportional-column-width(1)"/>
+ <fo:table-body>
+ <fo:table-row keep-with-next="always">
+ <fo:table-cell id="cellA1">
+ <fo:block>line1</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row keep-together="always">
+ <fo:table-cell id="cellA2">
+ <fo:block>line1</fo:block>
+ <fo:block>line2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block>block</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <element-list category="breaker">
+ <box w="14400"/>
+ <penalty w="0" p="INF"/>
+ <box w="28800"/>
+ <penalty w="0" p="0"/>
+ <box w="14400"/>
+ <skip>3</skip>
+ </element-list>
+ </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table_table-layout_fixed_2.xml b/test/layoutengine/standard-testcases/table_table-layout_fixed_2.xml
index 3ca02190e..cd611fca2 100644
--- a/test/layoutengine/standard-testcases/table_table-layout_fixed_2.xml
+++ b/test/layoutengine/standard-testcases/table_table-layout_fixed_2.xml
@@ -34,7 +34,7 @@
</fo:layout-master-set>
<fo:page-sequence master-reference="normal" white-space-collapse="true">
<fo:flow flow-name="xsl-region-body">
- <fo:table table-layout="fixed" width="300pt" border="solid 5pt">
+ <fo:table table-layout="fixed" width="300pt" border="solid 5pt" border-collapse="separate">
<fo:table-body>
<fo:table-cell width="100pt">
<fo:block>cell1</fo:block>