You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractBreaker.java 36KB

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
hace 16 años
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
hace 16 años
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  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.layoutmgr;
  19. import java.util.Collections;
  20. import java.util.Iterator;
  21. import java.util.LinkedList;
  22. import java.util.List;
  23. import java.util.ListIterator;
  24. import org.apache.commons.logging.Log;
  25. import org.apache.commons.logging.LogFactory;
  26. import org.apache.fop.events.EventBroadcaster;
  27. import org.apache.fop.fo.Constants;
  28. import org.apache.fop.layoutmgr.BreakingAlgorithm.KnuthNode;
  29. import org.apache.fop.traits.MinOptMax;
  30. import org.apache.fop.util.ListUtil;
  31. /**
  32. * Abstract base class for breakers (page breakers, static region handlers etc.).
  33. */
  34. public abstract class AbstractBreaker {
  35. /** logging instance */
  36. protected static final Log log = LogFactory.getLog(AbstractBreaker.class);
  37. private LayoutManager originalRestartAtLM;
  38. private Position positionAtBreak;
  39. private List firstElementsForRestart;
  40. protected PageSequenceLayoutManager pslm;
  41. /**
  42. * A page break position.
  43. */
  44. public static class PageBreakPosition extends LeafPosition {
  45. // Percentage to adjust (stretch or shrink)
  46. double bpdAdjust;
  47. int difference;
  48. int footnoteFirstListIndex;
  49. int footnoteFirstElementIndex;
  50. int footnoteLastListIndex;
  51. int footnoteLastElementIndex;
  52. PageBreakPosition(LayoutManager lm, int breakIndex,
  53. int ffli, int ffei, int flli, int flei,
  54. double bpdA, int diff) {
  55. super(lm, breakIndex);
  56. bpdAdjust = bpdA;
  57. difference = diff;
  58. footnoteFirstListIndex = ffli;
  59. footnoteFirstElementIndex = ffei;
  60. footnoteLastListIndex = flli;
  61. footnoteLastElementIndex = flei;
  62. }
  63. }
  64. public static class FloatPosition extends LeafPosition {
  65. double bpdAdjust; // Percentage to adjust (stretch or shrink)
  66. int difference;
  67. FloatPosition(LayoutManager lm, int breakIndex, double bpdA, int diff) {
  68. super(lm, breakIndex);
  69. bpdAdjust = bpdA;
  70. difference = diff;
  71. }
  72. }
  73. /**
  74. * Helper method, mainly used to improve debug/trace output
  75. * @param breakClassId the {@link Constants} enum value.
  76. * @return the break class name
  77. */
  78. static String getBreakClassName(int breakClassId) {
  79. switch (breakClassId) {
  80. case Constants.EN_ALL: return "ALL";
  81. case Constants.EN_ANY: return "ANY";
  82. case Constants.EN_AUTO: return "AUTO";
  83. case Constants.EN_COLUMN: return "COLUMN";
  84. case Constants.EN_EVEN_PAGE: return "EVEN PAGE";
  85. case Constants.EN_LINE: return "LINE";
  86. case Constants.EN_NONE: return "NONE";
  87. case Constants.EN_ODD_PAGE: return "ODD PAGE";
  88. case Constants.EN_PAGE: return "PAGE";
  89. default: return "??? (" + String.valueOf(breakClassId) + ")";
  90. }
  91. }
  92. /**
  93. * Helper class, extending the functionality of the
  94. * basic {@link BlockKnuthSequence}.
  95. */
  96. public static class BlockSequence extends BlockKnuthSequence {
  97. private static final long serialVersionUID = -5348831120146774118L;
  98. /** Number of elements to ignore at the beginning of the list. */
  99. int ignoreAtStart;
  100. /** Number of elements to ignore at the end of the list. */
  101. int ignoreAtEnd;
  102. /**
  103. * startOn represents where on the page/which page layout
  104. * should start for this BlockSequence. Acceptable values:
  105. * Constants.EN_ANY (can continue from finished location
  106. * of previous BlockSequence?), EN_COLUMN, EN_ODD_PAGE,
  107. * EN_EVEN_PAGE.
  108. */
  109. private final int startOn;
  110. private final int displayAlign;
  111. /**
  112. * Creates a new BlockSequence.
  113. * @param startOn the kind of page the sequence should start on.
  114. * One of {@link Constants#EN_ANY}, {@link Constants#EN_COLUMN},
  115. * {@link Constants#EN_ODD_PAGE}, or {@link Constants#EN_EVEN_PAGE}.
  116. * @param displayAlign the value for the display-align property
  117. */
  118. public BlockSequence(int startOn, int displayAlign) {
  119. super();
  120. this.startOn = startOn;
  121. this.displayAlign = displayAlign;
  122. }
  123. /**
  124. * @return the kind of page the sequence should start on.
  125. * One of {@link Constants#EN_ANY}, {@link Constants#EN_COLUMN},
  126. * {@link Constants#EN_ODD_PAGE}, or {@link Constants#EN_EVEN_PAGE}.
  127. */
  128. public int getStartOn() {
  129. return this.startOn;
  130. }
  131. /** @return the value for the display-align property */
  132. public int getDisplayAlign() {
  133. return this.displayAlign;
  134. }
  135. /**
  136. * Finalizes a Knuth sequence.
  137. * @return a finalized sequence.
  138. */
  139. @Override
  140. public KnuthSequence endSequence() {
  141. return endSequence(null);
  142. }
  143. /**
  144. * Finalizes a Knuth sequence.
  145. * @param breakPosition a Position instance for the last penalty (may be null)
  146. * @return a finalized sequence.
  147. */
  148. public KnuthSequence endSequence(Position breakPosition) {
  149. // remove glue and penalty item at the end of the paragraph
  150. while (this.size() > ignoreAtStart
  151. && !((KnuthElement) ListUtil.getLast(this)).isBox()) {
  152. ListUtil.removeLast(this);
  153. }
  154. if (this.size() > ignoreAtStart) {
  155. // add the elements representing the space at the end of the last line
  156. // and the forced break
  157. this.add(new KnuthPenalty(0, KnuthElement.INFINITE,
  158. false, null, false));
  159. this.add(new KnuthGlue(0, 10000000, 0, null, false));
  160. this.add(new KnuthPenalty(0, -KnuthElement.INFINITE,
  161. false, breakPosition, false));
  162. ignoreAtEnd = 3;
  163. return this;
  164. } else {
  165. this.clear();
  166. return null;
  167. }
  168. }
  169. /**
  170. * Finalizes a this {@link BlockSequence}, adding a terminating
  171. * penalty-glue-penalty sequence
  172. * @param breakPosition a Position instance pointing to the last penalty
  173. * @return the finalized {@link BlockSequence}
  174. */
  175. public BlockSequence endBlockSequence(Position breakPosition) {
  176. KnuthSequence temp = endSequence(breakPosition);
  177. if (temp != null) {
  178. BlockSequence returnSequence = new BlockSequence(startOn, displayAlign);
  179. returnSequence.addAll(temp);
  180. returnSequence.ignoreAtEnd = this.ignoreAtEnd;
  181. return returnSequence;
  182. } else {
  183. return null;
  184. }
  185. }
  186. }
  187. // used by doLayout and getNextBlockList*
  188. protected List<BlockSequence> blockLists;
  189. private boolean empty = true;
  190. /** blockListIndex of the current BlockSequence in blockLists */
  191. protected int blockListIndex;
  192. /** desired text alignment */
  193. protected int alignment;
  194. private int alignmentLast;
  195. /** footnote separator length */
  196. protected MinOptMax footnoteSeparatorLength = MinOptMax.ZERO;
  197. /** @return current display alignment */
  198. protected abstract int getCurrentDisplayAlign();
  199. /** @return true if content not exhausted */
  200. protected abstract boolean hasMoreContent();
  201. /**
  202. * Tell the layout manager to add all the child areas implied
  203. * by Position objects which will be returned by the
  204. * Iterator.
  205. *
  206. * @param posIter the position iterator
  207. * @param context the context
  208. */
  209. protected abstract void addAreas(PositionIterator posIter, LayoutContext context);
  210. /** @return top level layout manager */
  211. protected abstract LayoutManager getTopLevelLM();
  212. /** @return current child layout manager */
  213. protected abstract LayoutManager getCurrentChildLM();
  214. /**
  215. * Controls the behaviour of the algorithm in cases where the first element of a part
  216. * overflows a line/page.
  217. * @return true if the algorithm should try to send the element to the next line/page.
  218. */
  219. protected boolean isPartOverflowRecoveryActivated() {
  220. return true;
  221. }
  222. /**
  223. * @return true if one a single part should be produced if possible (ex. for block-containers)
  224. */
  225. protected boolean isSinglePartFavored() {
  226. return false;
  227. }
  228. /**
  229. * Returns the PageProvider if any. PageBreaker overrides this method because each
  230. * page may have a different available BPD which needs to be accessible to the breaking
  231. * algorithm.
  232. * @return the applicable PageProvider, or null if not applicable
  233. */
  234. protected PageProvider getPageProvider() {
  235. return null;
  236. }
  237. /**
  238. * Creates and returns a PageBreakingLayoutListener for the PageBreakingAlgorithm to
  239. * notify about layout problems.
  240. * @return the listener instance or null if no notifications are needed
  241. */
  242. protected PageBreakingAlgorithm.PageBreakingLayoutListener createLayoutListener() {
  243. return null;
  244. }
  245. /**
  246. * Get a sequence of KnuthElements representing the content
  247. * of the node assigned to the LM
  248. *
  249. * @param context the LayoutContext used to store layout information
  250. * @param alignment the desired text alignment
  251. * @return the list of KnuthElements
  252. */
  253. protected abstract List<KnuthElement> getNextKnuthElements(LayoutContext context,
  254. int alignment);
  255. /**
  256. * Get a sequence of KnuthElements representing the content
  257. * of the node assigned to the LM
  258. *
  259. * @param context the LayoutContext used to store layout information
  260. * @param alignment the desired text alignment
  261. * @param positionAtIPDChange last element on the part before an IPD change
  262. * @param restartAtLM the layout manager from which to restart, if IPD
  263. * change occurs between two LMs
  264. * @return the list of KnuthElements
  265. */
  266. protected List<KnuthElement> getNextKnuthElements(LayoutContext context, int alignment,
  267. Position positionAtIPDChange, LayoutManager restartAtLM) {
  268. throw new UnsupportedOperationException("TODO: implement acceptable fallback");
  269. }
  270. /** @return true if there's no content that could be handled. */
  271. public boolean isEmpty() {
  272. return empty;
  273. }
  274. /**
  275. * Start part.
  276. * @param list a block sequence
  277. * @param breakClass a break class
  278. */
  279. protected void startPart(BlockSequence list, int breakClass, boolean emptyContent) {
  280. //nop
  281. }
  282. /**
  283. * This method is called when no content is available for a part. Used to force empty pages.
  284. */
  285. protected void handleEmptyContent() {
  286. //nop
  287. }
  288. /**
  289. * Finish part.
  290. * @param alg a page breaking algorithm
  291. * @param pbp a page break posittion
  292. */
  293. protected abstract void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp);
  294. /**
  295. * Creates the top-level LayoutContext for the breaker operation.
  296. * @return the top-level LayoutContext
  297. */
  298. protected LayoutContext createLayoutContext() {
  299. return LayoutContext.newInstance();
  300. }
  301. /**
  302. * Used to update the LayoutContext in subclasses prior to starting a new element list.
  303. * @param context the LayoutContext to update
  304. */
  305. protected void updateLayoutContext(LayoutContext context) {
  306. //nop
  307. }
  308. /**
  309. * Used for debugging purposes. Notifies all registered observers about the element list.
  310. * Override to set different parameters.
  311. * @param elementList the Knuth element list
  312. */
  313. protected void observeElementList(List elementList) {
  314. ElementListObserver.observe(elementList, "breaker", null);
  315. }
  316. /**
  317. * Starts the page breaking process.
  318. * @param flowBPD the constant available block-progression-dimension (used for every part)
  319. * @param autoHeight true if warnings about overflows should be disabled because the
  320. * the BPD is really undefined (for footnote-separators, for example)
  321. */
  322. public boolean doLayout(int flowBPD, boolean autoHeight) {
  323. LayoutContext childLC = createLayoutContext();
  324. childLC.setStackLimitBP(MinOptMax.getInstance(flowBPD));
  325. alignment = Constants.EN_START;
  326. alignmentLast = Constants.EN_START;
  327. childLC.setBPAlignment(alignment);
  328. BlockSequence blockList;
  329. blockLists = new java.util.ArrayList<BlockSequence>();
  330. log.debug("PLM> flow BPD =" + flowBPD);
  331. int nextSequenceStartsOn = Constants.EN_ANY;
  332. while (hasMoreContent()) {
  333. blockLists.clear();
  334. //*** Phase 1: Get Knuth elements ***
  335. nextSequenceStartsOn = getNextBlockList(childLC, nextSequenceStartsOn);
  336. empty = empty && blockLists.size() == 0;
  337. //*** Phases 2 and 3 ***
  338. log.debug("PLM> blockLists.size() = " + blockLists.size());
  339. for (blockListIndex = 0; blockListIndex < blockLists.size(); blockListIndex++) {
  340. blockList = blockLists.get(blockListIndex);
  341. //debug code start
  342. if (log.isDebugEnabled()) {
  343. log.debug(" blockListIndex = " + blockListIndex);
  344. log.debug(" sequence starts on " + getBreakClassName(blockList.startOn));
  345. }
  346. observeElementList(blockList);
  347. //debug code end
  348. //*** Phase 2: Alignment and breaking ***
  349. log.debug("PLM> start of algorithm (" + this.getClass().getName()
  350. + "), flow BPD =" + flowBPD);
  351. PageBreakingAlgorithm alg = new PageBreakingAlgorithm(getTopLevelLM(),
  352. getPageProvider(), createLayoutListener(),
  353. alignment, alignmentLast, footnoteSeparatorLength,
  354. isPartOverflowRecoveryActivated(), autoHeight, isSinglePartFavored());
  355. alg.setConstantLineWidth(flowBPD);
  356. int optimalPageCount = alg.findBreakingPoints(blockList, 1, true,
  357. BreakingAlgorithm.ALL_BREAKS);
  358. boolean ipdChangesOnNextPage = (alg.getIPDdifference() != 0);
  359. boolean onLastPageAndIPDChanges = false;
  360. if (!ipdChangesOnNextPage) {
  361. onLastPageAndIPDChanges = (lastPageHasIPDChange() && !thereIsANonRestartableLM(alg)
  362. && (shouldRedoLayout() || (wasLayoutRedone() && optimalPageCount > 1)));
  363. }
  364. if ((ipdChangesOnNextPage || hasMoreContent() || optimalPageCount > 1)
  365. && pslm != null && pslm.getCurrentPage().isPagePositionOnly) {
  366. return false;
  367. }
  368. if (alg.handlingFloat()) {
  369. nextSequenceStartsOn = handleFloatLayout(alg, optimalPageCount, blockList, childLC);
  370. } else if (ipdChangesOnNextPage || onLastPageAndIPDChanges) {
  371. boolean visitedBefore = false;
  372. if (onLastPageAndIPDChanges) {
  373. visitedBefore = wasLayoutRedone();
  374. prepareToRedoLayout(alg, optimalPageCount, blockList, blockList);
  375. }
  376. firstElementsForRestart = null;
  377. LayoutManager restartAtLM = getRestartAtLM(alg, ipdChangesOnNextPage, onLastPageAndIPDChanges,
  378. visitedBefore, blockList, 1);
  379. if (restartAtLM == null || restartAtLM.getChildLMs().isEmpty()) {
  380. firstElementsForRestart = null;
  381. LayoutManager restartAtLM2 = getRestartAtLM(alg, ipdChangesOnNextPage, onLastPageAndIPDChanges,
  382. visitedBefore, blockList, 0);
  383. if (restartAtLM2 != null) {
  384. restartAtLM = restartAtLM2;
  385. }
  386. }
  387. if (ipdChangesOnNextPage) {
  388. addAreas(alg, optimalPageCount, blockList, blockList);
  389. }
  390. blockLists.clear();
  391. blockListIndex = -1;
  392. nextSequenceStartsOn = getNextBlockList(childLC, Constants.EN_COLUMN, positionAtBreak,
  393. restartAtLM, firstElementsForRestart);
  394. } else {
  395. log.debug("PLM> optimalPageCount= " + optimalPageCount
  396. + " pageBreaks.size()= " + alg.getPageBreaks().size());
  397. //*** Phase 3: Add areas ***
  398. doPhase3(alg, optimalPageCount, blockList, blockList);
  399. }
  400. }
  401. }
  402. // done
  403. blockLists = null;
  404. return true;
  405. }
  406. private LayoutManager getRestartAtLM(PageBreakingAlgorithm alg, boolean ipdChangesOnNextPage,
  407. boolean onLastPageAndIPDChanges, boolean visitedBefore,
  408. BlockSequence blockList, int start) {
  409. KnuthNode optimalBreak = ipdChangesOnNextPage ? alg.getBestNodeBeforeIPDChange() : alg
  410. .getBestNodeForLastPage();
  411. if (onLastPageAndIPDChanges && visitedBefore && this.originalRestartAtLM == null) {
  412. optimalBreak = null;
  413. }
  414. int positionIndex = findPositionIndex(optimalBreak, alg, start);
  415. if (ipdChangesOnNextPage || (positionAtBreak != null && positionAtBreak.getIndex() > -1)) {
  416. firstElementsForRestart = Collections.EMPTY_LIST;
  417. if (ipdChangesOnNextPage) {
  418. if (containsNonRestartableLM(positionAtBreak)) {
  419. if (alg.getIPDdifference() > 0) {
  420. EventBroadcaster eventBroadcaster = getCurrentChildLM().getFObj()
  421. .getUserAgent().getEventBroadcaster();
  422. BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider
  423. .get(eventBroadcaster);
  424. eventProducer.nonRestartableContentFlowingToNarrowerPage(this);
  425. }
  426. firstElementsForRestart = new LinkedList();
  427. boolean boxFound = false;
  428. Iterator iter = blockList.listIterator(positionIndex + 1);
  429. Position position = null;
  430. while (iter.hasNext()
  431. && (position == null || containsNonRestartableLM(position))) {
  432. positionIndex++;
  433. KnuthElement element = (KnuthElement) iter.next();
  434. position = element.getPosition();
  435. if (element.isBox()) {
  436. boxFound = true;
  437. firstElementsForRestart.add(element);
  438. } else if (boxFound) {
  439. firstElementsForRestart.add(element);
  440. }
  441. }
  442. if (position instanceof SpaceResolver.SpaceHandlingBreakPosition) {
  443. /* Retrieve the original position wrapped into this space position */
  444. positionAtBreak = position.getPosition();
  445. } else {
  446. positionAtBreak = null;
  447. }
  448. }
  449. }
  450. }
  451. LayoutManager restartAtLM = null;
  452. if (ipdChangesOnNextPage || !(positionAtBreak != null && positionAtBreak.getIndex() > -1)) {
  453. if (positionAtBreak != null && positionAtBreak.getIndex() == -1) {
  454. Position position;
  455. Iterator iter = blockList.listIterator(positionIndex + 1);
  456. do {
  457. KnuthElement nextElement = (KnuthElement) iter.next();
  458. position = nextElement.getPosition();
  459. } while (position == null
  460. || position instanceof SpaceResolver.SpaceHandlingPosition
  461. || position instanceof SpaceResolver.SpaceHandlingBreakPosition
  462. && position.getPosition().getIndex() == -1);
  463. LayoutManager surroundingLM = positionAtBreak.getLM();
  464. while (position.getLM() != surroundingLM) {
  465. position = position.getPosition();
  466. }
  467. restartAtLM = position.getPosition().getLM();
  468. }
  469. if (onLastPageAndIPDChanges && restartAtLM != null) {
  470. if (originalRestartAtLM == null) {
  471. originalRestartAtLM = restartAtLM;
  472. } else {
  473. restartAtLM = originalRestartAtLM;
  474. }
  475. firstElementsForRestart = Collections.EMPTY_LIST;
  476. }
  477. }
  478. if (onLastPageAndIPDChanges && !visitedBefore && positionAtBreak.getPosition() != null) {
  479. restartAtLM = positionAtBreak.getPosition().getLM();
  480. }
  481. return restartAtLM;
  482. }
  483. private int findPositionIndex(KnuthNode optimalBreak, PageBreakingAlgorithm alg, int start) {
  484. int positionIndex = (optimalBreak != null) ? optimalBreak.position : start;
  485. for (int i = positionIndex; i < alg.par.size(); i++) {
  486. KnuthElement elementAtBreak = alg.getElement(i);
  487. if (elementAtBreak.getPosition() == null) {
  488. elementAtBreak = alg.getElement(0);
  489. }
  490. positionAtBreak = elementAtBreak.getPosition();
  491. /* Retrieve the original position wrapped into this space position */
  492. positionAtBreak = positionAtBreak.getPosition();
  493. if (positionAtBreak != null) {
  494. return i;
  495. }
  496. }
  497. return positionIndex;
  498. }
  499. /**
  500. * Returns {@code true} if the given position or one of its descendants
  501. * corresponds to a non-restartable LM.
  502. *
  503. * @param position a position
  504. * @return {@code true} if there is a non-restartable LM in the hierarchy
  505. */
  506. private boolean containsNonRestartableLM(Position position) {
  507. LayoutManager lm = position.getLM();
  508. if (lm != null && !lm.isRestartable()) {
  509. return true;
  510. } else {
  511. Position subPosition = position.getPosition();
  512. return subPosition != null && containsNonRestartableLM(subPosition);
  513. }
  514. }
  515. /**
  516. * Phase 3 of Knuth algorithm: Adds the areas
  517. * @param alg PageBreakingAlgorithm instance which determined the breaks
  518. * @param partCount number of parts (pages) to be rendered
  519. * @param originalList original Knuth element list
  520. * @param effectiveList effective Knuth element list (after adjustments)
  521. */
  522. protected abstract void doPhase3(PageBreakingAlgorithm alg, int partCount,
  523. BlockSequence originalList, BlockSequence effectiveList);
  524. /**
  525. * Phase 3 of Knuth algorithm: Adds the areas
  526. * @param alg PageBreakingAlgorithm instance which determined the breaks
  527. * @param partCount number of parts (pages) to be rendered
  528. * @param originalList original Knuth element list
  529. * @param effectiveList effective Knuth element list (after adjustments)
  530. */
  531. protected void addAreas(PageBreakingAlgorithm alg, int partCount,
  532. BlockSequence originalList, BlockSequence effectiveList) {
  533. addAreas(alg, 0, partCount, originalList, effectiveList);
  534. }
  535. protected void addAreas(PageBreakingAlgorithm alg, int startPart, int partCount,
  536. BlockSequence originalList, BlockSequence effectiveList) {
  537. addAreas(alg, startPart, partCount, originalList, effectiveList, LayoutContext.newInstance());
  538. }
  539. /**
  540. * Phase 3 of Knuth algorithm: Adds the areas
  541. * @param alg PageBreakingAlgorithm instance which determined the breaks
  542. * @param startPart index of the first part (page) to be rendered
  543. * @param partCount number of parts (pages) to be rendered
  544. * @param originalList original Knuth element list
  545. * @param effectiveList effective Knuth element list (after adjustments)
  546. */
  547. protected void addAreas(PageBreakingAlgorithm alg, int startPart, int partCount,
  548. BlockSequence originalList, BlockSequence effectiveList, final LayoutContext childLC) {
  549. int startElementIndex = 0;
  550. int endElementIndex = 0;
  551. int lastBreak = -1;
  552. for (int p = startPart; p < startPart + partCount; p++) {
  553. PageBreakPosition pbp = alg.getPageBreaks().get(p);
  554. // Check the last break position for forced breaks
  555. int lastBreakClass;
  556. if (p == 0) {
  557. lastBreakClass = effectiveList.getStartOn();
  558. } else {
  559. ListElement lastBreakElement = effectiveList.getElement(endElementIndex);
  560. if (lastBreakElement.isPenalty()) {
  561. KnuthPenalty pen = (KnuthPenalty) lastBreakElement;
  562. if (pen.getPenalty() == KnuthPenalty.INFINITE) {
  563. /**
  564. * That means that there was a keep.within-page="always", but that
  565. * it's OK to break at a column. TODO The break class is being
  566. * abused to implement keep.within-column and keep.within-page.
  567. * This is very misleading and must be revised.
  568. */
  569. lastBreakClass = Constants.EN_COLUMN;
  570. } else {
  571. lastBreakClass = pen.getBreakClass();
  572. }
  573. } else {
  574. lastBreakClass = Constants.EN_COLUMN;
  575. }
  576. }
  577. // the end of the new part
  578. endElementIndex = pbp.getLeafPos();
  579. // ignore the first elements added by the
  580. // PageSequenceLayoutManager
  581. startElementIndex += (startElementIndex == 0) ? effectiveList.ignoreAtStart : 0;
  582. log.debug("PLM> part: " + (p + 1)
  583. + ", start at pos " + startElementIndex
  584. + ", break at pos " + endElementIndex
  585. + ", break class = " + getBreakClassName(lastBreakClass));
  586. startPart(effectiveList, lastBreakClass, startElementIndex > endElementIndex);
  587. int displayAlign = getCurrentDisplayAlign();
  588. // The following is needed by SpaceResolver.performConditionalsNotification()
  589. // further down as there may be important Position elements in the element list trailer
  590. int notificationEndElementIndex = endElementIndex;
  591. // ignore the last elements added by the
  592. // PageSequenceLayoutManager
  593. endElementIndex -= (endElementIndex == (originalList.size() - 1)) ? effectiveList.ignoreAtEnd : 0;
  594. // ignore the last element in the page if it is a KnuthGlue
  595. // object
  596. if (((KnuthElement) effectiveList.get(endElementIndex)).isGlue()) {
  597. endElementIndex--;
  598. }
  599. // ignore KnuthGlue and KnuthPenalty objects
  600. // at the beginning of the line
  601. startElementIndex = alg.par.getFirstBoxIndex(startElementIndex);
  602. if (startElementIndex <= endElementIndex) {
  603. if (log.isDebugEnabled()) {
  604. log.debug(" addAreas from " + startElementIndex
  605. + " to " + endElementIndex);
  606. }
  607. // set the space adjustment ratio
  608. childLC.setSpaceAdjust(pbp.bpdAdjust);
  609. // add space before if display-align is center or bottom
  610. // add space after if display-align is distribute and
  611. // this is not the last page
  612. if (pbp.difference != 0 && displayAlign == Constants.EN_CENTER) {
  613. childLC.setSpaceBefore(pbp.difference / 2);
  614. } else if (pbp.difference != 0 && displayAlign == Constants.EN_AFTER) {
  615. childLC.setSpaceBefore(pbp.difference);
  616. }
  617. // Handle SpaceHandling(Break)Positions, see SpaceResolver!
  618. SpaceResolver.performConditionalsNotification(effectiveList, startElementIndex,
  619. notificationEndElementIndex, lastBreak);
  620. // Add areas now!
  621. addAreas(new KnuthPossPosIter(effectiveList, startElementIndex, endElementIndex + 1), childLC);
  622. } else {
  623. // no content for this part
  624. handleEmptyContent();
  625. }
  626. finishPart(alg, pbp);
  627. lastBreak = endElementIndex;
  628. startElementIndex = pbp.getLeafPos() + 1;
  629. }
  630. if (alg.handlingFloat()) {
  631. addAreasForFloats(alg, startPart, partCount, originalList, effectiveList, childLC, lastBreak,
  632. startElementIndex, endElementIndex);
  633. }
  634. }
  635. /**
  636. * Notifies the layout managers about the space and conditional length situation based on
  637. * the break decisions.
  638. * @param effectiveList Element list to be painted
  639. * @param startElementIndex start index of the part
  640. * @param endElementIndex end index of the part
  641. * @param lastBreak index of the last break element
  642. */
  643. /**
  644. * Handles span changes reported through the <code>LayoutContext</code>.
  645. * Only used by the PSLM and called by <code>getNextBlockList()</code>.
  646. * @param childLC the LayoutContext
  647. * @param nextSequenceStartsOn previous value for break handling
  648. * @return effective value for break handling
  649. */
  650. protected int handleSpanChange(LayoutContext childLC, int nextSequenceStartsOn) {
  651. return nextSequenceStartsOn;
  652. }
  653. /**
  654. * Gets the next block list (sequence) and adds it to a list of block lists if it's not empty.
  655. * @param childLC LayoutContext to use
  656. * @param nextSequenceStartsOn indicates on what page the next sequence should start
  657. * @return the page on which the next content should appear after a hard break
  658. */
  659. protected int getNextBlockList(LayoutContext childLC, int nextSequenceStartsOn) {
  660. return getNextBlockList(childLC, nextSequenceStartsOn, null, null, null);
  661. }
  662. /**
  663. * Gets the next block list (sequence) and adds it to a list of block lists
  664. * if it's not empty.
  665. *
  666. * @param childLC LayoutContext to use
  667. * @param nextSequenceStartsOn indicates on what page the next sequence
  668. * should start
  669. * @param positionAtIPDChange last element on the part before an IPD change
  670. * @param restartAtLM the layout manager from which to restart, if IPD
  671. * change occurs between two LMs
  672. * @param firstElements elements from non-restartable LMs on the new page
  673. * @return the page on which the next content should appear after a hard
  674. * break
  675. */
  676. protected int getNextBlockList(LayoutContext childLC, int nextSequenceStartsOn,
  677. Position positionAtIPDChange, LayoutManager restartAtLM,
  678. List<KnuthElement> firstElements) {
  679. updateLayoutContext(childLC);
  680. //Make sure the span change signal is reset
  681. childLC.signalSpanChange(Constants.NOT_SET);
  682. BlockSequence blockList;
  683. List<KnuthElement> returnedList;
  684. if (firstElements == null) {
  685. returnedList = getNextKnuthElements(childLC, alignment);
  686. } else if (positionAtIPDChange == null) {
  687. /*
  688. * No restartable element found after changing IPD break. Simply add the
  689. * non-restartable elements found after the break.
  690. */
  691. returnedList = firstElements;
  692. /*
  693. * Remove the last 3 penalty-filler-forced break elements that were added by
  694. * the Knuth algorithm. They will be re-added later on.
  695. */
  696. if (returnedList.size() > 2) {
  697. ListIterator iter = returnedList.listIterator(returnedList.size());
  698. for (int i = 0; i < 3; i++) {
  699. iter.previous();
  700. iter.remove();
  701. }
  702. }
  703. } else {
  704. returnedList = getNextKnuthElements(childLC, alignment, positionAtIPDChange,
  705. restartAtLM);
  706. returnedList.addAll(0, firstElements);
  707. }
  708. if (returnedList != null) {
  709. if (returnedList.isEmpty()) {
  710. nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn);
  711. return nextSequenceStartsOn;
  712. }
  713. blockList = new BlockSequence(nextSequenceStartsOn, getCurrentDisplayAlign());
  714. //Only implemented by the PSLM
  715. nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn);
  716. Position breakPosition = null;
  717. if (ElementListUtils.endsWithForcedBreak(returnedList)) {
  718. KnuthPenalty breakPenalty = (KnuthPenalty) ListUtil
  719. .removeLast(returnedList);
  720. breakPosition = breakPenalty.getPosition();
  721. log.debug("PLM> break - " + getBreakClassName(breakPenalty.getBreakClass()));
  722. switch (breakPenalty.getBreakClass()) {
  723. case Constants.EN_PAGE:
  724. nextSequenceStartsOn = Constants.EN_ANY;
  725. break;
  726. case Constants.EN_COLUMN:
  727. //TODO Fix this when implementing multi-column layout
  728. nextSequenceStartsOn = Constants.EN_COLUMN;
  729. break;
  730. case Constants.EN_ODD_PAGE:
  731. nextSequenceStartsOn = Constants.EN_ODD_PAGE;
  732. break;
  733. case Constants.EN_EVEN_PAGE:
  734. nextSequenceStartsOn = Constants.EN_EVEN_PAGE;
  735. break;
  736. default:
  737. throw new IllegalStateException("Invalid break class: "
  738. + breakPenalty.getBreakClass());
  739. }
  740. if (ElementListUtils.isEmptyBox(returnedList)) {
  741. ListUtil.removeLast(returnedList);
  742. }
  743. }
  744. blockList.addAll(returnedList);
  745. BlockSequence seq;
  746. seq = blockList.endBlockSequence(breakPosition);
  747. if (seq != null) {
  748. blockLists.add(seq);
  749. }
  750. }
  751. return nextSequenceStartsOn;
  752. }
  753. protected boolean shouldRedoLayout() {
  754. return false;
  755. }
  756. protected void prepareToRedoLayout(PageBreakingAlgorithm alg, int partCount,
  757. BlockSequence originalList, BlockSequence effectiveList) {
  758. return;
  759. }
  760. protected boolean wasLayoutRedone() {
  761. return false;
  762. }
  763. private boolean thereIsANonRestartableLM(PageBreakingAlgorithm alg) {
  764. KnuthNode optimalBreak = alg.getBestNodeForLastPage();
  765. if (optimalBreak != null) {
  766. int positionIndex = optimalBreak.position;
  767. KnuthElement elementAtBreak = alg.getElement(positionIndex);
  768. Position positionAtBreak = elementAtBreak.getPosition();
  769. if (!(positionAtBreak instanceof SpaceResolver.SpaceHandlingBreakPosition)) {
  770. return false;
  771. }
  772. /* Retrieve the original position wrapped into this space position */
  773. positionAtBreak = positionAtBreak.getPosition();
  774. if (positionAtBreak != null && containsNonRestartableLM(positionAtBreak)) {
  775. return true;
  776. }
  777. }
  778. return false;
  779. }
  780. protected boolean lastPageHasIPDChange() {
  781. return false;
  782. }
  783. protected int handleFloatLayout(PageBreakingAlgorithm alg, int optimalPageCount, BlockSequence blockList,
  784. LayoutContext childLC) {
  785. throw new IllegalStateException();
  786. }
  787. protected void addAreasForFloats(PageBreakingAlgorithm alg, int startPart, int partCount,
  788. BlockSequence originalList, BlockSequence effectiveList, final LayoutContext childLC,
  789. int lastBreak, int startElementIndex, int endElementIndex) {
  790. throw new IllegalStateException();
  791. }
  792. }