Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

PCLGenerator.java 47KB

Merged branch https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ProcessingFeedback into Trunk. Changes on branch: ........ r615153 | jeremias | 2008-01-25 10:07:21 +0100 (Fr, 25 Jan 2008) | 1 line Created temporary branch for processing feedback. ........ r615155 | jeremias | 2008-01-25 10:11:59 +0100 (Fr, 25 Jan 2008) | 1 line Initial commit of what I've built already for those who prefer code to minimalistic design docs. ........ r615278 | jeremias | 2008-01-25 18:25:00 +0100 (Fr, 25 Jan 2008) | 1 line EventProducer interfaces now operational. ........ r615773 | jeremias | 2008-01-28 10:06:16 +0100 (Mo, 28 Jan 2008) | 1 line No casting in client code when creating EventProducer instances. ........ r616242 | vhennebert | 2008-01-29 11:34:45 +0100 (Di, 29 Jan 2008) | 3 lines Trick to avoid hard-coding the class name of EventProducer in the source file. Feel free to revert if it's not ok. ........ r616900 | jeremias | 2008-01-30 21:59:31 +0100 (Mi, 30 Jan 2008) | 1 line Generate event model XMLs in to the build directory: build/gensrc and build/test-gensrc (the latter is new and needs to be setup as source folder in your IDE!) ........ r616907 | jeremias | 2008-01-30 22:12:59 +0100 (Mi, 30 Jan 2008) | 1 line Added an XMLResourceBundle that uses an XML file instead of a properties file to load the translations. The XML format is the same as for Cocoon's XMLResourceBundle. ........ r617097 | vhennebert | 2008-01-31 11:53:21 +0100 (Do, 31 Jan 2008) | 2 lines Minor typo + slight improvement of Javadoc ........ r617176 | jeremias | 2008-01-31 19:14:19 +0100 (Do, 31 Jan 2008) | 5 lines Renamed FopEvent to Event as suggested by Simon. EventProducerCollectorTask.java now reads the EventSeverity from a doclet tag. Added generation of EventProducer translations (including simple merging, no validation, yet) EventFormatter introduced (only basic functionality, yet). Added a simple EventListener implementation that uses EventFormatter to convert the events to human-readable, localized messages that are sent to the log via Commons Logging. ........ r617362 | jeremias | 2008-02-01 08:18:07 +0100 (Fr, 01 Feb 2008) | 1 line Some remaining rename operations based on an earlier discussion. ........ r617413 | jeremias | 2008-02-01 10:46:26 +0100 (Fr, 01 Feb 2008) | 2 lines Extracted formatting functionality into utility class AdvancedMessageFormat.java. AdvancedMessageFormat.java now supports conditional sub-groups (delimited by []). ........ r618682 | jeremias | 2008-02-05 17:07:08 +0100 (Di, 05 Feb 2008) | 1 line Add support for special object formatters (where toString() isn't good enough). ATM, it's hard-coded but could later be hooked into dynamic discovery if we have multiple such formatters. The SAX Locator is the only example for now. ........ r618686 | jeremias | 2008-02-05 17:12:56 +0100 (Di, 05 Feb 2008) | 3 lines Hooked most of FONode into the new event mechanism. The FOUserAgent provides a DefaultEventBroadcaster instance. If a producer method declares throwing an exception, the event is automatically marked FATAL and the dynamic proxy throws an exception right after notifying the listeners. The exceptions are created through the EventExceptionManager. It currently contains only one exception factory for ValidationException. If we need more such factories it's better to register them dynamically. Right now, they're hard-coded. ........ r619313 | jeremias | 2008-02-07 10:14:15 +0100 (Do, 07 Feb 2008) | 1 line Make sure no events are now just silently swallowed because after upgrading a user doesn't know about the event system. ........ r619314 | jeremias | 2008-02-07 10:14:46 +0100 (Do, 07 Feb 2008) | 1 line Log what translation file is being written. ........ r619320 | jeremias | 2008-02-07 10:31:00 +0100 (Do, 07 Feb 2008) | 2 lines FObj hooked into the event system. Code reduction using a protected method on FONode to acquire a FOValidationEventProducer. ........ r619359 | jeremias | 2008-02-07 11:59:19 +0100 (Do, 07 Feb 2008) | 2 lines Fop's QName now extends XGCommons' QName to initiate a transition. Hooked PropertyList into the event mechanism. ........ r631252 | jeremias | 2008-02-26 16:24:33 +0100 (Di, 26 Feb 2008) | 1 line Removed superfluous warning. ........ r631268 | jeremias | 2008-02-26 17:08:11 +0100 (Di, 26 Feb 2008) | 1 line Deprecated two methods which are a problem for localization. Also helps finding additional spots to switch over to the event mechanism. ........ r633852 | jeremias | 2008-03-05 15:20:24 +0100 (Mi, 05 Mrz 2008) | 1 line Add severity to formatting parameters. ........ r633855 | jeremias | 2008-03-05 15:21:57 +0100 (Mi, 05 Mrz 2008) | 4 lines Added support for additional field styles: {<fieldname>,if,<true-text>,<false-text>} {<fieldname>,equals,<test-string>,<true-text>,<false-text>} ........ r633856 | jeremias | 2008-03-05 15:24:04 +0100 (Mi, 05 Mrz 2008) | 2 lines Javadocs and TODOs. EventListeners can change the event severity. ........ r633857 | jeremias | 2008-03-05 15:27:08 +0100 (Mi, 05 Mrz 2008) | 4 lines Javadocs. Moved out event listener registration into a CompositeEventListener. Event broadcaster uses the events effective severity, not the initial value (for the case where listeners override the initial value). Set up a special EventBroadCaster in the FOUserAgent that filters events through a class (FOValidationEventListenerProxy) that adjusts the event severity for relaxed validation. ........ r633858 | jeremias | 2008-03-05 15:32:07 +0100 (Mi, 05 Mrz 2008) | 2 lines Instead of always decentrally checking whether strict validation is enabled or not, this is now done in a special event listener. The event producer method caller simply indicates whether it can recover from the error condition and continue. Started switching to event production in table FOs. ........ r634027 | jeremias | 2008-03-05 21:58:35 +0100 (Mi, 05 Mrz 2008) | 7 lines Moved AdvancedMessageFormat into its own package. AdvancedMessageFormat got the following added functionality: - Alternative conditional regions [ bla {field}] -> [ bla {field1}| even more bla {field2}] - Functions: functions get access to the parameters and they can produce an object that is then formatted ({#gatherContextInfo}) - "if" and "equals" format moved to top-level classes and added by dynamic registration. EventFormatter now supports includes in the form {{includeName}} so you can include other entries from the resource bundle for better reuse. Some more events in table code. ........ r634031 | jeremias | 2008-03-05 22:05:22 +0100 (Mi, 05 Mrz 2008) | 1 line SVN Props ........ r634208 | jeremias | 2008-03-06 11:26:52 +0100 (Do, 06 Mrz 2008) | 2 lines Improved context gathering. Moved GatherContextInfoFunction to an inner class of FONode to reduce visibilities. ........ r634209 | jeremias | 2008-03-06 11:28:14 +0100 (Do, 06 Mrz 2008) | 1 line Made FOPException localizable. ........ r634280 | jeremias | 2008-03-06 15:38:30 +0100 (Do, 06 Mrz 2008) | 2 lines ExceptionFactory is now dynamically registered. More table warnings and errors switch to events. ........ r634326 | jeremias | 2008-03-06 17:08:16 +0100 (Do, 06 Mrz 2008) | 1 line Remaining table FOs switched to events. ........ r634328 | jeremias | 2008-03-06 17:09:21 +0100 (Do, 06 Mrz 2008) | 1 line Deprecated FOP's QName. Mixing with Commons' variant only produces problems. ........ r634381 | jeremias | 2008-03-06 20:12:57 +0100 (Do, 06 Mrz 2008) | 2 lines Made the "invalidChild" event fully localizable by adding a "lookup" field for the optional rule to be displayed. And a few switches to the event system. ........ r634692 | jeremias | 2008-03-07 15:31:43 +0100 (Fr, 07 Mrz 2008) | 1 line More FO tree stuff switched to events. ........ r634712 | jeremias | 2008-03-07 16:19:21 +0100 (Fr, 07 Mrz 2008) | 1 line Avoid an NPE that says nothing (ex. could happen if the message template is wrong). ........ r634738 | jeremias | 2008-03-07 17:38:21 +0100 (Fr, 07 Mrz 2008) | 2 lines Non-FO children were not properly run through validation by FOTreeBuilder. Unified the way that non-FO elements are validated. Some FOs were already fixed. I now fixed the rest, so foreign elements can occur everywhere. ........ r637833 | jeremias | 2008-03-17 12:01:41 +0100 (Mo, 17 Mrz 2008) | 1 line Exception while cloning for RetrieveMarker to be handled by user as suggested by Andreas. ........ r637835 | jeremias | 2008-03-17 12:03:31 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a RuntimeException of no other Exception class is specified for an event as a fallback if someone just sets the event severity to FATAL. ........ r637838 | jeremias | 2008-03-17 12:06:10 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a meaningful exception when the property name is wrong. Otherwise, there will be an ArrayIndexOutOfBoundsException. ........ r637859 | jeremias | 2008-03-17 13:35:26 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a meaningful exception when the property name is wrong. Otherwise, there will be an ArrayIndexOutOfBoundsException. ........ r637938 | jeremias | 2008-03-17 16:19:51 +0100 (Mo, 17 Mrz 2008) | 1 line Switched pagination package to events. ........ r637947 | jeremias | 2008-03-17 16:45:16 +0100 (Mo, 17 Mrz 2008) | 1 line Removed unlocalizable validation helper methods. ........ r637952 | jeremias | 2008-03-17 16:59:02 +0100 (Mo, 17 Mrz 2008) | 1 line Events on FOTreeBuilder. ........ r638299 | jeremias | 2008-03-18 11:09:30 +0100 (Di, 18 Mrz 2008) | 2 lines Added support for java.util.text's ChoiceFormat to AdvancedMessageFormat. Reuse the regexes as constants. ........ r638302 | jeremias | 2008-03-18 11:17:06 +0100 (Di, 18 Mrz 2008) | 1 line Events for inline-level layout managers. ........ r638774 | jeremias | 2008-03-19 11:17:36 +0100 (Mi, 19 Mrz 2008) | 1 line Added DEBUG level. ........ r638777 | jeremias | 2008-03-19 11:23:40 +0100 (Mi, 19 Mrz 2008) | 3 lines Generalized FOValidationEventListenerProxy into FOPEventListenerProxy, the main proxy for FOP's own event manipulation proxy. Done because of support for overflow="hidden" vs. overflow="error-if-overflow". Switched block-level layout managers to events. Some cleanup along the way. ........ r639222 | jeremias | 2008-03-20 10:27:34 +0100 (Do, 20 Mrz 2008) | 2 lines Some initial work for event forwarding from Batik. Missing errors/exceptions converted to events in PageSequenceMaster. ........ r639270 | jeremias | 2008-03-20 13:50:35 +0100 (Do, 20 Mrz 2008) | 1 line Removed DEBUG event severity again. Promoted constrained geometry adjustment event to INFO level as per discussion. ........ r640395 | jeremias | 2008-03-24 13:39:13 +0100 (Mo, 24 Mrz 2008) | 3 lines Moved the creation of the fallback LoggingEventListener to FOUserAgent so event before the startDocument() SAX event arrive in the log. Dynamic discovery of event models. Renderers and extensions can register renderer-specific event models. Switched the most important parts of the renderers to events (maybe not everything is converted). ........ r640397 | jeremias | 2008-03-24 13:43:04 +0100 (Mo, 24 Mrz 2008) | 1 line Remaining fixcrlfs. Xalan likes to mix CRLF and LF on Windows. ........ r640398 | jeremias | 2008-03-24 13:43:54 +0100 (Mo, 24 Mrz 2008) | 1 line Ignore namespace declarations for property handling. ........ r640463 | jeremias | 2008-03-24 17:59:52 +0100 (Mo, 24 Mrz 2008) | 2 lines Event in area package. Exposed getUserAgent() in Renderer interface (was already public in AbstractRenderer). ........ r642972 | jeremias | 2008-03-31 14:18:39 +0200 (Mo, 31 Mrz 2008) | 1 line Code restructured a bit. ........ r642975 | jeremias | 2008-03-31 14:24:07 +0200 (Mo, 31 Mrz 2008) | 2 lines Plugged fonts package into the event subsystem. Note: I did not follow the same pattern as for the rest as the font package is to be considered FOP-external, so I just added a manual adapter for the FontEventListener. This demonstrates how an external library can be integrated with the event system. Missing warning for unknown formatting objects added. Warning is not issued by the ElementMappingRegistry anymore but by FOTreeBuilder which has access to more context information. ........ r642997 | jeremias | 2008-03-31 16:10:08 +0200 (Mo, 31 Mrz 2008) | 1 line Added an example to demonstrate how to write your own event listener and how to deal with the exceptions thrown in the process. ........ r642998 | jeremias | 2008-03-31 16:13:40 +0200 (Mo, 31 Mrz 2008) | 1 line Removed unused method. Event formatting should not be part of the Event class. Use EventFormatter.format(Event) instead. ........ r643066 | jeremias | 2008-03-31 19:18:54 +0200 (Mo, 31 Mrz 2008) | 1 line First part of the event subsystem documentation (DRAFT). ........ r643784 | jeremias | 2008-04-02 10:05:33 +0200 (Mi, 02 Apr 2008) | 1 line More documentation. ........ r643785 | jeremias | 2008-04-02 10:06:38 +0200 (Mi, 02 Apr 2008) | 1 line Some nits. ........ r643787 | jeremias | 2008-04-02 10:24:41 +0200 (Mi, 02 Apr 2008) | 1 line Completed javadocs ........ r643824 | jeremias | 2008-04-02 12:00:30 +0200 (Mi, 02 Apr 2008) | 1 line Javadocs. ........ r645847 | vhennebert | 2008-04-08 12:54:16 +0200 (Di, 08 Apr 2008) | 2 lines Minor typo fixes ........ r645848 | vhennebert | 2008-04-08 12:58:30 +0200 (Di, 08 Apr 2008) | 2 lines Another small typo fix ........ r647678 | jeremias | 2008-04-14 09:20:26 +0200 (Mo, 14 Apr 2008) | 1 line Renamed *EventProducer.Factory.create() to *EventProducer.Provider.get() to better reflect what the method does (instances may be cached and reused). ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@647742 13f79535-47bb-0310-9956-ffa450edef68
před 16 roky
Merged branch https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ProcessingFeedback into Trunk. Changes on branch: ........ r615153 | jeremias | 2008-01-25 10:07:21 +0100 (Fr, 25 Jan 2008) | 1 line Created temporary branch for processing feedback. ........ r615155 | jeremias | 2008-01-25 10:11:59 +0100 (Fr, 25 Jan 2008) | 1 line Initial commit of what I've built already for those who prefer code to minimalistic design docs. ........ r615278 | jeremias | 2008-01-25 18:25:00 +0100 (Fr, 25 Jan 2008) | 1 line EventProducer interfaces now operational. ........ r615773 | jeremias | 2008-01-28 10:06:16 +0100 (Mo, 28 Jan 2008) | 1 line No casting in client code when creating EventProducer instances. ........ r616242 | vhennebert | 2008-01-29 11:34:45 +0100 (Di, 29 Jan 2008) | 3 lines Trick to avoid hard-coding the class name of EventProducer in the source file. Feel free to revert if it's not ok. ........ r616900 | jeremias | 2008-01-30 21:59:31 +0100 (Mi, 30 Jan 2008) | 1 line Generate event model XMLs in to the build directory: build/gensrc and build/test-gensrc (the latter is new and needs to be setup as source folder in your IDE!) ........ r616907 | jeremias | 2008-01-30 22:12:59 +0100 (Mi, 30 Jan 2008) | 1 line Added an XMLResourceBundle that uses an XML file instead of a properties file to load the translations. The XML format is the same as for Cocoon's XMLResourceBundle. ........ r617097 | vhennebert | 2008-01-31 11:53:21 +0100 (Do, 31 Jan 2008) | 2 lines Minor typo + slight improvement of Javadoc ........ r617176 | jeremias | 2008-01-31 19:14:19 +0100 (Do, 31 Jan 2008) | 5 lines Renamed FopEvent to Event as suggested by Simon. EventProducerCollectorTask.java now reads the EventSeverity from a doclet tag. Added generation of EventProducer translations (including simple merging, no validation, yet) EventFormatter introduced (only basic functionality, yet). Added a simple EventListener implementation that uses EventFormatter to convert the events to human-readable, localized messages that are sent to the log via Commons Logging. ........ r617362 | jeremias | 2008-02-01 08:18:07 +0100 (Fr, 01 Feb 2008) | 1 line Some remaining rename operations based on an earlier discussion. ........ r617413 | jeremias | 2008-02-01 10:46:26 +0100 (Fr, 01 Feb 2008) | 2 lines Extracted formatting functionality into utility class AdvancedMessageFormat.java. AdvancedMessageFormat.java now supports conditional sub-groups (delimited by []). ........ r618682 | jeremias | 2008-02-05 17:07:08 +0100 (Di, 05 Feb 2008) | 1 line Add support for special object formatters (where toString() isn't good enough). ATM, it's hard-coded but could later be hooked into dynamic discovery if we have multiple such formatters. The SAX Locator is the only example for now. ........ r618686 | jeremias | 2008-02-05 17:12:56 +0100 (Di, 05 Feb 2008) | 3 lines Hooked most of FONode into the new event mechanism. The FOUserAgent provides a DefaultEventBroadcaster instance. If a producer method declares throwing an exception, the event is automatically marked FATAL and the dynamic proxy throws an exception right after notifying the listeners. The exceptions are created through the EventExceptionManager. It currently contains only one exception factory for ValidationException. If we need more such factories it's better to register them dynamically. Right now, they're hard-coded. ........ r619313 | jeremias | 2008-02-07 10:14:15 +0100 (Do, 07 Feb 2008) | 1 line Make sure no events are now just silently swallowed because after upgrading a user doesn't know about the event system. ........ r619314 | jeremias | 2008-02-07 10:14:46 +0100 (Do, 07 Feb 2008) | 1 line Log what translation file is being written. ........ r619320 | jeremias | 2008-02-07 10:31:00 +0100 (Do, 07 Feb 2008) | 2 lines FObj hooked into the event system. Code reduction using a protected method on FONode to acquire a FOValidationEventProducer. ........ r619359 | jeremias | 2008-02-07 11:59:19 +0100 (Do, 07 Feb 2008) | 2 lines Fop's QName now extends XGCommons' QName to initiate a transition. Hooked PropertyList into the event mechanism. ........ r631252 | jeremias | 2008-02-26 16:24:33 +0100 (Di, 26 Feb 2008) | 1 line Removed superfluous warning. ........ r631268 | jeremias | 2008-02-26 17:08:11 +0100 (Di, 26 Feb 2008) | 1 line Deprecated two methods which are a problem for localization. Also helps finding additional spots to switch over to the event mechanism. ........ r633852 | jeremias | 2008-03-05 15:20:24 +0100 (Mi, 05 Mrz 2008) | 1 line Add severity to formatting parameters. ........ r633855 | jeremias | 2008-03-05 15:21:57 +0100 (Mi, 05 Mrz 2008) | 4 lines Added support for additional field styles: {<fieldname>,if,<true-text>,<false-text>} {<fieldname>,equals,<test-string>,<true-text>,<false-text>} ........ r633856 | jeremias | 2008-03-05 15:24:04 +0100 (Mi, 05 Mrz 2008) | 2 lines Javadocs and TODOs. EventListeners can change the event severity. ........ r633857 | jeremias | 2008-03-05 15:27:08 +0100 (Mi, 05 Mrz 2008) | 4 lines Javadocs. Moved out event listener registration into a CompositeEventListener. Event broadcaster uses the events effective severity, not the initial value (for the case where listeners override the initial value). Set up a special EventBroadCaster in the FOUserAgent that filters events through a class (FOValidationEventListenerProxy) that adjusts the event severity for relaxed validation. ........ r633858 | jeremias | 2008-03-05 15:32:07 +0100 (Mi, 05 Mrz 2008) | 2 lines Instead of always decentrally checking whether strict validation is enabled or not, this is now done in a special event listener. The event producer method caller simply indicates whether it can recover from the error condition and continue. Started switching to event production in table FOs. ........ r634027 | jeremias | 2008-03-05 21:58:35 +0100 (Mi, 05 Mrz 2008) | 7 lines Moved AdvancedMessageFormat into its own package. AdvancedMessageFormat got the following added functionality: - Alternative conditional regions [ bla {field}] -> [ bla {field1}| even more bla {field2}] - Functions: functions get access to the parameters and they can produce an object that is then formatted ({#gatherContextInfo}) - "if" and "equals" format moved to top-level classes and added by dynamic registration. EventFormatter now supports includes in the form {{includeName}} so you can include other entries from the resource bundle for better reuse. Some more events in table code. ........ r634031 | jeremias | 2008-03-05 22:05:22 +0100 (Mi, 05 Mrz 2008) | 1 line SVN Props ........ r634208 | jeremias | 2008-03-06 11:26:52 +0100 (Do, 06 Mrz 2008) | 2 lines Improved context gathering. Moved GatherContextInfoFunction to an inner class of FONode to reduce visibilities. ........ r634209 | jeremias | 2008-03-06 11:28:14 +0100 (Do, 06 Mrz 2008) | 1 line Made FOPException localizable. ........ r634280 | jeremias | 2008-03-06 15:38:30 +0100 (Do, 06 Mrz 2008) | 2 lines ExceptionFactory is now dynamically registered. More table warnings and errors switch to events. ........ r634326 | jeremias | 2008-03-06 17:08:16 +0100 (Do, 06 Mrz 2008) | 1 line Remaining table FOs switched to events. ........ r634328 | jeremias | 2008-03-06 17:09:21 +0100 (Do, 06 Mrz 2008) | 1 line Deprecated FOP's QName. Mixing with Commons' variant only produces problems. ........ r634381 | jeremias | 2008-03-06 20:12:57 +0100 (Do, 06 Mrz 2008) | 2 lines Made the "invalidChild" event fully localizable by adding a "lookup" field for the optional rule to be displayed. And a few switches to the event system. ........ r634692 | jeremias | 2008-03-07 15:31:43 +0100 (Fr, 07 Mrz 2008) | 1 line More FO tree stuff switched to events. ........ r634712 | jeremias | 2008-03-07 16:19:21 +0100 (Fr, 07 Mrz 2008) | 1 line Avoid an NPE that says nothing (ex. could happen if the message template is wrong). ........ r634738 | jeremias | 2008-03-07 17:38:21 +0100 (Fr, 07 Mrz 2008) | 2 lines Non-FO children were not properly run through validation by FOTreeBuilder. Unified the way that non-FO elements are validated. Some FOs were already fixed. I now fixed the rest, so foreign elements can occur everywhere. ........ r637833 | jeremias | 2008-03-17 12:01:41 +0100 (Mo, 17 Mrz 2008) | 1 line Exception while cloning for RetrieveMarker to be handled by user as suggested by Andreas. ........ r637835 | jeremias | 2008-03-17 12:03:31 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a RuntimeException of no other Exception class is specified for an event as a fallback if someone just sets the event severity to FATAL. ........ r637838 | jeremias | 2008-03-17 12:06:10 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a meaningful exception when the property name is wrong. Otherwise, there will be an ArrayIndexOutOfBoundsException. ........ r637859 | jeremias | 2008-03-17 13:35:26 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a meaningful exception when the property name is wrong. Otherwise, there will be an ArrayIndexOutOfBoundsException. ........ r637938 | jeremias | 2008-03-17 16:19:51 +0100 (Mo, 17 Mrz 2008) | 1 line Switched pagination package to events. ........ r637947 | jeremias | 2008-03-17 16:45:16 +0100 (Mo, 17 Mrz 2008) | 1 line Removed unlocalizable validation helper methods. ........ r637952 | jeremias | 2008-03-17 16:59:02 +0100 (Mo, 17 Mrz 2008) | 1 line Events on FOTreeBuilder. ........ r638299 | jeremias | 2008-03-18 11:09:30 +0100 (Di, 18 Mrz 2008) | 2 lines Added support for java.util.text's ChoiceFormat to AdvancedMessageFormat. Reuse the regexes as constants. ........ r638302 | jeremias | 2008-03-18 11:17:06 +0100 (Di, 18 Mrz 2008) | 1 line Events for inline-level layout managers. ........ r638774 | jeremias | 2008-03-19 11:17:36 +0100 (Mi, 19 Mrz 2008) | 1 line Added DEBUG level. ........ r638777 | jeremias | 2008-03-19 11:23:40 +0100 (Mi, 19 Mrz 2008) | 3 lines Generalized FOValidationEventListenerProxy into FOPEventListenerProxy, the main proxy for FOP's own event manipulation proxy. Done because of support for overflow="hidden" vs. overflow="error-if-overflow". Switched block-level layout managers to events. Some cleanup along the way. ........ r639222 | jeremias | 2008-03-20 10:27:34 +0100 (Do, 20 Mrz 2008) | 2 lines Some initial work for event forwarding from Batik. Missing errors/exceptions converted to events in PageSequenceMaster. ........ r639270 | jeremias | 2008-03-20 13:50:35 +0100 (Do, 20 Mrz 2008) | 1 line Removed DEBUG event severity again. Promoted constrained geometry adjustment event to INFO level as per discussion. ........ r640395 | jeremias | 2008-03-24 13:39:13 +0100 (Mo, 24 Mrz 2008) | 3 lines Moved the creation of the fallback LoggingEventListener to FOUserAgent so event before the startDocument() SAX event arrive in the log. Dynamic discovery of event models. Renderers and extensions can register renderer-specific event models. Switched the most important parts of the renderers to events (maybe not everything is converted). ........ r640397 | jeremias | 2008-03-24 13:43:04 +0100 (Mo, 24 Mrz 2008) | 1 line Remaining fixcrlfs. Xalan likes to mix CRLF and LF on Windows. ........ r640398 | jeremias | 2008-03-24 13:43:54 +0100 (Mo, 24 Mrz 2008) | 1 line Ignore namespace declarations for property handling. ........ r640463 | jeremias | 2008-03-24 17:59:52 +0100 (Mo, 24 Mrz 2008) | 2 lines Event in area package. Exposed getUserAgent() in Renderer interface (was already public in AbstractRenderer). ........ r642972 | jeremias | 2008-03-31 14:18:39 +0200 (Mo, 31 Mrz 2008) | 1 line Code restructured a bit. ........ r642975 | jeremias | 2008-03-31 14:24:07 +0200 (Mo, 31 Mrz 2008) | 2 lines Plugged fonts package into the event subsystem. Note: I did not follow the same pattern as for the rest as the font package is to be considered FOP-external, so I just added a manual adapter for the FontEventListener. This demonstrates how an external library can be integrated with the event system. Missing warning for unknown formatting objects added. Warning is not issued by the ElementMappingRegistry anymore but by FOTreeBuilder which has access to more context information. ........ r642997 | jeremias | 2008-03-31 16:10:08 +0200 (Mo, 31 Mrz 2008) | 1 line Added an example to demonstrate how to write your own event listener and how to deal with the exceptions thrown in the process. ........ r642998 | jeremias | 2008-03-31 16:13:40 +0200 (Mo, 31 Mrz 2008) | 1 line Removed unused method. Event formatting should not be part of the Event class. Use EventFormatter.format(Event) instead. ........ r643066 | jeremias | 2008-03-31 19:18:54 +0200 (Mo, 31 Mrz 2008) | 1 line First part of the event subsystem documentation (DRAFT). ........ r643784 | jeremias | 2008-04-02 10:05:33 +0200 (Mi, 02 Apr 2008) | 1 line More documentation. ........ r643785 | jeremias | 2008-04-02 10:06:38 +0200 (Mi, 02 Apr 2008) | 1 line Some nits. ........ r643787 | jeremias | 2008-04-02 10:24:41 +0200 (Mi, 02 Apr 2008) | 1 line Completed javadocs ........ r643824 | jeremias | 2008-04-02 12:00:30 +0200 (Mi, 02 Apr 2008) | 1 line Javadocs. ........ r645847 | vhennebert | 2008-04-08 12:54:16 +0200 (Di, 08 Apr 2008) | 2 lines Minor typo fixes ........ r645848 | vhennebert | 2008-04-08 12:58:30 +0200 (Di, 08 Apr 2008) | 2 lines Another small typo fix ........ r647678 | jeremias | 2008-04-14 09:20:26 +0200 (Mo, 14 Apr 2008) | 1 line Renamed *EventProducer.Factory.create() to *EventProducer.Provider.get() to better reflect what the method does (instances may be cached and reused). ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@647742 13f79535-47bb-0310-9956-ffa450edef68
před 16 roky
Merged branch https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ProcessingFeedback into Trunk. Changes on branch: ........ r615153 | jeremias | 2008-01-25 10:07:21 +0100 (Fr, 25 Jan 2008) | 1 line Created temporary branch for processing feedback. ........ r615155 | jeremias | 2008-01-25 10:11:59 +0100 (Fr, 25 Jan 2008) | 1 line Initial commit of what I've built already for those who prefer code to minimalistic design docs. ........ r615278 | jeremias | 2008-01-25 18:25:00 +0100 (Fr, 25 Jan 2008) | 1 line EventProducer interfaces now operational. ........ r615773 | jeremias | 2008-01-28 10:06:16 +0100 (Mo, 28 Jan 2008) | 1 line No casting in client code when creating EventProducer instances. ........ r616242 | vhennebert | 2008-01-29 11:34:45 +0100 (Di, 29 Jan 2008) | 3 lines Trick to avoid hard-coding the class name of EventProducer in the source file. Feel free to revert if it's not ok. ........ r616900 | jeremias | 2008-01-30 21:59:31 +0100 (Mi, 30 Jan 2008) | 1 line Generate event model XMLs in to the build directory: build/gensrc and build/test-gensrc (the latter is new and needs to be setup as source folder in your IDE!) ........ r616907 | jeremias | 2008-01-30 22:12:59 +0100 (Mi, 30 Jan 2008) | 1 line Added an XMLResourceBundle that uses an XML file instead of a properties file to load the translations. The XML format is the same as for Cocoon's XMLResourceBundle. ........ r617097 | vhennebert | 2008-01-31 11:53:21 +0100 (Do, 31 Jan 2008) | 2 lines Minor typo + slight improvement of Javadoc ........ r617176 | jeremias | 2008-01-31 19:14:19 +0100 (Do, 31 Jan 2008) | 5 lines Renamed FopEvent to Event as suggested by Simon. EventProducerCollectorTask.java now reads the EventSeverity from a doclet tag. Added generation of EventProducer translations (including simple merging, no validation, yet) EventFormatter introduced (only basic functionality, yet). Added a simple EventListener implementation that uses EventFormatter to convert the events to human-readable, localized messages that are sent to the log via Commons Logging. ........ r617362 | jeremias | 2008-02-01 08:18:07 +0100 (Fr, 01 Feb 2008) | 1 line Some remaining rename operations based on an earlier discussion. ........ r617413 | jeremias | 2008-02-01 10:46:26 +0100 (Fr, 01 Feb 2008) | 2 lines Extracted formatting functionality into utility class AdvancedMessageFormat.java. AdvancedMessageFormat.java now supports conditional sub-groups (delimited by []). ........ r618682 | jeremias | 2008-02-05 17:07:08 +0100 (Di, 05 Feb 2008) | 1 line Add support for special object formatters (where toString() isn't good enough). ATM, it's hard-coded but could later be hooked into dynamic discovery if we have multiple such formatters. The SAX Locator is the only example for now. ........ r618686 | jeremias | 2008-02-05 17:12:56 +0100 (Di, 05 Feb 2008) | 3 lines Hooked most of FONode into the new event mechanism. The FOUserAgent provides a DefaultEventBroadcaster instance. If a producer method declares throwing an exception, the event is automatically marked FATAL and the dynamic proxy throws an exception right after notifying the listeners. The exceptions are created through the EventExceptionManager. It currently contains only one exception factory for ValidationException. If we need more such factories it's better to register them dynamically. Right now, they're hard-coded. ........ r619313 | jeremias | 2008-02-07 10:14:15 +0100 (Do, 07 Feb 2008) | 1 line Make sure no events are now just silently swallowed because after upgrading a user doesn't know about the event system. ........ r619314 | jeremias | 2008-02-07 10:14:46 +0100 (Do, 07 Feb 2008) | 1 line Log what translation file is being written. ........ r619320 | jeremias | 2008-02-07 10:31:00 +0100 (Do, 07 Feb 2008) | 2 lines FObj hooked into the event system. Code reduction using a protected method on FONode to acquire a FOValidationEventProducer. ........ r619359 | jeremias | 2008-02-07 11:59:19 +0100 (Do, 07 Feb 2008) | 2 lines Fop's QName now extends XGCommons' QName to initiate a transition. Hooked PropertyList into the event mechanism. ........ r631252 | jeremias | 2008-02-26 16:24:33 +0100 (Di, 26 Feb 2008) | 1 line Removed superfluous warning. ........ r631268 | jeremias | 2008-02-26 17:08:11 +0100 (Di, 26 Feb 2008) | 1 line Deprecated two methods which are a problem for localization. Also helps finding additional spots to switch over to the event mechanism. ........ r633852 | jeremias | 2008-03-05 15:20:24 +0100 (Mi, 05 Mrz 2008) | 1 line Add severity to formatting parameters. ........ r633855 | jeremias | 2008-03-05 15:21:57 +0100 (Mi, 05 Mrz 2008) | 4 lines Added support for additional field styles: {<fieldname>,if,<true-text>,<false-text>} {<fieldname>,equals,<test-string>,<true-text>,<false-text>} ........ r633856 | jeremias | 2008-03-05 15:24:04 +0100 (Mi, 05 Mrz 2008) | 2 lines Javadocs and TODOs. EventListeners can change the event severity. ........ r633857 | jeremias | 2008-03-05 15:27:08 +0100 (Mi, 05 Mrz 2008) | 4 lines Javadocs. Moved out event listener registration into a CompositeEventListener. Event broadcaster uses the events effective severity, not the initial value (for the case where listeners override the initial value). Set up a special EventBroadCaster in the FOUserAgent that filters events through a class (FOValidationEventListenerProxy) that adjusts the event severity for relaxed validation. ........ r633858 | jeremias | 2008-03-05 15:32:07 +0100 (Mi, 05 Mrz 2008) | 2 lines Instead of always decentrally checking whether strict validation is enabled or not, this is now done in a special event listener. The event producer method caller simply indicates whether it can recover from the error condition and continue. Started switching to event production in table FOs. ........ r634027 | jeremias | 2008-03-05 21:58:35 +0100 (Mi, 05 Mrz 2008) | 7 lines Moved AdvancedMessageFormat into its own package. AdvancedMessageFormat got the following added functionality: - Alternative conditional regions [ bla {field}] -> [ bla {field1}| even more bla {field2}] - Functions: functions get access to the parameters and they can produce an object that is then formatted ({#gatherContextInfo}) - "if" and "equals" format moved to top-level classes and added by dynamic registration. EventFormatter now supports includes in the form {{includeName}} so you can include other entries from the resource bundle for better reuse. Some more events in table code. ........ r634031 | jeremias | 2008-03-05 22:05:22 +0100 (Mi, 05 Mrz 2008) | 1 line SVN Props ........ r634208 | jeremias | 2008-03-06 11:26:52 +0100 (Do, 06 Mrz 2008) | 2 lines Improved context gathering. Moved GatherContextInfoFunction to an inner class of FONode to reduce visibilities. ........ r634209 | jeremias | 2008-03-06 11:28:14 +0100 (Do, 06 Mrz 2008) | 1 line Made FOPException localizable. ........ r634280 | jeremias | 2008-03-06 15:38:30 +0100 (Do, 06 Mrz 2008) | 2 lines ExceptionFactory is now dynamically registered. More table warnings and errors switch to events. ........ r634326 | jeremias | 2008-03-06 17:08:16 +0100 (Do, 06 Mrz 2008) | 1 line Remaining table FOs switched to events. ........ r634328 | jeremias | 2008-03-06 17:09:21 +0100 (Do, 06 Mrz 2008) | 1 line Deprecated FOP's QName. Mixing with Commons' variant only produces problems. ........ r634381 | jeremias | 2008-03-06 20:12:57 +0100 (Do, 06 Mrz 2008) | 2 lines Made the "invalidChild" event fully localizable by adding a "lookup" field for the optional rule to be displayed. And a few switches to the event system. ........ r634692 | jeremias | 2008-03-07 15:31:43 +0100 (Fr, 07 Mrz 2008) | 1 line More FO tree stuff switched to events. ........ r634712 | jeremias | 2008-03-07 16:19:21 +0100 (Fr, 07 Mrz 2008) | 1 line Avoid an NPE that says nothing (ex. could happen if the message template is wrong). ........ r634738 | jeremias | 2008-03-07 17:38:21 +0100 (Fr, 07 Mrz 2008) | 2 lines Non-FO children were not properly run through validation by FOTreeBuilder. Unified the way that non-FO elements are validated. Some FOs were already fixed. I now fixed the rest, so foreign elements can occur everywhere. ........ r637833 | jeremias | 2008-03-17 12:01:41 +0100 (Mo, 17 Mrz 2008) | 1 line Exception while cloning for RetrieveMarker to be handled by user as suggested by Andreas. ........ r637835 | jeremias | 2008-03-17 12:03:31 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a RuntimeException of no other Exception class is specified for an event as a fallback if someone just sets the event severity to FATAL. ........ r637838 | jeremias | 2008-03-17 12:06:10 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a meaningful exception when the property name is wrong. Otherwise, there will be an ArrayIndexOutOfBoundsException. ........ r637859 | jeremias | 2008-03-17 13:35:26 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a meaningful exception when the property name is wrong. Otherwise, there will be an ArrayIndexOutOfBoundsException. ........ r637938 | jeremias | 2008-03-17 16:19:51 +0100 (Mo, 17 Mrz 2008) | 1 line Switched pagination package to events. ........ r637947 | jeremias | 2008-03-17 16:45:16 +0100 (Mo, 17 Mrz 2008) | 1 line Removed unlocalizable validation helper methods. ........ r637952 | jeremias | 2008-03-17 16:59:02 +0100 (Mo, 17 Mrz 2008) | 1 line Events on FOTreeBuilder. ........ r638299 | jeremias | 2008-03-18 11:09:30 +0100 (Di, 18 Mrz 2008) | 2 lines Added support for java.util.text's ChoiceFormat to AdvancedMessageFormat. Reuse the regexes as constants. ........ r638302 | jeremias | 2008-03-18 11:17:06 +0100 (Di, 18 Mrz 2008) | 1 line Events for inline-level layout managers. ........ r638774 | jeremias | 2008-03-19 11:17:36 +0100 (Mi, 19 Mrz 2008) | 1 line Added DEBUG level. ........ r638777 | jeremias | 2008-03-19 11:23:40 +0100 (Mi, 19 Mrz 2008) | 3 lines Generalized FOValidationEventListenerProxy into FOPEventListenerProxy, the main proxy for FOP's own event manipulation proxy. Done because of support for overflow="hidden" vs. overflow="error-if-overflow". Switched block-level layout managers to events. Some cleanup along the way. ........ r639222 | jeremias | 2008-03-20 10:27:34 +0100 (Do, 20 Mrz 2008) | 2 lines Some initial work for event forwarding from Batik. Missing errors/exceptions converted to events in PageSequenceMaster. ........ r639270 | jeremias | 2008-03-20 13:50:35 +0100 (Do, 20 Mrz 2008) | 1 line Removed DEBUG event severity again. Promoted constrained geometry adjustment event to INFO level as per discussion. ........ r640395 | jeremias | 2008-03-24 13:39:13 +0100 (Mo, 24 Mrz 2008) | 3 lines Moved the creation of the fallback LoggingEventListener to FOUserAgent so event before the startDocument() SAX event arrive in the log. Dynamic discovery of event models. Renderers and extensions can register renderer-specific event models. Switched the most important parts of the renderers to events (maybe not everything is converted). ........ r640397 | jeremias | 2008-03-24 13:43:04 +0100 (Mo, 24 Mrz 2008) | 1 line Remaining fixcrlfs. Xalan likes to mix CRLF and LF on Windows. ........ r640398 | jeremias | 2008-03-24 13:43:54 +0100 (Mo, 24 Mrz 2008) | 1 line Ignore namespace declarations for property handling. ........ r640463 | jeremias | 2008-03-24 17:59:52 +0100 (Mo, 24 Mrz 2008) | 2 lines Event in area package. Exposed getUserAgent() in Renderer interface (was already public in AbstractRenderer). ........ r642972 | jeremias | 2008-03-31 14:18:39 +0200 (Mo, 31 Mrz 2008) | 1 line Code restructured a bit. ........ r642975 | jeremias | 2008-03-31 14:24:07 +0200 (Mo, 31 Mrz 2008) | 2 lines Plugged fonts package into the event subsystem. Note: I did not follow the same pattern as for the rest as the font package is to be considered FOP-external, so I just added a manual adapter for the FontEventListener. This demonstrates how an external library can be integrated with the event system. Missing warning for unknown formatting objects added. Warning is not issued by the ElementMappingRegistry anymore but by FOTreeBuilder which has access to more context information. ........ r642997 | jeremias | 2008-03-31 16:10:08 +0200 (Mo, 31 Mrz 2008) | 1 line Added an example to demonstrate how to write your own event listener and how to deal with the exceptions thrown in the process. ........ r642998 | jeremias | 2008-03-31 16:13:40 +0200 (Mo, 31 Mrz 2008) | 1 line Removed unused method. Event formatting should not be part of the Event class. Use EventFormatter.format(Event) instead. ........ r643066 | jeremias | 2008-03-31 19:18:54 +0200 (Mo, 31 Mrz 2008) | 1 line First part of the event subsystem documentation (DRAFT). ........ r643784 | jeremias | 2008-04-02 10:05:33 +0200 (Mi, 02 Apr 2008) | 1 line More documentation. ........ r643785 | jeremias | 2008-04-02 10:06:38 +0200 (Mi, 02 Apr 2008) | 1 line Some nits. ........ r643787 | jeremias | 2008-04-02 10:24:41 +0200 (Mi, 02 Apr 2008) | 1 line Completed javadocs ........ r643824 | jeremias | 2008-04-02 12:00:30 +0200 (Mi, 02 Apr 2008) | 1 line Javadocs. ........ r645847 | vhennebert | 2008-04-08 12:54:16 +0200 (Di, 08 Apr 2008) | 2 lines Minor typo fixes ........ r645848 | vhennebert | 2008-04-08 12:58:30 +0200 (Di, 08 Apr 2008) | 2 lines Another small typo fix ........ r647678 | jeremias | 2008-04-14 09:20:26 +0200 (Mo, 14 Apr 2008) | 1 line Renamed *EventProducer.Factory.create() to *EventProducer.Provider.get() to better reflect what the method does (instances may be cached and reused). ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@647742 13f79535-47bb-0310-9956-ffa450edef68
před 16 roky
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.render.pcl;
  19. import java.awt.Color;
  20. import java.awt.Dimension;
  21. import java.awt.Graphics2D;
  22. import java.awt.Image;
  23. import java.awt.image.BufferedImage;
  24. import java.awt.image.ColorModel;
  25. import java.awt.image.DataBuffer;
  26. import java.awt.image.DataBufferByte;
  27. import java.awt.image.DataBufferInt;
  28. import java.awt.image.DirectColorModel;
  29. import java.awt.image.IndexColorModel;
  30. import java.awt.image.MultiPixelPackedSampleModel;
  31. import java.awt.image.Raster;
  32. import java.awt.image.RenderedImage;
  33. import java.awt.image.SinglePixelPackedSampleModel;
  34. import java.io.DataOutputStream;
  35. import java.io.IOException;
  36. import java.io.OutputStream;
  37. import java.text.DecimalFormat;
  38. import java.text.DecimalFormatSymbols;
  39. import java.util.HashMap;
  40. import java.util.LinkedHashMap;
  41. import java.util.Locale;
  42. import java.util.Map;
  43. import org.apache.commons.io.IOUtils;
  44. import org.apache.commons.io.output.ByteArrayOutputStream;
  45. import org.apache.commons.io.output.CountingOutputStream;
  46. import org.apache.xmlgraphics.util.UnitConv;
  47. import org.apache.fop.fonts.Typeface;
  48. import org.apache.fop.render.pcl.fonts.PCLFontReader;
  49. import org.apache.fop.render.pcl.fonts.PCLSoftFontManager;
  50. import org.apache.fop.util.bitmap.BitmapImageUtil;
  51. import org.apache.fop.util.bitmap.DitherUtil;
  52. /**
  53. * This class provides methods for generating PCL print files.
  54. */
  55. public class PCLGenerator {
  56. private static final String US_ASCII = "US-ASCII";
  57. private static final String ISO_8859_1 = "ISO-8859-1";
  58. /** The ESC (escape) character */
  59. public static final char ESC = '\033';
  60. /** A list of all supported resolutions in PCL (values in dpi) */
  61. public static final int[] PCL_RESOLUTIONS = new int[] {75, 100, 150, 200, 300, 600};
  62. private final DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
  63. private final DecimalFormat df2 = new DecimalFormat("0.##", symbols);
  64. private final DecimalFormat df4 = new DecimalFormat("0.####", symbols);
  65. private final CountingOutputStream out;
  66. protected Map<Typeface, PCLFontReader> fontReaderMap = new HashMap<Typeface, PCLFontReader>();
  67. protected Map<PCLSoftFontManager, Map<Typeface, Long>> fontManagerMap
  68. = new LinkedHashMap<PCLSoftFontManager, Map<Typeface, Long>>();
  69. private boolean currentSourceTransparency = true;
  70. private boolean currentPatternTransparency = true;
  71. private int maxBitmapResolution = PCL_RESOLUTIONS[PCL_RESOLUTIONS.length - 1];
  72. private float ditheringQuality = 0.5f;
  73. /**
  74. * true: Standard PCL shades are used (poor quality). false: user-defined pattern are used
  75. * to create custom dither patterns for better grayscale quality.
  76. */
  77. private static final boolean USE_PCL_SHADES = false;
  78. /**
  79. * Main constructor.
  80. * @param out the OutputStream to write the PCL stream to
  81. */
  82. public PCLGenerator(OutputStream out) {
  83. this.out = new CountingOutputStream(out);
  84. }
  85. /**
  86. * Main constructor.
  87. * @param out the OutputStream to write the PCL stream to
  88. * @param maxResolution the maximum resolution to encode bitmap images at
  89. */
  90. public PCLGenerator(OutputStream out, int maxResolution) {
  91. this(out);
  92. boolean found = false;
  93. for (int pclResolutions : PCL_RESOLUTIONS) {
  94. if (pclResolutions == maxResolution) {
  95. found = true;
  96. break;
  97. }
  98. }
  99. if (!found) {
  100. throw new IllegalArgumentException("Illegal value for maximum resolution!");
  101. }
  102. this.maxBitmapResolution = maxResolution;
  103. }
  104. public void addFont(PCLSoftFontManager sfManager, Typeface font) {
  105. if (!fontManagerMap.containsKey(sfManager)) {
  106. fontManagerMap.put(sfManager, new LinkedHashMap<Typeface, Long>());
  107. }
  108. Map<Typeface, Long> fonts = fontManagerMap.get(sfManager);
  109. if (!fonts.containsKey(font)) {
  110. fonts.put(font, out.getByteCount());
  111. }
  112. }
  113. /** @return the OutputStream that this generator writes to */
  114. public OutputStream getOutputStream() {
  115. return this.out;
  116. }
  117. /**
  118. * Returns the currently active text encoding.
  119. * @return the text encoding
  120. */
  121. public String getTextEncoding() {
  122. return ISO_8859_1;
  123. }
  124. /** @return the maximum resolution to encode bitmap images at */
  125. public int getMaximumBitmapResolution() {
  126. return this.maxBitmapResolution;
  127. }
  128. /**
  129. * Writes a PCL escape command to the output stream.
  130. * @param cmd the command (without the ESCAPE character)
  131. * @throws IOException In case of an I/O error
  132. */
  133. public void writeCommand(String cmd) throws IOException {
  134. out.write(27); //ESC
  135. out.write(cmd.getBytes(US_ASCII));
  136. }
  137. /**
  138. * Writes raw text (in ISO-8859-1 encoding) to the output stream.
  139. * @param s the text
  140. * @throws IOException In case of an I/O error
  141. */
  142. public void writeText(String s) throws IOException {
  143. out.write(s.getBytes(ISO_8859_1));
  144. }
  145. /**
  146. * Writes raw bytes to the output stream
  147. * @param bytes The bytes
  148. * @throws IOException In case of an I/O error
  149. */
  150. public void writeBytes(byte[] bytes) throws IOException {
  151. out.write(bytes);
  152. }
  153. /**
  154. * Formats a double value with two decimal positions for PCL output.
  155. *
  156. * @param value value to format
  157. * @return the formatted value
  158. */
  159. public final String formatDouble2(double value) {
  160. return df2.format(value);
  161. }
  162. /**
  163. * Formats a double value with four decimal positions for PCL output.
  164. *
  165. * @param value value to format
  166. * @return the formatted value
  167. */
  168. public final String formatDouble4(double value) {
  169. return df4.format(value);
  170. }
  171. /**
  172. * Sends the universal end of language command (UEL).
  173. * @throws IOException In case of an I/O error
  174. */
  175. public void universalEndOfLanguage() throws IOException {
  176. writeCommand("%-12345X");
  177. }
  178. /**
  179. * Resets the printer and restores the user default environment.
  180. * @throws IOException In case of an I/O error
  181. */
  182. public void resetPrinter() throws IOException {
  183. writeCommand("E");
  184. }
  185. /**
  186. * Sends the job separation command.
  187. * @throws IOException In case of an I/O error
  188. */
  189. public void separateJobs() throws IOException {
  190. writeCommand("&l1T");
  191. }
  192. /**
  193. * Sends the form feed character.
  194. * @throws IOException In case of an I/O error
  195. */
  196. public void formFeed() throws IOException {
  197. out.write(12); //=OC ("FF", Form feed)
  198. }
  199. /**
  200. * Sets the unit of measure.
  201. * @param value the resolution value (units per inch)
  202. * @throws IOException In case of an I/O error
  203. */
  204. public void setUnitOfMeasure(int value) throws IOException {
  205. writeCommand("&u" + value + "D");
  206. }
  207. /**
  208. * Sets the raster graphics resolution
  209. * @param value the resolution value (units per inch)
  210. * @throws IOException In case of an I/O error
  211. */
  212. public void setRasterGraphicsResolution(int value) throws IOException {
  213. writeCommand("*t" + value + "R");
  214. }
  215. /**
  216. * Selects the page size.
  217. * @param selector the integer representing the page size
  218. * @throws IOException In case of an I/O error
  219. */
  220. public void selectPageSize(int selector) throws IOException {
  221. writeCommand("&l" + selector + "A");
  222. }
  223. /**
  224. * Selects the paper source. The parameter is usually printer-specific. Usually, "1" is the
  225. * default tray, "2" is the manual paper feed, "3" is the manual envelope feed, "4" is the
  226. * "lower" tray and "7" is "auto-select". Consult the technical reference for your printer
  227. * for all available values.
  228. * @param selector the integer representing the paper source/tray
  229. * @throws IOException In case of an I/O error
  230. */
  231. public void selectPaperSource(int selector) throws IOException {
  232. writeCommand("&l" + selector + "H");
  233. }
  234. /**
  235. * Selects the output bin. The parameter is usually printer-specific. Usually, "1" is the
  236. * default output bin (upper bin) and "2" is the lower (rear) output bin. Some printers
  237. * may support additional output bins. Consult the technical reference for your printer
  238. * for all available values.
  239. * @param selector the integer representing the output bin
  240. * @throws IOException In case of an I/O error
  241. */
  242. public void selectOutputBin(int selector) throws IOException {
  243. writeCommand("&l" + selector + "G");
  244. }
  245. /**
  246. * Selects the duplexing mode for the page.
  247. * The parameter is usually printer-specific.
  248. * "0" means Simplex,
  249. * "1" means Duplex, Long-Edge Binding,
  250. * "2" means Duplex, Short-Edge Binding.
  251. * @param selector the integer representing the duplexing mode of the page
  252. * @throws IOException In case of an I/O error
  253. */
  254. public void selectDuplexMode(int selector) throws IOException {
  255. writeCommand("&l" + selector + "S");
  256. }
  257. /**
  258. * Clears the horizontal margins.
  259. * @throws IOException In case of an I/O error
  260. */
  261. public void clearHorizontalMargins() throws IOException {
  262. writeCommand("9");
  263. }
  264. /**
  265. * The Top Margin command designates the number of lines between
  266. * the top of the logical page and the top of the text area.
  267. * @param numberOfLines the number of lines (See PCL specification for details)
  268. * @throws IOException In case of an I/O error
  269. */
  270. public void setTopMargin(int numberOfLines) throws IOException {
  271. writeCommand("&l" + numberOfLines + "E");
  272. }
  273. /**
  274. * The Text Length command can be used to define the bottom border. See the PCL specification
  275. * for details.
  276. * @param numberOfLines the number of lines
  277. * @throws IOException In case of an I/O error
  278. */
  279. public void setTextLength(int numberOfLines) throws IOException {
  280. writeCommand("&l" + numberOfLines + "F");
  281. }
  282. /**
  283. * Sets the Vertical Motion Index (VMI).
  284. * @param value the VMI value
  285. * @throws IOException In case of an I/O error
  286. */
  287. public void setVMI(double value) throws IOException {
  288. writeCommand("&l" + formatDouble4(value) + "C");
  289. }
  290. /**
  291. * Sets the cursor to a new absolute coordinate.
  292. * @param x the X coordinate (in millipoints)
  293. * @param y the Y coordinate (in millipoints)
  294. * @throws IOException In case of an I/O error
  295. */
  296. public void setCursorPos(double x, double y) throws IOException {
  297. if (x < 0) {
  298. //A negative x value will result in a relative movement so go to "0" first.
  299. //But this will most probably have no effect anyway since you can't paint to the left
  300. //of the logical page
  301. writeCommand("&a0h" + formatDouble2(x / 100) + "h" + formatDouble2(y / 100) + "V");
  302. } else {
  303. writeCommand("&a" + formatDouble2(x / 100) + "h" + formatDouble2(y / 100) + "V");
  304. }
  305. }
  306. /**
  307. * Pushes the current cursor position on a stack (stack size: max 20 entries)
  308. * @throws IOException In case of an I/O error
  309. */
  310. public void pushCursorPos() throws IOException {
  311. writeCommand("&f0S");
  312. }
  313. /**
  314. * Pops the current cursor position from the stack.
  315. * @throws IOException In case of an I/O error
  316. */
  317. public void popCursorPos() throws IOException {
  318. writeCommand("&f1S");
  319. }
  320. /**
  321. * Changes the current print direction while maintaining the current cursor position.
  322. * @param rotate the rotation angle (counterclockwise), one of 0, 90, 180 and 270.
  323. * @throws IOException In case of an I/O error
  324. */
  325. public void changePrintDirection(int rotate) throws IOException {
  326. writeCommand("&a" + rotate + "P");
  327. }
  328. /**
  329. * Enters the HP GL/2 mode.
  330. * @param restorePreviousHPGL2Cursor true if the previous HP GL/2 pen position should be
  331. * restored, false if the current position is maintained
  332. * @throws IOException In case of an I/O error
  333. */
  334. public void enterHPGL2Mode(boolean restorePreviousHPGL2Cursor) throws IOException {
  335. if (restorePreviousHPGL2Cursor) {
  336. writeCommand("%0B");
  337. } else {
  338. writeCommand("%1B");
  339. }
  340. }
  341. /**
  342. * Enters the PCL mode.
  343. * @param restorePreviousPCLCursor true if the previous PCL cursor position should be restored,
  344. * false if the current position is maintained
  345. * @throws IOException In case of an I/O error
  346. */
  347. public void enterPCLMode(boolean restorePreviousPCLCursor) throws IOException {
  348. if (restorePreviousPCLCursor) {
  349. writeCommand("%0A");
  350. } else {
  351. writeCommand("%1A");
  352. }
  353. }
  354. /**
  355. * Generate a filled rectangle at the current cursor position.
  356. *
  357. * @param w the width in millipoints
  358. * @param h the height in millipoints
  359. * @param col the fill color
  360. * @throws IOException In case of an I/O error
  361. */
  362. protected void fillRect(int w, int h, Color col, boolean colorEnabled) throws IOException {
  363. if ((w == 0) || (h == 0)) {
  364. return;
  365. }
  366. if (h < 0) {
  367. h *= -1;
  368. } else {
  369. //y += h;
  370. }
  371. setPatternTransparencyMode(false);
  372. if (USE_PCL_SHADES
  373. || Color.black.equals(col)
  374. || Color.white.equals(col)) {
  375. writeCommand("*c" + formatDouble4(w / 100.0) + "h"
  376. + formatDouble4(h / 100.0) + "V");
  377. int lineshade = convertToPCLShade(col);
  378. writeCommand("*c" + lineshade + "G");
  379. writeCommand("*c2P"); //Shaded fill
  380. } else {
  381. if (colorEnabled) {
  382. selectColor(col);
  383. writeCommand("*c" + formatDouble4(w / 100.0) + "h"
  384. + formatDouble4(h / 100.0) + "V");
  385. writeCommand("*c0P"); //Solid fill
  386. } else {
  387. defineGrayscalePattern(col, 32, DitherUtil.DITHER_MATRIX_4X4);
  388. writeCommand("*c" + formatDouble4(w / 100.0) + "h"
  389. + formatDouble4(h / 100.0) + "V");
  390. writeCommand("*c32G");
  391. writeCommand("*c4P"); //User-defined pattern
  392. }
  393. }
  394. // Reset pattern transparency mode.
  395. setPatternTransparencyMode(true);
  396. }
  397. /**
  398. * Generates a user-defined pattern for a dithering pattern matching the grayscale value
  399. * of the color given.
  400. * @param col the color to create the pattern for
  401. * @param patternID the pattern ID to use
  402. * @param ditherMatrixSize the size of the Bayer dither matrix to use (4 or 8 supported)
  403. * @throws IOException In case of an I/O error
  404. */
  405. public void defineGrayscalePattern(Color col, int patternID, int ditherMatrixSize)
  406. throws IOException {
  407. ByteArrayOutputStream baout = new ByteArrayOutputStream();
  408. DataOutputStream data = new DataOutputStream(baout);
  409. data.writeByte(0); //Format
  410. data.writeByte(0); //Continuation
  411. data.writeByte(1); //Pixel Encoding
  412. data.writeByte(0); //Reserved
  413. data.writeShort(8); //Width in Pixels
  414. data.writeShort(8); //Height in Pixels
  415. //data.writeShort(600); //X Resolution (didn't manage to get that to work)
  416. //data.writeShort(600); //Y Resolution
  417. int gray255 = convertToGray(col.getRed(), col.getGreen(), col.getBlue());
  418. byte[] pattern;
  419. if (ditherMatrixSize == 8) {
  420. pattern = DitherUtil.getBayerDither(DitherUtil.DITHER_MATRIX_8X8, gray255, false);
  421. } else {
  422. //Since a 4x4 pattern did not work, the 4x4 pattern is applied 4 times to an
  423. //8x8 pattern. Maybe this could be changed to use an 8x8 bayer dither pattern
  424. //instead of the 4x4 one.
  425. pattern = DitherUtil.getBayerDither(DitherUtil.DITHER_MATRIX_4X4, gray255, true);
  426. }
  427. data.write(pattern);
  428. if ((baout.size() % 2) > 0) {
  429. baout.write(0);
  430. }
  431. writeCommand("*c" + patternID + "G");
  432. writeCommand("*c" + baout.size() + "W");
  433. baout.writeTo(this.out);
  434. IOUtils.closeQuietly(data);
  435. IOUtils.closeQuietly(baout);
  436. writeCommand("*c4Q"); //temporary pattern
  437. }
  438. /**
  439. * Sets the source transparency mode.
  440. * @param transparent true if transparent, false for opaque
  441. * @throws IOException In case of an I/O error
  442. */
  443. public void setSourceTransparencyMode(boolean transparent) throws IOException {
  444. setTransparencyMode(transparent, currentPatternTransparency);
  445. }
  446. /**
  447. * Sets the pattern transparency mode.
  448. * @param transparent true if transparent, false for opaque
  449. * @throws IOException In case of an I/O error
  450. */
  451. public void setPatternTransparencyMode(boolean transparent) throws IOException {
  452. setTransparencyMode(currentSourceTransparency, transparent);
  453. }
  454. /**
  455. * Sets the transparency modes.
  456. * @param source source transparency: true if transparent, false for opaque
  457. * @param pattern pattern transparency: true if transparent, false for opaque
  458. * @throws IOException In case of an I/O error
  459. */
  460. public void setTransparencyMode(boolean source, boolean pattern) throws IOException {
  461. if (source != currentSourceTransparency && pattern != currentPatternTransparency) {
  462. writeCommand("*v" + (source ? '0' : '1') + "n" + (pattern ? '0' : '1') + "O");
  463. } else if (source != currentSourceTransparency) {
  464. writeCommand("*v" + (source ? '0' : '1') + "N");
  465. } else if (pattern != currentPatternTransparency) {
  466. writeCommand("*v" + (pattern ? '0' : '1') + "O");
  467. }
  468. this.currentSourceTransparency = source;
  469. this.currentPatternTransparency = pattern;
  470. }
  471. /**
  472. * Convert an RGB color value to a grayscale from 0 to 100.
  473. * @param r the red component
  474. * @param g the green component
  475. * @param b the blue component
  476. * @return the gray value
  477. */
  478. public final int convertToGray(int r, int g, int b) {
  479. return BitmapImageUtil.convertToGray(r, g, b);
  480. }
  481. /**
  482. * Convert a Color value to a PCL shade value (0-100).
  483. * @param col the color
  484. * @return the PCL shade value (100=black)
  485. */
  486. public final int convertToPCLShade(Color col) {
  487. float gray = convertToGray(col.getRed(), col.getGreen(), col.getBlue()) / 255f;
  488. return (int)(100 - (gray * 100f));
  489. }
  490. /**
  491. * Selects the current grayscale color (the given color is converted to grayscales).
  492. * @param col the color
  493. * @throws IOException In case of an I/O error
  494. */
  495. public void selectGrayscale(Color col) throws IOException {
  496. if (Color.black.equals(col)) {
  497. selectCurrentPattern(0, 0); //black
  498. } else if (Color.white.equals(col)) {
  499. selectCurrentPattern(0, 1); //white
  500. } else {
  501. if (USE_PCL_SHADES) {
  502. selectCurrentPattern(convertToPCLShade(col), 2);
  503. } else {
  504. defineGrayscalePattern(col, 32, DitherUtil.DITHER_MATRIX_4X4);
  505. selectCurrentPattern(32, 4);
  506. }
  507. }
  508. }
  509. public void selectColor(Color col) throws IOException {
  510. writeCommand("*v6W");
  511. writeBytes(new byte[]{0, 1, 1, 8, 8, 8});
  512. writeCommand(String.format("*v%da%db%dc0I", col.getRed(), col.getGreen(), col.getBlue()));
  513. writeCommand("*v0S");
  514. }
  515. /**
  516. * Select the current pattern
  517. * @param patternID the pattern ID (&lt;ESC&gt;*c#G command)
  518. * @param pattern the pattern type (&lt;ESC&gt;*v#T command)
  519. * @throws IOException In case of an I/O error
  520. */
  521. public void selectCurrentPattern(int patternID, int pattern) throws IOException {
  522. if (pattern > 1) {
  523. writeCommand("*c" + patternID + "G");
  524. }
  525. writeCommand("*v" + pattern + "T");
  526. }
  527. /**
  528. * Sets the dithering quality used when encoding gray or color images. If not explicitely
  529. * set a medium setting (0.5f) is used.
  530. * @param quality a quality setting between 0.0f (worst/fastest) and 1.0f (best/slowest)
  531. */
  532. public void setDitheringQuality(float quality) {
  533. quality = Math.min(Math.max(0f, quality), 1.0f);
  534. this.ditheringQuality = quality;
  535. }
  536. /**
  537. * Returns the dithering quality used when encoding gray or color images.
  538. * @return the quality setting between 0.0f (worst/fastest) and 1.0f (best/slowest)
  539. */
  540. public float getDitheringQuality() {
  541. return this.ditheringQuality;
  542. }
  543. /**
  544. * Indicates whether an image is a monochrome (b/w) image.
  545. * @param img the image
  546. * @return true if it's a monochrome image
  547. */
  548. public static boolean isMonochromeImage(RenderedImage img) {
  549. return BitmapImageUtil.isMonochromeImage(img);
  550. }
  551. /**
  552. * Indicates whether an image is a grayscale image.
  553. * @param img the image
  554. * @return true if it's a grayscale image
  555. */
  556. public static boolean isGrayscaleImage(RenderedImage img) {
  557. return BitmapImageUtil.isGrayscaleImage(img);
  558. }
  559. private static int jaiAvailable = -1; //no synchronization necessary, not critical
  560. /**
  561. * Indicates whether JAI is available. JAI has shown to be reliable when dithering a
  562. * grayscale or color image to monochrome bitmaps (1-bit).
  563. * @return true if JAI is available
  564. */
  565. public static boolean isJAIAvailable() {
  566. if (jaiAvailable < 0) {
  567. try {
  568. String clName = "javax.media.jai.JAI";
  569. Class.forName(clName);
  570. jaiAvailable = 1;
  571. } catch (ClassNotFoundException cnfe) {
  572. jaiAvailable = 0;
  573. }
  574. }
  575. return (jaiAvailable > 0);
  576. }
  577. private int calculatePCLResolution(int resolution) {
  578. return calculatePCLResolution(resolution, false);
  579. }
  580. /**
  581. * Calculates the ideal PCL resolution for a given resolution.
  582. * @param resolution the input resolution
  583. * @param increased true if you want to go to a higher resolution, for example if you
  584. * convert grayscale or color images to monochrome images so dithering has
  585. * a chance to generate better quality.
  586. * @return the resulting PCL resolution (one of 75, 100, 150, 200, 300, 600)
  587. */
  588. private int calculatePCLResolution(int resolution, boolean increased) {
  589. int choice = -1;
  590. for (int i = PCL_RESOLUTIONS.length - 2; i >= 0; i--) {
  591. if (resolution > PCL_RESOLUTIONS[i]) {
  592. int idx = i + 1;
  593. if (idx < PCL_RESOLUTIONS.length - 2) {
  594. idx += increased ? 2 : 0;
  595. } else if (idx < PCL_RESOLUTIONS.length - 1) {
  596. idx += increased ? 1 : 0;
  597. }
  598. choice = idx;
  599. break;
  600. //return PCL_RESOLUTIONS[idx];
  601. }
  602. }
  603. if (choice < 0) {
  604. choice = (increased ? 2 : 0);
  605. }
  606. while (choice > 0 && PCL_RESOLUTIONS[choice] > getMaximumBitmapResolution()) {
  607. choice--;
  608. }
  609. return PCL_RESOLUTIONS[choice];
  610. }
  611. private boolean isValidPCLResolution(int resolution) {
  612. return resolution == calculatePCLResolution(resolution);
  613. }
  614. //Threshold table to convert an alpha channel (8-bit) into a clip mask (1-bit)
  615. private static final byte[] THRESHOLD_TABLE = new byte[256];
  616. static { // Initialize the arrays
  617. for (int i = 0; i < 256; i++) {
  618. THRESHOLD_TABLE[i] = (byte) ((i < 240) ? 255 : 0);
  619. }
  620. }
  621. /* not used
  622. private RenderedImage getMask(RenderedImage img, Dimension targetDim) {
  623. ColorModel cm = img.getColorModel();
  624. if (cm.hasAlpha()) {
  625. BufferedImage alpha = new BufferedImage(img.getWidth(), img.getHeight(),
  626. BufferedImage.TYPE_BYTE_GRAY);
  627. Raster raster = img.getData();
  628. GraphicsUtil.copyBand(raster, cm.getNumColorComponents(), alpha.getRaster(), 0);
  629. BufferedImageOp op1 = new LookupOp(new ByteLookupTable(0, THRESHOLD_TABLE), null);
  630. BufferedImage alphat = op1.filter(alpha, null);
  631. BufferedImage mask;
  632. if (true) {
  633. mask = new BufferedImage(targetDim.width, targetDim.height,
  634. BufferedImage.TYPE_BYTE_BINARY);
  635. } else {
  636. byte[] arr = {(byte)0, (byte)0xff};
  637. ColorModel colorModel = new IndexColorModel(1, 2, arr, arr, arr);
  638. WritableRaster wraster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
  639. targetDim.width, targetDim.height, 1, 1, null);
  640. mask = new BufferedImage(colorModel, wraster, false, null);
  641. }
  642. Graphics2D g2d = mask.createGraphics();
  643. try {
  644. AffineTransform at = new AffineTransform();
  645. double sx = targetDim.getWidth() / img.getWidth();
  646. double sy = targetDim.getHeight() / img.getHeight();
  647. at.scale(sx, sy);
  648. g2d.drawRenderedImage(alphat, at);
  649. } finally {
  650. g2d.dispose();
  651. }
  652. return mask;
  653. } else {
  654. return null;
  655. }
  656. }
  657. */
  658. /**
  659. * Paint a bitmap at the current cursor position. The bitmap is converted to a monochrome
  660. * (1-bit) bitmap image.
  661. * @param img the bitmap image
  662. * @param targetDim the target Dimention (in mpt)
  663. * @param sourceTransparency true if the background should not be erased
  664. * @throws IOException In case of an I/O error
  665. */
  666. public void paintBitmap(RenderedImage img, Dimension targetDim, boolean sourceTransparency,
  667. PCLRenderingUtil pclUtil) throws IOException {
  668. final boolean printerSupportsColor = pclUtil.isColorEnabled();
  669. boolean monochrome = isMonochromeImage(img);
  670. double targetHResolution = img.getWidth() / UnitConv.mpt2in(targetDim.width);
  671. double targetVResolution = img.getHeight() / UnitConv.mpt2in(targetDim.height);
  672. double targetResolution = Math.max(targetHResolution, targetVResolution);
  673. int resolution = (int)Math.round(targetResolution);
  674. int effResolution = calculatePCLResolution(resolution, !(printerSupportsColor && !monochrome));
  675. Dimension orgDim = new Dimension(img.getWidth(), img.getHeight());
  676. Dimension effDim;
  677. if (targetResolution == effResolution) {
  678. effDim = orgDim; //avoid scaling side-effects
  679. } else {
  680. effDim = new Dimension(
  681. (int)Math.ceil(UnitConv.mpt2px(targetDim.width, effResolution)),
  682. (int)Math.ceil(UnitConv.mpt2px(targetDim.height, effResolution)));
  683. }
  684. boolean scaled = !orgDim.equals(effDim);
  685. if (!monochrome) {
  686. if (printerSupportsColor) {
  687. RenderedImage effImg = img;
  688. if (scaled) {
  689. effImg = BitmapImageUtil.convertTosRGB(img, effDim);
  690. }
  691. selectCurrentPattern(0, 0); //Solid black
  692. renderImageAsColor(effImg, effResolution);
  693. } else {
  694. //Transparency mask disabled. Doesn't work reliably
  695. /*
  696. final boolean transparencyDisabled = true;
  697. RenderedImage mask = (transparencyDisabled ? null : getMask(img, effDim));
  698. if (mask != null) {
  699. pushCursorPos();
  700. selectCurrentPattern(0, 1); //Solid white
  701. setTransparencyMode(true, true);
  702. paintMonochromeBitmap(mask, effResolution);
  703. popCursorPos();
  704. }
  705. */
  706. RenderedImage red = BitmapImageUtil.convertToMonochrome(
  707. img, effDim, this.ditheringQuality);
  708. selectCurrentPattern(0, 0); //Solid black
  709. setTransparencyMode(sourceTransparency /*|| mask != null*/, true);
  710. paintMonochromeBitmap(red, effResolution);
  711. }
  712. } else {
  713. RenderedImage effImg = img;
  714. if (scaled) {
  715. effImg = BitmapImageUtil.convertToMonochrome(img, effDim);
  716. }
  717. setSourceTransparencyMode(sourceTransparency);
  718. selectCurrentPattern(0, 0); //Solid black
  719. paintMonochromeBitmap(effImg, effResolution);
  720. }
  721. }
  722. private int toGray(int rgb) {
  723. // see http://www.jguru.com/faq/view.jsp?EID=221919
  724. double greyVal = 0.072169d * (rgb & 0xff);
  725. rgb >>= 8;
  726. greyVal += 0.715160d * (rgb & 0xff);
  727. rgb >>= 8;
  728. greyVal += 0.212671d * (rgb & 0xff);
  729. return (int)greyVal;
  730. }
  731. private void renderImageAsColor(RenderedImage imgOrg, int dpi) throws IOException {
  732. BufferedImage img = new BufferedImage(imgOrg.getWidth(), imgOrg.getHeight(), BufferedImage.TYPE_INT_RGB);
  733. Graphics2D g = img.createGraphics();
  734. g.setColor(Color.WHITE);
  735. g.fillRect(0, 0, imgOrg.getWidth(), imgOrg.getHeight());
  736. g.drawImage((Image) imgOrg, 0, 0, null);
  737. if (!isValidPCLResolution(dpi)) {
  738. throw new IllegalArgumentException("Invalid PCL resolution: " + dpi);
  739. }
  740. int w = img.getWidth();
  741. ColorModel cm = img.getColorModel();
  742. if (cm instanceof DirectColorModel) {
  743. writeCommand("*v6W"); // ImagingMode
  744. out.write(new byte[]{0, 3, 0, 8, 8, 8});
  745. } else {
  746. IndexColorModel icm = (IndexColorModel)cm;
  747. writeCommand("*v6W"); // ImagingMode
  748. out.write(new byte[]{0, 1, (byte)icm.getMapSize(), 8, 8, 8});
  749. byte[] reds = new byte[256];
  750. byte[] greens = new byte[256];
  751. byte[] blues = new byte[256];
  752. icm.getReds(reds);
  753. icm.getGreens(greens);
  754. icm.getBlues(blues);
  755. for (int i = 0; i < icm.getMapSize(); i++) {
  756. writeCommand("*v" + (reds[i] & 0xFF) + "A"); //ColorComponentOne
  757. writeCommand("*v" + (greens[i] & 0xFF) + "B"); //ColorComponentTwo
  758. writeCommand("*v" + (blues[i] & 0xFF) + "C"); //ColorComponentThree
  759. writeCommand("*v" + i + "I"); //AssignColorIndex
  760. }
  761. }
  762. setRasterGraphicsResolution(dpi);
  763. writeCommand("*r0f" + img.getHeight() + "t" + (w) + "S");
  764. writeCommand("*r1A");
  765. Raster raster = img.getData();
  766. ColorEncoder encoder = new ColorEncoder(img);
  767. // Transfer graphics data
  768. if (cm.getTransferType() == DataBuffer.TYPE_BYTE) {
  769. DataBufferByte dataBuffer = (DataBufferByte)raster.getDataBuffer();
  770. if (img.getSampleModel() instanceof MultiPixelPackedSampleModel && dataBuffer.getNumBanks() == 1) {
  771. byte[] buf = dataBuffer.getData();
  772. MultiPixelPackedSampleModel sampleModel = (MultiPixelPackedSampleModel)img.getSampleModel();
  773. int scanlineStride = sampleModel.getScanlineStride();
  774. int idx = 0;
  775. for (int y = 0, maxy = img.getHeight(); y < maxy; y++) {
  776. for (int x = 0; x < scanlineStride; x++) {
  777. encoder.add8Bits(buf[idx]);
  778. idx++;
  779. }
  780. encoder.endLine();
  781. }
  782. } else {
  783. throw new IOException("Unsupported image");
  784. }
  785. } else if (cm.getTransferType() == DataBuffer.TYPE_INT) {
  786. DataBufferInt dataBuffer = (DataBufferInt)raster.getDataBuffer();
  787. if (img.getSampleModel() instanceof SinglePixelPackedSampleModel && dataBuffer.getNumBanks() == 1) {
  788. int[] buf = dataBuffer.getData();
  789. SinglePixelPackedSampleModel sampleModel = (SinglePixelPackedSampleModel)img.getSampleModel();
  790. int scanlineStride = sampleModel.getScanlineStride();
  791. int idx = 0;
  792. for (int y = 0, maxy = img.getHeight(); y < maxy; y++) {
  793. for (int x = 0; x < scanlineStride; x++) {
  794. encoder.add8Bits((byte)(buf[idx] >> 16));
  795. encoder.add8Bits((byte)(buf[idx] >> 8));
  796. encoder.add8Bits((byte)(buf[idx] >> 0));
  797. idx++;
  798. }
  799. encoder.endLine();
  800. }
  801. } else {
  802. throw new IOException("Unsupported image");
  803. }
  804. } else {
  805. throw new IOException("Unsupported image");
  806. }
  807. // End raster graphics
  808. writeCommand("*rB");
  809. }
  810. /**
  811. * Paint a bitmap at the current cursor position. The bitmap must be a monochrome
  812. * (1-bit) bitmap image.
  813. * @param img the bitmap image (must be 1-bit b/w)
  814. * @param resolution the resolution of the image (must be a PCL resolution)
  815. * @throws IOException In case of an I/O error
  816. */
  817. public void paintMonochromeBitmap(RenderedImage img, int resolution) throws IOException {
  818. if (!isValidPCLResolution(resolution)) {
  819. throw new IllegalArgumentException("Invalid PCL resolution: " + resolution);
  820. }
  821. boolean monochrome = isMonochromeImage(img);
  822. if (!monochrome) {
  823. throw new IllegalArgumentException("img must be a monochrome image");
  824. }
  825. setRasterGraphicsResolution(resolution);
  826. writeCommand("*r0f" + img.getHeight() + "t" + img.getWidth() + "s1A");
  827. Raster raster = img.getData();
  828. Encoder encoder = new Encoder(img);
  829. // Transfer graphics data
  830. int imgw = img.getWidth();
  831. IndexColorModel cm = (IndexColorModel)img.getColorModel();
  832. if (cm.getTransferType() == DataBuffer.TYPE_BYTE) {
  833. DataBufferByte dataBuffer = (DataBufferByte)raster.getDataBuffer();
  834. MultiPixelPackedSampleModel packedSampleModel = new MultiPixelPackedSampleModel(
  835. DataBuffer.TYPE_BYTE, img.getWidth(), img.getHeight(), 1);
  836. if (img.getSampleModel().equals(packedSampleModel)
  837. && dataBuffer.getNumBanks() == 1) {
  838. //Optimized packed encoding
  839. byte[] buf = dataBuffer.getData();
  840. int scanlineStride = packedSampleModel.getScanlineStride();
  841. int idx = 0;
  842. int c0 = toGray(cm.getRGB(0));
  843. int c1 = toGray(cm.getRGB(1));
  844. boolean zeroIsWhite = c0 > c1;
  845. for (int y = 0, maxy = img.getHeight(); y < maxy; y++) {
  846. for (int x = 0, maxx = scanlineStride; x < maxx; x++) {
  847. if (zeroIsWhite) {
  848. encoder.add8Bits(buf[idx]);
  849. } else {
  850. encoder.add8Bits((byte)~buf[idx]);
  851. }
  852. idx++;
  853. }
  854. encoder.endLine();
  855. }
  856. } else {
  857. //Optimized non-packed encoding
  858. for (int y = 0, maxy = img.getHeight(); y < maxy; y++) {
  859. byte[] line = (byte[])raster.getDataElements(0, y, imgw, 1, null);
  860. for (int x = 0, maxx = imgw; x < maxx; x++) {
  861. encoder.addBit(line[x] == 0);
  862. }
  863. encoder.endLine();
  864. }
  865. }
  866. } else {
  867. //Safe but slow fallback
  868. for (int y = 0, maxy = img.getHeight(); y < maxy; y++) {
  869. for (int x = 0, maxx = imgw; x < maxx; x++) {
  870. int sample = raster.getSample(x, y, 0);
  871. encoder.addBit(sample == 0);
  872. }
  873. encoder.endLine();
  874. }
  875. }
  876. // End raster graphics
  877. writeCommand("*rB");
  878. }
  879. private class Encoder {
  880. private int imgw;
  881. private int bytewidth;
  882. private byte[] rle; //compressed (RLE)
  883. private byte[] uncompressed; //uncompressed
  884. private int lastcount = -1;
  885. private byte lastbyte;
  886. private int rlewidth;
  887. private byte ib; //current image bits
  888. private int x;
  889. private boolean zeroRow = true;
  890. public Encoder(RenderedImage img) {
  891. imgw = img.getWidth();
  892. bytewidth = (imgw / 8);
  893. if ((imgw % 8) != 0) {
  894. bytewidth++;
  895. }
  896. rle = new byte[bytewidth * 2];
  897. uncompressed = new byte[bytewidth];
  898. }
  899. public void addBit(boolean bit) {
  900. //Set image bit for black
  901. if (bit) {
  902. ib |= 1;
  903. }
  904. //RLE encoding
  905. if ((x % 8) == 7 || ((x + 1) == imgw)) {
  906. finishedByte();
  907. } else {
  908. ib <<= 1;
  909. }
  910. x++;
  911. }
  912. public void add8Bits(byte b) {
  913. ib = b;
  914. finishedByte();
  915. x += 8;
  916. }
  917. private void finishedByte() {
  918. if (rlewidth < bytewidth) {
  919. if (lastcount >= 0) {
  920. if (ib == lastbyte) {
  921. lastcount++;
  922. } else {
  923. rle[rlewidth++] = (byte)(lastcount & 0xFF);
  924. rle[rlewidth++] = lastbyte;
  925. lastbyte = ib;
  926. lastcount = 0;
  927. }
  928. } else {
  929. lastbyte = ib;
  930. lastcount = 0;
  931. }
  932. if (lastcount == 255 || ((x + 1) == imgw)) {
  933. rle[rlewidth++] = (byte)(lastcount & 0xFF);
  934. rle[rlewidth++] = lastbyte;
  935. lastbyte = 0;
  936. lastcount = -1;
  937. }
  938. }
  939. uncompressed[x / 8] = ib;
  940. if (ib != 0) {
  941. zeroRow = false;
  942. }
  943. ib = 0;
  944. }
  945. public void endLine() throws IOException {
  946. if (zeroRow && PCLGenerator.this.currentSourceTransparency) {
  947. writeCommand("*b1Y");
  948. } else if (rlewidth < bytewidth) {
  949. writeCommand("*b1m" + rlewidth + "W");
  950. out.write(rle, 0, rlewidth);
  951. } else {
  952. writeCommand("*b0m" + bytewidth + "W");
  953. out.write(uncompressed);
  954. }
  955. lastcount = -1;
  956. rlewidth = 0;
  957. ib = 0;
  958. x = 0;
  959. zeroRow = true;
  960. }
  961. }
  962. private class ColorEncoder {
  963. private int imgw;
  964. private int bytewidth;
  965. private byte ib; //current image bits
  966. private int currentIndex;
  967. private int len;
  968. private int shiftBit = 0x80;
  969. private int whiteLines;
  970. final byte[] zeros;
  971. final byte[] buff1;
  972. final byte[] buff2;
  973. final byte[] encodedRun;
  974. final byte[] encodedTagged;
  975. final byte[] encodedDelta;
  976. byte[] seed;
  977. byte[] current;
  978. int compression;
  979. int seedLen;
  980. public ColorEncoder(RenderedImage img) {
  981. imgw = img.getWidth();
  982. bytewidth = imgw * 3 + 1;
  983. zeros = new byte[bytewidth];
  984. buff1 = new byte[bytewidth];
  985. buff2 = new byte[bytewidth];
  986. encodedRun = new byte[bytewidth];
  987. encodedTagged = new byte[bytewidth];
  988. encodedDelta = new byte[bytewidth];
  989. seed = buff1;
  990. current = buff2;
  991. seedLen = 0;
  992. compression = (-1);
  993. System.arraycopy(zeros, 0, seed, 0, zeros.length);
  994. }
  995. private int runCompression(byte[] buff, int len) {
  996. int bytes = 0;
  997. try {
  998. for (int i = 0; i < len;) {
  999. int sameCount;
  1000. byte seed = current[i++];
  1001. for (sameCount = 1; i < len && current[i] == seed; i++) {
  1002. sameCount++;
  1003. }
  1004. for (; sameCount > 256; sameCount -= 256) {
  1005. buff[bytes++] = (byte)255;
  1006. buff[bytes++] = seed;
  1007. }
  1008. if (sameCount > 0) {
  1009. buff[bytes++] = (byte)(sameCount - 1);
  1010. buff[bytes++] = seed;
  1011. }
  1012. }
  1013. } catch (ArrayIndexOutOfBoundsException e) {
  1014. return len + 1;
  1015. }
  1016. return bytes;
  1017. }
  1018. private int deltaCompression(byte[] seed, byte[] buff, int len) {
  1019. int bytes = 0;
  1020. try {
  1021. for (int i = 0; i < len;) {
  1022. int sameCount;
  1023. int diffCount;
  1024. for (sameCount = 0; i < len && current[i] == seed[i]; i++) {
  1025. sameCount++;
  1026. }
  1027. for (diffCount = 0; i < len && current[i] != seed[i]; i++) {
  1028. diffCount++;
  1029. }
  1030. for (; diffCount != 0;) {
  1031. int diffToWrite = (diffCount > 8) ? 8 : diffCount;
  1032. int sameToWrite = (sameCount > 31) ? 31 : sameCount;
  1033. buff[bytes++] = (byte)(((diffToWrite - 1) << 5) | sameToWrite);
  1034. sameCount -= sameToWrite;
  1035. if (sameToWrite == 31) {
  1036. for (; sameCount >= 255; sameCount -= 255) {
  1037. buff[bytes++] = (byte)255;
  1038. }
  1039. buff[bytes++] = (byte)sameCount;
  1040. sameCount = 0;
  1041. }
  1042. System.arraycopy(current, i - diffCount, buff, bytes, diffToWrite);
  1043. bytes += diffToWrite;
  1044. diffCount -= diffToWrite;
  1045. }
  1046. }
  1047. } catch (ArrayIndexOutOfBoundsException e) {
  1048. return len + 1;
  1049. }
  1050. return bytes;
  1051. }
  1052. private int tiffCompression(byte[] encodedTagged, int len) {
  1053. int literalCount = 0;
  1054. int bytes = 0;
  1055. try {
  1056. for (int from = 0; from < len;) {
  1057. int repeatLength;
  1058. int repeatValue = current[from];
  1059. for (repeatLength = 1; repeatLength < 128
  1060. && from + repeatLength < len
  1061. && current[from + repeatLength] == repeatValue;) {
  1062. repeatLength++;
  1063. }
  1064. if (literalCount == 128 || (repeatLength > 2 && literalCount > 0)) {
  1065. encodedTagged[bytes++] = (byte)(literalCount - 1);
  1066. System.arraycopy(current, from - literalCount, encodedTagged, bytes, literalCount);
  1067. bytes += literalCount;
  1068. literalCount = 0;
  1069. }
  1070. if (repeatLength > 2) {
  1071. encodedTagged[bytes++] = (byte)(1 - repeatLength);
  1072. encodedTagged[bytes++] = current[from];
  1073. from += repeatLength;
  1074. } else {
  1075. literalCount++;
  1076. from++;
  1077. }
  1078. }
  1079. if (literalCount > 0) {
  1080. encodedTagged[bytes++] = (byte)(literalCount - 1);
  1081. System.arraycopy(current, (3 * len) - literalCount, encodedTagged, bytes, literalCount);
  1082. bytes += literalCount;
  1083. }
  1084. } catch (ArrayIndexOutOfBoundsException e) {
  1085. return len + 1;
  1086. }
  1087. return bytes;
  1088. }
  1089. public void addBit(boolean bit) {
  1090. //Set image bit for black
  1091. if (bit) {
  1092. ib |= shiftBit;
  1093. }
  1094. shiftBit >>= 1;
  1095. if (shiftBit == 0) {
  1096. add8Bits(ib);
  1097. shiftBit = 0x80;
  1098. ib = 0;
  1099. }
  1100. }
  1101. public void add8Bits(byte b) {
  1102. current[currentIndex++] = b;
  1103. if (b != 0) {
  1104. len = currentIndex;
  1105. }
  1106. }
  1107. public void endLine() throws IOException {
  1108. if (len == 0) {
  1109. whiteLines++;
  1110. } else {
  1111. if (whiteLines > 0) {
  1112. writeCommand("*b" + whiteLines + "Y");
  1113. whiteLines = 0;
  1114. }
  1115. int unencodedCount = len;
  1116. int runCount = runCompression(encodedRun, len);
  1117. int tiffCount = tiffCompression(encodedTagged, len);
  1118. int deltaCount = deltaCompression(seed, encodedDelta, Math.max(len, seedLen));
  1119. int bestCount = Math.min(unencodedCount, Math.min(runCount, Math.min(tiffCount, deltaCount)));
  1120. int bestCompression;
  1121. if (bestCount == unencodedCount) {
  1122. bestCompression = 0;
  1123. } else if (bestCount == runCount) {
  1124. bestCompression = 1;
  1125. } else if (bestCount == tiffCount) {
  1126. bestCompression = 2;
  1127. } else {
  1128. bestCompression = 3;
  1129. }
  1130. if (compression != bestCompression) {
  1131. compression = bestCompression;
  1132. writeCommand("*b" + compression + "M");
  1133. }
  1134. if (bestCompression == 0) {
  1135. writeCommand("*b" + unencodedCount + "W");
  1136. out.write(current, 0, unencodedCount);
  1137. } else if (bestCompression == 1) {
  1138. writeCommand("*b" + runCount + "W");
  1139. out.write(encodedRun, 0, runCount);
  1140. } else if (bestCompression == 2) {
  1141. writeCommand("*b" + tiffCount + "W");
  1142. out.write(encodedTagged, 0, tiffCount);
  1143. } else if (bestCompression == 3) {
  1144. writeCommand("*b" + deltaCount + "W");
  1145. out.write(encodedDelta, 0, deltaCount);
  1146. }
  1147. if (current == buff1) {
  1148. seed = buff1;
  1149. current = buff2;
  1150. } else {
  1151. seed = buff2;
  1152. current = buff1;
  1153. }
  1154. seedLen = len;
  1155. }
  1156. shiftBit = 0x80;
  1157. ib = 0;
  1158. len = 0;
  1159. currentIndex = 0;
  1160. }
  1161. }
  1162. }