Browse Source

Merged revisions 636407-637074,637076-637118,637120-637790,637792-637856,637858-637992,637994-638047,638049-638307,638309-638315,638318-638936,638938-640888,640890-642905,642907-647402,647404-647536,647538-648983,648985-649005,649007-649013,649015-650549,650551-651301,651303-653536,653538-654452,654454-656285,656287-656523,656525-657519,657521-661579,661581-663481,663483-664691,664693-681285,681287-681290,681292-681298 via svnmerge from

https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_95

........
  r666635 | jeremias | 2008-06-11 14:18:53 +0200 (Mi, 11 Jun 2008) | 1 line
  
  Fixed resolution handling inside AWT preview dialog.
........
  r666662 | jeremias | 2008-06-11 15:33:20 +0200 (Mi, 11 Jun 2008) | 1 line
  
  Some notes on RTF and print output.
........
  r668533 | jeremias | 2008-06-17 09:57:55 +0200 (Di, 17 Jun 2008) | 2 lines
  
  Bugzilla #45151:
  Note on the "compiling" page that Ant 1.7 is required. The README file already points to this page.
........
  r668534 | jeremias | 2008-06-17 09:58:40 +0200 (Di, 17 Jun 2008) | 2 lines
  
  Update known issues.
  Remove ApacheConEU logo.
........
  r668550 | jeremias | 2008-06-17 10:05:22 +0200 (Di, 17 Jun 2008) | 2 lines
  
  Bugzilla #45146:
  Removed duplicate LICENSE.txt and Notice.txt from the JAR.
........
  r668570 | jeremias | 2008-06-17 10:54:07 +0200 (Di, 17 Jun 2008) | 1 line
  
  Wrong line number reported in the case of a line overflow.
........
  r668641 | jeremias | 2008-06-17 14:59:25 +0200 (Di, 17 Jun 2008) | 1 line
  
  Fixed potential NPE.
........
  r669118 | jeremias | 2008-06-18 11:02:45 +0200 (Mi, 18 Jun 2008) | 4 lines
  
  Bugzilla #44412:
  Regression fix for empty pages caused by multiple collapsible breaks.
  No more empty block areas if a break-before occurs on the first child of an FO to match the behaviour of tables and other FO implementations (clarification by XSL WG pending).
  Added an accessor interface for break-before/-after to avoid long if..else lists in BlockStackingLayoutManager.
........
  r669173 | jeremias | 2008-06-18 16:07:27 +0200 (Mi, 18 Jun 2008) | 7 lines
  
  Bugzilla #44887:
  Fixed potential multi-threading problem concerning the use of DecimalFormat.
  
  Results from performance measurements in a separate test (operation repeated 100'000 times, exemplary):
  shared static variable: ~220ms (old choice, problematic!)
  always create new instance: ~480ms
  ThreadLocal: ~220ms (new choice)
........
  r669478 | jeremias | 2008-06-19 15:03:57 +0200 (Do, 19 Jun 2008) | 4 lines
  
  Bugzilla #44412:
  Improvements after Vincent's feedback:
  Removal of the somewhat ugly Reference.
  getBreakBefore() reduced to private visibility.
........
  r670551 | jeremias | 2008-06-23 14:54:27 +0200 (Mo, 23 Jun 2008) | 3 lines
  
  Use configured source and target resolution for foreign objects in RTF output.
  Fixed intrinsic size calculation for SVG images when source resolution is not 72 dpi.
  Fixed calculation of px2mm values in the SVG to G2D converter (used by RTF output).
........
  r673750 | adelmelle | 2008-07-03 20:25:01 +0200 (Do, 03 Jul 2008) | 1 line
  
  Fix for Bugzilla 45295 (already committed to the trunk with r672010, r672495 and r672496)
........
  r674304 | jeremias | 2008-07-06 17:09:10 +0200 (So, 06 Jul 2008) | 18 lines
  
  Bugzilla #43606:
  column-width accepts percent values (proportional-column-width and % working)
  Table width accepts percent values (100% of the page width as standard)
  Nested tables are working
  It is also possible to make nested tables with a higher depth than 3 without causing word to crash
  Submitted by: Maximilan Aster <maximilian.aster.at.boc-eu.com>
  
  Changes to the patch by Jeremias:
  - Patch simplified (reuse of ColumnSetup from the layoutmgr package)
  - Percentages and proportional-column-width didn't work properly in my tests -> fixed
  - Adjustments for FOP code conventions
  
  Bugzilla #43824:
  page-number-citation working but has to be refreshed inside word to show the correct values
  Submitted by: Maximilan Aster <maximilian.aster.at.boc-eu.com>
  
  Changes to the patch by Jeremias:
  - Adjustments for FOP code conventions
........
  r674314 | jeremias | 2008-07-06 18:40:08 +0200 (So, 06 Jul 2008) | 7 lines
  
  Bugzilla #43825:
  leader supports fixed percent values for leader-length, most other properties
  use-content, leader-pattern-width not implemented
  Submitted by: Maximilan Aster <maximilian.aster.at.boc-eu.com>
  
  Changes to the patch by Jeremias:
  - Adjustments for FOP code conventions
........
  r674317 | jeremias | 2008-07-06 18:44:43 +0200 (So, 06 Jul 2008) | 1 line
  
  Doc update after RTF changes.
........
  r675106 | jeremias | 2008-07-09 09:03:46 +0200 (Mi, 09 Jul 2008) | 2 lines
  
  Bugzilla #45366:
  Document missing feature.
........
  r675150 | jeremias | 2008-07-09 14:56:41 +0200 (Mi, 09 Jul 2008) | 2 lines
  
  Bugzilla #39980:
  Fixed image scaling for RTF output.
........
  r675151 | jeremias | 2008-07-09 14:57:06 +0200 (Mi, 09 Jul 2008) | 1 line
  
  Removed unused code.
........
  r675152 | jeremias | 2008-07-09 14:58:18 +0200 (Mi, 09 Jul 2008) | 1 line
  
  Don't generate commands for default values.
........
  r675707 | jeremias | 2008-07-10 21:58:27 +0200 (Do, 10 Jul 2008) | 1 line
  
  Bugfix: -imagein didn't work because the stylesheet didn't get copied into fop.jar.
........
  r680715 | jeremias | 2008-07-29 16:37:10 +0200 (Di, 29 Jul 2008) | 1 line
  
  Found a surplus "pop state" which somehow causes a regression (fill color doesn't get properly reset) between 0.94 and 0.95. Shows in Barcode4J's fop-extension-demo.fo. The line has already been there in 0.94 but only shows in 0.95 probably due to an additional save/restore state pair added in PDFRenderer for reference areas after the block-container area refactoring.
........
  r680820 | jeremias | 2008-07-29 22:02:14 +0200 (Di, 29 Jul 2008) | 2 lines
  
  Bugzilla #41306:
  The AWT Renderer is really not out-of-order capable.
........
  r681284 | jeremias | 2008-07-31 08:47:49 +0200 (Do, 31 Jul 2008) | 1 line
  
  Some updates to status.xml (I was not the only one working on the final release).
........
  r681290 | jeremias | 2008-07-31 09:44:51 +0200 (Do, 31 Jul 2008) | 2 lines
  
  Website updates for the 0.95 release.
  The projectInfo plug-in of Forrest is not ideal for doing a bugfix release. It's not possible to combine the changes for two releases.
........
  r681292 | jeremias | 2008-07-31 09:47:13 +0200 (Do, 31 Jul 2008) | 1 line
  
  Disabling the ApacheCon ad for the release build.
........


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@681307 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Jeremias Maerki 15 years ago
parent
commit
178483e309
53 changed files with 1419 additions and 398 deletions
  1. 8
    4
      README
  2. 1
    0
      build.xml
  3. 3
    6
      known-issues.xml
  4. BIN
      lib/avalon-framework-4.2.0.jar
  5. 1
    1
      src/documentation/content/xdocs/0.95/compiling.xml
  6. 28
    0
      src/documentation/content/xdocs/0.95/output.xml
  7. 1
    0
      src/documentation/content/xdocs/knownissues.xml
  8. 4
    3
      src/documentation/content/xdocs/site.xml
  9. 1
    1
      src/documentation/content/xdocs/tabs.xml
  10. 1
    1
      src/documentation/content/xdocs/trunk/compiling.xml
  11. 29
    0
      src/documentation/content/xdocs/trunk/output.xml
  12. 2
    0
      src/documentation/skinconf.xml
  13. 2
    1
      src/java/org/apache/fop/fo/flow/Block.java
  14. 2
    1
      src/java/org/apache/fop/fo/flow/BlockContainer.java
  15. 2
    1
      src/java/org/apache/fop/fo/flow/ListBlock.java
  16. 2
    1
      src/java/org/apache/fop/fo/flow/ListItem.java
  17. 2
    1
      src/java/org/apache/fop/fo/flow/table/Table.java
  18. 1
    1
      src/java/org/apache/fop/fo/flow/table/TableAndCaption.java
  19. 2
    1
      src/java/org/apache/fop/fo/flow/table/TableRow.java
  20. 33
    0
      src/java/org/apache/fop/fo/properties/BreakPropertySet.java
  21. 2
    2
      src/java/org/apache/fop/fonts/MultiByteFont.java
  22. 2
    2
      src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java
  23. 11
    3
      src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java
  24. 6
    3
      src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
  25. 32
    25
      src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
  26. 6
    8
      src/java/org/apache/fop/layoutmgr/LayoutContext.java
  27. 2
    3
      src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
  28. 16
    4
      src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java
  29. 8
    6
      src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
  30. 30
    22
      src/java/org/apache/fop/pdf/PDFNumber.java
  31. 18
    14
      src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java
  32. 9
    3
      src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java
  33. 0
    1
      src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
  34. 6
    4
      src/java/org/apache/fop/render/rtf/BorderAttributesConverter.java
  35. 5
    2
      src/java/org/apache/fop/render/rtf/FoUnitsConverter.java
  36. 4
    1
      src/java/org/apache/fop/render/rtf/PageAttributesConverter.java
  37. 210
    242
      src/java/org/apache/fop/render/rtf/RTFHandler.java
  38. 134
    2
      src/java/org/apache/fop/render/rtf/TextAttributesConverter.java
  39. 10
    0
      src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java
  40. 63
    3
      src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java
  41. 219
    0
      src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLeader.java
  42. 4
    2
      src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java
  43. 4
    4
      src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java
  44. 20
    1
      src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java
  45. 2
    2
      src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java
  46. 19
    1
      src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java
  47. 136
    0
      src/java/org/apache/fop/render/rtf/rtflib/tools/PercentContext.java
  48. 2
    1
      src/java/org/apache/fop/util/BreakUtil.java
  49. 106
    1
      status.xml
  50. 45
    0
      test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java
  51. 4
    13
      test/layoutengine/standard-testcases/block_break-before_bug44412.xml
  52. 151
    0
      test/layoutengine/standard-testcases/block_break-before_bug44412_2.xml
  53. 8
    0
      test/resources/images/circles.svg

+ 8
- 4
README View File

@@ -90,11 +90,11 @@ http://xmlgraphics.apache.org/fop/stable/running.html
RELEASE NOTES
==============================================================================

Version 0.95beta
================
Version 0.95
============

This is a pre-version of the third production grade release of the new FOP
codebase. It contains many bug fixes and new features. See below for details.
This is a production grade release of Apache FOP.
It contains many bug fixes and new features. See below for details.

Compliance
----------
@@ -128,6 +128,10 @@ http://xmlgraphics.apache.org/fop/0.95/changes_0.95.html.
The long list of changes in this and earlier releases is available at
http://xmlgraphics.apache.org/fop/changes.html.

Changes since Version 0.95beta
------------------------------
Please refer to the list of changes on the web:
http://xmlgraphics.apache.org/fop/changes.html


Version 0.94

+ 1
- 0
build.xml View File

@@ -401,6 +401,7 @@ list of possible build targets.
<include name="**/*.icm"/>
<include name="**/*.xml"/>
<include name="**/*.LICENSE.txt"/>
<include name="**/*.xsl"/>
</fileset>
<fileset dir="${build.gensrc.dir}">
<include name="**/*.xml"/>

+ 3
- 6
known-issues.xml View File

@@ -21,8 +21,9 @@
MIF and SVG output support have not been restored, yet.
</known-issue>
<known-issue>
Java2D/AWT support has been improved, but some problems remain,
for example with block-containers.
RTF output is inferior to other output formats supported by FOP.
For details, please see the "Output Targets" page of the release
you're using.
</known-issue>
<known-issue>
Auto table layout is not implemented, yet.
@@ -80,10 +81,6 @@
Not all FO elements can be referenced by their "id", most notably:
table-body, table-header, table-footer and table-row.
</known-issue>
<known-issue>
The backgrounds of table-body, table-header, table-footer and
table-column are not painted, yet.
</known-issue>
<known-issue>
Border and padding conditionality are not supported on table-cells, yet.
</known-issue>

BIN
lib/avalon-framework-4.2.0.jar View File


+ 1
- 1
src/documentation/content/xdocs/0.95/compiling.xml View File

@@ -66,7 +66,7 @@
<section id="env-ant">
<title>Apache Ant</title>
<p>
<a href="ext:ant">Apache Ant</a> must be installed in order to
<a href="ext:ant">Apache Ant</a> (Version 1.7 or later) must be installed in order to
build FOP. Following best practices we don't include Ant with FOP anymore. You can find the
<a href="ext:ant/manual/">instructions to install Ant in the Ant manual</a> on the web.
</p>

+ 28
- 0
src/documentation/content/xdocs/0.95/output.xml View File

@@ -703,6 +703,24 @@ out = proc.getOutputStream();]]></source>
<note>RTF output is currently unmaintained and lacks many features compared to other output
formats. Using other editable formats like Open Document Format, instead of producing XSL-FO
then RTF through FOP, might give better results.</note>
<p>
These are some known restrictions compared to other supported output formats (not a complete list):
</p>
<ul>
<li>
Not supported/implemented:
<ul>
<li>break-before/after (supported by the RTF library but not tied into the RTFHandler)</li>
<li>fo:page-number-citation-last</li>
<li>keeps (supported by the RTF library but not tied into the RTFHandler)</li>
<li>region-start/end (RTF limitation)</li>
<li>multiple columns</li>
</ul>
</li>
<li>Only a single page-master is supported</li>
<li>Not all variations of fo:leader are supported (RTF limitation)</li>
<li>percentages are not supported everywhere</li>
</ul>
</section>
<section id="xml">
<title>XML (Area Tree XML)</title>
@@ -735,6 +753,16 @@ out = proc.getOutputStream();]]></source>
It is possible to directly print the document from the command line.
This is done with the same code that renders to the Java2D/AWT renderer.
</p>
<section id="print-issues">
<title>Known issues</title>
<p>
If you run into the problem that the printed output is incomplete on Windows:
this often happens to users printing to a PCL printer.
There seems to be an incompatibility between Java and certain PCL printer drivers
on Windows. Since most network-enabled laser printers support PostScript, try
switching to the PostScript printer driver for that printer model.
</p>
</section>
</section>
<section id="bitmap">
<title>Bitmap (TIFF/PNG)</title>

+ 1
- 0
src/documentation/content/xdocs/knownissues.xml View File

@@ -66,6 +66,7 @@
<section>
<title>Other known issues</title>
<p>This section lists other known issues.</p>
<!-- See <root>/known-issues.xml for the source document of this section! -->
<xi:include href="cocoon://knownissues-raw-static.xml#xpointer(/document/body/*)"/>
</section>
</section>

+ 4
- 3
src/documentation/content/xdocs/site.xml View File

@@ -96,10 +96,11 @@
<!--
BEGIN Version 0.95 documentation tab
-->
<trunk label="FOP 0.95beta" href="0.95/" tab="stableversion">
<trunk label="FOP 0.95" href="0.95/" tab="stableversion">
<about label="About" href="index.html"/>
<release label="Release Notes" href="releaseNotes_0.95beta.html"/>
<changes label="Changes" href="changes_0.95beta.html"/>
<release label="Release Notes" href="releaseNotes_0.95.html"/>
<changes label="Changes (0.95)" href="changes_0.95.html"/>
<changes-beta label="Changes (0.95beta)" href="changes_0.95beta.html"/>
<knownissues label="Known Issues" href="knownissues_overview.html"/>
<upgrading label="Upgrading" href="upgrading.html"/>

+ 1
- 1
src/documentation/content/xdocs/tabs.xml View File

@@ -22,7 +22,7 @@
<tabs software="FOP" title="FOP" copyright="@year@ The Apache Software Foundation" xmlns:xlink="http://www.w3.org/1999/xlink">
<tab label="Home" dir=""/>
<tab label="Version 0.94" dir="0.94/"/>
<tab label="Version 0.95beta" dir="0.95/"/>
<tab label="Version 0.95" dir="0.95/"/>
<tab label="FOP Trunk" dir="trunk/"/>
<tab label="Development" dir="dev/"/>
</tabs>

+ 1
- 1
src/documentation/content/xdocs/trunk/compiling.xml View File

@@ -66,7 +66,7 @@
<section id="env-ant">
<title>Apache Ant</title>
<p>
<a href="ext:ant">Apache Ant</a> must be installed in order to
<a href="ext:ant">Apache Ant</a> (Version 1.7 or later) must be installed in order to
build FOP. Following best practices we don't include Ant with FOP anymore. You can find the
<a href="ext:ant/manual/">instructions to install Ant in the Ant manual</a> on the web.
</p>

+ 29
- 0
src/documentation/content/xdocs/trunk/output.xml View File

@@ -728,6 +728,24 @@ out = proc.getOutputStream();]]></source>
<note>RTF output is currently unmaintained and lacks many features compared to other output
formats. Using other editable formats like Open Document Format, instead of producing XSL-FO
then RTF through FOP, might give better results.</note>
<p>
These are some known restrictions compared to other supported output formats (not a complete list):
</p>
<ul>
<li>
Not supported/implemented:
<ul>
<li>break-before/after (supported by the RTF library but not tied into the RTFHandler)</li>
<li>fo:page-number-citation-last</li>
<li>keeps (supported by the RTF library but not tied into the RTFHandler)</li>
<li>region-start/end (RTF limitation)</li>
<li>multiple columns</li>
</ul>
</li>
<li>Only a single page-master is supported</li>
<li>Not all variations of fo:leader are supported (RTF limitation)</li>
<li>percentages are not supported everywhere</li>
</ul>
</section>
<section id="xml">
<title>XML (Area Tree XML)</title>
@@ -760,6 +778,16 @@ out = proc.getOutputStream();]]></source>
It is possible to directly print the document from the command line.
This is done with the same code that renders to the Java2D/AWT renderer.
</p>
<section id="print-issues">
<title>Known issues</title>
<p>
If you run into the problem that the printed output is incomplete on Windows:
this often happens to users printing to a PCL printer.
There seems to be an incompatibility between Java and certain PCL printer drivers
on Windows. Since most network-enabled laser printers support PostScript, try
switching to the PostScript printer driver for that printer model.
</p>
</section>
</section>
<section id="bitmap">
<title>Bitmap (TIFF/PNG)</title>
@@ -911,3 +939,4 @@ out = proc.getOutputStream();]]></source>
</document>




+ 2
- 0
src/documentation/skinconf.xml View File

@@ -378,6 +378,7 @@ which will be used to configure the chosen Forrest skin.
<height>125</height>
</credit>
-->
<!--
<credit box-location="alt2">
<name>ApacheCon US 2008</name>
<url>http://us.apachecon.com/</url>
@@ -385,6 +386,7 @@ which will be used to configure the chosen Forrest skin.
<width>125</width>
<height>125</height>
</credit>
-->
<credit role="pdf">
<name>PDF created by Apache FOP</name>

+ 2
- 1
src/java/org/apache/fop/fo/flow/Block.java View File

@@ -32,6 +32,7 @@ import org.apache.fop.fo.FObjMixed;
import org.apache.fop.fo.NullCharIterator;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonFont;
import org.apache.fop.fo.properties.CommonHyphenation;
@@ -44,7 +45,7 @@ import org.apache.fop.fo.properties.SpaceProperty;
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_block">
* <code>fo:block object</code></a>.
*/
public class Block extends FObjMixed {
public class Block extends FObjMixed implements BreakPropertySet {

// used for FO validation
private boolean blockOrInlineItemFound = false;

+ 2
- 1
src/java/org/apache/fop/fo/flow/BlockContainer.java View File

@@ -28,6 +28,7 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
import org.apache.fop.fo.properties.CommonAbsolutePosition;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
@@ -38,7 +39,7 @@ import org.apache.fop.fo.properties.LengthRangeProperty;
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_block-container">
* <code>fo:block-container</code></a> object.
*/
public class BlockContainer extends FObj {
public class BlockContainer extends FObj implements BreakPropertySet {
// The value of properties relevant for fo:block-container.
private CommonAbsolutePosition commonAbsolutePosition;
private CommonBorderPaddingBackground commonBorderPaddingBackground;

+ 2
- 1
src/java/org/apache/fop/fo/flow/ListBlock.java View File

@@ -27,6 +27,7 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.KeepProperty;
@@ -35,7 +36,7 @@ import org.apache.fop.fo.properties.KeepProperty;
* Class modelling the <a href=http://www.w3.org/TR/xsl/#fo_list-block">
* <code>fo:list-block</code></a> object.
*/
public class ListBlock extends FObj {
public class ListBlock extends FObj implements BreakPropertySet {
// The value of properties relevant for fo:list-block.
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonMarginBlock commonMarginBlock;

+ 2
- 1
src/java/org/apache/fop/fo/flow/ListItem.java View File

@@ -26,6 +26,7 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.KeepProperty;
@@ -34,7 +35,7 @@ import org.apache.fop.fo.properties.KeepProperty;
* Class modelling the <a href=http://www.w3.org/TR/xsl/#fo_list-item">
* <code>fo:list-item</code></a> object.
*/
public class ListItem extends FObj {
public class ListItem extends FObj implements BreakPropertySet {
// The value of properties relevant for fo:list-item.
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonMarginBlock commonMarginBlock;

+ 2
- 1
src/java/org/apache/fop/fo/flow/table/Table.java View File

@@ -31,6 +31,7 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.StaticPropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.KeepProperty;
@@ -42,7 +43,7 @@ import org.apache.fop.fo.properties.TableColLength;
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table">
* <code>fo:table</code></a> object.
*/
public class Table extends TableFObj implements ColumnNumberManagerHolder {
public class Table extends TableFObj implements ColumnNumberManagerHolder, BreakPropertySet {

/** properties */
private CommonBorderPaddingBackground commonBorderPaddingBackground;

+ 1
- 1
src/java/org/apache/fop/fo/flow/table/TableAndCaption.java View File

@@ -32,7 +32,7 @@ import org.apache.fop.fo.ValidationException;
* <code>fo:table-and-caption</code></a> property.
* @todo needs implementation
*/
public class TableAndCaption extends FObj {
public class TableAndCaption extends FObj /*implements BreakPropertySet*/ {
// The value of properties relevant for fo:table-and-caption.
// Unused but valid items, commented out for performance:
// private CommonAccessibility commonAccessibility;

+ 2
- 1
src/java/org/apache/fop/fo/flow/table/TableRow.java View File

@@ -27,6 +27,7 @@ import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fo.properties.LengthRangeProperty;
@@ -35,7 +36,7 @@ import org.apache.fop.fo.properties.LengthRangeProperty;
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-row">
* <code>fo:table-row</code></a> object.
*/
public class TableRow extends TableCellContainer {
public class TableRow extends TableCellContainer implements BreakPropertySet {
// The value of properties relevant for fo:table-row.
private LengthRangeProperty blockProgressionDimension;
private CommonBorderPaddingBackground commonBorderPaddingBackground;

+ 33
- 0
src/java/org/apache/fop/fo/properties/BreakPropertySet.java View File

@@ -0,0 +1,33 @@
/*
* 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.properties;

/**
* Defines property access methods for the break-before and break-after properties.
*/
public interface BreakPropertySet {

/** @return the "break-after" property. */
int getBreakAfter();

/** @return the "break-before" property. */
int getBreakBefore();
}

+ 2
- 2
src/java/org/apache/fop/fonts/MultiByteFont.java View File

@@ -29,7 +29,6 @@ import java.util.Map;
public class MultiByteFont extends CIDFont {

private static int uniqueCounter = -1;
private static final DecimalFormat COUNTER_FORMAT = new DecimalFormat("00000");

private String ttcName = null;
private String encoding = "Identity-H";
@@ -58,7 +57,8 @@ public class MultiByteFont extends CIDFont {
uniqueCounter = 0; //We need maximum 5 character then we start again
}
}
String cntString = COUNTER_FORMAT.format(uniqueCounter);
DecimalFormat counterFormat = new DecimalFormat("00000");
String cntString = counterFormat.format(uniqueCounter);

//Subset prefix as described in chapter 5.5.3 of PDF 1.4
StringBuffer sb = new StringBuffer("E");

+ 2
- 2
src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java View File

@@ -68,10 +68,10 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter {
}

//Prepare
float pxToMillimeter = (float)UnitConv.mm2in(72); //default: 72dpi
float pxToMillimeter = UnitConv.IN2MM / 72; //default: 72dpi
Number ptm = (Number)hints.get(ImageProcessingHints.SOURCE_RESOLUTION);
if (ptm != null) {
pxToMillimeter = (float)UnitConv.mm2in(ptm.doubleValue());
pxToMillimeter = (float)(UnitConv.IN2MM / ptm.doubleValue());
}
UserAgent ua = createBatikUserAgent(pxToMillimeter);
GVTBuilder builder = new GVTBuilder();

+ 11
- 3
src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java View File

@@ -46,6 +46,7 @@ import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.util.MimeConstants;
import org.apache.xmlgraphics.util.UnitConv;

import org.apache.fop.svg.SimpleSVGUserAgent;
import org.apache.fop.util.UnclosableInputStream;
@@ -119,7 +120,7 @@ public class PreloaderSVG extends AbstractImagePreloader {
in.mark(length + 1);
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(
getParserName());
doc = (SVGDocument) factory.createSVGDocument(src.getSystemId(), in);
doc = factory.createSVGDocument(src.getSystemId(), in);
}
ImageInfo info = createImageInfo(uri, context, doc);

@@ -154,7 +155,7 @@ public class PreloaderSVG extends AbstractImagePreloader {

private ImageInfo createImageInfo(String uri, ImageContext context, SVGDocument doc) {
Element e = doc.getRootElement();
float pxUnitToMillimeter = 25.4f / context.getSourceResolution();
float pxUnitToMillimeter = UnitConv.IN2MM / context.getSourceResolution();
UserAgent userAg = new SimpleSVGUserAgent(pxUnitToMillimeter,
new AffineTransform()) {

@@ -184,9 +185,12 @@ public class PreloaderSVG extends AbstractImagePreloader {
float height = UnitProcessor.svgVerticalLengthToUserSpace(
s, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE, uctx);

int widthMpt = (int)Math.round(px2mpt(width, context.getSourceResolution()));
int heightMpt = (int)Math.round(px2mpt(height, context.getSourceResolution()));

ImageInfo info = new ImageInfo(uri, MimeConstants.MIME_SVG);
ImageSize size = new ImageSize();
size.setSizeInMillipoints(Math.round(width * 1000), Math.round(height * 1000));
size.setSizeInMillipoints(widthMpt, heightMpt);
//Set the resolution to that of the FOUserAgent
size.setResolution(context.getSourceResolution());
size.calcPixelsFromSize();
@@ -210,4 +214,8 @@ public class PreloaderSVG extends AbstractImagePreloader {

}

private static double px2mpt(double px, double resolution) {
return px * 1000 * UnitConv.IN2PT / resolution;
}

}

+ 6
- 3
src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java View File

@@ -251,12 +251,11 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
List returnList = new LinkedList();

if (!breakBeforeServed) {
try {
breakBeforeServed = true;
if (!context.suppressBreakBefore()) {
if (addKnuthElementsForBreakBefore(returnList, context)) {
return returnList;
}
} finally {
breakBeforeServed = true;
}
}

@@ -281,6 +280,10 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit));
childLC.setRefIPD(relDims.ipd);
childLC.setWritingMode(getBlockContainerFO().getWritingMode());
if (curLM == this.childLMs.get(0)) {
childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
//Handled already by the parent (break collapsing, see above)
}

// get elements from curLM
returnedList = curLM.getNextKnuthElements(childLC, alignment);

+ 32
- 25
src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java View File

@@ -31,11 +31,13 @@ import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.area.BlockParent;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.properties.BreakPropertySet;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.SpaceProperty;
import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
import org.apache.fop.layoutmgr.inline.LineLayoutManager;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.util.BreakUtil;
import org.apache.fop.util.ListUtil;

/**
@@ -255,12 +257,11 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
List returnList = new LinkedList();

if (!breakBeforeServed) {
try {
breakBeforeServed = true;
if (!context.suppressBreakBefore()) {
if (addKnuthElementsForBreakBefore(returnList, context)) {
return returnList;
}
} finally {
breakBeforeServed = true;
}
}

@@ -294,6 +295,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
childLC.setStackLimitBP(context.getStackLimitBP());
childLC.setRefIPD(referenceIPD);
}
if (curLM == this.childLMs.get(0)) {
childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
//Handled already by the parent (break collapsing, see above)
}

// get elements from curLM
returnedList = curLM.getNextKnuthElements(childLC, alignment);
@@ -1004,18 +1009,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
*/
protected boolean addKnuthElementsForBreakBefore(List returnList,
LayoutContext context) {
int breakBefore = -1;
if (fobj instanceof org.apache.fop.fo.flow.Block) {
breakBefore = ((org.apache.fop.fo.flow.Block) fobj).getBreakBefore();
} else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) {
breakBefore = ((org.apache.fop.fo.flow.BlockContainer) fobj).getBreakBefore();
} else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) {
breakBefore = ((org.apache.fop.fo.flow.ListBlock) fobj).getBreakBefore();
} else if (fobj instanceof org.apache.fop.fo.flow.ListItem) {
breakBefore = ((org.apache.fop.fo.flow.ListItem) fobj).getBreakBefore();
} else if (fobj instanceof org.apache.fop.fo.flow.table.Table) {
breakBefore = ((org.apache.fop.fo.flow.table.Table) fobj).getBreakBefore();
}
int breakBefore = getBreakBefore();
if (breakBefore == EN_PAGE
|| breakBefore == EN_COLUMN
|| breakBefore == EN_EVEN_PAGE
@@ -1029,6 +1023,27 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
}
}

/**
* Returns the break-before value of the current formatting object.
* @return the break-before value (Constants.EN_*)
*/
private int getBreakBefore() {
int breakBefore = EN_AUTO;
if (fobj instanceof BreakPropertySet) {
breakBefore = ((BreakPropertySet)fobj).getBreakBefore();
}
if (true /* uncomment to only partially merge: && breakBefore != EN_AUTO*/) {
LayoutManager lm = getChildLM();
//It is assumed this is only called when the first LM is active.
if (lm instanceof BlockStackingLayoutManager) {
BlockStackingLayoutManager bslm = (BlockStackingLayoutManager)lm;
breakBefore = BreakUtil.compareBreakClasses(
breakBefore, bslm.getBreakBefore());
}
}
return breakBefore;
}
/**
* Creates Knuth elements for break-after and adds them to the return list.
* @param returnList return list to add the additional elements to
@@ -1038,16 +1053,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
protected boolean addKnuthElementsForBreakAfter(List returnList,
LayoutContext context) {
int breakAfter = -1;
if (fobj instanceof org.apache.fop.fo.flow.Block) {
breakAfter = ((org.apache.fop.fo.flow.Block) fobj).getBreakAfter();
} else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) {
breakAfter = ((org.apache.fop.fo.flow.BlockContainer) fobj).getBreakAfter();
} else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) {
breakAfter = ((org.apache.fop.fo.flow.ListBlock) fobj).getBreakAfter();
} else if (fobj instanceof org.apache.fop.fo.flow.ListItem) {
breakAfter = ((org.apache.fop.fo.flow.ListItem) fobj).getBreakAfter();
} else if (fobj instanceof org.apache.fop.fo.flow.table.Table) {
breakAfter = ((org.apache.fop.fo.flow.table.Table) fobj).getBreakAfter();
if (fobj instanceof BreakPropertySet) {
breakAfter = ((BreakPropertySet)fobj).getBreakAfter();
}
if (breakAfter == EN_PAGE
|| breakAfter == EN_COLUMN

+ 6
- 8
src/java/org/apache/fop/layoutmgr/LayoutContext.java View File

@@ -47,12 +47,10 @@ public class LayoutContext {
public static final int CHECK_REF_AREA = 0x08;

/**
* If this flag is set, it indicates that any leading fo:character
* objects with suppress-at-line-break="suppress" should not generate
* areas. This is the case at the beginning of each new LineArea
* except the first.
* If this flag is set, it indicates that any break-before values other than "auto" should
* not cause a mandatory break as this break was already handled by a parent layout manager.
*/
public static final int SUPPRESS_LEADING_SPACE = 0x10;
public static final int SUPPRESS_BREAK_BEFORE = 0x10;
public static final int FIRST_AREA = 0x20;
public static final int TRY_HYPHENATE = 0x40;
public static final int LAST_AREA = 0x80;
@@ -227,8 +225,8 @@ public class LayoutContext {
return ((this.flags & LAST_AREA) != 0);
}

public boolean suppressLeadingSpace() {
return ((this.flags & SUPPRESS_LEADING_SPACE) != 0);
public boolean suppressBreakBefore() {
return ((this.flags & SUPPRESS_BREAK_BEFORE) != 0);
}

/**
@@ -655,7 +653,7 @@ public class LayoutContext {
+ "\nSpace Adjust: \t" + getSpaceAdjust()
+ "\nIPD Adjust: \t" + getIPDAdjust()
+ "\nResolve Leading Space: \t" + resolveLeadingSpace()
+ "\nSuppress Leading Space: \t" + suppressLeadingSpace()
+ "\nSuppress Break Before: \t" + suppressBreakBefore()
+ "\nIs First Area: \t" + isFirstArea()
+ "\nStarts New Area: \t" + startsNewArea()
+ "\nIs Last Area: \t" + isLastArea()

+ 2
- 3
src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java View File

@@ -197,12 +197,11 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
List returnList = new LinkedList();

if (!breakBeforeServed) {
try {
breakBeforeServed = true;
if (!context.suppressBreakBefore()) {
if (addKnuthElementsForBreakBefore(returnList, context)) {
return returnList;
}
} finally {
breakBeforeServed = true;
}
}


+ 16
- 4
src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java View File

@@ -184,10 +184,22 @@ public class ColumnSetup {
* @return the computed base unit (in millipoint)
*/
protected double computeTableUnit(TableLayoutManager tlm) {
return computeTableUnit(tlm, tlm.getContentAreaIPD());
}

/**
* Works out the base unit for resolving proportional-column-width()
* [p-c-w(x) = x * base_unit_ipd]
*
* @param percentBaseContext the percent base context for relative values
* @param contentAreaIPD the IPD of the available content area
* @return the computed base unit (in millipoints)
*/
public float computeTableUnit(PercentBaseContext percentBaseContext, int contentAreaIPD) {

int sumCols = 0;
float factors = 0;
double unit = 0;
float unit = 0;

/* calculate the total width (specified absolute/percentages),
* and work out the total number of factors to use to distribute
@@ -196,7 +208,7 @@ public class ColumnSetup {
for (Iterator i = colWidths.iterator(); i.hasNext();) {
Length colWidth = (Length) i.next();
if (colWidth != null) {
sumCols += colWidth.getValue(tlm);
sumCols += colWidth.getValue(percentBaseContext);
if (colWidth instanceof RelativeNumericProperty) {
factors += ((RelativeNumericProperty) colWidth).getTableUnits();
} else if (colWidth instanceof TableColLength) {
@@ -209,8 +221,8 @@ public class ColumnSetup {
* factors (if any)
*/
if (factors > 0) {
if (sumCols < tlm.getContentAreaIPD()) {
unit = (tlm.getContentAreaIPD() - sumCols) / factors;
if (sumCols < contentAreaIPD) {
unit = (contentAreaIPD - sumCols) / factors;
} else {
log.warn("No space remaining to distribute over columns.");
}

+ 8
- 6
src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java View File

@@ -267,12 +267,14 @@ public class TableLayoutManager extends BlockStackingLayoutManager
}
addKnuthElementsForSpaceAfter(returnList, alignment);

//addKnuthElementsForBreakBefore(returnList, context);
int breakBefore = BreakUtil.compareBreakClasses(getTable().getBreakBefore(),
childLC.getBreakBefore());
if (breakBefore != Constants.EN_AUTO) {
returnList.add(0, new BreakElement(getAuxiliaryPosition(), 0,
-KnuthElement.INFINITE, breakBefore, context));
if (!context.suppressBreakBefore()) {
//addKnuthElementsForBreakBefore(returnList, context);
int breakBefore = BreakUtil.compareBreakClasses(getTable().getBreakBefore(),
childLC.getBreakBefore());
if (breakBefore != Constants.EN_AUTO) {
returnList.add(0, new BreakElement(getAuxiliaryPosition(), 0,
-KnuthElement.INFINITE, breakBefore, context));
}
}

//addKnuthElementsForBreakAfter(returnList, context);

+ 30
- 22
src/java/org/apache/fop/pdf/PDFNumber.java View File

@@ -67,11 +67,33 @@ public class PDFNumber extends PDFObject {
return doubleOut(doubleDown, 6);
}

// Static cache. Possible concurrency implications. See comment in doubleOut(double, int).
private static DecimalFormat[] decimalFormatCache = new DecimalFormat[17];

private static final String BASE_FORMAT = "0.################";

private static class DecimalFormatThreadLocal extends ThreadLocal {
private int dec;
public DecimalFormatThreadLocal(int dec) {
this.dec = dec;
}
protected synchronized Object initialValue() {
String s = "0";
if (dec > 0) {
s = BASE_FORMAT.substring(0, dec + 2);
}
DecimalFormat df = new DecimalFormat(s, new DecimalFormatSymbols(Locale.US));
return df;
}
};
//DecimalFormat is not thread-safe!
private static final ThreadLocal[] DECIMAL_FORMAT_CACHE = new DecimalFormatThreadLocal[17];
static {
for (int i = 0, c = DECIMAL_FORMAT_CACHE.length; i < c; i++) {
DECIMAL_FORMAT_CACHE[i] = new DecimalFormatThreadLocal(i);
}
}
/**
* Output a double value to a string suitable for PDF.
* In this method it is possible to set the maximum
@@ -82,29 +104,15 @@ public class PDFNumber extends PDFObject {
* @return the value as a string
*/
public static String doubleOut(double doubleDown, int dec) {
if (dec < 0 || dec >= decimalFormatCache.length) {
if (dec < 0 || dec >= DECIMAL_FORMAT_CACHE.length) {
throw new IllegalArgumentException("Parameter dec must be between 1 and "
+ (decimalFormatCache.length + 1));
+ (DECIMAL_FORMAT_CACHE.length + 1));
}
if (decimalFormatCache[dec] == null) {
//We don't care about the rare case where a DecimalFormat might be replaced in
//a multi-threaded environment, so we don't synchronize the access to the static
//array (mainly for performance reasons). After all, the DecimalFormat instances
//read-only objects so it doesn't matter which instance is used as long as one
//is available.
String s = "0";
if (dec > 0) {
s = BASE_FORMAT.substring(0, dec + 2);
}
DecimalFormat df = new DecimalFormat(s, new DecimalFormatSymbols(Locale.US));
decimalFormatCache[dec] = df;
}
return decimalFormatCache[dec].format(doubleDown);
DecimalFormat df = (DecimalFormat)DECIMAL_FORMAT_CACHE[dec].get();
return df.format(doubleDown);
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
protected String toPDFString() {
if (getNumber() == null) {
throw new IllegalArgumentException(

+ 18
- 14
src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java View File

@@ -38,7 +38,6 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
@@ -60,8 +59,8 @@ import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.render.awt.AWTRenderer;

/**
@@ -76,6 +75,8 @@ public class PreviewDialog extends JFrame implements StatusListener {
protected AWTRenderer renderer;
/** The FOUserAgent associated with this window */
protected FOUserAgent foUserAgent;
/** The originally configured target resolution */
protected float configuredTargetResolution;
/**
* Renderable instance that can be used to reload and re-render a document after
* modifications.
@@ -107,6 +108,7 @@ public class PreviewDialog extends JFrame implements StatusListener {
public PreviewDialog(FOUserAgent foUserAgent, Renderable renderable) {
renderer = (AWTRenderer) foUserAgent.getRendererOverride();
this.foUserAgent = foUserAgent;
this.configuredTargetResolution = this.foUserAgent.getTargetResolution();
this.renderable = renderable;
translator = new Translator();

@@ -551,23 +553,23 @@ public class PreviewDialog extends JFrame implements StatusListener {
}

private void scaleActionPerformed(ActionEvent e) {
try {
int index = scale.getSelectedIndex();
if (index == 0) {
setScale(previewPanel.getScaleToFitWindow() * 100);
} else if (index == 1) {
setScale(previewPanel.getScaleToFitWidth() * 100);
} else {
String item = (String)scale.getSelectedItem();
setScale(Double.parseDouble(item.substring(0, item.indexOf('%'))));
}
} catch (FOPException fopEx) {
fopEx.printStackTrace();
int index = scale.getSelectedIndex();
if (index == 0) {
setScaleToFitWindow();
} else if (index == 1) {
setScaleToFitWidth();
} else {
String item = (String)scale.getSelectedItem();
setScale(Double.parseDouble(item.substring(0, item.indexOf('%'))));
}
}

/** Prints the document */
public void startPrinterJob(boolean showDialog) {
//Restore originally configured target resolution
float saveResolution = foUserAgent.getTargetResolution();
foUserAgent.setTargetResolution(this.configuredTargetResolution);
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPageable(renderer);
if (!showDialog || pj.printDialog()) {
@@ -577,6 +579,8 @@ public class PreviewDialog extends JFrame implements StatusListener {
e.printStackTrace();
}
}
foUserAgent.setTargetResolution(saveResolution);
}

/**

+ 9
- 3
src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java View File

@@ -23,6 +23,7 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
@@ -36,11 +37,12 @@ import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

import org.apache.xmlgraphics.util.UnitConv;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.area.PageViewport;

import org.apache.fop.render.awt.AWTRenderer;


@@ -155,6 +157,8 @@ public class PreviewPanel extends JPanel {
this.renderable = renderable;
this.renderer = renderer;
this.foUserAgent = foUserAgent;
//Override target resolution for the computer screen
this.foUserAgent.setTargetResolution(Toolkit.getDefaultToolkit().getScreenResolution());

gridPanel = new JPanel();
gridPanel.setLayout(new GridLayout(0, 1)); // rows, cols
@@ -393,8 +397,10 @@ public class PreviewPanel extends JPanel {
public double getScaleToFit(double viewWidth, double viewHeight) throws FOPException {
PageViewport pageViewport = renderer.getPageViewport(currentPage);
Rectangle2D pageSize = pageViewport.getViewArea();
double widthScale = viewWidth / (pageSize.getWidth() / 1000f);
double heightScale = viewHeight / (pageSize.getHeight() / 1000f);
float screenResolution = Toolkit.getDefaultToolkit().getScreenResolution();
float screenFactor = screenResolution / UnitConv.IN2PT;
double widthScale = viewWidth / (pageSize.getWidth() / 1000f) / screenFactor;
double heightScale = viewHeight / (pageSize.getHeight() / 1000f) / screenFactor;
return Math.min(displayMode == CONT_FACING ? widthScale / 2 : widthScale, heightScale);
}


+ 0
- 1
src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java View File

@@ -115,7 +115,6 @@ public class PDFGraphics2DAdapter extends AbstractGraphics2DAdapter {

pdfInfo.currentStream.add(graphics.getString());
renderer.restoreGraphicsState();
pdfInfo.pdfState.pop();
}

/** {@inheritDoc} */

+ 6
- 4
src/java/org/apache/fop/render/rtf/BorderAttributesConverter.java View File

@@ -75,10 +75,12 @@ public final class BorderAttributesConverter {

// Add padding to corresponding space (space-before or space-after)
// if side == START or END, do nothing
if (side == CommonBorderPaddingBackground.BEFORE) {
attributes.addIntegerValue(padding, RtfText.SPACE_BEFORE);
} else if (side == CommonBorderPaddingBackground.AFTER) {
attributes.addIntegerValue(padding, RtfText.SPACE_AFTER);
if (padding != 0) {
if (side == CommonBorderPaddingBackground.BEFORE) {
attributes.addIntegerValue(padding, RtfText.SPACE_BEFORE);
} else if (side == CommonBorderPaddingBackground.AFTER) {
attributes.addIntegerValue(padding, RtfText.SPACE_AFTER);
}
}
}
}

+ 5
- 2
src/java/org/apache/fop/render/rtf/FoUnitsConverter.java View File

@@ -19,10 +19,9 @@

package org.apache.fop.render.rtf;

import java.util.Map;
import java.util.HashMap;
import java.util.Map;

//FOP
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.properties.FixedLength;

@@ -143,4 +142,8 @@ final class FoUnitsConverter {
// RTF font size units are in half-points
return (int)(result * 2.0);
}

public float convertMptToTwips(int width) {
return width * POINT_TO_TWIPS / 1000;
}
}

+ 4
- 1
src/java/org/apache/fop/render/rtf/PageAttributesConverter.java View File

@@ -21,6 +21,7 @@ package org.apache.fop.render.rtf;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.SimpleLog;

import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.expr.NumericOp;
@@ -58,6 +59,8 @@ final class PageAttributesConverter {

attrib.setTwips(RtfPage.PAGE_WIDTH, pagemaster.getPageWidth());
attrib.setTwips(RtfPage.PAGE_HEIGHT, pagemaster.getPageHeight());
//Sets the document level property
attrib.set(RtfPage.ITAP, "0");

Object widthRaw = attrib.getValue(RtfPage.PAGE_WIDTH);
Object heightRaw = attrib.getValue(RtfPage.PAGE_HEIGHT);
@@ -102,7 +105,7 @@ final class PageAttributesConverter {
if (after != null) {
afterBottom = (Length) NumericOp.addition(pageBottom, after.getExtent());
}
attrib.setTwips(RtfPage.FOOTERY, beforeTop);
attrib.setTwips(RtfPage.FOOTERY, afterBottom);
} catch (Exception e) {
log.error("Exception in convertPageAttributes: "
+ e.getMessage() + "- page attributes ignored");

+ 210
- 242
src/java/org/apache/fop/render/rtf/RTFHandler.java View File

@@ -20,6 +20,8 @@
package org.apache.fop.render.rtf;

// Java
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -51,12 +53,13 @@ import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.datatypes.SimplePercentBaseContext;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.events.ResourceEventProducer;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FOEventHandler;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.XMLObj;
import org.apache.fop.fo.flow.AbstractGraphics;
import org.apache.fop.fo.flow.BasicLink;
@@ -74,6 +77,7 @@ import org.apache.fop.fo.flow.ListItem;
import org.apache.fop.fo.flow.ListItemBody;
import org.apache.fop.fo.flow.ListItemLabel;
import org.apache.fop.fo.flow.PageNumber;
import org.apache.fop.fo.flow.PageNumberCitation;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableFooter;
@@ -89,8 +93,10 @@ import org.apache.fop.fo.pagination.Region;
import org.apache.fop.fo.pagination.SimplePageMaster;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.FixedLength;
import org.apache.fop.fo.properties.EnumLength;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.layoutmgr.inline.ImageLayout;
import org.apache.fop.layoutmgr.table.ColumnSetup;
import org.apache.fop.render.DefaultFontResolver;
import org.apache.fop.render.RendererEventProducer;
import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfAfterContainer;
@@ -110,6 +116,7 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFootnote;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfHyperLink;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfPage;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfSection;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableCell;
@@ -117,6 +124,7 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableRow;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTextrun;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem.RtfListItemLabel;
import org.apache.fop.render.rtf.rtflib.tools.BuilderContext;
import org.apache.fop.render.rtf.rtflib.tools.PercentContext;
import org.apache.fop.render.rtf.rtflib.tools.TableContext;

/**
@@ -150,6 +158,10 @@ public class RTFHandler extends FOEventHandler {

private SimplePageMaster pagemaster;

private int nestedTableDepth = 1;

private PercentContext percentManager = new PercentContext();

/**
* Creates a new RTF structure handler.
* @param userAgent the FOUserAgent for this process
@@ -173,9 +185,7 @@ public class RTFHandler extends FOEventHandler {
eventProducer.ioError(this, ioe);
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startDocument() throws SAXException {
// TODO sections should be created
try {
@@ -187,9 +197,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endDocument() throws SAXException {
try {
rtfFile.flush();
@@ -199,9 +207,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startPageSequence(PageSequence pageSeq) {
try {
//This is needed for region handling
@@ -240,6 +246,14 @@ public class RTFHandler extends FOEventHandler {

builderContext.pushContainer(sect);

//Calculate usable page width for this flow
int useAblePageWidth = pagemaster.getPageWidth().getValue()
- pagemaster.getCommonMarginBlock().marginLeft.getValue()
- pagemaster.getCommonMarginBlock().marginRight.getValue()
- sect.getRtfAttributes().getValueAsInteger(RtfPage.MARGIN_LEFT).intValue()
- sect.getRtfAttributes().getValueAsInteger(RtfPage.MARGIN_RIGHT).intValue();
percentManager.setDimension(pageSeq, useAblePageWidth);

bHeaderSpecified = false;
bFooterSpecified = false;
} catch (IOException ioe) {
@@ -247,9 +261,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endPageSequence(PageSequence pageSeq) {
if (bDefer) {
//If endBlock was called while SAX parsing, and the passed FO is Block
@@ -267,9 +279,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startFlow(Flow fl) {
if (bDefer) {
return;
@@ -357,9 +367,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endFlow(Flow fl) {
if (bDefer) {
return;
@@ -384,9 +392,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startBlock(Block bl) {
if (bDefer) {
return;
@@ -414,10 +420,7 @@ public class RTFHandler extends FOEventHandler {
}
}


/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endBlock(Block bl) {

if (bDefer) {
@@ -443,9 +446,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startBlockContainer(BlockContainer blc) {
if (bDefer) {
return;
@@ -472,9 +473,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endBlockContainer(BlockContainer bl) {
if (bDefer) {
return;
@@ -499,9 +498,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startTable(Table tbl) {
if (bDefer) {
return;
@@ -519,6 +516,8 @@ public class RTFHandler extends FOEventHandler {
= TableAttributesConverter.convertTableAttributes(tbl);

RtfTable table = tc.newTable(atts, tableContext);
table.setNestedTableDepth(nestedTableDepth);
nestedTableDepth++;

CommonBorderPaddingBackground border = tbl.getCommonBorderPaddingBackground();
RtfAttributes borderAttributes = new RtfAttributes();
@@ -545,53 +544,32 @@ public class RTFHandler extends FOEventHandler {
builderContext.pushTableContext(tableContext);
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endTable(Table tbl) {
if (bDefer) {
return;
}

nestedTableDepth--;
builderContext.popTableContext();
builderContext.popContainer();
}

/**
*
* @param tc TableColumn that is starting;
*/

/** {@inheritDoc} */
public void startColumn(TableColumn tc) {
if (bDefer) {
return;
}

try {
/**
* Pass a SimplePercentBaseContext to getValue in order to
* avoid a NullPointerException, which occurs when you use
* proportional-column-width function in column-width attribute.
* Of course the results won't be correct, but at least the
* rest of the document will be rendered. Usage of the
* TableLayoutManager is not welcome due to design reasons and
* it also does not provide the correct values.
* TODO: Make proportional-column-width working for rtf output
*/
SimplePercentBaseContext context
= new SimplePercentBaseContext(null,
LengthBase.TABLE_UNITS,
100000);

Integer iWidth
= new Integer(tc.getColumnWidth().getValue(context) / 1000);
int iWidth = tc.getColumnWidth().getValue(percentManager);
percentManager.setDimension(tc, iWidth);

String strWidth = iWidth.toString() + FixedLength.POINT;
Float width = new Float(
FoUnitsConverter.getInstance().convertToTwips(strWidth));
//convert to twips
Float width = new Float(FoUnitsConverter.getInstance().convertMptToTwips(iWidth));
builderContext.getTableContext().setNextColumnWidth(width);
builderContext.getTableContext().setNextColumnRowSpanning(
new Integer(0), null);
new Integer(0), null);
builderContext.getTableContext().setNextFirstSpanningCol(false);
} catch (Exception e) {
log.error("startColumn: " + e.getMessage());
@@ -599,49 +577,34 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
*
* @param tc TableColumn that is ending;
*/

/** {@inheritDoc} */
public void endColumn(TableColumn tc) {
if (bDefer) {
return;
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startHeader(TableHeader header) {
startPart(header);
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endHeader(TableHeader header) {
endPart(header);
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startFooter(TableFooter footer) {
startPart(footer);
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endFooter(TableFooter footer) {
endPart(footer);
}

/**
*
* @param inl Inline that is starting.
*/
/** {@inheritDoc} */
public void startInline(Inline inl) {
if (bDefer) {
return;
@@ -669,10 +632,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
*
* @param inl Inline that is ending.
*/
/** {@inheritDoc} */
public void endInline(Inline inl) {
if (bDefer) {
return;
@@ -735,10 +695,7 @@ public class RTFHandler extends FOEventHandler {
startPart(body);
}


/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endBody(TableBody body) {
endPart(body);
}
@@ -775,9 +732,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endRow(TableRow tr) {
if (bDefer) {
return;
@@ -814,9 +769,7 @@ public class RTFHandler extends FOEventHandler {
builderContext.getTableContext().decreaseRowSpannings();
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startCell(TableCell tc) {
if (bDefer) {
return;
@@ -868,7 +821,6 @@ public class RTFHandler extends FOEventHandler {
//process number-columns-spanned attribute
if (numberColumnsSpanned > 0) {
// Get the number of columns spanned
RtfTable table = row.getTable();
tctx.setCurrentFirstSpanningCol(true);

// We widthdraw one cell because the first cell is already created
@@ -876,6 +828,8 @@ public class RTFHandler extends FOEventHandler {
for (int i = 0; i < numberColumnsSpanned - 1; ++i) {
tctx.selectNextColumn();

//aggregate width for further elements
width += tctx.getColumnWidth();
tctx.setCurrentFirstSpanningCol(false);
RtfTableCell hCell = row.newTableCellMergedHorizontally(
0, null);
@@ -890,10 +844,12 @@ public class RTFHandler extends FOEventHandler {
cell.getRtfAttributes());
} else {
tctx.setCurrentColumnRowSpanning(
new Integer(numberRowsSpanned), null);
new Integer(numberRowsSpanned), cell.getRtfAttributes());
}
}
}
//save width of the cell, convert from twips to mpt
percentManager.setDimension(tc, (int)width * 50);

builderContext.pushContainer(cell);
} catch (IOException ioe) {
@@ -904,9 +860,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endCell(TableCell tc) {
if (bDefer) {
return;
@@ -917,9 +871,7 @@ public class RTFHandler extends FOEventHandler {
}

// Lists
/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startList(ListBlock lb) {
if (bDefer) {
return;
@@ -944,9 +896,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endList(ListBlock lb) {
if (bDefer) {
return;
@@ -955,9 +905,7 @@ public class RTFHandler extends FOEventHandler {
builderContext.popContainer();
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startListItem(ListItem li) {
if (bDefer) {
return;
@@ -995,9 +943,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endListItem(ListItem li) {
if (bDefer) {
return;
@@ -1006,9 +952,7 @@ public class RTFHandler extends FOEventHandler {
builderContext.popContainer();
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startListLabel() {
if (bDefer) {
return;
@@ -1028,9 +972,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endListLabel() {
if (bDefer) {
return;
@@ -1039,46 +981,32 @@ public class RTFHandler extends FOEventHandler {
builderContext.popContainer();
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startListBody() {
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endListBody() {
}

// Static Regions
/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startStatic() {
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endStatic() {
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startMarkup() {
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endMarkup() {
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startLink(BasicLink basicLink) {
if (bDefer) {
return;
@@ -1109,9 +1037,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endLink() {
if (bDefer) {
return;
@@ -1120,9 +1046,7 @@ public class RTFHandler extends FOEventHandler {
builderContext.popContainer();
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void image(ExternalGraphic eg) {
if (bDefer) {
return;
@@ -1153,16 +1077,14 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void foreignObject(InstreamForeignObject ifo) {
if (bDefer) {
return;
}

try {
XMLObj child = (XMLObj) ifo.getChildXMLObj();
XMLObj child = ifo.getChildXMLObj();
Document doc = child.getDOMDocument();
String ns = child.getNamespaceURI();

@@ -1191,7 +1113,8 @@ public class RTFHandler extends FOEventHandler {

FOUserAgent userAgent = ifo.getUserAgent();
ImageManager manager = userAgent.getFactory().getImageManager();
Image converted = manager.convertImage(image, FLAVORS);
Map hints = ImageUtil.getDefaultHints(ua.getImageSessionContext());
Image converted = manager.convertImage(image, FLAVORS, hints);
putGraphic(ifo, converted);

} catch (ImageException ie) {
@@ -1242,7 +1165,7 @@ public class RTFHandler extends FOEventHandler {
throws IOException {
byte[] rawData = null;

ImageInfo info = image.getInfo();
final ImageInfo info = image.getInfo();

if (image instanceof ImageRawStream) {
ImageRawStream rawImage = (ImageRawStream)image;
@@ -1261,6 +1184,25 @@ public class RTFHandler extends FOEventHandler {
return;
}

//Set up percentage calculations
this.percentManager.setDimension(abstractGraphic);
PercentBaseContext pContext = new PercentBaseContext() {

public int getBaseLength(int lengthBase, FObj fobj) {
switch (lengthBase) {
case LengthBase.IMAGE_INTRINSIC_WIDTH:
return info.getSize().getWidthMpt();
case LengthBase.IMAGE_INTRINSIC_HEIGHT:
return info.getSize().getHeightMpt();
default:
return percentManager.getBaseLength(lengthBase, fobj);
}
}

};
ImageLayout layout = new ImageLayout(abstractGraphic, pContext,
image.getInfo().getSize().getDimensionMpt());

final IRtfTextrunContainer c
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
@@ -1273,63 +1215,23 @@ public class RTFHandler extends FOEventHandler {
}
rtfGraphic.setImageData(rawData);

//set scaling
if (abstractGraphic.getScaling() == Constants.EN_UNIFORM) {
rtfGraphic.setScaling ("uniform");
}

//get width
int width = 0;
if (abstractGraphic.getWidth().getEnum() == Constants.EN_AUTO) {
width = info.getSize().getWidthMpt();
} else {
width = abstractGraphic.getWidth().getValue();
}

//get height
int height = 0;
if (abstractGraphic.getWidth().getEnum() == Constants.EN_AUTO) {
height = info.getSize().getHeightMpt();
} else {
height = abstractGraphic.getHeight().getValue();
}

//get content-width
int contentwidth = 0;
if (abstractGraphic.getContentWidth().getEnum()
== Constants.EN_AUTO) {
contentwidth = info.getSize().getWidthMpt();
} else if (abstractGraphic.getContentWidth().getEnum()
== Constants.EN_SCALE_TO_FIT) {
contentwidth = width;
} else {
//TODO: check, if the value is a percent value
contentwidth = abstractGraphic.getContentWidth().getValue();
}

//get content-width
int contentheight = 0;
if (abstractGraphic.getContentHeight().getEnum()
== Constants.EN_AUTO) {

contentheight = info.getSize().getHeightMpt();

} else if (abstractGraphic.getContentHeight().getEnum()
== Constants.EN_SCALE_TO_FIT) {

contentheight = height;
} else {
//TODO: check, if the value is a percent value
contentheight = abstractGraphic.getContentHeight().getValue();
}

//set width in rtf
//newGraphic.setWidth((long) (contentwidth / 1000f) + FixedLength.POINT);
rtfGraphic.setWidth((long) (contentwidth / 50f) + "twips");

//set height in rtf
//newGraphic.setHeight((long) (contentheight / 1000f) + FixedLength.POINT);
rtfGraphic.setHeight((long) (contentheight / 50f) + "twips");
FoUnitsConverter converter = FoUnitsConverter.getInstance();
Dimension viewport = layout.getViewportSize();
Rectangle placement = layout.getPlacement();
int cropLeft = Math.round(converter.convertMptToTwips(-placement.x));
int cropTop = Math.round(converter.convertMptToTwips(-placement.y));
int cropRight = Math.round(converter.convertMptToTwips(
-1 * (viewport.width - placement.x - placement.width)));
int cropBottom = Math.round(converter.convertMptToTwips(
-1 * (viewport.height - placement.y - placement.height)));
rtfGraphic.setCropping(cropLeft, cropTop, cropRight, cropBottom);

int width = Math.round(converter.convertMptToTwips(viewport.width));
int height = Math.round(converter.convertMptToTwips(viewport.height));
width += cropLeft + cropRight;
height += cropTop + cropBottom;
rtfGraphic.setWidthTwips(width);
rtfGraphic.setHeightTwips(height);

//TODO: make this configurable:
// int compression = m_context.m_options.getRtfExternalGraphicCompressionRate ();
@@ -1342,15 +1244,11 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void pageRef() {
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startFootnote(Footnote footnote) {
if (bDefer) {
return;
@@ -1375,9 +1273,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endFootnote(Footnote footnote) {
if (bDefer) {
return;
@@ -1386,9 +1282,7 @@ public class RTFHandler extends FOEventHandler {
builderContext.popContainer();
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void startFootnoteBody(FootnoteBody body) {
if (bDefer) {
return;
@@ -1409,9 +1303,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void endFootnoteBody(FootnoteBody body) {
if (bDefer) {
return;
@@ -1432,10 +1324,28 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public void leader(Leader l) {
if (bDefer) {
return;
}

try {
percentManager.setDimension(l);
RtfAttributes rtfAttr = TextAttributesConverter.convertLeaderAttributes(
l, percentManager);

IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();

textrun.addLeader(rtfAttr);

} catch (Exception e) {
log.error("startLeader: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}

/**
@@ -1469,10 +1379,7 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
*
* @param pagenum PageNumber that is starting.
*/
/** {@inheritDoc} */
public void startPageNumber(PageNumber pagenum) {
if (bDefer) {
return;
@@ -1497,16 +1404,64 @@ public class RTFHandler extends FOEventHandler {
}
}

/**
*
* @param pagenum PageNumber that is ending.
*/
/** {@inheritDoc} */
public void endPageNumber(PageNumber pagenum) {
if (bDefer) {
return;
}
}

/** {@inheritDoc} */
public void startPageNumberCitation(PageNumberCitation l) {
if (bDefer) {
return;
}
try {

IRtfTextrunContainer container
= (IRtfTextrunContainer)builderContext.getContainer(
IRtfTextrunContainer.class, true, this);
RtfTextrun textrun = container.getTextrun();

textrun.addPageNumberCitation(l.getRefId());

} catch (Exception e) {
log.error("startPageNumberCitation: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
}

private void prepareTable(Table tab) {
// Allows to receive the available width of the table
percentManager.setDimension(tab);

// Table gets expanded by half of the border on each side inside Word
// When using wide borders the table gets cut off
int tabDiff = tab.getCommonBorderPaddingBackground().getBorderStartWidth(false) / 2
+ tab.getCommonBorderPaddingBackground().getBorderEndWidth(false);

// check for "auto" value
if (!(tab.getInlineProgressionDimension().getMaximum(null).getLength()
instanceof EnumLength)) {
// value specified
percentManager.setDimension(tab,
tab.getInlineProgressionDimension().getMaximum(null)
.getLength().getValue(percentManager)
- tabDiff);
} else {
// set table width again without border width
percentManager.setDimension(tab, percentManager.getBaseLength(
LengthBase.CONTAINING_BLOCK_WIDTH, tab) - tabDiff);
}

ColumnSetup columnSetup = new ColumnSetup(tab);
//int sumOfColumns = columnSetup.getSumOfColumnWidths(percentManager);
float tableWidth = percentManager.getBaseLength(LengthBase.CONTAINING_BLOCK_WIDTH, tab);
float tableUnit = columnSetup.computeTableUnit(percentManager, Math.round(tableWidth));
percentManager.setTableUnit(tab, Math.round(tableUnit));

}

/**
* Calls the appropriate event handler for the passed FObj.
*
@@ -1659,6 +1614,16 @@ public class RTFHandler extends FOEventHandler {
} else {
endCell( (TableCell) foNode);
}
} else if (foNode instanceof Leader) {
if (bStart) {
leader((Leader) foNode);
}
} else if (foNode instanceof PageNumberCitation) {
if (bStart) {
startPageNumberCitation((PageNumberCitation) foNode);
} else {
endPageNumberCitation((PageNumberCitation) foNode);
}
} else {
RTFEventProducer eventProducer = RTFEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
@@ -1701,9 +1666,12 @@ public class RTFHandler extends FOEventHandler {

//recurse all table-columns
if (table.getColumns() != null) {
for (Iterator it = table.getColumns().iterator(); it.hasNext();) {
recurseFONode( (FONode) it.next() );
}
//Calculation for column-widths which are not set
prepareTable(table);

for (Iterator it = table.getColumns().iterator(); it.hasNext();) {
recurseFONode( (FONode) it.next() );
}
} else {
//TODO Implement implicit column setup handling!
RTFEventProducer eventProducer = RTFEventProducer.Provider.get(

+ 134
- 2
src/java/org/apache/fop/render/rtf/TextAttributesConverter.java View File

@@ -21,25 +21,30 @@ package org.apache.fop.render.rtf;

import java.awt.Color;

//FOP
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.flow.Block;
import org.apache.fop.fo.flow.BlockContainer;
import org.apache.fop.fo.flow.Inline;
import org.apache.fop.fo.flow.Leader;
import org.apache.fop.fo.flow.PageNumber;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonFont;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.CommonTextDecoration;
import org.apache.fop.render.rtf.BorderAttributesConverter;
import org.apache.fop.fo.properties.PercentLength;
import org.apache.fop.render.rtf.rtflib.rtfdoc.IBorderAttributes;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfColorTable;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFontManager;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfLeader;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfText;

/** Converts FO properties to RtfAttributes
@@ -53,6 +58,8 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfText;
*/
final class TextAttributesConverter {

private static Log log = LogFactory.getLog(TextAttributesConverter.class);

/**
* Constructor is private, because it's just a utility class.
*/
@@ -137,6 +144,131 @@ final class TextAttributesConverter {
return attrib;
}


/**
* Converts FO properties used by RtfLeader to RtfAttributes.
* @param fobj Leader
* @param context PercentBaseContext
* @return RtfAttributes
* @throws FOPException
*/
public static RtfAttributes convertLeaderAttributes(Leader fobj, PercentBaseContext context)
throws FOPException {
boolean tab = false;
FOPRtfAttributes attrib = new FOPRtfAttributes();
attrib.set(RtfText.ATTR_FONT_FAMILY,
RtfFontManager.getInstance().getFontNumber(fobj.getCommonFont().getFirstFontFamily()));

if (fobj.getLeaderLength() != null) {
attrib.set(RtfLeader.LEADER_WIDTH, convertMptToTwips(fobj.getLeaderLength().getMaximum(
context).getLength().getValue(context)));

if (fobj.getLeaderLength().getMaximum(context) instanceof PercentLength) {
if (((PercentLength)fobj.getLeaderLength().getMaximum(context)).getString().equals(
"100.0%")) {
// Use Tab instead of white spaces
attrib.set(RtfLeader.LEADER_USETAB, 1);
tab = true;
}
}
}

attrFontColor(fobj.getColor(), attrib);

if (fobj.getLeaderPatternWidth() != null) {
//TODO calculate pattern width not possible for white spaces, because its using
//underlines for tab it would work with LEADER_PATTERN_WIDTH (expndtw)
}

switch(fobj.getLeaderPattern()) {
case Constants.EN_DOTS:
if (tab) {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_DOTTED);
} else {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_DOTTED);
}
break;
case Constants.EN_SPACE:
//nothing has to be set for spaces
break;
case Constants.EN_RULE:
//Things like start-indent, space-after, ... not supported?
//Leader class does not offer these properties
//TODO aggregate them with the leader width or
// create a second - blank leader - before

if (fobj.getRuleThickness() != null) {
//TODO See inside RtfLeader, better calculation for
//white spaces would be necessary
//attrib.set(RtfLeader.LEADER_RULE_THICKNESS,
// fobj.getRuleThickness().getValue(context));
log.warn("RTF: fo:leader rule-thickness not supported");
}

switch (fobj.getRuleStyle()) {
case Constants.EN_SOLID:
if (tab) {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_THICK);
} else {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_THICK);
}
break;
case Constants.EN_DASHED:
if (tab) {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_MIDDLEDOTTED);
} else {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_MIDDLEDOTTED);
}
break;
case Constants.EN_DOTTED:
if (tab) {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_DOTTED);
} else {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_DOTTED);
}
break;
case Constants.EN_DOUBLE:
if (tab) {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_EQUAL);
} else {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_EQUAL);
}
break;
case Constants.EN_GROOVE:
if (tab) {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_HYPHENS);
} else {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_HYPHENS);
}
break;
case Constants.EN_RIDGE:
if (tab) {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_UNDERLINE);
} else {
attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_UNDERLINE);
}
break;
default:
break;
}
break;
case Constants.EN_USECONTENT:
log.warn("RTF: fo:leader use-content not supported");
break;
default:
break;
}

if (fobj.getLeaderAlignment() == Constants.EN_REFERENCE_AREA) {
log.warn("RTF: fo:leader reference-area not supported");
}
return attrib;
}

private static int convertMptToTwips(int mpt) {
return Math.round(FoUnitsConverter.getInstance().convertMptToTwips(mpt));
}

private static void attrFont(CommonFont font, FOPRtfAttributes rtfAttr) {
rtfAttr.set(RtfText.ATTR_FONT_FAMILY,
RtfFontManager.getInstance().getFontNumber(font.getFirstFontFamily()));

+ 10
- 0
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java View File

@@ -28,6 +28,7 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc;

import java.util.HashMap;
import java.util.Iterator;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;

@@ -163,6 +164,15 @@ implements java.lang.Cloneable {
return values.get(name);
}

/**
* Returns a value as an Integer. The value is simply cast to an Integer.
* @param name String containing attribute name
* @return the value of an attribute, null if not found
*/
public Integer getValueAsInteger(String name) {
return (Integer)values.get(name);
}

/**
* @param name String containing attribute name
* @return true if given attribute is set

+ 63
- 3
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java View File

@@ -269,6 +269,9 @@ public class RtfExternalGraphic extends RtfElement {
*/
protected boolean scaleUniform = false;

/** cropping on left/top/right/bottom edges for \piccrop*N */
private int[] cropValues = new int[4];

/**
* Graphic compression rate
*/
@@ -406,6 +409,7 @@ public class RtfExternalGraphic extends RtfElement {

computeImageSize();
writeSizeInfo();
writeAttributes(getRtfAttributes(), null);

for (int i = 0; i < imagedata.length; i++) {
int iData = imagedata [i];
@@ -519,6 +523,19 @@ public class RtfExternalGraphic extends RtfElement {
writeControlWord("picscaley" + widthDesired * 100 / width);
}
}

if (this.cropValues[0] != 0) {
writeOneAttribute("piccropl", new Integer(this.cropValues[0]));
}
if (this.cropValues[1] != 0) {
writeOneAttribute("piccropt", new Integer(this.cropValues[1]));
}
if (this.cropValues[2] != 0) {
writeOneAttribute("piccropr", new Integer(this.cropValues[2]));
}
if (this.cropValues[3] != 0) {
writeOneAttribute("piccropb", new Integer(this.cropValues[3]));
}
}

//////////////////////////////////////////////////
@@ -545,6 +562,24 @@ public class RtfExternalGraphic extends RtfElement {
this.perCentW = ImageUtil.isPercent(theWidth);
}

/**
* Sets the desired width of the image.
* @param twips The desired image width (in twips)
*/
public void setWidthTwips(int twips) {
this.widthDesired = twips;
this.perCentW = false;
}

/**
* Sets the desired height of the image.
* @param twips The desired image height (in twips)
*/
public void setHeightTwips(int twips) {
this.heightDesired = twips;
this.perCentH = false;
}

/**
* Sets the flag whether the image size shall be adjusted.
*
@@ -553,9 +588,34 @@ public class RtfExternalGraphic extends RtfElement {
* false no adjustment
*/
public void setScaling(String value) {
if (value.equalsIgnoreCase("uniform")) {
this.scaleUniform = true;
}
setUniformScaling("uniform".equalsIgnoreCase(value));
}

/**
* Sets the flag whether the image size shall be adjusted.
*
* @param uniform
* true image width or height shall be adjusted automatically\n
* false no adjustment
*/
public void setUniformScaling(boolean uniform) {
this.scaleUniform = uniform;
}

/**
* Sets cropping values for all four edges for the \piccrop*N commands.
* A positive value crops toward the center of the picture;
* a negative value crops away from the center, adding a space border around the picture
* @param left left cropping value (in twips)
* @param top top cropping value (in twips)
* @param right right cropping value (in twips)
* @param bottom bottom cropping value (in twips)
*/
public void setCropping(int left, int top, int right, int bottom) {
this.cropValues[0] = left;
this.cropValues[1] = top;
this.cropValues[2] = right;
this.cropValues[3] = bottom;
}

/**

+ 219
- 0
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLeader.java View File

@@ -0,0 +1,219 @@
/*
* 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.render.rtf.rtflib.rtfdoc;

import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;

/**
* Generates the leader in RTF.
*/
public class RtfLeader extends RtfContainer {

/*
* Format : \tqr \style \tx## { \pard \format \tab }
* ## represents the width \style represents the style (tldot, tlth, ...)
* \format represents standard formats (color, fontsize, ...)
*
*
* \pard \zwnj {\fsxx <format> } \zwnj
*
* <format>: \\ulcN Underline color. \\uld Dotted underline. \\uldash Dashed
* underline. \\uldashd Dash-dotted underline. \\uldashdd Dash-dot-dotted
* underline. \\uldb Double underline. \\ulhwave Heavy wave underline.
* \\ulldash Long dashed underline. \\ulnone Stops all underlining. \\ulth
* Thick underline. \\ulthd Thick dotted underline. \\ulthdash Thick dashed
* underline. \\ulthdashd Thick dash-dotted underline. \\ulthdashdd Thick
* dash-dot-dotted underline. \\ulthldash Thick long dashed underline.
* \\ululdbwave Double wave underline.
*/

private RtfAttributes attrs = null;

/** Private attribute: tab style */
public static final String LEADER_TABLEAD = "tablead";

/** Private attribute: tab usage indicator */
public static final String LEADER_USETAB = "tabuse";

/** Private attribute: leader width */
public static final String LEADER_WIDTH = "lwidth";

// +++++++++++++++ Styles Underline ++++++++++++++++++++++

/** Dotted underline */
public static final String LEADER_DOTTED = "uld"; // dotted

/** Dashed underline */
public static final String LEADER_MIDDLEDOTTED = "uldash"; // dashed

/** Heavy wave underline */
public static final String LEADER_HYPHENS = "ulhwave"; // groove

/** Dash-dot-dotted underline */
public static final String LEADER_UNDERLINE = "ulthdashdd"; // ridge

/** Double underline */
public static final String LEADER_EQUAL = "uldb"; // double

/** Thick underline */
public static final String LEADER_THICK = "ulth"; // solid

// +++++++++++++++ Styles Tabulator +++++++++++++++++++++++

/** Leader dots */
public static final String LEADER_TAB_DOTTED = "tldot"; // dotted

/** Leader middle dots */
public static final String LEADER_TAB_MIDDLEDOTTED = "tlmdot"; // dashed

/** Leader hyphens */
public static final String LEADER_TAB_HYPHENS = "tlhyph"; // groove

/** Leader underline */
public static final String LEADER_TAB_UNDERLINE = "tlul"; // ridge

/** Leader equal sign */
public static final String LEADER_TAB_EQUAL = "tleq"; // double

/** Leader thick line */
public static final String LEADER_TAB_THICK = "tlth"; // solid

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++

/** Resets to default properties */
public static final String LEADER_IGNORE_STYLE = "pard";

/** Font size determines rule thickness */
public static final String LEADER_RULE_THICKNESS = "fs"; // thickness = fontsize

/** Expansion or compression of the space between characters in twips */
public static final String LEADER_PATTERN_WIDTH = "expndtw";

/** Zero-width break opportunity */
public static final String LEADER_ZERO_WIDTH = "zwbo";

/** Standard leader width */
public static final int LEADER_STANDARD_WIDTH = 30;

/** Move up 4 half-points */
public static final String LEADER_UP = "up4";

/** Negative expansion */
public static final String LEADER_EXPAND = "expnd-2"; // negative value
// for compression

/** Tab */
public static final String LEADER_TAB_VALUE = "tab";

/** Right-aligned tab */
public static final String LEADER_TAB_RIGHT = "tqr";

/** Tab width */
public static final String LEADER_TAB_WIDTH = "tx";

RtfLeader(RtfContainer parent, Writer w, RtfAttributes attrs) throws IOException {
super(parent, w);
this.attrs = attrs;
}

/** {@inheritDoc} */
protected void writeRtfContent() throws IOException {

int thickness = LEADER_STANDARD_WIDTH;
String tablead = null;
String tabwidth = null;
for (Iterator it = attrs.nameIterator(); it.hasNext();) {
final String name = (String)it.next();
if (attrs.isSet(name)) {
if (name.equals(LEADER_TABLEAD)) {
tablead = attrs.getValue(LEADER_TABLEAD).toString();
} else if (name.equals(LEADER_WIDTH)) {
tabwidth = attrs.getValue(LEADER_WIDTH).toString();
}
}
}

if (attrs.getValue(LEADER_RULE_THICKNESS) != null) {
thickness += Integer.parseInt(attrs.getValue(LEADER_RULE_THICKNESS).toString())
/ 1000 * 2;
attrs.unset(LEADER_RULE_THICKNESS);
}

//Remove private attributes
attrs.unset(LEADER_WIDTH);
attrs.unset(LEADER_TABLEAD);

// If leader is 100% we use a tabulator, because its more
// comfortable, specially for the table of content
if (attrs.getValue(LEADER_USETAB) != null) {
attrs.unset(LEADER_USETAB);
writeControlWord(LEADER_TAB_RIGHT);

if (tablead != null) {
writeControlWord(tablead);
}
writeControlWord(LEADER_TAB_WIDTH + tabwidth);

writeGroupMark(true);

writeControlWord(LEADER_IGNORE_STYLE);
writeAttributes(attrs, null);
writeControlWord(LEADER_EXPAND);
writeControlWord(LEADER_TAB_VALUE);

writeGroupMark(false);

}
// Using white spaces with different underline formats
else {
writeControlWord(LEADER_IGNORE_STYLE);
writeControlWord(LEADER_ZERO_WIDTH);
writeGroupMark(true);

writeControlWord(LEADER_RULE_THICKNESS + thickness);

writeControlWord(LEADER_UP);

super.writeAttributes(attrs, null);
if (tablead != null) {
writeControlWord(tablead);
}

// Calculation for the necessary amount of white spaces
// Depending on font-size 15 -> 1cm = 7,5 spaces
// TODO for rule-thickness this has to be done better

for (double d = (Integer.parseInt(tabwidth) / 560) * 7.5; d >= 1; d--) {
RtfStringConverter.getInstance().writeRtfString(writer, " ");
}

writeGroupMark(false);
writeControlWord(LEADER_ZERO_WIDTH);
}
}

/** {@inheritDoc} */
public boolean isEmpty() {
return false;
}

}

+ 4
- 2
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java View File

@@ -60,11 +60,13 @@ extends RtfContainer {
public static final String HEADERY = "headery";
/** constant for footer position */
public static final String FOOTERY = "footery";

/** constant for itap level */
public static final String ITAP = "itap";
/** String array of RtfPage attributes */
public static final String[] PAGE_ATTR = new String[]{
PAGE_WIDTH, PAGE_HEIGHT, LANDSCAPE, MARGIN_TOP, MARGIN_BOTTOM,
MARGIN_LEFT, MARGIN_RIGHT, HEADERY, FOOTERY
MARGIN_LEFT, MARGIN_RIGHT, HEADERY, FOOTERY, ITAP
};

/** RtfPage creates new page attributes with the parent container, the writer

+ 4
- 4
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java View File

@@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc;
* the FOP project.
*/

import java.io.Writer;
import java.io.IOException;
import java.io.Writer;

/**
* @author Christopher Scott, scottc@westinghouse.com
@@ -50,9 +50,9 @@ public class RtfPageNumberCitation extends RtfContainer {
private String id = null;

/** Create an RTF page number citation as a child of given container with default attributes */
RtfPageNumberCitation (IRtfPageNumberCitationContainer parent, Writer w, String id)
RtfPageNumberCitation (RtfContainer parent, Writer w, String id)
throws IOException {
super((RtfContainer)parent, w);
super(parent, w);
this.id = id;
}

@@ -92,7 +92,7 @@ public class RtfPageNumberCitation extends RtfContainer {
writeStarControlWord(pageRef);
writeGroupMark(false);
writeGroupMark(true);
writeControlWord(RTF_FIELD_RESULT);
writeControlWord(RTF_FIELD_RESULT + '#'); //To see where the page-number would be
writeGroupMark(false);
writeGroupMark(false);
}

+ 20
- 1
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java View File

@@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc;
* the FOP project.
*/

import java.io.Writer;
import java.io.IOException;
import java.io.Writer;

/** Container for RtfRow elements
* @author Bertrand Delacretaz bdelacretaz@codeconsult.ch
@@ -43,6 +43,9 @@ public class RtfTable extends RtfContainer {
* number-columns-spanned attribute */
private ITableColumnsInfo tableContext;

/** Shows the table depth necessary for nested tables */
private int nestedTableDepth = 0;

/** Create an RTF element as a child of given container */
RtfTable(IRtfTableContainer parent, Writer w, ITableColumnsInfo tc)
throws IOException {
@@ -212,6 +215,22 @@ public class RtfTable extends RtfContainer {
return null;
}

/**
* Sets the nested table depth.
* @param nestedTableDepth the nested table depth
*/
public void setNestedTableDepth(int nestedTableDepth) {
this.nestedTableDepth = nestedTableDepth;
}

/**
* Returns the nested table depth.
* @return the nested table depth
*/
public int getNestedTableDepth() {
return this.nestedTableDepth;
}

/**
* Sets the RtfAttributes for the borders of the table.
* @param attributes Border attributes of the table.

+ 2
- 2
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java View File

@@ -133,11 +133,11 @@ public class RtfTableRow extends RtfContainer implements ITableAttributes {
* @throws IOException for I/O problems
*/
protected void writeRtfContent() throws IOException {

if (getTable().isNestedTable()) {
//nested table
writeControlWord("intbl");
writeControlWord("itap2");
//itap is the depth (level) of the current nested table
writeControlWord("itap" + getTable().getNestedTableDepth());
} else {
//normal (not nested) table
writeRowAndCellsDefintions();

+ 19
- 1
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java View File

@@ -22,8 +22,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc;
// Java
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

// FOP
@@ -175,6 +175,15 @@ public class RtfTextrun extends RtfContainer {
addOpenGroupMark(attrs);
}

/**
* Inserts a page number citation.
* @param refId the identifier being referenced
* @throws IOException for I/O problems
*/
public void addPageNumberCitation(String refId) throws IOException {
RtfPageNumberCitation r = new RtfPageNumberCitation(this, writer, refId);
}

/**
* Pop inline attributes.
*
@@ -242,6 +251,15 @@ public class RtfTextrun extends RtfContainer {
}
}

/**
* Inserts a leader.
* @param attrs Attributes for the leader
* @throws IOException for I/O problems
*/
public void addLeader(RtfAttributes attrs) throws IOException {
new RtfLeader(this, writer, attrs);
}

/**
* Inserts a page number.
* @param attr Attributes for the page number to insert.

+ 136
- 0
src/java/org/apache/fop/render/rtf/rtflib/tools/PercentContext.java View File

@@ -0,0 +1,136 @@
/*
* 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.render.rtf.rtflib.tools;

import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.pagination.PageSequence;

/**
* PercentBaseContext implementation to track base widths for percentage calculations.
*/
public class PercentContext implements PercentBaseContext {
private static Log log = LogFactory.getLog(PercentContext.class);

/** Map containing the FObj and its width */
private Map lengthMap = new java.util.HashMap();

/** Map containing the Tables and their table units */
private Map tableUnitMap = new java.util.HashMap();

/** Variable to check if a base width is set */
private boolean baseWidthSet = false;

/**
* Returns the available width for a specific FObj
*
* @param lengthBase
* lengthBase not used
* @param fobj
* the FObj
* @return Available Width
*/
public int getBaseLength(int lengthBase, FObj fobj) {
if (fobj == null) {
return 0;
}
switch (lengthBase) {
case LengthBase.CONTAINING_BLOCK_WIDTH:
case LengthBase.PARENT_AREA_WIDTH:
case LengthBase.CONTAINING_REFAREA_WIDTH:
Object width = lengthMap.get(fobj);
if (width != null) {
return Integer.parseInt(width.toString());
} else {
return -1;
}
case LengthBase.TABLE_UNITS:
Object unit = tableUnitMap.get(fobj);
return (unit != null) ? ((Integer)unit).intValue() : 0;
default:
log.error(new Exception("Unsupported base type for LengthBase:" + lengthBase));
return 0;
}
}

/**
* Elements having a width property can call this function if their width is
* calculated in RTFHandler
*
* @param fobj the FObj
* @param width width of the FObj (in millipoints)
*/
public void setDimension(FObj fobj, int width) {
// TODO ACCEPT only objects above for setting a width
if (fobj instanceof PageSequence) {
baseWidthSet = true;
}
// width in mpt
lengthMap.put(fobj, new Integer(width));
}

/**
* Records the calculated table unit for a given table.
* @param table the table for which the table unit is set
* @param tableUnit the table unit value (in millipoints)
*/
public void setTableUnit(Table table, int tableUnit) {
tableUnitMap.put(table, new Integer(tableUnit));
}

/**
* Searches for the parent object of fobj.
*/
private Integer findParent(FONode fobj) {
if (fobj.getRoot() != fobj) {
if (lengthMap.containsKey(fobj)) {
return new Integer(lengthMap.get(fobj).toString());
} else {
return findParent(fobj.getParent());
}
} else {
log.error("Base Value for element " + fobj.getName() + " not found");
return new Integer(-1);
}
}

/**
* Elements willing to use this context have to register themselves by
* calling this function.
*
* @param fobj the FObj
*/
public void setDimension(FObj fobj) {
if (baseWidthSet) {
Integer width = findParent(fobj.getParent());
if (width.intValue() != -1) {
lengthMap.put(fobj, width);
}
}
}
}

+ 2
- 1
src/java/org/apache/fop/util/BreakUtil.java View File

@@ -36,7 +36,8 @@ public final class BreakUtil {
case Constants.EN_PAGE: return 2;
case Constants.EN_EVEN_PAGE: return 3;
case Constants.EN_ODD_PAGE: return 3;
default: throw new IllegalArgumentException();
default: throw new IllegalArgumentException(
"Illegal value for breakClass: " + breakClass);
}
}


+ 106
- 1
status.xml View File

@@ -172,12 +172,117 @@
</action>
</release>
<release version="0.95" date="TBD">
<notes>
<section>
<title>Notes</title>
<p>
Besides the important changes listed below, the most important areas with
improvements in this release are:
</p>
<ul>
<li>
Many bugfixes in tables, plus some new features (full support for keeps and
breaks, border conditionality, background on columns and header/footer/body)
</li>
<li>
Improvements and bugfixes for font handling and font
auto-detection/-registration.
</li>
<li>
Performance improvements and memory optimizations for the property handling
in the FO tree.
</li>
</ul>
<p>
Please note that with this release, we've dropped support for Java 1.3.
FOP will, from now on, <strong>require at least Java 1.4</strong>.
</p>
<p>
There have been a few changes in tables that make FOP both more strict and more
compliant to the Recommendation:
<ul>
<li>XSL-FO 1.1 explicitly states that a row-spanning fo:table-cell element is not
allowed to span further than its enclosing fo:table-header/footer/body element
(see bottom of <link href="http://www.w3.org/TR/xsl11/#fo_table">section
6.7.3</link>). From now on FOP will give a validation error if a document
contains such an erroneous cell.
</li>
<li>
<p>If an fo:table element contains explicit fo:table-column children, then those
elements set the total number of columns in the table. This means that a
validation error will now occur if a row contains more cells than available
columns. This change allows to improve performance, since the rendering of the
table may start as soon as the table-column elements have been parsed.</p>
<p>If more flexibility is needed, then the fo:table-column elements may be just
omitted. The final number of columns will then be set by the row that has the
most cells.</p>
</li>
</ul>
</p>
<p>
The image libraries Jimi and JAI are no longer needed (and used) for image loading.
Instead we rely completely on the Image I/O API that has been introduced with
Java 1.4. If you still need support for bitmap image formats that do not work
out-of-the-box, we recommend adding
<link href="http://jai-imageio.dev.java.net/">JAI Image I/O Tools</link>
(an Image I/O compatible image codec package) to the classpath. JAI is still required
for building the FOP distribution but it is optional for normal builds and at run-time.
</p>
<note>
This final 0.95 release contains all the
<a href="changes_0.95beta.html">changes made for Apache FOP 0.95beta</a>.
</note>
</section>
</notes>
<action context="Renderers" dev="JM" type="fix">
Fixed positioning of absolutely positioned block-containers in multi-column documents.
Fixed a color selection problem which occurred after an image has been painted
through the Graphics2DAdapter in PDF output.
</action>
<action context="Renderers" dev="JM" type="fix" fixes-bug="41306">
Fixed page ordering problem with AWTRenderer.
</action>
<action context="Renderers" dev="JM" type="fix" fixes-bug="39980">
Fixed image scaling for RTF output.
</action>
<action context="API" dev="JM" type="fix">
Fixed the -imagein command-line option.
</action>
<action context="Renderers" dev="JM" type="add" fixes-bug="43825" due-to="Maximilian Aster">
Added support for fo:leader for RTF output (no full support!). Fixes problems with empty leaders
being used to force empty lines among other issues.
</action>
<action context="Renderers" dev="JM" type="add" fixes-bug="43824" due-to="Maximilian Aster">
Added support for page-number-citation for RTF output.
</action>
<action context="Renderers" dev="JM" type="fix" fixes-bug="43606" due-to="Maximilian Aster">
Fixed handling of proportional-column-width() and percentages for table column in RTF
output.
</action>
<action context="Layout" dev="AD" type="fix" fixes-bug="45295">
Fixed NullPointerException when page-number-citations are used inside a marker.
</action>
<action context="Images" dev="JM" type="fix">
Fixed two bugs concerning resolution handling with SVG images and their
conversion to bitmaps for RTF output.
</action>
<action context="Code" dev="JM" type="fix" fixes-bug="44887" importance="high">
Fixed potential multi-threading problem concerning the use of DecimalFormat.
</action>
<action context="Layout" dev="JM" type="fix" fixes-bug="44412">
Regression bugfix: Multiple collapsible breaks don't cause empty pages anymore.
</action>
<action context="Renderers" dev="JM" type="fix">
Fixed resolution handling inside AWT preview dialog.
</action>
<action context="Renderers" dev="JM" type="fix" importance="high">
Fixed positioning of absolutely positioned block-containers in multi-column documents.
</action>
<action context="Renderers" dev="JM" type="fix" importance="high">
Fixed rendering of fixed block-containers in AFP output.
</action>
<action context="Layout" dev="VH" type="fix" fixes-bug="41621" importance="high">
Various bugfixes for table layout.
</action>
<action context="Renderers" dev="JM" type="fix">
Fixed regression causing bad positioning of block-containers if used as descendant
of a table-cell.

+ 45
- 0
test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java View File

@@ -88,6 +88,51 @@ public class ImageLoaderTestCase extends TestCase {
assertEquals(16000, info.getSize().getHeightMpt());
}

public void testSVGNoViewbox() throws Exception {
String uri = "test/resources/images/circles.svg";

FopFactory ff = FopFactory.newInstance();
ff.setSourceResolution(96);
ff.setTargetResolution(300);

FOUserAgent userAgent = ff.newFOUserAgent();

ImageManager manager = ff.getImageManager();
ImageInfo info = manager.preloadImage(uri, userAgent.getImageSessionContext());
assertNotNull("ImageInfo must not be null", info);

Image img = manager.getImage(info, ImageFlavor.XML_DOM,
userAgent.getImageSessionContext());
assertNotNull("Image must not be null", img);
assertEquals(ImageFlavor.XML_DOM, img.getFlavor());
ImageXMLDOM imgDom = (ImageXMLDOM)img;
assertNotNull(imgDom.getDocument());
assertEquals("http://www.w3.org/2000/svg", imgDom.getRootNamespace());
info = imgDom.getInfo(); //Switch to the ImageInfo returned by the image
assertEquals(96, info.getSize().getDpiHorizontal(), 0);
assertEquals(340158, info.getSize().getWidthMpt());
assertEquals(340158, info.getSize().getHeightMpt());
assertEquals(454, info.getSize().getWidthPx());
assertEquals(454, info.getSize().getHeightPx());

img = manager.getImage(info, ImageFlavor.RENDERED_IMAGE,
userAgent.getImageSessionContext());
assertNotNull("Image must not be null", img);
assertEquals(ImageFlavor.RENDERED_IMAGE, img.getFlavor());
ImageRendered imgRed = (ImageRendered)img;
assertNotNull(imgRed.getRenderedImage());
if (DEBUG_TARGET_DIR != null) {
ImageWriterUtil.saveAsPNG(imgRed.getRenderedImage(),
(int)userAgent.getTargetResolution(),
new File(DEBUG_TARGET_DIR, "circles.svg.png"));
}
assertEquals(1418, imgRed.getRenderedImage().getWidth());
assertEquals(1418, imgRed.getRenderedImage().getHeight());
info = imgRed.getInfo(); //Switch to the ImageInfo returned by the image
assertEquals(340158, info.getSize().getWidthMpt());
assertEquals(340158, info.getSize().getHeightMpt());
}

public void testWMF() throws Exception {
String uri = "test/resources/images/testChart.wmf";


+ 4
- 13
test/layoutengine/standard-testcases/block_break-before_bug44412.xml View File

@@ -20,8 +20,7 @@
<info>
<p>
This test checks Bugzilla #44412 where a break-before on the first child of an otherwise
empty block is set. It is expected that the parent block creates two areas, the first with
only border-before on the first page and zero bpd.
empty block is set.
</p>
</info>
<fo>
@@ -44,20 +43,12 @@
</fo:root>
</fo>
<checks>
<eval expected="2" xpath="count(//block[@prod-id = 'b1'])"/>
<eval expected="4000 4000 4000 0" xpath="(//block[@prod-id = 'b1'])[1]/@bap"/>
<eval expected="4000 4000 0 4000" xpath="(//block[@prod-id = 'b1'])[2]/@bap"/>
<eval expected="0" xpath="(//block[@prod-id = 'b1'])[1]/@bpd"/>
<eval expected="43200" xpath="(//block[@prod-id = 'b1'])[2]/@bpd"/>
<eval expected="1" xpath="count(//block[@prod-id = 'b1'])"/>
<eval expected="4000 4000 4000 4000" xpath="(//block[@prod-id = 'b1'])[1]/@bap"/>
<eval expected="43200" xpath="(//block[@prod-id = 'b1'])[1]/@bpd"/>
<element-list category="breaker" index="0">
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="0" aux="true"/>
<penalty w="0" p="INF"/>
<glue w="4000"/> <!-- border-before -->
<box w="0"/> <!-- first block area of the "b1" block with zero bpd -->
<skip>3</skip>
</element-list>
</checks>

+ 151
- 0
test/layoutengine/standard-testcases/block_break-before_bug44412_2.xml View File

@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- $Id$ -->
<testcase>
<info>
<p>
This test checks for the correct behaviour of multiple breaks at the same break possibility.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="page" page-height="5in" page-width="5in" margin="20pt">
<fo:region-body/>
<fo:region-after extent="1.2em"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="page" id="ps1" initial-page-number="1" force-page-count="no-force">
<fo:static-content flow-name="xsl-region-after">
<fo:block>page: <fo:page-number/></fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block id="b1">Before the break</fo:block>
<fo:block break-before="page" break-after="column">
<fo:block id="b2" break-before="page">
This text should be on page 2.
</fo:block>
<fo:block>
<fo:block id="b3" break-after="page">
Inner block with break-after.
</fo:block>
</fo:block>
</fo:block>
<fo:block id="b4">This text should be on page 3.</fo:block>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="page" id="ps2" initial-page-number="1" force-page-count="no-force">
<fo:static-content flow-name="xsl-region-after">
<fo:block>page: <fo:page-number/></fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block id="b11">Before the break</fo:block>
<fo:block-container break-before="page" break-after="column">
<fo:block-container break-before="page">
<fo:block id="b12">This text should be on page 2.</fo:block>
</fo:block-container>
<fo:block>
<fo:block id="b13" break-after="page">
Inner block with break-after.
</fo:block>
</fo:block>
</fo:block-container>
<fo:block id="b14">This text should be on page 3.</fo:block>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="page" id="ps3" initial-page-number="1" force-page-count="no-force">
<fo:static-content flow-name="xsl-region-after">
<fo:block>page: <fo:page-number/></fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block id="b21">Before the break</fo:block>
<fo:block break-before="page" break-after="column">
<fo:table table-layout="fixed" width="100%" break-before="page">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block id="b22">This text should be on page 2.</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
<fo:block>
<fo:table table-layout="fixed" width="100%" break-after="page">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block id="b23">Inner block in table with break-after.</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</fo:block>
<fo:block id="b24">This text should be on page 3.</fo:block>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="page" id="ps4" initial-page-number="1" force-page-count="no-force">
<fo:static-content flow-name="xsl-region-after">
<fo:block>page: <fo:page-number/></fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block id="b31">Before the break</fo:block>
<fo:block break-before="page" break-after="column">
<fo:list-block break-before="page">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>+</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block id="b32">This text should be on page 2.</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item break-after="page">
<fo:list-item-label end-indent="label-end()">
<fo:block>+</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block id="b33">Inner block in list-item with break-after.</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:block>
<fo:block id="b34">This text should be on page 3.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<eval expected="1" xpath="//block[@prod-id = 'b1']/ancestor::pageViewport/@nr"/>
<eval expected="2" xpath="//block[@prod-id = 'b2']/ancestor::pageViewport/@nr"/>
<eval expected="2" xpath="//block[@prod-id = 'b3']/ancestor::pageViewport/@nr"/>
<eval expected="3" xpath="//block[@prod-id = 'b4']/ancestor::pageViewport/@nr"/>

<eval expected="1" xpath="//block[@prod-id = 'b11']/ancestor::pageViewport/@nr"/>
<eval expected="2" xpath="//block[@prod-id = 'b12']/ancestor::pageViewport/@nr"/>
<eval expected="2" xpath="//block[@prod-id = 'b13']/ancestor::pageViewport/@nr"/>
<eval expected="3" xpath="//block[@prod-id = 'b14']/ancestor::pageViewport/@nr"/>

<eval expected="1" xpath="//block[@prod-id = 'b21']/ancestor::pageViewport/@nr"/>
<eval expected="2" xpath="//block[@prod-id = 'b22']/ancestor::pageViewport/@nr"/>
<eval expected="2" xpath="//block[@prod-id = 'b23']/ancestor::pageViewport/@nr"/>
<eval expected="3" xpath="//block[@prod-id = 'b24']/ancestor::pageViewport/@nr"/>
</checks>
</testcase>

+ 8
- 0
test/resources/images/circles.svg View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="12cm" height="12cm">
<g style="fill-opacity:0.7; stroke:black; stroke-width:0.1cm;">
<circle cx="6cm" cy="2cm" r="100" style="fill:red;" transform="translate(0,50)" />
<circle cx="6cm" cy="2cm" r="100" style="fill:blue;" transform="translate(70,150)" />
<circle cx="6cm" cy="2cm" r="100" style="fill:green;" transform="translate(-70,150)"/>
</g>
</svg>

Loading…
Cancel
Save