diff options
author | Adrian Cumiskey <acumiskey@apache.org> | 2008-04-01 15:08:24 +0000 |
---|---|---|
committer | Adrian Cumiskey <acumiskey@apache.org> | 2008-04-01 15:08:24 +0000 |
commit | 068f78cf23e72c8f596c982eda4f295e7e7d5aed (patch) | |
tree | 03c06b88a10430c9fe3b1be2872fe661a5efb4ae /src/java/org | |
parent | 8aea6dca9c87eceacace44a78534f23f45096162 (diff) | |
download | xmlgraphics-fop-068f78cf23e72c8f596c982eda4f295e7e7d5aed.tar.gz xmlgraphics-fop-068f78cf23e72c8f596c982eda4f295e7e7d5aed.zip |
Merged revisions 611142,611175,611278,611285,611766-611768,612560,612785,612815-612816,612825,613144,613185,613828,613831,613835,613896,614156,614169-614170,614191,614201-614202,614566,614845,614920,614924,614964,614966,614993,615144,615164,615197,615251,615598,615604,615845,615906,615917,616080,616191,616260,616334,616485,616691,616694,616798,617126,617473,617512,617531,617550,617708,617716,617765,617812,617907,617909,617976,617989,618239,618470,618626-618627,618992,619417,619461,619670,619674,619790,619854,619856,619870,619923,619979,620272,620276-620278,620283,620285,620558-620559,620565,620567,620570,620723,620750,620761,627318,627324,627367,627495,627497,627553,627576,627679,627698,627702,627712,627719,627721,628140,628280,628652,628668,628775,628804,628816,628826,628829,629048,629093,629103,629129,629131,629169,629769,629902,630215,630772,630814,631178,631226,631276,631575,631609,631984,632121-632122,632321,632558,632716,632784,632938,632972,633389-633391,633396-633397,633437,633460,633470,633473,633525,633557,633559,633561,633961,634187,635508,635686,635701,635741,635884,635961,635967,636276,636293,636295,636405,636409,636471,637057,637076,638396,640089,640242,641742,641764,641827 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk
................
r611142 | jeremias | 2008-01-11 11:13:42 +0000 (Fri, 11 Jan 2008) | 3 lines
Initialized merge tracking via "svnmerge" with revisions "1-594557" from
https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImagePackageRedesign
................
r611175 | jeremias | 2008-01-11 13:41:54 +0000 (Fri, 11 Jan 2008) | 4 lines
Removed merge tracking for "svnmerge" for
https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImagePackageRedesign
(I'm not happy with the result)
................
r611278 | jeremias | 2008-01-11 19:50:53 +0000 (Fri, 11 Jan 2008) | 925 lines
Merged branch https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImagePackageRedesign (revs 594558 to 611138) into Trunk:
A new image loading framework has been introduced to fix various problems with external graphics and improve performance.
Switched to Batik 1.7.
Added xml-apis-ext.jar as needed by Batik 1.7.
Updated to latest XML Graphics Commons snapshot.
Changelog of branch:
------------------------------------------------------------------------
r594558 | jeremias | 2007-11-13 16:04:56 +0100 (Di, 13 Nov 2007) | 1 line
Branch for image package redesign
------------------------------------------------------------------------
r594560 | jeremias | 2007-11-13 16:10:35 +0100 (Di, 13 Nov 2007) | 1 line
Implementation of Dijkstra's algorithm for finding the shortest path. Used in the new image package to find the best combination of image loaders and image converters to provide an image in the optimal form for a renderer.
------------------------------------------------------------------------
r594848 | jeremias | 2007-11-14 13:12:50 +0100 (Mi, 14 Nov 2007) | 3 lines
Initial upload of what I have already for the image package redesign.
For now, it's in a parallel package (image2). The final package name is TBD.
The code isn't hooked into the renderers, yet, and there's no image cache. This is still all work in progress.
------------------------------------------------------------------------
r594851 | jeremias | 2007-11-14 13:20:12 +0100 (Mi, 14 Nov 2007) | 1 line
Test cases and additional test files for the new image package.
------------------------------------------------------------------------
r595305 | jeremias | 2007-11-15 15:01:37 +0100 (Do, 15 Nov 2007) | 1 line
Small mistake while reimplementing JPEG.
------------------------------------------------------------------------
r595308 | jeremias | 2007-11-15 15:13:36 +0100 (Do, 15 Nov 2007) | 5 lines
Introduced a usage penalty for ImageLoaders so we can calculate an overall penalty for a pipeline.
Multiple image flavors can be passed to ImageManager.getImage() if the caller supports multiple formats. The image package chooses the best pipeline.
Implemented a converter from RenderedImage to PNG.
Implemented loaders for raw formats (EMF, JPEG and PNG).
Hooked the new image package into the RTF handler as first real proof-of-concept.
------------------------------------------------------------------------
r596240 | jeremias | 2007-11-19 11:02:13 +0100 (Mo, 19 Nov 2007) | 1 line
Fixed bug in pipeline selection.
------------------------------------------------------------------------
r596242 | jeremias | 2007-11-19 11:03:06 +0100 (Mo, 19 Nov 2007) | 1 line
MIME type in parentheses behind the URI makes more sense.
------------------------------------------------------------------------
r599430 | jeremias | 2007-11-29 14:08:01 +0100 (Do, 29 Nov 2007) | 1 line
Support for baseline information (needed by at least MathML).
------------------------------------------------------------------------
r599433 | jeremias | 2007-11-29 14:09:04 +0100 (Do, 29 Nov 2007) | 1 line
Bugfix: BMP don't all have resolution information.
------------------------------------------------------------------------
r599434 | jeremias | 2007-11-29 14:10:54 +0100 (Do, 29 Nov 2007) | 1 line
Change MIME type
------------------------------------------------------------------------
r599436 | jeremias | 2007-11-29 14:17:14 +0100 (Do, 29 Nov 2007) | 3 lines
Started integrating into Java2D and PostScript renderers and ExternalGraphic.
Added support for EPS graphics.
Added support for raw embedding of JPEG images (for PostScript).
------------------------------------------------------------------------
r600821 | jeremias | 2007-12-04 08:51:06 +0100 (Di, 04 Dez 2007) | 5 lines
Clean up
Javadocs
Generally make more useful.
Reuse FOProcessor instance for the whole run to actually feel the effect of an image cache attached to the FopFactory.
Add option to prompt the user before actually starting (in order to connect a VM monitor).
------------------------------------------------------------------------
r600870 | jeremias | 2007-12-04 11:27:51 +0100 (Di, 04 Dez 2007) | 14 lines
Note: The API of the new image package has changed a bit. (it became necessary when I introduced caching)
The direct dependency on FOUserAgent has been removed to make the image package more universally usable. Instead an ImageContext (provided by FopFactory in FOP) and ImageSessionContext (provided by FOUserAgent in FOP) was introduced.
Introduced image caching with soft references (I didn't reintroduce the FOUserAgent lock, yet, because it doesn't help much)
ImageInfo doesn't carry the Source for the image anymore. The Source is provided by the new ImageSessionContext.java and only shared within the same thread to make things simpler and to avoid complex synchronization and cleanup.
Image instances now indicate whether they are cacheable (not all Image instances are cacheable, for example when they just carry an InputStream).
Moved the converter pipeline functionality into its own subpackage to keep "spi" clean.
Added checks in ImageSize to detect incomplete Preloaders.
ImageSource can now indicate whether its a fast source (loading from local file) or a slow source (loading over the network). (but this isn't used, yet)
Fixed a bug in WMF and SVG preloaders: they didn't close their Sources after fully loading the images.
Bugfix in ImageRawJPEG: it illegally reported being an EPS file
ImageRawStream got an "InputStreamFactory" so it is possible to reuse raw images if they have been loaded into memory (or to a local file which hasn't been implemented, yet).
The pipeline code now converts single-use raw images to reusable raw images when possible. But there's nothing built in to restrict the image size to a maximum, yet.
Improved JPEG preloader so it can stop early an deal with images that have to APP0 segment. Images from digicams are such an example. They carry the resolution info in the EXIF block which is currently not interpreted. Fallback is to the configured source resolution.
------------------------------------------------------------------------
r600930 | jeremias | 2007-12-04 14:25:43 +0100 (Di, 04 Dez 2007) | 1 line
Package HTML Files.
------------------------------------------------------------------------
r600934 | jeremias | 2007-12-04 14:34:41 +0100 (Di, 04 Dez 2007) | 1 line
Javadoc fixes
------------------------------------------------------------------------
r602023 | jeremias | 2007-12-07 09:46:56 +0100 (Fr, 07 Dez 2007) | 2 lines
Bugfix for bug in SVG preloader which didn't calculate the size of an SVG correctly when there's no explicit size.
------------------------------------------------------------------------
r602024 | jeremias | 2007-12-07 09:49:49 +0100 (Fr, 07 Dez 2007) | 1 line
Some small javadoc and logging improvements/refinements.
------------------------------------------------------------------------
r602025 | jeremias | 2007-12-07 09:50:22 +0100 (Fr, 07 Dez 2007) | 1 line
Enable assert keyword for javadoc production.
------------------------------------------------------------------------
r602032 | jeremias | 2007-12-07 09:59:10 +0100 (Fr, 07 Dez 2007) | 11 lines
Added color space information and an optional ICC color profile to the basic Image interface.
Reimplemented transparency support (for now only for ImageIO loader and PDF output)
ImageIO preloader passes the already loaded metadata to the ImageIO loader through the "custom objects" so it doesn't have to load them again.
PDF library: Corrected the naming of the method indicating the "bits per component" (bits per component != bits per pixel)
PDF library: Added a method which lets a user override values in an XObject's dictionary after the major values have been set (useful not to make the PDFImage interface more complicated).
PDF library: Support for gray transparent colors.
PDF library: Added a convenience class for alpha channel bitmaps (AlphaRasterImage)
Integration of the new image package into the PDFRenderer (currently supports all previous embedding methods except deprecated EPS embedding and CCITT embedding, now supports even more transparency options than before)
------------------------------------------------------------------------
r602033 | jeremias | 2007-12-07 09:59:57 +0100 (Fr, 07 Dez 2007) | 1 line
Small optimization from my failed experiments to support native PNG embedding.
------------------------------------------------------------------------
r602034 | jeremias | 2007-12-07 10:01:34 +0100 (Fr, 07 Dez 2007) | 1 line
Don't use "content" filter for ICC profiles. Instead compress using "default". "content" is for page content.
------------------------------------------------------------------------
r602036 | jeremias | 2007-12-07 10:02:25 +0100 (Fr, 07 Dez 2007) | 1 line
Added general key for precompressed content of any kind.
------------------------------------------------------------------------
r602037 | jeremias | 2007-12-07 10:03:39 +0100 (Fr, 07 Dez 2007) | 1 line
Various variants of the FOP logo for testing. Some of them have transparency info.
------------------------------------------------------------------------
r602228 | jeremias | 2007-12-07 22:30:17 +0100 (Fr, 07 Dez 2007) | 4 lines
Discarded PreloaderPNG in favor of PreloaderImageIO which now supports all formats supported by ImageIO (meaning that you can uses JPEG-2000 images if you have a suitable ImageIO codec installed).
ImagePreloader.getMimeType() removed because it isn't really used in the new setup.
ImagePreloader.getPriority() introduced which allows to prioritize preloaders and thus gives the opportunity to tweak the order in which the preloaders are checked when an image is inspected.
ImageLoaderImageIO can now use multiple Readers if one fails (one codec may not support all format variants, for example).
------------------------------------------------------------------------
r602229 | jeremias | 2007-12-07 22:30:48 +0100 (Fr, 07 Dez 2007) | 1 line
Added a toString() impl for debugging.
------------------------------------------------------------------------
r602442 | jeremias | 2007-12-08 11:36:32 +0100 (Sa, 08 Dez 2007) | 6 lines
Support handling images with no associated URI (from instream-foreign-object). These images are not cached.
Add support for plain image conversion (i.e. with no loading) for instream-foreign-object.
Add convenience writeTo() methods in ImageRawStream to save a few lines of code.
Support for instream-foreign-object in RTF output.
Teach RTF library to handle images without an associated URL.
------------------------------------------------------------------------
r603191 | jeremias | 2007-12-11 11:03:32 +0100 (Di, 11 Dez 2007) | 2 lines
Bugfix: Graphics2DAdapter didn't do the graphics state save correct so subsequent images may have been painted with the wrong transformation matrix.
Bugfix: bitmap images didn't scale correctly when the resolutions were changed.
------------------------------------------------------------------------
r603207 | jeremias | 2007-12-11 12:08:36 +0100 (Di, 11 Dez 2007) | 1 line
Convenience method for obtaining the image size in points.
------------------------------------------------------------------------
r603208 | jeremias | 2007-12-11 12:12:50 +0100 (Di, 11 Dez 2007) | 3 lines
Precisely define the expectations for the area parameter in Graphics2DImagePainter.
New ImageConverter: Bitmap -> Graphics2D
------------------------------------------------------------------------
r603209 | jeremias | 2007-12-11 12:15:49 +0100 (Di, 11 Dez 2007) | 3 lines
Refine pipeline building:
Expose a method to allow the PS Renderer to predict what kind of pipeline will be selected (because it doesn't support all image types as PostScript forms)
If there are multiple candidate pipelines for one conversion type, choose the one with the lowest penalty, not just the one that happens to be first.
------------------------------------------------------------------------
r603250 | jeremias | 2007-12-11 15:17:32 +0100 (Di, 11 Dez 2007) | 1 line
Removing failed experiment: raw PNG embedding didn't work out.
------------------------------------------------------------------------
r603254 | jeremias | 2007-12-11 15:29:48 +0100 (Di, 11 Dez 2007) | 2 lines
Plugged new image package into form generation for PostScript.
XML images and EPS files are currently supported as forms. They are added inline.
------------------------------------------------------------------------
r603256 | jeremias | 2007-12-11 15:34:52 +0100 (Di, 11 Dez 2007) | 1 line
Embedding EPS in PDF is no longer implemented as it is a deprecated feature in PDF. Therefore, this test is not needed anymore. The PDF renderer will say: "Cannot load image (no suitable loader/converter combination available) for myfile.eps (application/postscript)"
------------------------------------------------------------------------
r603266 | jeremias | 2007-12-11 16:16:22 +0100 (Di, 11 Dez 2007) | 1 line
Size calculation for images can be slightly different after the redesign due to different rounding. Give a little tolerance.
------------------------------------------------------------------------
r603271 | jeremias | 2007-12-11 16:24:08 +0100 (Di, 11 Dez 2007) | 1 line
Bugfix: Only generate the FixedLength if there is baseline information.
------------------------------------------------------------------------
r603358 | jeremias | 2007-12-11 22:13:22 +0100 (Di, 11 Dez 2007) | 1 line
Switched background images to new image package.
------------------------------------------------------------------------
r603632 | jeremias | 2007-12-12 15:52:09 +0100 (Mi, 12 Dez 2007) | 1 line
Switch to new image package for PDF/SVG support.
------------------------------------------------------------------------
r603642 | jeremias | 2007-12-12 16:30:16 +0100 (Mi, 12 Dez 2007) | 3 lines
Initialized merge tracking via "svnmerge" with revisions "1-594557" from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk
------------------------------------------------------------------------
r603656 | jeremias | 2007-12-12 17:13:06 +0100 (Mi, 12 Dez 2007) | 307 lines
Merged revisions 594558-603642 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk
........
r594571 | vhennebert | 2007-11-13 17:24:32 +0100 (Di, 13 Nov 2007) | 7 lines
Moved the creation of grid units to the FO tree building stage. Brought a few improvements along with the move:
- bugfix: border-resolution for border-end on row-spanning cells was wrong
- bugfix: in case of missing cells the border-end of the table was applied to an inner cell, instead of the cell in the last column (but missing cells aren't painted yet :-\)
- bugfix: in collapsing-border model, border-before and -after specified on table-column were applied to every cell of the column, instead of only the first and the last ones
- border resolution is now made progressively when possible, and no longer triggers the fetching of all the rows of the table
Added testcases for the border conflict resolution (between the various elements of a table and not only the cells)
........
r594578 | vhennebert | 2007-11-13 17:50:09 +0100 (Di, 13 Nov 2007) | 2 lines
Moved *GridUnit from layoutmgr/table to fo/flow/table
........
r594579 | vhennebert | 2007-11-13 17:55:54 +0100 (Di, 13 Nov 2007) | 2 lines
Changed back visibility of fields from public to package-private, due to the move of *GridUnit in the fo.flow.table package
........
r594584 | vhennebert | 2007-11-13 18:13:19 +0100 (Di, 13 Nov 2007) | 2 lines
Use a singleton for a default BorderInfo of style none, instead of every time a new instance
........
r594592 | vhennebert | 2007-11-13 18:39:17 +0100 (Di, 13 Nov 2007) | 2 lines
Cleaned up RowGroupLayoutManager and TableRowIterator
........
r594821 | vhennebert | 2007-11-14 11:18:45 +0100 (Mi, 14 Nov 2007) | 2 lines
Moved EffRow to the fo.flow.table package
........
r594829 | vhennebert | 2007-11-14 11:41:52 +0100 (Mi, 14 Nov 2007) | 2 lines
Reduced visibility of some methods and constructors from public to package-private, as a consequence of the move of *GridUnit to the fo.flow.table package
........
r594836 | vhennebert | 2007-11-14 12:14:03 +0100 (Mi, 14 Nov 2007) | 2 lines
Restored the setting of the parent table-row element on grid units
........
r594852 | vhennebert | 2007-11-14 13:21:53 +0100 (Mi, 14 Nov 2007) | 2 lines
Restored the setting of rowIndex on primary grid units (although testcases were already working...)
........
r595297 | jeremias | 2007-11-15 14:28:58 +0100 (Do, 15 Nov 2007) | 2 lines
Bugzilla #43143:
Had to remove the Expert(Subset) Encoding detection as this caused problems with a barcode font that used dfCharset=2 but was not using ExpertSubset encoding. To detect Expert(Subset)Encoding, the AFM needs to be parsed. And since we don't support that encoding, yet, the fallback to WinAnsiEncoding should work well enough.
........
r595637 | acumiskey | 2007-11-16 13:12:52 +0100 (Fr, 16 Nov 2007) | 3 lines
This should improve the ability of the FontLoader when resolving PFM files
for Type 1 fonts on case sensitive Unix systems.
........
r596072 | jeremias | 2007-11-18 11:48:53 +0100 (So, 18 Nov 2007) | 4 lines
ApacheCon US is over.
OSSSummit was cancelled/postponed.
Added example for total page count using XSL 1.1
Adjusted total page count example to new FOP API. (Thanks to Miroslav Gregan for the hint)
........
r596097 | jeremias | 2007-11-18 17:56:09 +0100 (So, 18 Nov 2007) | 6 lines
Bugzilla #43605:
Added methods for page-number-citation and page-number-citation-last in FOEventHandler.java
Submitted by: V. Schappert <vschappert.at.bloomberg.net>
Patch modified by Jeremias:
Bugfix: FOEventHandler.startPageNumberCitation() was also called in the case of a page-number-citation-last. Introduced abstract base classes to avoid this.
........
r596100 | jeremias | 2007-11-18 18:17:24 +0100 (So, 18 Nov 2007) | 1 line
Added sample as suggested by Kumar Puppala.
........
r596390 | vhennebert | 2007-11-19 19:25:27 +0100 (Mo, 19 Nov 2007) | 2 lines
Bugzilla #43766: breaks generated by the merging algorithm for table rows containing empty cells has always a penalty of 900
........
r596554 | jeremias | 2007-11-20 08:14:33 +0100 (Di, 20 Nov 2007) | 2 lines
Bugzilla #43904:
Buffer the OutputStreams in our transcoders if the users forget.
........
r596600 | jeremias | 2007-11-20 11:20:29 +0100 (Di, 20 Nov 2007) | 3 lines
Bugzilla #43910:
Avoid a NullPointerException in AreaTreeHandler.endDocument().
Submitted by: David Delbecq <delbd.at.oma.be>
........
r596724 | jeremias | 2007-11-20 16:56:33 +0100 (Di, 20 Nov 2007) | 3 lines
Bugfix: Bugfix for URI resolution: Make StreamSources without system identifier work again.
Bugfix: Close streams opened by test font resolution in font configuration (the font URIs will be resolved again later anyway).
Better error message when the loading of font metric files doesn't work due to missing information in the returned Source instances.
........
r596727 | vhennebert | 2007-11-20 17:07:32 +0100 (Di, 20 Nov 2007) | 2 lines
Bugfix in tables: wrong element generation by the merging algorithm when glues must be produced to cope with conditional spaces. The corresponding length was added twice: one in the glue itself and one in the following box.
........
r596739 | cbowditch | 2007-11-20 17:49:13 +0100 (Di, 20 Nov 2007) | 1 line
bug fix: memory leak in PropertyCache. Fix provided by Jeremias. There are still some thread synchronization issues to be addressed in the PropertyCache. See the following thread for details: http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200711.mbox/%3cBAY117-DAV109E36CC066889386AB917FB870@phx.gbl%3e
........
r596742 | vhennebert | 2007-11-20 18:08:46 +0100 (Di, 20 Nov 2007) | 2 lines
Added a news entry about Max Berger becoming a committer. Welcome Max!
........
r596776 | vhennebert | 2007-11-20 19:47:39 +0100 (Di, 20 Nov 2007) | 2 lines
Bugzilla #43803: table cells having no children are allowed in relaxed validation mode.
........
r597052 | vhennebert | 2007-11-21 13:23:59 +0100 (Mi, 21 Nov 2007) | 2 lines
Bugfix: the last element generated by the merging algorithm may now be a glue
........
r597448 | jeremias | 2007-11-22 17:13:05 +0100 (Do, 22 Nov 2007) | 2 lines
First draft of a possible new intermediate format for Apache FOP.
Details on: http://wiki.apache.org/xmlgraphics-fop/AreaTreeIntermediateXml/NewDesign
........
r598558 | jeremias | 2007-11-27 09:36:23 +0100 (Di, 27 Nov 2007) | 6 lines
Bugzilla #40230:
Bugfix: no empty page is generated anymore if there's no content after a break-after.
Bugzilla #43917:
Bugfix for border-after painting and element list generation when a forced break is involved.
........
r599536 | vhennebert | 2007-11-29 19:31:13 +0100 (Do, 29 Nov 2007) | 4 lines
Added fixes-bug attributes for:
- wrong element generation in table when glues are produced
- border-resolution on row-spanning cells
........
r599746 | jeremias | 2007-11-30 10:04:54 +0100 (Fr, 30 Nov 2007) | 2 lines
Bugzilla #37993:
Bugfix: allow multiple bookmarks to point at the same destination.
........
r600195 | adelmelle | 2007-12-01 22:11:53 +0100 (Sa, 01 Dez 2007) | 1 line
Correction and simplification of the PropertyCache: subclass WeakReference and remove internal threading
........
r600467 | jeremias | 2007-12-03 11:16:27 +0100 (Mo, 03 Dez 2007) | 2 lines
Log RuntimeExceptions during rendering so that they are at least visible somewhere if someone doesn't set an ErrorListener on the XSLT processor (this could lead to exceptions being swallowed). This is a temporary measure until we have time to improve the exception handling in FOP.
The original problem that led to this change was: "The number of this PDFNumber must not be empty" while producing a PDF/A with customized filter entries in the PDF configuration. The exception was a follow-up exception after a PDFConformanceException that was swallowed by a default ErrorListener.
........
r600521 | jeremias | 2007-12-03 14:21:06 +0100 (Mo, 03 Dez 2007) | 1 line
Added a possibility to rerun the whole run a defined number of times to test for possible issues outside a single rendering run.
........
r600529 | jeremias | 2007-12-03 14:32:04 +0100 (Mo, 03 Dez 2007) | 1 line
Oops.
........
r601413 | vhennebert | 2007-12-05 17:56:47 +0100 (Mi, 05 Dez 2007) | 2 lines
Typo in property: svn:kewords -> svn:keywords
........
r601415 | acumiskey | 2007-12-05 18:11:44 +0100 (Mi, 05 Dez 2007) | 2 lines
Corrected javadocs
........
r601416 | acumiskey | 2007-12-05 18:12:54 +0100 (Mi, 05 Dez 2007) | 2 lines
Corrected javadoc
........
r601417 | acumiskey | 2007-12-05 18:13:31 +0100 (Mi, 05 Dez 2007) | 2 lines
Corrected javadoc
........
r601419 | acumiskey | 2007-12-05 18:15:46 +0100 (Mi, 05 Dez 2007) | 2 lines
Improved use of logging
........
r601423 | acumiskey | 2007-12-05 18:19:43 +0100 (Mi, 05 Dez 2007) | 2 lines
Corrected javadoc, fixed checkstyle issues, and now also correctly caters for negative number conversions
........
r601424 | acumiskey | 2007-12-05 18:21:15 +0100 (Mi, 05 Dez 2007) | 2 lines
Fixed checkstyle issues
........
r601426 | acumiskey | 2007-12-05 18:24:15 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601427 | acumiskey | 2007-12-05 18:25:07 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601428 | acumiskey | 2007-12-05 18:25:58 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601429 | acumiskey | 2007-12-05 18:27:06 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601430 | acumiskey | 2007-12-05 18:28:03 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601431 | acumiskey | 2007-12-05 18:28:48 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601432 | acumiskey | 2007-12-05 18:29:31 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601433 | acumiskey | 2007-12-05 18:30:04 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601434 | acumiskey | 2007-12-05 18:31:20 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601435 | acumiskey | 2007-12-05 18:32:29 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601436 | acumiskey | 2007-12-05 18:34:44 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601437 | acumiskey | 2007-12-05 18:35:31 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601438 | acumiskey | 2007-12-05 18:36:12 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes and cleanup
........
r601439 | acumiskey | 2007-12-05 18:37:40 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601440 | acumiskey | 2007-12-05 18:39:54 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601442 | acumiskey | 2007-12-05 18:42:13 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601443 | acumiskey | 2007-12-05 18:42:48 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601444 | acumiskey | 2007-12-05 18:43:46 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601445 | acumiskey | 2007-12-05 18:44:36 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601446 | acumiskey | 2007-12-05 18:45:20 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601447 | acumiskey | 2007-12-05 18:47:44 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601448 | acumiskey | 2007-12-05 18:48:56 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601449 | acumiskey | 2007-12-05 18:49:46 +0100 (Mi, 05 Dez 2007) | 2 lines
Checkstyle fixes
........
r601712 | acumiskey | 2007-12-06 12:57:14 +0100 (Do, 06 Dez 2007) | 2 lines
Temporary fix to the build
........
r602045 | jeremias | 2007-12-07 10:20:28 +0100 (Fr, 07 Dez 2007) | 1 line
Avoid a NPE in toString().
........
r602125 | maxberger | 2007-12-07 16:36:53 +0100 (Fr, 07 Dez 2007) | 6 lines
Updated xmlgraphics from SVN
Added autodetection of fonts in jar files (x-font and x-font-truetype)
Added files needed for testcase
Please note: Actual testcase is still missing!
........
r602898 | maxberger | 2007-12-10 14:35:33 +0100 (Mo, 10 Dez 2007) | 2 lines
Added documentation for font-in-jar-files
........
r603590 | acumiskey | 2007-12-12 13:24:10 +0100 (Mi, 12 Dez 2007) | 4 lines
* Added an SVG handler and Graphics2D implementation for AFP which injects AFP GOCA structured fields into the AFPDataStream.
* Fixed many checkstyle problems.
* Updated xmlgraphics-commons-1.3svn.jar to include changes to TextHandler
........
r603592 | acumiskey | 2007-12-12 13:26:39 +0100 (Mi, 12 Dez 2007) | 2 lines
Updated status with SVG support for AFP.
........
------------------------------------------------------------------------
r603661 | jeremias | 2007-12-12 17:20:09 +0100 (Mi, 12 Dez 2007) | 1 line
Fix javadoc
------------------------------------------------------------------------
r603886 | jeremias | 2007-12-13 12:15:48 +0100 (Do, 13 Dez 2007) | 1 line
Copy/paste programming is dangerous. :-)
------------------------------------------------------------------------
r603902 | jeremias | 2007-12-13 13:17:56 +0100 (Do, 13 Dez 2007) | 2 lines
Factored out all image handling code in the PDFRenderer into PDFImageHandler classes. The interface was introduced to handle PDF-in-PDF images.
The PDFImageHandler interface changes in a backwards-incompatible way but since the PDF-in-PDF plug-in probably has the only implementation, that's not very problematic. I'll release a new version as soon as the image stuff is merged back into Trunk.
------------------------------------------------------------------------
r603937 | jeremias | 2007-12-13 16:20:46 +0100 (Do, 13 Dez 2007) | 1 line
Some cleanup
------------------------------------------------------------------------
r603938 | jeremias | 2007-12-13 16:23:23 +0100 (Do, 13 Dez 2007) | 2 lines
Switch PCL renderer to new image package.
Add an option to force a color canvas (RGB) instead of a gray canvas. Set this to true for all SVG graphics since Batik does not seem to support gradients on a grayscale canvas (IllegalArgumentException).
------------------------------------------------------------------------
r604122 | jeremias | 2007-12-14 08:58:56 +0100 (Fr, 14 Dez 2007) | 1 line
Stupid copy/paste again.
------------------------------------------------------------------------
r604135 | jeremias | 2007-12-14 10:04:43 +0100 (Fr, 14 Dez 2007) | 1 line
Preliminary changes to switch to the new image library. TIFF optimizations still missing. Untested.
------------------------------------------------------------------------
r604144 | jeremias | 2007-12-14 11:12:41 +0100 (Fr, 14 Dez 2007) | 1 line
Switch to new image package. At some point we will probably want to remove this example as JEuclid has a better plug-in now.
------------------------------------------------------------------------
r604150 | jeremias | 2007-12-14 11:27:39 +0100 (Fr, 14 Dez 2007) | 1 line
Old JEuclid doesn't notice itself if no MathML document is loaded.
------------------------------------------------------------------------
r604155 | jeremias | 2007-12-14 11:48:07 +0100 (Fr, 14 Dez 2007) | 2 lines
Switched to new image package.
The preloader simply loads the full document and converts it to SVG. That's the only way to determine the intrinsic size of the image.
------------------------------------------------------------------------
r604157 | jeremias | 2007-12-14 11:51:21 +0100 (Fr, 14 Dez 2007) | 1 line
No longer needed.
------------------------------------------------------------------------
r604214 | jeremias | 2007-12-14 17:07:30 +0100 (Fr, 14 Dez 2007) | 1 line
Added work-around for decoding CMYK JPEGs with ImageIO (no guarantees for color fidelity but it's better than not being able to use CMYK images).
------------------------------------------------------------------------
r604297 | jeremias | 2007-12-14 22:14:12 +0100 (Fr, 14 Dez 2007) | 68 lines
Merged revisions 603643-604293 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk
........
r603890 | vhennebert | 2007-12-13 12:35:17 +0100 (Do, 13 Dez 2007) | 2 lines
Fixed @throws statements in javadoc
........
r603926 | adelmelle | 2007-12-13 15:43:08 +0100 (Do, 13 Dez 2007) | 4 lines
Minor tweaks:
* only add text to a fo:wrapper if it is not a direct flow-descendant
* error if an fo:wrapper that is a direct flow-descendant contains inline-level children
........
r603943 | vhennebert | 2007-12-13 16:55:29 +0100 (Do, 13 Dez 2007) | 2 lines
Removed calls to removeLegalBreaks since they aren't necessary (the whole content is put in a single box anyway) and the method is buggy.
........
r603945 | vhennebert | 2007-12-13 17:10:32 +0100 (Do, 13 Dez 2007) | 2 lines
Implemented the resolution of collapsing borders in the FO tree, for every situation (normal, cell at the top of a page, cell broken), taking conditionality, headers and footers into account.
........
r603959 | vhennebert | 2007-12-13 18:21:24 +0100 (Do, 13 Dez 2007) | 2 lines
Reverted change accidentally introduced in the previous commit. A proper fix needs to be found for this one.
........
r603961 | vhennebert | 2007-12-13 18:31:26 +0100 (Do, 13 Dez 2007) | 2 lines
Ok, now /really/ revert the previous commit :-\
........
r603962 | vhennebert | 2007-12-13 18:32:43 +0100 (Do, 13 Dez 2007) | 2 lines
Style only: removed trailing white spaces
........
r603968 | vhennebert | 2007-12-13 19:28:56 +0100 (Do, 13 Dez 2007) | 2 lines
Fixed the handling of columns in the border resolution, especially in case of column-spanning cells
........
r603975 | vhennebert | 2007-12-13 19:52:48 +0100 (Do, 13 Dez 2007) | 2 lines
Removed parameter from the endPart method, since the part is already passed as a parameter of the previously called startPart method
........
r603979 | vhennebert | 2007-12-13 19:57:25 +0100 (Do, 13 Dez 2007) | 2 lines
Removed parameter from the endTablePart method, as the part is already passed as as a parameter of the previously called startTablePart method
........
r603990 | vhennebert | 2007-12-13 20:17:12 +0100 (Do, 13 Dez 2007) | 2 lines
Throw a ValidationException if table-footer is put after table-body and the table uses the collapsing border model. The footer must be known to properly resolve borders.
........
r604171 | vhennebert | 2007-12-14 12:32:51 +0100 (Fr, 14 Dez 2007) | 2 lines
Clean up: removed all reset and resetPosition methods, which pre-date the Knuth era and are no longer needed
........
r604180 | vhennebert | 2007-12-14 13:23:10 +0100 (Fr, 14 Dez 2007) | 2 lines
Reduced visibility of methods from public to package-private
........
r604185 | acumiskey | 2007-12-14 14:16:06 +0100 (Fr, 14 Dez 2007) | 2 lines
Fixed copy constructor
........
r604293 | jeremias | 2007-12-14 21:58:53 +0100 (Fr, 14 Dez 2007) | 2 lines
Bugfix: DecodeParms -> DecodeParams (introduced when I changed to generic PDF structures)
(fixes CCITT encoded images)
........
------------------------------------------------------------------------
r604301 | jeremias | 2007-12-14 22:26:27 +0100 (Fr, 14 Dez 2007) | 9 lines
Merged revisions 604294-604299 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk
........
r604299 | jeremias | 2007-12-14 22:24:14 +0100 (Fr, 14 Dez 2007) | 1 line
Don't hack when you're tired! Reverting r604293 and instead fixing the right value. It's DecodeParams -> DecodeParms!
........
------------------------------------------------------------------------
r604930 | jeremias | 2007-12-17 18:05:47 +0100 (Mo, 17 Dez 2007) | 2 lines
Dispose ImageReader when done reading.
Don't close streams as some codecs appear to do "late reading" of the image, i.e. only when the rasters are accessed, at which point they still seek on the stream. For this, the streams must remain open. I hope the codecs all properly close the streams once they don't need them anymore. The javadocs are not clear enough in this regards, IMO.
------------------------------------------------------------------------
r604968 | jeremias | 2007-12-17 20:03:45 +0100 (Mo, 17 Dez 2007) | 3 lines
Added an isSupported() method to ImageLoaderFactory so we can check early if an ImageLoader may or may not support a particular subformat. This is used to allow optimized loading of CCITT compressed TIFF images.
Support for undecoded embedding of single-strip CCITT compressed images for PDF, PostScript and AFP.
Added a fallback mechanism for ImageLoaders: if one ImageLoader cannot load a particular image, try equivalent others registered for the same format.
------------------------------------------------------------------------
r604972 | jeremias | 2007-12-17 20:07:43 +0100 (Mo, 17 Dez 2007) | 1 line
Update Commons
------------------------------------------------------------------------
r605138 | jeremias | 2007-12-18 09:42:41 +0100 (Di, 18 Dez 2007) | 2 lines
Support for specifying a particular page number of a multi-page image (such as TIFF).
Format: http://localhost/images/scan1.tif#page=3
------------------------------------------------------------------------
r605479 | jeremias | 2007-12-19 10:18:33 +0100 (Mi, 19 Dez 2007) | 3 lines
Removed new image package after the copying it to XML Graphics Commons.
Adjusted to use the Commons' version.
Batik-dependent plugins remain but will eventually need a different resting place.
------------------------------------------------------------------------
r605486 | jeremias | 2007-12-19 10:39:33 +0100 (Mi, 19 Dez 2007) | 1 line
Adjust the (pre)loader registration for the demo extensions.
------------------------------------------------------------------------
r605567 | jeremias | 2007-12-19 16:03:25 +0100 (Mi, 19 Dez 2007) | 1 line
Fixed scaling and translation (didn't work correctly in certain situations)
------------------------------------------------------------------------
r607034 | jeremias | 2007-12-27 11:47:12 +0100 (Do, 27 Dez 2007) | 71 lines
Merged revisions 604300-607033 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk
........
r604475 | vhennebert | 2007-12-15 19:16:01 +0100 (Sa, 15 Dez 2007) | 2 lines
Testcase for the resolution of collapsed and conditional borders in the FO tree
........
r604678 | adelmelle | 2007-12-16 20:54:00 +0100 (So, 16 Dez 2007) | 8 lines
Streamlining/Correction of the changes made in r603926
- delegate validation of the fo:wrapper's children to the parent: added static FONode.validateChildNode()
- narrow the condition for processing text-childnodes:
this is not only constrained to fo:flow and fo:static-content, but the same goes
for a fo:wrapper that is a direct descendant of a fo:block-container or fo:inline-container,
which only allow block-level content (interpretation)
- minor javadoc fixups/improvements
........
r604814 | vhennebert | 2007-12-17 11:21:04 +0100 (Mo, 17 Dez 2007) | 2 lines
Organized imports
........
r604965 | vhennebert | 2007-12-17 19:56:46 +0100 (Mo, 17 Dez 2007) | 2 lines
Renaming GridUnitPart into the more accurate CellPart. Moreover I was always making the confusion between gup and pgu
........
r604970 | vhennebert | 2007-12-17 20:05:27 +0100 (Mo, 17 Dez 2007) | 2 lines
Simplified addAreasAndFlushRow: there can no longer be null GridUnits, every hole in the grid is now filled with an EmptyGridUnit
........
r605195 | vhennebert | 2007-12-18 12:56:38 +0100 (Di, 18 Dez 2007) | 2 lines
Reset previousRowsLength before a new row-group is handled
........
r605246 | vhennebert | 2007-12-18 17:48:03 +0100 (Di, 18 Dez 2007) | 2 lines
Simplification in RowPainter: avoid the use of an array to store rowOffsets and firstRow index for each part of the table (header, footer, body). One at a time is enough.
........
r605253 | vhennebert | 2007-12-18 18:01:45 +0100 (Di, 18 Dez 2007) | 2 lines
Renamed firstRow into firstRowIndex and moved its initialization into handeTableContentPosition
........
r605295 | vhennebert | 2007-12-18 19:58:29 +0100 (Di, 18 Dez 2007) | 2 lines
Streamlined the recording of row offsets, by replacing Map with a List. Fixed bug #43633 in the same time.
........
r605297 | vhennebert | 2007-12-18 20:02:02 +0100 (Di, 18 Dez 2007) | 3 lines
SVG support for AFP is an important addition IMO.
IIUC it will have to be advertised in the next release as "Support for SVG images using primitive AFP graphics commands instead of bitmap images", or something like that?
........
r605517 | vhennebert | 2007-12-19 12:47:38 +0100 (Mi, 19 Dez 2007) | 2 lines
I said currentGU can no longer be null
........
r605978 | jeremias | 2007-12-20 18:00:46 +0100 (Do, 20 Dez 2007) | 1 line
Remove commented code.
........
r606004 | jeremias | 2007-12-20 20:19:19 +0100 (Do, 20 Dez 2007) | 1 line
Added support for scale-down-to-fit and scale-up-to-fit.
........
r607032 | jeremias | 2007-12-27 11:34:15 +0100 (Do, 27 Dez 2007) | 4 lines
Added new extension element: fox:external-document. It allows to add whole documents such as multi-page TIFF images to be inserted as peers to a page-sequence. Each image will make up an entire page. See the documentation for details. ATM, only single pages are possible. Multi-page images will be supported with the new image package.
Some preparations for page-position="only" but the implementation is incomplete and "only" has no effect, yet. (Just uploaded some stuff I once started)
Some javadoc cleanups.
........
------------------------------------------------------------------------
r607091 | jeremias | 2007-12-27 18:13:45 +0100 (Do, 27 Dez 2007) | 1 line
Avoid cutting away the URI fragment when building URLs from filenames.
------------------------------------------------------------------------
r607092 | jeremias | 2007-12-27 18:15:49 +0100 (Do, 27 Dez 2007) | 3 lines
Switched fox:external-document to new image package.
Added multi-page support for fox:external-document.
Changed multi-page.tiff: page 4 is now bigger than all other pages. (to make sure that individually sized pages are handled properly)
------------------------------------------------------------------------
r607188 | jeremias | 2007-12-28 09:38:26 +0100 (Fr, 28 Dez 2007) | 2 lines
Throwing IllegalStateException causes a prior exception to be swallowed by Xalan-J. Need to throw a SAXException instead.
Instead of logging an error about the element mismatch throw a SAXException because the logging only confuses the user as it's practically always a follow-up exception of an exception happening earlier in the respective startElement() event.
------------------------------------------------------------------------
r607249 | jeremias | 2007-12-28 15:27:39 +0100 (Fr, 28 Dez 2007) | 1 line
Metadata didn't get transported to the renderer when only fox:external-document is used.
------------------------------------------------------------------------
r607256 | jeremias | 2007-12-28 16:06:35 +0100 (Fr, 28 Dez 2007) | 1 line
Corrected content model.
------------------------------------------------------------------------
r607261 | jeremias | 2007-12-28 16:11:56 +0100 (Fr, 28 Dez 2007) | 1 line
Added -imagein to command-line so (multi-page) images such as TIFF files can be converted to PDF and other formats supported by FOP. The default stylesheet can be overwritten (with -xslt) if desired.
------------------------------------------------------------------------
r609530 | jeremias | 2008-01-07 09:16:09 +0100 (Mo, 07 Jan 2008) | 1 line
Fixed copy/paste mistake. Thanks for spotting it, Vincent.
------------------------------------------------------------------------
r609600 | jeremias | 2008-01-07 14:28:53 +0100 (Mo, 07 Jan 2008) | 1 line
Removed "image2" package again and moved the Batik-dependent implementations under the old "image" package. In this form, the deprecated code doesn't conflict with the new implementations anymore.
------------------------------------------------------------------------
r610029 | jeremias | 2008-01-08 16:48:53 +0100 (Di, 08 Jan 2008) | 3 lines
Added minimal support for the .minimum/.maximum components of block/inline-progression-dimension on fo:external-graphic and fo:instream-foreign-object. This will only constrain the image itself but not allow the layout engine itself to resize the image as seen fit.
Added missing Javadocs in ImageLayout.java.
------------------------------------------------------------------------
r611120 | jeremias | 2008-01-11 10:20:57 +0100 (Fr, 11 Jan 2008) | 100 lines
Merged revisions 607034-611115 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk
........
r607036 | jeremias | 2007-12-27 11:51:11 +0100 (Do, 27 Dez 2007) | 1 line
Don't just exit with no error message if the document contains no content. Pretty irritating if it does so.
........
r608812 | acumiskey | 2008-01-04 13:14:33 +0100 (Fr, 04 Jan 2008) | 3 lines
The fonts variable would have always had an empty Configuration node (non-null value) even if a <fonts/> wasn't present
in the fop configuration.
........
r609567 | jeremias | 2008-01-07 11:52:09 +0100 (Mo, 07 Jan 2008) | 4 lines
Reenabled documentation for fox:destination.
Enabled intermediate format functionality for fox:destination.
Added a test case to check fox:destination.
Deprecated FOP's XMLizable in favor of the XML Graphics Commons variant (and extend that variant).
........
r609627 | jeremias | 2008-01-07 16:06:24 +0100 (Mo, 07 Jan 2008) | 5 lines
Bugzilla #44176:
Support for custom fonts in Java2DRenderer and derived renderers.
Submitted by: Patrick Jaromin <patrick.at.jgsullivan.dot.com>
Patch modified slightly by jeremias.
........
r610020 | acumiskey | 2008-01-08 16:27:02 +0100 (Di, 08 Jan 2008) | 2 lines
cleaned up
........
r610021 | acumiskey | 2008-01-08 16:28:56 +0100 (Di, 08 Jan 2008) | 2 lines
Appears to be unused/referenced and superceeded by PageGroup
........
r610022 | acumiskey | 2008-01-08 16:34:07 +0100 (Di, 08 Jan 2008) | 2 lines
cleaned up
........
r610023 | acumiskey | 2008-01-08 16:35:18 +0100 (Di, 08 Jan 2008) | 2 lines
fixed javadoc
........
r610337 | vhennebert | 2008-01-09 12:02:08 +0100 (Mi, 09 Jan 2008) | 2 lines
Fixed checkstyle issues: tabs and trailing spaces
........
r610355 | vhennebert | 2008-01-09 13:01:21 +0100 (Mi, 09 Jan 2008) | 2 lines
keep-together is an inherited property
........
r610420 | acumiskey | 2008-01-09 16:40:25 +0100 (Mi, 09 Jan 2008) | 2 lines
cleanup
........
r610704 | jeremias | 2008-01-10 08:38:47 +0100 (Do, 10 Jan 2008) | 1 line
Added basic support for PDF page labels.
........
r610739 | jeremias | 2008-01-10 11:13:21 +0100 (Do, 10 Jan 2008) | 1 line
PostScript output now generates the bounding box DSC comments for the whole document.
........
r610821 | vhennebert | 2008-01-10 16:53:20 +0100 (Do, 10 Jan 2008) | 4 lines
- renamed variables for clarity
- moved the computation of a cell's content length in PrimaryGridUnit
- better javadoc for getHeight method in EffRow
........
r610848 | vhennebert | 2008-01-10 18:41:52 +0100 (Do, 10 Jan 2008) | 2 lines
No need to check if the end of the cell is reached when creating the areas for a row
........
r610853 | vhennebert | 2008-01-10 18:54:16 +0100 (Do, 10 Jan 2008) | 2 lines
Simplified addAreasAndFlushRow
........
r610886 | vhennebert | 2008-01-10 20:23:56 +0100 (Do, 10 Jan 2008) | 2 lines
Removed endPart() method and moved its content into addAreasAndFlushRow()
........
r610891 | vhennebert | 2008-01-10 20:34:13 +0100 (Do, 10 Jan 2008) | 2 lines
Removed accumulatedBPD which is redundant with yoffset
........
r610893 | vhennebert | 2008-01-10 20:35:24 +0100 (Do, 10 Jan 2008) | 2 lines
The return value of addAreasAndFlushRow is never used, changed it to void
........
r610905 | vhennebert | 2008-01-10 20:57:29 +0100 (Do, 10 Jan 2008) | 2 lines
Renamed lastRow into currentRow and yoffset into currentRowOffset
........
r611114 | jeremias | 2008-01-11 10:04:28 +0100 (Fr, 11 Jan 2008) | 2 lines
Bugfix: Some string objects were not encrypted (for example in named destinations)
I had to refactor the PDF library a little bit but since it only affects the inner API it shouldn't be a problem that I removed some methods which caused trouble because a didn't think about encryption when I worked on the PDF library last year.
........
------------------------------------------------------------------------
r611133 | jeremias | 2008-01-11 11:45:01 +0100 (Fr, 11 Jan 2008) | 4 lines
Fixed merge problems.
Fixed a NPE when a mask is null in BitmapImage.java
Add support for properly encoding binary data as a hexadecimal string object (including encryption).
Adjust palette generation for indexed bitmaps to work correctly with encryption.
------------------------------------------------------------------------
r611138 | jeremias | 2008-01-11 11:59:27 +0100 (Fr, 11 Jan 2008) | 1 line
Removed empty package.
------------------------------------------------------------------------
................
r611285 | jeremias | 2008-01-11 20:03:36 +0000 (Fri, 11 Jan 2008) | 1 line
Removed stray reference to ImageFactory.
................
r611766 | jeremias | 2008-01-14 11:01:11 +0000 (Mon, 14 Jan 2008) | 1 line
java.net.URI doesn't eat non-escaped URIs so I added an escaping method to URISpecification that should cover most cases. Usually, it's just about a space in a filename.
................
r611767 | jeremias | 2008-01-14 11:02:34 +0000 (Mon, 14 Jan 2008) | 1 line
Restore default constructor for PDFArray.
................
r611768 | jeremias | 2008-01-14 11:02:54 +0000 (Mon, 14 Jan 2008) | 1 line
Clear parent if later on an object number is assigned to a PDFObject which means it is a top-level object.
................
r612560 | jeremias | 2008-01-16 20:14:56 +0000 (Wed, 16 Jan 2008) | 1 line
Fixed dead link.
................
r612785 | acumiskey | 2008-01-17 10:36:36 +0000 (Thu, 17 Jan 2008) | 1 line
added serial version id
................
r612815 | jeremias | 2008-01-17 13:37:04 +0000 (Thu, 17 Jan 2008) | 6 lines
Fixed logic error setting the transformation matrix for block-container viewports (applies to absolute and fixed block-containers only). The CTM now only rotates and shifts the content as necessary for reference-orientation and writing-mode. All the rest of the transformation is done by the renderer which allows to add additional transformations as made possible by fox:transform (see below).
Important: External renderer implementations need to adjust for the change and implement the new method concatenateTransformationMatrix(AffineTransform) if the renderer is derived from AbstractPathOrientedRenderer.
New extension attribute fox:transform on fo:block-container allows free-form transformation (rotation, scaling etc.) of absolute and fixed block-containers. Supported only for PDF, PS and Java2D-based renderers.
Added missing region background painting for PCL renderer.
................
r612816 | jeremias | 2008-01-17 13:43:33 +0000 (Thu, 17 Jan 2008) | 1 line
Slight performance improvement on multi-core CPUs using a cheap trick.
................
r612825 | jeremias | 2008-01-17 14:23:13 +0000 (Thu, 17 Jan 2008) | 2 lines
Fixed layout problem in two of the changes.
Categorized the individual changes a bit.
................
r613144 | jeremias | 2008-01-18 12:44:56 +0000 (Fri, 18 Jan 2008) | 1 line
Forgot to adjust the JAR name when updating to Batik 1.7
................
r613185 | jeremias | 2008-01-18 15:25:26 +0000 (Fri, 18 Jan 2008) | 1 line
Copy/Paste problem with TTF has long been fixed.
................
r613828 | jeremias | 2008-01-21 10:21:25 +0000 (Mon, 21 Jan 2008) | 1 line
Removed stray System.out
................
r613831 | jeremias | 2008-01-21 10:33:10 +0000 (Mon, 21 Jan 2008) | 1 line
A name object can be encoded as a stand-along PDF object with object number and all, so extend from PDFObject. Fixes a possible ClassCastException with the PDF-in-PDF extension.
................
r613835 | jeremias | 2008-01-21 10:40:38 +0000 (Mon, 21 Jan 2008) | 1 line
Correct inline writing when object has an object number.
................
r613896 | jeremias | 2008-01-21 14:13:29 +0000 (Mon, 21 Jan 2008) | 1 line
A note about the internal coordinate system when using fox:transform.
................
r614156 | jeremias | 2008-01-22 09:26:05 +0000 (Tue, 22 Jan 2008) | 2 lines
Complete overhaul of the "Graphics" page after the new image loading framework has been introduced.
Some updates on external links and about Java 1.4.
................
r614169 | vhennebert | 2008-01-22 10:48:43 +0000 (Tue, 22 Jan 2008) | 2 lines
Fixed minor typos
................
r614170 | vhennebert | 2008-01-22 10:50:24 +0000 (Tue, 22 Jan 2008) | 2 lines
Updated text to reflect the upgrading of the minimum Java requirement to 1.4
................
r614191 | jeremias | 2008-01-22 12:31:11 +0000 (Tue, 22 Jan 2008) | 1 line
A note on the difference between JAI Image I/O Tools, the codec package, and JAI, the image library.
................
r614201 | jeremias | 2008-01-22 14:02:27 +0000 (Tue, 22 Jan 2008) | 2 lines
Bugzilla #44160:
Fixed a possible IndexOutOfBoundsException that could happen with certain constellations when footnotes are used. Note: I haven't been able to come up with a scaled-down testcase for regression testing. Maybe someone more intimate with the footnote handling can.
................
r614202 | jeremias | 2008-01-22 14:13:22 +0000 (Tue, 22 Jan 2008) | 1 line
We need JAI Image I/O Tools now rather than Jimi or JAI.
................
r614566 | vhennebert | 2008-01-23 15:22:05 +0000 (Wed, 23 Jan 2008) | 3 lines
Added support for conditional borders (and paddings) in tables.
The proper borders are not selected yet between the header/footer and the body. There might still be a few glitches in some cases
................
r614845 | vhennebert | 2008-01-24 11:32:07 +0000 (Thu, 24 Jan 2008) | 2 lines
Removed the no longer needed maxColumnCount parameter
................
r614920 | vhennebert | 2008-01-24 16:40:46 +0000 (Thu, 24 Jan 2008) | 6 lines
Cleanup:
- renamed startRow/startCol into rowIndex/colIndex
- improved javadoc of PrimaryGridUnit.getRowIndex()
- moved colIndex from GridUnit into PrimaryGridUnit since it's only needed there
- simplified EmptyGridUnit constructor
................
r614924 | vhennebert | 2008-01-24 16:51:53 +0000 (Thu, 24 Jan 2008) | 2 lines
Removed no longer needed reference to TableColumn in GridUnit
................
r614964 | vhennebert | 2008-01-24 19:56:05 +0000 (Thu, 24 Jan 2008) | 2 lines
Replaced 'non-lead' with 'normal'
................
r614966 | vhennebert | 2008-01-24 19:59:20 +0000 (Thu, 24 Jan 2008) | 2 lines
Added license header
................
r614993 | vhennebert | 2008-01-24 21:10:22 +0000 (Thu, 24 Jan 2008) | 2 lines
Bugzilla #44289: Wrong border resolution when header/footer omitted at break
................
r615144 | jeremias | 2008-01-25 08:26:54 +0000 (Fri, 25 Jan 2008) | 1 line
Added support for DOMSource to Preloader SVG so a URI Resolver can be written that provides the SVG as a W3C SVG DOM.
................
r615164 | jeremias | 2008-01-25 09:59:29 +0000 (Fri, 25 Jan 2008) | 1 line
Fix exception when closing Source that doesn't have any streams.
................
r615197 | jeremias | 2008-01-25 12:14:52 +0000 (Fri, 25 Jan 2008) | 1 line
Improved error tolerance: an enum property value with leading or trailing spaces is still recognized. Example: content-width="scale-to-fit "
................
r615251 | vhennebert | 2008-01-25 15:52:53 +0000 (Fri, 25 Jan 2008) | 2 lines
Fixed a bug in computeContentLength when there are empty cells
................
r615598 | adelmelle | 2008-01-27 13:35:39 +0000 (Sun, 27 Jan 2008) | 4 lines
Bugzilla #44286:
Fixed a memory-leak in XMLWhiteSpaceHandler.
Submitted by: Stefan Ziel <stefan.ziel.at.claninfo.ch>
................
r615604 | vhennebert | 2008-01-27 14:09:12 +0000 (Sun, 27 Jan 2008) | 2 lines
Of course startIndex == endIndex means there is one element whose length must be computed... Changed >= into >
................
r615845 | jeremias | 2008-01-28 10:32:46 +0000 (Mon, 28 Jan 2008) | 1 line
Improve breaking for block-container and static-content so there are no more "breaking artifacts" (like additional border lines) in the overflowing part of the content anymore. This is done by removing all breaks from the result list prior to constructing the area tree. The presence of breaks simply indicates that there is an overflow.
................
r615906 | jeremias | 2008-01-28 15:04:39 +0000 (Mon, 28 Jan 2008) | 2 lines
Added support for the natural language indentifier ("Lang" in the document catalog) for PDF documents based on the language/country values on fo:page-sequence. This required a few changes in the AreaTreeModel and the Renderer interface because it didn't support passing through the PageSequence object, only its title. Now, we can put other values on the PageSequence and transport them to the renderers.
................
r615917 | jeremias | 2008-01-28 15:45:10 +0000 (Mon, 28 Jan 2008) | 1 line
A note on country/language.
................
r616080 | jeremias | 2008-01-28 22:05:39 +0000 (Mon, 28 Jan 2008) | 1 line
Bugfix for invalid numTables entry in subset TrueType fonts if there was no "fpgm" table (Example: FreeSerif).
................
r616191 | jeremias | 2008-01-29 07:30:08 +0000 (Tue, 29 Jan 2008) | 1 line
A more detailed comment on RTF output explaining that RTF has limitations besides the incomplete implementation on the FOP side.
................
r616260 | vhennebert | 2008-01-29 11:15:29 +0000 (Tue, 29 Jan 2008) | 2 lines
Added more tests to ensure no weird things occurs when keep-with-previous/next is set on table. Runs ok
................
r616334 | vhennebert | 2008-01-29 14:15:52 +0000 (Tue, 29 Jan 2008) | 2 lines
Renamed testcase for clarity
................
r616485 | vhennebert | 2008-01-29 19:12:58 +0000 (Tue, 29 Jan 2008) | 2 lines
Replaced testcases for forced break on table-row with more complete ones. Tests failing because of bug #44320 have been commented out and will need to be re-enabled once the bug is fixed
................
r616691 | jeremias | 2008-01-30 08:53:48 +0000 (Wed, 30 Jan 2008) | 1 line
"cvt ", "fpgm" and "prep" are all optional tables in TrueType. Some PDF viewers fail because FOP didn't handle those correctly.
................
r616694 | jeremias | 2008-01-30 09:05:30 +0000 (Wed, 30 Jan 2008) | 1 line
Removing the previous entry because the new one basically covers the other, too.
................
r616798 | jeremias | 2008-01-30 16:03:00 +0000 (Wed, 30 Jan 2008) | 1 line
Removed the Dijkstra stuff as it was moved to Commons.
................
r617126 | jeremias | 2008-01-31 13:44:46 +0000 (Thu, 31 Jan 2008) | 1 line
Update lib README based on recent findings.
................
r617473 | jeremias | 2008-02-01 11:11:02 +0000 (Fri, 01 Feb 2008) | 1 line
Implemented drawRenderedImage() which fixes painting of PNG images embedded inside SVG images.
................
r617512 | jeremias | 2008-02-01 14:58:30 +0000 (Fri, 01 Feb 2008) | 4 lines
AlphaRasterImage now knows how to deal with TYPE_INT Rasters.
Streamlined image handling in Graphics2D.
Support natively handling CCITT images in SVG images.
Add fallback to device RGB if sRGB isn't set up as the default color space in PDF.
................
r617531 | jeremias | 2008-02-01 16:02:33 +0000 (Fri, 01 Feb 2008) | 2 lines
Move sRGB installation into the PDF library. That way it can be used in PDFDocumentGraphics2D, too (via AbstractImageAdapter).
Ensures correct handling of sRGB images in PDFTranscoder.
................
r617550 | jeremias | 2008-02-01 16:31:24 +0000 (Fri, 01 Feb 2008) | 1 line
Add a note about color space overrides which currently aren't supported for natively handled images, yet.
................
r617708 | adelmelle | 2008-02-01 23:30:13 +0000 (Fri, 01 Feb 2008) | 5 lines
Bugzilla 44343:
Fixed a bug when using relative (smaller/larger) font-sizes in combination with percentages.
Percentages now resolved as per the spec (XSL-FO 1.1 7.9.4):
"A percentage value specifies an absolute font size relative to the parent element's font-size."
................
r617716 | adelmelle | 2008-02-02 00:06:29 +0000 (Sat, 02 Feb 2008) | 4 lines
Minor cleanup/improvement:
- FontSizePropertyMaker: remove redundant casts (FixedLength already casts the doubles internally)
- FixedLength: reduce visibility of 'fishy' convert() method (not used anywhere else)
................
r617765 | jeremias | 2008-02-02 06:45:39 +0000 (Sat, 02 Feb 2008) | 1 line
Fixed transcoder test after yesterday's changes.
................
r617812 | adelmelle | 2008-02-02 15:13:40 +0000 (Sat, 02 Feb 2008) | 6 lines
Further cleanup/refinement of FixedLength:
* improve consistency in use of the PropertyCache
remove public constructor -> replaced by getInstance() in a handful of classes
* added a sourceResolution parameter to getInstance() and the private
constructor to allow better handling of device-dependent units (px)
................
r617907 | adelmelle | 2008-02-02 22:11:12 +0000 (Sat, 02 Feb 2008) | 4 lines
Further improvement in FixedLength:
* added a special ZERO_FIXED_LENGTH instance
* store only non-zero values in the PropertyCache
................
r617909 | adelmelle | 2008-02-02 22:18:30 +0000 (Sat, 02 Feb 2008) | 2 lines
Slight correction for pixel-values: pass the ratio of pixels-per-point into FixedLength.getInstance()
................
r617976 | adelmelle | 2008-02-03 12:05:49 +0000 (Sun, 03 Feb 2008) | 5 lines
Added very basic parsing for the xml:lang shorthand.
No validation of the specified value, but the language and country
properties now do take the shorthand into account to determine their
value.
................
r617989 | adelmelle | 2008-02-03 14:11:40 +0000 (Sun, 03 Feb 2008) | 5 lines
Bugzilla 43705:
Fixed a bug when the rgb-icc() function was used before the fo:declarations,
or in documents without fo:declarations. Function now correctly (?) reverts
to the sRGB fallback in those cases.
................
r618239 | vhennebert | 2008-02-04 11:25:13 +0000 (Mon, 04 Feb 2008) | 2 lines
Fixed minor typo I stumbled upon while doing something completely unrelated
................
r618470 | adelmelle | 2008-02-04 22:26:53 +0000 (Mon, 04 Feb 2008) | 1 line
Added testcase for Bugzilla 44343
................
r618626 | jeremias | 2008-02-05 12:34:56 +0000 (Tue, 05 Feb 2008) | 1 line
Change PDFPage to use PDFDictionary in order to make it possible to better set MediaBox/TrimBox/BleedBox.
................
r618627 | jeremias | 2008-02-05 12:35:42 +0000 (Tue, 05 Feb 2008) | 1 line
FOX_TRANSFORM constant should be static.
................
r618992 | jeremias | 2008-02-06 14:07:03 +0000 (Wed, 06 Feb 2008) | 4 lines
Bugzilla #36391:
Fixed problem with positioning of content when reference-orientation="180" is used. CTM is now correct. It is updated after the height of the content is known. Instead of somehow inverting the element list, I've simply declared this case non-breakable, i.e. I generate one box.
Fixed a few other problems mostly occurring when rotating block-container content by 90 or 270 degrees plus a few remaining auto-height handling problems. This involved switching off some sometimes unwanted side-effects from auto-updating the BPD in some area classes.
................
r619417 | jeremias | 2008-02-07 14:02:44 +0000 (Thu, 07 Feb 2008) | 1 line
Added an option to disable the default sRGB profile in PDF output for those who don't care about color fidelity, but care about PDF file size. Note that this option is not possible if PDF/A, PDF/X or an output profile is used. Makes simple PDFs about 4KB smaller. Ha!
................
r619461 | jeremias | 2008-02-07 15:42:03 +0000 (Thu, 07 Feb 2008) | 2 lines
Bugfix for date formatting with negative time zones in the PDF's Info object.
Update of xmlgraphics-commons-1.3.jar because of a similar bug with formatting dates in XMP.
................
r619670 | adelmelle | 2008-02-07 22:32:27 +0000 (Thu, 07 Feb 2008) | 1 line
Tweak: early percentage resolution by the parser (if the base is known and absolute). Reduces the number of PercentLength instances in favor of cached FixedLengths.
................
r619674 | adelmelle | 2008-02-07 22:41:26 +0000 (Thu, 07 Feb 2008) | 3 lines
Tweak: modify PercentLength.toString() to return a value that facilitates debugging.
Moved the original code to a getString() implementation, which is now used by the fotree test suite.
................
r619790 | jeremias | 2008-02-08 07:27:06 +0000 (Fri, 08 Feb 2008) | 1 line
Added a clarification that this bug affected PDF/A compliance.
................
r619854 | vhennebert | 2008-02-08 12:11:04 +0000 (Fri, 08 Feb 2008) | 3 lines
Removed the 900 penalty mechanism which anyway almost always produced visually bad results. Now the first step for a row is computed so that each cell starting on it can contribute some content.
Used a similar mechanism to replace backtracking: the current row is now allowed to grow as long as there is not enough space on the current page to make the next row fit. The next row is "delayed", so this mechanism is called "row-delaying"
................
r619856 | vhennebert | 2008-02-08 12:14:01 +0000 (Fri, 08 Feb 2008) | 2 lines
Also display the column index in the toString method
................
r619870 | jeremias | 2008-02-08 13:23:47 +0000 (Fri, 08 Feb 2008) | 1 line
Added missing width for Euro glyph.
................
r619923 | vhennebert | 2008-02-08 15:59:21 +0000 (Fri, 08 Feb 2008) | 2 lines
Testcase for bug #43676, which is now fixed
................
r619979 | spepping | 2008-02-08 19:20:27 +0000 (Fri, 08 Feb 2008) | 5 lines
In addKnuthElementsForBorderPaddingXXX, if the returnlist is a
BlockKnuthSequence, the border and padding should be added to the
first or last paragraph inside it, but it is too late to do that
now. At least, avoid adding it to the bpd sequence.
................
r620272 | adelmelle | 2008-02-10 12:31:46 +0000 (Sun, 10 Feb 2008) | 5 lines
Some minor tweaks:
* added convenience shortcut to PropertyInfo to get to the user agent.
* replaced occurrences to use the shortcut in PropertyParser and RGBColorFunction.
* PropertyParser -> 0% of a length always yields FixedLength.ZERO_FIXED_LENGTH
................
r620276 | adelmelle | 2008-02-10 12:50:47 +0000 (Sun, 10 Feb 2008) | 3 lines
Revisit background-position shorthand implementation: always convert to percentages (more possibilities/precision).
................
r620277 | adelmelle | 2008-02-10 13:01:07 +0000 (Sun, 10 Feb 2008) | 2 lines
Tweak: wrap numeric values internally in Integers or Longs if possible, Doubles only if necessary.
................
r620278 | adelmelle | 2008-02-10 13:07:34 +0000 (Sun, 10 Feb 2008) | 2 lines
Missing file from r620272
................
r620283 | adelmelle | 2008-02-10 13:17:20 +0000 (Sun, 10 Feb 2008) | 5 lines
Correction/Rectification of changes made in r617989:
* adjustment in ColorUtil to cater for the change
* added check to the color_1.xml testcase, checking for bug 43705
................
r620285 | adelmelle | 2008-02-10 13:42:39 +0000 (Sun, 10 Feb 2008) | 3 lines
Bugzilla 41631: Percentage resolution for arguments to proportional-column-width()
................
r620558 | vhennebert | 2008-02-11 18:10:09 +0000 (Mon, 11 Feb 2008) | 2 lines
Added full support for breaks inside table-cell elements
................
r620559 | vhennebert | 2008-02-11 18:11:09 +0000 (Mon, 11 Feb 2008) | 2 lines
Fixed illegal character in the file
................
r620565 | vhennebert | 2008-02-11 18:18:13 +0000 (Mon, 11 Feb 2008) | 2 lines
Better javadoc for break class
................
r620567 | vhennebert | 2008-02-11 18:24:00 +0000 (Mon, 11 Feb 2008) | 2 lines
Disabled region-body_column-count_bug#37468 testcase because of bug 44393
................
r620570 | adelmelle | 2008-02-11 18:36:14 +0000 (Mon, 11 Feb 2008) | 1 line
Missing file from r620283
................
r620723 | jeremias | 2008-02-12 08:23:04 +0000 (Tue, 12 Feb 2008) | 2 lines
Bugzilla #44393:
Recognize the newly used EN_AUTO constant for break values. Other LMs generate a -1 value for this case.
................
r620750 | jeremias | 2008-02-12 10:45:50 +0000 (Tue, 12 Feb 2008) | 1 line
Simplification.
................
r620761 | vhennebert | 2008-02-12 11:12:25 +0000 (Tue, 12 Feb 2008) | 2 lines
Fixed wrong numbering of cells
................
r627318 | maxberger | 2008-02-13 09:12:25 +0000 (Wed, 13 Feb 2008) | 1 line
Added *.xml to svn:ignore
................
r627324 | maxberger | 2008-02-13 09:35:01 +0000 (Wed, 13 Feb 2008) | 1 line
Ensured all SVN properties are set equally
................
r627367 | maxberger | 2008-02-13 12:03:30 +0000 (Wed, 13 Feb 2008) | 1 line
Ensured all SVN properties are set equally
................
r627495 | jeremias | 2008-02-13 15:55:34 +0000 (Wed, 13 Feb 2008) | 1 line
Replace useless javadoc comment.
................
r627497 | jeremias | 2008-02-13 15:57:01 +0000 (Wed, 13 Feb 2008) | 1 line
Easy way to force the discarding of the user's font cache file (especially after the recent changes).
................
r627553 | vhennebert | 2008-02-13 18:11:06 +0000 (Wed, 13 Feb 2008) | 2 lines
Added support for breaks before and after table cells
................
r627576 | vhennebert | 2008-02-13 20:10:01 +0000 (Wed, 13 Feb 2008) | 2 lines
Moved to the FO tree stage the check for break-before/after on table-row while spanning in progress, and fixed bug #44321 as well
................
r627679 | jeremias | 2008-02-14 08:12:34 +0000 (Thu, 14 Feb 2008) | 10 lines
Added support for Type 1 fonts which don't use the AdobeStandardEncoding for PDF and PS output. Details:
Added an Type 1 AFM parser (only basic ltr script fonts are properly supported).
Font loading changed slightly to allow loading an AFM in addition to a PFM.
Added some mapping functionality to CodePointMapping. Now we also build custom CodePointMapping instances from AFM files and use it in SingleByteFonts.
Changed more PDF object classes to make use of the generic PDFDictionary and PDFArray base classes.
Type 1 Fonts with a special encoding now register their encoding in the Encoding value of the font dictionary so the mapping is correct. For PS this isn't necessary as the interpreter just uses the font's default encoding.
Refactored CMap building code to it can also be used outside the PDF context. A CMap can now also be built from a single byte encoding.
Update of XML Graphics Commons snapshot.
................
r627698 | acumiskey | 2008-02-14 10:12:48 +0000 (Thu, 14 Feb 2008) | 3 lines
When I first saw this it surprised me, it seems to have been here for quite some time.
The code block directly following this if/else condition was identical so I removed the copy/paste duplication and refactored it.
................
r627702 | jeremias | 2008-02-14 10:41:26 +0000 (Thu, 14 Feb 2008) | 2 lines
Fix problem with alternate Unicode code point overriding existing better ones in CodePointMapping (ex. a char code for NBSP was used in place of SPACE for non-standard encodings).
Made PFM completely optional if an AFM is available. Widths and Kerning are now also read from the AFM. Fallbacks for missing values are in place. If both AFM and PFM are available, both are used to get the best possible result for certain metrics.
................
r627712 | vhennebert | 2008-02-14 11:36:01 +0000 (Thu, 14 Feb 2008) | 2 lines
Simplified the detection of double as integer
................
r627719 | maxberger | 2008-02-14 11:57:05 +0000 (Thu, 14 Feb 2008) | 1 line
Created Constants for unit descriptions
................
r627721 | vhennebert | 2008-02-14 12:09:05 +0000 (Thu, 14 Feb 2008) | 2 lines
break-after set on the last child of a row-spanning cell must apply to the last row spanned by the cell
................
r628140 | vhennebert | 2008-02-15 18:33:12 +0000 (Fri, 15 Feb 2008) | 2 lines
rowStarted doesn't need to be set in the signalNewRow method. If it is, it will prevent the startTablePart event from being triggered on RowGroupBuilder, in addChildNode. This will lead to a NPE being thrown in CollapsingBorderResolver because it would be improperly set up.
................
r628280 | jeremias | 2008-02-16 12:28:48 +0000 (Sat, 16 Feb 2008) | 7 lines
Extracted most of the code in CodePointMapping (generated by XSLT) into a base class for easier maintenance and proper Javadocs.
Deprecated FOP's copy of Glyphs.java.
Took a different approach at handling mapping alternatives for single-byte fonts. The AFM now only lists the main character. Substitution is done through Glyphs.java later in CodePointMapping.
Fixed a problem in Type1FontLoader where the PFM overrides asc/desc/cap/x even though the AFM provides the values. It showed itself because the URW Symbol font has wrong values in the PFM.
Added a note to myself in Type1FontLoader to implement the "Flags" value. The whole thing still seems to work without that part.
Added a glyph name list to the CodePointMapping so we can work with the original list from the AFM. Otherwise, various mapping operations to and from resulted in unwanted mappings (because the mappings are not necessarily 1:1) and in the end the PDF received an incorrect Encoding map. Now there's no such problem anymore.
................
r628652 | jeremias | 2008-02-18 09:00:08 +0000 (Mon, 18 Feb 2008) | 1 line
No stack traces with missing images.
................
r628668 | jeremias | 2008-02-18 09:41:03 +0000 (Mon, 18 Feb 2008) | 2 lines
Extract original exception in BasePDFTestCase.java. They are normally embedded in a TransformerException and sometimes additionally in a SAXException (depending on the JAXP implementation).
Restore validation for Base14 font check when PDF/A is active. Got lost when I refactored to generic structures in the PDF library.
................
r628775 | jeremias | 2008-02-18 15:02:39 +0000 (Mon, 18 Feb 2008) | 2 lines
fop-rgb-icc() function did not make the round-trip which caused an error in the color_1.xml test case (intermediate format tests). Added a unit test to test the parsing and round-trip.
Documented the cmyk() function.
................
r628804 | jeremias | 2008-02-18 16:45:18 +0000 (Mon, 18 Feb 2008) | 1 line
Reducing noise. Better messages.
................
r628816 | jeremias | 2008-02-18 17:06:39 +0000 (Mon, 18 Feb 2008) | 1 line
It currently doesn't work properly without a layout-master-set.
................
r628826 | jeremias | 2008-02-18 17:24:23 +0000 (Mon, 18 Feb 2008) | 1 line
Made the necessary changes to remove the long-standing deprecations in the apps package as discussed.
................
r628829 | jeremias | 2008-02-18 17:30:15 +0000 (Mon, 18 Feb 2008) | 1 line
Makes sense to mention the removal of deprecated methods.
................
r629048 | vhennebert | 2008-02-19 09:36:23 +0000 (Tue, 19 Feb 2008) | 2 lines
Style only: removed spurious ^M characters at the end of lines
................
r629093 | jeremias | 2008-02-19 13:08:39 +0000 (Tue, 19 Feb 2008) | 9 lines
Bugzilla #44451:
The patch fixes two problems:
- If distinct fonts declare the same font family name, the resulting font mapping is currently arbitrary; now, a name-similarity heuristic is used to prioritize the font mappings.
- "Medium" and "demi" fonts are now recognized as "bold", solving several real-world problems (although this solution may be an oversimplification).
Submitted by: Justus Piater <justus-bulk.at.piater.name>
Patch modified by jeremias:
- Style fixes (tab chars)
- Refined font weight identification: medium -> 500, semi/demi -> 600
................
r629103 | jeremias | 2008-02-19 14:16:08 +0000 (Tue, 19 Feb 2008) | 1 line
Bugfix: a specified font-weight of 100 could result into a resolved font-weight of 400 even when a font with weight 200 is registered.
................
r629129 | jeremias | 2008-02-19 15:43:31 +0000 (Tue, 19 Feb 2008) | 1 line
Fixed NPE when no AFM is available and the PFM didn't provide a xHeight.
................
r629131 | jeremias | 2008-02-19 15:47:48 +0000 (Tue, 19 Feb 2008) | 2 lines
Added support for reading the OS/2 table's usWeightClass value which supports the same font weight values as we use in XSL-FO.
However, in my tests these values proved to be unreliable (like ExtraBlack fonts returning 400). I just hooked the whole thing in so this work isn't lost if anyone has an idea to make it work. The FontInfoFinder will continue to only use guessed font weights for now.
................
r629169 | vhennebert | 2008-02-19 17:32:18 +0000 (Tue, 19 Feb 2008) | 2 lines
Fixed a bug leading to the content of row-spanning cells being duplicated at page breaks, when it's small enough to fit on the previous row
................
r629769 | maxberger | 2008-02-21 12:52:33 +0000 (Thu, 21 Feb 2008) | 1 line
Moved me to commiters :)
................
r629902 | maxberger | 2008-02-21 18:22:22 +0000 (Thu, 21 Feb 2008) | 1 line
Turned on XInclude processing for the main source given on the command line.
................
r630215 | maxberger | 2008-02-22 14:17:20 +0000 (Fri, 22 Feb 2008) | 2 lines
Fixed backward compatiblity with 1.4
................
r630772 | jeremias | 2008-02-25 09:17:43 +0000 (Mon, 25 Feb 2008) | 1 line
Bugfix: When scale-up/down-to-fit was used, the image scaling rule was not always respected.
................
r630814 | vhennebert | 2008-02-25 11:30:43 +0000 (Mon, 25 Feb 2008) | 5 lines
- added full support for keep-with-previous on table-row and in table-cell
- added more testcases for keeps in tables
- assign the right table-row element to grid units that are not on the first row spanned
- slightly re-worked the RowGroupBuilder interface to make it more SAX-like
................
r631178 | jeremias | 2008-02-26 11:07:20 +0000 (Tue, 26 Feb 2008) | 3 lines
Reverted revision 603590 which broke the AFP renderer. The other changes after revision 603590 should be preserved as well as possible, including the switch to the new image library.
Adjustments for change in behaviour of the block viewport CTM.
Bugfix: SVG painting is now always done on a color canvas (like for PCL) because Batik cannot handle gradients on a grayscale canvas.
................
r631226 | jeremias | 2008-02-26 14:30:50 +0000 (Tue, 26 Feb 2008) | 1 line
GOCA support temporarily removed.
................
r631276 | vhennebert | 2008-02-26 16:23:15 +0000 (Tue, 26 Feb 2008) | 2 lines
Moved the getBody method into PrimaryGridUnit, since it's only needed there and that allows to simplify EmptyGridUnit
................
r631575 | jeremias | 2008-02-27 13:00:54 +0000 (Wed, 27 Feb 2008) | 2 lines
Bugzilla #44497:
AFP Renderer: Bugfix for broken reference orientation on absolutely positioned block-containers.
................
r631609 | vhennebert | 2008-02-27 15:09:06 +0000 (Wed, 27 Feb 2008) | 2 lines
bpBeforeNormal and bpAfterNormal already include border-separation, no need to re-substract it from the box height
................
r631984 | jeremias | 2008-02-28 14:30:46 +0000 (Thu, 28 Feb 2008) | 2 lines
Slight improvement for thin lines in Java2D/AWT output.
Submitted by: Gordon Cooke <cookeg.at.btinternet.com>
................
r632121 | adelmelle | 2008-02-28 21:29:04 +0000 (Thu, 28 Feb 2008) | 6 lines
Minor tweaks/updates:
- change toString() to getLocalizedMessage() for exceptions passed to warning()
- removed deprecated method isLocatorDisabled()
- removed superfluous try-catch block
- some javadoc changes
................
r632122 | adelmelle | 2008-02-28 21:33:11 +0000 (Thu, 28 Feb 2008) | 2 lines
Minor tweak: switch from toString() to getLocalizedMessage() for Exceptions passed into warning()
................
r632321 | jeremias | 2008-02-29 14:03:01 +0000 (Fri, 29 Feb 2008) | 1 line
Bugfix: Disabled setting widths from AFM since we're using WinAnsiEncoding internally but the AFM delivers the character widths using the font's native encoding which causes problems with some characters.
................
r632558 | clay | 2008-03-01 07:10:03 +0000 (Sat, 01 Mar 2008) | 1 line
Preparing for FOP 0.95 release.
................
r632716 | clay | 2008-03-02 06:42:02 +0000 (Sun, 02 Mar 2008) | 1 line
Adding Quick Start Guide.
................
r632784 | jeremias | 2008-03-02 16:53:24 +0000 (Sun, 02 Mar 2008) | 1 line
Further preparations for the 0.95 release. This was tested with the latest Forrest Trunk (which uses FOP 0.94 for the PDFs).
................
r632938 | clay | 2008-03-03 04:44:28 +0000 (Mon, 03 Mar 2008) | 2 lines
Updated the Apache FOP Quick Start to include a 'Hello World' document and make it more geared toward newbies (thanks Jeremias!).
................
r632972 | jeremias | 2008-03-03 07:51:14 +0000 (Mon, 03 Mar 2008) | 1 line
Tried to make font configuration easier to understand by splitting the basics from the advanced stuff. Otherwise, people will believe for the next 100 years that generating XML font metrics file is still always necessary.
................
r633389 | jeremias | 2008-03-04 08:37:05 +0000 (Tue, 04 Mar 2008) | 1 line
Removed 0.93 and 0.94, added 0.95. There's no noticeable difference between 0.94 and 0.95 so I removed a column to regain some space.
................
r633390 | jeremias | 2008-03-04 08:38:36 +0000 (Tue, 04 Mar 2008) | 1 line
Switched to Commons 1.3 being released.
................
r633391 | jeremias | 2008-03-04 08:39:12 +0000 (Tue, 04 Mar 2008) | 1 line
Added ApacheCon US 2008.
................
r633396 | jeremias | 2008-03-04 09:06:03 +0000 (Tue, 04 Mar 2008) | 1 line
Various updates.
................
r633397 | jeremias | 2008-03-04 09:15:50 +0000 (Tue, 04 Mar 2008) | 1 line
Using Forrest Trunk from now on (in order to use FOP 0.94 for PDFs). We'll switch to a stable release as soon as a release with a new FOP version is available.
................
r633437 | jeremias | 2008-03-04 11:50:34 +0000 (Tue, 04 Mar 2008) | 3 lines
Renamed to 0.95beta.
Made changes and release notes work again by switching to the projectInfo plug-in rather than relying on our local copy of the stylesheets. There's a little bug (missing images) in the release notes for which I submitted a patch (https://issues.apache.org/jira/browse/FOR-1076) to Forrest.
Brought status.xml more in line with the official status DTD.
................
r633460 | jeremias | 2008-03-04 12:59:57 +0000 (Tue, 04 Mar 2008) | 1 line
Copyright year
................
r633470 | jeremias | 2008-03-04 13:25:12 +0000 (Tue, 04 Mar 2008) | 1 line
Noted some of the major change areas in this release.
................
r633473 | jeremias | 2008-03-04 13:40:11 +0000 (Tue, 04 Mar 2008) | 2 lines
Ha! Almost forgot the most important change: Java 1.4!
Plus a note on image libraries.
................
r633525 | jeremias | 2008-03-04 16:13:17 +0000 (Tue, 04 Mar 2008) | 1 line
Bugfix: Without the system ID (base URI), the XSLT processor cannot resolve document(<uri>, .) function calls correctly.
................
r633557 | jeremias | 2008-03-04 17:30:40 +0000 (Tue, 04 Mar 2008) | 1 line
Bugfix: If there's shrink available in an auto-height situation, the difference is now set to 0 in order to avoid unwanted effects. IOW, never shrink in an auto-height situation.
................
r633559 | jeremias | 2008-03-04 17:35:52 +0000 (Tue, 04 Mar 2008) | 2 lines
Update FOP poster for OpenExpo 2008 in Bern.
This fixes various warnings, updates the history and simplifies configuration (if you're on Windows, it will work out of the box because all fonts are available).
................
r633561 | jeremias | 2008-03-04 17:39:08 +0000 (Tue, 04 Mar 2008) | 1 line
Update README.
................
r633961 | vhennebert | 2008-03-05 18:22:06 +0000 (Wed, 05 Mar 2008) | 5 lines
- Fixed the rendering of the area of a table corresponding to border-separation, which must be filled with the background of the table, and not the rows.
- Improved conformance: even if a table-cell spans several rows its background must correspond to the first row spanned.
- Added support for background on fo:table-column and fo:table-header/footer/body
TODO more testcases needed, especially tables with collapsing border model and tables broken over pages
................
r634187 | jeremias | 2008-03-06 08:21:06 +0000 (Thu, 06 Mar 2008) | 1 line
Added some notes on getting the same output for PDF/PS and Java2D-based renderers.
................
r635508 | jeremias | 2008-03-10 10:06:37 +0000 (Mon, 10 Mar 2008) | 4 lines
Fixed NPE in BlockContainerLayoutManager when used as a child of an inline-level FO. Split IP and BP stack limits in LayoutContext (there's now a certain amount of redundancy with "refIPD" in LayoutContext which I didn't resolve).
Areas are now generated for block-level FOs when used as children of inline-level FOs.
ClassCastException in ListLayoutManager.mustKeepTogether() fixed (occured if used as child of an inline-level FO).
................
r635686 | vhennebert | 2008-03-10 20:52:43 +0000 (Mon, 10 Mar 2008) | 2 lines
Bugfix: forced break ignored when the minimum height of a table-row isn't reached
................
r635701 | jeremias | 2008-03-10 21:28:08 +0000 (Mon, 10 Mar 2008) | 1 line
Need to clean up after myself.
................
r635741 | jeremias | 2008-03-10 22:39:38 +0000 (Mon, 10 Mar 2008) | 1 line
Bugfix for row/body/col background painting when padding is used in the table-cells.
................
r635884 | vhennebert | 2008-03-11 11:02:27 +0000 (Tue, 11 Mar 2008) | 2 lines
Fixed a copy-paste error (getPaddingStart instead of getPaddingEnd)
................
r635961 | vhennebert | 2008-03-11 15:05:27 +0000 (Tue, 11 Mar 2008) | 2 lines
Forgot to add the testcase for forced break vs explicit row height in revision 635686
................
r635967 | vhennebert | 2008-03-11 15:13:51 +0000 (Tue, 11 Mar 2008) | 2 lines
Updated the disabled-testcases.xml file: re-enabled testcases which could easily be updated, removed the other ones which anyway were superseded by more complete ones
................
r636276 | vhennebert | 2008-03-12 10:51:09 +0000 (Wed, 12 Mar 2008) | 2 lines
Since compliance.ihtml is now the source file and it would cost too much to revert to an xml version, tidied the file a bit. No content change.
................
r636293 | vhennebert | 2008-03-12 12:14:51 +0000 (Wed, 12 Mar 2008) | 2 lines
Updated the compliance page. Re-added the 0.94 column since there are some noteworthy changes between the 0.94 and 0.95 versions
................
r636295 | vhennebert | 2008-03-12 12:19:15 +0000 (Wed, 12 Mar 2008) | 3 lines
Update of the documentation before the release.
Added notes about improved checks and conformance in tables.
................
r636405 | vhennebert | 2008-03-12 16:25:52 +0000 (Wed, 12 Mar 2008) | 2 lines
Initialized merge tracking via "svnmerge" from the 0.95 branch
................
r636409 | vhennebert | 2008-03-12 16:36:29 +0000 (Wed, 12 Mar 2008) | 8 lines
Blocked revisions 636406 via svnmerge
........
r636406 | vhennebert | 2008-03-12 16:28:00 +0000 (Wed, 12 Mar 2008) | 2 lines
Set the version to 0.95beta
........
................
r636471 | vhennebert | 2008-03-12 19:24:05 +0000 (Wed, 12 Mar 2008) | 2 lines
Removed no longer used borderAndPaddingBPD field
................
r637057 | jeremias | 2008-03-14 11:15:24 +0000 (Fri, 14 Mar 2008) | 2 lines
Bugzilla #44412:
Bugfix: When there was a forced break after a block with (conditional) borders the border-after wasn't painted.
................
r637076 | vhennebert | 2008-03-14 12:22:44 +0000 (Fri, 14 Mar 2008) | 2 lines
Reverting changes of rev. 637057. I applied the changes to the 0.95 branch instead so that they make their way into the 0.95 release. I will merge them back to the Trunk via svnmerge
................
r638396 | vhennebert | 2008-03-18 15:01:43 +0000 (Tue, 18 Mar 2008) | 53 lines
Merged revisions 636400-636405,636407-638388 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_95
........
r636403 | vhennebert | 2008-03-12 16:24:48 +0000 (Wed, 12 Mar 2008) | 2 lines
Updated copyright years
........
r637075 | vhennebert | 2008-03-14 12:19:45 +0000 (Fri, 14 Mar 2008) | 4 lines
Bugzilla #44412:
Bugfix: When there was a forced break after a block with (conditional) borders the border-after wasn't painted.
Changes made by Jeremias
........
r637119 | jeremias | 2008-03-14 14:41:03 +0000 (Fri, 14 Mar 2008) | 2 lines
Bugzilla #44412:
Bugfix: The before border of a block is no longer swallowed if its first child issues a break-before.
........
r637791 | jeremias | 2008-03-17 08:59:51 +0000 (Mon, 17 Mar 2008) | 3 lines
Removed old image adapters.
Removed support for Java 1.3 building as it didn't work anymore anyway.
Added a check to require Java 1.4 for building.
........
r637857 | jeremias | 2008-03-17 12:24:33 +0000 (Mon, 17 Mar 2008) | 3 lines
Partially reverted revision 637791:
Restored JAI as a required dependency for distribution builds (used for error diffusion dithering in the PCL Renderer). It is optional otherwise.
Updated the licensing info and release notes to make the changes clear.
........
r637993 | vhennebert | 2008-03-17 17:48:44 +0000 (Mon, 17 Mar 2008) | 3 lines
Bugzilla #44621: when the after border of a cell, in the trailing case, is bigger than in the normal case, the generated sequence of Knuth elements was wrong, leading to content being swallowed
This is a partial fix only: the content is no longer swallowed, but the penalty is wrong (shorter than it should be). This will lead to the table overflowing the region-body without warning.
........
r638048 | vhennebert | 2008-03-17 20:00:36 +0000 (Mon, 17 Mar 2008) | 2 lines
Changed the documentation to reflect the move to Java 1.4 as a minimum requirement
........
r638308 | vhennebert | 2008-03-18 10:26:32 +0000 (Tue, 18 Mar 2008) | 2 lines
Simplified the getNextKnuthElements method a little bit
........
r638316 | vhennebert | 2008-03-18 11:06:59 +0000 (Tue, 18 Mar 2008) | 2 lines
Removed the 'jdk1.4' suffix appended to the binary artifacts. There's no point in making the distinction anymore since there is only one binary now
........
r638317 | vhennebert | 2008-03-18 11:08:29 +0000 (Tue, 18 Mar 2008) | 2 lines
Updated the probable date of the release
........
................
r640089 | clay | 2008-03-22 21:54:27 +0000 (Sat, 22 Mar 2008) | 1 line
updates to Forrest web site (expand menu structure).
................
r640242 | adelmelle | 2008-03-23 19:36:36 +0000 (Sun, 23 Mar 2008) | 11 lines
Cleanup and minor refactoring:
* consolidate addId() in AbstractLayoutManager
* replace getPSLM().addIdToPage(getXXX().getId()) in various LMs
Smaller changes/cleanup in the affected LMs include:
* removal of some redundant casts
* simplified conditionals
* avoid duplicating the reference to the FObj as much as possible:
the reference is already stored in AbstractLM, yet every subclass seems to
add another reference...
................
r641742 | jeremias | 2008-03-27 08:49:41 +0000 (Thu, 27 Mar 2008) | 6 lines
Added support for addressing all glyphs available in a Type 1 font, not just the ones in the font's primary encoding.
Typeface: getEncoding() changed to getEncodingName() to make clearer what is held here.
Some cleanup in the font classes to put the various things in more appropriate places.
Created a common base class for all Base 14 fonts (makes the hierarchy clearer).
Made PDFTextUtil more universally useful and made use of it in PDFRenderer, too.
Made PDFStream.add(String) more efficient. The encoding converter is not called for each invocation anymore as the whole thing get buffered by a BufferedWriter (as suggested by the javadoc of OutputStreamWriter).
................
r641764 | maxberger | 2008-03-27 10:02:25 +0000 (Thu, 27 Mar 2008) | 1 line
Added my key
................
r641827 | jeremias | 2008-03-27 14:29:44 +0000 (Thu, 27 Mar 2008) | 2 lines
When a JPEG image is embedded, an optionally embedded color profile is filtered out as it's already embedded separately in the PDF file.
Worked around a problem (PDF renderer) with JPEG image containing RGB color profiles which are not sRGB. The images drifted into yellow. The color profile is simply disabled in this case. Please let us know if you know what the problem could be.
................
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@643433 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org')
139 files changed, 2920 insertions, 7003 deletions
diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index e6ac70d67..ce77d9040 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -46,7 +46,6 @@ import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.ElementMappingRegistry; import org.apache.fop.fonts.FontCache; import org.apache.fop.hyphenation.HyphenationTreeResolver; -import org.apache.fop.image.ImageFactory; import org.apache.fop.layoutmgr.LayoutManagerMaker; import org.apache.fop.render.RendererFactory; import org.apache.fop.render.XMLHandlerRegistry; @@ -82,9 +81,6 @@ public class FopFactory implements ImageContext { private ColorSpaceCache colorSpaceCache = null; - /** Image factory for creating fop image objects */ - private ImageFactory imageFactory; - /** Image manager for loading and caching image objects */ private ImageManager imageManager; @@ -155,7 +151,6 @@ public class FopFactory implements ImageContext { this.elementMappingRegistry = new ElementMappingRegistry(this); this.foURIResolver = new FOURIResolver(validateUserConfigStrictly()); this.colorSpaceCache = new ColorSpaceCache(foURIResolver); - this.imageFactory = new ImageFactory(); this.imageManager = new ImageManager(this); this.rendererFactory = new RendererFactory(); this.xmlHandlers = new XMLHandlerRegistry(); @@ -290,11 +285,6 @@ public class FopFactory implements ImageContext { return this.contentHandlerFactoryRegistry; } - /** @return the image factory */ - public ImageFactory getImageFactory() { - return this.imageFactory; - } - /** * Returns the image manager. * @return the image manager diff --git a/src/java/org/apache/fop/cli/InputHandler.java b/src/java/org/apache/fop/cli/InputHandler.java index 68af6ae51..4c38fa5c7 100644 --- a/src/java/org/apache/fop/cli/InputHandler.java +++ b/src/java/org/apache/fop/cli/InputHandler.java @@ -39,8 +39,13 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; @@ -150,6 +155,7 @@ public class InputHandler implements ErrorListener, Renderable { try { InputSource is = new InputSource(new FileInputStream( this.sourcefile)); + is.setSystemId(this.sourcefile.toURI().toASCIIString()); SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setFeature("http://xml.org/sax/features/namespaces", true); spf.setFeature("http://apache.org/xml/features/xinclude", true); @@ -221,7 +227,7 @@ public class InputHandler implements ErrorListener, Renderable { * {@inheritDoc} */ public void warning(TransformerException exc) { - log.warn(exc.toString()); + log.warn(exc.getLocalizedMessage()); } /** diff --git a/src/java/org/apache/fop/fo/ElementMapping.java b/src/java/org/apache/fop/fo/ElementMapping.java index 0f436ae28..495983750 100644 --- a/src/java/org/apache/fop/fo/ElementMapping.java +++ b/src/java/org/apache/fop/fo/ElementMapping.java @@ -19,7 +19,7 @@ package org.apache.fop.fo; -import java.util.HashMap; +import java.util.Map; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -37,7 +37,7 @@ public abstract class ElementMapping { public static final String DEFAULT = "<default>"; /** The HashMap table of formatting objects defined by the ElementMapping */ - protected HashMap foObjs = null; + protected Map foObjs = null; /** The namespace for the ElementMapping */ protected String namespaceURI = null; @@ -47,7 +47,7 @@ public abstract class ElementMapping { * * @return Table of Maker objects for this ElementMapping */ - public HashMap getTable() { + public Map getTable() { if (foObjs == null) { initialize(); } diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 9910f1ce7..539648f5a 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -412,6 +412,7 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.setDefault("auto"); + l.setPercentBase(LengthBase.CONTAINING_BLOCK_HEIGHT); addPropertyMaker("top", l); // right @@ -419,6 +420,7 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.setDefault("auto"); + l.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH); addPropertyMaker("right", l); // bottom @@ -426,6 +428,7 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.setDefault("auto"); + l.setPercentBase(LengthBase.CONTAINING_BLOCK_HEIGHT); addPropertyMaker("bottom", l); // left @@ -433,6 +436,7 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.setDefault("auto"); + l.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH); addPropertyMaker("left", l); } @@ -1161,6 +1165,7 @@ public final class FOPropertyMapping implements Constants { m = new LengthProperty.Maker(PR_START_INDENT); m.setInherited(true); m.setDefault("0pt"); + m.setPercentBase(LengthBase.CONTAINING_REFAREA_WIDTH); IndentPropertyMaker sCorr = new IndentPropertyMaker(m); sCorr.setCorresponding(PR_MARGIN_LEFT, PR_MARGIN_RIGHT, PR_MARGIN_TOP); sCorr.setUseParent(false); @@ -1177,6 +1182,7 @@ public final class FOPropertyMapping implements Constants { m = new LengthProperty.Maker(PR_END_INDENT); m.setInherited(true); m.setDefault("0pt"); + m.setPercentBase(LengthBase.CONTAINING_REFAREA_WIDTH); IndentPropertyMaker eCorr = new IndentPropertyMaker(m); eCorr.setCorresponding(PR_MARGIN_RIGHT, PR_MARGIN_LEFT, PR_MARGIN_BOTTOM); eCorr.setUseParent(false); diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index 63fc5cb5b..d02a058fe 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -38,7 +38,6 @@ import org.apache.fop.area.AreaTreeHandler; import org.apache.fop.fo.ElementMapping.Maker; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fo.pagination.Root; -import org.apache.fop.image.ImageFactory; import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener; import org.apache.fop.util.ContentHandlerFactory.ObjectSource; @@ -57,9 +56,7 @@ public class FOTreeBuilder extends DefaultHandler { /** The registry for ElementMapping instances */ protected ElementMappingRegistry elementMappingRegistry; - /** - * The root of the formatting object tree - */ + /** The root of the formatting object tree */ protected Root rootFObj = null; /** Main DefaultHandler that handles the FO namespace. */ @@ -68,10 +65,7 @@ public class FOTreeBuilder extends DefaultHandler { /** Current delegate ContentHandler to receive the SAX events */ protected ContentHandler delegate; - /** - * The class that handles formatting and rendering to a stream - * (mark-fop@inomial.com) - */ + /** The object that handles formatting and rendering to a stream */ private FOEventHandler foEventHandler; /** The SAX locator object managing the line and column counters */ @@ -86,14 +80,18 @@ public class FOTreeBuilder extends DefaultHandler { private int depth; /** - * FOTreeBuilder constructor + * <code>FOTreeBuilder</code> constructor + * * @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). - * @param foUserAgent in effect for this process - * @param stream OutputStream to direct results - * @throws FOPException if the FOTreeBuilder cannot be properly created + * @param foUserAgent the {@link FOUserAgent} in effect for this process + * @param stream the <code>OutputStream</code> to direct the results to + * @throws FOPException if the <code>FOTreeBuilder</code> cannot be properly created */ - public FOTreeBuilder(String outputFormat, FOUserAgent foUserAgent, - OutputStream stream) throws FOPException { + public FOTreeBuilder( + String outputFormat, + FOUserAgent foUserAgent, + OutputStream stream) + throws FOPException { this.userAgent = foUserAgent; this.elementMappingRegistry = userAgent.getFactory().getElementMappingRegistry(); @@ -108,40 +106,25 @@ public class FOTreeBuilder extends DefaultHandler { }); } - /** - * This method enables to reduce memory consumption of the FO tree slightly. When it returns - * true no Locator is passed to the FO tree nodes which would copy the information into - * a SAX LocatorImpl instance. - * @return true if no context information should be stored on each node in the FO tree. - * @deprecated Use FOUserAgent.isLocatorEnabled() instead. - */ - protected boolean isLocatorDisabled() { - return !userAgent.isLocatorEnabled(); - } - - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void setDocumentLocator(Locator locator) { this.locator = locator; } - /** @return a Locator instance if it is available and not disabled */ + /** + * @return a {@link Locator} instance if it is available and not disabled + */ protected Locator getEffectiveLocator() { return (userAgent.isLocatorEnabled() ? this.locator : null); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void characters(char[] data, int start, int length) throws SAXException { delegate.characters(data, start, length); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startDocument() throws SAXException { if (used) { throw new IllegalStateException("FOTreeBuilder (and the Fop class) cannot be reused." @@ -159,9 +142,7 @@ public class FOTreeBuilder extends DefaultHandler { this.delegate = this.mainFOHandler; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endDocument() throws SAXException { this.delegate.endDocument(); if (this.rootFObj == null && empty) { @@ -173,24 +154,16 @@ public class FOTreeBuilder extends DefaultHandler { log.debug("Parsing of document complete"); } foEventHandler.endDocument(); - - //Notify the image factory that this user agent has expired. - ImageFactory imageFactory = userAgent.getFactory().getImageFactory(); - imageFactory.removeContext(this.userAgent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startElement(String namespaceURI, String localName, String rawName, Attributes attlist) throws SAXException { this.depth++; delegate.startElement(namespaceURI, localName, rawName, attlist); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endElement(String uri, String localName, String rawName) throws SAXException { this.delegate.endElement(uri, localName, rawName); @@ -206,7 +179,8 @@ public class FOTreeBuilder extends DefaultHandler { } /** - * Finds the Maker used to create node objects of a particular type + * Finds the {@link Maker} used to create {@link FONode} objects of a particular type + * * @param namespaceURI URI for the namespace of the element * @param localName name of the Element * @return the ElementMapping.Maker that can create an FO object for this element @@ -218,7 +192,7 @@ public class FOTreeBuilder extends DefaultHandler { /** {@inheritDoc} */ public void warning(SAXParseException e) { - log.warn(e.toString()); + log.warn(e.getLocalizedMessage()); } /** {@inheritDoc} */ @@ -233,7 +207,8 @@ public class FOTreeBuilder extends DefaultHandler { } /** - * Provides access to the underlying FOEventHandler object. + * Provides access to the underlying {@link FOEventHandler} object. + * * @return the FOEventHandler object */ public FOEventHandler getEventHandler() { @@ -244,6 +219,7 @@ public class FOTreeBuilder extends DefaultHandler { * Returns the results of the rendering process. Information includes * the total number of pages generated and the number of pages per * page-sequence. + * * @return the results of the rendering process. */ public FormattingResults getResults() { @@ -257,23 +233,17 @@ public class FOTreeBuilder extends DefaultHandler { } /** - * Main DefaultHandler implementation which builds the FO tree. + * Main <code>DefaultHandler</code> implementation which builds the FO tree. */ private class MainFOHandler extends DefaultHandler { - /** - * Current formatting object being handled - */ + /** Current formatting object being handled */ protected FONode currentFObj = null; - /** - * Current propertyList for the node being handled. - */ + /** Current propertyList for the node being handled */ protected PropertyList currentPropertyList; - /** - * Current marker nesting-depth - */ + /** Current marker nesting-depth */ private int nestedMarkerDepth = 0; /** {@inheritDoc} */ @@ -298,11 +268,7 @@ public class FOTreeBuilder extends DefaultHandler { } else { // check that incoming node is valid for currentFObj if (namespaceURI.equals(FOElementMapping.URI) || namespaceURI.equals(ExtensionElementMapping.URI)) { - try { - currentFObj.validateChildNode(locator, namespaceURI, localName); - } catch (ValidationException e) { - throw e; - } + currentFObj.validateChildNode(locator, namespaceURI, localName); } } @@ -391,12 +357,11 @@ public class FOTreeBuilder extends DefaultHandler { if (currentFObj.getParent() == null) { log.debug("endElement for top-level " + currentFObj.getName()); } + currentFObj = currentFObj.getParent(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void characters(char[] data, int start, int length) throws FOPException { if (currentFObj != null) { @@ -405,6 +370,7 @@ public class FOTreeBuilder extends DefaultHandler { } } + /** {@inheritDoc} */ public void endDocument() throws SAXException { currentFObj = null; } diff --git a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java index 201029ff1..2c910d3f8 100644 --- a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java @@ -25,8 +25,6 @@ package org.apache.fop.fo.flow.table; */ public class EmptyGridUnit extends GridUnit { - private TableBody body; - /** * @param table the containing table * @param row the table-row element this grid unit belongs to (if any) @@ -57,11 +55,6 @@ public class EmptyGridUnit extends GridUnit { } /** {@inheritDoc} */ - public TableBody getBody() { - return this.body; - } - - /** {@inheritDoc} */ public boolean isLastGridUnitColSpan() { return true; } diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java index 23d1cc001..b9394ff31 100644 --- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java @@ -19,7 +19,6 @@ package org.apache.fop.fo.flow.table; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.layoutmgr.table.CollapsingBorderModel; @@ -165,14 +164,6 @@ public class GridUnit { this.row = row; } - public TableBody getBody() { - FONode node = getCell(); - while (node != null && !(node instanceof TableBody)) { - node = node.getParent(); - } - return (TableBody) node; - } - /** * Returns the before-start grid unit of the cell containing this grid unit. * diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 1a47a7dcf..8af896fa2 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -23,6 +23,7 @@ import java.util.LinkedList; import java.util.List; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FONode; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.table.TableCellLayoutManager; @@ -71,6 +72,19 @@ public class PrimaryGridUnit extends GridUnit { .getValue() / 2; // TODO } + /** + * Returns the fo:table-header/footer/body element containing this cell. + * + * @return the enclosing table part + */ + public TableBody getTableBody() { + FONode node = cell.getParent(); + if (node instanceof TableRow) { + node = node.getParent(); + } + return (TableBody) node; + } + public TableCellLayoutManager getCellLM() { assert cellLM != null; return cellLM; @@ -224,18 +238,6 @@ public class PrimaryGridUnit extends GridUnit { return contentLength; } - /** @return true if cell/row has an explicit BPD/height */ - public boolean hasBPD() { - if (!getCell().getBlockProgressionDimension().getOptimum(null).isAuto()) { - return true; - } - if (getRow() != null - && !getRow().getBlockProgressionDimension().getOptimum(null).isAuto()) { - return true; - } - return false; - } - /** * Returns the grid units belonging to the same span as this one. * diff --git a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java index 26747c24d..f47ddbe0c 100644 --- a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java +++ b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java @@ -21,6 +21,7 @@ package org.apache.fop.fo.properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.Constants; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; @@ -142,7 +143,7 @@ public final class CommonHyphenation { FontMetrics metrics = font.getFontMetrics(); if (metrics instanceof Typeface) { Typeface typeface = (Typeface)metrics; - if ("SymbolEncoding".equals(typeface.getEncoding())) { + if ("SymbolEncoding".equals(typeface.getEncodingName())) { //SymbolEncoding doesn't have HYPHEN_MINUS, so replace by MINUS_SIGN } else { //only warn if the encoding is not SymbolEncoding @@ -154,7 +155,7 @@ public final class CommonHyphenation { FontMetrics metrics = font.getFontMetrics(); if (metrics instanceof Typeface) { Typeface typeface = (Typeface)metrics; - if ("ZapfDingbatsEncoding".equals(typeface.getEncoding())) { + if ("ZapfDingbatsEncoding".equals(typeface.getEncodingName())) { //ZapfDingbatsEncoding doesn't have HYPHEN_MINUS, so replace by ' ' } else { //only warn if the encoding is not ZapfDingbatsEncoding diff --git a/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java b/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java index 69ca372e5..5a5cf95c5 100644 --- a/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java +++ b/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * -/* $Id:$ */ +/* $Id$ */ package org.apache.fop.fo.properties; diff --git a/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java b/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java index 91d13da85..3a2ac5022 100644 --- a/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java +++ b/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java @@ -29,7 +29,7 @@ import org.apache.fop.util.CharUtilities; /** * Abstract base class for code point mapping classes (1-byte character encodings). */ -public class AbstractCodePointMapping { +public class AbstractCodePointMapping implements SingleByteEncoding { private String name; private char[] latin1Map; @@ -114,19 +114,12 @@ public class AbstractCodePointMapping { } } - /** - * Returns the encoding's name. - * @return the name of the encoding - */ + /** {@inheritDoc} */ public String getName() { return this.name; } - /** - * Maps a Unicode character to a code point in the encoding. - * @param c the Unicode character to map - * @return the coid point in the encoding or 0 (=.notdef) if not found - */ + /** {@inheritDoc} */ public final char mapChar(char c) { if (c < 256) { char latin1 = latin1Map[c]; @@ -172,8 +165,8 @@ public class AbstractCodePointMapping { } } - putFallbackCharacter(c, '\0'); - return 0; + putFallbackCharacter(c, NOT_FOUND_CODE_POINT); + return NOT_FOUND_CODE_POINT; } private void putFallbackCharacter(char c, char mapTo) { @@ -227,11 +220,7 @@ public class AbstractCodePointMapping { return -1; } - /** - * Returns the array of character names for this encoding. - * @return the array of character names - * (unmapped code points are represented by a ".notdef" value) - */ + /** {@inheritDoc} */ public String[] getCharNameMap() { if (this.charNameMap != null) { String[] copy = new String[this.charNameMap.length]; diff --git a/src/java/org/apache/fop/image/EmfImage.java b/src/java/org/apache/fop/fonts/Base14Font.java index 73bbad232..26c11e72b 100644 --- a/src/java/org/apache/fop/image/EmfImage.java +++ b/src/java/org/apache/fop/fonts/Base14Font.java @@ -16,36 +16,12 @@ */ /* $Id$ */ - -package org.apache.fop.image; + +package org.apache.fop.fonts; /** - * Enhanced metafile image. - * This supports loading a EMF image. - * - * @see AbstractFopImage - * @see FopImage + * Base class for all Base 14 fonts. */ -public class EmfImage extends AbstractFopImage { - - /** - * Create a bitmap image with the image data. - * - * @param imgInfo the image information - */ - public EmfImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } +public abstract class Base14Font extends Typeface { - /** - * Load the original EMF data. - * This loads the original EMF data and reads the color space, - * and icc profile if any. - * - * @return true if loaded false for any error - */ - protected boolean loadOriginalData() { - return loadDefaultOriginalData(); - } } - diff --git a/src/java/org/apache/fop/fonts/CIDFont.java b/src/java/org/apache/fop/fonts/CIDFont.java index c554d2165..7216c8f15 100644 --- a/src/java/org/apache/fop/fonts/CIDFont.java +++ b/src/java/org/apache/fop/fonts/CIDFont.java @@ -20,31 +20,14 @@ package org.apache.fop.fonts; //Java -import java.util.Map; /** * Abstract base class for CID fonts. */ public abstract class CIDFont extends CustomFont { - /** - * usedGlyphs contains orginal, new glyph index - */ - public Map usedGlyphs = new java.util.HashMap(); - - /** - * usedGlyphsIndex contains new glyph, original index - */ - public Map usedGlyphsIndex = new java.util.HashMap(); - public int usedGlyphsCount = 0; - - /** - * usedCharsIndex contains new glyph, original char - */ - public Map usedCharsIndex = new java.util.HashMap(); - - //private PDFWArray warray = new PDFWArray(); - public int width[] = null; + /** Contains the character widths for all characters in the font */ + protected int[] width = null; // ---- Required ---- /** @@ -73,6 +56,11 @@ public abstract class CIDFont extends CustomFont { */ public abstract int getSupplement(); + /** + * Returns the subset information for this font. + * @return the subset information + */ + public abstract CIDSubset getCIDSubset(); // ---- Optional ---- /** @@ -88,9 +76,4 @@ public abstract class CIDFont extends CustomFont { return true; } - /** - * Returns a char array containing all Unicode characters that have been accessed. - * @return a char array with all used Unicode characters - */ - public abstract char[] getCharsUsed(); -}
\ No newline at end of file +} diff --git a/src/java/org/apache/fop/fonts/CIDSubset.java b/src/java/org/apache/fop/fonts/CIDSubset.java new file mode 100644 index 000000000..6bcfc0b71 --- /dev/null +++ b/src/java/org/apache/fop/fonts/CIDSubset.java @@ -0,0 +1,177 @@ +/* + * 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.fonts; + +import java.util.BitSet; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; + +import org.apache.fop.util.CharUtilities; + +//Naming: +//glyph index: original index of the glyph in the non-subset font (!= unicode index) +//character selector: index into a set of glyphs. For subset CID fonts, this starts at 0. For +// non-subset fonts, this is the same as the glyph index. +//Unicode index: The Unicode codepoint of a character. +//Glyph name: the Adobe glyph name (as found in Glyphs.java) + +/** + * Keeps track of the glyphs used in a document. This information is later used to build + * a subset of a font. + */ +public class CIDSubset { + + /** + * usedGlyphs contains orginal, new glyph index (glyph index -> char selector) + */ + private Map/*<Integer, Integer>*/ usedGlyphs = new java.util.HashMap(); + + /** + * usedGlyphsIndex contains new glyph, original index (char selector -> glyph index) + */ + private Map/*<Integer, Integer>*/ usedGlyphsIndex = new java.util.HashMap(); + private int usedGlyphsCount = 0; + + /** + * usedCharsIndex contains new glyph, original char (char selector -> Unicode) + */ + private Map/*<Integer, Character>*/ usedCharsIndex = new java.util.HashMap(); + + public CIDSubset() { + } + + /** + * Adds the initial 3 glyphs which are the same for all CID subsets. + */ + public void setupFirstThreeGlyphs() { + // Make sure that the 3 first glyphs are included + usedGlyphs.put(new Integer(0), new Integer(0)); + usedGlyphsIndex.put(new Integer(0), new Integer(0)); + usedGlyphsCount++; + usedGlyphs.put(new Integer(1), new Integer(1)); + usedGlyphsIndex.put(new Integer(1), new Integer(1)); + usedGlyphsCount++; + usedGlyphs.put(new Integer(2), new Integer(2)); + usedGlyphsIndex.put(new Integer(2), new Integer(2)); + usedGlyphsCount++; + } + + /** + * Returns the original index of the glyph inside the (non-subset) font's glyph list. This + * index can be used to access the character width information, for example. + * @param subsetIndex the subset index (character selector) to access the glyph + * @return the original index (or -1 if no glyph index is available for the subset index) + */ + public int getGlyphIndexForSubsetIndex(int subsetIndex) { + Integer glyphIndex = (Integer)usedGlyphsIndex.get(new Integer(subsetIndex)); + if (glyphIndex != null) { + return glyphIndex.intValue(); + } else { + return -1; + } + } + + /** + * Returns the Unicode value for a subset index (character selector). If there's no such + * Unicode value, the "NOT A CHARACTER" (0xFFFF) is returned. + * @param subsetIndex the subset index (character selector) + * @return the Unicode value or "NOT A CHARACTER" (0xFFFF) + */ + public char getUnicodeForSubsetIndex(int subsetIndex) { + Character mapValue = (Character)usedCharsIndex.get(new Integer(subsetIndex)); + if (mapValue != null) { + return mapValue.charValue(); + } else { + return CharUtilities.NOT_A_CHARACTER; + } + } + + /** + * Maps a character to a character selector for a font subset. If the character isn't in the + * subset, yet, it is added and a new character selector returned. Otherwise, the already + * allocated character selector is returned from the existing map/subset. + * @param glyphIndex the glyph index of the character + * @param unicode the Unicode index of the character + * @return the subset index + */ + public int mapSubsetChar(int glyphIndex, char unicode) { + // Reencode to a new subset font or get the reencoded value + // IOW, accumulate the accessed characters and build a character map for them + Integer subsetCharSelector = (Integer)usedGlyphs.get(new Integer(glyphIndex)); + if (subsetCharSelector == null) { + int selector = usedGlyphsCount; + usedGlyphs.put(new Integer(glyphIndex), + new Integer(selector)); + usedGlyphsIndex.put(new Integer(selector), + new Integer(glyphIndex)); + usedCharsIndex.put(new Integer(selector), + new Character(unicode)); + usedGlyphsCount++; + return selector; + } else { + return subsetCharSelector.intValue(); + } + } + + /** + * Returns an unmodifiable Map of the font subset. It maps from glyph index to + * character selector (i.e. the subset index in this case). + * @return Map Map<Integer, Integer> of the font subset + */ + public Map/*<Integer, Integer>*/ getSubsetGlyphs() { + return Collections.unmodifiableMap(this.usedGlyphs); + } + + /** + * Returns a char array containing all Unicode characters that are in the subset. + * @return a char array with all used Unicode characters + */ + public char[] getSubsetChars() { + char[] charArray = new char[usedGlyphsCount]; + for (int i = 0; i < usedGlyphsCount; i++) { + charArray[i] = getUnicodeForSubsetIndex(i); + } + return charArray; + } + + /** + * Returns the number of glyphs in the subset. + * @return the number of glyphs in the subset + */ + public int getSubsetSize() { + return this.usedGlyphsCount; + } + + /** + * Returns a BitSet with bits set for each available glyph index. + * @return a BitSet indicating available glyph indices + */ + public BitSet getGlyphIndexBitSet() { + BitSet bitset = new BitSet(); + Iterator iter = usedGlyphs.keySet().iterator(); + while (iter.hasNext()) { + Integer cid = (Integer)iter.next(); + bitset.set(cid.intValue()); + } + return bitset; + } + +} diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java index e123513c2..ff71434c6 100644 --- a/src/java/org/apache/fop/fonts/Font.java +++ b/src/java/org/apache/fop/fonts/Font.java @@ -199,7 +199,7 @@ public class Font { // Use default CodePointMapping char d = CodePointMapping.getMapping("WinAnsiEncoding").mapChar(c); - if (d != 0) { + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { c = d; } else { log.warn("Glyph " + (int) c + " not available in font " + fontName); diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index e6ed7e881..8997069d4 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -64,11 +64,10 @@ public class LazyFont extends Typeface implements FontDescriptor { this.resolver = resolver; } - /** - * String representation of LazyFont - */ + /** {@inheritDoc} */ public String toString() { - return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath + ", kerning=" + useKerning ); + return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath + + ", kerning=" + useKerning ); } private void load(boolean fail) { @@ -80,8 +79,9 @@ public class LazyFont extends Typeface implements FontDescriptor { if (resolver != null) { Source source = resolver.resolve(metricsFileName); if (source == null) { - String err = "Cannot load font: failed to create Source from metrics file " - + metricsFileName; + String err + = "Cannot load font: failed to create Source from metrics file " + + metricsFileName; if (fail) { throw new RuntimeException(err); } else { @@ -112,8 +112,8 @@ public class LazyFont extends Typeface implements FontDescriptor { src.setSystemId(source.getSystemId()); reader = new FontReader(src); } else { - reader - = new FontReader(new InputSource(new URL(metricsFileName).openStream())); + reader = new FontReader(new InputSource( + new URL(metricsFileName).openStream())); } reader.setKerningEnabled(useKerning); reader.setFontEmbedPath(fontEmbedPath); @@ -153,12 +153,10 @@ public class LazyFont extends Typeface implements FontDescriptor { } // ---- Font ---- - /** - * {@inheritDoc} - */ - public String getEncoding() { + /** {@inheritDoc} */ + public String getEncodingName() { load(true); - return realFont.getEncoding(); + return realFont.getEncodingName(); } /** diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index e40c40985..5849379bd 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/src/java/org/apache/fop/fonts/MultiByteFont.java @@ -39,6 +39,9 @@ public class MultiByteFont extends CIDFont { private String namePrefix = null; // Quasi unique prefix + private CIDSubset subset = new CIDSubset(); + + /** A map from Unicode indices to glyph indices */ private BFEntry[] bfentries = null; /** @@ -46,15 +49,7 @@ public class MultiByteFont extends CIDFont { */ public MultiByteFont() { // Make sure that the 3 first glyphs are included - usedGlyphs.put(new Integer(0), new Integer(0)); - usedGlyphsIndex.put(new Integer(0), new Integer(0)); - usedGlyphsCount++; - usedGlyphs.put(new Integer(1), new Integer(1)); - usedGlyphsIndex.put(new Integer(1), new Integer(1)); - usedGlyphsCount++; - usedGlyphs.put(new Integer(2), new Integer(2)); - usedGlyphsIndex.put(new Integer(2), new Integer(2)); - usedGlyphsCount++; + subset.setupFirstThreeGlyphs(); // Create a quasiunique prefix for fontname synchronized (this.getClass()) { @@ -77,37 +72,27 @@ public class MultiByteFont extends CIDFont { setFontType(FontType.TYPE0); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getDefaultWidth() { return defaultWidth; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getRegistry() { return "Adobe"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getOrdering() { return "UCS"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getSupplement() { return 0; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public CIDFontType getCIDType() { return cidType; } @@ -133,68 +118,47 @@ public class MultiByteFont extends CIDFont { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean isEmbeddable() { return !(getEmbedFileName() == null && getEmbedResourceName() == null); } - /** - * {@inheritDoc} - */ - public String getEncoding() { + /** {@inheritDoc} */ + public CIDSubset getCIDSubset() { + return this.subset; + } + + /** {@inheritDoc} */ + public String getEncodingName() { return encoding; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getWidth(int i, int size) { if (isEmbeddable()) { - Integer idx = (Integer)usedGlyphsIndex.get(new Integer(i)); - return size * width[idx.intValue()]; + int glyphIndex = subset.getGlyphIndexForSubsetIndex(i); + return size * width[glyphIndex]; } else { return size * width[i]; } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int[] getWidths() { int[] arr = new int[width.length]; System.arraycopy(width, 0, arr, 0, width.length - 1); - /* - for (int i = 0; i < arr.length; i++) - arr[i] *= size; - */ return arr; } /** - * Remaps a codepoint based. - * @param i codepoint to remap - * @return new codepoint + * Returns the glyph index for a Unicode character. The method returns 0 if there's no + * such glyph in the character map. + * @param c the Unicode character index + * @return the glyph index (or 0 if the glyph is not available) */ -/* unused - public Integer reMap(Integer i) { - if (isEmbeddable()) { - Integer ret = (Integer)usedGlyphsIndex.get(i); - if (ret == null) { - ret = i; - } - return ret; - } else { - return i; - } - - } -*/ - private int findGlyphIndex(char c) { int idx = (int)c; - int retIdx = 0; + int retIdx = 0; //.notdef for (int i = 0; (i < bfentries.length) && retIdx == 0; i++) { if (bfentries[i].getUnicodeStart() <= idx @@ -208,48 +172,30 @@ public class MultiByteFont extends CIDFont { return retIdx; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public char mapChar(char c) { notifyMapOperation(); - int retIdx = findGlyphIndex(c); + int glyphIndex = findGlyphIndex(c); if (isEmbeddable()) { - // Reencode to a new subset font or get - // the reencoded value - Integer newIdx = (Integer)usedGlyphs.get(new Integer(retIdx)); - if (newIdx == null) { - usedGlyphs.put(new Integer(retIdx), - new Integer(usedGlyphsCount)); - usedGlyphsIndex.put(new Integer(usedGlyphsCount), - new Integer(retIdx)); - usedCharsIndex.put(new Integer(usedGlyphsCount), - new Integer((int) c)); - retIdx = usedGlyphsCount; - usedGlyphsCount++; - } else { - retIdx = newIdx.intValue(); - } + glyphIndex = subset.mapSubsetChar(glyphIndex, c); } - return (char)retIdx; + return (char)glyphIndex; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean hasChar(char c) { return (findGlyphIndex(c) > 0); } - /** - * Sets the bfentries. - * @param bfentries The bfentries to set + * Sets the array of BFEntry instances which constitutes the Unicode to glyph index map for + * a font. ("BF" means "base font") + * @param entries the Unicode to glyph index map */ - public void setBFEntries(BFEntry[] bfentries) { - this.bfentries = bfentries; + public void setBFEntries(BFEntry[] entries) { + this.bfentries = entries; } /** @@ -277,17 +223,6 @@ public class MultiByteFont extends CIDFont { } /** - * Adds a new CID width entry to the font. - * @param cidWidthIndex index - * @param wds array of widths - */ - /* - public void addCIDWidthEntry(int cidWidthIndex, int[] wds) { - this.warray.addEntry(cidWidthIndex, wds); - }*/ - - - /** * Sets the width array. * @param wds array of widths. */ @@ -300,30 +235,15 @@ public class MultiByteFont extends CIDFont { * @return Map Map of used Glyphs */ public Map getUsedGlyphs() { - return usedGlyphs; + return subset.getSubsetGlyphs(); } - /** The invalid Unicode character, suitable as a return value in methods - * that need to return an invalid character. */ - public static final char INVALID_UNICODE_CHAR = 0xFFFF; - /** {@inheritDoc} */ public char[] getCharsUsed() { if (!isEmbeddable()) { return null; } - char[] charArray = new char[usedGlyphsCount]; - for (int i = 0; i < usedGlyphsCount; i++) { - Integer mapValue = (Integer)usedCharsIndex.get(new Integer(i)); - if (mapValue != null) { - char arrayItem = (char) mapValue.intValue(); - charArray[i] = arrayItem; - } - else { - charArray[i] = INVALID_UNICODE_CHAR; - } - } - return charArray; + return subset.getSubsetChars(); } } diff --git a/src/java/org/apache/fop/fonts/NamedCharacter.java b/src/java/org/apache/fop/fonts/NamedCharacter.java new file mode 100644 index 000000000..2c8007ba1 --- /dev/null +++ b/src/java/org/apache/fop/fonts/NamedCharacter.java @@ -0,0 +1,142 @@ +/* + * 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.fonts; + +import org.apache.xmlgraphics.fonts.Glyphs; + +import org.apache.fop.util.CharUtilities; + +/** + * Represents an named character with character name (from the Adobe glyph list) and a Unicode + * sequence that this character represents. + */ +public class NamedCharacter { + + private String charName; + private String unicodeSequence; + + /** + * Main constructor. + * @param charName the character name + * @param unicodeSequence the Unicode sequence associated with this character + */ + public NamedCharacter(String charName, String unicodeSequence) { + if (charName == null) { + throw new NullPointerException("charName must not be null"); + } + this.charName = charName; + if (unicodeSequence != null) { + this.unicodeSequence = unicodeSequence; + } else { + this.unicodeSequence = Glyphs.getUnicodeSequenceForGlyphName(charName); + } + } + + /** + * Simple constructor. + * @param charName the character name + */ + public NamedCharacter(String charName) { + this(charName, null); + } + + /** {@inheritDoc} */ + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((charName == null) ? 0 : charName.hashCode()); + return result; + } + + /** {@inheritDoc} */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final NamedCharacter other = (NamedCharacter)obj; + return charName.equals(other.charName); + } + + /** + * Returns the character name (as defined by the Adobe glyph list). + * @return the character name + */ + public String getName() { + return this.charName; + } + + /** + * Returns the Unicode sequence associated with this character. + * @return the Unicode sequence (or null if no Unicode sequence is associated) + */ + public String getUnicodeSequence() { + return this.unicodeSequence; + } + + /** + * Indicates whether a single Unicode value is associated with this character. + * @return true if exactly one Unicode value is associated with this character, false otherwise + */ + public boolean hasSingleUnicodeValue() { + return (this.unicodeSequence != null && this.unicodeSequence.length() == 1); + } + + /** + * Returns the single Unicode value associated with this named character. Check + * {@link #hasSingleUnicodeValue()} before you call this method because an + * IllegalStateException is thrown is a Unicode sequence with more than one character is + * associated with this character. + * @return the single Unicode value (or FFFF ("NOT A CHARACTER") if no Unicode value is + * available) + * @throws IllegalStateException if a Unicode sequence with more than one value is associated + * with the named character + */ + public char getSingleUnicodeValue() throws IllegalStateException { + if (this.unicodeSequence == null) { + return CharUtilities.NOT_A_CHARACTER; + } + if (this.unicodeSequence.length() > 1) { + throw new IllegalStateException("getSingleUnicodeValue() may not be called for a" + + " named character that has more than one Unicode value (a sequence)" + + " associated with the named character!"); + } + return this.unicodeSequence.charAt(0); + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(this.unicodeSequence); + sb.append(" ("); + if (this.unicodeSequence != null) { + for (int i = 0, c = this.unicodeSequence.length(); i < c; i++) { + sb.append("0x").append(Integer.toHexString(this.unicodeSequence.charAt(0))); + } + sb.append(", "); + } + sb.append(getName()).append(')'); + return sb.toString(); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java b/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java new file mode 100644 index 000000000..a5ba1a33b --- /dev/null +++ b/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java @@ -0,0 +1,145 @@ +/* + * 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.fonts; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.xmlgraphics.fonts.Glyphs; + +/** + * A simple implementation of the OneByteEncoding mostly used for encodings that are constructed + * on-the-fly. + */ +public class SimpleSingleByteEncoding implements SingleByteEncoding { + + private String name; + private List mapping = new java.util.ArrayList(); + //List<NamedCharacter> + private Map charMap = new java.util.HashMap(); + //Map<Character(Unicode), Character(code point)> + + /** + * Main constructor. + * @param name the encoding's name + */ + public SimpleSingleByteEncoding(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + public String getName() { + return this.name; + } + + /** {@inheritDoc} */ + public char mapChar(char c) { + Character nc = (Character)charMap.get(new Character(c)); + if (nc != null) { + return nc.charValue(); + } + return NOT_FOUND_CODE_POINT; + } + + /** {@inheritDoc} */ + public String[] getCharNameMap() { + String[] map = new String[getSize()]; + Arrays.fill(map, Glyphs.NOTDEF); + for (int i = getFirstChar(); i <= getLastChar(); i++) { + NamedCharacter ch = (NamedCharacter)this.mapping.get(i - 1); + map[i] = ch.getName(); + } + return map; + } + + /** + * Returns the index of the first defined character. + * @return the index of the first defined character (always 1 for this class) + */ + public int getFirstChar() { + return 1; + } + + /** + * Returns the index of the last defined character. + * @return the index of the last defined character + */ + public int getLastChar() { + return this.mapping.size(); + } + + /** + * Returns the number of characters defined by this encoding. + * @return the number of characters + */ + public int getSize() { + return this.mapping.size() + 1; + } + + /** + * Indicates whether the encoding is full (with 256 code points). + * @return true if the encoding is full + */ + public boolean isFull() { + return (getSize() == 256); + } + + /** + * Adds a new character to the encoding. + * @param ch the named character + * @return the code point assigned to the character + */ + public char addCharacter(NamedCharacter ch) { + if (!ch.hasSingleUnicodeValue()) { + throw new IllegalArgumentException("Only NamedCharacters with a single Unicode value" + + " are currently supported!"); + } + if (isFull()) { + throw new IllegalStateException("Encoding is full!"); + } + char newSlot = (char)(getLastChar() + 1); + this.mapping.add(ch); + this.charMap.put(new Character(ch.getSingleUnicodeValue()), new Character(newSlot)); + return newSlot; + } + + /** + * Returns the named character at a given code point in the encoding. + * @param codePoint the code point of the character + * @return the NamedCharacter (or null if no character is at this position) + */ + public NamedCharacter getCharacterForIndex(int codePoint) { + if (codePoint < 0 || codePoint > 255) { + throw new IllegalArgumentException("codePoint must be between 0 and 255"); + } + if (codePoint <= getLastChar()) { + return (NamedCharacter)this.mapping.get(codePoint - 1); + } else { + return null; + } + } + + /** {@inheritDoc} */ + public String toString() { + return getName() + " (" + getSize() + " chars)"; + } + +} diff --git a/src/java/org/apache/fop/image/RegisterableImageProvider.java b/src/java/org/apache/fop/fonts/SingleByteEncoding.java index fd79ebd91..ac7241e24 100644 --- a/src/java/org/apache/fop/image/RegisterableImageProvider.java +++ b/src/java/org/apache/fop/fonts/SingleByteEncoding.java @@ -16,34 +16,35 @@ */ /* $Id$ */ - -package org.apache.fop.image; + +package org.apache.fop.fonts; /** - * This interface is used to dynamically register FopImage implementations. - * <p> - * NOTE: Please don't rely on this interface too much. It is a temporary measure - * until the whole image package can be redesigned. The redesign will likely - * provide a different mechanism to dynamically register new implementations. + * The interface defines a 1-byte character encoding (with 256 characters). */ -public interface RegisterableImageProvider { +public interface SingleByteEncoding { + + /** Code point that is used if no code point for a specific character has been found. */ + char NOT_FOUND_CODE_POINT = '\0'; /** - * Returns the MIME type the implementation supports. - * @return the MIME type - */ - String getSupportedMimeType(); - - /** - * Returns the name of the implementation. - * @return the name + * Returns the encoding's name. + * @return the name of the encoding */ String getName(); - + /** - * Returns the fully qualified class name for the implementing class. - * @return the class name + * Maps a Unicode character to a code point in the encoding. + * @param c the Unicode character to map + * @return the code point in the encoding or 0 (=.notdef) if not found */ - String getClassName(); + char mapChar(char c); + /** + * Returns the array of character names for this encoding. + * @return the array of character names + * (unmapped code points are represented by a ".notdef" value) + */ + String[] getCharNameMap(); + } diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index 814d05a2c..ac12b7615 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -19,6 +19,8 @@ package org.apache.fop.fonts; +import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; @@ -31,14 +33,21 @@ import org.apache.xmlgraphics.fonts.Glyphs; */ public class SingleByteFont extends CustomFont { + /** Code point that is used if no code point for a specific character has been found. */ + public static final char NOT_FOUND = '#'; + /** logger */ private static Log log = LogFactory.getLog(SingleByteFont.class); - private CodePointMapping mapping; + private SingleByteEncoding mapping; private int[] width = null; private Set warnedChars; + + private Map unencodedCharacters; + //Map<Character, UnencodedCharacter> + private List additionalEncodings; /** * Main constructor. @@ -54,7 +63,7 @@ public class SingleByteFont extends CustomFont { } /** {@inheritDoc} */ - public String getEncoding() { + public String getEncodingName() { return this.mapping.getName(); } @@ -62,18 +71,28 @@ public class SingleByteFont extends CustomFont { * Returns the code point mapping (encoding) of this font. * @return the code point mapping */ - public CodePointMapping getCodePointMapping() { + public SingleByteEncoding getEncoding() { return this.mapping; } /** {@inheritDoc} */ public int getWidth(int i, int size) { - int idx = i - getFirstChar(); - if (idx >= 0 && idx < width.length) { - return size * width[i - getFirstChar()]; - } else { - return 0; + if (i < 256) { + int idx = i - getFirstChar(); + if (idx >= 0 && idx < width.length) { + return size * width[i - getFirstChar()]; + } + } else if (this.additionalEncodings != null) { + int encodingIndex = (i / 256) - 1; + SimpleSingleByteEncoding encoding = getAdditionalEncoding(encodingIndex); + int codePoint = i % 256; + NamedCharacter nc = encoding.getCharacterForIndex(codePoint); + UnencodedCharacter uc + = (UnencodedCharacter)this.unencodedCharacters.get( + new Character(nc.getSingleUnicodeValue())); + return size * uc.getWidth(); } + return 0; } /** {@inheritDoc} */ @@ -87,30 +106,80 @@ public class SingleByteFont extends CustomFont { public char mapChar(char c) { notifyMapOperation(); char d = mapping.mapChar(c); - if (d != 0) { + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { return d; - } else { - Character ch = new Character(c); - if (warnedChars == null) { - warnedChars = new java.util.HashSet(); + } + + //Check unencoded characters which are available in the font by character name + d = mapUnencodedChar(c); + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { + return d; + } + + //Give up, character is not available + Character ch = new Character(c); + if (warnedChars == null) { + warnedChars = new java.util.HashSet(); + } + if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { + warnedChars.add(ch); + if (warnedChars.size() == 8) { + log.warn("Many requested glyphs are not available in font " + getFontName()); + } else { + log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) + + ", " + Glyphs.charToGlyphName(c) + + ") not available in font " + getFontName()); } - if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { - warnedChars.add(ch); - if (warnedChars.size() == 8) { - log.warn("Many requested glyphs are not available in font " + getFontName()); - } else { - log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) - + ", " + Glyphs.charToGlyphName(c) - + ") not available in font " + getFontName()); + } + return NOT_FOUND; + } + + private char mapUnencodedChar(char ch) { + if (this.unencodedCharacters != null) { + UnencodedCharacter unencoded + = (UnencodedCharacter)this.unencodedCharacters.get(new Character(ch)); + if (unencoded != null) { + if (this.additionalEncodings == null) { + this.additionalEncodings = new java.util.ArrayList(); + } + SimpleSingleByteEncoding encoding = null; + char mappedStart = 0; + int additionalsCount = this.additionalEncodings.size(); + for (int i = 0; i < additionalsCount; i++) { + mappedStart += 256; + encoding = getAdditionalEncoding(i); + char alt = encoding.mapChar(ch); + if (alt != 0) { + return (char)(mappedStart + alt); + } + } + if (encoding != null && encoding.isFull()) { + encoding = null; } + if (encoding == null) { + encoding = new SimpleSingleByteEncoding( + getFontName() + "EncodingSupp" + (additionalsCount + 1)); + this.additionalEncodings.add(encoding); + mappedStart += 256; + } + return (char)(mappedStart + encoding.addCharacter(unencoded.getCharacter())); } - return '#'; } + return 0; } /** {@inheritDoc} */ public boolean hasChar(char c) { - return (mapping.mapChar(c) > 0); + char d = mapping.mapChar(c); + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { + return true; + } + //Check unencoded characters which are available in the font by character name + d = mapUnencodedChar(c); + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { + return true; + } + return false; } /* ---- single byte font specific setters --- */ @@ -146,13 +215,106 @@ public class SingleByteFont extends CustomFont { /** * Sets a width for a character. * @param index index of the character - * @param width the width of the character + * @param w the width of the character */ - public void setWidth(int index, int width) { + public void setWidth(int index, int w) { if (this.width == null) { this.width = new int[getLastChar() - getFirstChar() + 1]; } - this.width[index - getFirstChar()] = width; + this.width[index - getFirstChar()] = w; + } + + /** + * Adds an unencoded character (one that is not supported by the primary encoding). + * @param ch the named character + * @param width the width of the character + */ + public void addUnencodedCharacter(NamedCharacter ch, int width) { + if (this.unencodedCharacters == null) { + this.unencodedCharacters = new java.util.HashMap(); + } + if (ch.hasSingleUnicodeValue()) { + UnencodedCharacter uc = new UnencodedCharacter(ch, width); + this.unencodedCharacters.put(new Character(ch.getSingleUnicodeValue()), uc); + } else { + //Cannot deal with unicode sequences, so ignore this character + } + } + + /** + * Indicates whether the encoding has additional encodings besides the primary encoding. + * @return true if there are additional encodings. + */ + public boolean hasAdditionalEncodings() { + return (this.additionalEncodings != null) && (this.additionalEncodings.size() > 0); + } + + /** + * Returns the number of additional encodings this single-byte font maintains. + * @return the number of additional encodings + */ + public int getAdditionalEncodingCount() { + if (hasAdditionalEncodings()) { + return this.additionalEncodings.size(); + } else { + return 0; + } + } + + /** + * Returns an additional encoding. + * @param index the index of the additional encoding + * @return the additional encoding + * @throws IndexOutOfBoundsException if the index is out of bounds + */ + public SimpleSingleByteEncoding getAdditionalEncoding(int index) + throws IndexOutOfBoundsException { + if (hasAdditionalEncodings()) { + return (SimpleSingleByteEncoding)this.additionalEncodings.get(index); + } else { + throw new IndexOutOfBoundsException("No additional encodings available"); + } + } + + /** + * Returns an array with the widths for an additional encoding. + * @param index the index of the additional encoding + * @return the width array + */ + public int[] getAdditionalWidths(int index) { + SimpleSingleByteEncoding enc = getAdditionalEncoding(index); + int[] arr = new int[enc.getLastChar() - enc.getFirstChar() + 1]; + for (int i = 0, c = arr.length; i < c; i++) { + NamedCharacter nc = enc.getCharacterForIndex(enc.getFirstChar() + i); + UnencodedCharacter uc = (UnencodedCharacter)this.unencodedCharacters.get( + new Character(nc.getSingleUnicodeValue())); + arr[i] = uc.getWidth(); + } + return arr; + } + + private static final class UnencodedCharacter { + + private NamedCharacter character; + private int width; + + public UnencodedCharacter(NamedCharacter character, int width) { + this.character = character; + this.width = width; + } + + public NamedCharacter getCharacter() { + return this.character; + } + + public int getWidth() { + return this.width; + } + + /** {@inheritDoc} */ + public String toString() { + return getCharacter().toString(); + } } } diff --git a/src/java/org/apache/fop/fonts/Typeface.java b/src/java/org/apache/fop/fonts/Typeface.java index 3bc3be772..173d2e8a3 100644 --- a/src/java/org/apache/fop/fonts/Typeface.java +++ b/src/java/org/apache/fop/fonts/Typeface.java @@ -19,11 +19,8 @@ package org.apache.fop.fonts; -// FOP - - /** - * Base class for PDF font classes + * Base class for font classes */ public abstract class Typeface implements FontMetrics { @@ -37,7 +34,7 @@ public abstract class Typeface implements FontMetrics { * Get the encoding of the font. * @return the encoding */ - public abstract String getEncoding(); + public abstract String getEncodingName(); /** * Map a Unicode character to a code point in the font. diff --git a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java index 99fd10315..d593c4544 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java @@ -592,8 +592,8 @@ public class TTFSubSetFile extends TTFFile { + mtxTab[origIndex.intValue()].getOffset()) < 0) { // origIndex is a composite glyph allComposites.put(origIndex, glyphs.get(origIndex)); - List composites = - getIncludedGlyphs(in, (int)entry.getOffset(), + List composites + = getIncludedGlyphs(in, (int)entry.getOffset(), origIndex); // Iterate through all composites pointed to @@ -651,6 +651,9 @@ public class TTFSubSetFile extends TTFFile { if (!checkTTC(in, name)) { throw new IOException("Failed to read font"); } + + //Copy the Map as we're going to modify it + Map subsetGlyphs = new java.util.HashMap(glyphs); output = new byte[in.getFileSize()]; @@ -661,14 +664,14 @@ public class TTFSubSetFile extends TTFFile { readHorizontalMetrics(in); readIndexToLocation(in); - scanGlyphs(in, glyphs); + scanGlyphs(in, subsetGlyphs); createDirectory(); // Create the TrueType header and directory createHead(in); - createHhea(in, glyphs.size()); // Create the hhea table - createHmtx(in, glyphs); // Create hmtx table - createMaxp(in, glyphs.size()); // copy the maxp table + createHhea(in, subsetGlyphs.size()); // Create the hhea table + createHmtx(in, subsetGlyphs); // Create hmtx table + createMaxp(in, subsetGlyphs.size()); // copy the maxp table boolean optionalTableFound; optionalTableFound = createCvt(in); // copy the cvt table @@ -689,8 +692,8 @@ public class TTFSubSetFile extends TTFFile { log.debug("TrueType: prep table not present. Skipped."); } - createLoca(glyphs.size()); // create empty loca table - createGlyf(in, glyphs); //create glyf table and update loca table + createLoca(subsetGlyphs.size()); // create empty loca table + createGlyf(in, subsetGlyphs); //create glyf table and update loca table pad4(); createCheckSumAdjustment(); diff --git a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java index 1b7f814b8..758078af4 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java +++ b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java @@ -21,6 +21,8 @@ package org.apache.fop.fonts.type1; import java.awt.geom.RectangularShape; +import org.apache.fop.fonts.NamedCharacter; + /** * Holds the metrics of a single character from an AFM file. @@ -28,8 +30,7 @@ import java.awt.geom.RectangularShape; public class AFMCharMetrics { private int charCode = -1; - private String unicodeSequence; - private String charName; + private NamedCharacter character; private double widthX; private double widthY; private RectangularShape bBox; @@ -59,36 +60,45 @@ public class AFMCharMetrics { } /** - * Returns the Unicode sequence for this character. - * @return the Unicode characters - * (or null if no such Unicode sequence exists for this character) + * Returns the named character represented by this instance. + * @return the named character (or null if no named character is associated) */ - public String getUnicodeSequence() { - return this.unicodeSequence; + public NamedCharacter getCharacter() { + return this.character; + } + + /** + * Sets the named character represented by this instance. + * @param ch the named character + */ + public void setCharacter(NamedCharacter ch) { + this.character = ch; } /** - * Sets the Unicode sequence for this character. + * Sets the named character represented by this instance. + * @param charName the character name (as defined in the Adobe glyph list) * @param unicodeSequence the Unicode sequence */ - public void setUnicodeSequence(String unicodeSequence) { - this.unicodeSequence = unicodeSequence; + public void setCharacter(String charName, String unicodeSequence) { + setCharacter(new NamedCharacter(charName, unicodeSequence)); } /** - * Returns the PostScript character name. - * @return the charName + * Returns the Unicode sequence for this character. + * @return the Unicode characters + * (or null if no such Unicode sequence exists for this character) */ - public String getCharName() { - return charName; + public String getUnicodeSequence() { + return (getCharacter() != null ? getCharacter().getUnicodeSequence() : null); } /** - * Sets the PostScript character name. - * @param charName the charName to set + * Returns the PostScript character name. + * @return the charName (or null if no character name is associated) */ - public void setCharName(String charName) { - this.charName = charName; + public String getCharName() { + return (getCharacter() != null ? getCharacter().getName() : null); } /** diff --git a/src/java/org/apache/fop/fonts/type1/AFMFile.java b/src/java/org/apache/fop/fonts/type1/AFMFile.java index b51485485..6a1973843 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMFile.java +++ b/src/java/org/apache/fop/fonts/type1/AFMFile.java @@ -26,7 +26,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.xmlgraphics.fonts.Glyphs; import org.apache.xmlgraphics.java2d.Dimension2DDouble; /** @@ -315,15 +314,8 @@ public class AFMFile { public void addCharMetrics(AFMCharMetrics metrics) { String name = metrics.getCharName(); if (metrics.getUnicodeSequence() == null) { - if (name != null) { - String u = Glyphs.getUnicodeSequenceForGlyphName(metrics.getCharName()); - if (u != null) { - metrics.setUnicodeSequence(u); - } - } else { - //Ignore as no Unicode assignment is possible - return; - } + //Ignore as no Unicode assignment is possible + return; } this.charMetrics.add(metrics); if (name != null) { diff --git a/src/java/org/apache/fop/fonts/type1/AFMParser.java b/src/java/org/apache/fop/fonts/type1/AFMParser.java index bb7ea3d30..2e63ea729 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMParser.java +++ b/src/java/org/apache/fop/fonts/type1/AFMParser.java @@ -31,6 +31,8 @@ import java.util.Stack; import org.apache.commons.io.IOUtils; +import org.apache.fop.fonts.NamedCharacter; + /** * Parses the contents of a Type 1 AFM font metrics file into an object structure ({@link AFMFile}). */ @@ -126,7 +128,7 @@ public class AFMParser { VALUE_PARSERS.put(W, new NotImplementedYet(W)); VALUE_PARSERS.put(W0, new NotImplementedYet(W0)); VALUE_PARSERS.put(W1, new NotImplementedYet(W1)); - VALUE_PARSERS.put(N, new StringSetter("CharName")); + VALUE_PARSERS.put(N, new NamedCharacterSetter("Character")); VALUE_PARSERS.put(B, new CharBBox()); VALUE_PARSERS.put(START_TRACK_KERN, new NotImplementedYet(START_TRACK_KERN)); VALUE_PARSERS.put(END_TRACK_KERN, new NotImplementedYet(END_TRACK_KERN)); @@ -379,6 +381,19 @@ public class AFMParser { } } + private static class NamedCharacterSetter extends BeanSetter { + + public NamedCharacterSetter(String variable) { + super(variable); + } + + public void parse(String line, int startpos, Stack stack) throws IOException { + NamedCharacter ch = new NamedCharacter(getStringValue(line, startpos)); + Object obj = stack.peek(); + setValue(obj, ch); + } + } + private static class NumberSetter extends BeanSetter { public NumberSetter(String variable) { super(variable); diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 910ee82cc..8cf6f2371 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -108,6 +108,11 @@ public class Type1FontLoader extends FontLoader { throw new java.io.FileNotFoundException( "Neither an AFM nor a PFM file was found for " + this.fontFileURI); } + if (pfm == null) { + //Cannot do without the PFM for now + throw new java.io.FileNotFoundException( + "No PFM file was found for " + this.fontFileURI); + } buildFont(afm, pfm); this.loaded = true; } @@ -122,12 +127,17 @@ public class Type1FontLoader extends FontLoader { singleFont.setEmbedFileName(this.fontFileURI); returnFont = singleFont; + handleEncoding(afm, pfm); + handleFontName(afm, pfm); + handleMetrics(afm, pfm); + } + + private void handleEncoding(AFMFile afm, PFMFile pfm) { //Encoding if (afm != null) { String encoding = afm.getEncodingScheme(); if ("AdobeStandardEncoding".equals(encoding)) { - //Use WinAnsi in this case as it better fits the usual character set people need - singleFont.setEncoding(CodePointMapping.WIN_ANSI_ENCODING); + singleFont.setEncoding(CodePointMapping.STANDARD_ENCODING); } else { String effEncodingName; if ("FontSpecific".equals(encoding)) { @@ -142,6 +152,14 @@ public class Type1FontLoader extends FontLoader { CodePointMapping mapping = buildCustomEncoding(effEncodingName, afm); singleFont.setEncoding(mapping); } + List charMetrics = afm.getCharMetrics(); + for (int i = 0, c = afm.getCharCount(); i < c; i++) { + AFMCharMetrics metrics = (AFMCharMetrics)charMetrics.get(i); + if (!metrics.hasCharCode() && metrics.getCharacter() != null) { + singleFont.addUnencodedCharacter(metrics.getCharacter(), + (int)Math.round(metrics.getWidthX())); + } + } } else { if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) { singleFont.setEncoding(pfm.getCharSetName() + "Encoding"); @@ -151,7 +169,9 @@ public class Type1FontLoader extends FontLoader { singleFont.setEncoding("WinAnsiEncoding"); //Try fallback, no guarantees! } } - + } + + private void handleFontName(AFMFile afm, PFMFile pfm) { //Font name if (afm != null) { returnFont.setFontName(afm.getFontName()); //PostScript font name @@ -168,7 +188,9 @@ public class Type1FontLoader extends FontLoader { names.add(pfm.getWindowsName()); //emulate afm.getFamilyName() returnFont.setFamilyNames(names); } - + } + + private void handleMetrics(AFMFile afm, PFMFile pfm) { //Basic metrics if (afm != null) { if (afm.getCapHeight() != null) { @@ -268,6 +290,7 @@ public class Type1FontLoader extends FontLoader { if (afm != null) { //TODO returnFont.setFlags(flags); + returnFont.setFirstChar(afm.getFirstChar()); returnFont.setLastChar(afm.getLastChar()); Iterator iter = afm.getCharMetrics().iterator(); @@ -279,7 +302,6 @@ public class Type1FontLoader extends FontLoader { } returnFont.replaceKerningMap(afm.createXKerningMapEncoded()); } else { - returnFont.setFlags(pfm.getFlags()); returnFont.setFirstChar(pfm.getFirstChar()); returnFont.setLastChar(pfm.getLastChar()); for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { @@ -287,6 +309,7 @@ public class Type1FontLoader extends FontLoader { } returnFont.replaceKerningMap(pfm.getKerning()); } + returnFont.setFlags(pfm.getFlags()); } private CodePointMapping buildCustomEncoding(String encodingName, AFMFile afm) { diff --git a/src/java/org/apache/fop/image/AbstractFopImage.java b/src/java/org/apache/fop/image/AbstractFopImage.java deleted file mode 100644 index 68949b9c9..000000000 --- a/src/java/org/apache/fop/image/AbstractFopImage.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * 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.image; - -// Java -import java.awt.color.ColorSpace; -import java.awt.color.ICC_ColorSpace; -import java.awt.color.ICC_Profile; -import java.io.InputStream; -import java.awt.Color; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.datatypes.Length; - -/** - * Base class to implement the FopImage interface. - * - * @see FopImage - */ -public abstract class AbstractFopImage implements FopImage { - - /** - * logging instance - */ - protected static Log log = LogFactory.getLog(AbstractFopImage.class); - - /** - * Keeps track of what has been loaded. - */ - protected int loaded = 0; - - /** - * Image width (in pixel). - */ - protected int width = 0; - - /** - * Image height (in pixel). - */ - protected int height = 0; - - /** Horizontal bitmap resolution (in dpi) */ - protected double dpiHorizontal = 72.0f; - - /** Vertical bitmap resolution (in dpi) */ - protected double dpiVertical = 72.0f; - - /** - * Image input stream. - */ - protected InputStream inputStream = null; - - /** - * ImageReader object (to obtain image header informations). - */ - protected FopImage.ImageInfo imageInfo = null; - - /** - * Image color space (java.awt.color.ColorSpace). - */ - protected ColorSpace colorSpace = null; - - /** - * Bits per pixel. - */ - protected int bitsPerPixel = 0; - - /** - * Image data (pixels, uncompressed). - */ - protected byte[] bitmaps = null; - - /** - * Image data (undecoded, compressed, for image formats that can be embedded without decoding. - */ - protected byte[] raw = null; - - /** - * Image transparency. - */ - protected boolean isTransparent = false; - - /** - * Transparent color (java.awt.Color). - */ - protected Color transparentColor = null; - - /** - * Photoshop generated CMYK JPEGs are inverted. - */ - protected boolean invertImage = false; - - /** - * Constructor. - * Construct a new FopImage object and initialize its default properties: - * <UL> - * <LI>image width - * <LI>image height - * </UL> - * The image data isn't kept in memory. - * @param info image information - */ - public AbstractFopImage(FopImage.ImageInfo info) { - this.inputStream = info.inputStream; - this.imageInfo = info; - if (this.imageInfo.width != -1) { - width = imageInfo.width; - height = imageInfo.height; - dpiHorizontal = imageInfo.dpiHorizontal; - dpiVertical = imageInfo.dpiVertical; - loaded = loaded | DIMENSIONS; - } - } - - /** - * Get the mime type for this image. - * - * @return the mime type for the image - */ - public String getMimeType() { - return imageInfo.mimeType; - } - - /** {@inheritDoc} */ - public String getOriginalURI() { - return this.imageInfo.originalURI; - } - - /** - * Load image data and initialize its properties. - * - * @param type the type of loading to do - * @return true if the loading was successful - */ - public synchronized boolean load(int type) { - if ((loaded & type) != 0) { - return true; - } - boolean success = true; - if (((type & DIMENSIONS) != 0) && ((loaded & DIMENSIONS) == 0)) { - success = success && loadDimensions(); - - if (!success) { - return false; - } - loaded = loaded | DIMENSIONS; - } - if (((type & BITMAP) != 0) && ((loaded & BITMAP) == 0)) { - success = success && loadBitmap(); - if (success) { - loaded = loaded | BITMAP; - } - } - if (((type & ORIGINAL_DATA) != 0) && ((loaded & ORIGINAL_DATA) == 0)) { - success = success && loadOriginalData(); - if (success) { - loaded = loaded | ORIGINAL_DATA; - } - } - return success; - } - - /** - * Load the dimensions of the image. - * All implementations should override this to get and - * return the dimensions. - * - * @return true if the loading was successful - */ - protected boolean loadDimensions() { - return false; - } - - /** - * Load a bitmap array of the image. - * If the renderer requires a bitmap image then the - * implementations should override this to load the bitmap. - * - * @return true if the loading was successful - */ - protected boolean loadBitmap() { - return false; - } - - /** - * Load the original image data. - * In some cases the original data can be used by the renderer. - * This should load the data and any other associated information. - * - * @return true if the loading was successful - */ - protected boolean loadOriginalData() { - return false; - } - - /** - * Load the original image data. This is generic code for use by any - * subclass that wants to use this from a loadOriginalData() implementation. - * - * @return true if the loading was successful - */ - protected boolean loadDefaultOriginalData() { - if (inputStream == null) { - throw new IllegalStateException("inputStream is already null or was never set"); - } - try { - this.raw = IOUtils.toByteArray(inputStream); - } catch (java.io.IOException ex) { - log.error("Error while reading raw image: " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - return true; - } - - /** - * @return the image width (in pixels) - */ - public int getWidth() { - return this.width; - } - - /** - * @return the image height (in pixels) - */ - public int getHeight() { - return this.height; - } - - /** {@inheritDoc} */ - public int getIntrinsicWidth() { - return (int)(getWidth() * 72000 / getHorizontalResolution()); - } - - /** {@inheritDoc} */ - public int getIntrinsicHeight() { - return (int)(getHeight() * 72000 / getVerticalResolution()); - } - - /** {@inheritDoc} */ - public Length getIntrinsicAlignmentAdjust() { - return this.imageInfo.alignmentAdjust; - } - - /** {@inheritDoc} */ - public double getHorizontalResolution() { - return this.dpiHorizontal; - } - - /** {@inheritDoc} */ - public double getVerticalResolution() { - return this.dpiVertical; - } - - /** - * Return the image color space. - * @return the image color space (java.awt.color.ColorSpace) - */ - public ColorSpace getColorSpace() { - return this.colorSpace; - } - - /** - * Get ICC profile for this image. - * @return the icc profile or null if not applicable - */ - public ICC_Profile getICCProfile() { - if (this.colorSpace != null && this.colorSpace instanceof ICC_ColorSpace) { - return ((ICC_ColorSpace)this.colorSpace).getProfile(); - } - return null; - } - - /** - * Return the number of bits per pixel. - * @return number of bits per pixel - */ - public int getBitsPerPixel() { - return this.bitsPerPixel; - } - - /** - * Return the image transparency. - * @return true if the image is transparent - */ - public boolean isTransparent() { - return this.isTransparent; - } - - /** - * Check if this image has a soft mask. - * - * @return true if the image also has a soft transparency mask - */ - public boolean hasSoftMask() { - return false; - } - - /** - * Get the soft mask. - * The soft mask should have the same bitdepth as the image data. - * - * @return the data array of soft mask values - */ - public byte[] getSoftMask() { - return null; - } - - /** - * Return the transparent color. - * @return the transparent color (java.awt.Color) - */ - public Color getTransparentColor() { - return this.transparentColor; - } - - /** @return true for CMYK images generated by Adobe Photoshop */ - public boolean isInverted() { - return this.invertImage; - } - - /** - * Return the image data (pixels, uncompressed). - * @return the image data - */ - public byte[] getBitmaps() { - return this.bitmaps; - } - - /** - * Return the image data size (number of bytes taken up by the uncompressed pixels). - * @return the image data size - */ - public int getBitmapsSize() { - return (bitmaps != null ? bitmaps.length : 0); - } - - /** - * Return the original image data (compressed). - * @return the original image data - */ - public byte[] getResourceBytes() { - return raw; - } - - /** - * Return the original image data size (compressed). - * @return the original image data size - */ - public int getResourceBytesSize() { - return (raw != null ? raw.length : 0); - } - -} - diff --git a/src/java/org/apache/fop/image/BmpImage.java b/src/java/org/apache/fop/image/BmpImage.java deleted file mode 100644 index 5ebf522e9..000000000 --- a/src/java/org/apache/fop/image/BmpImage.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * 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.image; - -// Java -import java.io.IOException; -import java.awt.color.ColorSpace; - -import org.apache.commons.io.IOUtils; - -/** - * Bitmap image. - * This supports loading a bitmap image into bitmap data. - * - * @see AbstractFopImage - * @see FopImage - */ -public class BmpImage extends AbstractFopImage { - /** - * Create a bitmap image with the image data. - * - * @param imgInfo the image information - */ - public BmpImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * Load the bitmap. - * This laods the bitmap data from the bitmap image. - * - * @return true if it was loaded successfully - */ - protected boolean loadBitmap() { - int wpos = 18; - int hpos = 22; // offset positioning for w and height in bmp files - int[] headermap = new int[54]; - int filepos = 0; - byte[] palette = null; - try { - boolean eof = false; - while ((!eof) && (filepos < 54)) { - int input = inputStream.read(); - if (input == -1) { - eof = true; - } else { - headermap[filepos++] = input; - } - } - - if (headermap[28] == 4 || headermap[28] == 8) { - int palettesize = 1 << headermap[28]; - palette = new byte[palettesize * 3]; - int countr = 0; - while (!eof && countr < palettesize) { - int count2 = 2; - while (!eof && count2 >= -1) { - int input = inputStream.read(); - if (input == -1) { - eof = true; - } else if (count2 >= 0) { - palette[countr * 3 + count2] = (byte)(input & 0xFF); - } - count2--; - filepos++; - } - countr++; - } - } - } catch (IOException ex) { - log.error("Error while loading image (Bmp): " + ex.getMessage(), ex); - IOUtils.closeQuietly(inputStream); - inputStream = null; - return false; - } - // gets h & w from headermap - this.width = headermap[wpos] - + headermap[wpos + 1] * 256 - + headermap[wpos + 2] * 256 * 256 - + headermap[wpos + 3] * 256 * 256 * 256; - this.height = headermap[hpos] - + headermap[hpos + 1] * 256 - + headermap[hpos + 2] * 256 * 256 - + headermap[hpos + 3] * 256 * 256 * 256; - - int imagestart = headermap[10] - + headermap[11] * 256 - + headermap[12] * 256 * 256 - + headermap[13] * 256 * 256 * 256; - this.bitsPerPixel = headermap[28]; - this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); - int bytes = 0; - if (this.bitsPerPixel == 1) { - bytes = (this.width + 7) / 8; - } else if (this.bitsPerPixel == 24) { - bytes = this.width * 3; - } else if (this.bitsPerPixel == 4 || this.bitsPerPixel == 8) { - bytes = this.width / (8 / this.bitsPerPixel); - } else { - log.error("Image (" + "" - + ") has " + this.bitsPerPixel - + " which is not a supported BMP format."); - return false; - } - if ((bytes & 0x03) != 0) { - bytes |= 0x03; - bytes++; - } - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - - int[] temp = new int[bytes * this.height]; - try { - int input; - int count = 0; - inputStream.skip((long)(imagestart - filepos)); - while ((input = inputStream.read()) != -1) { - if (count >= temp.length) { - log.warn("Data longer than expected while loading image"); - break; - } else { - temp[count++] = input; - } - } - } catch (IOException ex) { - log.error("Error while loading image (Bmp): " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - for (int i = 0; i < this.height; i++) { - int x = 0; - int j = 0; - while (j < bytes) { - int p = temp[(this.height - i - 1) * bytes + j]; - - if (this.bitsPerPixel == 24 && x < this.width) { - int countr = 2; - do { - this.bitmaps[3 * (i * this.width + x) + countr] - = (byte)(temp[(this.height - i - 1) * bytes + j] & 0xFF); - j++; - } while (--countr >= 0) - ; - x++; - } else if (this.bitsPerPixel == 1) { - for (int countr = 0; - countr < 8 && x < this.width; countr++) { - if ((p & 0x80) != 0) { - this.bitmaps[3 * (i * this.width + x)] = (byte) 0xFF; - this.bitmaps[3 * (i * this.width + x) + 1] = (byte) 0xFF; - this.bitmaps[3 * (i * this.width + x) + 2] = (byte) 0xFF; - } else { - this.bitmaps[3 * (i * this.width + x)] = (byte) 0; - this.bitmaps[3 * (i * this.width + x) + 1] = (byte) 0; - this.bitmaps[3 * (i * this.width + x) + 2] = (byte) 0; - } - p <<= 1; - x++; - } - j++; - } else if (this.bitsPerPixel == 4) { - for (int countr = 0; - countr < 2 && x < this.width; countr++) { - int pal = ((p & 0xF0) >> 4) * 3; - this.bitmaps[3 * (i * this.width + x)] = palette[pal]; - this.bitmaps[3 * (i * this.width + x) + 1] = palette[pal + 1]; - this.bitmaps[3 * (i * this.width + x) + 2] = palette[pal + 2]; - p <<= 4; - x++; - } - j++; - } else if (this.bitsPerPixel == 8) { - if (x < this.width) { - p *= 3; - this.bitmaps[3 * (i * this.width + x)] = palette[p]; - this.bitmaps[3 * (i * this.width + x) + 1] = palette[p + 1]; - this.bitmaps[3 * (i * this.width + x) + 2] = palette[p + 2]; - j++; - x++; - } else { - j = bytes; - } - } else { - j++; - } - } - } - - // This seems really strange to me, but I noticed that - // JimiImage hardcodes bitsPerPixel to 8. If I do not - // do this Acrobat is unable to read the resultant PDF, - // so we will hardcode this... - this.bitsPerPixel = 8; - - return true; - } - -} - diff --git a/src/java/org/apache/fop/image/EPSImage.java b/src/java/org/apache/fop/image/EPSImage.java deleted file mode 100644 index ab708f2a4..000000000 --- a/src/java/org/apache/fop/image/EPSImage.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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.image; - - -/** - * EPS image handler. - * This handles the Encapulated PostScript images. - * It gets the dimensions and original data from the analyser. - * - * @see AbstractFopImage - * @see FopImage - */ -public class EPSImage extends AbstractFopImage { - - private String docName; - private int[] bbox; - - private EPSData epsData = null; - - /** - * Create an EPS image with the image information. - * - * @param imgInfo the information containing the data and bounding box - */ - public EPSImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - init(""); - if (imgInfo.data instanceof EPSData) { - epsData = (EPSData) imgInfo.data; - bbox = new int[4]; - bbox[0] = (int) epsData.bbox[0]; - bbox[1] = (int) epsData.bbox[1]; - bbox[2] = (int) epsData.bbox[2]; - bbox[3] = (int) epsData.bbox[3]; - - loaded = loaded | ORIGINAL_DATA; - } - } - - /** - * Initialize docName and bounding box. - * @param name the document name - */ - private void init(String name) { - bbox = new int[4]; - bbox[0] = 0; - bbox[1] = 0; - bbox[2] = 0; - bbox[3] = 0; - - docName = name; - } - - /** - * Return the name of the eps - * @return the name of the eps - */ - public String getDocName() { - return docName; - } - - /** - * Return the bounding box - * @return an int array containing the bounding box - */ - public int[] getBBox() { - return bbox; - } - - /** - * Get the eps image. - * - * @return the original eps image data - */ - public byte[] getEPSImage() { - if (epsData.epsFile == null) { - //log.error("ERROR LOADING EXTERNAL EPS"); - } - return epsData.epsFile; - } - - /** - * Data for EPS image. - */ - public static class EPSData { - public long[] bbox; - public boolean isAscii; // True if plain ascii eps file - - // offsets if not ascii - public long psStart = 0; - public long psLength = 0; - public long wmfStart = 0; - public long wmfLength = 0; - public long tiffStart = 0; - public long tiffLength = 0; - - /** raw eps file */ - public byte[] rawEps; - /** eps part */ - public byte[] epsFile; - public byte[] preview = null; - } - -} diff --git a/src/java/org/apache/fop/image/FopImage.java b/src/java/org/apache/fop/image/FopImage.java deleted file mode 100644 index abe11ef25..000000000 --- a/src/java/org/apache/fop/image/FopImage.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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.image; - -import java.io.InputStream; -import java.awt.color.ColorSpace; -import java.awt.color.ICC_Profile; -import java.awt.Color; - -import org.apache.fop.datatypes.Length; - -/** - * Fop image interface for loading images. - */ -public interface FopImage { - /** - * Flag for loading dimensions. - */ - int DIMENSIONS = 1; - - /** - * Flag for loading original data. - */ - int ORIGINAL_DATA = 2; - - /** - * Flag for loading bitmap data. - */ - int BITMAP = 4; - - /** - * Get the mime type of this image. - * This is used so that when reading from the image it knows - * what type of image it is. - * - * @return the mime type string - */ - String getMimeType(); - - /** @return the original URI used to access this image. */ - String getOriginalURI(); - - /** - * Load particular inforamtion for this image - * This must be called before attempting to get - * the information. - * - * @param type the type of loading required - * @return boolean true if the information could be loaded - */ - boolean load(int type); - - /** - * Returns the image width. - * @return the width in pixels - */ - int getWidth(); - - /** - * Returns the image height. - * @return the height in pixels - */ - int getHeight(); - - /** - * @return the intrinsic image width (in millipoints) - */ - int getIntrinsicWidth(); - - /** - * @return the intrinsic image width (in millipoints) - */ - int getIntrinsicHeight(); - - /** - * @return the intrinsic alignment-adjust value or NULL if the image does - * not have one. - */ - Length getIntrinsicAlignmentAdjust(); - - /** - * @return the horizontal bitmap resolution (in dpi) - */ - double getHorizontalResolution(); - - /** - * @return the vertical bitmap resolution (in dpi) - */ - double getVerticalResolution(); - - /** - * Returns the color space of the image. - * @return the color space - */ - ColorSpace getColorSpace(); - - /** - * Returns the ICC profile. - * @return the ICC profile, null if none is available - */ - ICC_Profile getICCProfile(); - - /** - * Returns the number of bits per pixel for the image. - * @return the number of bits per pixel - */ - int getBitsPerPixel(); - - /** - * Indicates whether the image is transparent. - * @return True if it is transparent - */ - boolean isTransparent(); - - /** - * For transparent images. Returns the transparent color. - * @return the transparent color - */ - Color getTransparentColor(); - - /** - * Indicates whether the image has a Soft Mask (See section 7.5.4 in the - * PDF specs) - * @return True if a Soft Mask exists - */ - boolean hasSoftMask(); - - /** - * For images with a Soft Mask. Returns the Soft Mask as an array. - * @return the Soft Mask - */ - byte[] getSoftMask(); - - /** @return true for CMYK images generated by Adobe Photoshop */ - boolean isInverted(); - - /** - * Returns the decoded and uncompressed image as a array of - * width * height * [colorspace-multiplicator] pixels. - * @return the bitmap - */ - byte[] getBitmaps(); - /** - * Returns the size of the image. - * width * (bitsPerPixel / 8) * height, no ? - * @return the size - */ - int getBitmapsSize(); - - /** - * Returns the encoded/compressed image as an array of bytes. - * @return the raw image - */ - byte[] getResourceBytes(); - - /** - * Returns the number of bytes of the raw image. - * @return the size in bytes - */ - int getResourceBytesSize(); - - /** - * Image info class. - * Information loaded from analyser and passed to image object. - */ - public static class ImageInfo { - /** InputStream to load the image from */ - public InputStream inputStream; - /** Original URI the image was accessed with */ - public String originalURI; - /** image width (in pixels) */ - public int width; - /** image height (in pixels) */ - public int height; - /** horizontal bitmap resolution (in dpi) */ - public double dpiHorizontal = 72.0f; - /** vertical bitmap resolution (in dpi) */ - public double dpiVertical = 72.0f; - /** implementation-specific data object (ex. a SVG DOM for SVG images) */ - public Object data; - /** MIME type of the image */ - public String mimeType; - /** implementation-specific String (ex. the namespace for XML-based images) */ - public String str; - /** intrinsic alignment-adjust or null if there is none */ - public Length alignmentAdjust; - } - -} - diff --git a/src/java/org/apache/fop/image/FopImageConsumer.java b/src/java/org/apache/fop/image/FopImageConsumer.java deleted file mode 100644 index 4e4d7be48..000000000 --- a/src/java/org/apache/fop/image/FopImageConsumer.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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.image; - -// Java -import java.util.Hashtable; -import java.awt.image.ColorModel; -import java.awt.image.ImageConsumer; -import java.awt.image.ImageProducer; -import java.awt.image.PixelGrabber; - -/** - * ImageConsumer implementation for FopImage classes. - */ -public class FopImageConsumer implements ImageConsumer { - - /** Image width in pixels */ - protected int width = -1; - /** Image height in pixels */ - protected int height = -1; - /** Image status */ - protected Integer imageStatus = new Integer(-1); - /** hints */ - protected int hints = 0; - /** Image properties */ - protected Hashtable properties = null; - /** Color model */ - protected ColorModel cm = null; - /** Image producer */ - protected ImageProducer ip = null; - - /** - * Main constructor - * @param iprod ImageProducer to use - */ - public FopImageConsumer(ImageProducer iprod) { - this.ip = iprod; - } - - /** - * {@inheritDoc} - */ - public void imageComplete(int status) { - /* - * log.error("Status "); - * if (status == ImageConsumer.COMPLETESCANLINES) { - * log.error("CompleteScanLines"); - * } else if (status == ImageConsumer.IMAGEABORTED) { - * log.error("ImageAborted"); - * } else if (status == ImageConsumer.IMAGEERROR) { - * log.error("ImageError"); - * } else if (status == ImageConsumer.RANDOMPIXELORDER) { - * log.error("RandomPixelOrder"); - * } else if (status == ImageConsumer.SINGLEFRAME) { - * log.error("SingleFrame"); - * } else if (status == ImageConsumer.SINGLEFRAMEDONE) { - * log.error("SingleFrameDone"); - * } else if (status == ImageConsumer.SINGLEPASS) { - * log.error("SinglePass"); - * } else if (status == ImageConsumer.STATICIMAGEDONE) { - * log.error("StaticImageDone"); - * } else if (status == ImageConsumer.TOPDOWNLEFTRIGHT) { - * log.error("TopDownLeftRight"); - * } - */ - synchronized (this.imageStatus) { - // Need to stop status if image done - if (imageStatus.intValue() != ImageConsumer.STATICIMAGEDONE - && imageStatus.intValue() != ImageConsumer.SINGLEFRAMEDONE) { - this.imageStatus = new Integer(status); - } - } - } - - /** - * {@inheritDoc} - */ - public void setColorModel(ColorModel model) { - // log.error("setColorModel: " + model); - this.cm = model; - } - - /** - * {@inheritDoc} - */ - public void setDimensions(int width, int height) { - // log.error("setDimension: w=" + width + " h=" + height); - this.width = width; - this.height = height; - } - - /** - * {@inheritDoc} - */ - public void setHints(int hintflags) { - // log.error("setHints: " + hintflags); - this.hints = hintflags; - } - - /** - * {@inheritDoc} - */ - public void setProperties(Hashtable props) { - // log.error("setProperties: " + props); - this.properties = props; - } - - /** - * {@inheritDoc} - */ - public void setPixels(int x, int y, int w, int h, ColorModel model, - byte[] pixels, int off, int scansize) { - } - - /** - * {@inheritDoc} - */ - public void setPixels(int x, int y, int w, int h, ColorModel model, - int[] pixels, int off, int scansize) { - } - - /** - * Indicates whether the image is ready. - * @return boolean True if the image is ready, false if it's still loading - * @throws Exception If an error happened while loading the image - */ - public boolean isImageReady() throws Exception { - /**@todo Use a better exception than Exception */ - synchronized (this.imageStatus) { - if (this.imageStatus.intValue() == ImageConsumer.IMAGEABORTED) { - throw new Exception("Image aborted"); - } - if (this.imageStatus.intValue() == ImageConsumer.IMAGEERROR) { - throw new Exception("Image error"); - } - - if (imageStatus.intValue() == ImageConsumer.STATICIMAGEDONE - || imageStatus.intValue() == ImageConsumer.SINGLEFRAMEDONE) { - return true; - } - - return false; - } - } - - /** - * Returns the image width - * @return the width in pixels - */ - public int getWidth() { - return this.width; - } - - /** - * Returns the image height - * @return the height in pixels - */ - public int getHeight() { - return this.height; - } - - /** - * Returns the color model of the image - * @return the color model - */ - public ColorModel getColorModel() { - return this.cm; - } - - /** - * Returns the bitmap as an array. - * @return the bitmap as an array. - * @throws Exception if an error occured while generating the array - */ - public int[] getImage() throws Exception { - int tmpMap[] = new int[this.width * this.height]; - PixelGrabber pg = new PixelGrabber(this.ip, 0, 0, this.width, - this.height, tmpMap, 0, this.width); - pg.setDimensions(this.width, this.height); - pg.setColorModel(this.cm); - pg.setHints(this.hints); - pg.setProperties(this.properties); - try { - pg.grabPixels(); - } catch (InterruptedException intex) { - /**@todo Use a better exception than Exception */ - throw new Exception("Image grabbing interrupted : " - + intex.getMessage()); - } - return tmpMap; - } - -} - diff --git a/src/java/org/apache/fop/image/GifImage.java b/src/java/org/apache/fop/image/GifImage.java deleted file mode 100644 index 27e81c4fc..000000000 --- a/src/java/org/apache/fop/image/GifImage.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * 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.image; - -// Java -import java.awt.image.ImageProducer; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.color.ColorSpace; -import java.awt.Color; -import java.io.InputStream; -import java.io.IOException; -import java.net.URLConnection; - -import org.apache.commons.io.IOUtils; - -/** - * FopImage object for GIF images, using Java native classes. - * - * @see AbstractFopImage - * @see FopImage - */ -public class GifImage extends AbstractFopImage { - - /** - * Create a new gif image. - * - * @param imgInfo the image info for this gif image - */ - public GifImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * Load the bitmap for this gif image. - * This loads the data and creates a bitmap byte array - * of the image data. - * To decode the image a dummy URLConnection is used that - * will do the conversion. - * - * @return True if the load process succeeded - */ - protected boolean loadBitmap() { - int[] tmpMap = null; - try { - URLConnection con = new DummyConnection(inputStream); - - ImageProducer ip = (ImageProducer) con.getContent(); - if (ip == null) { - return false; - } - FopImageConsumer consumer = new FopImageConsumer(ip); - ip.startProduction(consumer); - - //Load the image into memory - while (!consumer.isImageReady()) { - Thread.sleep(500); - } - - this.height = consumer.getHeight(); - this.width = consumer.getWidth(); - - try { - tmpMap = consumer.getImage(); - } catch (Exception ex) { - log.error("Image grabbing interrupted : " - + ex.getMessage(), ex); - return false; - } - - ColorModel cm = consumer.getColorModel(); - this.bitsPerPixel = 8; - // this.bitsPerPixel = cm.getPixelSize(); - this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); - if (cm.hasAlpha()) { - // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT - int transparencyType = cm.getTransparency(); - - if (transparencyType == java.awt.Transparency.OPAQUE) { - this.isTransparent = false; - } else if (transparencyType == java.awt.Transparency.BITMASK) { - if (cm instanceof IndexColorModel) { - IndexColorModel indexcm = (IndexColorModel) cm; - this.isTransparent = false; - byte[] alphas = new byte[indexcm.getMapSize()]; - byte[] reds = new byte[indexcm.getMapSize()]; - byte[] greens = new byte[indexcm.getMapSize()]; - byte[] blues = new byte[indexcm.getMapSize()]; - indexcm.getAlphas(alphas); - indexcm.getReds(reds); - indexcm.getGreens(greens); - indexcm.getBlues(blues); - for (int i = 0; - i < indexcm.getMapSize(); - i++) { - if ((alphas[i] & 0xFF) == 0) { - this.isTransparent = true; - this.transparentColor = new Color( - (int)(reds[i] & 0xFF), - (int)(greens[i] & 0xFF), - (int)(blues[i] & 0xFF)); - break; - } - } - } else { - // TRANSLUCENT - /* - * this.isTransparent = false; - * for (int i = 0; i < this.width * this.height; i++) { - * if (cm.getAlpha(tmpMap[i]) == 0) { - * this.isTransparent = true; - * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]), - * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i])); - * break; - * } - * } - */ - // use special API... - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } catch (Exception ex) { - log.error("Error while loading image (Gif): " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - for (int i = 0; i < this.height; i++) { - for (int j = 0; j < this.width; j++) { - int p = tmpMap[i * this.width + j]; - int r = (p >> 16) & 0xFF; - int g = (p >> 8) & 0xFF; - int b = (p) & 0xFF; - this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF); - } - } - return true; - } - - /** {@inheritDoc} */ - protected boolean loadOriginalData() { - return loadDefaultOriginalData(); - } - - /** - * A dummy url connection for a gif image in an input stream. - */ - protected static class DummyConnection extends URLConnection { - private InputStream inputStream; - - DummyConnection(InputStream is) { - super(null); - inputStream = is; - } - - /** - * {@inheritDoc} - */ - public InputStream getInputStream() throws IOException { - return inputStream; - } - - /** - * {@inheritDoc} - */ - public void connect() throws IOException { - // do nothing - } - - /** - * {@inheritDoc} - */ - public String getContentType() { - return "image/gif"; - } - - /** - * {@inheritDoc} - */ - public int getContentLength() { - try { - return inputStream.available(); - } catch (IOException e) { - return -1; - } - } - - } -} - diff --git a/src/java/org/apache/fop/image/ImageCache.java b/src/java/org/apache/fop/image/ImageCache.java deleted file mode 100644 index 3dd639823..000000000 --- a/src/java/org/apache/fop/image/ImageCache.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.image; - -// FOP -import org.apache.fop.apps.FOUserAgent; - -/** - * Image cache holder. - * This interface is used for caching images. - */ -public interface ImageCache { - - /** - * Get an image from the cache. - * - * @param url the url and key for the image - * @param context the user agent context - * @return the requested image - */ - FopImage getImage(String url, FOUserAgent context); - - /** - * Release an image in the current context. - * - * @param url the url and key for the image - * @param context the user agent context - */ - void releaseImage(String url, FOUserAgent context); - - /** - * Invalidate image. - * If during loading this image is found to be invalid - * it will be invalidated to prevent further attempts at - * loading the image. - * - * @param url the url and key for the image - * @param context the user agent context - */ - void invalidateImage(String url, FOUserAgent context); - - /** - * Remove a context and handle all images in the context. - * - * @param context the user agent context - */ - void removeContext(FOUserAgent context); - - /** - * Forces the cache to fully cleared. - */ - void clearAll(); - -} - diff --git a/src/java/org/apache/fop/image/ImageFactory.java b/src/java/org/apache/fop/image/ImageFactory.java deleted file mode 100644 index 5c9f198e8..000000000 --- a/src/java/org/apache/fop/image/ImageFactory.java +++ /dev/null @@ -1,708 +0,0 @@ -/* - * 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.image; - -// Java -import java.io.InputStream; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.SoftReference; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; - -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.datatypes.URISpecification; -import org.apache.fop.image.analyser.ImageReaderFactory; -import org.apache.xmlgraphics.util.Service; - -/** - * Create FopImage objects (with a configuration file - not yet implemented). - * @author Eric SCHAEFFER - */ -public final class ImageFactory { - - /** - * logging instance - */ - protected static Log log = LogFactory.getLog(FopImage.class); - - private HashMap imageMimeTypes = new HashMap(); - - private ImageCache cache = new ContextImageCache(true); - - /** - * Main constructor for the ImageFactory. - */ - public ImageFactory() { - /* @todo The mappings set up below of image mime types to implementing - * classes should be made externally configurable - */ - ImageProvider jaiImage = new ImageProvider("JAIImage", "org.apache.fop.image.JAIImage"); - ImageProvider jimiImage = new ImageProvider("JIMIImage", "org.apache.fop.image.JimiImage"); - ImageProvider imageIoImage = new ImageProvider( - "ImageIOImage", "org.apache.fop.image.ImageIOImage"); - ImageProvider gifImage = new ImageProvider("GIFImage", "org.apache.fop.image.GifImage"); - ImageProvider jpegImage = new ImageProvider("JPEGImage", "org.apache.fop.image.JpegImage"); - ImageProvider jpegImageIOImage = new ImageProvider( - "JPEGImage", "org.apache.fop.image.JpegImageIOImage"); - ImageProvider bmpImage = new ImageProvider("BMPImage", "org.apache.fop.image.BmpImage"); - ImageProvider epsImage = new ImageProvider("EPSImage", "org.apache.fop.image.EPSImage"); - ImageProvider pngImage = new ImageProvider("PNGImage", "org.apache.fop.image.PNGImage"); - ImageProvider tiffImage = new ImageProvider("TIFFImage", "org.apache.fop.image.TIFFImage"); - ImageProvider xmlImage = new ImageProvider("XMLImage", "org.apache.fop.image.XMLImage"); - ImageProvider emfImage = new ImageProvider("EMFImage", "org.apache.fop.image.EmfImage"); - - ImageMimeType imt = new ImageMimeType("image/gif"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(imageIoImage); - imt.addProvider(jaiImage); - imt.addProvider(jimiImage); - imt.addProvider(gifImage); - - imt = new ImageMimeType("image/jpeg"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(jpegImageIOImage); - imt.addProvider(jpegImage); - - imt = new ImageMimeType("image/bmp"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(bmpImage); - - imt = new ImageMimeType("image/eps"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(epsImage); - - imt = new ImageMimeType("image/png"); - imageMimeTypes.put(imt.getMimeType(), imt); - //Image I/O is faster and more memory-efficient than own codec for PNG - imt.addProvider(imageIoImage); - imt.addProvider(pngImage); - - imt = new ImageMimeType("image/tga"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(jaiImage); - imt.addProvider(imageIoImage); - imt.addProvider(jimiImage); - - imt = new ImageMimeType("image/tiff"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(tiffImage); //Slower but supports CCITT embedding - imt.addProvider(imageIoImage); //Fast but doesn't support CCITT embedding - imt.addProvider(jaiImage); //Fast but doesn't support CCITT embedding - - imt = new ImageMimeType("image/svg+xml"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(xmlImage); - - imt = new ImageMimeType("text/xml"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(xmlImage); - - imt = new ImageMimeType("image/emf"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(emfImage); - - Iterator iter = Service.providers(RegisterableImageProvider.class, true); - while (iter.hasNext()) { - RegisterableImageProvider impl = (RegisterableImageProvider)iter.next(); - imt = new ImageMimeType(impl.getSupportedMimeType()); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(new ImageProvider(impl.getName(), impl.getClassName())); - } - } - - /** - * Get the url string from a wrapped url. - * - * @param href the input wrapped url - * @return the raw url - */ - public static String getURL(String href) { - return URISpecification.getURL(href); - } - - /** - * Get the image from the cache or load. - * If this returns null then the image could not be loaded - * due to an error. Messages should be logged. - * Before calling this the getURL(url) must be used. - * - * @param url the url for the image - * @param context the user agent context - * @return the fop image instance - */ - public FopImage getImage(String url, FOUserAgent context) { - return cache.getImage(url, context); - } - - /** - * Release an image from the cache. - * This can be used if the renderer has its own cache of - * the image. - * The image should then be put into the weak cache. - * - * @param url the url for the image - * @param context the user agent context - */ - public void releaseImage(String url, FOUserAgent context) { - cache.releaseImage(url, context); - } - - /** - * Release the context and all images in the context. - * - * @param context the context to remove - */ - public void removeContext(FOUserAgent context) { - cache.removeContext(context); - } - - /** - * Create an FopImage objects. - * @param href the url for the image - * @param ua the user agent context - * @return the fop image instance - */ - public FopImage loadImage(String href, FOUserAgent ua) { - - Source source = ua.resolveURI(href); - if (source == null) { - return null; - } - - // Got a valid source, obtain an InputStream from it - InputStream in = null; - if (source instanceof StreamSource) { - in = ((StreamSource)source).getInputStream(); - } - if (in == null) { - try { - in = new java.net.URL(source.getSystemId()).openStream(); - } catch (Exception ex) { - log.error("Unable to obtain stream from id '" - + source.getSystemId() + "'"); - } - } - if (in == null) { - return null; - } - - //Make sure the InputStream is decorated with a BufferedInputStream - if (!(in instanceof java.io.BufferedInputStream)) { - in = new java.io.BufferedInputStream(in); - } - - // Check image type - FopImage.ImageInfo imgInfo = null; - try { - imgInfo = ImageReaderFactory.make(source.getSystemId(), in, ua); - } catch (Exception e) { - log.error("Error while recovering image information (" - + href + ") : " + e.getMessage(), e); - return null; - } - if (imgInfo == null) { - try { - in.close(); - in = null; - } catch (Exception e) { - log.debug("Error closing the InputStream for the image", e); - } - log.error("No ImageReader for this type of image (" + href + ")"); - return null; - } - // Associate mime-type to FopImage class - String imgMimeType = imgInfo.mimeType; - Class imageClass = getImageClass(imgMimeType); - if (imageClass == null) { - log.error("Unsupported image type (" + href + "): " + imgMimeType); - return null; - } else { - if (log.isDebugEnabled()) { - log.debug("Loading " + imgMimeType + " with " + imageClass.getName() - + ": " + href); - } - } - - // load the right image class - // return new <FopImage implementing class> - Object imageInstance = null; - try { - Class[] imageConstructorParameters = new Class[1]; - imageConstructorParameters[0] = org.apache.fop.image.FopImage.ImageInfo.class; - Constructor imageConstructor = imageClass.getDeclaredConstructor( - imageConstructorParameters); - Object[] initArgs = new Object[1]; - initArgs[0] = imgInfo; - imageInstance = imageConstructor.newInstance(initArgs); - } catch (java.lang.reflect.InvocationTargetException ex) { - Throwable t = ex.getTargetException(); - String msg; - if (t != null) { - msg = t.getMessage(); - } else { - msg = ex.getMessage(); - } - log.error("Error creating FopImage object (" - + href + "): " + msg, (t == null) ? ex : t); - return null; - } catch (InstantiationException ie) { - log.error("Error creating FopImage object (" - + href + "): Could not instantiate " + imageClass.getName() + " instance"); - return null; - } catch (Exception ex) { - log.error("Error creating FopImage object (" - + href + "): " + ex.getMessage(), ex); - return null; - } - if (!(imageInstance instanceof org.apache.fop.image.FopImage)) { - log.error("Error creating FopImage object (" + href + "): " + "class " - + imageClass.getName() - + " doesn't implement org.apache.fop.image.FopImage interface"); - return null; - } - return (FopImage) imageInstance; - } - - private Class getImageClass(String imgMimeType) { - ImageMimeType imt = (ImageMimeType)imageMimeTypes.get(imgMimeType); - if (imt == null) { - return null; - } - return imt.getFirstImplementingClass(); - } - - /** - * Forces all the image caches to be cleared. This should normally only be used in - * testing environments. If you happen to think that you need to call this yourself - * in a production environment, please notify the development team so we can look - * into the issue. A call like this shouldn't be necessary anymore like it may have - * been with FOP 0.20.5. - */ - public void clearCaches() { - cache.clearAll(); - } -} - -/** - * Basic image cache. - * This keeps track of invalid images. - */ -class BasicImageCache implements ImageCache { - - private Set invalid = Collections.synchronizedSet(new java.util.HashSet()); - //private Map contextStore = Collections.synchronizedMap(new java.util.HashMap()); - - public FopImage getImage(String url, FOUserAgent context) { - if (invalid.contains(url)) { - return null; - } - //TODO Doesn't seem to be fully implemented. Do we need it at all? Not referenced. - return null; - } - - public void releaseImage(String url, FOUserAgent context) { - // do nothing - } - - public void invalidateImage(String url, FOUserAgent context) { - // cap size of invalid list - if (invalid.size() > 100) { - invalid.clear(); - } - invalid.add(url); - } - - public void removeContext(FOUserAgent context) { - // do nothing - } - - /** {@inheritDoc} */ - public void clearAll() { - invalid.clear(); - } - -} - -/** - * This is the context image cache. - * This caches images on the basis of the given context. - * Common images in different contexts are currently not handled. - * There are two possiblities, each context handles its own images - * and renderers can cache information or images are shared and - * all information is retained. - * Once a context is removed then all images are placed into a - * weak hashmap so they may be garbage collected. - */ -class ContextImageCache implements ImageCache { - - // if this cache is collective then images can be shared - // among contexts, this implies that the base directory - // is either the same or does not effect the images being - // loaded - private boolean collective; - private Map contextStore = Collections.synchronizedMap(new java.util.HashMap()); - private Set invalid = null; - private Map refStore = null; - private ReferenceQueue refQueue = new ReferenceQueue(); - - public ContextImageCache(boolean col) { - collective = col; - if (collective) { - refStore = Collections.synchronizedMap(new java.util.HashMap()); - invalid = Collections.synchronizedSet(new java.util.HashSet()); - } - } - - // sync around lookups and puts - // another sync around load for a particular image - public FopImage getImage(String url, FOUserAgent context) { - ImageLoader im = null; - // this protects the finding or creating of a new - // ImageLoader for multi threads - synchronized (this) { - if (collective && invalid.contains(url)) { - return null; - } - Context con = (Context) contextStore.get(context); - if (con == null) { - con = new Context(context, collective); - contextStore.put(context, con); - } else { - if (con.invalid(url)) { - return null; - } - im = con.getImage(url); - } - if (im == null && collective) { - Iterator i = contextStore.values().iterator(); - while (i.hasNext()) { - Context c = (Context)i.next(); - if (c != con) { - im = c.getImage(url); - if (im != null) { - break; - } - } - } - if (im == null) { - Reference ref = (Reference)refStore.get(url); - if (ref != null) { - im = (ImageLoader) ref.get(); - if (im == null) { - //Remove key if its value has been garbage collected - refStore.remove(url); - } - } - } - } - - if (im != null) { - con.putImage(url, im); - } else { - im = con.getImage(url, this); - } - } - - // the ImageLoader is synchronized so images with the - // same url will not be loaded at the same time - if (im != null) { - return im.loadImage(); - } - return null; - } - - public void releaseImage(String url, FOUserAgent context) { - Context con = (Context) contextStore.get(context); - if (con != null) { - if (collective) { - ImageLoader im = con.getImage(url); - refStore.put(url, wrapInReference(im, url)); - } - con.releaseImage(url); - } - } - - public void invalidateImage(String url, FOUserAgent context) { - if (collective) { - // cap size of invalid list - if (invalid.size() > 100) { - invalid.clear(); - } - invalid.add(url); - } - Context con = (Context) contextStore.get(context); - if (con != null) { - con.invalidateImage(url); - } - } - - private Reference wrapInReference(Object obj, Object key) { - return new SoftReferenceWithKey(obj, key, refQueue); - } - - private static class SoftReferenceWithKey extends SoftReference { - - private Object key; - - public SoftReferenceWithKey(Object referent, Object key, ReferenceQueue q) { - super(referent, q); - this.key = key; - } - } - - public void removeContext(FOUserAgent context) { - Context con = (Context) contextStore.get(context); - if (con != null) { - if (collective) { - Map images = con.getImages(); - Iterator iter = images.entrySet().iterator(); - while (iter.hasNext()) { - Entry entry = (Entry)iter.next(); - refStore.put(entry.getKey(), - wrapInReference(entry.getValue(), entry.getKey())); - } - } - contextStore.remove(context); - } - //House-keeping (remove cleared references) - checkReferenceQueue(); - } - - /** - * Checks the reference queue if any references have been cleared and removes them from the - * cache. - */ - private void checkReferenceQueue() { - SoftReferenceWithKey ref; - while ((ref = (SoftReferenceWithKey)refQueue.poll()) != null) { - refStore.remove(ref.key); - } - } - - class Context { - private Map images = Collections.synchronizedMap(new java.util.HashMap()); - private Set invalid = null; - private FOUserAgent userAgent; - - public Context(FOUserAgent ua, boolean inv) { - userAgent = ua; - if (inv) { - invalid = Collections.synchronizedSet(new java.util.HashSet()); - } - } - - public ImageLoader getImage(String url, ImageCache c) { - if (images.containsKey(url)) { - return (ImageLoader) images.get(url); - } - ImageLoader loader = new ImageLoader(url, c, userAgent); - images.put(url, loader); - return loader; - } - - public void putImage(String url, ImageLoader image) { - images.put(url, image); - } - - public ImageLoader getImage(String url) { - return (ImageLoader) images.get(url); - } - - public void releaseImage(String url) { - images.remove(url); - } - - public Map getImages() { - return images; - } - - public void invalidateImage(String url) { - invalid.add(url); - } - - public boolean invalid(String url) { - return invalid.contains(url); - } - - } - - /** {@inheritDoc} */ - public void clearAll() { - this.refStore.clear(); - this.invalid.clear(); - //The context-sensitive caches are not cleared so there are no negative side-effects - //in a multi-threaded environment. Not that it's a good idea to use this method at - //all except in testing environments. If such a calls is necessary in normal environments - //we need to check on memory leaks! - } - -} - -/** - * Encapsulates a class of type FopImage by holding its class name. - * This allows dynamic loading of the class at runtime. - */ -class ImageProvider { - - private String name = null; - - private String className = null; - - private boolean checked = false; - - private Class clazz = null; - - /** - * Creates an ImageProvider with a given name and implementing class. - * The class name should refer to a class of type {@link FopImage}. - * However, this is not checked on construction. - * @param name The name of the provider - * @param className The full class name of the class implementing this provider - */ - public ImageProvider(String name, String className) { - setName(name); - setClassName(className); - } - - /** - * Returns the provider name. - * @return The provider name - */ - public String getName() { - return name; - } - - private void setName(String name) { - this.name = name; - } - - /** - * Returns the implementing class name. - * @return The implementing class name - */ - public String getClassName() { - return className; - } - - private void setClassName(String className) { - this.className = className; - } - - /** - * Returns the implementing class as a {@link Class} object. - * @return The implementing class or null if it couldn't be loaded. - */ - public Class getImplementingClass() { - if (!checked) { - try { - clazz = Class.forName(getClassName()); - } catch (ClassNotFoundException cnfe) { - //nop - } catch (LinkageError le) { - // This can happen if fop was build with support for a - // particular provider (e.g. a binary fop distribution) - // but the required support files (e.g. jai, jimi) are not - // available in the current runtime environment. - ImageFactory.log.debug("Image support provider " + getName() - + " could not be loaded. If " + getName() + " should be" - + " available please make sure all required external libraries" - + " are on the classpath."); - } - checked = true; - } - return clazz; - } -} - -/** - * Holds a mime type for a particular image format plus a list of - * {@link ImageProvider} objects which support the particular image format. - */ -class ImageMimeType { - - private String mimeType = null; - - private List providers = null; - - /** - * Constructor for a particular mime type. - * @param mimeType The mime type - */ - public ImageMimeType(String mimeType) { - setMimeType(mimeType); - } - - /** - * Returns the mime type. - * @return The mime type - */ - public String getMimeType() { - return mimeType; - } - - private void setMimeType(String mimeType) { - this.mimeType = mimeType; - } - - /** - * Returns the class from the first available provider. - * @return The first available class or null if none can be found - */ - public Class getFirstImplementingClass() { - if (providers == null) { - return null; - } - for (Iterator it = providers.iterator(); it.hasNext();) { - ImageProvider ip = (ImageProvider)it.next(); - Class clazz = ip.getImplementingClass(); - if (clazz != null) { - return clazz; - } - } - return null; - } - - /** - * Adds a new provider. - * The provider is added to the end of the current provider list. - * @param The new provider to add - */ - public void addProvider(ImageProvider provider) { - if (providers == null) { - providers = new ArrayList(4); // Assume we only have a few providers - } - if (!providers.contains(provider)) { - providers.add(provider); - } - } -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/image/ImageLoader.java b/src/java/org/apache/fop/image/ImageLoader.java deleted file mode 100644 index 111ef919f..000000000 --- a/src/java/org/apache/fop/image/ImageLoader.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.image; - -import org.apache.fop.apps.FOUserAgent; - -/** - * Class to load images. - */ -class ImageLoader { - - private String url; - private ImageCache cache; - private boolean valid = true; - private FOUserAgent userAgent; - private FopImage image = null; - - /** - * Main constructor. - * @param url URL to the image - * @param cache Image cache - * @param ua User agent - */ - public ImageLoader(String url, ImageCache cache, FOUserAgent ua) { - this.url = url; - this.cache = cache; - this.userAgent = ua; - } - - /** - * Loads the image. - * @return the loaded image - */ - public synchronized FopImage loadImage() { - if (!valid || image != null) { - return image; - } - ImageFactory imageFactory = userAgent.getFactory().getImageFactory(); - image = imageFactory.loadImage(url, userAgent); - if (image == null) { - cache.invalidateImage(url, userAgent); - valid = false; - } - return image; - } - -} diff --git a/src/java/org/apache/fop/image/JAIImage.java b/src/java/org/apache/fop/image/JAIImage.java deleted file mode 100644 index 8b3074052..000000000 --- a/src/java/org/apache/fop/image/JAIImage.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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.image; - -// AWT -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.image.BufferedImage; -import java.awt.Color; - -// JAI -import javax.media.jai.JAI; -import javax.media.jai.RenderedOp; - -import org.apache.commons.io.IOUtils; -// Sun codec -import com.sun.media.jai.codec.FileCacheSeekableStream; - -/** - * FopImage object using JAI. - * - * @see AbstractFopImage - * @see FopImage - */ -public class JAIImage extends AbstractFopImage { - - /** - * Create a new JAI image. - * - * @param imgInfo the image info for this JAI image - */ - public JAIImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * {@inheritDoc} - */ - protected boolean loadDimensions() { - if (this.bitmaps == null) { - loadImage(); - } - return this.bitmaps != null; - } - - /** - * {@inheritDoc} - */ - protected boolean loadBitmap() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.bitmaps != null; - } - - /** - * Loads the image from the inputstream - */ - protected void loadImage() { - com.sun.media.jai.codec.FileCacheSeekableStream seekableInput = null; - RenderedOp imageOp = null; - try { - seekableInput = new FileCacheSeekableStream(inputStream); - imageOp = JAI.create("stream", seekableInput); - - this.height = imageOp.getHeight(); - this.width = imageOp.getWidth(); - - ColorModel cm = imageOp.getColorModel(); - //this.bitsPerPixel = 8; - this.bitsPerPixel = cm.getPixelSize(); - - // TODO: the getRGB() function converts the image into the RGB - // colorspace. However, here we assume the image colorspace is kept. - // It should be either one of them, but not both. Unfortunately - // there are other hacks for images in the CMYK colorspace (e.g. in - // the PDF output) that would need to be changed as well. - - //this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); - this.colorSpace = cm.getColorSpace(); - - BufferedImage imageData = imageOp.getAsBufferedImage(); - int[] tmpMap = imageData.getRGB(0, 0, this.width, - this.height, null, 0, this.width); - - if (cm.hasAlpha()) { - // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT - int transparencyType = cm.getTransparency(); - - if (transparencyType == java.awt.Transparency.OPAQUE) { - this.isTransparent = false; - } else if (transparencyType == java.awt.Transparency.BITMASK) { - if (cm instanceof IndexColorModel) { - this.isTransparent = false; - byte[] alphas = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] reds = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] greens = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] blues = new byte[ - ((IndexColorModel) cm).getMapSize()]; - ((IndexColorModel) cm).getAlphas(alphas); - ((IndexColorModel) cm).getReds(reds); - ((IndexColorModel) cm).getGreens(greens); - ((IndexColorModel) cm).getBlues(blues); - for (int i = 0; - i < ((IndexColorModel) cm).getMapSize(); - i++) { - if ((alphas[i] & 0xFF) == 0) { - this.isTransparent = true; - this.transparentColor = new Color( - (int)(reds[i] & 0xFF), - (int)(greens[i] & 0xFF), - (int)(blues[i] & 0xFF)); - break; - } - } - } else { - // TRANSLUCENT - /* - * this.isTransparent = false; - * for (int i = 0; i < this.width * this.height; i++) { - * if (cm.getAlpha(tmpMap[i]) == 0) { - * this.isTransparent = true; - * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]), - * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i])); - * break; - * } - * } - * // or use special API... - */ - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - for (int i = 0; i < this.height; i++) { - for (int j = 0; j < this.width; j++) { - int p = tmpMap[i * this.width + j]; - int r = (p >> 16) & 0xFF; - int g = (p >> 8) & 0xFF; - int b = (p) & 0xFF; - this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF); - } - } - - } catch (Exception ex) { - log.error("Error while loading image (JAI): " + ex.getMessage(), ex); - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - if (imageOp != null) { - imageOp.dispose(); - } - if (seekableInput != null) { - IOUtils.closeQuietly(seekableInput); - } - } - } - - /** {@inheritDoc} */ - protected boolean loadOriginalData() { - return loadDefaultOriginalData(); - } - -} - diff --git a/src/java/org/apache/fop/image/JimiImage.java b/src/java/org/apache/fop/image/JimiImage.java deleted file mode 100644 index 49fb0b2e0..000000000 --- a/src/java/org/apache/fop/image/JimiImage.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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.image; - -// Java -import java.awt.image.ImageProducer; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.color.ColorSpace; -import java.awt.Color; - -import org.apache.commons.io.IOUtils; - -// Jimi -import com.sun.jimi.core.Jimi; - -/** - * FopImage object for several images types, using Jimi. - * See Jimi documentation for supported image types. - * - * @see AbstractFopImage - * @see FopImage - */ -public class JimiImage extends AbstractFopImage { - - /** - * Create a new Jimi image. - * - * @param imgInfo the image info for this Jimi image - */ - public JimiImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * {@inheritDoc} - */ - protected boolean loadDimensions() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.bitmaps != null; - } - - /** - * {@inheritDoc} - */ - protected boolean loadBitmap() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.bitmaps != null; - } - - /** - * Loads the image from the inputstream - */ - protected void loadImage() { - int[] tmpMap = null; - try { - ImageProducer ip = Jimi.getImageProducer(inputStream, - Jimi.SYNCHRONOUS | Jimi.IN_MEMORY); - FopImageConsumer consumer = new FopImageConsumer(ip); - ip.startProduction(consumer); - - while (!consumer.isImageReady()) { - Thread.sleep(500); - } - this.height = consumer.getHeight(); - this.width = consumer.getWidth(); - - try { - tmpMap = consumer.getImage(); - } catch (Exception ex) { - log.error("Image grabbing interrupted", ex); - return; - } - - ColorModel cm = consumer.getColorModel(); - this.bitsPerPixel = 8; - // this.bitsPerPixel = cm.getPixelSize(); - this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); - if (cm.hasAlpha()) { - // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT - int transparencyType = cm.getTransparency(); - if (transparencyType == java.awt.Transparency.OPAQUE) { - this.isTransparent = false; - } else if (transparencyType == java.awt.Transparency.BITMASK) { - if (cm instanceof IndexColorModel) { - this.isTransparent = false; - byte[] alphas = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] reds = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] greens = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] blues = new byte[ - ((IndexColorModel) cm).getMapSize()]; - ((IndexColorModel) cm).getAlphas(alphas); - ((IndexColorModel) cm).getReds(reds); - ((IndexColorModel) cm).getGreens(greens); - ((IndexColorModel) cm).getBlues(blues); - for (int i = 0; - i < ((IndexColorModel) cm).getMapSize(); - i++) { - if ((alphas[i] & 0xFF) == 0) { - this.isTransparent = true; - this.transparentColor = new Color( - (int)(reds[i] & 0xFF), - (int)(greens[i] & 0xFF), - (int)(blues[i] & 0xFF)); - break; - } - } - } else { - // TRANSLUCENT - /* - * this.isTransparent = false; - * for (int i = 0; i < this.width * this.height; i++) { - * if (cm.getAlpha(tmpMap[i]) == 0) { - * this.isTransparent = true; - * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]), - * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i])); - * break; - * } - * } - */ - // use special API... - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } catch (Throwable ex) { - log.error("Error while loading image (Jimi): " + ex.getMessage(), ex); - return; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - for (int i = 0; i < this.height; i++) { - for (int j = 0; j < this.width; j++) { - int p = tmpMap[i * this.width + j]; - int r = (p >> 16) & 0xFF; - int g = (p >> 8) & 0xFF; - int b = (p) & 0xFF; - this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF); - } - } - } - - /** {@inheritDoc} */ - protected boolean loadOriginalData() { - return loadDefaultOriginalData(); - } - -} - diff --git a/src/java/org/apache/fop/image/JpegImage.java b/src/java/org/apache/fop/image/JpegImage.java deleted file mode 100644 index 1de6b0d48..000000000 --- a/src/java/org/apache/fop/image/JpegImage.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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.image; - -import java.awt.color.ColorSpace; -import java.awt.color.ICC_Profile; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.fop.util.CMYKColorSpace; - -/** - * FopImage object for JPEG images, Using Java native classes. - * - * @see AbstractFopImage - * @see FopImage - */ -public class JpegImage extends AbstractFopImage { - private ICC_Profile iccProfile = null; - private boolean foundICCProfile = false; - private boolean hasAPPEMarker = false; - - /** - * Create a jpeg image with the info. - * - * @param imgInfo the image info for this jpeg - */ - public JpegImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * Load the original jpeg data. - * This loads the original jpeg data and reads the color space, - * and icc profile if any. - * - * @return true if loaded false for any error - */ - protected boolean loadOriginalData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ByteArrayOutputStream iccStream = null; - int index = 0; - boolean cont = true; - - try { - byte[] readBuf = new byte[4096]; - int bytesRead; - while ((bytesRead = inputStream.read(readBuf)) != -1) { - baos.write(readBuf, 0, bytesRead); - } - } catch (java.io.IOException ex) { - log.error("Error while loading image (Jpeg): " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - this.raw = baos.toByteArray(); - this.bitsPerPixel = 8; - this.isTransparent = false; - - //Check for SOI (Start of image) marker (FFD8) - if (this.raw.length > (index + 2) - && uByte(this.raw[index]) == 255 /*0xFF*/ - && uByte(this.raw[index + 1]) == 216 /*0xD8*/) { - index += 2; - - while (index < this.raw.length && cont) { - //check to be sure this is the begining of a header - if (this.raw.length > (index + 2) - && uByte(this.raw[index]) == 255 /*0xFF*/) { - - //192 or 194 are the header bytes that contain - // the jpeg width height and color depth. - if (uByte(this.raw[index + 1]) == 192 /*0xC0*/ - || uByte(this.raw[index + 1]) == 194 /*0xC2*/) { - - this.height = calcBytes(this.raw[index + 5], - this.raw[index + 6]); - this.width = calcBytes(this.raw[index + 7], - this.raw[index + 8]); - - int numComponents = this.raw[index + 9]; - if (numComponents == 1) { - this.colorSpace = ColorSpace.getInstance( - ColorSpace.CS_GRAY); - } else if (numComponents == 3) { - this.colorSpace = ColorSpace.getInstance( - ColorSpace.CS_LINEAR_RGB); - } else if (numComponents == 4) { - // howto create CMYK color space - /* - this.colorSpace = ColorSpace.getInstance( - ColorSpace.CS_CIEXYZ); - */ - this.colorSpace = CMYKColorSpace.getInstance(); - } else { - log.error("Unknown ColorSpace for image: " - + ""); - return false; - } - - if (foundICCProfile) { - cont = false; - break; - } - index += calcBytes(this.raw[index + 2], - this.raw[index + 3]) + 2; - - } else if (uByte(this.raw[index + 1]) == 226 /*0xE2*/ - && this.raw.length > (index + 60)) { - // Check if ICC profile - byte[] iccString = new byte[11]; - System.arraycopy(this.raw, index + 4, - iccString, 0, 11); - - if ("ICC_PROFILE".equals(new String(iccString))) { - int chunkSize = calcBytes( - this.raw[index + 2], - this.raw[index + 3]) + 2; - - if (iccStream == null) { - iccStream = new ByteArrayOutputStream(); - } - iccStream.write(this.raw, - index + 18, chunkSize - 18); - - } - - index += calcBytes(this.raw[index + 2], - this.raw[index + 3]) + 2; - // Check for Adobe APPE Marker - } else if ((uByte(this.raw[index]) == 0xff - && uByte(this.raw[index + 1]) == 0xee - && uByte(this.raw[index + 2]) == 0 - && uByte(this.raw[index + 3]) == 14 - && "Adobe".equals(new String(this.raw, index + 4, 5)))) { - // The reason for reading the APPE marker is that Adobe Photoshop - // generates CMYK JPEGs with inverted values. The correct thing - // to do would be to interpret the values in the marker, but for now - // only assume that if APPE marker is present and colorspace is CMYK, - // the image is inverted. - hasAPPEMarker = true; - - index += calcBytes(this.raw[index + 2], - this.raw[index + 3]) + 2; - } else { - index += calcBytes(this.raw[index + 2], - this.raw[index + 3]) + 2; - } - - } else { - cont = false; - } - } - } else { - log.error("Error while loading " - + "JpegImage - Invalid JPEG Header."); - return false; - } - if (iccStream != null && iccStream.size() > 0) { - int padding = (8 - (iccStream.size() % 8)) % 8; - if (padding != 0) { - try { - iccStream.write(new byte[padding]); - } catch (Exception ex) { - log.error("Error while aligning ICC stream: " + ex.getMessage(), ex); - return false; - } - } - try { - iccProfile = ICC_Profile.getInstance(iccStream.toByteArray()); - } catch (IllegalArgumentException iae) { - log.warn("An ICC profile is present but it is invalid (" - + iae.getMessage() + "). The color profile will be ignored. (" - + this.getOriginalURI() + ")"); - } - if (iccProfile.getNumComponents() != this.colorSpace.getNumComponents()) { - log.warn("The number of components of the ICC profile (" - + iccProfile.getNumComponents() - + ") doesn't match the image (" - + this.colorSpace.getNumComponents() - + "). Ignoring the ICC color profile."); - this.iccProfile = null; - } - } else if (this.colorSpace == null) { - log.error("ColorSpace not specified for JPEG image"); - return false; - } - if (hasAPPEMarker && this.colorSpace.getType() == ColorSpace.TYPE_CMYK) { - if (log.isDebugEnabled()) { - log.debug("JPEG has an Adobe APPE marker. Note: CMYK Image will be inverted. (" - + this.getOriginalURI() + ")"); - } - this.invertImage = true; - } - return true; - } - - /** - * Get the ICC profile for this Jpeg image. - * - * @return the icc profile or null if not found - */ - public ICC_Profile getICCProfile() { - return iccProfile; - } - - private int calcBytes(byte bOne, byte bTwo) { - return (uByte(bOne) * 256) + uByte(bTwo); - } - - private int uByte(byte bIn) { - if (bIn < 0) { - return 256 + bIn; - } else { - return bIn; - } - } -} - diff --git a/src/java/org/apache/fop/image/PNGImage.java b/src/java/org/apache/fop/image/PNGImage.java deleted file mode 100644 index c83d491f0..000000000 --- a/src/java/org/apache/fop/image/PNGImage.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.image; - -import java.io.IOException; - -import org.apache.xmlgraphics.image.codec.png.PNGRed; -import org.apache.xmlgraphics.image.codec.png.PNGDecodeParam; -import org.apache.xmlgraphics.image.codec.util.SeekableStream; -import org.apache.xmlgraphics.image.rendered.CachableRed; -import org.apache.commons.io.IOUtils; - -/** - * FopImage object using PNG - * - * @see AbstractFopImage - * @see FopImage - */ -public class PNGImage extends XmlGraphicsCommonsImage { - - /** - * Constructs a new PNGImage instance. - * @param imgReader basic metadata for the image - */ - public PNGImage(FopImage.ImageInfo imgReader) { - super(imgReader); - this.loaded = 0; //TODO The PNGReader cannot read the resolution, yet. - } - - /** - * {@inheritDoc} - */ - protected CachableRed decodeImage(SeekableStream stream) throws IOException { - PNGDecodeParam param = new PNGDecodeParam(); - param.setPerformGammaCorrection(true); - param.setDisplayExponent(2.2f); // sRGB gamma - PNGRed red = new PNGRed(stream, param); - String unit = (String)red.getProperty("pixel_units"); - if ("Meters".equals(unit)) { - this.dpiHorizontal = ((Integer)red.getProperty("x_pixels_per_unit")).intValue() - * 25.4f / 1000f; - this.dpiVertical = ((Integer)red.getProperty("y_pixels_per_unit")).intValue() - * 25.4f / 1000f; - } - return red; - } - - /** - * Load the original PNG data. - * This loads the original PNG data as is into memory. - * - * @return true if loaded false for any error - */ - protected boolean loadOriginalData() { - try { - seekableInput.seek(0); - this.raw = IOUtils.toByteArray(seekableInput); - - } catch (java.io.IOException ex) { - log.error("Error while loading raw image: " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - return true; - } - -} diff --git a/src/java/org/apache/fop/image/TIFFImage.java b/src/java/org/apache/fop/image/TIFFImage.java deleted file mode 100644 index d9a9fc022..000000000 --- a/src/java/org/apache/fop/image/TIFFImage.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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.image; - -import java.awt.color.ColorSpace; -import java.io.IOException; - -import org.apache.xmlgraphics.image.codec.util.SeekableStream; -import org.apache.xmlgraphics.image.codec.tiff.TIFFDirectory; -import org.apache.xmlgraphics.image.codec.tiff.TIFFField; -import org.apache.xmlgraphics.image.codec.tiff.TIFFImageDecoder; -import org.apache.xmlgraphics.image.rendered.CachableRed; -import org.apache.commons.io.IOUtils; - -/** - * TIFF implementation using the Batik codecs. - */ -public class TIFFImage extends XmlGraphicsCommonsImage { - - private int compression = 0; - private int stripCount = 0; - private long stripOffset = 0; - private long stripLength = 0; - private int fillOrder = 1; - - /** - * Constructs a new BatikImage instance. - * @param imgReader basic metadata for the image - */ - public TIFFImage(FopImage.ImageInfo imgReader) { - super(imgReader); - } - - /** - * The compression type set in the TIFF directory - * @return the TIFF compression type - */ - public int getCompression() { - return compression; - } - - /** - * The number of strips in the image - * @return the number of strips in the image - */ - public int getStripCount() { - return stripCount; - } - - /** - * {@inheritDoc} - * org.apache.xmlgraphics.image.codec.util.SeekableStream) - */ - protected CachableRed decodeImage(SeekableStream stream) throws IOException { - org.apache.xmlgraphics.image.codec.tiff.TIFFImage img - = new org.apache.xmlgraphics.image.codec.tiff.TIFFImage - (stream, null, 0); - TIFFDirectory dir = (TIFFDirectory)img.getProperty("tiff_directory"); - TIFFField fld = dir.getField(TIFFImageDecoder.TIFF_RESOLUTION_UNIT); - int resUnit = fld.getAsInt(0); - fld = dir.getField(TIFFImageDecoder.TIFF_X_RESOLUTION); - double xRes = fld.getAsDouble(0); - fld = dir.getField(TIFFImageDecoder.TIFF_Y_RESOLUTION); - double yRes = fld.getAsDouble(0); - switch (resUnit) { - case 2: //inch - this.dpiHorizontal = xRes; - this.dpiVertical = yRes; - break; - case 3: //cm - this.dpiHorizontal = xRes * 2.54f; - this.dpiVertical = yRes * 2.54f; - break; - default: - //ignored - log.warn("Cannot determine bitmap resolution." - + " Unimplemented resolution unit: " + resUnit); - } - fld = dir.getField(TIFFImageDecoder.TIFF_COMPRESSION); - if (fld != null) { - compression = fld.getAsInt(0); - } - fld = dir.getField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE); - if (fld != null) { - bitsPerPixel = fld.getAsInt(0); - } - fld = dir.getField(TIFFImageDecoder.TIFF_ROWS_PER_STRIP); - if (fld == null) { - stripCount = 1; - } else { - stripCount = (int)(dir.getFieldAsLong(TIFFImageDecoder.TIFF_IMAGE_LENGTH) - / fld.getAsLong(0)); - } - - fld = dir.getField(TIFFImageDecoder.TIFF_FILL_ORDER); - if (fld != null) { - fillOrder = fld.getAsInt(0); - } - - stripOffset = dir.getField(TIFFImageDecoder.TIFF_STRIP_OFFSETS).getAsLong(0); - stripLength = dir.getField(TIFFImageDecoder.TIFF_STRIP_BYTE_COUNTS).getAsLong(0); - - if (this.bitsPerPixel == 1) { - this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY); - } - return img; - } - - /** - * Load the original TIFF data. - * This loads only strip 1 of the original TIFF data. - * - * @return true if loaded false for any error - * {@inheritDoc} - */ - protected boolean loadOriginalData() { - if (loadDimensions()) { - byte[] readBuf = new byte[(int)stripLength]; - int bytesRead; - - try { - this.seekableInput.reset(); - this.seekableInput.skip(stripOffset); - bytesRead = seekableInput.read(readBuf); - if (bytesRead != stripLength) { - log.error("Error while loading image: length mismatch on read"); - return false; - } - - // need to invert bytes if fill order = 2 - if (fillOrder == 2) { - for (int i = 0; i < (int)stripLength; i++) { - readBuf[i] = flipTable[readBuf[i] & 0xff]; - } - } - this.raw = readBuf; - - return true; - } catch (IOException ioe) { - log.error("Error while loading image strip 1 (TIFF): ", ioe); - return false; - } finally { - IOUtils.closeQuietly(seekableInput); - IOUtils.closeQuietly(inputStream); - this.seekableInput = null; - this.inputStream = null; - this.cr = null; - } - } - return false; - } - - // Table to be used when fillOrder = 2, for flipping bytes. - // Copied from XML Graphics Commons' TIFFFaxDecoder class - private static byte[] flipTable = { - 0, -128, 64, -64, 32, -96, 96, -32, - 16, -112, 80, -48, 48, -80, 112, -16, - 8, -120, 72, -56, 40, -88, 104, -24, - 24, -104, 88, -40, 56, -72, 120, -8, - 4, -124, 68, -60, 36, -92, 100, -28, - 20, -108, 84, -44, 52, -76, 116, -12, - 12, -116, 76, -52, 44, -84, 108, -20, - 28, -100, 92, -36, 60, -68, 124, -4, - 2, -126, 66, -62, 34, -94, 98, -30, - 18, -110, 82, -46, 50, -78, 114, -14, - 10, -118, 74, -54, 42, -86, 106, -22, - 26, -102, 90, -38, 58, -70, 122, -6, - 6, -122, 70, -58, 38, -90, 102, -26, - 22, -106, 86, -42, 54, -74, 118, -10, - 14, -114, 78, -50, 46, -82, 110, -18, - 30, -98, 94, -34, 62, -66, 126, -2, - 1, -127, 65, -63, 33, -95, 97, -31, - 17, -111, 81, -47, 49, -79, 113, -15, - 9, -119, 73, -55, 41, -87, 105, -23, - 25, -103, 89, -39, 57, -71, 121, -7, - 5, -123, 69, -59, 37, -91, 101, -27, - 21, -107, 85, -43, 53, -75, 117, -11, - 13, -115, 77, -51, 45, -83, 109, -19, - 29, -99, 93, -35, 61, -67, 125, -3, - 3, -125, 67, -61, 35, -93, 99, -29, - 19, -109, 83, -45, 51, -77, 115, -13, - 11, -117, 75, -53, 43, -85, 107, -21, - 27, -101, 91, -37, 59, -69, 123, -5, - 7, -121, 71, -57, 39, -89, 103, -25, - 23, -105, 87, -41, 55, -73, 119, -9, - 15, -113, 79, -49, 47, -81, 111, -17, - 31, -97, 95, -33, 63, -65, 127, -1, - }; - // end -} diff --git a/src/java/org/apache/fop/image/XMLImage.java b/src/java/org/apache/fop/image/XMLImage.java deleted file mode 100644 index 261dc8494..000000000 --- a/src/java/org/apache/fop/image/XMLImage.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.image; - -// Java -import org.w3c.dom.Document; -import javax.xml.parsers.SAXParserFactory; - -/** - * This is an implementation for XML-based images such as SVG. - * - * @see AbstractFopImage - * @see FopImage - */ -public class XMLImage extends AbstractFopImage { - - private Document doc; - private String namespace = ""; - - /** - * @see org.apache.fop.image.AbstractFopImage#AbstractFopImage(FopImage.ImageInfo) - */ - public XMLImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - if (imgInfo.data instanceof Document) { - doc = (Document)imgInfo.data; - loaded = loaded | ORIGINAL_DATA; - } - namespace = imgInfo.str; - } - - /** - * Returns the fully qualified classname of an XML parser for - * Batik classes that apparently need it (error messages, perhaps) - * @return an XML parser classname - */ - public static String getParserName() { - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - return factory.newSAXParser().getXMLReader().getClass().getName(); - } catch (Exception e) { - return null; - } - } - - /** - * Returns the XML document as a DOM document. - * @return the DOM document - */ - public Document getDocument() { - return this.doc; - } - - /** - * Returns the namespace of the XML document. - * @return the namespace - */ - public String getNameSpace() { - return this.namespace; - } -} diff --git a/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java b/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java deleted file mode 100644 index 662673726..000000000 --- a/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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.image; - -import java.awt.Color; -import java.awt.Transparency; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.image.RenderedImage; -import java.awt.image.WritableRaster; -import java.awt.image.BufferedImage; -import java.io.IOException; - -import org.apache.xmlgraphics.image.GraphicsUtil; -import org.apache.xmlgraphics.image.codec.util.SeekableStream; -import org.apache.xmlgraphics.image.codec.util.MemoryCacheSeekableStream; -import org.apache.xmlgraphics.image.codec.util.FileCacheSeekableStream; -import org.apache.xmlgraphics.image.rendered.CachableRed; - -import org.apache.commons.io.IOUtils; - -/** - * Abstract FopImage implementation which uses the internal codecs from XML Graphics Commons. - * - * @see AbstractFopImage - * @see FopImage - */ -public abstract class XmlGraphicsCommonsImage extends AbstractFopImage { - - private byte[] softMask = null; - - /** - * The InputStream wrapped into a SeekableStream for decoding. - */ - protected SeekableStream seekableInput = null; - - /** - * The Batik representation of the image - */ - protected CachableRed cr = null; - - /** - * Constructs a new BatikImage instance. - * @param imgReader basic metadata for the image - */ - public XmlGraphicsCommonsImage(FopImage.ImageInfo imgReader) { - super(imgReader); - } - - /** - * {@inheritDoc} - */ - protected boolean loadDimensions() { - if (seekableInput == null && inputStream != null) { - try { - seekableInput = new FileCacheSeekableStream(inputStream); - } catch (IOException ioe) { - seekableInput = new MemoryCacheSeekableStream(inputStream); - } - try { - this.bitsPerPixel = 8; - cr = decodeImage(seekableInput); - this.height = cr.getHeight(); - this.width = cr.getWidth(); - this.isTransparent = false; - this.softMask = null; - ColorModel cm = cr.getColorModel(); - - this.height = cr.getHeight(); - this.width = cr.getWidth(); - this.isTransparent = false; - this.softMask = null; - - int transparencyType = cm.getTransparency(); - if (cm instanceof IndexColorModel) { - if (transparencyType == Transparency.BITMASK) { - // Use 'transparent color'. - IndexColorModel icm = (IndexColorModel)cm; - int numColor = icm.getMapSize(); - byte [] alpha = new byte[numColor]; - icm.getAlphas(alpha); - for (int i = 0; i < numColor; i++) { - if ((alpha[i] & 0xFF) == 0) { - this.isTransparent = true; - int red = (icm.getRed (i)) & 0xFF; - int grn = (icm.getGreen(i)) & 0xFF; - int blu = (icm.getBlue (i)) & 0xFF; - this.transparentColor = new Color(red, grn, blu); - break; - } - } - } - } else { - cr = GraphicsUtil.convertTosRGB(cr); - } - - // Get our current ColorModel - cm = cr.getColorModel(); - if (this.colorSpace == null) { - this.colorSpace = cm.getColorSpace(); - } - } catch (IOException ioe) { - log.error("Error while loading image (Batik): " + ioe.getMessage(), ioe); - IOUtils.closeQuietly(seekableInput); - IOUtils.closeQuietly(inputStream); - seekableInput = null; - inputStream = null; - return false; - } - } - return this.height != -1; - } - - /** - * {@inheritDoc} - */ - protected boolean loadBitmap() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.bitmaps != null; - } - - /** - * {@inheritDoc} - */ - public boolean hasSoftMask() { - if (this.bitmaps == null && this.raw == null) { - loadImage(); - } - - return (this.softMask != null); - } - - /** - * {@inheritDoc} - */ - public byte[] getSoftMask() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.softMask; - } - - /** - * Decodes the image from the stream. - * @param stream the stream to read the image from - * @return the decoded image - * @throws IOException in case an I/O problem occurs - */ - protected abstract CachableRed decodeImage(SeekableStream stream) throws IOException; - - /** - * Loads the image from the InputStream. - */ - protected void loadImage() { - if (loadDimensions()) { - try { - if (cr == null) { - throw new IllegalStateException( - "Can't load the bitmaps data without the CachableRed instance"); - } - - // Get our current ColorModel - ColorModel cm = cr.getColorModel(); - - // It has an alpha channel so generate a soft mask. - if (!this.isTransparent && cm.hasAlpha()) { - this.softMask = new byte[this.width * this.height]; - } - - this.bitmaps = new byte[this.width * this.height * 3]; - - constructBitmaps(cr, this.bitmaps, this.softMask); - } catch (Exception ex) { - log.error("Error while loading image (Batik): " + ex.getMessage(), ex); - } finally { - // Make sure we clean up - IOUtils.closeQuietly(seekableInput); - IOUtils.closeQuietly(inputStream); - seekableInput = null; - inputStream = null; - cr = null; - } - } - } - - private static void constructBitmaps(RenderedImage red, byte[] bitmaps, byte[] softMask) { - WritableRaster wr = (WritableRaster)red.getData(); - ColorModel cm = red.getColorModel(); - BufferedImage bi = new BufferedImage - (cm, wr.createWritableTranslatedChild(0, 0), - cm.isAlphaPremultiplied(), null); - int width = red.getWidth(); - int height = red.getHeight(); - int [] tmpMap = new int[width]; - int idx = 0; - int sfIdx = 0; - for (int y = 0; y < height; y++) { - tmpMap = bi.getRGB(0, y, width, 1, tmpMap, 0, width); - if (softMask != null) { - for (int x = 0; x < width; x++) { - int pix = tmpMap[x]; - softMask[sfIdx++] = (byte)(pix >>> 24); - bitmaps[idx++] = (byte)((pix >>> 16) & 0xFF); - bitmaps[idx++] = (byte)((pix >>> 8) & 0xFF); - bitmaps[idx++] = (byte)((pix) & 0xFF); - } - } else { - for (int x = 0; x < width; x++) { - int pix = tmpMap[x]; - bitmaps[idx++] = (byte)((pix >> 16) & 0xFF); - bitmaps[idx++] = (byte)((pix >> 8) & 0xFF); - bitmaps[idx++] = (byte)((pix) & 0xFF); - } - } - } - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/image/analyser/BMPReader.java b/src/java/org/apache/fop/image/analyser/BMPReader.java deleted file mode 100644 index caca6f3dd..000000000 --- a/src/java/org/apache/fop/image/analyser/BMPReader.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for BMP image type. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class BMPReader implements ImageReader { - - /** Length of the BMP header */ - protected static final int BMP_SIG_LENGTH = 46; - - /** offset to width */ - private static final int WIDTH_OFFSET = 18; - /** offset to height */ - private static final int HEIGHT_OFFSET = 22; - /** offset to horizontal res */ - private static final int HRES_OFFSET = 38; - /** offset to vertical res */ - private static final int VRES_OFFSET = 42; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported = ((header[0] == (byte) 0x42) - && (header[1] == (byte) 0x4d)); - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(header, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/bmp"; - } - - private void getDimension(byte[] header, FopImage.ImageInfo info) { - // little endian notation - int byte1 = header[WIDTH_OFFSET] & 0xff; - int byte2 = header[WIDTH_OFFSET + 1] & 0xff; - int byte3 = header[WIDTH_OFFSET + 2] & 0xff; - int byte4 = header[WIDTH_OFFSET + 3] & 0xff; - long l = (long) ((byte4 << 24) | (byte3 << 16) - | (byte2 << 8) | byte1); - info.width = (int) (l & 0xffffffff); - - byte1 = header[HEIGHT_OFFSET] & 0xff; - byte2 = header[HEIGHT_OFFSET + 1] & 0xff; - byte3 = header[HEIGHT_OFFSET + 2] & 0xff; - byte4 = header[HEIGHT_OFFSET + 3] & 0xff; - l = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - info.height = (int) (l & 0xffffffff); - - byte1 = header[HRES_OFFSET] & 0xff; - byte2 = header[HRES_OFFSET + 1] & 0xff; - byte3 = header[HRES_OFFSET + 2] & 0xff; - byte4 = header[HRES_OFFSET + 3] & 0xff; - l = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - if (l > 0) { - info.dpiHorizontal = l / 39.37d; - } - - byte1 = header[VRES_OFFSET] & 0xff; - byte2 = header[VRES_OFFSET + 1] & 0xff; - byte3 = header[VRES_OFFSET + 2] & 0xff; - byte4 = header[VRES_OFFSET + 3] & 0xff; - l = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - if (l > 0) { - info.dpiVertical = l / 39.37d; - } - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[BMP_SIG_LENGTH]; - try { - imageStream.mark(BMP_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - -} diff --git a/src/java/org/apache/fop/image/analyser/EMFReader.java b/src/java/org/apache/fop/image/analyser/EMFReader.java deleted file mode 100644 index d6e2f2975..000000000 --- a/src/java/org/apache/fop/image/analyser/EMFReader.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for EMF image type. - * - * @author Peter Herweg - */ -public class EMFReader implements ImageReader { - - /** Length of the EMF header */ - protected static final int EMF_SIG_LENGTH = 88; - - /** offset to signature */ - private static final int SIGNATURE_OFFSET = 40; - /** offset to width */ - private static final int WIDTH_OFFSET = 32; - /** offset to height */ - private static final int HEIGHT_OFFSET = 36; - /** offset to horizontal resolution in pixel */ - private static final int HRES_PIXEL_OFFSET = 72; - /** offset to vertical resolution in pixel */ - private static final int VRES_PIXEL_OFFSET = 76; - /** offset to horizontal resolution in mm */ - private static final int HRES_MM_OFFSET = 80; - /** offset to vertical resolution in mm */ - private static final int VRES_MM_OFFSET = 84; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported - = ( (header[SIGNATURE_OFFSET + 0] == (byte) 0x20) - && (header[SIGNATURE_OFFSET + 1] == (byte) 0x45) - && (header[SIGNATURE_OFFSET + 2] == (byte) 0x4D) - && (header[SIGNATURE_OFFSET + 3] == (byte) 0x46) ); - - if (supported) { - FopImage.ImageInfo info = getDimension(header); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/emf"; - } - - private FopImage.ImageInfo getDimension(byte[] header) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - long value = 0; - int byte1; - int byte2; - int byte3; - int byte4; - - // little endian notation - - //resolution - byte1 = header[HRES_MM_OFFSET] & 0xff; - byte2 = header[HRES_MM_OFFSET + 1] & 0xff; - byte3 = header[HRES_MM_OFFSET + 2] & 0xff; - byte4 = header[HRES_MM_OFFSET + 3] & 0xff; - long hresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - byte1 = header[VRES_MM_OFFSET] & 0xff; - byte2 = header[VRES_MM_OFFSET + 1] & 0xff; - byte3 = header[VRES_MM_OFFSET + 2] & 0xff; - byte4 = header[VRES_MM_OFFSET + 3] & 0xff; - long vresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - byte1 = header[HRES_PIXEL_OFFSET] & 0xff; - byte2 = header[HRES_PIXEL_OFFSET + 1] & 0xff; - byte3 = header[HRES_PIXEL_OFFSET + 2] & 0xff; - byte4 = header[HRES_PIXEL_OFFSET + 3] & 0xff; - long hresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - byte1 = header[VRES_PIXEL_OFFSET] & 0xff; - byte2 = header[VRES_PIXEL_OFFSET + 1] & 0xff; - byte3 = header[VRES_PIXEL_OFFSET + 2] & 0xff; - byte4 = header[VRES_PIXEL_OFFSET + 3] & 0xff; - long vresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - info.dpiHorizontal = hresPixel / (hresMM / 25.4f); - info.dpiVertical = vresPixel / (vresMM / 25.4f); - - //width - byte1 = header[WIDTH_OFFSET] & 0xff; - byte2 = header[WIDTH_OFFSET + 1] & 0xff; - byte3 = header[WIDTH_OFFSET + 2] & 0xff; - byte4 = header[WIDTH_OFFSET + 3] & 0xff; - value = (long) ((byte4 << 24) | (byte3 << 16) - | (byte2 << 8) | byte1); - value = Math.round(value / 100f / 25.4f * info.dpiHorizontal); - info.width = (int) (value & 0xffffffff); - - //height - byte1 = header[HEIGHT_OFFSET] & 0xff; - byte2 = header[HEIGHT_OFFSET + 1] & 0xff; - byte3 = header[HEIGHT_OFFSET + 2] & 0xff; - byte4 = header[HEIGHT_OFFSET + 3] & 0xff; - value = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - value = Math.round(value / 100f / 25.4f * info.dpiVertical); - info.height = (int) (value & 0xffffffff); - - return info; - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[EMF_SIG_LENGTH]; - try { - imageStream.mark(EMF_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } -} diff --git a/src/java/org/apache/fop/image/analyser/EPSReader.java b/src/java/org/apache/fop/image/analyser/EPSReader.java deleted file mode 100644 index 92260d1ab..000000000 --- a/src/java/org/apache/fop/image/analyser/EPSReader.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -// FOP -import org.apache.commons.io.IOUtils; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.EPSImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for EPS document image type. - * - * @version $Id$ - */ -public class EPSReader implements ImageReader { - - private static final byte[] EPS_HEADER_ASCII = "%!PS".getBytes(); - private static final byte[] BOUNDINGBOX = "%%BoundingBox: ".getBytes(); - //private static final byte[] HIRESBOUNDINGBOX = "%%HiResBoundingBox: ".getBytes(); - //TODO Implement HiResBoundingBox, ImageInfo probably needs some changes for that - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - - boolean isEPS = false; - - bis.mark(32); - byte[] header = new byte[30]; - bis.read(header, 0, 30); - bis.reset(); - - EPSImage.EPSData data = new EPSImage.EPSData(); - - // Check if binary header - if (getLong(header, 0) == 0xC6D3D0C5) { - data.isAscii = false; - isEPS = true; - - data.psStart = getLong(header, 4); - data.psLength = getLong(header, 8); - data.wmfStart = getLong(header, 12); - data.wmfLength = getLong(header, 16); - data.tiffStart = getLong(header, 20); - data.tiffLength = getLong(header, 24); - - } else { - // Check if plain ascii - byte[] epsh = "%!PS".getBytes(); - if (EPS_HEADER_ASCII[0] == header[0] - && EPS_HEADER_ASCII[1] == header[1] - && EPS_HEADER_ASCII[2] == header[2] - && EPS_HEADER_ASCII[3] == header[3]) { - data.isAscii = true; - isEPS = true; - } - } - - if (isEPS) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.data = data; - readEPSImage(bis, data); - data.bbox = readBBox(data); - - if (data.bbox != null) { - info.width = (int) (data.bbox[2] - data.bbox[0]); - info.height = (int) (data.bbox[3] - data.bbox[1]); - - // image data read - IOUtils.closeQuietly(bis); - info.inputStream = null; - - return info; - } else { - // Ain't eps if no BoundingBox - isEPS = false; - } - } - - return null; - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/eps"; - } - - private long getLong(byte[] buf, int idx) { - int b1 = buf[idx] & 0xff; - int b2 = buf[idx + 1] & 0xff; - int b3 = buf[idx + 2] & 0xff; - int b4 = buf[idx + 3] & 0xff; - - return (long) ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); - } - - /** - * Read the eps file and extract eps part. - * - * @param bis The InputStream - * @param data EPSData object to write the results to - * @exception IOException If an I/O error occurs - */ - private void readEPSImage(InputStream bis, EPSImage.EPSData data) - throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] file; - byte[] readBuf = new byte[20480]; - int bytesRead; - int index = 0; - boolean cont = true; - - try { - while ((bytesRead = bis.read(readBuf)) != -1) { - baos.write(readBuf, 0, bytesRead); - } - } catch (java.io.IOException ex) { - throw new IOException("Error while loading EPS image: " - + ex.getMessage()); - } - - file = baos.toByteArray(); - - if (data.isAscii) { - data.rawEps = null; - data.epsFile = new byte[file.length]; - System.arraycopy(file, 0, data.epsFile, 0, data.epsFile.length); - } else { - data.rawEps = new byte[file.length]; - data.epsFile = new byte[(int) data.psLength]; - System.arraycopy(file, 0, data.rawEps, 0, data.rawEps.length); - System.arraycopy(data.rawEps, (int) data.psStart, data.epsFile, 0, - (int) data.psLength); - } - } - - /** - * Get embedded TIFF preview or null. - * - * @param data The EPS payload - * @return The embedded preview - */ - public byte[] getPreview(EPSImage.EPSData data) { - if (data.preview == null) { - if (data.tiffLength > 0) { - data.preview = new byte[(int) data.tiffLength]; - System.arraycopy(data.rawEps, (int) data.tiffStart, data.preview, 0, - (int) data.tiffLength); - } - } - return data.preview; - } - - /** - * Extract bounding box from eps part. - * - * @param data The EPS payload - * @return An Array of four coordinates making up the bounding box - */ - private long[] readBBox(EPSImage.EPSData data) { - long[] mbbox = null; - int idx = 0; - boolean found = false; - - while (!found && (data.epsFile.length > (idx + BOUNDINGBOX.length))) { - boolean sfound = true; - int i = idx; - for (i = idx; sfound && (i - idx) < BOUNDINGBOX.length; i++) { - if (BOUNDINGBOX[i - idx] != data.epsFile[i]) { - sfound = false; - } - } - if (sfound) { - found = true; - idx = i; - } else { - idx++; - } - } - - if (!found) { - return mbbox; - } - - mbbox = new long[4]; - idx += readLongString(data, mbbox, 0, idx); - idx += readLongString(data, mbbox, 1, idx); - idx += readLongString(data, mbbox, 2, idx); - idx += readLongString(data, mbbox, 3, idx); - - return mbbox; - } - - private int readLongString(EPSImage.EPSData data, long[] mbbox, int i, int idx) { - while (idx < data.epsFile.length && (data.epsFile[idx] == 32)) { - idx++; - } - - int nidx = idx; - - // check also for ANSI46(".") to identify floating point values - while (nidx < data.epsFile.length - && ((data.epsFile[nidx] >= 48 && data.epsFile[nidx] <= 57) - || (data.epsFile[nidx] == 45) - || (data.epsFile[nidx] == 46))) { - nidx++; - } - - byte[] num = new byte[nidx - idx]; - System.arraycopy(data.epsFile, idx, num, 0, nidx - idx); - String ns = new String(num); - - //if( ns.indexOf(".") != -1 ) { - // do something like logging a warning - //} - - // then parse the double and round off to the next math. Integer - mbbox[i] = (long) Math.ceil(Double.parseDouble(ns)); - - return (1 + nidx - idx); - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/GIFReader.java b/src/java/org/apache/fop/image/analyser/GIFReader.java deleted file mode 100644 index d8da89607..000000000 --- a/src/java/org/apache/fop/image/analyser/GIFReader.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for GIF image type. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class GIFReader implements ImageReader { - - private static final int GIF_SIG_LENGTH = 10; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported = ((header[0] == 'G') - && (header[1] == 'I') - && (header[2] == 'F') - && (header[3] == '8') - && (header[4] == '7' || header[4] == '9') - && (header[5] == 'a')); - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(header, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/gif"; - } - - private void getDimension(byte[] header, FopImage.ImageInfo info) { - // little endian notation - int byte1 = header[6] & 0xff; - int byte2 = header[7] & 0xff; - info.width = ((byte2 << 8) | byte1) & 0xffff; - - byte1 = header[8] & 0xff; - byte2 = header[9] & 0xff; - info.height = ((byte2 << 8) | byte1) & 0xffff; - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[GIF_SIG_LENGTH]; - try { - imageStream.mark(GIF_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/ImageReader.java b/src/java/org/apache/fop/image/analyser/ImageReader.java deleted file mode 100644 index 980d1e489..000000000 --- a/src/java/org/apache/fop/image/analyser/ImageReader.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader objects read image headers to determine the image size. - * - * @author Pankaj Narula - * @version $Id$ - */ -public interface ImageReader { - - /** - * Verify image type. If the stream does not contain image data expected by - * the reader it must reset the stream to the start. This is so that the - * next reader can start reading from the start. The reader must not close - * the stream unless it can handle the image and it has read the - * information. - * - * @param bis Image buffered input stream - * @param uri URI to the image - * @param ua The user agent - * @return <code>true</code> if image type is the handled one - * @exception IOException if an I/O error occurs - */ - FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) - throws IOException; - -} - diff --git a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java b/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java deleted file mode 100644 index c07d68d39..000000000 --- a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.image.FopImage; -import org.apache.xmlgraphics.util.Service; - -/** - * Factory for ImageReader objects. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class ImageReaderFactory { - - private static List formats = new java.util.ArrayList(); - - /** logger */ - protected static Log log = LogFactory.getLog(ImageReaderFactory.class); - - static { - registerFormat(new JPEGReader()); - registerFormat(new BMPReader()); - registerFormat(new GIFReader()); - registerFormat(new PNGReader()); - registerFormat(new TIFFReader()); - registerFormat(new EPSReader()); - registerFormat(new EMFReader()); - - //Dynamic registration of ImageReaders - Iterator iter = Service.providers(ImageReader.class, true); - while (iter.hasNext()) { - registerFormat((ImageReader)iter.next()); - } - - // the xml parser through batik closes the stream when finished - // so there is a workaround in the SVGReader - registerFormat(new SVGReader()); - registerFormat(new SVGZReader()); - registerFormat(new XMLReader()); - } - - /** - * Registers a new ImageReader. - * - * @param reader An ImageReader instance - */ - public static void registerFormat(ImageReader reader) { - formats.add(reader); - } - - /** - * ImageReader maker. - * - * @param uri URI to the image - * @param in image input stream - * @param ua user agent - * @return An ImageInfo object describing the image - */ - public static FopImage.ImageInfo make(String uri, InputStream in, - FOUserAgent ua) { - - ImageReader reader; - try { - for (int count = 0; count < formats.size(); count++) { - reader = (ImageReader) formats.get(count); - FopImage.ImageInfo info = reader.verifySignature(uri, in, ua); - if (info != null) { - return info; - } - } - log.warn("No ImageReader found for " + uri); - in.close(); - } catch (IOException ex) { - log.error("Error while recovering Image Informations (" - + uri + ")", ex); - } - return null; - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/JPEGReader.java b/src/java/org/apache/fop/image/analyser/JPEGReader.java deleted file mode 100644 index c90f6b000..000000000 --- a/src/java/org/apache/fop/image/analyser/JPEGReader.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for JPEG image type. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class JPEGReader implements ImageReader { - - /** - * Only SOFn and APPn markers are defined as SOFn is needed for the height and - * width search. APPn is also defined because if the JPEG contains thumbnails - * the dimensions of the thumnail would also be after the SOFn marker enclosed - * inside the APPn marker. And we don't want to confuse those dimensions with - * the image dimensions. - */ - private static final int MARK = 0xff; // Beginning of a Marker - private static final int NULL = 0x00; // Special case for 0xff00 - private static final int SOF1 = 0xc0; // Baseline DCT - private static final int SOF2 = 0xc1; // Extended Sequential DCT - private static final int SOF3 = 0xc2; // Progrssive DCT only PDF 1.3 - private static final int SOFA = 0xca; // Progressice DCT only PDF 1.3 - private static final int APP0 = 0xe0; // Application marker, JFIF - private static final int APPF = 0xef; // Application marker - private static final int SOS = 0xda; // Start of Scan - private static final int SOI = 0xd8; // start of Image - private static final int JPG_SIG_LENGTH = 2; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream fis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(fis); - boolean supported = ((header[0] == (byte) 0xff) - && (header[1] == (byte) 0xd8)); - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(fis, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = fis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/jpeg"; - } - - private byte[] getDefaultHeader(InputStream imageStream) throws IOException { - byte[] header = new byte[JPG_SIG_LENGTH]; - try { - imageStream.mark(JPG_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - - private void getDimension(InputStream imageStream, - FopImage.ImageInfo info) - throws IOException { - try { - int pos=0, avail = imageStream.available(); - imageStream.mark(avail); - int marker = NULL; - long length, skipped; -outer: - while (true) { - do { - if (avail == 0) { - imageStream.reset(); - avail = 2*pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - //Marker first byte (FF) - marker = imageStream.read(); - pos++; avail--; - } while (marker != MARK); - - do { - if (avail == 0) { - imageStream.reset(); - avail = 2*pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - //Marker second byte - marker = imageStream.read(); - pos++; avail--; - } while (marker == MARK); - - switch (marker) { - case SOI: - break; - case NULL: - break; - case APP0: - if (avail < 14) { - imageStream.reset(); - avail = 2 * pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - int reclen = this.read2bytes(imageStream); - pos += 2; avail -= 2; - this.skip(imageStream, 7); - pos += 7; avail -= 7; - int densityUnits = imageStream.read(); - pos++; avail--; - int xdensity = this.read2bytes(imageStream); - pos += 2; avail -= 2; - int ydensity = this.read2bytes(imageStream); - pos += 2; avail -= 2; - - if (densityUnits == 2) { - info.dpiHorizontal = xdensity * 28.3464567 / 72; //dpi - info.dpiVertical = ydensity * 28.3464567 / 72; //dpi - } else if (densityUnits == 1) { - info.dpiHorizontal = xdensity; - info.dpiVertical = ydensity; - } else { - // Use resolution specified in - // FOUserAgent.getFactory() (default 72dpi). - } - - int restlen = reclen - 12; - if (avail < restlen) { - imageStream.reset(); - avail = 2 * pos; - if (avail < pos + restlen + 10) { - avail = (int)(pos + restlen + 10); - } - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - skipped = this.skip(imageStream, restlen - 2); - pos += skipped; avail -= skipped; - if (skipped != restlen - 2) { - throw new IOException("Skipping Error"); - } - break; - case SOF1: - case SOF2: - case SOF3: // SOF3 and SOFA are only supported by PDF 1.3 - case SOFA: - while (avail < 7) { - imageStream.reset(); - avail = 2*pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - this.skip(imageStream, 3); - pos+=3; avail-=3; - info.height = this.read2bytes(imageStream); - pos+=2; avail-=2; - info.width = this.read2bytes(imageStream); - pos+=2; avail-=2; - break outer; - default: - while (avail < 2) { - imageStream.reset(); - avail = 2*pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - length = this.read2bytes(imageStream); - pos+=2; avail-=2; - if (avail < length) { - imageStream.reset(); - avail = 2*pos; - if (avail < pos+length+10) { - avail = (int)(pos+length+10); - } - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - skipped = this.skip(imageStream, length - 2); - pos += skipped; avail -= skipped; - if (skipped != length - 2) { - throw new IOException("Skipping Error"); - } - } - } - imageStream.reset(); - } catch (IOException ioe) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ioe; - } - } - - private int read2bytes(InputStream imageStream) throws IOException { - int byte1 = imageStream.read(); - int byte2 = imageStream.read(); - return (int) ((byte1 << 8) | byte2); - } - - private long skip(InputStream imageStream, long n) throws IOException { - long discarded = 0; - while (discarded != n) { - imageStream.read(); - discarded++; - } - return discarded; // scope for exception - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/PNGReader.java b/src/java/org/apache/fop/image/analyser/PNGReader.java deleted file mode 100644 index ab6c64775..000000000 --- a/src/java/org/apache/fop/image/analyser/PNGReader.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for PNG image type. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class PNGReader implements ImageReader { - - private static final int PNG_SIG_LENGTH = 24; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported = ((header[0] == (byte) 0x89) - && (header[1] == (byte) 0x50) - && (header[2] == (byte) 0x4e) - && (header[3] == (byte) 0x47) - && (header[4] == (byte) 0x0d) - && (header[5] == (byte) 0x0a) - && (header[6] == (byte) 0x1a) - && (header[7] == (byte) 0x0a)); - - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(header, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/png"; - } - - private void getDimension(byte[] header, FopImage.ImageInfo info) { - // png is always big endian - int byte1 = header[16] & 0xff; - int byte2 = header[17] & 0xff; - int byte3 = header[18] & 0xff; - int byte4 = header[19] & 0xff; - long l = (long) ((byte1 << 24) - | (byte2 << 16) - | (byte3 << 8) - | (byte4)); - info.width = (int) l; - - byte1 = header[20] & 0xff; - byte2 = header[21] & 0xff; - byte3 = header[22] & 0xff; - byte4 = header[23] & 0xff; - l = (long) ((byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4); - info.height = (int) l; - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[PNG_SIG_LENGTH]; - try { - imageStream.mark(PNG_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - -} diff --git a/src/java/org/apache/fop/image/analyser/SVGReader.java b/src/java/org/apache/fop/image/analyser/SVGReader.java deleted file mode 100644 index cffaa365c..000000000 --- a/src/java/org/apache/fop/image/analyser/SVGReader.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; -import java.awt.geom.AffineTransform; - -// XML -import org.w3c.dom.Element; -import org.w3c.dom.svg.SVGDocument; - -// Batik -import org.apache.batik.dom.svg.SAXSVGDocumentFactory; -import org.apache.batik.dom.svg.SVGOMDocument; -import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.bridge.UnitProcessor; -import org.apache.batik.dom.svg.SVGDOMImplementation; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -// FOP -import org.apache.fop.image.XMLImage; -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.svg.SVGUserAgent; -import org.apache.fop.util.UnclosableInputStream; - -/** - * ImageReader object for SVG document image type. - */ -public class SVGReader implements ImageReader { - - /** Logger instance */ - protected static Log log = LogFactory.getLog(SVGReader.class); - - /** SVG's MIME type */ - public static final String SVG_MIME_TYPE = "image/svg+xml"; - - private boolean batik = true; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream fis, - FOUserAgent ua) throws IOException { - FopImage.ImageInfo info = loadImage(uri, fis, ua); - if (info != null) { - IOUtils.closeQuietly(fis); - } - return info; - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return SVG_MIME_TYPE; - } - - /** - * This means the external svg document will be loaded twice. Possibly need - * a slightly different design for the image stuff. - * - * @param uri @todo Description of the Parameter - * @param fis @todo Description of the Parameter - * @param ua @todo Description of the Parameter - * @return @todo Description of the Return Value - */ - private FopImage.ImageInfo loadImage(String uri, InputStream bis, - FOUserAgent ua) { - if (batik) { - try { - Loader loader = new Loader(); - return loader.getImage(uri, bis, - ua.getSourcePixelUnitToMillimeter()); - } catch (NoClassDefFoundError e) { - batik = false; - log.warn("Batik not in class path", e); - return null; - } - } - return null; - } - - /** - * This method is put in another class so that the classloader does not - * attempt to load batik related classes when constructing the SVGReader - * class. - */ - class Loader { - private FopImage.ImageInfo getImage(String uri, InputStream fis, - float pixelUnitToMM) { - // parse document and get the size attributes of the svg element - - try { - fis = new UnclosableInputStream(fis); - - FopImage.ImageInfo info = new FopImage.ImageInfo(); - - //Set the resolution to that of the FOUserAgent - info.dpiHorizontal = 25.4f / pixelUnitToMM; - info.dpiVertical = info.dpiHorizontal; - - info.originalURI = uri; - info.mimeType = getMimeType(); - info.str = SVGDOMImplementation.SVG_NAMESPACE_URI; - - int length = fis.available(); - fis.mark(length + 1); - SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( - XMLImage.getParserName()); - SVGDocument doc = (SVGDocument) factory.createSVGDocument(uri, fis); - info.data = doc; - - Element e = doc.getRootElement(); - String s; - SVGUserAgent userAg = new SVGUserAgent(pixelUnitToMM, - new AffineTransform()); - BridgeContext ctx = new BridgeContext(userAg); - UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); - - // 'width' attribute - default is 100% - s = e.getAttributeNS(null, - SVGOMDocument.SVG_WIDTH_ATTRIBUTE); - if (s.length() == 0) { - s = SVGOMDocument.SVG_SVG_WIDTH_DEFAULT_VALUE; - } - info.width = Math.round(UnitProcessor.svgHorizontalLengthToUserSpace( - s, SVGOMDocument.SVG_WIDTH_ATTRIBUTE, uctx)); - - // 'height' attribute - default is 100% - s = e.getAttributeNS(null, - SVGOMDocument.SVG_HEIGHT_ATTRIBUTE); - if (s.length() == 0) { - s = SVGOMDocument.SVG_SVG_HEIGHT_DEFAULT_VALUE; - } - info.height = Math.round(UnitProcessor.svgVerticalLengthToUserSpace( - s, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE, uctx)); - - return info; - } catch (NoClassDefFoundError ncdfe) { - try { - fis.reset(); - } catch (IOException ioe) { - // we're more interested in the original exception - } - batik = false; - log.warn("Batik not in class path", ncdfe); - return null; - } catch (IOException e) { - // If the svg is invalid then it throws an IOException - // so there is no way of knowing if it is an svg document - - log.debug("Error while trying to load stream as an SVG file: " - + e.getMessage()); - // assuming any exception means this document is not svg - // or could not be loaded for some reason - try { - fis.reset(); - } catch (IOException ioe) { - // we're more interested in the original exception - } - return null; - } - } - } - -} diff --git a/src/java/org/apache/fop/image/analyser/TIFFReader.java b/src/java/org/apache/fop/image/analyser/TIFFReader.java deleted file mode 100644 index 08d702780..000000000 --- a/src/java/org/apache/fop/image/analyser/TIFFReader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for TIFF image type. - * - * @author Pankaj Narula, Michael Lee - * @version $Id$ - */ -public class TIFFReader implements ImageReader { - - private static final int TIFF_SIG_LENGTH = 8; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported = false; - - // first 2 bytes = II (little endian encoding) - if (header[0] == (byte) 0x49 && header[1] == (byte) 0x49) { - - // look for '42' in byte 3 and '0' in byte 4 - if (header[2] == 42 && header[3] == 0) { - supported = true; - } - } - - // first 2 bytes == MM (big endian encoding) - if (header[0] == (byte) 0x4D && header[1] == (byte) 0x4D) { - - // look for '42' in byte 4 and '0' in byte 3 - if (header[2] == 0 && header[3] == 42) { - supported = true; - } - } - - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(header, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/tiff"; - } - - private void getDimension(byte[] header, FopImage.ImageInfo info) { - // currently not setting the width and height - // these are set again by the Jimi image reader. - // I suppose I'll do it one day to be complete. Or - // someone else will. - // Note: bytes 4,5,6,7 contain the byte offset in the stream of the first IFD block - info.width = -1; - info.height = -1; - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[TIFF_SIG_LENGTH]; - try { - imageStream.mark(TIFF_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/XMLReader.java b/src/java/org/apache/fop/image/analyser/XMLReader.java deleted file mode 100644 index 4d0145eed..000000000 --- a/src/java/org/apache/fop/image/analyser/XMLReader.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; -import java.util.Map; - -// XML -import javax.xml.parsers.DocumentBuilderFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.util.UnclosableInputStream; -import org.apache.fop.apps.FOUserAgent; - -// Commons-Logging -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** ImageReader object for XML document image type. */ -public class XMLReader implements ImageReader { - - /** - * logging instance - */ - private Log log = LogFactory.getLog(XMLReader.class); - - private static Map converters = new java.util.HashMap(); - - /** - * Registers a Converter implementation with XMLReader. - * - * @param ns The namespace to associate with this converter - * @param conv The actual Converter implementation - */ - public static void setConverter(String ns, Converter conv) { - converters.put(ns, conv); - } - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream fis, - FOUserAgent ua) - throws IOException { - FopImage.ImageInfo info = loadImage(uri, fis, ua); - if (info != null) { - info.originalURI = uri; - IOUtils.closeQuietly(fis); - } - return info; - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "text/xml"; - } - - /** - * Creates an ImageInfo object from an XML image read from a stream. - * - * (todo) This means the external svg document will be loaded twice. Possibly need - * a slightly different design for the image stuff. - * - * @param uri The URI to the image - * @param bis The InputStream - * @param ua The user agent - * @return An ImageInfo object describing the image - */ - protected FopImage.ImageInfo loadImage(String uri, InputStream bis, - FOUserAgent ua) { - return createDocument(bis, ua); - } - - /** - * Creates an ImageInfo object from an XML image read from a stream. - * - * @param input The InputStream - * @param ua The user agent - * @return An ImageInfo object describing the image - */ - public FopImage.ImageInfo createDocument(final InputStream input, final FOUserAgent ua) { - Document doc = null; - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.mimeType = getMimeType(); - - try { - final InputStream is = new UnclosableInputStream(input); - int length = is.available(); - is.mark(length); - - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - doc = dbf.newDocumentBuilder().parse(is); - info.data = doc; - - Element root = doc.getDocumentElement(); - log.debug("XML image namespace: " + root.getAttribute("xmlns")); - String ns = root.getAttribute("xmlns"); - info.str = ns; - - Converter conv = (Converter) converters.get(ns); - if (conv != null) { - FopImage.ImageInfo i = conv.convert(doc); - if (i != null) { - info = i; - } - } - } catch (Exception e) { - log.debug("Error while constructing image from XML", e); - try { - input.reset(); - } catch (IOException ioe) { - // throw the original exception, not this one - } - return null; - } - if (info != null) { - try { - input.close(); - } catch (IOException io) { - // ignore - } - } - return info; - } - - /** - * This interface is to be implemented for XML to image converters. - */ - public static interface Converter { - - /** - * This method is called for a DOM document to be converted into an - * ImageInfo object. - * - * @param doc The DOM document to convert - * @return An ImageInfo object describing the image - */ - FopImage.ImageInfo convert(Document doc); - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/package.html b/src/java/org/apache/fop/image/analyser/package.html deleted file mode 100644 index 677a625b2..000000000 --- a/src/java/org/apache/fop/image/analyser/package.html +++ /dev/null @@ -1,23 +0,0 @@ -<!-- - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<!-- $Id$ --> -<HTML> -<TITLE>org.apache.fop.image.analyser Package</TITLE> -<BODY> -<P>Image analyzers for determining the format of an image and to preload its intrinsic size.</P> -</BODY> -</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/image/package.html b/src/java/org/apache/fop/image/package.html index 0145864b2..cbd2d7c5e 100644 --- a/src/java/org/apache/fop/image/package.html +++ b/src/java/org/apache/fop/image/package.html @@ -18,6 +18,6 @@ <HTML> <TITLE>org.apache.fop.image Package</TITLE> <BODY> -<P>Contains image loading adapters for various image sources and the image cache.</P> +<P>Contains image loading adapters for various image sources.</P> </BODY> </HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 54fd315b1..65d537bcd 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -272,7 +272,7 @@ public abstract class AbstractBreaker { */ public void doLayout(int flowBPD, boolean autoHeight) { LayoutContext childLC = createLayoutContext(); - childLC.setStackLimit(new MinOptMax(flowBPD)); + childLC.setStackLimitBP(new MinOptMax(flowBPD)); if (getCurrentDisplayAlign() == Constants.EN_X_FILL) { //EN_X_FILL is non-standard (by LF) @@ -495,7 +495,7 @@ public abstract class AbstractBreaker { int averageLineLength = optimizeLineLength(effectiveList, startElementIndex, endElementIndex); if (averageLineLength != 0) { - childLC.setStackLimit(new MinOptMax(averageLineLength)); + childLC.setStackLimitBP(new MinOptMax(averageLineLength)); } } /* *** *** non-standard extension *** *** */ diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index f75fffc0d..656b5e2df 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -113,7 +113,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager if (curChildLM != null && !curChildLM.isFinished()) { return curChildLM; } - while (childLMiter.hasNext()) { + if (childLMiter.hasNext()) { curChildLM = (LayoutManager) childLMiter.next(); curChildLM.initialize(); return curChildLM; @@ -350,6 +350,10 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager /** * Registers the FO's markers on the current PageViewport + * + * @param isStarting boolean indicating whether the markers qualify as 'starting' + * @param isFirst boolean indicating whether the markers qualify as 'first' + * @param isLast boolean indicating whether the markers qualify as 'last' */ protected void addMarkersToPage(boolean isStarting, boolean isFirst, boolean isLast) { if (this.markers != null) { @@ -361,10 +365,18 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager } } + /** + * Registers the FO's id on the current PageViewport + */ + protected void addId() { + if (fobj != null) { + getPSLM().addIDToPage(fobj.getId()); + } + } + /** {@inheritDoc} */ public String toString() { return (super.toString() + (fobj != null ? "[fobj=" + fobj.toString() + "]" : "")); } - } diff --git a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java index 80e0b74cc..1b0d02639 100644 --- a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java +++ b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java @@ -117,7 +117,7 @@ public class AreaAdditionUtil { // set space after for each LM, in order to implement // display-align = distribute lc.setSpaceAfter(layoutContext.getSpaceAfter()); - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitsFrom(layoutContext); childLM.addAreas(childPosIter, lc); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index fc60b561e..e8ca88c1c 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -38,7 +38,6 @@ import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.BlockContainer; import org.apache.fop.fo.properties.CommonAbsolutePosition; -import org.apache.fop.layoutmgr.inline.InlineLayoutManager; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; @@ -201,7 +200,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); autoHeight = false; //boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); - int maxbpd = context.getStackLimit().opt; + int maxbpd = context.getStackLimitBP().opt; int allocBPD; if (height.getEnum() == EN_AUTO || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) { @@ -249,7 +248,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager MinOptMax stackLimit = new MinOptMax(relDims.bpd); - LinkedList returnedList = null; + LinkedList returnedList; LinkedList contentList = new LinkedList(); LinkedList returnList = new LinkedList(); @@ -280,8 +279,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager LayoutContext childLC = new LayoutContext(0); childLC.copyPendingMarksFrom(context); // curLM is a ? - childLC.setStackLimit(MinOptMax.subtract(context - .getStackLimit(), stackLimit)); + childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit)); childLC.setRefIPD(relDims.ipd); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); @@ -388,6 +386,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); + + //All child content is processed. Only break-after can occur now, so... + context.clearPendingMarks(); addKnuthElementsForBreakAfter(returnList, context); setFinished(true); @@ -411,7 +412,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager if (isFixed()) { availHeight = (int)getCurrentPV().getViewArea().getHeight(); } else { - availHeight = context.getStackLimit().opt; + availHeight = context.getStackLimitBP().opt; } allocBPD = availHeight; allocBPD -= offset.y; @@ -444,7 +445,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } } else { - int maxbpd = context.getStackLimit().opt; + int maxbpd = context.getStackLimitBP().opt; allocBPD = maxbpd; if (!switchedProgressionDirection) { autoHeight = true; @@ -601,11 +602,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } public boolean isOverflow() { - if (isEmpty()) { - return false; - } else { - return (deferredAlg.getPageBreaks().size() > 1); - } + return !isEmpty() && (deferredAlg.getPageBreaks().size() > 1); } protected LayoutManager getTopLevelLM() { @@ -625,7 +622,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(context.getStackLimit()); + childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); @@ -707,7 +704,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); } - LayoutManager childLM = null; + LayoutManager childLM; LayoutManager lastLM = null; LayoutContext lc = new LayoutContext(0); lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); @@ -736,7 +733,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } Position innerPosition = pos; if (pos instanceof NonLeafPosition) { - innerPosition = ((NonLeafPosition)pos).getPosition(); + innerPosition = pos.getPosition(); } if (pos instanceof BlockContainerPosition) { if (bcpos != null) { @@ -772,7 +769,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } - getPSLM().addIDToPage(getBlockContainerFO().getId()); + addId(); addMarkersToPage(true, isFirst(firstPos), isLast(lastPos)); @@ -854,7 +851,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // set last area flag lc.setFlags(LayoutContext.LAST_AREA, (layoutContext.isLastArea() && childLM == lastLM)); - /*LF*/lc.setStackLimit(layoutContext.getStackLimit()); + /*LF*/lc.setStackLimitBP(layoutContext.getStackLimitBP()); // Add the line areas to Area childLM.addAreas(childPosIter, lc); } @@ -873,7 +870,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager referenceArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(((BlockContainer)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** @@ -992,30 +989,21 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepTogether() { //TODO Keeps will have to be more sophisticated sooner or later - return (!getBlockContainerFO().getKeepTogether().getWithinPage().isAuto() - || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto() - || (getParent() instanceof BlockLevelLayoutManager - && ((BlockLevelLayoutManager) getParent()).mustKeepTogether()) - || (getParent() instanceof InlineLayoutManager - && ((InlineLayoutManager) getParent()).mustKeepTogether())); + return super.mustKeepTogether() + || !getBlockContainerFO().getKeepTogether().getWithinPage().isAuto() + || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { return !getBlockContainerFO().getKeepWithPrevious().getWithinPage().isAuto() || !getBlockContainerFO().getKeepWithPrevious().getWithinColumn().isAuto(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithNext() { return !getBlockContainerFO().getKeepWithNext().getWithinPage().isAuto() || !getBlockContainerFO().getKeepWithNext().getWithinColumn().isAuto(); diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index bb39def8d..f5270107c 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -25,6 +25,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.LineArea; @@ -146,7 +147,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager * @return true if there are more child lms */ public boolean hasNext() { - return (curPos < listLMs.size()) ? true : createNextChildLMs(curPos); + return (curPos < listLMs.size()) || createNextChildLMs(curPos); } /** @@ -249,7 +250,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); } - LayoutManager childLM = null; + LayoutManager childLM; LayoutManager lastLM = null; LayoutContext lc = new LayoutContext(0); lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); @@ -279,7 +280,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager Position innerPosition = pos; if (pos instanceof NonLeafPosition) { //Not all elements are wrapped - innerPosition = ((NonLeafPosition) pos).getPosition(); + innerPosition = pos.getPosition(); } if (innerPosition == null) { // pos was created by this BlockLM and was inside an element @@ -308,7 +309,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager } } - getPSLM().addIDToPage(getBlockFO().getId()); + addId(); addMarkersToPage(true, isFirst(firstPos), isLast(lastPos)); @@ -389,7 +390,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager // set last area flag lc.setFlags(LayoutContext.LAST_AREA, (layoutContext.isLastArea() && childLM == lastLM)); - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); // Add the line areas to Area childLM.addAreas(childPosIter, lc); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 5faad623c..67ed1de9f 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -274,13 +274,14 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (curLM instanceof LineLayoutManager) { // curLM is a LineLayoutManager // set stackLimit for lines (stack limit is now i-p-direction, not b-p-direction!) - childLC.setStackLimit(new MinOptMax(getContentAreaIPD())); + childLC.setStackLimitBP(context.getStackLimitBP()); + childLC.setStackLimitIP(new MinOptMax(getContentAreaIPD())); childLC.setRefIPD(getContentAreaIPD()); } else { // curLM is a ? //childLC.setStackLimit(MinOptMax.subtract(context // .getStackLimit(), stackSize)); - childLC.setStackLimit(context.getStackLimit()); + childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(referenceIPD); } @@ -293,15 +294,22 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (returnedList != null && returnedList.size() == 1 && ((ListElement) returnedList.getFirst()).isForcedBreak()) { - // a descendant of this block has break-before - contentList.addAll(returnedList); if (curLM.isFinished() && !hasNextChildLM()) { - forcedBreakAfterLast = (BreakElement)contentList.removeLast(); + // a descendant of this block has break-before + forcedBreakAfterLast = (BreakElement) returnedList.getFirst(); context.clearPendingMarks(); break; } + if (contentList.size() == 0) { + // Empty fo:block, zero-length box makes sure the IDs and/or markers + // are registered and borders/padding are painted. + returnList.add(new KnuthBox(0, notifyPos(new Position(this)), false)); + } + // a descendant of this block has break-before + contentList.addAll(returnedList); + /* extension: conversione di tutta la sequenza fin'ora ottenuta */ if (bpUnit > 0) { storedList = contentList; @@ -392,6 +400,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); + + //All child content is processed. Only break-after can occur now, so... + context.clearPendingMarks(); if (forcedBreakAfterLast == null) { addKnuthElementsForBreakAfter(returnList, context); } diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index a70dd0883..115532cf1 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -99,7 +99,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager //MinOptMax bpd = context.getStackLimit(); LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(context.getStackLimit()); + childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(getCurrentPage().getSimplePageMaster().getWritingMode()); diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 9eb38600b..79b5e232f 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -74,18 +74,29 @@ public class LayoutContext { private int flags; // Contains some set of flags defined above /** * Total available stacking dimension for a "galley-level" layout - * manager (Line or Flow). It is passed by the parent LM. For LineLM, - * the block LM determines this based on indent properties. + * manager in block-progression-direction. It is passed by the + * parent LM. * These LM <b>may</b> wish to pass this information down to lower * level LM to allow them to optimize returned break possibilities. */ - private MinOptMax stackLimit; + private MinOptMax stackLimitBP; + /** + * Total available stacking dimension for a "galley-level" layout + * manager in inline-progression-direction. It is passed by the + * parent LM. For LineLM, the block LM determines this based on + * indent properties. + * These LM <b>may</b> wish to pass this information down to lower + * level LM to allow them to optimize returned break possibilities. + */ + private MinOptMax stackLimitIP; /** True if current element list is spanning in multi-column layout. */ private int nextSpan = Constants.NOT_SET; /** inline-progression-dimension of nearest ancestor reference area */ private int refIPD; + //TODO After the split of stackLimit into stackLimitBP and stackLimitIP there's now some + //overlap with refIPD. Need to investigate how best to refactor that. /** the writing mode established by the nearest ancestor reference area */ private int writingMode = Constants.EN_LR_TB; @@ -145,7 +156,7 @@ public class LayoutContext { this.flags = parentLC.flags; this.refIPD = parentLC.refIPD; this.writingMode = parentLC.writingMode; - this.stackLimit = null; // Don't reference parent MinOptMax! + setStackLimitsFrom(parentLC); this.leadingSpace = parentLC.leadingSpace; //??? this.trailingSpace = parentLC.trailingSpace; //??? this.hyphContext = parentLC.hyphContext; @@ -166,7 +177,8 @@ public class LayoutContext { public LayoutContext(int flags) { this.flags = flags; this.refIPD = 0; - stackLimit = new MinOptMax(0); + stackLimitBP = new MinOptMax(0); + stackLimitIP = new MinOptMax(0); leadingSpace = null; trailingSpace = null; } @@ -273,12 +285,8 @@ public class LayoutContext { * Clears all pending marks on the LayoutContext. */ public void clearPendingMarks() { - if (this.pendingBeforeMarks != null) { - this.pendingBeforeMarks.clear(); - } - if (this.pendingAfterMarks != null) { - this.pendingAfterMarks.clear(); - } + this.pendingBeforeMarks = null; + this.pendingAfterMarks = null; } /** @@ -306,15 +314,48 @@ public class LayoutContext { } } - public void setStackLimit(MinOptMax limit) { - stackLimit = limit; + /** + * Sets the stack limit in block-progression-dimension. + * @param limit the stack limit + */ + public void setStackLimitBP(MinOptMax limit) { + stackLimitBP = limit; } - public MinOptMax getStackLimit() { - return stackLimit; + /** + * Returns the stack limit in block-progression-dimension. + * @return the stack limit + */ + public MinOptMax getStackLimitBP() { + return stackLimitBP; } /** + * Sets the stack limit in inline-progression-dimension. + * @param limit the stack limit + */ + public void setStackLimitIP(MinOptMax limit) { + stackLimitIP = limit; + } + + /** + * Returns the stack limit in inline-progression-dimension. + * @return the stack limit + */ + public MinOptMax getStackLimitIP() { + return stackLimitIP; + } + + /** + * Sets (Copies) the stack limits in both directions from another layout context. + * @param context the layout context to taje the values from + */ + public void setStackLimitsFrom(LayoutContext context) { + setStackLimitBP(context.getStackLimitBP()); + setStackLimitIP(context.getStackLimitIP()); + } + + /** * Sets the inline-progression-dimension of the nearest ancestor reference area. */ public void setRefIPD(int ipd) { @@ -536,22 +577,27 @@ public class LayoutContext { /** {@inheritDoc} */ public String toString() { - return "Layout Context:" + - "\nStack Limit: \t" + (getStackLimit() == null ? "null" : getStackLimit().toString()) + - "\nTrailing Space: \t" + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString()) + - "\nLeading Space: \t" + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString()) + - "\nReference IPD: \t" + getRefIPD() + - "\nSpace Adjust: \t" + getSpaceAdjust() + - "\nIPD Adjust: \t" + getIPDAdjust() + - "\nResolve Leading Space: \t" + resolveLeadingSpace() + - "\nSuppress Leading Space: \t" + suppressLeadingSpace() + - "\nIs First Area: \t" + isFirstArea() + - "\nStarts New Area: \t" + startsNewArea() + - "\nIs Last Area: \t" + isLastArea() + - "\nTry Hyphenate: \t" + tryHyphenate() + - "\nKeeps: \t[" + (isKeepWithNextPending() ? "keep-with-next" : "") + "][" - + (isKeepWithPreviousPending() ? "keep-with-previous" : "") + "] pending" + - "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" + return "Layout Context:" + + "\nStack Limit BPD: \t" + + (getStackLimitBP() == null ? "null" : getStackLimitBP().toString()) + + "\nStack Limit IPD: \t" + + (getStackLimitIP() == null ? "null" : getStackLimitIP().toString()) + + "\nTrailing Space: \t" + + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString()) + + "\nLeading Space: \t" + + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString()) + + "\nReference IPD: \t" + getRefIPD() + + "\nSpace Adjust: \t" + getSpaceAdjust() + + "\nIPD Adjust: \t" + getIPDAdjust() + + "\nResolve Leading Space: \t" + resolveLeadingSpace() + + "\nSuppress Leading Space: \t" + suppressLeadingSpace() + + "\nIs First Area: \t" + isFirstArea() + + "\nStarts New Area: \t" + startsNewArea() + + "\nIs Last Area: \t" + isLastArea() + + "\nTry Hyphenate: \t" + tryHyphenate() + + "\nKeeps: \t[" + (isKeepWithNextPending() ? "keep-with-next" : "") + "][" + + (isKeepWithPreviousPending() ? "keep-with-previous" : "") + "] pending" + + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]"; } diff --git a/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java b/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java index ff9bdb1d9..b58af1cfe 100644 --- a/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java +++ b/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java @@ -68,19 +68,16 @@ public class MinOptMaxUtil { } /** - * Extend the minimum length to the given length. + * Extends the minimum length to the given length if necessary, and adjusts opt and + * max accordingly. + * * @param mom the min/opt/max trait * @param len the new minimum length - * @param optToLen if set adjusts the optimum length to be the smaller of the - * minimum length and the given length */ - public static void extendMinimum(MinOptMax mom, int len, boolean optToLen) { + public static void extendMinimum(MinOptMax mom, int len) { if (mom.min < len) { mom.min = len; mom.opt = Math.max(mom.min, mom.opt); - if (optToLen) { - mom.opt = Math.min(mom.min, len); - } mom.max = Math.max(mom.opt, mom.max); } } @@ -111,7 +108,7 @@ public class MinOptMaxUtil { ? 0 : prop.getMinimum(context).getLength().getValue(context)), (prop.getOptimum(context).isAuto() ? 0 : prop.getOptimum(context).getLength().getValue(context)), - (prop.getMinimum(context).isAuto() + (prop.getMaximum(context).isAuto() ? Integer.MAX_VALUE : prop.getMaximum(context).getLength().getValue(context))); return mom; diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index cf830a7ec..3e100cd50 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -156,7 +156,7 @@ public class PageBreaker extends AbstractBreaker { // element represents a line with footnote citations bFootnotesPresent = true; LayoutContext footnoteContext = new LayoutContext(context); - footnoteContext.setStackLimit(context.getStackLimit()); + footnoteContext.setStackLimitBP(context.getStackLimitBP()); footnoteContext.setRefIPD(pslm.getCurrentPV() .getRegionReference(Constants.FO_REGION_BODY).getIPD()); LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs(); diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index 57fc4600e..d98d29b5c 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -364,7 +364,13 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { } else { // there are no footnotes } - return getLineWidth(activeNode.line) - actualWidth; + int diff = getLineWidth(activeNode.line) - actualWidth; + if (autoHeight && diff < 0) { + //getLineWidth() for auto-height parts return 0 so the diff will be negative + return 0; //...but we don't want to shrink in this case. Stick to optimum. + } else { + return diff; + } } /** Checks whether footnotes from preceding pages may be deferred to the page after diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index c8b89e6af..b1e414527 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -93,7 +93,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { //TODO Empty this method?!? // set layout dimensions setContentAreaIPD(context.getRefIPD()); - setContentAreaBPD(context.getStackLimit().opt); + setContentAreaBPD(context.getStackLimitBP().opt); //TODO Copied from elsewhere. May be worthwhile to factor out the common parts. // currently active LM @@ -111,10 +111,10 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { } // Set up a LayoutContext - MinOptMax bpd = context.getStackLimit(); + MinOptMax bpd = context.getStackLimitBP(); LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(MinOptMax.subtract(bpd, stackSize)); + childLC.setStackLimitBP(MinOptMax.subtract(bpd, stackSize)); childLC.setRefIPD(context.getRefIPD()); // get elements from curLM @@ -307,7 +307,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(context.getStackLimit()); + childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(context.getWritingMode()); diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java index 841a94705..dfc8c99f2 100644 --- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java +++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java @@ -29,6 +29,7 @@ import org.apache.fop.datatypes.SimplePercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonMarginBlock; +import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.fonts.Font; @@ -281,6 +282,90 @@ public class TraitSetter { } /** + * Add background to an area. This method is mainly used by table-related layout + * managers to add background for column, body or row. Since the area corresponding to + * border-separation must be filled with the table's background, for every cell an + * additional area with the same dimensions is created to hold the background for the + * corresponding column/body/row. An additional shift must then be added to + * background-position-horizontal/vertical to ensure the background images are + * correctly placed. Indeed the placement of images must be made WRT the + * column/body/row and not the cell. + * + * <p>Note: The area's IPD and BPD must be set before calling this method.</p> + * + * <p>TODO the regular + * {@link #addBackground(Area, CommonBorderPaddingBackground, PercentBaseContext)} + * method should be used instead, and a means to retrieve the original area's + * dimensions must be found.</p> + * + * <p>TODO the placement of images in the x- or y-direction will be incorrect if + * background-repeat is set for that direction.</p> + * + * @param area the area to set the traits on + * @param backProps the background properties + * @param context Property evaluation context + * @param ipdShift horizontal shift to affect to the background, in addition to the + * value of the background-position-horizontal property + * @param bpdShift vertical shift to affect to the background, in addition to the + * value of the background-position-vertical property + * @param referenceIPD value to use as a reference for percentage calculation + * @param referenceBPD value to use as a reference for percentage calculation + */ + public static void addBackground(Area area, + CommonBorderPaddingBackground backProps, + PercentBaseContext context, + int ipdShift, int bpdShift, int referenceIPD, int referenceBPD) { + if (!backProps.hasBackground()) { + return; + } + Trait.Background back = new Trait.Background(); + back.setColor(backProps.backgroundColor); + + if (backProps.getImageInfo() != null) { + back.setURL(backProps.backgroundImage); + back.setImageInfo(backProps.getImageInfo()); + back.setRepeat(backProps.backgroundRepeat); + if (backProps.backgroundPositionHorizontal != null) { + if (back.getRepeat() == Constants.EN_NOREPEAT + || back.getRepeat() == Constants.EN_REPEATY) { + if (area.getIPD() > 0) { + PercentBaseContext refContext = new SimplePercentBaseContext(context, + LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL, + (referenceIPD - back.getImageInfo().getSize().getWidthMpt())); + + back.setHoriz(ipdShift + + backProps.backgroundPositionHorizontal.getValue(refContext)); + } else { + // TODO Area IPD has to be set for this to work + log.warn("Horizontal background image positioning ignored" + + " because the IPD was not set on the area." + + " (Yes, it's a bug in FOP)"); + } + } + } + if (backProps.backgroundPositionVertical != null) { + if (back.getRepeat() == Constants.EN_NOREPEAT + || back.getRepeat() == Constants.EN_REPEATX) { + if (area.getBPD() > 0) { + PercentBaseContext refContext = new SimplePercentBaseContext(context, + LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL, + (referenceBPD - back.getImageInfo().getSize().getHeightMpt())); + back.setVertical(bpdShift + + backProps.backgroundPositionVertical.getValue(refContext)); + } else { + // TODO Area BPD has to be set for this to work + log.warn("Vertical background image positioning ignored" + + " because the BPD was not set on the area." + + " (Yes, it's a bug in FOP)"); + } + } + } + } + + area.addTrait(Trait.BACKGROUND, back); + } + + /** * Add background to an area. * Layout managers that create areas with a background can use this to * add the background to the area. @@ -312,7 +397,7 @@ public class TraitSetter { back.setHoriz(backProps.backgroundPositionHorizontal.getValue( new SimplePercentBaseContext(context, LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL, - (width - back.getImageInfo().getSize().getHeightMpt()) + (width - back.getImageInfo().getSize().getWidthMpt()) ) )); } else { diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index 6426f15db..38e0c35bc 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -124,13 +124,6 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage } /** - * {@inheritDoc} - */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } - - /** * Returns the image of foreign object area to be put into * the viewport. * @return the appropriate area diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java index 41d4af1c1..c92bdb6fc 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java @@ -51,7 +51,7 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa * Constructor * * @param node the formatting object that creates this area - * @todo better retrieval of font info + * TODO better retrieval of font info */ public AbstractPageNumberCitationLayoutManager(AbstractPageNumberCitation node) { super(node); @@ -83,7 +83,7 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa /** {@inheritDoc} */ public InlineArea get(LayoutContext context) { - curArea = getPageNumberCitationInlineArea(parentLM); + curArea = getPageNumberCitationInlineArea(); return curArea; } @@ -99,12 +99,15 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa } /** - * if id can be resolved then simply return a word, otherwise + * If id can be resolved then simply return a word, otherwise * return a resolvable area + * + * @param parentLM the parent LayoutManager + * @return a corresponding InlineArea */ - private InlineArea getPageNumberCitationInlineArea(LayoutManager parentLM) { + private InlineArea getPageNumberCitationInlineArea() { PageViewport page = getPSLM().getFirstPVWithID(fobj.getRefId()); - TextArea text = null; + TextArea text; if (page != null) { String str = page.getPageNumberString(); // get page string from parent, build area @@ -150,9 +153,5 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa return width; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index 0430eef0c..b53e442d4 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -45,7 +45,6 @@ import org.apache.fop.util.CharUtilities; * LayoutManager for the fo:character formatting object */ public class CharacterLayoutManager extends LeafNodeLayoutManager { - private Character fobj; private MinOptMax letterSpaceIPD; private int hyphIPD; private Font font; @@ -57,13 +56,13 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { * @param node the fo:character formatting object */ public CharacterLayoutManager(Character node) { - // @todo better null checking of node super(node); - fobj = node; } /** {@inheritDoc} */ public void initialize() { + Character fobj = (Character)this.fobj; + FontInfo fi = fobj.getFOEventHandler().getFontInfo(); FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this)); @@ -90,7 +89,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { text.addWord(String.valueOf(ch), 0); } TraitSetter.setProducerID(text, node.getId()); - TraitSetter.addTextDecoration(text, fobj.getTextDecoration()); + TraitSetter.addTextDecoration(text, node.getTextDecoration()); return text; } @@ -105,6 +104,8 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { return null; } + Character fobj = (Character)this.fobj; + ipd = new MinOptMax(font.getCharWidth(fobj.getCharacter())); curArea.setIPD(ipd.opt); @@ -178,14 +179,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public boolean applyChanges(List oldList) { setFinished(false); - if (isSomethingChanged) { - // there is nothing to do, - // possible changes have already been applied - // in the hyphenate() method - return true; - } else { - return false; - } + return isSomethingChanged; } /** {@inheritDoc} */ @@ -238,10 +232,5 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { return returnList; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } - } diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index 03e9b382a..ff7c5b3ce 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -19,9 +19,20 @@ package org.apache.fop.layoutmgr.inline; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; +import org.apache.fop.area.LineArea; +import org.apache.fop.area.inline.InlineArea; import org.apache.fop.fo.Constants; import org.apache.fop.fo.pagination.Title; import org.apache.fop.layoutmgr.AbstractBaseLayoutManager; @@ -34,19 +45,8 @@ import org.apache.fop.layoutmgr.PageSequenceLayoutManager; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.SpaceSpecifier; -import org.apache.fop.area.Area; -import org.apache.fop.area.LineArea; -import org.apache.fop.area.inline.InlineArea; - -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.ArrayList; -import java.util.Iterator; import org.apache.fop.traits.MinOptMax; -import org.apache.fop.area.Block; - /** * Content Layout Manager. * For use with objects that contain inline areas such as @@ -115,7 +115,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager childLC.setLeadingSpace(new SpaceSpecifier(false)); childLC.setTrailingSpace(new SpaceSpecifier(false)); // set stackLimit for lines - childLC.setStackLimit(new MinOptMax(ipd)); + childLC.setStackLimitIP(new MinOptMax(ipd)); childLC.setRefIPD(ipd); int lineHeight = 14000; diff --git a/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java index 4ffafb061..7ca9e0d5e 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java @@ -31,12 +31,10 @@ import org.apache.fop.fo.flow.InlineContainer; * and id areas are maintained for later retrieval. */ public class ICLayoutManager extends LeafNodeLayoutManager { - private InlineContainer fobj; private List childrenLM; public ICLayoutManager(InlineContainer node, List childLM) { super(node); - fobj = node; childrenLM = childLM; } @@ -44,7 +42,4 @@ public class ICLayoutManager extends LeafNodeLayoutManager { return null; } - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index b449b6689..e9919e02f 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -19,12 +19,13 @@ package org.apache.fop.layoutmgr.inline; -import java.util.ListIterator; import java.util.LinkedList; import java.util.List; +import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineBlockParent; @@ -47,12 +48,12 @@ import org.apache.fop.layoutmgr.InlineKnuthSequence; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthSequence; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.NonLeafPosition; -import org.apache.fop.layoutmgr.SpaceSpecifier; -import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.NonLeafPosition; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.SpaceSpecifier; +import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; @@ -296,7 +297,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { ); } - while ((curLM = (LayoutManager) getChildLM()) != null) { + while ((curLM = getChildLM()) != null) { if (!(curLM instanceof InlineLevelLayoutManager)) { // A block LM @@ -435,7 +436,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // layout context given to lastLM, but must be cleared in the // layout context given to the other LMs. LinkedList positionList = new LinkedList(); - NonLeafPosition pos = null; + NonLeafPosition pos; LayoutManager lastLM = null;// last child LM in this iterator Position lastPos = null; while (parentIter.hasNext()) { @@ -599,9 +600,4 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { return this.auxiliaryPosition; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } - } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index 4d0872a6d..bf1538a7c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -75,15 +75,9 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager private Area currentArea; // LineArea or InlineParent - //private BreakPoss prevBP; - /** The child layout context */ protected LayoutContext childLC; - private boolean bAreaCreated = false; - - //private LayoutManager currentLM = null; - /** Used to store previous content IPD for each child LM. */ private HashMap hmPrevIPD = new HashMap(); @@ -171,14 +165,6 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager } /** - * This method is called by addAreas() so IDs can be added to a page for FOs that - * support the 'id' property. - */ - protected void addId() { - // Do nothing here, overriden in subclasses that have an 'id' property. - } - - /** * Returns the current area. * @return the current area */ @@ -255,7 +241,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager // "unwrap" the Position stored in each element of oldList while (oldListIterator.hasNext()) { element = (KnuthElement) oldListIterator.next(); - element.setPosition(((NonLeafPosition)element.getPosition()).getPosition()); + element.setPosition(element.getPosition().getPosition()); } // The last element may not have a layout manager (its position == null); @@ -288,7 +274,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager // "unwrap" the Position stored in each element of oldList while (oldListIterator.hasNext()) { element = (KnuthElement) oldListIterator.next(); - element.setPosition(((NonLeafPosition)element.getPosition()).getPosition()); + element.setPosition(element.getPosition().getPosition()); } ((InlineLevelLayoutManager) @@ -298,14 +284,14 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager /** {@inheritDoc} */ public void getWordChars(StringBuffer sbChars, Position pos) { - Position newPos = ((NonLeafPosition) pos).getPosition(); + Position newPos = pos.getPosition(); ((InlineLevelLayoutManager) newPos.getLM()).getWordChars(sbChars, newPos); } /** {@inheritDoc} */ public void hyphenate(Position pos, HyphContext hc) { - Position newPos = ((NonLeafPosition) pos).getPosition(); + Position newPos = pos.getPosition(); ((InlineLevelLayoutManager) newPos.getLM()).hyphenate(newPos, hc); } @@ -318,7 +304,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager while (oldListIterator.hasNext()) { oldElement = (KnuthElement) oldListIterator.next(); oldElement.setPosition - (((NonLeafPosition) oldElement.getPosition()).getPosition()); + (oldElement.getPosition().getPosition()); } // reset the iterator oldListIterator = oldList.listIterator(); @@ -385,7 +371,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager while (oldListIterator.hasNext()) { oldElement = (KnuthElement) oldListIterator.next(); oldElement.setPosition - (((NonLeafPosition) oldElement.getPosition()).getPosition()); + (oldElement.getPosition().getPosition()); } // reset the iterator oldListIterator = oldList.listIterator(); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index 5f93ab98c..f4bcde96f 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -339,11 +339,6 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { return returnList; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } - /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index 78d126194..fb5e9ee4d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -65,8 +65,6 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager /** The alignment context applying to this area */ protected AlignmentContext alignmentContext = null; - private MinOptMax ipd; - /** Flag to indicate if something was changed as part of the getChangeKnuthElements sequence */ protected boolean isSomethingChanged = false; /** Our area info for the Knuth elements */ @@ -205,14 +203,6 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager } /** - * This method is called by addAreas() so IDs can be added to a page for FOs that - * support the 'id' property. - */ - protected void addId() { - // Do nothing here, overriden in subclasses that have an 'id' property. - } - - /** * Offset this area. * Offset the inline area in the bpd direction when adding the * inline area. diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 6df7ac00c..9a818232c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -26,6 +26,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.LineArea; import org.apache.fop.area.Trait; @@ -582,9 +583,6 @@ public class LineLayoutManager extends InlineStackingLayoutManager // Get a break from currently active child LM // Set up constraints for inline level managers - // IPD remaining in line - MinOptMax availIPD = context.getStackLimit(); - clearPrevIPD(); //PHASE 1: Create Knuth elements @@ -646,7 +644,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager InlineLevelLayoutManager curLM; LinkedList returnedList = null; - iLineWidth = context.getStackLimit().opt; + iLineWidth = context.getStackLimitIP().opt; // convert all the text in a sequence of paragraphs made // of KnuthBox, KnuthGlue and KnuthPenalty objects @@ -1687,7 +1685,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager */ if (false && textAlignment == EN_JUSTIFY) { // re-compute space adjust ratio - int updatedDifference = context.getStackLimit().opt + int updatedDifference = context.getStackLimitIP().opt - lbp.lineWidth + lbp.difference; double updatedRatio = 0.0; if (updatedDifference > 0) { @@ -1701,12 +1699,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager } else if (false && textAlignment == EN_CENTER) { // re-compute indent int updatedIndent = lbp.startIndent - + (context.getStackLimit().opt - lbp.lineWidth) / 2; + + (context.getStackLimitIP().opt - lbp.lineWidth) / 2; lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); } else if (false && textAlignment == EN_END) { // re-compute indent int updatedIndent = lbp.startIndent - + (context.getStackLimit().opt - lbp.lineWidth); + + (context.getStackLimitIP().opt - lbp.lineWidth); lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); } @@ -1770,7 +1768,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager // set last area flag blocklc.setFlags(LayoutContext.LAST_AREA, (context.isLastArea() && childLM == lastLM)); - blocklc.setStackLimit(context.getStackLimit()); + blocklc.setStackLimitsFrom(context); // Add the line areas to Area childLM.addAreas(childPosIter, blocklc); blocklc.setLeadingSpace(blocklc.getTrailingSpace()); diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java index 88f1d283c..1aaaaf527 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java @@ -42,7 +42,7 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { * Constructor * * @param node the fo:page-number formatting object that creates the area - * @todo better null checking of node, font + * TODO better null checking of node, font */ public PageNumberLayoutManager(PageNumber node) { super(node); @@ -131,9 +131,5 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { return width; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index 470cbbe9c..c17ddc711 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -19,29 +19,29 @@ package org.apache.fop.layoutmgr.list; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; import org.apache.fop.fo.flow.ListBlock; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListUtils; -import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.RelSide; import org.apache.fop.layoutmgr.TraitSetter; -import org.apache.fop.area.Area; -import org.apache.fop.area.Block; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - /** * LayoutManager for a list-block FO. * A list block contains list items which are stacked within @@ -156,11 +156,11 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); } - getPSLM().addIDToPage(getListBlockFO().getId()); + addId(); // the list block contains areas stacked from each list item - LayoutManager childLM = null; + LayoutManager childLM; LayoutContext lc = new LayoutContext(0); LayoutManager firstLM = null; LayoutManager lastLM = null; @@ -181,10 +181,10 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } if (pos instanceof NonLeafPosition && (pos.getPosition() != null) - && ((NonLeafPosition) pos).getPosition().getLM() != this) { + && pos.getPosition().getLM() != this) { // pos was created by a child of this ListBlockLM - positionList.add(((NonLeafPosition) pos).getPosition()); - lastLM = ((NonLeafPosition) pos).getPosition().getLM(); + positionList.add(pos.getPosition()); + lastLM = pos.getPosition().getLM(); if (firstLM == null) { firstLM = lastLM; } @@ -200,7 +200,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); lc.setFlags(LayoutContext.FIRST_AREA, childLM == firstLM); lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM); - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); childLM.addAreas(childPosIter, lc); } @@ -218,7 +218,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(((ListBlock)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** @@ -280,7 +280,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public boolean mustKeepTogether() { //TODO Keeps will have to be more sophisticated sooner or later - return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() + return super.mustKeepTogether() || !getListBlockFO().getKeepTogether().getWithinPage().isAuto() || !getListBlockFO().getKeepTogether().getWithinColumn().isAuto(); } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 853b1a128..8b0028a8f 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -19,24 +19,24 @@ package org.apache.fop.layoutmgr.list; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; import org.apache.fop.fo.flow.AbstractListItemPart; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; -import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition; -import org.apache.fop.area.Area; -import org.apache.fop.area.Block; - -import java.util.Iterator; -import java.util.List; -import java.util.LinkedList; /** * LayoutManager for a list-item-label or list-item-body FO. @@ -115,9 +115,9 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(getPartFO().getId()); + addId(); - LayoutManager childLM = null; + LayoutManager childLM; LayoutContext lc = new LayoutContext(0); LayoutManager firstLM = null; LayoutManager lastLM = null; @@ -141,8 +141,8 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { } if (pos instanceof NonLeafPosition) { // pos was created by a child of this ListBlockLM - positionList.add(((NonLeafPosition) pos).getPosition()); - lastLM = ((NonLeafPosition) pos).getPosition().getLM(); + positionList.add(pos.getPosition()); + lastLM = pos.getPosition().getLM(); if (firstLM == null) { firstLM = lastLM; } @@ -162,7 +162,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM); // set the space adjustment ratio lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); childLM.addAreas(childPosIter, lc); } @@ -172,7 +172,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { curBlockArea = null; - getPSLM().notifyEndOfLayout(((AbstractListItemPart)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index dc28e98e2..c6b5b8cf9 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -19,8 +19,16 @@ package org.apache.fop.layoutmgr.list; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; import org.apache.fop.fo.flow.ListItem; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; @@ -30,28 +38,21 @@ import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.ElementListUtils; -import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.KnuthBox; +import org.apache.fop.layoutmgr.KnuthElement; +import org.apache.fop.layoutmgr.KnuthPenalty; +import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.RelSide; import org.apache.fop.layoutmgr.SpaceResolver; import org.apache.fop.layoutmgr.TraitSetter; -import org.apache.fop.layoutmgr.KnuthElement; -import org.apache.fop.layoutmgr.KnuthBox; -import org.apache.fop.layoutmgr.KnuthPenalty; -import org.apache.fop.layoutmgr.KnuthPossPosIter; -import org.apache.fop.area.Area; -import org.apache.fop.area.Block; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; -import java.util.ArrayList; -import java.util.List; -import java.util.LinkedList; -import java.util.ListIterator; - /** * LayoutManager for a list-item FO. * The list item contains a list item label and a list item body. @@ -72,8 +73,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager private LinkedList labelList = null; private LinkedList bodyList = null; - private int listItemHeight; - private boolean discardBorderBefore; private boolean discardBorderAfter; private boolean discardPaddingBefore; @@ -83,7 +82,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager private boolean keepWithNextPendingOnLabel; private boolean keepWithNextPendingOnBody; - + + private int listItemHeight; + private class ListItemPosition extends Position { private int iLabelFirstIndex; private int iLabelLastIndex; @@ -116,6 +117,11 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ + public boolean generatesAreas() { + return true; + } + + /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer("ListItemPosition:"); sb.append(getIndex()).append("("); @@ -301,12 +307,12 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int additionalPenaltyHeight = 0; KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]); if (endEl instanceof KnuthPenalty) { - additionalPenaltyHeight = ((KnuthPenalty)endEl).getW(); + additionalPenaltyHeight = endEl.getW(); } endEl = (KnuthElement)elementLists[1].get(end[1]); if (endEl instanceof KnuthPenalty) { additionalPenaltyHeight = Math.max( - additionalPenaltyHeight, ((KnuthPenalty)endEl).getW()); + additionalPenaltyHeight, endEl.getW()); } int boxHeight = step - addedBoxHeight - penaltyHeight; @@ -413,10 +419,10 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager // body // "unwrap" the Positions stored in the elements ListIterator oldListIterator = oldList.listIterator(); - KnuthElement oldElement = null; + KnuthElement oldElement; while (oldListIterator.hasNext()) { oldElement = (KnuthElement)oldListIterator.next(); - Position innerPosition = ((NonLeafPosition) oldElement.getPosition()).getPosition(); + Position innerPosition = oldElement.getPosition().getPosition(); //log.debug(" BLM> unwrapping: " + (oldElement.isBox() // ? "box " : (oldElement.isGlue() ? "glue " : "penalty")) // + " creato da " + oldElement.getLayoutManager().getClass().getName()); @@ -459,7 +465,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(getListItemFO().getId()); + addId(); LayoutContext lc = new LayoutContext(0); Position firstPos = null; @@ -478,7 +484,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } if (pos instanceof NonLeafPosition && pos.getPosition() != null) { // pos contains a ListItemPosition created by this ListBlockLM - positionList.add(((NonLeafPosition) pos).getPosition()); + positionList.add(pos.getPosition()); } } @@ -510,7 +516,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager // set the space adjustment ratio lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); // TO DO: use the right stack limit for the label - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); label.addAreas(labelIter, lc); } @@ -531,7 +537,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager // set the space adjustment ratio lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); // TO DO: use the right stack limit for the body - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); body.addAreas(bodyIter, lc); } @@ -554,7 +560,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(((ListItem)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index c1e4ae619..61d0f8e6f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -33,6 +33,8 @@ import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPenalty; +import org.apache.fop.layoutmgr.MinOptMaxUtil; +import org.apache.fop.traits.MinOptMax; /** * A cell playing in the construction of steps for a row-group. @@ -133,6 +135,49 @@ class ActiveCell { } } + // TODO to be removed along with the RowPainter#computeContentLength method + /** See {@link ActiveCell#handleExplicitHeight(MinOptMax, MinOptMax)}. */ + private static class FillerPenalty extends KnuthPenalty { + + private int contentLength; + + FillerPenalty(KnuthPenalty p, int length) { + super(length, p.getP(), p.isFlagged(), p.getBreakClass(), + p.getPosition(), p.isAuxiliary()); + contentLength = p.getW(); + } + + FillerPenalty(int length) { + super(length, 0, false, null, true); + contentLength = 0; + } + } + + /** See {@link ActiveCell#handleExplicitHeight(MinOptMax, MinOptMax)}. */ + private static class FillerBox extends KnuthBox { + FillerBox(int length) { + super(length, null, true); + } + } + + /** + * Returns the actual length of the content represented by the given element. In the + * case where this element is used as a filler to match a row's fixed height, the + * value returned by the getW() method will be higher than the actual content. + * + * @param el an element + * @return the actual content length corresponding to the element + */ + static int getElementContentLength(KnuthElement el) { + if (el instanceof FillerPenalty) { + return ((FillerPenalty) el).contentLength; + } else if (el instanceof FillerBox) { + return 0; + } else { + return el.getW(); + } + } + ActiveCell(PrimaryGridUnit pgu, EffRow row, int rowIndex, int previousRowsLength, TableLayoutManager tableLM) { this.pgu = pgu; @@ -149,23 +194,10 @@ class ActiveCell { + pgu.getBeforeBorderWidth(0, ConditionalBorder.REST); bpAfterNormal = paddingAfterNormal + pgu.getAfterBorderWidth(ConditionalBorder.NORMAL); bpAfterTrailing = paddingAfterTrailing + pgu.getAfterBorderWidth(0, ConditionalBorder.REST); - boolean makeBoxForWholeRow = false; - if (row.getExplicitHeight().min > 0) { - boolean contentsSmaller = ElementListUtils.removeLegalBreaks( - pgu.getElements(), row.getExplicitHeight()); - if (contentsSmaller) { - makeBoxForWholeRow = true; - } - } - if (makeBoxForWholeRow) { - elementList = new java.util.ArrayList(1); - int height = row.getHeight().opt; - height -= 2 * tableLM.getHalfBorderSeparationBPD(); - height -= bpBeforeNormal + bpAfterNormal; - elementList.add(new KnuthBoxCellWithBPD(height)); - } else { - elementList = pgu.getElements(); - } + elementList = pgu.getElements(); + handleExplicitHeight( + MinOptMaxUtil.toMinOptMax(pgu.getCell().getBlockProgressionDimension(), tableLM), + row.getExplicitHeight()); knuthIter = elementList.listIterator(); includedLength = -1; // Avoid troubles with cells having content of zero length totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList); @@ -182,6 +214,46 @@ class ActiveCell { } } + /** + * Modifies the cell's element list by putting filler elements, so that the cell's or + * row's explicit height is always reached. + * + * TODO this will work properly only for the first break. Then the limitation + * explained on http://wiki.apache.org/xmlgraphics-fop/TableLayout/KnownProblems + * occurs. The list of elements needs to be re-adjusted after each break. + */ + private void handleExplicitHeight(MinOptMax cellBPD, MinOptMax rowBPD) { + int minBPD = Math.max(cellBPD.min, rowBPD.min); + if (minBPD > 0) { + ListIterator iter = elementList.listIterator(); + int cumulateLength = 0; + boolean prevIsBox = false; + while (iter.hasNext() && cumulateLength < minBPD) { + KnuthElement el = (KnuthElement) iter.next(); + if (el.isBox()) { + prevIsBox = true; + cumulateLength += el.getW(); + } else if (el.isGlue()) { + if (prevIsBox) { + elementList.add(iter.nextIndex() - 1, + new FillerPenalty(minBPD - cumulateLength)); + } + prevIsBox = false; + cumulateLength += el.getW(); + } else { + prevIsBox = false; + if (cumulateLength + el.getW() < minBPD) { + iter.set(new FillerPenalty((KnuthPenalty) el, minBPD - cumulateLength)); + } + } + } + } + int optBPD = Math.max(minBPD, Math.max(cellBPD.opt, rowBPD.opt)); + if (pgu.getContentLength() < optBPD) { + elementList.add(new FillerBox(optBPD - pgu.getContentLength())); + } + } + PrimaryGridUnit getPrimaryGridUnit() { return pgu; } @@ -265,14 +337,22 @@ class ActiveCell { } /** - * Returns the last step for this cell. + * Returns the last step for this cell. This includes the normal border- and + * padding-before, the whole content, the normal padding-after, and the + * <em>trailing</em> after border. Indeed, if the normal border is taken instead, + * and appears to be smaller than the trailing one, the last step may be smaller than + * the current step (see TableStepper#considerRowLastStep). This will produce a wrong + * infinite penalty, plus the cell's content won't be taken into account since the + * final step will be smaller than the current one (see {@link #signalNextStep(int)}). + * This actually means that the content will be swallowed. * - * @return the step including all of the cell's content plus the normal borders and paddings + * @return the length of last step */ int getLastStep() { assert nextStep.end == elementList.size() - 1; assert nextStep.contentLength == totalLength && nextStep.penaltyLength == 0; - int lastStep = bpBeforeNormal + totalLength + bpAfterNormal; + int lastStep = bpBeforeNormal + totalLength + paddingAfterNormal + + pgu.getAfterBorderWidth(ConditionalBorder.LEADING_TRAILING); log.debug(this + ": last step = " + lastStep); return lastStep; } @@ -394,8 +474,12 @@ class ActiveCell { */ void endRow(int rowIndex) { if (endsOnRow(rowIndex)) { + // Subtract the old value of bpAfterTrailing... + nextStep.totalLength -= bpAfterTrailing; bpAfterTrailing = paddingAfterNormal + pgu.getAfterBorderWidth(ConditionalBorder.LEADING_TRAILING); + // ... and add the new one + nextStep.totalLength += bpAfterTrailing; lastCellPart = true; } else { bpBeforeLeading = paddingBeforeLeading @@ -445,13 +529,6 @@ class ActiveCell { return new CellPart(pgu, nextStep.start, previousStep.end, lastCellPart, 0, 0, previousStep.penaltyLength, bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterTrailing); - } else if (nextStep.start == 0 && nextStep.end == 0 - && elementList.size() == 1 - && elementList.get(0) instanceof KnuthBoxCellWithBPD) { - //Special case: Cell with fixed BPD - return new CellPart(pgu, 0, pgu.getElements().size() - 1, lastCellPart, - nextStep.condBeforeContentLength, length, nextStep.penaltyLength, - bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterTrailing); } else { return new CellPart(pgu, nextStep.start, nextStep.end, lastCellPart, nextStep.condBeforeContentLength, length, nextStep.penaltyLength, @@ -463,20 +540,9 @@ class ActiveCell { return keepWithNextSignal; } - + /** {@inheritDoc} */ public String toString() { return "Cell " + (pgu.getRowIndex() + 1) + "." + (pgu.getColIndex() + 1); } - - - /** - * Marker class denoting table cells fitting in just one box (no legal break inside). - */ - private static class KnuthBoxCellWithBPD extends KnuthBox { - - public KnuthBoxCellWithBPD(int w) { - super(w, null, true); - } - } } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index c2e26e18d..9c97ca827 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -19,16 +19,16 @@ package org.apache.fop.layoutmgr.table; +import java.util.Iterator; import java.util.LinkedList; -import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.Constants; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; +import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.LengthRangeProperty; @@ -94,137 +94,119 @@ class RowGroupLayoutManager { private void createElementsForRowGroup(LayoutContext context, int alignment, int bodyType, LinkedList returnList) { log.debug("Handling row group with " + rowGroup.length + " rows..."); + EffRow row; + for (int rgi = 0; rgi < rowGroup.length; rgi++) { + row = rowGroup[rgi]; + for (Iterator iter = row.getGridUnits().iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + if (gu.isPrimary()) { + PrimaryGridUnit primary = gu.getPrimary(); + // TODO a new LM must be created for every new static-content + primary.createCellLM(); + primary.getCellLM().setParent(tableLM); + //Calculate width of cell + int spanWidth = 0; + Iterator colIter = tableLM.getTable().getColumns().listIterator( + primary.getColIndex()); + for (int i = 0, c = primary.getCell().getNumberColumnsSpanned(); i < c; i++) { + spanWidth += ((TableColumn) colIter.next()).getColumnWidth().getValue( + tableLM); + } + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimitBP(context.getStackLimitBP()); //necessary? + childLC.setRefIPD(spanWidth); + + //Get the element list for the cell contents + LinkedList elems = primary.getCellLM().getNextKnuthElements( + childLC, alignment); + ElementListObserver.observe(elems, "table-cell", primary.getCell().getId()); + primary.setElements(elems); + } + } + } + computeRowHeights(); + LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context, + rowGroup, bodyType); + returnList.addAll(elements); + } + + /** + * Calculate the heights of the rows in the row group, see CSS21, 17.5.3 Table height + * algorithms. + * + * TODO this method will need to be adapted once clarification has been made by the + * W3C regarding whether borders or border-separation must be included or not + */ + private void computeRowHeights() { + log.debug("rowGroup:"); MinOptMax[] rowHeights = new MinOptMax[rowGroup.length]; - MinOptMax[] explicitRowHeights = new MinOptMax[rowGroup.length]; EffRow row; - List pgus = new java.util.ArrayList(); //holds a list of a row's primary grid units for (int rgi = 0; rgi < rowGroup.length; rgi++) { row = rowGroup[rgi]; - rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE); - explicitRowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE); - - pgus.clear(); - TableRow tableRow = null; - // The row's minimum content height; 0 if the row's height is auto, otherwise - // the .minimum component of the explicitly specified value - int minRowBPD = 0; // The BPD of the biggest cell in the row - int maxCellBPD = 0; - for (int j = 0; j < row.getGridUnits().size(); j++) { - GridUnit gu = row.getGridUnit(j); - if ((gu.isPrimary() || (gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan())) - && !gu.isEmpty()) { +// int maxCellBPD = 0; + MinOptMax explicitRowHeight; + TableRow tableRowFO = rowGroup[rgi].getTableRow(); + if (tableRowFO == null) { + rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE); + explicitRowHeight = new MinOptMax(0, 0, Integer.MAX_VALUE); + } else { + LengthRangeProperty rowBPD = tableRowFO.getBlockProgressionDimension(); + rowHeights[rgi] = MinOptMaxUtil.toMinOptMax(rowBPD, tableLM); + explicitRowHeight = MinOptMaxUtil.toMinOptMax(rowBPD, tableLM); + } + for (Iterator iter = row.getGridUnits().iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) { PrimaryGridUnit primary = gu.getPrimary(); - - if (gu.isPrimary()) { - // TODO a new LM must be created for every new static-content - primary.createCellLM(); - primary.getCellLM().setParent(tableLM); - - //Determine the table-row if any - if (tableRow == null && primary.getRow() != null) { - tableRow = primary.getRow(); - - //Check for bpd on row, see CSS21, 17.5.3 Table height algorithms - LengthRangeProperty rowBPD = tableRow.getBlockProgressionDimension(); - if (!rowBPD.getMinimum(tableLM).isAuto()) { - minRowBPD = Math.max(minRowBPD, - rowBPD.getMinimum(tableLM).getLength().getValue(tableLM)); - } - MinOptMaxUtil.restrict(explicitRowHeights[rgi], rowBPD, tableLM); - - } - - //Calculate width of cell - int spanWidth = 0; - for (int i = primary.getColIndex(); - i < primary.getColIndex() - + primary.getCell().getNumberColumnsSpanned(); - i++) { - if (tableLM.getColumns().getColumn(i + 1) != null) { - spanWidth += tableLM.getColumns().getColumn(i + 1) - .getColumnWidth().getValue(tableLM); - } - } - LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(context.getStackLimit()); //necessary? - childLC.setRefIPD(spanWidth); - - //Get the element list for the cell contents - LinkedList elems = primary.getCellLM().getNextKnuthElements( - childLC, alignment); - ElementListObserver.observe(elems, "table-cell", primary.getCell().getId()); - primary.setElements(elems); + int effectiveCellBPD = 0; + LengthRangeProperty cellBPD = primary.getCell().getBlockProgressionDimension(); + if (!cellBPD.getMinimum(tableLM).isAuto()) { + effectiveCellBPD = cellBPD.getMinimum(tableLM).getLength() + .getValue(tableLM); } - - //Calculate height of row, see CSS21, 17.5.3 Table height algorithms - if (gu.isLastGridUnitRowSpan()) { - // The effective cell's bpd, after taking into account bpd - // (possibly explicitly) set on the row or on the cell, and the - // cell's content length - int effectiveCellBPD = minRowBPD; - LengthRangeProperty cellBPD = primary.getCell() - .getBlockProgressionDimension(); - if (!cellBPD.getMinimum(tableLM).isAuto()) { - effectiveCellBPD = Math.max(effectiveCellBPD, - cellBPD.getMinimum(tableLM).getLength().getValue(tableLM)); - } - if (!cellBPD.getOptimum(tableLM).isAuto()) { - effectiveCellBPD = Math.max(effectiveCellBPD, - cellBPD.getOptimum(tableLM).getLength().getValue(tableLM)); - } - if (gu.getRowSpanIndex() == 0) { - //TODO ATM only non-row-spanned cells are taken for this - MinOptMaxUtil.restrict(explicitRowHeights[rgi], cellBPD, tableLM); - } - effectiveCellBPD = Math.max(effectiveCellBPD, - primary.getContentLength()); - - int borderWidths = primary.getBeforeAfterBorderWidth(); - int padding = 0; - maxCellBPD = Math.max(maxCellBPD, effectiveCellBPD); - CommonBorderPaddingBackground cbpb - = primary.getCell().getCommonBorderPaddingBackground(); - padding += cbpb.getPaddingBefore(false, primary.getCellLM()); - padding += cbpb.getPaddingAfter(false, primary.getCellLM()); - int effRowHeight = effectiveCellBPD - + padding + borderWidths; - for (int previous = 0; previous < gu.getRowSpanIndex(); previous++) { - effRowHeight -= rowHeights[rgi - previous - 1].opt; - } - if (effRowHeight > rowHeights[rgi].min) { - //This is the new height of the (grid) row - MinOptMaxUtil.extendMinimum(rowHeights[rgi], effRowHeight, false); - } + if (!cellBPD.getOptimum(tableLM).isAuto()) { + effectiveCellBPD = cellBPD.getOptimum(tableLM).getLength() + .getValue(tableLM); } - - if (gu.isPrimary()) { - pgus.add(primary); + if (gu.getRowSpanIndex() == 0) { + effectiveCellBPD = Math.max(effectiveCellBPD, explicitRowHeight.opt); + } + effectiveCellBPD = Math.max(effectiveCellBPD, primary.getContentLength()); + int borderWidths = primary.getBeforeAfterBorderWidth(); + int padding = 0; + CommonBorderPaddingBackground cbpb = primary.getCell() + .getCommonBorderPaddingBackground(); + padding += cbpb.getPaddingBefore(false, primary.getCellLM()); + padding += cbpb.getPaddingAfter(false, primary.getCellLM()); + int effRowHeight = effectiveCellBPD + padding + borderWidths; + for (int prev = rgi - 1; prev >= rgi - gu.getRowSpanIndex(); prev--) { + effRowHeight -= rowHeights[prev].opt; + } + if (effRowHeight > rowHeights[rgi].min) { + // This is the new height of the (grid) row + MinOptMaxUtil.extendMinimum(rowHeights[rgi], effRowHeight); } } } row.setHeight(rowHeights[rgi]); - row.setExplicitHeight(explicitRowHeights[rgi]); - if (maxCellBPD > row.getExplicitHeight().max) { - log.warn(FONode.decorateWithContextInfo( - "The contents of row " + (row.getIndex() + 1) - + " are taller than they should be (there is a" - + " block-progression-dimension or height constraint on the indicated row)." - + " Due to its contents the row grows" - + " to " + maxCellBPD + " millipoints, but the row shouldn't get" - + " any taller than " + row.getExplicitHeight() + " millipoints.", - row.getTableRow())); - } - } - if (log.isDebugEnabled()) { - log.debug("rowGroup:"); - for (int i = 0; i < rowHeights.length; i++) { - log.debug(" height=" + rowHeights[i] + " explicit=" + explicitRowHeights[i]); + row.setExplicitHeight(explicitRowHeight); + // TODO re-enable and improve after clarification +// if (maxCellBPD > row.getExplicitHeight().max) { +// log.warn(FONode.decorateWithContextInfo( +// "The contents of row " + (row.getIndex() + 1) +// + " are taller than they should be (there is a" +// + " block-progression-dimension or height constraint +// + " on the indicated row)." +// + " Due to its contents the row grows" +// + " to " + maxCellBPD + " millipoints, but the row shouldn't get" +// + " any taller than " + row.getExplicitHeight() + " millipoints.", +// row.getTableRow())); +// } + if (log.isDebugEnabled()) { + log.debug(" height=" + rowHeights[rgi] + " explicit=" + explicitRowHeight); } } - LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context, - rowGroup, bodyType); - returnList.addAll(elements); } } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 022ff0589..bed9c53ae 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -23,25 +23,27 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.area.Block; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; -import org.apache.fop.fo.flow.table.TableRow; +import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.SpaceResolver; +import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.BorderProps; class RowPainter { private static Log log = LogFactory.getLog(RowPainter.class); - /** The fo:table-row containing the currently handled grid rows. */ - private TableRow rowFO = null; private int colCount; private int currentRowOffset = 0; /** Currently handled row (= last encountered row). */ @@ -71,6 +73,13 @@ class RowPainter { private CellPart[] firstCellParts; private CellPart[] lastCellParts; + /** y-offset of the current table part. */ + private int tablePartOffset = 0; + /** See {@link RowPainter#registerPartBackgroundArea(Block)}. */ + private CommonBorderPaddingBackground tablePartBackground; + /** See {@link RowPainter#registerPartBackgroundArea(Block)}. */ + private List tablePartBackgroundAreas; + private TableContentLayoutManager tclm; RowPainter(TableContentLayoutManager tclm, LayoutContext layoutContext) { @@ -85,6 +94,44 @@ class RowPainter { this.firstRowOnPageIndex = -1; } + void startTablePart(TableBody tablePart) { + CommonBorderPaddingBackground background = tablePart.getCommonBorderPaddingBackground(); + if (background.hasBackground()) { + tablePartBackground = background; + if (tablePartBackgroundAreas == null) { + tablePartBackgroundAreas = new ArrayList(); + } + } + tablePartOffset = currentRowOffset; + } + + /** + * Signals that the end of the current table part is reached. + * + * @param lastInBody true if the part is the last table-body element to be displayed + * on the current page. In which case all the cells must be flushed even if they + * aren't finished, plus the proper collapsed borders must be selected (trailing + * instead of normal, or rest if the cell is unfinished) + * @param lastOnPage true if the part is the last to be displayed on the current page. + * In which case collapsed after borders for the cells on the last row must be drawn + * in the outer mode + */ + void endTablePart(boolean lastInBody, boolean lastOnPage) { + addAreasAndFlushRow(lastInBody, lastOnPage); + + if (tablePartBackground != null) { + TableLayoutManager tableLM = tclm.getTableLM(); + for (Iterator iter = tablePartBackgroundAreas.iterator(); iter.hasNext();) { + Block backgroundArea = (Block) iter.next(); + TraitSetter.addBackground(backgroundArea, tablePartBackground, tableLM, + -backgroundArea.getXOffset(), tablePartOffset - backgroundArea.getYOffset(), + tableLM.getContentAreaIPD(), currentRowOffset - tablePartOffset); + } + tablePartBackground = null; + tablePartBackgroundAreas.clear(); + } + } + int getAccumulatedBPD() { return currentRowOffset; } @@ -108,7 +155,6 @@ class RowPainter { currentRow = row; } } - rowFO = currentRow.getTableRow(); if (firstRowIndex < 0) { firstRowIndex = currentRow.getIndex(); if (firstRowOnPageIndex < 0) { @@ -148,7 +194,7 @@ class RowPainter { * displayed on the current page. In which case collapsed after borders must be drawn * in the outer mode */ - void addAreasAndFlushRow(boolean lastInPart, boolean lastOnPage) { + private void addAreasAndFlushRow(boolean lastInPart, boolean lastOnPage) { if (log.isDebugEnabled()) { log.debug("Remembering yoffset for row " + currentRow.getIndex() + ": " + currentRowOffset); @@ -182,8 +228,6 @@ class RowPainter { } // Then add areas for cells finishing on the current row - tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(), - currentRowOffset); for (int i = 0; i < colCount; i++) { GridUnit currentGU = currentRow.getGridUnit(i); if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 @@ -255,18 +299,22 @@ class RowPainter { // cell, in most cases) return 0; } else { - int actualStart = startIndex; + ListIterator iter = pgu.getElements().listIterator(startIndex); // Skip from the content length calculation glues and penalties occurring at the // beginning of the page - while (actualStart <= endIndex - && !((KnuthElement) pgu.getElements().get(actualStart)).isBox()) { - actualStart++; + boolean nextIsBox = false; + while (iter.nextIndex() <= endIndex && !nextIsBox) { + nextIsBox = ((KnuthElement) iter.next()).isBox(); } - int len = ElementListUtils.calcContentLength( - pgu.getElements(), actualStart, endIndex); - KnuthElement el = (KnuthElement)pgu.getElements().get(endIndex); - if (el.isPenalty()) { - len += el.getW(); + int len = 0; + if (((KnuthElement) iter.previous()).isBox()) { + while (iter.nextIndex() < endIndex) { + KnuthElement el = (KnuthElement) iter.next(); + if (el.isBox() || el.isGlue()) { + len += el.getW(); + } + } + len += ActiveCell.getElementContentLength((KnuthElement) iter.next()); } return len; } @@ -278,8 +326,20 @@ class RowPainter { * Determine the index of the first row of this cell that will be displayed on the * current page. */ - int startRowIndex = Math.max(pgu.getRowIndex(), firstRowIndex); int currentRowIndex = currentRow.getIndex(); + int startRowIndex; + int firstRowHeight; + if (pgu.getRowIndex() >= firstRowIndex) { + startRowIndex = pgu.getRowIndex(); + if (startRowIndex < currentRowIndex) { + firstRowHeight = getRowOffset(startRowIndex + 1) - getRowOffset(startRowIndex); + } else { + firstRowHeight = rowHeight; + } + } else { + startRowIndex = firstRowIndex; + firstRowHeight = 0; + } /* * In collapsing-border model, if the cell spans over several columns/rows then @@ -319,7 +379,25 @@ class RowPainter { cellLM.addAreas(new KnuthPossPosIter(pgu.getElements(), startPos, endPos + 1), layoutContext, spannedGridRowHeights, startRowIndex - pgu.getRowIndex(), currentRowIndex - pgu.getRowIndex(), borderBeforeWhich, borderAfterWhich, - startRowIndex == firstRowOnPageIndex, lastOnPage); + startRowIndex == firstRowOnPageIndex, lastOnPage, this, firstRowHeight); + } + + + /** + * Registers the given area, that will be used to render the part of + * table-header/footer/body background covered by a table-cell. If percentages are + * used to place the background image, the final bpd of the (fraction of) table part + * that will be rendered on the current page must be known. The traits can't then be + * set when the areas for the cell are created since at that moment this bpd is yet + * unknown. So they will instead be set in + * {@link #addAreasAndFlushRow(boolean, boolean)}. + * + * @param backgroundArea the block of the cell's dimensions that will hold the part + * background + */ + void registerPartBackgroundArea(Block backgroundArea) { + tclm.getTableLM().addBackgroundArea(backgroundArea); + tablePartBackgroundAreas.add(backgroundArea); } /** @@ -357,11 +435,13 @@ class RowPainter { } // TODO get rid of that + /** Signals that the first table-body instance has started. */ void startBody() { Arrays.fill(firstCellOnPage, true); } // TODO get rid of that + /** Signals that the last table-body instance has ended. */ void endBody() { Arrays.fill(firstCellOnPage, false); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java index 6d2e49e96..2e5bbdf1f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -23,7 +23,6 @@ import org.apache.fop.fo.flow.table.TableAndCaption; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -36,8 +35,7 @@ import org.apache.fop.area.Block; * @todo Implement getNextKnuthElements() */ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { - private TableAndCaption fobj; - + private Block curBlockArea; //private List childBreaks = new java.util.ArrayList(); @@ -48,7 +46,6 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { */ public TableAndCaptionLayoutManager(TableAndCaption node) { super(node); - fobj = node; } /** @@ -134,7 +131,7 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(fobj.getId()); + addId(); /* TODO: Reimplement using Knuth approach LayoutManager childLM; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java index 4c21df937..674fd9a90 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java @@ -23,7 +23,6 @@ import org.apache.fop.fo.flow.table.TableCaption; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -34,7 +33,6 @@ import org.apache.fop.area.Block; * @todo Implement getNextKnuthElements() */ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { - private TableCaption fobj; private Block curBlockArea; @@ -46,7 +44,6 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { */ public TableCaptionLayoutManager(TableCaption node) { super(node); - fobj = node; } /** @@ -133,7 +130,7 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(fobj.getId()); + addId(); /* TODO: Reimplement using Knuth approach LayoutManager childLM; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 289785d68..8acfebca0 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -23,16 +23,19 @@ import java.util.LinkedList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.Trait; import org.apache.fop.datatypes.PercentBaseContext; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.flow.table.Table; +import org.apache.fop.fo.flow.table.TableBody; import org.apache.fop.fo.flow.table.TableCell; +import org.apache.fop.fo.flow.table.TableColumn; +import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.layoutmgr.AreaAdditionUtil; @@ -71,9 +74,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager private int xoffset; private int yoffset; private int cellIPD; - private int rowHeight; + private int totalHeight; private int usedBPD; - private int borderAndPaddingBPD; private boolean emptyCell = true; /** @@ -96,31 +98,11 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager return getTable().isSeparateBorderModel(); } - /** {@inheritDoc} */ - public void initialize() { - borderAndPaddingBPD = 0; - borderAndPaddingBPD += getTableCell() - .getCommonBorderPaddingBackground().getBorderBeforeWidth(false); - borderAndPaddingBPD += getTableCell() - .getCommonBorderPaddingBackground().getBorderAfterWidth(false); - if (!isSeparateBorderModel()) { - borderAndPaddingBPD /= 2; - } - borderAndPaddingBPD += getTableCell().getCommonBorderPaddingBackground() - .getPaddingBefore(false, this); - borderAndPaddingBPD += getTableCell().getCommonBorderPaddingBackground() - .getPaddingAfter(false, this); - } - /** * @return the table owning this cell */ public Table getTable() { - FONode node = fobj.getParent(); - while (!(node instanceof Table)) { - node = node.getParent(); - } - return (Table)node; + return getTableCell().getTable(); } @@ -148,13 +130,13 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * {@inheritDoc} */ public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { - MinOptMax stackLimit = new MinOptMax(context.getStackLimit()); + MinOptMax stackLimit = new MinOptMax(context.getStackLimitBP()); referenceIPD = context.getRefIPD(); cellIPD = referenceIPD; cellIPD -= getIPIndents(); - LinkedList returnedList = null; + LinkedList returnedList; LinkedList contentList = new LinkedList(); LinkedList returnList = new LinkedList(); @@ -163,8 +145,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); // curLM is a ? - childLC.setStackLimit(MinOptMax.subtract(context - .getStackLimit(), stackLimit)); + childLC.setStackLimitBP(MinOptMax.subtract(context + .getStackLimitBP(), stackLimit)); childLC.setRefIPD(cellIPD); // get elements from curLM @@ -260,7 +242,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager p.setP(0); } - getPSLM().notifyEndOfLayout(((TableCell)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); setFinished(true); return returnList; @@ -303,7 +285,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * @param h the height of cell */ public void setTotalHeight(int h) { - rowHeight = h; + totalHeight = h; } /** @@ -330,6 +312,10 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * which case collapsed before borders must be drawn in the outer mode * @param lastOnPage true if the cell will be the very last one on the page, in which * case collapsed after borders must be drawn in the outer mode + * @param painter painter + * @param firstRowHeight height of the first row spanned by this cell (may be zero if + * this row is placed on a previous page). Used to calculate the placement of the + * row's background image if any */ public void addAreas(PositionIterator parentIter, LayoutContext layoutContext, @@ -339,13 +325,25 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager int borderBeforeWhich, int borderAfterWhich, boolean firstOnPage, - boolean lastOnPage) { + boolean lastOnPage, + RowPainter painter, + int firstRowHeight) { getParentArea(null); - getPSLM().addIDToPage(getTableCell().getId()); + addId(); int borderBeforeWidth = primaryGridUnit.getBeforeBorderWidth(startRow, borderBeforeWhich); int borderAfterWidth = primaryGridUnit.getAfterBorderWidth(endRow, borderAfterWhich); + + CommonBorderPaddingBackground padding = primaryGridUnit.getCell() + .getCommonBorderPaddingBackground(); + int paddingRectBPD = totalHeight - borderBeforeWidth - borderAfterWidth; + int cellBPD = paddingRectBPD; + cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this); + cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this); + + addBackgroundAreas(painter, firstRowHeight, borderBeforeWidth, paddingRectBPD); + if (isSeparateBorderModel()) { if (!emptyCell || getTableCell().showEmptyCells()) { if (borderBeforeWidth > 0) { @@ -421,7 +419,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager int dx = xoffset; for (int x = 0; x < gridUnits.length; x++) { int ipd = getTable().getColumn(primaryGridUnit.getColIndex() + x) - .getColumnWidth().getValue((PercentBaseContext) getParent()); + .getColumnWidth().getValue(getParent()); if (blocks[y][x] != null) { Block block = blocks[y][x]; adjustYOffset(block, dy); @@ -437,18 +435,12 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } } - CommonBorderPaddingBackground padding = primaryGridUnit.getCell() - .getCommonBorderPaddingBackground(); TraitSetter.addPadding(curBlockArea, padding, borderBeforeWhich == ConditionalBorder.REST, borderAfterWhich == ConditionalBorder.REST, false, false, this); - int cellBPD = rowHeight - borderBeforeWidth - borderAfterWidth; - cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this); - cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this); - //Handle display-align if (usedBPD < cellBPD) { if (getTableCell().getDisplayAlign() == EN_CENTER) { @@ -468,16 +460,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager curBlockArea.setBPD(cellBPD); // Add background after we know the BPD - if (isSeparateBorderModel()) { - if (!emptyCell || getTableCell().showEmptyCells()) { - TraitSetter.addBackground(curBlockArea, - getTableCell().getCommonBorderPaddingBackground(), - this); - } - } else { + if (!isSeparateBorderModel() || !emptyCell || getTableCell().showEmptyCells()) { TraitSetter.addBackground(curBlockArea, - getTableCell().getCommonBorderPaddingBackground(), - this); + getTableCell().getCommonBorderPaddingBackground(), this); } flush(); @@ -485,6 +470,33 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager curBlockArea = null; } + /** Adds background areas for the column, body and row, if any. */ + private void addBackgroundAreas(RowPainter painter, int firstRowHeight, int borderBeforeWidth, + int paddingRectBPD) { + TableColumn column = getTable().getColumn(primaryGridUnit.getColIndex()); + if (column.getCommonBorderPaddingBackground().hasBackground()) { + Block colBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth); + ((TableLayoutManager) parentLM).registerColumnBackgroundArea(column, colBackgroundArea, + -startIndent); + } + + TableBody body = primaryGridUnit.getTableBody(); + if (body.getCommonBorderPaddingBackground().hasBackground()) { + painter.registerPartBackgroundArea( + getBackgroundArea(paddingRectBPD, borderBeforeWidth)); + } + + TableRow row = primaryGridUnit.getRow(); + if (row != null && row.getCommonBorderPaddingBackground().hasBackground()) { + Block rowBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth); + ((TableLayoutManager) parentLM).addBackgroundArea(rowBackgroundArea); + TraitSetter.addBackground(rowBackgroundArea, row.getCommonBorderPaddingBackground(), + parentLM, + -xoffset - startIndent, -borderBeforeWidth, + parentLM.getContentAreaIPD(), firstRowHeight); + } + } + private void addBorder(Block[][] blocks, int i, int j, Integer side, BorderInfo border, boolean outer) { if (blocks[i][j] == null) { @@ -513,6 +525,21 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager block.setBPD(block.getBPD() + amount); } + private Block getBackgroundArea(int bpd, int borderBeforeWidth) { + CommonBorderPaddingBackground padding = getTableCell().getCommonBorderPaddingBackground(); + int paddingStart = padding.getPaddingStart(false, this); + int paddingEnd = padding.getPaddingEnd(false, this); + + Block block = new Block(); + TraitSetter.setProducerID(block, getTable().getId()); + block.setPositioning(Block.ABSOLUTE); + block.setIPD(cellIPD + paddingStart + paddingEnd); + block.setBPD(bpd); + block.setXOffset(xoffset + startIndent - paddingStart); + block.setYOffset(yoffset + borderBeforeWidth); + return block; + } + /** * Return an Area which can contain the passed childArea. The childArea * may not yet have any content, but it has essential traits set. diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index b9a118e28..7cdeb79d5 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -27,8 +27,6 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.area.Block; -import org.apache.fop.area.Trait; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; @@ -36,7 +34,6 @@ import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; -import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthBox; @@ -46,7 +43,6 @@ import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.ListElement; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition; import org.apache.fop.util.BreakUtil; @@ -293,7 +289,7 @@ public class TableContentLayoutManager implements PercentBaseContext { this.usedBPD = 0; RowPainter painter = new RowPainter(this, layoutContext); - List positions = new java.util.ArrayList(); + List tablePositions = new ArrayList(); List headerElements = null; List footerElements = null; Position firstPos = null; @@ -330,7 +326,7 @@ public class TableContentLayoutManager implements PercentBaseContext { //ignore for now, see special handling below if break is at a penalty //Only if the last position in this part/page us such a position it will be used } else if (pos instanceof TableContentPosition) { - positions.add(pos); + tablePositions.add(pos); } else { if (log.isDebugEnabled()) { log.debug("Ignoring position: " + pos); @@ -359,21 +355,23 @@ public class TableContentLayoutManager implements PercentBaseContext { if (headerElements != null) { //header positions for the last part are the second-to-last element and need to //be handled first before all other TableContentPositions - PositionIterator nestedIter = new KnuthPossPosIter(headerElements); - iterateAndPaintPositions(nestedIter, painter, false); + addHeaderFooterAreas(headerElements, tableLM.getTable().getTableHeader(), painter, + false); } - //Iterate over all steps - Iterator posIter = positions.iterator(); - painter.startBody(); - // Here we are sure that posIter iterates only over TableContentPosition instances - iterateAndPaintPositions(posIter, painter, footerElements == null); - painter.endBody(); + if (tablePositions.isEmpty()) { + // TODO make sure this actually never happens + log.error("tablePositions empty." + + " Please send your FO file to fop-users@xmlgraphics.apache.org"); + } else { + // Here we are sure that posIter iterates only over TableContentPosition instances + addBodyAreas(tablePositions.iterator(), painter, footerElements == null); + } if (footerElements != null) { //Positions for footers are simply added at the end - PositionIterator nestedIter = new KnuthPossPosIter(footerElements); - iterateAndPaintPositions(nestedIter, painter, true); + addHeaderFooterAreas(footerElements, tableLM.getTable().getTableFooter(), painter, + true); } this.usedBPD += painter.getAccumulatedBPD(); @@ -384,106 +382,74 @@ public class TableContentLayoutManager implements PercentBaseContext { } } + private void addHeaderFooterAreas(List elements, TableBody part, RowPainter painter, + boolean lastOnPage) { + List lst = new ArrayList(elements.size()); + for (Iterator iter = new KnuthPossPosIter(elements); iter.hasNext();) { + Position pos = (Position) iter.next(); + /* + * Unlike for the body the Positions associated to the glues generated by + * TableStepper haven't been removed yet. + */ + if (pos instanceof TableContentPosition) { + lst.add((TableContentPosition) pos); + } + } + addTablePartAreas(lst, painter, part, true, true, true, lastOnPage); + } + /** - * Iterates over a part of the table (header, footer, body) and paints the related - * elements. + * Iterates over the positions corresponding to the table's body (which may contain + * several table-body elements!) and adds the corresponding areas. * - * @param iterator iterator over Position elements. Those positions correspond to the - * elements of the table present on the current page + * @param iterator iterator over TableContentPosition elements. Those positions + * correspond to the elements of the body present on the current page * @param painter - * @param lastOnPage true if the corresponding part will be the last on the page - * (either body or footer, obviously) + * @param lastOnPage true if the table has no footer (then the last line of the table + * that will be present on the page belongs to the body) */ - private void iterateAndPaintPositions(Iterator iterator, RowPainter painter, + private void addBodyAreas(Iterator iterator, RowPainter painter, boolean lastOnPage) { + painter.startBody(); List lst = new ArrayList(); - boolean firstPos = false; - TableBody body = null; + TableContentPosition pos = (TableContentPosition) iterator.next(); + boolean isFirstPos = pos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP) + && pos.getRow().getFlag(EffRow.FIRST_IN_PART); + TableBody body = pos.getTableBody(); + lst.add(pos); while (iterator.hasNext()) { - Position pos = (Position)iterator.next(); - if (pos instanceof TableContentPosition) { - TableContentPosition tcpos = (TableContentPosition)pos; - lst.add(tcpos); - CellPart part = (CellPart)tcpos.cellParts.get(0); - if (body == null) { - body = part.pgu.getBody(); - } - if (tcpos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP) - && tcpos.getRow().getFlag(EffRow.FIRST_IN_PART)) { - firstPos = true; - - } - if (tcpos.getFlag(TableContentPosition.LAST_IN_ROWGROUP) - && tcpos.getRow().getFlag(EffRow.LAST_IN_PART)) { - log.trace("LAST_IN_ROWGROUP + LAST_IN_PART"); - handleMarkersAndPositions(lst, body, firstPos, true, painter); - //reset - firstPos = false; - body = null; - lst.clear(); - } + pos = (TableContentPosition) iterator.next(); + if (pos.getTableBody() != body) { + addTablePartAreas(lst, painter, body, isFirstPos, true, false, false); + isFirstPos = true; + lst.clear(); + body = pos.getTableBody(); } + lst.add(pos); } - if (body != null) { - // Entering this block means that the end of the current table-part hasn't - // been reached (otherwise it would have been caught by the test above). So - // lastPos is necessarily false - handleMarkersAndPositions(lst, body, firstPos, false, painter); - } - painter.addAreasAndFlushRow(true, lastOnPage); - } - - private void handleMarkersAndPositions(List positions, TableBody body, boolean firstPos, - boolean lastPos, RowPainter painter) { - getTableLM().getCurrentPV().addMarkers(body.getMarkers(), - true, firstPos, lastPos); - int size = positions.size(); - for (int i = 0; i < size; i++) { - painter.handleTableContentPosition((TableContentPosition)positions.get(i)); - } - getTableLM().getCurrentPV().addMarkers(body.getMarkers(), - false, firstPos, lastPos); + boolean isLastPos = pos.getFlag(TableContentPosition.LAST_IN_ROWGROUP) + && pos.getRow().getFlag(EffRow.LAST_IN_PART); + addTablePartAreas(lst, painter, body, isFirstPos, isLastPos, true, lastOnPage); + painter.endBody(); } /** - * Get the area for a row for background. - * @param row the table-row object or null - * @return the row area or null if there's no background to paint + * Adds the areas corresponding to a single fo:table-header/footer/body element. */ - Block getRowArea(TableRow row) { - if (row == null || !row.getCommonBorderPaddingBackground().hasBackground()) { - return null; - } else { - Block block = new Block(); - block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); - block.setPositioning(Block.ABSOLUTE); - return block; + private void addTablePartAreas(List positions, RowPainter painter, TableBody body, + boolean isFirstPos, boolean isLastPos, boolean lastInBody, boolean lastOnPage) { + getTableLM().getCurrentPV().addMarkers(body.getMarkers(), + true, isFirstPos, isLastPos); + painter.startTablePart(body); + for (Iterator iter = positions.iterator(); iter.hasNext();) { + painter.handleTableContentPosition((TableContentPosition) iter.next()); } + getTableLM().getCurrentPV().addMarkers(body.getMarkers(), + false, isFirstPos, isLastPos); + painter.endTablePart(lastInBody, lastOnPage); } /** - * Adds the area for the row background if any. - * @param row row for which to generate the background - * @param bpd block-progression-dimension of the row - * @param ipd inline-progression-dimension of the row - * @param yoffset Y offset at which to paint - */ - void addRowBackgroundArea(TableRow row, int bpd, int ipd, int yoffset) { - //Add row background if any - Block rowBackground = getRowArea(row); - if (rowBackground != null) { - rowBackground.setBPD(bpd); - rowBackground.setIPD(ipd); - rowBackground.setXOffset(this.startXOffset); - rowBackground.setYOffset(yoffset); - getTableLM().addChildArea(rowBackground); - TraitSetter.addBackground(rowBackground, - row.getCommonBorderPaddingBackground(), getTableLM()); - } - } - - - /** * Sets the overall starting x-offset. Used for proper placement of cells. * @param startXOffset starting x-offset (table's start-indent) */ diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java index e702c58a9..260b8cfdf 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java @@ -22,6 +22,7 @@ package org.apache.fop.layoutmgr.table; import java.util.List; import org.apache.fop.fo.flow.table.EffRow; +import org.apache.fop.fo.flow.table.TableBody; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.Position; @@ -79,6 +80,10 @@ class TableContentPosition extends Position { return row; } + TableBody getTableBody() { + return ((CellPart) cellParts.get(0)).pgu.getTableBody(); + } + /** * Returns a flag for this GridUnit. * @param which the requested flag @@ -101,10 +106,12 @@ class TableContentPosition extends Position { } } + /** {@inheritDoc} */ public boolean generatesAreas() { return true; } + /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer("TableContentPosition:"); sb.append(getIndex()); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java index afa166985..3e504a45c 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java @@ -43,6 +43,11 @@ class TableHFPenaltyPosition extends Position { super(lm); } + /** {@inheritDoc} */ + public boolean generatesAreas() { + return true; + } + public String toString() { StringBuffer sb = new StringBuffer("TableHFPenaltyPosition:"); sb.append(getIndex()).append("("); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java index c3ae72c74..8d3b993b2 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java @@ -48,6 +48,11 @@ class TableHeaderFooterPosition extends Position { this.nestedElements = nestedElements; } + /** {@inheritDoc} */ + public boolean generatesAreas() { + return true; + } + public String toString() { StringBuffer sb = new StringBuffer("Table"); sb.append(header ? "Header" : "Footer"); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 1cbc3e50a..d6bba5cb5 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -19,8 +19,10 @@ package org.apache.fop.layoutmgr.table; +import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -79,7 +81,27 @@ public class TableLayoutManager extends BlockStackingLayoutManager private int halfBorderSeparationBPD; private int halfBorderSeparationIPD; - + + /** See {@link TableLayoutManager#registerColumnBackgroundArea(TableColumn, Block, int)}. */ + private List columnBackgroundAreas; + + /** + * Temporary holder of column background informations for a table-cell's area. + * + * @see TableLayoutManager#registerColumnBackgroundArea(TableColumn, Block, int) + */ + private static final class ColumnBackgroundInfo { + private TableColumn column; + private Block backgroundArea; + private int xShift; + + private ColumnBackgroundInfo(TableColumn column, Block backgroundArea, int xShift) { + this.column = column; + this.backgroundArea = backgroundArea; + this.xShift = xShift; + } + } + /** * Create a new table layout manager. * @param node the table FO @@ -211,7 +233,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager // Elements for the table-header/footer/body - LinkedList contentKnuthElements = null; + LinkedList contentKnuthElements; contentLM = new TableContentLayoutManager(this); LayoutContext childLC = new LayoutContext(0); /* @@ -263,7 +285,30 @@ public class TableLayoutManager extends BlockStackingLayoutManager resetSpaces(); return returnList; } - + + /** + * Registers the given area, that will be used to render the part of column background + * covered by a table-cell. If percentages are used to place the background image, the + * final bpd of the (fraction of) table that will be rendered on the current page must + * be known. The traits can't then be set when the areas for the cell are created + * since at that moment this bpd is yet unknown. So they will instead be set in + * TableLM's {@link #addAreas(PositionIterator, LayoutContext)} method. + * + * @param column the table-column element from which the cell gets background + * informations + * @param backgroundArea the block of the cell's dimensions that will hold the column + * background + * @param xShift additional amount by which the image must be shifted to be correctly + * placed (to counterbalance the cell's start border) + */ + void registerColumnBackgroundArea(TableColumn column, Block backgroundArea, int xShift) { + addBackgroundArea(backgroundArea); + if (columnBackgroundAreas == null) { + columnBackgroundAreas = new ArrayList(); + } + columnBackgroundAreas.add(new ColumnBackgroundInfo(column, backgroundArea, xShift)); + } + /** * The table area is a reference area that contains areas for * columns, bodies, rows and the contents are in cells. @@ -274,7 +319,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(getTable().getId()); + addId(); // add space before, in order to implement display-align = "center" or "after" if (layoutContext.getSpaceBefore() != 0) { @@ -298,6 +343,17 @@ public class TableLayoutManager extends BlockStackingLayoutManager curBlockArea.setBPD(tableHeight); + if (columnBackgroundAreas != null) { + for (Iterator iter = columnBackgroundAreas.iterator(); iter.hasNext();) { + ColumnBackgroundInfo b = (ColumnBackgroundInfo) iter.next(); + TraitSetter.addBackground(b.backgroundArea, + b.column.getCommonBorderPaddingBackground(), this, + b.xShift, -b.backgroundArea.getYOffset(), + b.column.getColumnWidth().getValue(this), tableHeight); + } + columnBackgroundAreas.clear(); + } + if (getTable().isSeparateBorderModel()) { TraitSetter.addBorders(curBlockArea, getTable().getCommonBorderPaddingBackground(), @@ -323,7 +379,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager resetSpaces(); curBlockArea = null; - getPSLM().notifyEndOfLayout(((Table)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** @@ -366,6 +422,15 @@ public class TableLayoutManager extends BlockStackingLayoutManager } } + /** + * Adds the given area to this layout manager's area, without updating the used bpd. + * + * @param background an area + */ + void addBackgroundArea(Block background) { + curBlockArea.addChildArea(background); + } + /** {@inheritDoc} */ public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) { // TODO Auto-generated method stub diff --git a/src/java/org/apache/fop/pdf/PDFCMap.java b/src/java/org/apache/fop/pdf/PDFCMap.java index bdf8108c2..1be5e9dc4 100644 --- a/src/java/org/apache/fop/pdf/PDFCMap.java +++ b/src/java/org/apache/fop/pdf/PDFCMap.java @@ -21,7 +21,6 @@ package org.apache.fop.pdf; import java.io.IOException; import java.io.OutputStream; -import java.io.StringWriter; import java.io.Writer; /** @@ -425,10 +424,8 @@ public class PDFCMap extends PDFStream { /** {@inheritDoc} */ protected int output(OutputStream stream) throws IOException { - StringWriter writer = new StringWriter(); - CMapBuilder builder = createCMapBuilder(writer); + CMapBuilder builder = createCMapBuilder(getBufferWriter()); builder.writeCMap(); - add(writer.getBuffer().toString()); //TODO Could be optimized by not buffering return super.output(stream); } } diff --git a/src/java/org/apache/fop/pdf/PDFEncoding.java b/src/java/org/apache/fop/pdf/PDFEncoding.java index b2fba6e53..6dc448b40 100644 --- a/src/java/org/apache/fop/pdf/PDFEncoding.java +++ b/src/java/org/apache/fop/pdf/PDFEncoding.java @@ -132,6 +132,14 @@ public class PDFEncoding extends PDFDictionary { } /** + * Indicates whether any differences have been recorded. + * @return true if there are differences. + */ + public boolean hasDifferences() { + return (this.differences.length() > 0); + } + + /** * Creates and returns the PDFArray representing the Differences entry. * @return the Differences entry */ diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index 687b32016..f4474331f 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -43,6 +43,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.xmlgraphics.xmp.Metadata; import org.apache.fop.fonts.CIDFont; +import org.apache.fop.fonts.CIDSubset; import org.apache.fop.fonts.CodePointMapping; import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.FontDescriptor; @@ -50,6 +51,8 @@ import org.apache.fop.fonts.FontMetrics; import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.MultiByteFont; +import org.apache.fop.fonts.SimpleSingleByteEncoding; +import org.apache.fop.fonts.SingleByteEncoding; import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; import org.apache.fop.fonts.truetype.FontFileReader; @@ -1166,7 +1169,7 @@ public class PDFFactory { } /** - * make a Type1 /Font object + * Make a Type1 /Font object. * * @param fontname internal name to use for this font (eg "F1") * @param basefont name of the base font (eg "Helvetica") @@ -1217,10 +1220,12 @@ public class PDFFactory { (PDFCIDFontDescriptor)pdfdesc); getDocument().registerObject(cidFont); - PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics.getCharsUsed(), "fop-ucs-H", - new PDFCIDSystemInfo("Adobe", - "Identity", - 0)); + PDFCMap cmap = new PDFToUnicodeCMap( + cidMetrics.getCIDSubset().getSubsetChars(), + "fop-ucs-H", + new PDFCIDSystemInfo("Adobe", + "Identity", + 0)); getDocument().registerObject(cmap); ((PDFFontType0)font).setCMAP(cmap); ((PDFFontType0)font).setDescendantFonts(cidFont); @@ -1238,35 +1243,20 @@ public class PDFFactory { int lastChar = singleByteFont.getLastChar(); nonBase14.setWidthMetrics(firstChar, lastChar, - makeArray(metrics.getWidths())); + new PDFArray(null, metrics.getWidths())); //Handle encoding - CodePointMapping mapping = singleByteFont.getCodePointMapping(); + SingleByteEncoding mapping = singleByteFont.getEncoding(); if (PDFEncoding.isPredefinedEncoding(mapping.getName())) { font.setEncoding(mapping.getName()); } else { - CodePointMapping winansi = CodePointMapping.getMapping( - CodePointMapping.WIN_ANSI_ENCODING); - PDFEncoding pdfEncoding = new PDFEncoding(winansi.getName()); - PDFEncoding.DifferencesBuilder builder - = pdfEncoding.createDifferencesBuilder(); - int start = -1; - String[] winansiNames = winansi.getCharNameMap(); - String[] charNameMap = mapping.getCharNameMap(); - for (int i = 0; i < 256; i++) { - String wac = winansiNames[i]; - String c = charNameMap[i]; - if (!wac.equals(c)) { - if (start != i) { - builder.addDifference(i); - start = i; - } - builder.addName(c); - start++; - } + Object pdfEncoding = createPDFEncoding(mapping, + singleByteFont.getFontName()); + if (pdfEncoding instanceof PDFEncoding) { + font.setEncoding((PDFEncoding)pdfEncoding); + } else { + font.setEncoding((String)pdfEncoding); } - pdfEncoding.setDifferences(builder.toPDFArray()); - font.setEncoding(pdfEncoding); /* JM: What I thought would be a necessity with custom encodings turned out to * be a bug in Adobe Acrobat 8. The following section just demonstrates how @@ -1278,21 +1268,88 @@ public class PDFFactory { nonBase14.setToUnicode(cmap); */ } + + //Handle additional encodings (characters outside the primary encoding) + if (singleByteFont.hasAdditionalEncodings()) { + for (int i = 0, c = singleByteFont.getAdditionalEncodingCount(); i < c; i++) { + SimpleSingleByteEncoding addEncoding + = singleByteFont.getAdditionalEncoding(i); + String name = fontname + "_" + (i + 1); + Object pdfenc = createPDFEncoding(addEncoding, + singleByteFont.getFontName()); + PDFFontNonBase14 addFont = (PDFFontNonBase14)PDFFont.createFont( + name, fonttype, + basefont, pdfenc); + addFont.setDescriptor(pdfdesc); + addFont.setWidthMetrics( + addEncoding.getFirstChar(), + addEncoding.getLastChar(), + new PDFArray(null, singleByteFont.getAdditionalWidths(i))); + getDocument().registerObject(addFont); + getDocument().getResources().addFont(addFont); + } + } } return font; } } + /** + * Creates a PDFEncoding instance from a CodePointMapping instance. + * @param encoding the code point mapping (encoding) + * @return the PDF Encoding dictionary (or a String with the predefined encoding) + */ + public Object createPDFEncoding(SingleByteEncoding encoding, String fontNameHint) { + SingleByteEncoding baseEncoding; + if (fontNameHint.indexOf("Symbol") >= 0) { + baseEncoding = CodePointMapping.getMapping( + CodePointMapping.SYMBOL_ENCODING); + } else { + baseEncoding = CodePointMapping.getMapping( + CodePointMapping.STANDARD_ENCODING); + } + PDFEncoding pdfEncoding = new PDFEncoding(baseEncoding.getName()); + PDFEncoding.DifferencesBuilder builder + = pdfEncoding.createDifferencesBuilder(); + int start = -1; + String[] baseNames = baseEncoding.getCharNameMap(); + String[] charNameMap = encoding.getCharNameMap(); + for (int i = 0, ci = charNameMap.length; i < ci; i++) { + String basec = baseNames[i]; + String c = charNameMap[i]; + if (!basec.equals(c)) { + if (start != i) { + builder.addDifference(i); + start = i; + } + builder.addName(c); + start++; + } + } + if (builder.hasDifferences()) { + pdfEncoding.setDifferences(builder.toPDFArray()); + return pdfEncoding; + } else { + return baseEncoding.getName(); + } + } + + /** + * Creates and returns a width array with the widths of all the characters in the subset. + * @param cidFont the font + * @return the width array + */ public PDFWArray getSubsetWidths(CIDFont cidFont) { // Create widths for reencoded chars PDFWArray warray = new PDFWArray(); - int[] tmpWidth = new int[cidFont.usedGlyphsCount]; + int[] widths = cidFont.getWidths(); + CIDSubset subset = cidFont.getCIDSubset(); + int[] tmpWidth = new int[subset.getSubsetSize()]; - for (int i = 0; i < cidFont.usedGlyphsCount; i++) { - Integer nw = (Integer)cidFont.usedGlyphsIndex.get(new Integer(i)); - int nwx = (nw == null) ? 0 : nw.intValue(); - tmpWidth[i] = cidFont.width[nwx]; + for (int i = 0, c = subset.getSubsetSize(); i < c; i++) { + int nwx = Math.max(0, subset.getGlyphIndexForSubsetIndex(i)); + tmpWidth[i] = widths[nwx]; } warray.addEntry(0, tmpWidth); return warray; @@ -1345,12 +1402,7 @@ public class PDFFactory { } private void buildCIDSet(PDFFontDescriptor descriptor, CIDFont cidFont) { - BitSet cidSubset = new BitSet(); - Iterator iter = cidFont.usedGlyphs.keySet().iterator(); - while (iter.hasNext()) { - Integer cid = (Integer)iter.next(); - cidSubset.set(cid.intValue()); - } + BitSet cidSubset = cidFont.getCIDSubset().getGlyphIndexBitSet(); PDFStream cidSet = makeStream(null, true); ByteArrayOutputStream baout = new ByteArrayOutputStream(cidSubset.length() / 8 + 1); int value = 0; @@ -1548,14 +1600,13 @@ public class PDFFactory { } /** - * make an Array object (ex. Widths array for a font) + * Make an Array object (ex. Widths array for a font). * * @param values the int array values * @return the PDF Array with the int values */ public PDFArray makeArray(int[] values) { PDFArray array = new PDFArray(null, values); - getDocument().registerObject(array); return array; } diff --git a/src/java/org/apache/fop/pdf/PDFResources.java b/src/java/org/apache/fop/pdf/PDFResources.java index 66ccdc78b..b0c0128e1 100644 --- a/src/java/org/apache/fop/pdf/PDFResources.java +++ b/src/java/org/apache/fop/pdf/PDFResources.java @@ -110,7 +110,7 @@ public class PDFResources extends PDFObject { desc = (FontDescriptor)font; } addFont(doc.getFactory().makeFont( - f, font.getEmbedFontName(), font.getEncoding(), font, desc)); + f, font.getEmbedFontName(), font.getEncodingName(), font, desc)); } } } diff --git a/src/java/org/apache/fop/pdf/PDFStream.java b/src/java/org/apache/fop/pdf/PDFStream.java index 59a8336c5..a213340e3 100644 --- a/src/java/org/apache/fop/pdf/PDFStream.java +++ b/src/java/org/apache/fop/pdf/PDFStream.java @@ -19,8 +19,9 @@ package org.apache.fop.pdf; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; /** * Class representing a PDF stream. @@ -37,6 +38,8 @@ public class PDFStream extends AbstractPDFStream { */ protected StreamCache data; + private transient Writer streamWriter; + /** * Create an empty stream object */ @@ -44,6 +47,10 @@ public class PDFStream extends AbstractPDFStream { super(); try { data = StreamCacheFactory.getInstance().createStreamCache(); + this.streamWriter = new java.io.OutputStreamWriter( + getBufferOutputStream(), PDFDocument.ENCODING); + //Buffer to minimize calls to the converter + this.streamWriter = new java.io.BufferedWriter(this.streamWriter); } catch (IOException ex) { //TODO throw the exception and catch it elsewhere ex.printStackTrace(); @@ -57,21 +64,35 @@ public class PDFStream extends AbstractPDFStream { */ public void add(String s) { try { - data.getOutputStream().write(PDFDocument.encode(s)); + this.streamWriter.write(s); } catch (IOException ex) { //TODO throw the exception and catch it elsewhere ex.printStackTrace(); } - + } + + private void flush() throws IOException { + this.streamWriter.flush(); } /** + * Returns a Writer that writes to the OutputStream of the buffer. + * @return the Writer + */ + public Writer getBufferWriter() { + return this.streamWriter; + } + + /** * Returns an OutputStream that can be used to write to the buffer which is used * to build up the PDF stream. * @return the OutputStream * @throws IOException In case of an I/O problem */ public OutputStream getBufferOutputStream() throws IOException { + if (this.streamWriter != null) { + flush(); //Just to be sure + } return this.data.getOutputStream(); } @@ -91,6 +112,7 @@ public class PDFStream extends AbstractPDFStream { */ public int getDataLength() { try { + flush(); return data.getSize(); } catch (Exception e) { //TODO throw the exception and catch it elsewhere @@ -99,17 +121,15 @@ public class PDFStream extends AbstractPDFStream { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected int getSizeHint() throws IOException { + flush(); return data.getSize(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void outputRawStreamData(OutputStream out) throws IOException { + flush(); data.outputContents(out); } diff --git a/src/java/org/apache/fop/pdf/PDFTTFStream.java b/src/java/org/apache/fop/pdf/PDFTTFStream.java index b3488f6a1..5570c62f3 100644 --- a/src/java/org/apache/fop/pdf/PDFTTFStream.java +++ b/src/java/org/apache/fop/pdf/PDFTTFStream.java @@ -67,7 +67,7 @@ public class PDFTTFStream extends PDFStream { */ public void setData(byte[] data, int size) throws IOException { this.data.clear(); - this.data.getOutputStream().write(data, 0, size); + getBufferOutputStream().write(data, 0, size); } } diff --git a/src/java/org/apache/fop/pdf/PDFTextUtil.java b/src/java/org/apache/fop/pdf/PDFTextUtil.java new file mode 100644 index 000000000..224bb6a1d --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFTextUtil.java @@ -0,0 +1,295 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.pdf; + +import java.awt.geom.AffineTransform; + +/** + * Utility class for generating PDF text objects. It needs to be subclassed to add writing + * functionality (see {@link #write(String)}). + */ +public abstract class PDFTextUtil { + + /** The number of decimal places. */ + private static final int DEC = 8; + + /** PDF text rendering mode: Fill text */ + public static final int TR_FILL = 0; + /** PDF text rendering mode: Stroke text */ + public static final int TR_STROKE = 1; + /** PDF text rendering mode: Fill, then stroke text */ + public static final int TR_FILL_STROKE = 2; + /** PDF text rendering mode: Neither fill nor stroke text (invisible) */ + public static final int TR_INVISIBLE = 3; + /** PDF text rendering mode: Fill text and add to path for clipping */ + public static final int TR_FILL_CLIP = 4; + /** PDF text rendering mode: Stroke text and add to path for clipping */ + public static final int TR_STROKE_CLIP = 5; + /** PDF text rendering mode: Fill, then stroke text and add to path for clipping */ + public static final int TR_FILL_STROKE_CLIP = 6; + /** PDF text rendering mode: Add text to path for clipping */ + public static final int TR_CLIP = 7; + + private boolean inTextObject = false; + private String startText; + private String endText; + private boolean useMultiByte; + private StringBuffer bufTJ; + private int textRenderingMode = TR_FILL; + + private String currentFontName; + private double currentFontSize; + + /** + * Main constructor. + */ + public PDFTextUtil() { + //nop + } + + /** + * Writes PDF code. + * @param code the PDF code to write + */ + protected abstract void write(String code); + + private void writeAffineTransform(AffineTransform at, StringBuffer sb) { + double[] lt = new double[6]; + at.getMatrix(lt); + sb.append(PDFNumber.doubleOut(lt[0], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[1], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[2], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[3], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[4], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[5], DEC)); + } + + private void writeChar(char ch, StringBuffer sb) { + if (!useMultiByte) { + if (ch < 32 || ch > 127) { + sb.append("\\").append(Integer.toOctalString((int)ch)); + } else { + switch (ch) { + case '(': + case ')': + case '\\': + sb.append("\\"); + break; + default: + } + sb.append(ch); + } + } else { + sb.append(PDFText.toUnicodeHex(ch)); + } + } + + private void checkInTextObject() { + if (!inTextObject) { + throw new IllegalStateException("Not in text object"); + } + } + + /** + * Indicates whether we are in a text object or not. + * @return true if we are in a text object + */ + public boolean isInTextObject() { + return inTextObject; + } + + /** + * Called when a new text object should be started. Be sure to call setFont() before + * issuing any text painting commands. + */ + public void beginTextObject() { + if (inTextObject) { + throw new IllegalStateException("Already in text object"); + } + write("BT\n"); + this.inTextObject = true; + } + + /** + * Called when a text object should be ended. + */ + public void endTextObject() { + checkInTextObject(); + write("ET\n"); + this.inTextObject = false; + initValues(); + } + + /** + * Resets the state fields. + */ + protected void initValues() { + this.currentFontName = null; + this.currentFontSize = 0.0; + this.textRenderingMode = TR_FILL; + } + + /** + * Creates a "q" command, pushing a copy of the entire graphics state onto the stack. + */ + public void saveGraphicsState() { + write("q\n"); + } + + /** + * Creates a "Q" command, restoring the entire graphics state to its former value by popping + * it from the stack. + */ + public void restoreGraphicsState() { + write("Q\n"); + } + + /** + * Creates a "cm" command. + * @param at the transformation matrix + */ + public void concatMatrix(AffineTransform at) { + if (!at.isIdentity()) { + writeTJ(); + StringBuffer sb = new StringBuffer(); + writeAffineTransform(at, sb); + sb.append(" cm\n"); + write(sb.toString()); + } + } + + /** + * Writes a "Tf" command, setting a new current font. + * @param fontName the name of the font to select + * @param fontSize the font size (in points) + */ + public void writeTf(String fontName, double fontSize) { + checkInTextObject(); + write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n"); + + this.startText = useMultiByte ? "<" : "("; + this.endText = useMultiByte ? ">" : ")"; + } + + /** + * Updates the current font. This method only writes a "Tf" if the current font changes. + * @param fontName the name of the font to select + * @param fontSize the font size (in points) + * @param multiByte true indicates the font is a multi-byte font, false means single-byte + */ + public void updateTf(String fontName, double fontSize, boolean multiByte) { + checkInTextObject(); + if (!fontName.equals(this.currentFontName) || (fontSize != this.currentFontSize)) { + writeTJ(); + this.currentFontName = fontName; + this.currentFontSize = fontSize; + this.useMultiByte = multiByte; + writeTf(fontName, fontSize); + } + } + + /** + * Sets the text rendering mode. + * @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*) + */ + public void setTextRenderingMode(int mode) { + if (mode < 0 || mode > 7) { + throw new IllegalArgumentException( + "Illegal value for text rendering mode. Expected: 0-7"); + } + if (mode != this.textRenderingMode) { + writeTJ(); + this.textRenderingMode = mode; + write(this.textRenderingMode + " Tr\n"); + } + } + + /** + * Sets the text rendering mode. + * @param fill true if the text should be filled + * @param stroke true if the text should be stroked + * @param addToClip true if the path should be added for clipping + */ + public void setTextRenderingMode(boolean fill, boolean stroke, boolean addToClip) { + int mode; + if (fill) { + mode = (stroke ? 2 : 0); + } else { + mode = (stroke ? 1 : 3); + } + if (addToClip) { + mode += 4; + } + setTextRenderingMode(mode); + } + + /** + * Writes a "Tm" command, setting a new text transformation matrix. + * @param localTransform the new text transformation matrix + */ + public void writeTextMatrix(AffineTransform localTransform) { + StringBuffer sb = new StringBuffer(); + writeAffineTransform(localTransform, sb); + sb.append(" Tm "); + write(sb.toString()); + } + + /** + * Writes a char to the "TJ-Buffer". + * @param codepoint the mapped character (code point/character code) + */ + public void writeTJMappedChar(char codepoint) { + if (bufTJ == null) { + bufTJ = new StringBuffer(); + } + if (bufTJ.length() == 0) { + bufTJ.append("[").append(startText); + } + writeChar(codepoint, bufTJ); + } + + /** + * Writes a glyph adjust value to the "TJ-Buffer". + * @param adjust the glyph adjust value in thousands of text unit space. + */ + public void adjustGlyphTJ(double adjust) { + bufTJ.append(endText).append(" "); + bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4)); + bufTJ.append(" "); + bufTJ.append(startText); + } + + /** + * Writes a "TJ" command, writing out the accumulated buffer with the characters and glyph + * positioning values. The buffer is reset afterwards. + */ + public void writeTJ() { + if (isInString()) { + bufTJ.append(endText).append("] TJ\n"); + write(bufTJ.toString()); + bufTJ.setLength(0); + } + } + + private boolean isInString() { + return bufTJ != null && bufTJ.length() > 0; + } + +} diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java index f74699fd5..c0c9ce88c 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -47,7 +47,7 @@ import org.apache.fop.svg.SVGUserAgent; public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererContextConstants { /** logging instance */ - private static Log log = LogFactory.getLog(AbstractGenericSVGHandler.class); + protected static Log log = LogFactory.getLog(AbstractGenericSVGHandler.class); /** {@inheritDoc} */ public void handleXML(RendererContext context, diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index b10f4b30f..cb3d3a433 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -940,10 +940,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { int x = origin.x + posInt.x; int y = origin.y + posInt.y; - String name = null; - if (pageSegmentsMap != null) { - name = (String) pageSegmentsMap.get(uri); - } + String name = (String)getPageSegments().get(uri); if (name != null) { afpDataStream.createIncludePageSegment(name, mpts2units(x), mpts2units(y)); } else { @@ -1543,6 +1540,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { return MimeConstants.MIME_AFP; } + private Map getPageSegments() { + if (pageSegmentsMap == null) { + pageSegmentsMap = new java.util.HashMap(); + } + return pageSegmentsMap; + } + /** * Method to render the page extension. * <p> @@ -1571,17 +1575,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { .equals(element)) { String name = aps.getName(); String source = aps.getValue(); - if (pageSegmentsMap == null) { - pageSegmentsMap = new java.util.HashMap(); - } - pageSegmentsMap.put(source, name); + getPageSegments().put(source, name); } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT .equals(element)) { String name = aps.getName(); String value = aps.getValue(); - if (pageSegmentsMap == null) { - pageSegmentsMap = new java.util.HashMap(); - } afpDataStream.createTagLogicalElement(name, value); } else if (AFPElementMapping.NO_OPERATION.equals(element)) { String content = aps.getContent(); @@ -1589,7 +1587,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { afpDataStream.createNoOperation(content); } } else if (AFPElementMapping.RESOURCE.equals(element)) { - System.out.println("resource: " + attachment); + log.info("resource: " + attachment); } } } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index 4c8a3dc9f..cde464ba5 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -234,8 +234,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false); if (rendererResolutionCfg != null) { - afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger( - AFPRenderer.DPI_240_RESOLUTION)); + afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(240)); } Configuration gocaSupportCfg = cfg.getChild("goca-enabled", false); diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 2641e6fbe..1d469ea94 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -49,9 +49,6 @@ import org.w3c.dom.Document; */ public class AFPSVGHandler extends AbstractGenericSVGHandler { - /** logging instance */ - private static Log log = LogFactory.getLog(AFPSVGHandler.class); - /** {@inheritDoc} */ public void handleXML(RendererContext context, Document doc, String ns) throws Exception { @@ -196,7 +193,10 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { } /** {@inheritDoc} */ - public String getNamespace() { - return SVGDOMImplementation.SVG_NAMESPACE_URI; + protected void updateRendererContext(RendererContext context) { + //Work around a problem in Batik: Gradients cannot be done in ColorSpace.CS_GRAY + context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, + Boolean.FALSE); } + } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java index 808cd88f1..659c79a8e 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java @@ -55,7 +55,8 @@ public class AFPElement extends AbstractAFPExtensionObject { } } - protected ExtensionAttachment instantiateExtensionAttachment() { - return null; - } + protected ExtensionAttachment instantiateExtensionAttachment() { + return new AFPPageSetup(getName()); + } + } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java index 8d4b0ae5e..ad80399e3 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java @@ -19,8 +19,6 @@ package org.apache.fop.render.afp.extensions; -import java.util.HashMap; - import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.FONode; @@ -39,7 +37,7 @@ public class AFPElementMapping extends ElementMapping { public static final String PAGE = "page"; /** page group element */ - public static final String PAGE_GROUP = "page-group"; +// public static final String PAGE_GROUP = "page-group"; /** tag logical element */ public static final String TAG_LOGICAL_ELEMENT = "tag-logical-element"; @@ -78,9 +76,12 @@ public class AFPElementMapping extends ElementMapping { protected void initialize() { if (foObjs == null) { - foObjs = new HashMap(); + super.foObjs = new java.util.HashMap(); foObjs.put(PAGE, new AFPPageSetupMaker()); - // foObjs.put(PAGE_GROUP, new AFPMaker()); +// foObjs.put( +// PAGE_GROUP, +// new AFPPageGroupMaker() +// ); foObjs.put( TAG_LOGICAL_ELEMENT, new AFPTagLogicalElementMaker()); @@ -94,7 +95,6 @@ public class AFPElementMapping extends ElementMapping { NO_OPERATION, new AFPNoOperationMaker()); } - } static class AFPPageSetupMaker extends ElementMapping.Maker { @@ -126,4 +126,10 @@ public class AFPElementMapping extends ElementMapping { return new AFPElement(parent, NO_OPERATION); } } + +// static class AFPPageGroupMaker extends ElementMapping.Maker { +// public FONode make(FONode parent) { +// return new AFPElement(parent, PAGE_GROUP); +// } +// } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java index 7fdf7cd11..fca486279 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java @@ -54,7 +54,7 @@ public class AFPExtensionHandler extends DefaultHandler || localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY) || localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT) || localName.equals(AFPElementMapping.PAGE) - || localName.equals(AFPElementMapping.PAGE_GROUP)) { + /*|| localName.equals(AFPElementMapping.PAGE_GROUP)*/) { //handled in endElement } else { handled = false; diff --git a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java index 57886f89c..f8dd9a1ed 100644 --- a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java @@ -174,11 +174,8 @@ public class OutlineFont extends AFPFont { return charSet.mapChar(c); } - /** - * Get the encoding of the font. - * @return the encoding - */ - public String getEncoding() { + /** {@inheritDoc} */ + public String getEncodingName() { return charSet.getEncoding(); } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java index a61f97ab5..44dcd0e9f 100644 --- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java @@ -229,11 +229,8 @@ public class RasterFont extends AFPFont { return charSet.mapChar(c); } - /** - * Get the encoding of the font. - * @return the encoding - */ - public String getEncoding() { + /** {@inheritDoc} */ + public String getEncodingName() { return charSet.getEncoding(); } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java index 26d42b2d4..106454ad6 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java @@ -44,7 +44,7 @@ public abstract class AbstractAFPObject { * DataStream objects must implement the writeDataStream() * method to write its data to the given OutputStream * @param os The outputsteam stream - * @throws java.io.IOException in the event that an I/O exception occurred + * @throws java.io.IOException */ public abstract void writeDataStream(OutputStream os) throws IOException; @@ -52,10 +52,10 @@ public abstract class AbstractAFPObject { * Help method to write a set of AFPObjects to the AFP datastream. * @param objects a list of AFPObjects * @param os The stream to write to - * @throws java.io.IOException in the event that an I/O exception occurred + * @throws java.io.IOException */ protected void writeObjects(Collection/*<AbstractAFPObject>*/ objects, OutputStream os) - throws IOException { + throws IOException { if (objects != null) { for (Iterator it = objects.iterator(); it.hasNext();) { Object obj1 = it.next(); @@ -63,5 +63,7 @@ public abstract class AbstractAFPObject { obj.writeDataStream(os); } } + } -}
\ No newline at end of file +} + diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java b/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java index 29c619d32..6d827766e 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java @@ -28,22 +28,22 @@ public abstract class AbstractDescriptor extends AbstractAFPObject { /** height of this descriptor */ protected int height = 0; /** width resolution of this descriptor */ - protected int widthRes = 0; + protected int widthResolution = 0; /** height resolution of this descriptor */ - protected int heightRes = 0; + protected int heightResolution = 0; /** * Constructor a PresentationTextDescriptor for the specified * width and height. * @param width The width of the page. * @param height The height of the page. - * @param widthRes The width resolution of the page. - * @param heightRes The height resolution of the page. + * @param widthResolution The width resolution of the page. + * @param heightResolution The height resolution of the page. */ - public AbstractDescriptor(int width, int height, int widthRes, int heightRes) { + public AbstractDescriptor(int width, int height, int widthResolution, int heightResolution) { this.width = width; this.height = height; - this.widthRes = widthRes; - this.heightRes = heightRes; + this.widthResolution = widthResolution; + this.heightResolution = heightResolution; } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java index 393cff84b..09fa33f8f 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java @@ -38,7 +38,7 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject * The name of the object in EBCIDIC bytes */ protected byte[] nameBytes; - + /** * Default constructor */ @@ -51,19 +51,17 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject * @param name the object name */ protected AbstractNamedAFPObject(String name) { - int nameLen = getNameLength(); - if (name.length() < nameLen) { - this.name = (name + " ").substring(0, nameLen); - } else if (name.length() > nameLen) { - log.warn("Constructor:: name truncated to " + nameLen + " chars: " + name); - this.name = name.substring(0, nameLen); - } else { - this.name = name; + this.name = name; + if (name.length() < 8) { + name = (name + " ").substring(0, 8); + } else if (name.length() > 8) { + log.warn("Constructor:: name truncated to 8 chars" + name); + name = name.substring(0, 8); } try { - this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); + nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); } catch (UnsupportedEncodingException usee) { - this.nameBytes = name.getBytes(); + nameBytes = name.getBytes(); log.warn( "Constructor:: UnsupportedEncodingException translating the name " + name); @@ -82,5 +80,6 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject */ public String getName() { return name; - } + } + } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java index f373b5bf7..984aa44c9 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java @@ -310,7 +310,7 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer private PresentationTextObject getPresentationTextObject() { if (presentationTextObject == null) { this.presentationTextObject = new PresentationTextObject(); - addObject(this.presentationTextObject); + super.addObject(this.presentationTextObject); } return presentationTextObject; } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageContent.java b/src/java/org/apache/fop/render/afp/modca/ImageContent.java index 4aea02901..726c58762 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageContent.java @@ -18,13 +18,11 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; - import java.io.IOException; import java.io.OutputStream; import org.apache.fop.render.afp.tools.BinaryUtils; /** - * Image content IOCA object */ public class ImageContent extends AbstractStructuredAFPObject { @@ -55,27 +53,27 @@ public class ImageContent extends AbstractStructuredAFPObject { /** * The image size parameter */ - private ImageSizeParameter imageSizeParam = null; + private ImageSizeParameter _imageSizeParameter = null; /** * The image encoding */ - private byte encoding = 0x03; + private byte _encoding = 0x03; /** * The image ide size */ - private byte size = 1; + private byte _size = 1; /** * The image compression */ - private byte compression = (byte)0xC0; + private byte _compression = (byte)0xC0; /** * The image color model */ - private byte colorModel = 0x01; + private byte _colorModel = 0x01; /** * The image data @@ -97,39 +95,39 @@ public class ImageContent extends AbstractStructuredAFPObject { * @param vsize The vertival size of the image. */ public void setImageSize(int hresol, int vresol, int hsize, int vsize) { - this.imageSizeParam = new ImageSizeParameter(hresol, vresol, hsize, vsize); + _imageSizeParameter = new ImageSizeParameter(hresol, vresol, hsize, vsize); } /** * Sets the image encoding. - * @param enc The image encoding. + * @param encoding The image encoding. */ - public void setImageEncoding(byte enc) { - this.encoding = enc; + public void setImageEncoding(byte encoding) { + _encoding = encoding; } /** * Sets the image compression. - * @param comp The image compression. + * @param compression The image compression. */ - public void setImageCompression(byte comp) { - this.compression = comp; + public void setImageCompression(byte compression) { + _compression = compression; } /** * Sets the image IDE size. - * @param siz The IDE size. + * @param size The IDE size. */ - public void setImageIDESize(byte siz) { - this.size = siz; + public void setImageIDESize(byte size) { + _size = size; } /** * Sets the image IDE color model. - * @param model the IDE color model. + * @param colorModel the IDE color model. */ - public void setImageIDEColorModel(byte model) { - this.colorModel = model; + public void setImageIDEColorModel(byte colorModel) { + _colorModel = colorModel; } /** @@ -144,8 +142,8 @@ public class ImageContent extends AbstractStructuredAFPObject { * {@inheritDoc} */ protected void writeContent(OutputStream os) throws IOException { - if (imageSizeParam != null) { - imageSizeParam.writeDataStream(os); + if (_imageSizeParameter != null) { + _imageSizeParameter.writeDataStream(os); } os.write(getImageEncodingParameter()); os.write(getImageIDESizeParameter()); @@ -190,16 +188,21 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getImageDataStart(int len) { - byte[] imageDataStartData = new byte[] { + + byte[] data = new byte[] { (byte)0xFE, // ID (byte)0x92, // ID 0x00, // Length 0x00, // Length }; + byte[] l = BinaryUtils.convert(len, 2); - imageDataStartData[2] = l[0]; - imageDataStartData[3] = l[1]; - return imageDataStartData; + data[2] = l[0]; + data[3] = l[1]; + + + return data; + } /** @@ -207,13 +210,16 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getImageEncodingParameter() { - byte[] imageEncParamData = new byte[] { + + byte[] data = new byte[] { (byte)0x95, // ID 0x02, // Length - encoding, + _encoding, 0x01, // RECID }; - return imageEncParamData; + + return data; + } /** @@ -221,8 +227,9 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getExternalAlgorithmParameter() { - if (encoding == (byte)0x83 && compression != 0) { - byte[] extAlgParamData = new byte[] { + + if (_encoding == (byte)0x83 && _compression != 0) { + byte[] data = new byte[] { (byte)0x95, // ID 0x00, // Length 0x10, // ALGTYPE = Compression Algorithm @@ -231,13 +238,13 @@ public class ImageContent extends AbstractStructuredAFPObject { 0x00, // Reserved 0x00, // Reserved 0x00, // Reserved - compression, // MARKER + _compression, // MARKER 0x00, // Reserved 0x00, // Reserved 0x00, // Reserved }; - extAlgParamData[1] = (byte)(extAlgParamData.length - 2); - return extAlgParamData; + data[1] = (byte)(data.length - 2); + return data; } return new byte[0]; } @@ -247,12 +254,15 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getImageIDESizeParameter() { - byte[] imageIDESizeParamData = new byte[] { + + byte[] data = new byte[] { (byte)0x96, // ID 0x01, // Length - size, + _size, }; - return imageIDESizeParamData; + + return data; + } /** @@ -260,14 +270,15 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getIDEStructureParameter() { - if (colorModel != 0 && size == 24) { - byte bits = (byte)(size / 3); - byte[] ideStructParamData = new byte[] { + + if (_colorModel != 0 && _size == 24) { + byte bits = (byte)(_size / 3); + byte[] data = new byte[] { (byte)0x9B, // ID 0x00, // Length 0x00, // FLAGS 0x00, // Reserved - colorModel, // COLOR MODEL + _colorModel, // COLOR MODEL 0x00, // Reserved 0x00, // Reserved 0x00, // Reserved @@ -275,9 +286,10 @@ public class ImageContent extends AbstractStructuredAFPObject { bits, bits, }; - ideStructParamData[1] = (byte)(ideStructParamData.length - 2); - return ideStructParamData; + data[1] = (byte)(data.length - 2); + return data; } return new byte[0]; } + } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java index d1c2c11c7..9250f0c7f 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java @@ -27,17 +27,10 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class ImageDataDescriptor extends AbstractAFPObject { - /** x resolution */ - private int xresol = 0; - - /** y resolution */ - private int yresol = 0; - - /** width */ - private int width = 0; - - /** height */ - private int height = 0; + private int _xresol = 0; + private int _yresol = 0; + private int _width = 0; + private int _height = 0; /** * Constructor for a ImageDataDescriptor for the specified @@ -48,25 +41,26 @@ public class ImageDataDescriptor extends AbstractAFPObject { * @param height The height of the height. */ public ImageDataDescriptor(int xresol, int yresol, int width, int height) { - this.xresol = xresol; - this.yresol = yresol; - this.width = width; - this.height = height; + + _xresol = xresol; + _yresol = yresol; + _width = width; + _height = height; + } /** - * {@inheritDoc} + * Accessor method to write the AFP datastream for the Image Data Descriptor + * @param os The stream to write to + * @throws java.io.IOException */ - public void writeDataStream(OutputStream os) throws IOException { - byte[] len = BinaryUtils.convert(21, 2); - byte[] xres = BinaryUtils.convert(xresol, 2); - byte[] yres = BinaryUtils.convert(yresol, 2); - byte[] w = BinaryUtils.convert(width, 2); - byte[] h = BinaryUtils.convert(height, 2); + public void writeDataStream(OutputStream os) + throws IOException { + byte[] data = new byte[] { 0x5A, - len[0], - len[1], + 0x00, + 0x20, (byte) 0xD3, (byte) 0xA6, (byte) 0xFB, @@ -74,19 +68,42 @@ public class ImageDataDescriptor extends AbstractAFPObject { 0x00, // Reserved 0x00, // Reserved 0x00, // Unit base - 10 Inches - xres[0], // XRESOL - xres[1], // - yres[0], // YRESOL - yres[1], // - w[0], // XSIZE - w[1], // - h[0], // YSIZE - h[1], // + 0x00, // XRESOL + 0x00, // + 0x00, // YRESOL + 0x00, // + 0x00, // XSIZE + 0x00, // + 0x00, // YSIZE + 0x00, // (byte)0xF7, // ID = Set IOCA Function Set 0x02, // Length 0x01, // Category = Function set identifier 0x0B, // FCNSET = IOCA FS 11 }; + + byte[] l = BinaryUtils.convert(data.length - 1, 2); + data[1] = l[0]; + data[2] = l[1]; + + byte[] x = BinaryUtils.convert(_xresol, 2); + data[10] = x[0]; + data[11] = x[1]; + + byte[] y = BinaryUtils.convert(_yresol, 2); + data[12] = y[0]; + data[13] = y[1]; + + byte[] w = BinaryUtils.convert(_width, 2); + data[14] = w[0]; + data[15] = w[1]; + + byte[] h = BinaryUtils.convert(_height, 2); + data[16] = h[0]; + data[17] = h[1]; + os.write(data); + } + } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java index 2876e8348..ea8eb334b 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java @@ -18,7 +18,6 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; - import java.io.IOException; import java.io.OutputStream; @@ -165,6 +164,7 @@ public class ImageSegment extends AbstractNamedAFPObject { * {@inheritDoc} */ protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[] { 0x71, // ID 0x00, // Length diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java index aa35db10e..7c940148b 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java @@ -35,11 +35,11 @@ public class ObjectAreaDescriptor extends AbstractDescriptor { * and object height. * @param width The page width. * @param height The page height. - * @param widthRes The page width resolution. - * @param heightRes The page height resolution. + * @param widthResolution The page width resolution. + * @param heightResolution The page height resolution. */ - public ObjectAreaDescriptor(int width, int height, int widthRes, int heightRes) { - super(width, height, widthRes, heightRes); + public ObjectAreaDescriptor(int width, int height, int widthResolution, int heightResolution) { + super(width, height, widthResolution, heightResolution); } /** @@ -47,7 +47,8 @@ public class ObjectAreaDescriptor extends AbstractDescriptor { * @param os The stream to write to * @throws java.io.IOException thrown if an I/O exception of some sort has occurred */ - public void writeDataStream(OutputStream os) throws IOException { + public void writeDataStream(OutputStream os) + throws IOException { byte[] data = new byte[29]; data[0] = 0x5A; @@ -71,12 +72,12 @@ public class ObjectAreaDescriptor extends AbstractDescriptor { data[15] = 0x00; // YaoBase = 10 inches // XaoUnits - byte[] xdpi = BinaryUtils.convert(this.widthRes * 10, 2); + byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2); data[16] = xdpi[0]; data[17] = xdpi[1]; // YaoUnits - byte[] ydpi = BinaryUtils.convert(this.heightRes * 10, 2); + byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2); data[18] = ydpi[0]; data[19] = ydpi[1]; @@ -84,16 +85,18 @@ public class ObjectAreaDescriptor extends AbstractDescriptor { data[21] = 0x4C; // tid = Object Area Size data[22] = 0x02; // Size Type - byte[] x = BinaryUtils.convert(this.width, 3); + byte[] x = BinaryUtils.convert(width, 3); data[23] = x[0]; data[24] = x[1]; data[25] = x[2]; - byte[] y = BinaryUtils.convert(this.height, 3); + byte[] y = BinaryUtils.convert(height, 3); data[26] = y[0]; data[27] = y[1]; data[28] = y[2]; os.write(data); + } + }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java index ffa5f3c85..1cdec7616 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java @@ -35,11 +35,11 @@ public class PageDescriptor extends AbstractDescriptor { * and page height. * @param width The page width. * @param height The page height. - * @param widthRes The page width resolution - * @param heightRes The page height resolution + * @param widthResolution The page width resolution + * @param heightResolution The page height resolution */ - public PageDescriptor(int width, int height, int widthRes, int heightRes) { - super(width, height, widthRes, heightRes); + public PageDescriptor(int width, int height, int widthResolution, int heightResolution) { + super(width, height, widthResolution, heightResolution); } /** @@ -68,12 +68,12 @@ public class PageDescriptor extends AbstractDescriptor { data[10] = 0x00; // YpgBase = 10 inches // XpgUnits - byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2); + byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2); data[11] = xdpi[0]; data[12] = xdpi[1]; // YpgUnits - byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2); + byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2); data[13] = ydpi[0]; data[14] = ydpi[1]; diff --git a/src/java/org/apache/fop/render/afp/modca/PageObject.java b/src/java/org/apache/fop/render/afp/modca/PageObject.java index bad80bcc1..9a8646ba0 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PageObject.java @@ -56,14 +56,14 @@ public class PageObject extends AbstractPageObject { * the height of the page. * @param rotation * the rotation of the page. - * @param widthRes + * @param widthResolution * the width resolution of the page. - * @param heightRes + * @param heightResolution * the height resolution of the page. */ public PageObject(String name, int width, int height, int rotation, - int widthRes, int heightRes) { - super(name, width, height, rotation, widthRes, heightRes); + int widthResolution, int heightResolution) { + super(name, width, height, rotation, widthResolution, heightResolution); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java index 30a78d6c9..98beb96f7 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java @@ -56,42 +56,42 @@ public class PresentationTextData extends AbstractAFPObject { /** * The afp data relating to this presentaion text data. */ - private ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + private ByteArrayOutputStream _baos = new ByteArrayOutputStream(1024); /** * The current x coordinate. */ - private int currentXCoordinate = -1; + private int _currentXCoordinate = -1; /** * The current y cooridnate */ - private int currentYCoordinate = -1; + private int _currentYCoordinate = -1; /** * The current font */ - private String currentFont = ""; + private String _currentFont = ""; /** * The current orientation */ - private int currentOrientation = 0; + private int _currentOrientation = 0; /** * The current color */ - private Color currentColor = new Color(0, 0, 0); + private Color _currentColor = new Color(0, 0, 0); /** * The current variable space increment */ - private int currentVariableSpaceCharacterIncrement = 0; + private int _currentVariableSpaceCharacterIncrement = 0; /** * The current inter character adjustment */ - private int currentInterCharacterAdjustment = 0; + private int _currentInterCharacterAdjustment = 0; /** * Default constructor for the PresentationTextData. @@ -112,7 +112,7 @@ public class PresentationTextData extends AbstractAFPObject { */ public PresentationTextData(boolean controlInd) { - baos.write(new byte[] {0x5A, // Structured field identifier + _baos.write(new byte[] { 0x5A, // Structured field identifier 0x00, // Record length byte 1 0x00, // Record length byte 2 (byte) 0xD3, // PresentationTextData identifier byte 1 @@ -124,7 +124,7 @@ public class PresentationTextData extends AbstractAFPObject { }, 0, 9); if (controlInd) { - baos.write(new byte[] {0x2B, (byte) 0xD3}, 0, 2); + _baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2); } } @@ -142,13 +142,13 @@ public class PresentationTextData extends AbstractAFPObject { private void setCodedFont(byte font, ByteArrayOutputStream afpdata) { // Avoid unnecessary specification of the font - if (String.valueOf(font).equals(currentFont)) { + if (String.valueOf(font).equals(_currentFont)) { return; } else { - currentFont = String.valueOf(font); + _currentFont = String.valueOf(font); } - afpdata.write(new byte[] {0x03, (byte) 0xF1, font}, 0, 3); + afpdata.write(new byte[] { 0x03, (byte) 0xF1, font, }, 0, 3); } @@ -167,9 +167,9 @@ public class PresentationTextData extends AbstractAFPObject { byte[] b = BinaryUtils.convert(coordinate, 2); - afpdata.write(new byte[] {0x04, (byte) 0xC7, b[0], b[1]}, 0, 4); + afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4); - currentXCoordinate = coordinate; + _currentXCoordinate = coordinate; } @@ -188,9 +188,9 @@ public class PresentationTextData extends AbstractAFPObject { byte[] b = BinaryUtils.convert(coordinate, 2); - afpdata.write(new byte[] {0x04, (byte) 0xD3, b[0], b[1]}, 0, 4); + afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4); - currentYCoordinate = coordinate; + _currentYCoordinate = coordinate; } @@ -214,7 +214,7 @@ public class PresentationTextData extends AbstractAFPObject { "Transparent data is longer than 253 bytes: " + data); } - afpdata.write(new byte[] {BinaryUtils.convert(l)[0], (byte) 0xDB}, + afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, }, 0, 2); afpdata.write(data, 0, data.length); @@ -236,7 +236,7 @@ public class PresentationTextData extends AbstractAFPObject { private void drawBaxisRule(int length, int width, ByteArrayOutputStream afpdata) { - afpdata.write(new byte[] {0x07, // Length + afpdata.write(new byte[] { 0x07, // Length (byte) 0xE7, // Type }, 0, 2); @@ -266,7 +266,7 @@ public class PresentationTextData extends AbstractAFPObject { private void drawIaxisRule(int length, int width, ByteArrayOutputStream afpdata) { - afpdata.write(new byte[] {0x07, // Length + afpdata.write(new byte[] { 0x07, // Length (byte) 0xE5, // Type }, 0, 2); @@ -284,7 +284,7 @@ public class PresentationTextData extends AbstractAFPObject { /** * Create the presentation text data for the byte array of data. * - * @param fontReference + * @param fontNumber * The font resource identifier. * @param x * The x coordinate for the text data. @@ -300,64 +300,64 @@ public class PresentationTextData extends AbstractAFPObject { * The inter character adjustment. * @param data * The text data to be created. - * @throws MaximumSizeExceededException if the maximum size is exceeded + * @throws MaximumSizeExceededException */ - public void createTextData(int fontReference, int x, int y, int orientation, + public void createTextData(int fontNumber, int x, int y, int orientation, Color col, int vsci, int ica, byte[] data) throws MaximumSizeExceededException { ByteArrayOutputStream afpdata = new ByteArrayOutputStream(); - if (currentOrientation != orientation) { + if (_currentOrientation != orientation) { setTextOrientation(orientation, afpdata); - currentOrientation = orientation; - currentXCoordinate = -1; - currentYCoordinate = -1; + _currentOrientation = orientation; + _currentXCoordinate = -1; + _currentYCoordinate = -1; } // Avoid unnecessary specification of the Y co-ordinate - if (y != currentYCoordinate) { + if (y != _currentYCoordinate) { absoluteMoveBaseline(y, afpdata); - currentXCoordinate = -1; + _currentXCoordinate = -1; } // Avoid unnecessary specification of the X co-ordinate - if (x != currentXCoordinate) { + if (x != _currentXCoordinate) { absoluteMoveInline(x, afpdata); } // Avoid unnecessary specification of the variable space increment - if (vsci != currentVariableSpaceCharacterIncrement) { + if (vsci != _currentVariableSpaceCharacterIncrement) { setVariableSpaceCharacterIncrement(vsci, afpdata); - currentVariableSpaceCharacterIncrement = vsci; + _currentVariableSpaceCharacterIncrement = vsci; } // Avoid unnecessary specification of the inter character adjustment - if (ica != currentInterCharacterAdjustment) { + if (ica != _currentInterCharacterAdjustment) { setInterCharacterAdjustment(ica, afpdata); - currentInterCharacterAdjustment = ica; + _currentInterCharacterAdjustment = ica; } // Avoid unnecessary specification of the text color - if (!col.equals(currentColor)) { + if (!col.equals(_currentColor)) { setExtendedTextColor(col, afpdata); - currentColor = col; + _currentColor = col; } - setCodedFont(BinaryUtils.convert(fontReference)[0], afpdata); + setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata); addTransparentData(data, afpdata); - currentXCoordinate = -1; + _currentXCoordinate = -1; int s = afpdata.size(); - if (baos.size() + s > MAX_SIZE) { - currentXCoordinate = -1; - currentYCoordinate = -1; + if (_baos.size() + s > MAX_SIZE) { + _currentXCoordinate = -1; + _currentYCoordinate = -1; throw new MaximumSizeExceededException(); } byte[] outputdata = afpdata.toByteArray(); - baos.write(outputdata, 0, outputdata.length); + _baos.write(outputdata, 0, outputdata.length); } @@ -379,31 +379,30 @@ public class PresentationTextData extends AbstractAFPObject { * The orientation of the text data. * @param col * The text color. - * @throws MaximumSizeExceededException if the maximum size is exceeded */ public void createLineData(int x1, int y1, int x2, int y2, int thickness, int orientation, Color col) throws MaximumSizeExceededException { ByteArrayOutputStream afpdata = new ByteArrayOutputStream(); - if (currentOrientation != orientation) { + if (_currentOrientation != orientation) { setTextOrientation(orientation, afpdata); - currentOrientation = orientation; + _currentOrientation = orientation; } // Avoid unnecessary specification of the Y coordinate - if (y1 != currentYCoordinate) { + if (y1 != _currentYCoordinate) { absoluteMoveBaseline(y1, afpdata); } // Avoid unnecessary specification of the X coordinate - if (x1 != currentXCoordinate) { + if (x1 != _currentXCoordinate) { absoluteMoveInline(x1, afpdata); } - if (!col.equals(currentColor)) { + if (!col.equals(_currentColor)) { setExtendedTextColor(col, afpdata); - currentColor = col; + _currentColor = col; } if (y1 == y2) { @@ -416,14 +415,14 @@ public class PresentationTextData extends AbstractAFPObject { int s = afpdata.size(); - if (baos.size() + s > MAX_SIZE) { - currentXCoordinate = -1; - currentYCoordinate = -1; + if (_baos.size() + s > MAX_SIZE) { + _currentXCoordinate = -1; + _currentYCoordinate = -1; throw new MaximumSizeExceededException(); } byte[] outputdata = afpdata.toByteArray(); - baos.write(outputdata, 0, outputdata.length); + _baos.write(outputdata, 0, outputdata.length); } @@ -444,7 +443,7 @@ public class PresentationTextData extends AbstractAFPObject { private void setTextOrientation(int orientation, ByteArrayOutputStream afpdata) { - afpdata.write(new byte[] {0x06, (byte) 0xF7}, 0, 2); + afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2); switch (orientation) { case 90: @@ -560,11 +559,12 @@ public class PresentationTextData extends AbstractAFPObject { * Accessor method to write the AFP datastream for * the text data. * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurred + * @throws java.io.IOException */ - public void writeDataStream(OutputStream os) throws IOException { + public void writeDataStream(OutputStream os) + throws IOException { - byte[] data = baos.toByteArray(); + byte[] data = _baos.toByteArray(); byte[] size = BinaryUtils.convert(data.length - 1, 2); data[1] = size[0]; data[2] = size[1]; @@ -580,7 +580,7 @@ public class PresentationTextData extends AbstractAFPObject { * presentation text data objects, but must eventually be terminated. This * method terminates the control sequence. * - * @throws MaximumSizeExceededException if the maximum size is exceeded + * @throws MaximumSizeExceededException */ public void endControlSequence() throws MaximumSizeExceededException { @@ -588,10 +588,12 @@ public class PresentationTextData extends AbstractAFPObject { data[0] = 0x02; data[1] = (byte) 0xF8; - if (data.length + baos.size() > MAX_SIZE) { + if (data.length + _baos.size() > MAX_SIZE) { throw new MaximumSizeExceededException(); } - baos.write(data, 0, data.length); + + _baos.write(data, 0, data.length); + } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java index 27b3de5ca..3858f4169 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java @@ -52,11 +52,12 @@ public class PresentationTextDescriptor extends AbstractDescriptor { * width and height. * @param width The width of the page. * @param height The height of the page. - * @param widthRes The width resolution of the page. - * @param heightRes The height resolution of the page. + * @param widthResolution The width resolution of the page. + * @param heightResolution The height resolution of the page. */ - public PresentationTextDescriptor(int width, int height, int widthRes, int heightRes) { - super(width, height, widthRes, heightRes); + public PresentationTextDescriptor(int width, int height, + int widthResolution, int heightResolution) { + super(width, height, widthResolution, heightResolution); } /** @@ -80,11 +81,11 @@ public class PresentationTextDescriptor extends AbstractDescriptor { data[9] = 0x00; data[10] = 0x00; - byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2); + byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2); data[11] = xdpi[0]; // xdpi data[12] = xdpi[1]; - byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2); + byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2); data[13] = ydpi[0]; // ydpi data[14] = ydpi[1]; diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java index 49f7c81a8..5df9fdb4c 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java @@ -117,7 +117,6 @@ public class PresentationTextObject extends AbstractNamedAFPObject { startPresentationTextData(); } try { - currentPresentationTextData.createTextData(fontRef, x, y, orientation, col, vsci, ica, data); } catch (MaximumSizeExceededException msee) { @@ -279,4 +278,4 @@ public class PresentationTextObject extends AbstractNamedAFPObject { endControlSequence(); } } -}
\ No newline at end of file +} diff --git a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java b/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java index 99f31ba14..29ac9eb5d 100644 --- a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java +++ b/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java @@ -47,7 +47,7 @@ public class TagLogicalElementBean { * @return the key */ public String getKey() { - return this.key; + return key; } /** @@ -55,7 +55,7 @@ public class TagLogicalElementBean { * @return the value */ public String getValue() { - return this.value; + return value; } } diff --git a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java index 208bc303a..3a773a2db 100644 --- a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java @@ -112,7 +112,7 @@ public class CustomFontMetricsMapper extends Typeface implements FontMetricsMapp } /** {@inheritDoc} */ - public final String getEncoding() { + public final String getEncodingName() { return null; //Not applicable to Java2D rendering } diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 8442af229..583d2ad2f 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -312,6 +312,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); } + graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, + RenderingHints.VALUE_STROKE_PURE); // transform page based on scale factor supplied AffineTransform at = graphics.getTransform(); diff --git a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java index ed7391383..19e9a4d1d 100644 --- a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java @@ -172,7 +172,7 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp } /** {@inheritDoc} */ - public String getEncoding() { + public String getEncodingName() { return null; //Not applicable to Java2D rendering } diff --git a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java index b676ad6d5..caf8928ac 100644 --- a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java +++ b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java @@ -81,7 +81,7 @@ public abstract class AbstractImageAdapter implements PDFImage { /** {@inheritDoc} */ public void setup(PDFDocument doc) { - ICC_Profile prof = image.getICCProfile(); + ICC_Profile prof = getEffectiveICCProfile(); PDFDeviceColorSpace pdfCS = toPDFColorSpace(getImageColorSpace()); if (prof != null) { pdfICCStream = setupColorProfile(doc, prof, pdfCS); @@ -100,6 +100,14 @@ public abstract class AbstractImageAdapter implements PDFImage { } } + /** + * Returns the effective ICC profile for the image. + * @return an ICC profile or null + */ + protected ICC_Profile getEffectiveICCProfile() { + return image.getICCProfile(); + } + private static PDFICCStream setupColorProfile(PDFDocument doc, ICC_Profile prof, PDFDeviceColorSpace pdfCS) { boolean defaultsRGB = ColorProfileUtil.isDefaultsRGB(prof); diff --git a/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java index 4b0ce4a85..1c8fceb50 100644 --- a/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java +++ b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java @@ -18,19 +18,33 @@ /* $Id$ */ package org.apache.fop.render.pdf; +import java.awt.color.ICC_Profile; +import java.io.DataInput; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +import org.apache.commons.io.IOUtils; + import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.image.loader.impl.JPEGConstants; +import org.apache.xmlgraphics.image.loader.impl.JPEGFile; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.fop.pdf.DCTFilter; import org.apache.fop.pdf.PDFDeviceColorSpace; import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFFilter; import org.apache.fop.pdf.PDFFilterList; +import org.apache.fop.util.ColorProfileUtil; /** * PDFImage implementation for the PDF renderer which handles raw JPEG images. + * <p> + * The JPEG is copied to the XObject's stream as-is but some elements (marker segments) are + * filtered. For example, an embedded color profile is filtered since it is already added as + * a PDF object and associated with the XObject. This way, the PDF file size is kept as small + * as possible. */ public class ImageRawJPEGAdapter extends AbstractImageAdapter { @@ -68,6 +82,21 @@ public class ImageRawJPEGAdapter extends AbstractImageAdapter { } /** {@inheritDoc} */ + protected ICC_Profile getEffectiveICCProfile() { + ICC_Profile profile = super.getEffectiveICCProfile(); + if (profile != null + && profile.getNumComponents() == 3 + && !ColorProfileUtil.isDefaultsRGB(profile)) { + //RGB profiles which are not sRGB don't seem to work. + //Without this override, the image drifts into yellow for an unknown reason. + //TODO Find out why this happens. + //Test using a JPEG images with, for example, "Adobe RGB 1998" color profile. + profile = null; + } + return profile; + } + + /** {@inheritDoc} */ public int getBitsPerComponent() { return 8; } @@ -84,7 +113,77 @@ public class ImageRawJPEGAdapter extends AbstractImageAdapter { /** {@inheritDoc} */ public void outputContents(OutputStream out) throws IOException { - getImage().writeTo(out); + InputStream in = getImage().createInputStream(); + in = ImageUtil.decorateMarkSupported(in); + try { + JPEGFile jpeg = new JPEGFile(in); + DataInput din = jpeg.getDataInput(); + + //Copy the whole JPEG file except: + // - the ICC profile + //TODO Thumbnails could safely be skipped, too. + //TODO Metadata (XMP, IPTC, EXIF) could safely be skipped, too. + while (true) { + int reclen; + int segID = jpeg.readMarkerSegment(); + switch (segID) { + case JPEGConstants.SOI: + out.write(0xFF); + out.write(segID); + break; + case JPEGConstants.EOI: + case JPEGConstants.SOS: + out.write(0xFF); + out.write(segID); + IOUtils.copy(in, out); //Just copy the rest! + return; + /* + case JPEGConstants.APP1: //Metadata + case JPEGConstants.APPD: + jpeg.skipCurrentMarkerSegment(); + break;*/ + case JPEGConstants.APP2: //ICC (see ICC1V42.pdf) + boolean skipICCProfile = false; + in.mark(16); + try { + reclen = jpeg.readSegmentLength(); + // Check for ICC profile + byte[] iccString = new byte[11]; + din.readFully(iccString); + din.skipBytes(1); //string terminator (null byte) + + if ("ICC_PROFILE".equals(new String(iccString, "US-ASCII"))) { + skipICCProfile = (this.image.getICCProfile() != null); + } + } finally { + in.reset(); + } + if (skipICCProfile) { + //ICC profile is skipped as it is already embedded as a PDF object + jpeg.skipCurrentMarkerSegment(); + break; + } + default: + out.write(0xFF); + out.write(segID); + + reclen = jpeg.readSegmentLength(); + //write short + out.write((reclen >>> 8) & 0xFF); + out.write((reclen >>> 0) & 0xFF); + int left = reclen - 2; + byte[] buf = new byte[2048]; + while (left > 0) { + int part = Math.min(buf.length, left); + din.readFully(buf, 0, part); + out.write(buf, 0, part); + left -= part; + } + } + } + } finally { + IOUtils.closeQuietly(in); + } } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java index 1a121e294..c47b944d0 100644 --- a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java @@ -89,8 +89,8 @@ public class PDFGraphics2DAdapter extends AbstractGraphics2DAdapter { PDFGraphics2D graphics = new PDFGraphics2D(textAsShapes, pdfInfo.fi, pdfInfo.pdfDoc, pdfInfo.pdfContext, pdfInfo.pdfPage.referencePDF(), - renderer.currentFontName, - renderer.currentFontSize); + pdfInfo.currentFontName, + pdfInfo.currentFontSize); graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); AffineTransform transform = new AffineTransform(); diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 19f274902..55524534e 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -63,7 +63,6 @@ import org.apache.fop.area.OffDocumentExtensionAttachment; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageSequence; import org.apache.fop.area.PageViewport; -import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.AbstractTextArea; import org.apache.fop.area.inline.Image; @@ -78,6 +77,8 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.extensions.xmp.XMPMetadata; import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.LazyFont; +import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; import org.apache.fop.pdf.PDFAMode; import org.apache.fop.pdf.PDFAction; @@ -106,7 +107,7 @@ import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFResources; import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFStream; -import org.apache.fop.pdf.PDFText; +import org.apache.fop.pdf.PDFTextUtil; import org.apache.fop.pdf.PDFXMode; import org.apache.fop.pdf.PDFXObject; import org.apache.fop.render.AbstractPathOrientedRenderer; @@ -250,21 +251,14 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** drawing state */ protected PDFState currentState = null; - /** Name of currently selected font */ - protected String currentFontName = ""; - /** Size of currently selected font */ - protected int currentFontSize = 0; + /** Text generation utility holding the current font status */ + protected PDFTextUtil textutil; /** page height */ protected int pageHeight; /** Registry of PDF filters */ protected Map filterMap; - /** - * true if a BT command has been written. - */ - protected boolean inTextMode = false; - /** Image handler registry */ private PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry(); @@ -527,7 +521,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { currentContext = null; currentPage = null; currentState = null; - currentFontName = ""; + this.textutil = null; idPositions.clear(); idGoTos.clear(); @@ -665,19 +659,15 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** Indicates the beginning of a text object. */ protected void beginTextObject() { - if (!inTextMode) { - currentStream.add("BT\n"); - currentFontName = ""; - inTextMode = true; + if (!textutil.isInTextObject()) { + textutil.beginTextObject(); } } /** Indicates the end of a text object. */ protected void endTextObject() { - closeText(); - if (inTextMode) { - currentStream.add("ET\n"); - inTextMode = false; + if (textutil.isInTextObject()) { + textutil.endTextObject(); } } @@ -787,6 +777,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { currentStream = this.pdfDoc.getFactory() .makeStream(PDFFilterList.CONTENT_FILTER, false); + this.textutil = new PDFTextUtil() { + protected void write(String code) { + currentStream.add(code); + } + }; currentState = new PDFState(); // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFRenderer's @@ -795,9 +790,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { currentState.concatenate(basicPageTransform); currentStream.add(CTMHelper.toPDFString(basicPageTransform, false) + " cm\n"); - - currentFontName = ""; - super.renderPage(page); this.pdfDoc.registerObject(currentStream); @@ -808,6 +800,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } this.pdfDoc.addObject(currentPage); this.pdfDoc.output(ostream); + this.textutil = null; } /** {@inheritDoc} */ @@ -841,17 +834,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } /** - * Handle the traits for a region - * This is used to draw the traits for the given page region. - * (See Sect. 6.4.1.2 of XSL-FO spec.) - * @param region the RegionViewport whose region is to be drawn - */ - protected void handleRegionTraits(RegionViewport region) { - currentFontName = ""; - super.handleRegionTraits(region); - } - - /** * Formats a float value (normally coordinates) as Strings. * @param value the value * @return the formatted value @@ -866,7 +848,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { float w = x2 - x1; float h = y2 - y1; if ((w < 0) || (h < 0)) { - log.error("Negative extent received (w=" + w + ", h=" + h + "). Border won't be painted."); + log.error("Negative extent received (w=" + w + ", h=" + h + + "). Border won't be painted."); return; } switch (style) { @@ -1329,12 +1312,9 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { super.renderBlock(block); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void renderLineArea(LineArea line) { super.renderLineArea(line); - closeText(); } /** @@ -1423,11 +1403,20 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } } - /** - * {@inheritDoc} - */ + private Typeface getTypeface(String fontName) { + Typeface tf = (Typeface) fontInfo.getFonts().get(fontName); + if (tf instanceof LazyFont) { + tf = ((LazyFont)tf).getRealFont(); + } + return tf; + } + + /** {@inheritDoc} */ public void renderText(TextArea text) { renderInlineAreaBackAndBorders(text); + Color ct = (Color) text.getTrait(Trait.COLOR); + updateColor(ct, true); + beginTextObject(); StringBuffer pdf = new StringBuffer(); @@ -1435,12 +1424,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); // This assumes that *all* CIDFonts use a /ToUnicode mapping - Typeface tf = (Typeface) fontInfo.getFonts().get(fontName); - boolean useMultiByte = tf.isMultiByte(); + Typeface tf = getTypeface(fontName); + + textutil.updateTf(fontName, size / 1000f, tf.isMultiByte()); - updateFont(fontName, size, pdf); - Color ct = (Color) text.getTrait(Trait.COLOR); - updateColor(ct, true, pdf); // word.getOffset() = only height of text itself // currentBlockIPPosition: 0 for beginning of line; nonzero @@ -1448,66 +1435,46 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { int rx = currentIPPosition + text.getBorderAndPaddingWidthStart(); int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset(); - pdf.append("1 0 0 -1 " + format(rx / 1000f) + " " + format(bl / 1000f) + " Tm " - /*+ format(text.getTextLetterSpaceAdjust() / 1000f) + " Tc\n"*/ - /*+ format(text.getTextWordSpaceAdjust() / 1000f) + " Tw ["*/); + textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, rx / 1000f, bl / 1000f)); - pdf.append("["); currentStream.add(pdf.toString()); super.renderText(text); - currentStream.add("] TJ\n"); + textutil.writeTJ(); renderTextDecoration(tf, size, text, bl, rx); } - - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ public void renderWord(WordArea word) { Font font = getFontFromArea(word.getParentArea()); - Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName()); - boolean useMultiByte = tf.isMultiByte(); - - StringBuffer pdf = new StringBuffer(); - String s = word.getWord(); - escapeText(s, word.getLetterAdjustArray(), - font, (AbstractTextArea)word.getParentArea(), useMultiByte, pdf); - currentStream.add(pdf.toString()); + escapeText(s, word.getLetterAdjustArray(), + font, (AbstractTextArea)word.getParentArea()); super.renderWord(word); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderSpace(SpaceArea space) { Font font = getFontFromArea(space.getParentArea()); - Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName()); - boolean useMultiByte = tf.isMultiByte(); - String s = space.getSpace(); - StringBuffer pdf = new StringBuffer(); - AbstractTextArea textArea = (AbstractTextArea)space.getParentArea(); - escapeText(s, null, font, textArea, useMultiByte, pdf); + escapeText(s, null, font, textArea); if (space.isAdjustable()) { int tws = -((TextArea) space.getParentArea()).getTextWordSpaceAdjust() - 2 * textArea.getTextLetterSpaceAdjust(); if (tws != 0) { - pdf.append(format(tws / (font.getFontSize() / 1000f))); - pdf.append(" "); + float adjust = tws / (font.getFontSize() / 1000f); + textutil.adjustGlyphTJ(adjust); } } - currentStream.add(pdf.toString()); - super.renderSpace(space); } @@ -1515,101 +1482,77 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { * Escapes text according to PDF rules. * @param s Text to escape * @param letterAdjust an array of widths for letter adjustment (may be null) - * @param fs Font state + * @param font to font in use + * @param parentArea the parent text area to retrieve certain traits from + */ + protected void escapeText(String s, + int[] letterAdjust, + Font font, AbstractTextArea parentArea) { + escapeText(s, 0, s.length(), letterAdjust, font, parentArea); + } + + /** + * Escapes text according to PDF rules. + * @param s Text to escape + * @param start the start position in the text + * @param end the end position in the text + * @param letterAdjust an array of widths for letter adjustment (may be null) + * @param font to font in use * @param parentArea the parent text area to retrieve certain traits from - * @param useMultiByte Indicates the use of multi byte convention - * @param pdf target buffer for the escaped text */ - public void escapeText(String s, int[] letterAdjust, - Font fs, AbstractTextArea parentArea, - boolean useMultiByte, StringBuffer pdf) { - String startText = useMultiByte ? "<" : "("; - String endText = useMultiByte ? "> " : ") "; - - /* - boolean kerningAvailable = false; - Map kerning = fs.getKerning(); - if (kerning != null && !kerning.isEmpty()) { - //kerningAvailable = true; - //TODO Reenable me when the layout engine supports kerning, too - log.warn("Kerning support is disabled until it is supported by the layout engine!"); - } - */ + protected void escapeText(String s, int start, int end, + int[] letterAdjust, + Font font, AbstractTextArea parentArea) { + String fontName = font.getFontName(); + float fontSize = font.getFontSize() / 1000f; + Typeface tf = getTypeface(fontName); + SingleByteFont singleByteFont = null; + if (tf instanceof SingleByteFont) { + singleByteFont = (SingleByteFont)tf; + } int l = s.length(); - - float fontSize = fs.getFontSize() / 1000f; - boolean startPending = true; - for (int i = 0; i < l; i++) { + + for (int i = start; i < end; i++) { char orgChar = s.charAt(i); char ch; float glyphAdjust = 0; - if (fs.hasChar(orgChar)) { - ch = fs.mapChar(orgChar); + if (font.hasChar(orgChar)) { + ch = font.mapChar(orgChar); + if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) { + int encoding = ch / 256; + if (encoding == 0) { + textutil.updateTf(fontName, fontSize, tf.isMultiByte()); + } else { + textutil.updateTf(fontName + "_" + Integer.toString(encoding), + fontSize, tf.isMultiByte()); + ch = (char)(ch % 256); + } + } int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0); glyphAdjust -= tls; } else { if (CharUtilities.isFixedWidthSpace(orgChar)) { //Fixed width space are rendered as spaces so copy/paste works in a reader - ch = fs.mapChar(CharUtilities.SPACE); - glyphAdjust = fs.getCharWidth(ch) - fs.getCharWidth(orgChar); + ch = font.mapChar(CharUtilities.SPACE); + glyphAdjust = font.getCharWidth(ch) - font.getCharWidth(orgChar); } else { - ch = fs.mapChar(orgChar); + ch = font.mapChar(orgChar); } } if (letterAdjust != null && i < l - 1) { glyphAdjust -= letterAdjust[i + 1]; } - if (startPending) { - pdf.append(startText); - startPending = false; - } - if (!useMultiByte) { - if (ch < 32 || ch > 127) { - pdf.append("\\"); - pdf.append(Integer.toOctalString((int) ch)); - } else { - switch (ch) { - case '(': - case ')': - case '\\': - pdf.append("\\"); - break; - default: - } - pdf.append(ch); - } - } else { - pdf.append(PDFText.toUnicodeHex(ch)); - } + textutil.writeTJMappedChar(ch); float adjust = glyphAdjust / fontSize; if (adjust != 0) { - pdf.append(endText).append(format(adjust)).append(' '); - startPending = true; + textutil.adjustGlyphTJ(adjust); } } - if (!startPending) { - pdf.append(endText); - } - } - - /** - * Checks to see if we have some text rendering commands open - * still and writes out the TJ command to the stream if we do - */ - protected void closeText() { - /* - if (textOpen) { - currentStream.add("] TJ\n"); - textOpen = false; - prevWordX = 0; - prevWordY = 0; - currentFontName = ""; - }*/ } /** @@ -1623,8 +1566,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { protected void setColor(Color col, boolean fill, StringBuffer pdf) { PDFColor color = new PDFColor(this.pdfDoc, col); - closeText(); - if (pdf != null) { pdf.append(color.getColorSpaceOut(fill)); } else { @@ -1656,22 +1597,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } /** {@inheritDoc} */ - protected void updateColor(Color col, boolean fill) { + protected void updateColor(Color col, boolean fill) { updateColor(col, fill, null); } - private void updateFont(String name, int size, StringBuffer pdf) { - if ((!name.equals(this.currentFontName)) - || (size != this.currentFontSize)) { - closeText(); - - this.currentFontName = name; - this.currentFontSize = size; - pdf = pdf.append("/" + name + " " + format((float) size / 1000f) - + " Tf\n"); - } - } - /** {@inheritDoc} */ public void renderImage(Image image, Rectangle2D pos) { endTextObject(); @@ -1727,8 +1656,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); info = manager.getImageInfo(uri, sessionContext); - - Map hints = ImageUtil.getDefaultHints(sessionContext); org.apache.xmlgraphics.image.loader.Image img = manager.getImage( info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext); @@ -1803,9 +1730,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { context.setProperty(PDFRendererContextConstants.PDF_CONTEXT, currentContext); context.setProperty(PDFRendererContextConstants.PDF_STREAM, currentStream); context.setProperty(PDFRendererContextConstants.PDF_FONT_INFO, fontInfo); - context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, currentFontName); - context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE, - new Integer(currentFontSize)); + context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, ""); + context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE, new Integer(0)); return context; } diff --git a/src/java/org/apache/fop/render/ps/PSFontUtils.java b/src/java/org/apache/fop/render/ps/PSFontUtils.java index bbc811b4e..1566ef799 100644 --- a/src/java/org/apache/fop/render/ps/PSFontUtils.java +++ b/src/java/org/apache/fop/render/ps/PSFontUtils.java @@ -32,16 +32,20 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.fonts.Glyphs; import org.apache.xmlgraphics.ps.DSCConstants; import org.apache.xmlgraphics.ps.PSGenerator; import org.apache.xmlgraphics.ps.PSResource; import org.apache.xmlgraphics.ps.dsc.ResourceTracker; +import org.apache.fop.fonts.Base14Font; import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.LazyFont; +import org.apache.fop.fonts.SingleByteEncoding; +import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; /** @@ -81,9 +85,21 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { while (iter.hasNext()) { String key = (String)iter.next(); Typeface tf = getTypeFace(fontInfo, fonts, key); - PSResource fontRes = new PSResource("font", tf.getFontName()); + PSResource fontRes = new PSResource(PSResource.TYPE_FONT, tf.getFontName()); fontResources.put(key, fontRes); embedFont(gen, tf, fontRes); + + if (tf instanceof SingleByteFont) { + SingleByteFont sbf = (SingleByteFont)tf; + for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) { + SingleByteEncoding encoding = sbf.getAdditionalEncoding(i); + defineEncoding(gen, encoding); + String postFix = "_" + (i + 1); + PSResource derivedFontRes = defineDerivedFont(gen, tf.getFontName(), + tf.getFontName() + postFix, encoding.getName()); + fontResources.put(key + postFix, derivedFontRes); + } + } } gen.commentln("%FOPEndFontDict"); reencodeFonts(gen, fonts); @@ -91,29 +107,35 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { } private static void reencodeFonts(PSGenerator gen, Map fonts) throws IOException { + ResourceTracker tracker = gen.getResourceTracker(); + + if (!tracker.isResourceSupplied(WINANSI_ENCODING_RESOURCE)) { + defineWinAnsiEncoding(gen); + } gen.commentln("%FOPBeginFontReencode"); - defineWinAnsiEncoding(gen); //Rewrite font encodings Iterator iter = fonts.keySet().iterator(); while (iter.hasNext()) { String key = (String)iter.next(); - Typeface fm = (Typeface)fonts.get(key); - if (fm instanceof LazyFont && ((LazyFont)fm).getRealFont() == null) { - continue; - } else if (null == fm.getEncoding()) { + Typeface tf = (Typeface)fonts.get(key); + if (tf instanceof LazyFont) { + tf = ((LazyFont)tf).getRealFont(); + if (tf == null) { + continue; + } + } + if (null == tf.getEncodingName()) { //ignore (ZapfDingbats and Symbol used to run through here, kept for safety reasons) - } else if ("SymbolEncoding".equals(fm.getEncoding())) { + } else if ("SymbolEncoding".equals(tf.getEncodingName())) { //ignore (no encoding redefinition) - } else if ("ZapfDingbatsEncoding".equals(fm.getEncoding())) { + } else if ("ZapfDingbatsEncoding".equals(tf.getEncodingName())) { //ignore (no encoding redefinition) - } else if ("WinAnsiEncoding".equals(fm.getEncoding())) { - redefineFontEncoding(gen, fm.getFontName(), fm.getEncoding()); } else { - /* Don't complain anymore, just use the font's default encoding. - gen.commentln("%WARNING: Only WinAnsiEncoding is supported. Font '" - + fm.getFontName() + "' asks for: " + fm.getEncoding()); - */ + if (tf instanceof Base14Font) { + //Our Base 14 fonts don't use the default encoding + redefineFontEncoding(gen, tf.getFontName(), tf.getEncodingName()); + } } } gen.commentln("%FOPEndFontReencode"); @@ -233,10 +255,88 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { if (isEmbeddable(cf)) { resTracker.registerSuppliedResource(fontRes); } + if (tf instanceof SingleByteFont) { + SingleByteFont sbf = (SingleByteFont)tf; + for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) { + SingleByteEncoding encoding = sbf.getAdditionalEncoding(i); + PSResource encodingRes = new PSResource( + PSResource.TYPE_ENCODING, encoding.getName()); + resTracker.registerSuppliedResource(encodingRes); + PSResource derivedFontRes = new PSResource( + PSResource.TYPE_FONT, tf.getFontName() + "_" + (i + 1)); + resTracker.registerSuppliedResource(derivedFontRes); + } + } } } } return fontResources; } + /** + * Defines the single-byte encoding for use in PostScript files. + * @param gen the PostScript generator + * @param encoding the single-byte encoding + * @return the PSResource instance that represents the encoding + * @throws IOException In case of an I/O problem + */ + public static PSResource defineEncoding(PSGenerator gen, SingleByteEncoding encoding) + throws IOException { + PSResource res = new PSResource(PSResource.TYPE_ENCODING, encoding.getName()); + gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res); + gen.writeln("/" + encoding.getName() + " ["); + String[] charNames = encoding.getCharNameMap(); + for (int i = 0; i < 256; i++) { + if (i > 0) { + if ((i % 5) == 0) { + gen.newLine(); + } else { + gen.write(" "); + } + } + String glyphname = null; + if (i < charNames.length) { + glyphname = charNames[i]; + } + if (glyphname == null || "".equals(glyphname)) { + glyphname = Glyphs.NOTDEF; + } + gen.write("/"); + gen.write(glyphname); + } + gen.newLine(); + gen.writeln("] def"); + gen.writeDSCComment(DSCConstants.END_RESOURCE); + gen.getResourceTracker().registerSuppliedResource(res); + return res; + } + + /** + * Derives a new font based on an existing font with a given encoding. The encoding must + * have been registered before. + * @param gen the PostScript generator + * @param baseFontName the font name of the font to derive from + * @param fontName the font name of the new font to be define + * @param encoding the new encoding (must be predefined in the PS file) + * @return the PSResource representing the derived font + * @throws IOException In case of an I/O problem + */ + public static PSResource defineDerivedFont(PSGenerator gen, String baseFontName, String fontName, + String encoding) throws IOException { + PSResource res = new PSResource(PSResource.TYPE_FONT, fontName); + gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res); + gen.commentln("%XGCDependencies: font " + baseFontName); + gen.commentln("%XGC+ encoding " + encoding); + gen.writeln("/" + baseFontName + " findfont"); + gen.writeln("dup length dict begin"); + gen.writeln(" {1 index /FID ne {def} {pop pop} ifelse} forall"); + gen.writeln(" /Encoding " + encoding + " def"); + gen.writeln(" currentdict"); + gen.writeln("end"); + gen.writeln("/" + fontName + " exch definefont pop"); + gen.writeDSCComment(DSCConstants.END_RESOURCE); + gen.getResourceTracker().registerSuppliedResource(res); + return res; + } + } diff --git a/src/java/org/apache/fop/render/ps/PSImageUtils.java b/src/java/org/apache/fop/render/ps/PSImageUtils.java deleted file mode 100644 index 004d5a22a..000000000 --- a/src/java/org/apache/fop/render/ps/PSImageUtils.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.ps; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.xmlgraphics.ps.PSGenerator; - -import org.apache.fop.image.EPSImage; -import org.apache.fop.image.FopImage; - -/** - * Utility code for rendering images in PostScript. - */ -public class PSImageUtils extends org.apache.xmlgraphics.ps.PSImageUtils { - - /** logging instance */ - protected static Log log = LogFactory.getLog(PSImageUtils.class); - - /** - * Renders an EPS image to PostScript. - * @param img EPS image to render - * @param x x position - * @param y y position - * @param w width - * @param h height - * @param gen PS generator - * @deprecated Use {@link #renderEPS(java.io.InputStream, String, java.awt.geom.Rectangle2D, - * java.awt.geom.Rectangle2D, PSGenerator)} instead - */ - public static void renderEPS(EPSImage img, - float x, float y, float w, float h, - PSGenerator gen) { - try { - if (!img.load(FopImage.ORIGINAL_DATA)) { - gen.commentln("%EPS image could not be processed: " + img); - return; - } - int[] bbox = img.getBBox(); - int bboxw = bbox[2] - bbox[0]; - int bboxh = bbox[3] - bbox[1]; - String name = img.getDocName(); - if (name == null || name.length() == 0) { - name = img.getOriginalURI(); - } - renderEPS(img.getEPSImage(), name, - x, y, w, h, - bbox[0], bbox[1], bboxw, bboxh, gen); - - } catch (Exception e) { - log.error("PSRenderer.renderImageArea(): Error rendering bitmap (" - + e.getMessage() + ")", e); - } - } - -} diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index ecd403749..7e32977e6 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -89,6 +89,7 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.LazyFont; +import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.Graphics2DAdapter; @@ -660,6 +661,12 @@ public class PSRenderer extends AbstractPathOrientedRenderer } private String getPostScriptNameForFontKey(String key) { + int pos = key.indexOf('_'); + String postFix = null; + if (pos > 0) { + postFix = key.substring(pos); + key = key.substring(0, pos); + } Map fonts = fontInfo.getFonts(); Typeface tf = (Typeface)fonts.get(key); if (tf instanceof LazyFont) { @@ -668,7 +675,11 @@ public class PSRenderer extends AbstractPathOrientedRenderer if (tf == null) { throw new IllegalStateException("Font not available: " + key); } - return tf.getFontName(); + if (postFix == null) { + return tf.getFontName(); + } else { + return tf.getFontName() + postFix; + } } /** @@ -698,7 +709,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer protected void useFont(String key, int size) { try { PSResource res = getPSResourceForFontKey(key); - //gen.useFont(key, size / 1000f); gen.useFont("/" + res.getName(), size / 1000f); gen.getResourceTracker().notifyResourceUsageOnPage(res); } catch (IOException ioe) { @@ -951,7 +961,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer if (!isOptimizeResources()) { this.fontResources = PSFontUtils.writeFontDict(gen, fontInfo); } else { - gen.commentln("%FOPFontSetup"); + gen.commentln("%FOPFontSetup"); //Place-holder, will be replaced in the second pass } gen.writeDSCComment(DSCConstants.END_SETUP); } @@ -1292,17 +1302,16 @@ public class PSRenderer extends AbstractPathOrientedRenderer */ public void renderText(TextArea area) { renderInlineAreaBackAndBorders(area); - String fontname = getInternalFontNameForArea(area); + String fontkey = getInternalFontNameForArea(area); int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE); // This assumes that *all* CIDFonts use a /ToUnicode mapping - Typeface tf = (Typeface) fontInfo.getFonts().get(fontname); + Typeface tf = (Typeface) fontInfo.getFonts().get(fontkey); //Determine position int rx = currentIPPosition + area.getBorderAndPaddingWidthStart(); int bl = currentBPPosition + area.getOffset() + area.getBaselineOffset(); - useFont(fontname, fontsize); Color ct = (Color)area.getTrait(Trait.COLOR); if (ct != null) { try { @@ -1347,30 +1356,75 @@ public class PSRenderer extends AbstractPathOrientedRenderer super.renderSpace(space); } + private Typeface getTypeface(String fontName) { + Typeface tf = (Typeface)fontInfo.getFonts().get(fontName); + if (tf instanceof LazyFont) { + tf = ((LazyFont)tf).getRealFont(); + } + return tf; + } + private void renderText(AbstractTextArea area, String text, int[] letterAdjust) { + String fontkey = getInternalFontNameForArea(area); + int fontSize = area.getTraitAsInteger(Trait.FONT_SIZE); Font font = getFontFromArea(area); - Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName()); + Typeface tf = getTypeface(font.getFontName()); + SingleByteFont singleByteFont = null; + if (tf instanceof SingleByteFont) { + singleByteFont = (SingleByteFont)tf; + } + int textLen = text.length(); + if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) { + int start = 0; + int currentEncoding = -1; + for (int i = 0; i < textLen; i++) { + char c = text.charAt(i); + char mapped = tf.mapChar(c); + int encoding = mapped / 256; + if (currentEncoding != encoding) { + if (i > 0) { + writeText(area, text, start, i - start, letterAdjust, fontSize, tf); + } + if (encoding == 0) { + useFont(fontkey, fontSize); + } else { + useFont(fontkey + "_" + Integer.toString(encoding), fontSize); + } + currentEncoding = encoding; + start = i; + } + } + writeText(area, text, start, textLen - start, letterAdjust, fontSize, tf); + } else { + useFont(fontkey, fontSize); + writeText(area, text, 0, textLen, letterAdjust, fontSize, tf); + } + } + + private void writeText(AbstractTextArea area, String text, int start, int len, + int[] letterAdjust, int fontsize, Typeface tf) { + int end = start + len; int initialSize = text.length(); initialSize += initialSize / 2; StringBuffer sb = new StringBuffer(initialSize); - int textLen = text.length(); if (letterAdjust == null && area.getTextLetterSpaceAdjust() == 0 && area.getTextWordSpaceAdjust() == 0) { sb.append("("); - for (int i = 0; i < textLen; i++) { + for (int i = start; i < end; i++) { final char c = text.charAt(i); - final char mapped = tf.mapChar(c); + final char mapped = (char)(tf.mapChar(c) % 256); PSGenerator.escapeChar(mapped, sb); } sb.append(") t"); } else { sb.append("("); - int[] offsets = new int[textLen]; - for (int i = 0; i < textLen; i++) { + int[] offsets = new int[len]; + for (int i = start; i < end; i++) { final char c = text.charAt(i); final char mapped = tf.mapChar(c); + char codepoint = (char)(mapped % 256); int wordSpace; if (CharUtilities.isAdjustableSpace(mapped)) { @@ -1378,14 +1432,14 @@ public class PSRenderer extends AbstractPathOrientedRenderer } else { wordSpace = 0; } - int cw = tf.getWidth(mapped, font.getFontSize()) / 1000; - int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0); - int tls = (i < textLen - 1 ? area.getTextLetterSpaceAdjust() : 0); - offsets[i] = cw + ladj + tls + wordSpace; - PSGenerator.escapeChar(mapped, sb); + int cw = tf.getWidth(mapped, fontsize) / 1000; + int ladj = (letterAdjust != null && i < end - 1 ? letterAdjust[i + 1] : 0); + int tls = (i < end - 1 ? area.getTextLetterSpaceAdjust() : 0); + offsets[i - start] = cw + ladj + tls + wordSpace; + PSGenerator.escapeChar(codepoint, sb); } sb.append(")" + PSGenerator.LF + "["); - for (int i = 0; i < textLen; i++) { + for (int i = 0; i < len; i++) { if (i > 0) { if (i % 8 == 0) { sb.append(PSGenerator.LF); @@ -1398,7 +1452,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer sb.append("]" + PSGenerator.LF + "xshow"); } writeln(sb.toString()); - } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/rtf/SVGConverter.java b/src/java/org/apache/fop/render/rtf/SVGConverter.java deleted file mode 100644 index 11ba8dc82..000000000 --- a/src/java/org/apache/fop/render/rtf/SVGConverter.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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; - -import org.apache.batik.transcoder.TranscoderException; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.batik.transcoder.TranscoderOutput; -import org.apache.batik.transcoder.image.JPEGTranscoder; -import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.image.XMLImage; - -/** - * Helper class for converting SVG to bitmap images. - */ -public final class SVGConverter { - - /** logger instance */ - private static Log log = LogFactory.getLog(SVGConverter.class); - - /** - * Constructor is private, because it's just a utility class. - */ - private SVGConverter() { - } - - /** - * Converts a SVG image to a JPEG bitmap. - * @param image the SVG image - * @return a byte array containing the JPEG image - */ - public static byte[] convertToJPEG(XMLImage image) { - JPEGTranscoder transcoder = new JPEGTranscoder(); - /* TODO Disabled to avoid side-effect due to the mixing of source and target resolutions - * This should be reenabled when it has been determined how exactly to handle this - transcoder.addTranscodingHint(ImageTranscoder.KEY_PIXEL_UNIT_TO_MILLIMETER, - new Float(25.4f / 300)); //300dpi should be enough for now. - */ - transcoder.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(0.9f)); - TranscoderInput input = new TranscoderInput(image.getDocument()); - ByteArrayOutputStream baout = new ByteArrayOutputStream(16384); - TranscoderOutput output = new TranscoderOutput(baout); - try { - transcoder.transcode(input, output); - return baout.toByteArray(); - } catch (TranscoderException e) { - log.error(e); - return null; - } - } - -} diff --git a/src/java/org/apache/fop/image/analyser/SVGZReader.java b/src/java/org/apache/fop/svg/GraphicsConfiguration.java index 14fde1cb6..a92baed27 100644 --- a/src/java/org/apache/fop/image/analyser/SVGZReader.java +++ b/src/java/org/apache/fop/svg/GraphicsConfiguration.java @@ -16,38 +16,36 @@ */ /* $Id$ */ + -package org.apache.fop.image.analyser; +package org.apache.fop.svg; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.GZIPInputStream; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.image.FopImage; +import java.awt.image.VolatileImage; /** - * Implements a reader for gzipped XMLFiles. + * Adapter to allow subclassing java.awt.GraphicsConfiguration without + * compilation errors. + * The version for JDK 1.4 needs to add an override for the abstract + * createCompatibleVolatileImage() method. It can't be overidden + * for JDK 1.3 because there is no VolatileImage there. * - * <p> - * The current implementation is limited to SVG files only. */ -public class SVGZReader extends XMLReader { +abstract public class GraphicsConfiguration extends java.awt.GraphicsConfiguration { + /** - * Default constructor. + * @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int) + * @since JDK 1.4 */ - public SVGZReader() { + public VolatileImage createCompatibleVolatileImage(int width, int height) { + return null; } - /** {@inheritDoc} */ - protected FopImage.ImageInfo loadImage(final String uri, - final InputStream bis, final FOUserAgent ua) { - try { - return new SVGReader().verifySignature(uri, - new GZIPInputStream(bis), ua); - } catch (final IOException e) { - // ignore - } + /** + * @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int, int) + * @since JDK 1.5 + */ + public VolatileImage createCompatibleVolatileImage(int width, int height, int transparency) { return null; } + } diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index 864809ebe..f6a7cbc3b 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -70,12 +70,10 @@ import org.apache.xmlgraphics.image.loader.impl.ImageRendered; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; -import org.apache.fop.fonts.CIDFont; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.FontTriplet; -import org.apache.fop.fonts.LazyFont; import org.apache.fop.pdf.BitmapImage; import org.apache.fop.pdf.PDFAnnotList; import org.apache.fop.pdf.PDFColor; @@ -1473,14 +1471,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { // This assumes that *all* CIDFonts use a /ToUnicode mapping org.apache.fop.fonts.Typeface f = (org.apache.fop.fonts.Typeface)fontInfo.getFonts().get(name); - if (f instanceof LazyFont) { - if (((LazyFont) f).getRealFont() instanceof CIDFont) { - return true; - } - } else if (f instanceof CIDFont) { - return true; - } - return false; + return f.isMultiByte(); } private void addKerning(StringWriter buf, Integer ch1, Integer ch2, diff --git a/src/java/org/apache/fop/svg/PDFTextPainter.java b/src/java/org/apache/fop/svg/PDFTextPainter.java index 7154c68a9..754b0794b 100644 --- a/src/java/org/apache/fop/svg/PDFTextPainter.java +++ b/src/java/org/apache/fop/svg/PDFTextPainter.java @@ -43,6 +43,7 @@ import org.apache.batik.gvt.renderer.StrokingTextPainter; import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; import org.apache.batik.gvt.text.TextPaintInfo; import org.apache.batik.gvt.text.TextSpanLayout; + import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; @@ -83,8 +84,12 @@ public class PDFTextPainter extends StrokingTextPainter { super.paintTextRuns(textRuns, g2d); return; } - PDFGraphics2D pdf = (PDFGraphics2D)g2d; - PDFTextUtil textUtil = new PDFTextUtil(pdf); + final PDFGraphics2D pdf = (PDFGraphics2D)g2d; + PDFTextUtil textUtil = new PDFTextUtil(pdf.fontInfo) { + protected void write(String code) { + pdf.currentStream.write(code); + } + }; for (int i = 0; i < textRuns.size(); i++) { TextRun textRun = (TextRun)textRuns.get(i); AttributedCharacterIterator runaci = textRun.getACI(); @@ -134,7 +139,7 @@ public class PDFTextPainter extends StrokingTextPainter { } textUtil.saveGraphicsState(); - textUtil.concatMatrixCurrentTransform(); + textUtil.concatMatrix(g2d.getTransform()); Shape imclip = g2d.getClip(); pdf.writeClip(imclip); diff --git a/src/java/org/apache/fop/svg/PDFTextUtil.java b/src/java/org/apache/fop/svg/PDFTextUtil.java index 0fb552026..f3c7f31a2 100644 --- a/src/java/org/apache/fop/svg/PDFTextUtil.java +++ b/src/java/org/apache/fop/svg/PDFTextUtil.java @@ -19,145 +19,33 @@ package org.apache.fop.svg; -import java.awt.geom.AffineTransform; - import org.apache.fop.fonts.Font; -import org.apache.fop.pdf.PDFNumber; -import org.apache.fop.pdf.PDFText; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.Typeface; /** - * Utility class for generating PDF text objects. + * Utility class for generating PDF text objects. It needs to be subclassed to add writing + * functionality (see {@link #write(String)}). */ -public class PDFTextUtil { +public abstract class PDFTextUtil extends org.apache.fop.pdf.PDFTextUtil { - /** The number of decimal places. */ - private static final int DEC = 8; - - /** PDF text rendering mode: Fill text */ - public static final int TR_FILL = 0; - /** PDF text rendering mode: Stroke text */ - public static final int TR_STROKE = 1; - /** PDF text rendering mode: Fill, then stroke text */ - public static final int TR_FILL_STROKE = 2; - /** PDF text rendering mode: Neither fill nor stroke text (invisible) */ - public static final int TR_INVISIBLE = 3; - /** PDF text rendering mode: Fill text and add to path for clipping */ - public static final int TR_FILL_CLIP = 4; - /** PDF text rendering mode: Stroke text and add to path for clipping */ - public static final int TR_STROKE_CLIP = 5; - /** PDF text rendering mode: Fill, then stroke text and add to path for clipping */ - public static final int TR_FILL_STROKE_CLIP = 6; - /** PDF text rendering mode: Add text to path for clipping */ - public static final int TR_CLIP = 7; - - - private PDFGraphics2D g2d; - private boolean inTextObject = false; + private FontInfo fontInfo; private Font[] fonts; private Font font; - private String startText; - private String endText; - private boolean useMultiByte; - private StringBuffer bufTJ; - private int textRenderingMode = 0; /** * Main constructor. - * @param g2d the PDFGraphics2D instance to work with + * @param fontInfo the font catalog */ - public PDFTextUtil(PDFGraphics2D g2d) { - this.g2d = g2d; + public PDFTextUtil(FontInfo fontInfo) { + super(); + this.fontInfo = fontInfo; } - private void writeAffineTransform(AffineTransform at, StringBuffer sb) { - double[] lt = new double[6]; - at.getMatrix(lt); - sb.append(PDFNumber.doubleOut(lt[0], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[1], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[2], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[3], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[4], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[5], DEC)); - } - - private void writeChar(char ch, StringBuffer sb) { - if (!useMultiByte) { - if (ch > 127) { - sb.append("\\").append(Integer.toOctalString((int)ch)); - } else { - switch (ch) { - case '(': - case ')': - case '\\': - sb.append("\\"); - break; - default: - } - sb.append(ch); - } - } else { - sb.append(PDFText.toUnicodeHex(ch)); - } - } - - private void checkInTextObject() { - if (!inTextObject) { - throw new IllegalStateException("Not in text object"); - } - } - - /** - * Called when a new text object should be started. Be sure to call setFont() before - * issuing any text painting commands. - */ - public void beginTextObject() { - if (inTextObject) { - throw new IllegalStateException("Already in text object"); - } - g2d.currentStream.write("BT\n"); - this.inTextObject = true; - } - - /** - * Called when a text object should be ended. - */ - public void endTextObject() { - checkInTextObject(); - g2d.currentStream.write("ET\n"); - this.inTextObject = false; - initValues(); - } - - private void initValues() { + /** {@inheritDoc} */ + protected void initValues() { + super.initValues(); this.font = null; - this.textRenderingMode = TR_FILL; - } - - /** - * Creates a "q" command, pushing a copy of the entire graphics state onto the stack. - */ - public void saveGraphicsState() { - g2d.currentStream.write("q\n"); - } - - /** - * Creates a "Q" command, restoring the entire graphics state to its former value by popping - * it from the stack. - */ - public void restoreGraphicsState() { - g2d.currentStream.write("Q\n"); - } - - /** - * Creates a "cm" command using the current transformation as the matrix. - */ - public void concatMatrixCurrentTransform() { - StringBuffer sb = new StringBuffer(); - if (!g2d.getTransform().isIdentity()) { - writeAffineTransform(g2d.getTransform(), sb); - sb.append(" cm\n"); - } - g2d.currentStream.write(sb.toString()); } /** @@ -194,63 +82,23 @@ public class PDFTextUtil { } /** + * Determines whether the font with the given name is a multi-byte font. + * @param name the name of the font + * @return true if it's a multi-byte font + */ + protected boolean isMultiByteFont(String name) { + Typeface f = (Typeface)fontInfo.getFonts().get(name); + return f.isMultiByte(); + } + + /** * Writes a "Tf" command, setting a new current font. * @param f the font to select */ public void writeTf(Font f) { - checkInTextObject(); String fontName = f.getFontName(); float fontSize = (float)f.getFontSize() / 1000f; - g2d.currentStream.write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n"); - - this.useMultiByte = g2d.isMultiByteFont(fontName); - this.startText = useMultiByte ? "<" : "("; - this.endText = useMultiByte ? ">" : ")"; - } - - /** - * Sets the text rendering mode. - * @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*) - */ - public void setTextRenderingMode(int mode) { - if (mode < 0 || mode > 7) { - throw new IllegalArgumentException( - "Illegal value for text rendering mode. Expected: 0-7"); - } - if (mode != this.textRenderingMode) { - this.textRenderingMode = mode; - g2d.currentStream.write(this.textRenderingMode + " Tr\n"); - } - } - - /** - * Sets the text rendering mode. - * @param fill true if the text should be filled - * @param stroke true if the text should be stroked - * @param addToClip true if the path should be added for clipping - */ - public void setTextRenderingMode(boolean fill, boolean stroke, boolean addToClip) { - int mode; - if (fill) { - mode = (stroke ? 2 : 0); - } else { - mode = (stroke ? 1 : 3); - } - if (addToClip) { - mode += 4; - } - setTextRenderingMode(mode); - } - - /** - * Writes a "Tm" command, setting a new text transformation matrix. - * @param localTransform the new text transformation matrix - */ - public void writeTextMatrix(AffineTransform localTransform) { - StringBuffer sb = new StringBuffer(); - writeAffineTransform(localTransform, sb); - sb.append(" Tm\n"); - g2d.currentStream.write(sb.toString()); + updateTf(fontName, fontSize, isMultiByteFont(fontName)); } /** @@ -272,37 +120,8 @@ public class PDFTextUtil { * @param ch the unmapped character */ public void writeTJChar(char ch) { - if (bufTJ == null) { - bufTJ = new StringBuffer(); - } - if (bufTJ.length() == 0) { - bufTJ.append("[").append(startText); - } char mappedChar = font.mapChar(ch); - writeChar(mappedChar, bufTJ); - } - - /** - * Writes a glyph adjust value to the "TJ-Buffer". - * @param adjust the glyph adjust value in thousands of text unit space. - */ - public void adjustGlyphTJ(double adjust) { - bufTJ.append(endText).append(" "); - bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4)); - bufTJ.append(" "); - bufTJ.append(startText); - } - - /** - * Writes a "TJ" command, writing out the accumulated buffer with the characters and glyph - * positioning values. The buffer is reset afterwards. - */ - public void writeTJ() { - if (bufTJ != null && bufTJ.length() > 0) { - bufTJ.append(endText).append("] TJ\n"); - g2d.currentStream.write(bufTJ.toString()); - bufTJ.setLength(0); - } + writeTJMappedChar(mappedChar); } } |