From: Jeremias Maerki Date: Thu, 31 Jul 2008 09:06:10 +0000 (+0000) Subject: Merged revisions 636407-637074,637076-637118,637120-637790,637792-637856,637858-63799... X-Git-Tag: fop-1_0~475 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=178483e30913d2065d5f7a154932b2870a83081e;p=xmlgraphics-fop.git 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 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 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 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 --- diff --git a/README b/README index 133232276..37ede8930 100644 --- a/README +++ b/README @@ -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 diff --git a/build.xml b/build.xml index ff76686b6..60225fc29 100644 --- a/build.xml +++ b/build.xml @@ -401,6 +401,7 @@ list of possible build targets. + diff --git a/known-issues.xml b/known-issues.xml index 27ae55494..2ef4b7102 100644 --- a/known-issues.xml +++ b/known-issues.xml @@ -21,8 +21,9 @@ MIF and SVG output support have not been restored, yet. - 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. 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. - - The backgrounds of table-body, table-header, table-footer and - table-column are not painted, yet. - Border and padding conditionality are not supported on table-cells, yet. diff --git a/lib/avalon-framework-4.2.0.jar b/lib/avalon-framework-4.2.0.jar index b1aa6d7c9..22a7ab341 100644 Binary files a/lib/avalon-framework-4.2.0.jar and b/lib/avalon-framework-4.2.0.jar differ diff --git a/src/documentation/content/xdocs/0.95/compiling.xml b/src/documentation/content/xdocs/0.95/compiling.xml index 57761429f..98a6dfb6d 100644 --- a/src/documentation/content/xdocs/0.95/compiling.xml +++ b/src/documentation/content/xdocs/0.95/compiling.xml @@ -66,7 +66,7 @@
Apache Ant

- Apache Ant must be installed in order to + Apache Ant (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 instructions to install Ant in the Ant manual on the web.

diff --git a/src/documentation/content/xdocs/0.95/output.xml b/src/documentation/content/xdocs/0.95/output.xml index 628df1248..fbf277b90 100644 --- a/src/documentation/content/xdocs/0.95/output.xml +++ b/src/documentation/content/xdocs/0.95/output.xml @@ -703,6 +703,24 @@ out = proc.getOutputStream();]]> 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. +

+ These are some known restrictions compared to other supported output formats (not a complete list): +

+
    +
  • + Not supported/implemented: +
      +
    • break-before/after (supported by the RTF library but not tied into the RTFHandler)
    • +
    • fo:page-number-citation-last
    • +
    • keeps (supported by the RTF library but not tied into the RTFHandler)
    • +
    • region-start/end (RTF limitation)
    • +
    • multiple columns
    • +
    +
  • +
  • Only a single page-master is supported
  • +
  • Not all variations of fo:leader are supported (RTF limitation)
  • +
  • percentages are not supported everywhere
  • +
XML (Area Tree XML) @@ -735,6 +753,16 @@ out = proc.getOutputStream();]]> 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.

+
Bitmap (TIFF/PNG) diff --git a/src/documentation/content/xdocs/knownissues.xml b/src/documentation/content/xdocs/knownissues.xml index caf96ceaa..ea39b2974 100644 --- a/src/documentation/content/xdocs/knownissues.xml +++ b/src/documentation/content/xdocs/knownissues.xml @@ -66,6 +66,7 @@
Other known issues

This section lists other known issues.

+
diff --git a/src/documentation/content/xdocs/site.xml b/src/documentation/content/xdocs/site.xml index b0a3214e7..5ebdef322 100644 --- a/src/documentation/content/xdocs/site.xml +++ b/src/documentation/content/xdocs/site.xml @@ -96,10 +96,11 @@ - + - - + + + diff --git a/src/documentation/content/xdocs/tabs.xml b/src/documentation/content/xdocs/tabs.xml index a42fc9bd7..3db01d4fa 100644 --- a/src/documentation/content/xdocs/tabs.xml +++ b/src/documentation/content/xdocs/tabs.xml @@ -22,7 +22,7 @@ - + diff --git a/src/documentation/content/xdocs/trunk/compiling.xml b/src/documentation/content/xdocs/trunk/compiling.xml index 57761429f..98a6dfb6d 100644 --- a/src/documentation/content/xdocs/trunk/compiling.xml +++ b/src/documentation/content/xdocs/trunk/compiling.xml @@ -66,7 +66,7 @@
Apache Ant

- Apache Ant must be installed in order to + Apache Ant (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 instructions to install Ant in the Ant manual on the web.

diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index 22d916d31..b9916e198 100644 --- a/src/documentation/content/xdocs/trunk/output.xml +++ b/src/documentation/content/xdocs/trunk/output.xml @@ -728,6 +728,24 @@ out = proc.getOutputStream();]]> 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. +

+ These are some known restrictions compared to other supported output formats (not a complete list): +

+
    +
  • + Not supported/implemented: +
      +
    • break-before/after (supported by the RTF library but not tied into the RTFHandler)
    • +
    • fo:page-number-citation-last
    • +
    • keeps (supported by the RTF library but not tied into the RTFHandler)
    • +
    • region-start/end (RTF limitation)
    • +
    • multiple columns
    • +
    +
  • +
  • Only a single page-master is supported
  • +
  • Not all variations of fo:leader are supported (RTF limitation)
  • +
  • percentages are not supported everywhere
  • +
XML (Area Tree XML) @@ -760,6 +778,16 @@ out = proc.getOutputStream();]]> 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.

+
Bitmap (TIFF/PNG) @@ -911,3 +939,4 @@ out = proc.getOutputStream();]]> + diff --git a/src/documentation/skinconf.xml b/src/documentation/skinconf.xml index 20b12808e..b9a12fa59 100644 --- a/src/documentation/skinconf.xml +++ b/src/documentation/skinconf.xml @@ -378,6 +378,7 @@ which will be used to configure the chosen Forrest skin. 125 --> + PDF created by Apache FOP diff --git a/src/java/org/apache/fop/fo/flow/Block.java b/src/java/org/apache/fop/fo/flow/Block.java index d1df9c21d..4645734b2 100644 --- a/src/java/org/apache/fop/fo/flow/Block.java +++ b/src/java/org/apache/fop/fo/flow/Block.java @@ -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 * fo:block object. */ -public class Block extends FObjMixed { +public class Block extends FObjMixed implements BreakPropertySet { // used for FO validation private boolean blockOrInlineItemFound = false; diff --git a/src/java/org/apache/fop/fo/flow/BlockContainer.java b/src/java/org/apache/fop/fo/flow/BlockContainer.java index 25b3f2a2a..b0bfb3a32 100644 --- a/src/java/org/apache/fop/fo/flow/BlockContainer.java +++ b/src/java/org/apache/fop/fo/flow/BlockContainer.java @@ -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 * fo:block-container 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; diff --git a/src/java/org/apache/fop/fo/flow/ListBlock.java b/src/java/org/apache/fop/fo/flow/ListBlock.java index dfadc9c02..8f72ded67 100644 --- a/src/java/org/apache/fop/fo/flow/ListBlock.java +++ b/src/java/org/apache/fop/fo/flow/ListBlock.java @@ -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 * fo:list-block 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; diff --git a/src/java/org/apache/fop/fo/flow/ListItem.java b/src/java/org/apache/fop/fo/flow/ListItem.java index 95760c00b..f748bc15a 100644 --- a/src/java/org/apache/fop/fo/flow/ListItem.java +++ b/src/java/org/apache/fop/fo/flow/ListItem.java @@ -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 * fo:list-item 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; diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index efd1f1c93..86196cb29 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -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 * fo:table object. */ -public class Table extends TableFObj implements ColumnNumberManagerHolder { +public class Table extends TableFObj implements ColumnNumberManagerHolder, BreakPropertySet { /** properties */ private CommonBorderPaddingBackground commonBorderPaddingBackground; diff --git a/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java b/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java index 548a9c4fa..919e73bfb 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java +++ b/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java @@ -32,7 +32,7 @@ import org.apache.fop.fo.ValidationException; * fo:table-and-caption 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; diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java index 4d11f8780..a40b550bc 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableRow.java +++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java @@ -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 * fo:table-row 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; diff --git a/src/java/org/apache/fop/fo/properties/BreakPropertySet.java b/src/java/org/apache/fop/fo/properties/BreakPropertySet.java new file mode 100644 index 000000000..2babe0f19 --- /dev/null +++ b/src/java/org/apache/fop/fo/properties/BreakPropertySet.java @@ -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(); + +} diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index 4843b308a..f25ca4e7e 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/src/java/org/apache/fop/fonts/MultiByteFont.java @@ -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"); diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java index 8ad9fea44..6c43e4878 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -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(); diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java index ce6cde9d9..916b80d02 100644 --- a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java @@ -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; + } + } diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 17eb44049..b6dd4d082 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -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); diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 1d6662cb2..8837b1a0f 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -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 diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 1be89304b..8b716dfde 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -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() diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index f027922f7..d83cca642 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -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; } } diff --git a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java index c32c6eb3d..c1fc19050 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java +++ b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java @@ -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."); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 143c63bb9..dc2b3cc46 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -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); diff --git a/src/java/org/apache/fop/pdf/PDFNumber.java b/src/java/org/apache/fop/pdf/PDFNumber.java index 55834f529..c2fc704da 100644 --- a/src/java/org/apache/fop/pdf/PDFNumber.java +++ b/src/java/org/apache/fop/pdf/PDFNumber.java @@ -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( diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java b/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java index 7c4d66689..e3f510853 100644 --- a/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java +++ b/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java @@ -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); } /** diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java b/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java index 05e03fda0..f8152a978 100644 --- a/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java +++ b/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java @@ -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); } diff --git a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java index b61ebc346..f05a16f1a 100644 --- a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java @@ -115,7 +115,6 @@ public class PDFGraphics2DAdapter extends AbstractGraphics2DAdapter { pdfInfo.currentStream.add(graphics.getString()); renderer.restoreGraphicsState(); - pdfInfo.pdfState.pop(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/rtf/BorderAttributesConverter.java b/src/java/org/apache/fop/render/rtf/BorderAttributesConverter.java index 216802c8f..10c4a9c92 100644 --- a/src/java/org/apache/fop/render/rtf/BorderAttributesConverter.java +++ b/src/java/org/apache/fop/render/rtf/BorderAttributesConverter.java @@ -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); + } } } } diff --git a/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java b/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java index caf11323f..33a2ff904 100644 --- a/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java +++ b/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java @@ -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; + } } diff --git a/src/java/org/apache/fop/render/rtf/PageAttributesConverter.java b/src/java/org/apache/fop/render/rtf/PageAttributesConverter.java index c7f97ef4f..d50a81656 100644 --- a/src/java/org/apache/fop/render/rtf/PageAttributesConverter.java +++ b/src/java/org/apache/fop/render/rtf/PageAttributesConverter.java @@ -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"); diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 1adba9e2b..65c7bf681 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -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( diff --git a/src/java/org/apache/fop/render/rtf/TextAttributesConverter.java b/src/java/org/apache/fop/render/rtf/TextAttributesConverter.java index 792193b15..63c470b5d 100644 --- a/src/java/org/apache/fop/render/rtf/TextAttributesConverter.java +++ b/src/java/org/apache/fop/render/rtf/TextAttributesConverter.java @@ -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())); diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java index 2eb95b587..5ec5e907e 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java @@ -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 diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java index 182894ea5..6123ac563 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java @@ -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; } /** diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLeader.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLeader.java new file mode 100644 index 000000000..b3f11bc0a --- /dev/null +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLeader.java @@ -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 } \zwnj + * + * : \\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; + } + +} diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java index fb2df3fac..657900574 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java @@ -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 diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java index 92ba2bb7f..44c03c316 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java @@ -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); } diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java index eda5644a2..3747103d1 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java @@ -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. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java index fe936e3f5..f5e5978ec 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java @@ -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(); diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java index e0703d7ba..a9ba432b1 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java @@ -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. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/tools/PercentContext.java b/src/java/org/apache/fop/render/rtf/rtflib/tools/PercentContext.java new file mode 100644 index 000000000..ef9b248f1 --- /dev/null +++ b/src/java/org/apache/fop/render/rtf/rtflib/tools/PercentContext.java @@ -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); + } + } + } +} diff --git a/src/java/org/apache/fop/util/BreakUtil.java b/src/java/org/apache/fop/util/BreakUtil.java index 0e419016e..7302f270c 100644 --- a/src/java/org/apache/fop/util/BreakUtil.java +++ b/src/java/org/apache/fop/util/BreakUtil.java @@ -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); } } diff --git a/status.xml b/status.xml index 3e37d89a0..1a9cdb85e 100644 --- a/status.xml +++ b/status.xml @@ -172,12 +172,117 @@ + +
+ Notes +

+ Besides the important changes listed below, the most important areas with + improvements in this release are: +

+
    +
  • + Many bugfixes in tables, plus some new features (full support for keeps and + breaks, border conditionality, background on columns and header/footer/body) +
  • +
  • + Improvements and bugfixes for font handling and font + auto-detection/-registration. +
  • +
  • + Performance improvements and memory optimizations for the property handling + in the FO tree. +
  • +
+

+ Please note that with this release, we've dropped support for Java 1.3. + FOP will, from now on, require at least Java 1.4. +

+

+ There have been a few changes in tables that make FOP both more strict and more + compliant to the Recommendation: +

    +
  • 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 section + 6.7.3). From now on FOP will give a validation error if a document + contains such an erroneous cell. +
  • +
  • +

    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.

    +

    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.

    +
  • +
+

+

+ 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 + JAI Image I/O Tools + (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. +

+ + This final 0.95 release contains all the + changes made for Apache FOP 0.95beta. + +
+
- 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. + + + Fixed page ordering problem with AWTRenderer. + + + Fixed image scaling for RTF output. + + + Fixed the -imagein command-line option. + + + 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. + + + Added support for page-number-citation for RTF output. + + + Fixed handling of proportional-column-width() and percentages for table column in RTF + output. + + + Fixed NullPointerException when page-number-citations are used inside a marker. + + + Fixed two bugs concerning resolution handling with SVG images and their + conversion to bitmaps for RTF output. + + + Fixed potential multi-threading problem concerning the use of DecimalFormat. + + + Regression bugfix: Multiple collapsible breaks don't cause empty pages anymore. + Fixed resolution handling inside AWT preview dialog. + + + Fixed positioning of absolutely positioned block-containers in multi-column documents. + + Fixed rendering of fixed block-containers in AFP output. + + Various bugfixes for table layout. + Fixed regression causing bad positioning of block-containers if used as descendant of a table-cell. diff --git a/test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java b/test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java index c6c4015cc..457aa91d4 100644 --- a/test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java +++ b/test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java @@ -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"; diff --git a/test/layoutengine/standard-testcases/block_break-before_bug44412.xml b/test/layoutengine/standard-testcases/block_break-before_bug44412.xml index 9ef4150b5..cc5bcd3c8 100644 --- a/test/layoutengine/standard-testcases/block_break-before_bug44412.xml +++ b/test/layoutengine/standard-testcases/block_break-before_bug44412.xml @@ -20,8 +20,7 @@

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.

@@ -44,20 +43,12 @@ - - - - - + + + - - - - - - 3 diff --git a/test/layoutengine/standard-testcases/block_break-before_bug44412_2.xml b/test/layoutengine/standard-testcases/block_break-before_bug44412_2.xml new file mode 100644 index 000000000..3f54f809a --- /dev/null +++ b/test/layoutengine/standard-testcases/block_break-before_bug44412_2.xml @@ -0,0 +1,151 @@ + + + + + +

+ This test checks for the correct behaviour of multiple breaks at the same break possibility. +

+
+ + + + + + + + + + + page: + + + Before the break + + + This text should be on page 2. + + + + Inner block with break-after. + + + + This text should be on page 3. + + + + + page: + + + Before the break + + + This text should be on page 2. + + + + Inner block with break-after. + + + + This text should be on page 3. + + + + + page: + + + Before the break + + + + + + + This text should be on page 2. + + + + + + + + + + + Inner block in table with break-after. + + + + + + + This text should be on page 3. + + + + + page: + + + Before the break + + + + + + + + + This text should be on page 2. + + + + + + + + + Inner block in list-item with break-after. + + + + + This text should be on page 3. + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/resources/images/circles.svg b/test/resources/images/circles.svg new file mode 100644 index 000000000..8b71e8224 --- /dev/null +++ b/test/resources/images/circles.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file