diff options
author | Adrian Cumiskey <acumiskey@apache.org> | 2008-07-07 14:09:01 +0000 |
---|---|---|
committer | Adrian Cumiskey <acumiskey@apache.org> | 2008-07-07 14:09:01 +0000 |
commit | 64912d1dd4c858eeb21a123e98e6f19bd78cc614 (patch) | |
tree | 2dc81b04b5d02090e4a5e1fe244edcb4c43b0a61 /src/java | |
parent | cb82679d9f56be1fa4d8f198366e472da23709a2 (diff) | |
download | xmlgraphics-fop-64912d1dd4c858eeb21a123e98e6f19bd78cc614.tar.gz xmlgraphics-fop-64912d1dd4c858eeb21a123e98e6f19bd78cc614.zip |
Merged revisions 656546,657465,657521,657921,660979,660998,661276,661310,661999,662009,662203,662417,662807,662991,663045,663493,664347,664349-664350,665691,665699,665740,665793,665995,666596,666967,667367,667831,667862,667864,667893,668177,668576,669423,669436,669835,670217,670222,670323,670325,670332,670335-670336,670341,670344,670401,670409,670411-670412,670422-670424,670492,670689,670723,670760-670761,670763,670765-670767,670770,670773,670777,671145,672010,672026,672495-672496,672499,672537,672539,672564-672565,672617-672618,672670,672833,674039,674043,674056,674065,674245,674267,674269,674272-674273,674276,674325,674468,674470-674471,674484,674486-674487 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk
................
r656546 | adelmelle | 2008-05-15 09:33:19 +0100 (Thu, 15 May 2008) | 1 line
Tweak: make sure the fo:flow's id is bound to the FObj
................
r657465 | adelmelle | 2008-05-17 22:18:19 +0100 (Sat, 17 May 2008) | 1 line
Corrected testcase: since the fo:flow's ID is correctly processed...
................
r657521 | maxberger | 2008-05-18 10:39:03 +0100 (Sun, 18 May 2008) | 1 line
Updated as per suggestions in bug 45019
................
r657921 | spepping | 2008-05-19 20:02:18 +0100 (Mon, 19 May 2008) | 6 lines
Added event TableEventProducer.forceNextColumnNumber when
TableFObj.ColumnNumberPropertyMaker forces a zero or negative
column-number property to the next available column, because this is a
FOP extension. Fixed TableFObj.ColumnNumberPropertyMaker.make to
really report a cell overlap event.
................
r660979 | vhennebert | 2008-05-28 16:24:23 +0100 (Wed, 28 May 2008) | 3 lines
Bugzilla 37579: added support for footnotes in lists and table bodies (not header nor footer).
This is /not/ to be considered a final fix: similar code is duplicated over several classes (LineLayoutManager, ListItemLayoutManager and to less extent TableStepper). Footnotes should probably be handled another way.
................
r660998 | maxberger | 2008-05-28 17:10:32 +0100 (Wed, 28 May 2008) | 1 line
Implemented Font auto-selection word-by-word
................
r661276 | vhennebert | 2008-05-29 10:58:06 +0100 (Thu, 29 May 2008) | 2 lines
Set svn:keywords and svn:eol-style properties for files added in revision 660998
................
r661310 | maxberger | 2008-05-29 13:03:48 +0100 (Thu, 29 May 2008) | 1 line
Added docs for my recent commit (word-by-word character selection)
................
r661999 | adelmelle | 2008-05-31 11:56:05 +0100 (Sat, 31 May 2008) | 3 lines
Bugzilla 45097:
Leading/trailing white-space not removed from nested inline-content when there is no preceding/following text.
................
r662009 | maxberger | 2008-05-31 12:45:55 +0100 (Sat, 31 May 2008) | 1 line
Code Cleanups (no functional change)
................
r662203 | maxberger | 2008-06-01 12:57:33 +0100 (Sun, 01 Jun 2008) | 1 line
More code Cleanups (no functional changes)
................
r662417 | jeremias | 2008-06-02 13:50:55 +0100 (Mon, 02 Jun 2008) | 1 line
Integer keeps inside multi-line blocks and in between block-paragraphs.
................
r662807 | jeremias | 2008-06-03 15:13:27 +0100 (Tue, 03 Jun 2008) | 3 lines
Bugzilla #45115:
Added a PCL-specific extension attribute on simple-page-master for controlling the simplex/duplex mode.
Submitted by: Martin Edge <Martin.Edge.at.asmorphic.net.au>
................
r662991 | jeremias | 2008-06-04 07:10:37 +0100 (Wed, 04 Jun 2008) | 1 line
ApacheCon EU 2008 is long over.
................
r663045 | adelmelle | 2008-06-04 10:53:15 +0100 (Wed, 04 Jun 2008) | 1 line
Minor cleanup: remove spurious white-space
................
r663493 | jeremias | 2008-06-05 08:41:06 +0100 (Thu, 05 Jun 2008) | 1 line
Restored lost overflow warning in static-content.
................
r664347 | adelmelle | 2008-06-07 15:49:42 +0100 (Sat, 07 Jun 2008) | 5 lines
Extended behavior of preserved linefeeds to codepoints representing mandatory breaks in Unicode UAX#14:
- NEXT LINE (U+0085)
- LINE SEPARATOR (U+2028)
- PARAGRAPH SEPARATOR (U+2029)
................
r664349 | adelmelle | 2008-06-07 15:54:13 +0100 (Sat, 07 Jun 2008) | 1 line
Minor cleanup: remove unneeded constant
................
r664350 | adelmelle | 2008-06-07 16:09:42 +0100 (Sat, 07 Jun 2008) | 1 line
Improve code-readability; add some clarifying comments
................
r665691 | jeremias | 2008-06-09 15:01:53 +0100 (Mon, 09 Jun 2008) | 82 lines
Merged revisions 636407-637074,637076-637118,637120-637790,637792-637856,637858-637992,637994-638047,638049-638307,638309-638315,638318-664698 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_95
........
r638937 | jeremias | 2008-03-19 18:08:57 +0100 (Mi, 19 Mrz 2008) | 1 line
A nit.
........
r640889 | vhennebert | 2008-03-25 17:43:55 +0100 (Di, 25 Mrz 2008) | 2 lines
Set the final release date and added a news item about the 0.95beta release (the change was made before updating the website)
........
r642906 | jeremias | 2008-03-31 09:12:40 +0200 (Mo, 31 Mrz 2008) | 3 lines
Added version number to xml-apis-ext (as suggested by Karel Vervaeke).
Moved xml-apis to same version as xml-apis-ext.
Added missing licensing info about xml-apis-ext.
........
r647403 | jeremias | 2008-04-12 11:02:01 +0200 (Sa, 12 Apr 2008) | 1 line
Fixed NullPointerException when loading a TrueType font using XML font metric files.
........
r647537 | jeremias | 2008-04-13 09:36:00 +0200 (So, 13 Apr 2008) | 1 line
Performance improvement when encoding images: Fixed an important hotspot by extending CloseBlocker from ProxyOutputStream instead of FilterOutputStream as the latter routes all write(byte[]) calls through write(int).
........
r648984 | jeremias | 2008-04-17 09:00:22 +0200 (Do, 17 Apr 2008) | 1 line
HeadURL was missing in the properties.
........
r649006 | jeremias | 2008-04-17 10:42:52 +0200 (Do, 17 Apr 2008) | 1 line
Fixed text extraction problem with ZapfDingbats and Symbol font in PDF output. These fonts are symbolic and must not use an Encoding value in PDF. Applies to the built-in base 14 variant and to the case where these fonts are explicitely embedded.
........
r649014 | jeremias | 2008-04-17 11:10:15 +0200 (Do, 17 Apr 2008) | 1 line
Added missing change information.
........
r650550 | vhennebert | 2008-04-22 17:22:31 +0200 (Di, 22 Apr 2008) | 4 lines
Bugzilla 41621:
- length of the penalty now correctly computed;
- AssertionError fixed.
........
r651302 | jeremias | 2008-04-24 18:08:53 +0200 (Do, 24 Apr 2008) | 3 lines
Fixed regression causing bad positioning of block-containers if used as descendant of a table-cell. This was not caught because of the lack of a test case that would have shown the problem in visual testing with BatchDiffer.
See also: http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-users/200804.mbox/%3c20080424164128.973A.DEV@jeremias-maerki.ch%3e
........
r653537 | vhennebert | 2008-05-05 19:47:28 +0200 (Mo, 05 Mai 2008) | 2 lines
Bugfix: the before border of cells below a column-spanning cell had their value taken from the leading case, instead of the normal one.
........
r654453 | jeremias | 2008-05-08 11:14:04 +0200 (Do, 08 Mai 2008) | 2 lines
Added /usr/local/share/fonts as additional possible location for fonts on Unixes.
........
r656286 | jeremias | 2008-05-14 16:16:49 +0200 (Mi, 14 Mai 2008) | 1 line
Restored plug-in API compatibility with FOP 0.94. Fixes a NoSuchMethodError when Barcode4J is run.
........
r656524 | jeremias | 2008-05-15 09:07:18 +0200 (Do, 15 Mai 2008) | 1 line
Fixed rendering of fixed block-containers in AFP output. The break-out was actually never implemented which is necessary for supporting fixed positioned viewports.
........
r657520 | maxberger | 2008-05-18 11:38:45 +0200 (So, 18 Mai 2008) | 1 line
Updated as per suggestions in bug 45019
........
r661580 | maxberger | 2008-05-30 08:42:17 +0200 (Fr, 30 Mai 2008) | 1 line
added my key to KEYS, it is used for signing mvn artifacts
........
r663482 | jeremias | 2008-06-05 09:06:37 +0200 (Do, 05 Jun 2008) | 1 line
Fixed positioning of absolutely positioned block-containers in multi-column documents.
........
r664692 | jeremias | 2008-06-09 14:49:45 +0200 (Mo, 09 Jun 2008) | 1 line
Restored PSImageUtils. I had deleted it prematurely. Extensions like Barcode4J rely on this class.
........
................
r665699 | maxberger | 2008-06-09 15:15:38 +0100 (Mon, 09 Jun 2008) | 1 line
Replaced LinkedList with generic List interface
................
r665740 | adelmelle | 2008-06-09 17:20:08 +0100 (Mon, 09 Jun 2008) | 1 line
Minor update: make the codegen-unicode target create LineBreakUtils.java at the appropriate place in the source tree
................
r665793 | adelmelle | 2008-06-09 18:27:51 +0100 (Mon, 09 Jun 2008) | 9 lines
Some updates (improvements?) in the UAX#14-related files:
- LineBreakPairTable.txt: replace tabs with spaces to make the file a bit easier to read (constant column-width, instead of depending on an editor's settings for tabs)
- GenerateLineBreakUtils.java:
- generate a public final utility class
- add some spacing in the generated file, after commas and before/after '=' (same styling as manually created files)
- use Java 1.4 String.split() to tokenize lines, instead of StringTokenizer
- add javadoc comments for public constants and methods
- LineBreakUtils.java: regenerated after the above updates
................
r665995 | maxberger | 2008-06-10 08:52:36 +0100 (Tue, 10 Jun 2008) | 1 line
Replaced getLast() calls with calls to listUtil
................
r666596 | vhennebert | 2008-06-11 10:52:04 +0100 (Wed, 11 Jun 2008) | 2 lines
Fixed typo
................
r666967 | maxberger | 2008-06-12 07:07:28 +0100 (Thu, 12 Jun 2008) | 1 line
Added PMD and Findbugs report, 'reports' target'
................
r667367 | maxberger | 2008-06-13 07:03:30 +0100 (Fri, 13 Jun 2008) | 1 line
Disabled retroweaver task definition, because it breaks gump
................
r667831 | maxberger | 2008-06-14 17:21:15 +0100 (Sat, 14 Jun 2008) | 1 line
minor spelling fixes
................
r667862 | maxberger | 2008-06-14 19:18:14 +0100 (Sat, 14 Jun 2008) | 1 line
minor spelling fixes
................
r667864 | maxberger | 2008-06-14 19:23:28 +0100 (Sat, 14 Jun 2008) | 1 line
minor spelling & checkstyle fixes
................
r667893 | maxberger | 2008-06-14 23:20:42 +0100 (Sat, 14 Jun 2008) | 1 line
removed double storage of 'fobj'
................
r668177 | lfurini | 2008-06-16 15:52:14 +0100 (Mon, 16 Jun 2008) | 2 lines
Fixing the PageBreakingAlgorithm, replacing calls to getLineWidth() with getLineWidth(int) so as to take into account each page's real height.
This fixes the positioning of footnotes when the page bpd is not the same for all pages.
................
r668576 | jeremias | 2008-06-17 10:04:05 +0100 (Tue, 17 Jun 2008) | 1 line
Wrong line number reported in the case of a line overflow.
................
r669423 | jeremias | 2008-06-19 09:25:46 +0100 (Thu, 19 Jun 2008) | 1 line
Simplifications and a Checkstyle fix.
................
r669436 | jeremias | 2008-06-19 10:46:12 +0100 (Thu, 19 Jun 2008) | 2 lines
Separation of concerns:
Split FOEventHandler into FOEventHandler and FOTreeBuilderContext. The latter contains stuff only used at tree-building stage. FOEventHandler is oriented towards output.
................
r669835 | acumiskey | 2008-06-20 10:18:56 +0100 (Fri, 20 Jun 2008) | 1 line
Strict/loose validation of <fo:table-footer/> ordering somehow got lost in processing feedback branch merge.
................
r670217 | acumiskey | 2008-06-21 17:10:03 +0100 (Sat, 21 Jun 2008) | 1 line
Moved the contents of TableBody into a new abstract base class TablePart, which is now subclassed by TableBody, TableHeader and TableFooter.
................
r670222 | acumiskey | 2008-06-21 17:28:56 +0100 (Sat, 21 Jun 2008) | 1 line
Moved the contents of TableBody into a new abstract base class TablePart, which is now subclassed by TableBody, TableHeader and TableFooter.
................
r670323 | adelmelle | 2008-06-22 10:07:47 +0100 (Sun, 22 Jun 2008) | 1 line
Addition to r670217
................
r670325 | adelmelle | 2008-06-22 10:28:56 +0100 (Sun, 22 Jun 2008) | 1 line
Minor javadoc correction
................
r670332 | adelmelle | 2008-06-22 11:21:03 +0100 (Sun, 22 Jun 2008) | 1 line
Minor tweak: avoid warning when running through Saxon
................
r670335 | adelmelle | 2008-06-22 11:53:51 +0100 (Sun, 22 Jun 2008) | 1 line
Avoid StackOverflow on TableColumn.toString() during debugging.
................
r670336 | adelmelle | 2008-06-22 12:01:27 +0100 (Sun, 22 Jun 2008) | 1 line
Minor tweak: use XG Commons version of the interface
................
r670341 | adelmelle | 2008-06-22 12:18:03 +0100 (Sun, 22 Jun 2008) | 2 lines
Changed FONode.addCharacters() signature to match the characters() event (use 'length' as a parameter instead of 'end')
................
r670344 | adelmelle | 2008-06-22 12:28:06 +0100 (Sun, 22 Jun 2008) | 1 line
Changed signature for static handleWhiteSpaceFor(), and used internally to make the code a bit more compact
................
r670401 | adelmelle | 2008-06-22 20:19:17 +0100 (Sun, 22 Jun 2008) | 1 line
Correction: characters() expects a 'length' not an 'endIndex'
................
r670409 | adelmelle | 2008-06-22 21:18:27 +0100 (Sun, 22 Jun 2008) | 1 line
Very minor tweak: simplify conditional
................
r670411 | adelmelle | 2008-06-22 21:38:28 +0100 (Sun, 22 Jun 2008) | 2 lines
Deleted deprecated interface; unused after r670336
................
r670412 | adelmelle | 2008-06-22 21:57:43 +0100 (Sun, 22 Jun 2008) | 6 lines
Partial fix of FOEventHandler call sequence (see also Bugzilla #45237):
call startOfNode() after addChildNode()
moved initialization for tableFOs to processNode()
moved finishing code to a finalizeNode() method (which is now also used by AbstractRetrieveMarker)
restored protected status of startOfNode()/endOfNode() in fo.flow.table package
................
r670422 | adelmelle | 2008-06-22 23:10:55 +0100 (Sun, 22 Jun 2008) | 4 lines
Switch FOText to use a java.nio.CharBuffer, and implement the CharSequence interface.
TextLayoutManager no longer duplicates the char array, operates on the FOText (charAt(i))
Additionally: endOfNode() for FOText and Character deferred until after white-space handling.
................
r670423 | adelmelle | 2008-06-22 23:17:00 +0100 (Sun, 22 Jun 2008) | 1 line
Added missing file from r670422
................
r670424 | adelmelle | 2008-06-22 23:18:53 +0100 (Sun, 22 Jun 2008) | 1 line
Another missing file...
................
r670492 | lfurini | 2008-06-23 10:24:14 +0100 (Mon, 23 Jun 2008) | 2 lines
Added support for non-zero borders and padding on page regions.
Testcase included, now disabled because it is supposed to run with relaxed validation switched on.
................
r670689 | adelmelle | 2008-06-23 19:01:25 +0100 (Mon, 23 Jun 2008) | 1 line
Fix XMLObj.addCharacters(): incorrect after r670341
................
r670723 | adelmelle | 2008-06-23 20:56:51 +0100 (Mon, 23 Jun 2008) | 1 line
Javadoc modification + addition of clarifying comments
................
r670760 | adelmelle | 2008-06-23 22:18:45 +0100 (Mon, 23 Jun 2008) | 1 line
Javadoc fixup
................
r670761 | adelmelle | 2008-06-23 22:21:09 +0100 (Mon, 23 Jun 2008) | 1 line
Minor cleanup: remove unused parameter from method signature
................
r670763 | adelmelle | 2008-06-23 22:22:48 +0100 (Mon, 23 Jun 2008) | 1 line
Minor cleanup: remove double storage of the FObj
................
r670765 | adelmelle | 2008-06-23 22:24:46 +0100 (Mon, 23 Jun 2008) | 1 line
Minor cleanup: remove redundant cast
................
r670766 | adelmelle | 2008-06-23 22:25:30 +0100 (Mon, 23 Jun 2008) | 1 line
Minor cleanup: remove redundant cast
................
r670767 | adelmelle | 2008-06-23 22:26:56 +0100 (Mon, 23 Jun 2008) | 1 line
Javadoc fixup
................
r670770 | adelmelle | 2008-06-23 22:29:53 +0100 (Mon, 23 Jun 2008) | 1 line
Minor cleanup: simplified conditional
................
r670773 | adelmelle | 2008-06-23 22:32:31 +0100 (Mon, 23 Jun 2008) | 1 line
A nit...
................
r670777 | adelmelle | 2008-06-23 22:39:19 +0100 (Mon, 23 Jun 2008) | 1 line
Fix imports...
................
r671145 | maxberger | 2008-06-24 12:59:33 +0100 (Tue, 24 Jun 2008) | 2 lines
Another character handling problem, replaced end-start by length
................
r672010 | adelmelle | 2008-06-26 20:44:20 +0100 (Thu, 26 Jun 2008) | 1 line
Fixed a possible NullPointerException: if the citation appears in a fo:marker, the property will only be parsed if the marker is retrieved...
................
r672026 | acumiskey | 2008-06-26 21:49:11 +0100 (Thu, 26 Jun 2008) | 5 lines
Some basic cleanup.
* Duplicated/redundant PSDictionary, PSPageDeviceDictionary and PSDictionaryFormatException removed and now referenced from xmlgraphics commons.
* Updated xmlgraphics commons jar containing migrated PSPageDeviceDictionary class.
................
r672495 | adelmelle | 2008-06-28 12:22:58 +0100 (Sat, 28 Jun 2008) | 1 line
Removed unnecessary override
................
r672496 | adelmelle | 2008-06-28 12:24:20 +0100 (Sat, 28 Jun 2008) | 1 line
Added testcase for r672010
................
r672499 | adelmelle | 2008-06-28 13:11:40 +0100 (Sat, 28 Jun 2008) | 3 lines
Added basic-checks.xml: file currently only contains one default check.
Modified testcase2checks.xsl: the added basic-checks.xml will be inserted before the checks particular to the testcase.
................
r672537 | acumiskey | 2008-06-28 17:05:08 +0100 (Sat, 28 Jun 2008) | 1 line
Corrected minor spelling mistake in javadoc
................
r672539 | acumiskey | 2008-06-28 17:08:13 +0100 (Sat, 28 Jun 2008) | 1 line
Corrected minor spelling mistake in javadoc
................
r672564 | adelmelle | 2008-06-28 19:39:39 +0100 (Sat, 28 Jun 2008) | 1 line
Corrected basic checks: check for empty document, as well as empty areaTree...
................
r672565 | adelmelle | 2008-06-28 19:45:16 +0100 (Sat, 28 Jun 2008) | 1 line
Removed instream-foreign-object in marker; still threw a NPE
................
r672617 | adelmelle | 2008-06-29 11:52:30 +0100 (Sun, 29 Jun 2008) | 1 line
Added disabled testcase for instream-foreign-object in a marker
................
r672618 | adelmelle | 2008-06-29 11:58:31 +0100 (Sun, 29 Jun 2008) | 2 lines
Correct svn props
................
r672670 | adelmelle | 2008-06-29 20:53:17 +0100 (Sun, 29 Jun 2008) | 1 line
Cleanup/re-ordering, and addition of XSL 1.1 FO_ and PR_ constants
................
r672833 | adelmelle | 2008-06-30 18:34:41 +0100 (Mon, 30 Jun 2008) | 2 lines
Added check for the case where column-number is specified on something other than a fo:table-cell or fo:table-column (strictly not an error)
................
r674039 | acumiskey | 2008-07-04 14:13:29 +0100 (Fri, 04 Jul 2008) | 2 lines
Minor readability improvement.
................
r674043 | acumiskey | 2008-07-04 14:17:06 +0100 (Fri, 04 Jul 2008) | 3 lines
The pdf StringBuffer is only used on these two lines and doesn't seem to do anything...
Very strange... :-S
................
r674056 | acumiskey | 2008-07-04 14:57:57 +0100 (Fri, 04 Jul 2008) | 3 lines
* Some minor optimizations in AbstractRenderer.
* Renamed getBooleanTrait() to getTraitAsBoolean() in Area.
................
r674065 | acumiskey | 2008-07-04 15:12:37 +0100 (Fri, 04 Jul 2008) | 2 lines
Replaced conditional with a switch and capitalized method javadoc description.
................
r674245 | adelmelle | 2008-07-05 23:53:58 +0100 (Sat, 05 Jul 2008) | 1 line
Fixed ClassCastException when specifying column-number on something other than a fo:table-column or fo:table-cell...
................
r674267 | adelmelle | 2008-07-06 08:50:23 +0100 (Sun, 06 Jul 2008) | 1 line
Switch AreaTreeParser to use a java.nio.CharBuffer, and ignore characters events for all elements other than <word>, <space> or <character>
................
r674269 | adelmelle | 2008-07-06 09:15:50 +0100 (Sun, 06 Jul 2008) | 1 line
Remove deprecated Character area class
................
r674272 | adelmelle | 2008-07-06 09:44:54 +0100 (Sun, 06 Jul 2008) | 1 line
Redo changes made in r674056...
................
r674273 | adelmelle | 2008-07-06 09:46:50 +0100 (Sun, 06 Jul 2008) | 1 line
Simplified implementation of Area.getTraitAsBoolean()
................
r674276 | adelmelle | 2008-07-06 10:17:14 +0100 (Sun, 06 Jul 2008) | 3 lines
Extracted conversion methods for String to int[] or double[] to a utility class.
Made AreaTreeParser.getAttributeAsXXX() methods static to stress their utility character, and removed the private parseRect() in favor of getAttributeAsRectangle2D().
................
r674325 | adelmelle | 2008-07-06 19:19:48 +0100 (Sun, 06 Jul 2008) | 1 line
Fixed error; inadvertently switched the condition with r674272...
................
r674468 | acumiskey | 2008-07-07 13:36:57 +0100 (Mon, 07 Jul 2008) | 1 line
Possible NullPointerException avoided
................
r674470 | acumiskey | 2008-07-07 13:38:04 +0100 (Mon, 07 Jul 2008) | 1 line
Added new set accessor method for EncryptionParams.
................
r674471 | acumiskey | 2008-07-07 13:42:12 +0100 (Mon, 07 Jul 2008) | 1 line
Added PDF encryption parameter support in configuration.
................
r674484 | acumiskey | 2008-07-07 14:28:26 +0100 (Mon, 07 Jul 2008) | 1 line
Added new AbstractXMLRenderer base class.
................
r674486 | acumiskey | 2008-07-07 14:43:19 +0100 (Mon, 07 Jul 2008) | 1 line
Cleaned up some javadocs.
................
r674487 | acumiskey | 2008-07-07 14:44:14 +0100 (Mon, 07 Jul 2008) | 2 lines
Refactored this class, moving much of its behaviour to the base AbstractXMLRenderer class.
................
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign@674497 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java')
129 files changed, 4602 insertions, 3767 deletions
diff --git a/src/java/org/apache/fop/apps/MimeConstants.java b/src/java/org/apache/fop/apps/MimeConstants.java index 31bdaaab1..cdd30c0e1 100644 --- a/src/java/org/apache/fop/apps/MimeConstants.java +++ b/src/java/org/apache/fop/apps/MimeConstants.java @@ -55,7 +55,7 @@ public interface MimeConstants { /** FrameMaker's MIF */ String MIME_MIF = "application/mif"; - /** Structured Vector Graphics */ + /** Scalable Vector Graphics */ String MIME_SVG = "image/svg+xml"; /** GIF images */ diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java index ff9f5c7d0..30911700f 100644 --- a/src/java/org/apache/fop/area/Area.java +++ b/src/java/org/apache/fop/area/Area.java @@ -418,13 +418,8 @@ public class Area extends AreaTreeObject implements Serializable { * @param oTraitCode the trait key * @return the trait value */ - public boolean getBooleanTrait(Object oTraitCode) { - final Object obj = getTrait(oTraitCode); - if (obj instanceof Boolean) { - return ((Boolean)obj).booleanValue(); - } else { - return false; - } + public boolean getTraitAsBoolean(Object oTraitCode) { + return Boolean.TRUE.equals(getTrait(oTraitCode)); } /** diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index d48221c0a..6d9fd4f32 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.StringTokenizer; +import java.nio.CharBuffer; import javax.xml.transform.Source; import javax.xml.transform.Transformer; @@ -56,7 +57,6 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Trait.Background; import org.apache.fop.area.Trait.InternalLink; import org.apache.fop.area.inline.AbstractTextArea; -import org.apache.fop.area.inline.Character; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; @@ -78,6 +78,7 @@ import org.apache.fop.traits.BorderProps; import org.apache.fop.util.ColorUtil; import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactoryRegistry; +import org.apache.fop.util.ConversionUtils; import org.apache.fop.util.DefaultErrorListener; /** @@ -132,8 +133,10 @@ public class AreaTreeParser { private ElementMappingRegistry elementMappingRegistry; private Attributes lastAttributes; - private StringBuffer content = new StringBuffer(); + private CharBuffer content = CharBuffer.allocate(64); + private boolean ignoreCharacters = true; + private PageViewport currentPageViewport; private Map pageViewportsByKey = new java.util.HashMap(); // set of "ID firsts" that have already been assigned to a PV: @@ -176,7 +179,6 @@ public class AreaTreeParser { makers.put("text", new TextMaker()); makers.put("word", new WordMaker()); makers.put("space", new SpaceMaker()); - makers.put("char", new CharMaker()); makers.put("leader", new LeaderMaker()); makers.put("viewport", new ViewportMaker()); makers.put("image", new ImageMaker()); @@ -186,15 +188,6 @@ public class AreaTreeParser { makers.put("destination", new DestinationMaker()); } - private static Rectangle2D parseRect(String rect) { - StringTokenizer tokenizer = new StringTokenizer(rect, " "); - return new Rectangle2D.Double( - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken())); - } - private Area findAreaType(Class clazz) { if (areaStack.size() > 0) { int pos = areaStack.size() - 1; @@ -261,7 +254,10 @@ public class AreaTreeParser { boolean handled = true; if ("".equals(uri)) { Maker maker = (Maker)makers.get(localName); + content.clear(); + ignoreCharacters = true; if (maker != null) { + ignoreCharacters = maker.ignoreCharacters(); maker.startElement(attributes); } else if ("extension-attachments".equals(localName)) { //TODO implement me @@ -311,11 +307,12 @@ public class AreaTreeParser { Maker maker = (Maker)makers.get(localName); if (maker != null) { maker.endElement(); + content.clear(); } + ignoreCharacters = true; } else { //log.debug("Ignoring " + localName + " in namespace: " + uri); } - content.setLength(0); //Reset text buffer (see characters()) } } @@ -324,6 +321,7 @@ public class AreaTreeParser { private static interface Maker { void startElement(Attributes attributes) throws SAXException; void endElement(); + boolean ignoreCharacters(); } private abstract class AbstractMaker implements Maker { @@ -335,6 +333,10 @@ public class AreaTreeParser { public void endElement() { //nop } + + public boolean ignoreCharacters() { + return true; + } } private class AreaTreeMaker extends AbstractMaker { @@ -384,7 +386,7 @@ public class AreaTreeParser { if (currentPageViewport != null) { throw new IllegalStateException("currentPageViewport must be null"); } - Rectangle2D viewArea = parseRect(attributes.getValue("bounds")); + Rectangle2D viewArea = getAttributeAsRectangle2D(attributes, "bounds"); int pageNumber = getAttributeAsInteger(attributes, "nr", -1); String key = attributes.getValue("key"); String pageNumberString = attributes.getValue("formatted-nr"); @@ -420,7 +422,7 @@ public class AreaTreeParser { if (rv != null) { throw new IllegalStateException("Current RegionViewport must be null"); } - Rectangle2D viewArea = parseRect(attributes.getValue("rect")); + Rectangle2D viewArea = getAttributeAsRectangle2D(attributes, "rect"); rv = new RegionViewport(viewArea); transferForeignObjects(attributes, rv); rv.setClip(getAttributeAsBoolean(attributes, "clipped", false)); @@ -444,7 +446,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionAfterMaker extends AbstractMaker { @@ -455,7 +457,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionStartMaker extends AbstractMaker { @@ -466,7 +468,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionEndMaker extends AbstractMaker { @@ -477,7 +479,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionBodyMaker extends AbstractMaker { @@ -575,7 +577,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), BeforeFloat.class); - } + } } private class BlockMaker extends AbstractMaker { @@ -627,7 +629,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), Block.class); - } + } } private class LineAreaMaker extends AbstractMaker { @@ -735,47 +737,37 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), TextArea.class); - } + } } private class WordMaker extends AbstractMaker { - private int[] toIntArray(String s) { - if (s == null || s.length() == 0) { - return null; - } - StringTokenizer tokenizer = new StringTokenizer(s, " "); - List values = new java.util.ArrayList(); - while (tokenizer.hasMoreTokens()) { - values.add(new Integer(tokenizer.nextToken())); - } - int[] res = new int[values.size()]; - for (int i = 0, c = res.length; i < c; i++) { - res[i] = ((Integer)values.get(i)).intValue(); - } - return res; - } - public void endElement() { int offset = getAttributeAsInteger(lastAttributes, "offset", 0); - int[] letterAdjust = toIntArray(lastAttributes.getValue("letter-adjust")); - String txt = content.toString(); - WordArea word = new WordArea(txt, offset, letterAdjust); + int[] letterAdjust + = ConversionUtils.toIntArray( + lastAttributes.getValue("letter-adjust"), "\\s"); + content.flip(); + WordArea word = new WordArea(content.toString().trim(), offset, letterAdjust); AbstractTextArea text = getCurrentText(); word.setParentArea(text); text.addChildArea(word); - } + } + + public boolean ignoreCharacters() { + return false; + } } private class SpaceMaker extends AbstractMaker { - + public void endElement() { int offset = getAttributeAsInteger(lastAttributes, "offset", 0); - String txt = content.toString(); //TODO the isAdjustable parameter is currently not used/implemented - if (txt.length() > 0) { + if (content.position() > 0) { + content.flip(); boolean adjustable = getAttributeAsBoolean(lastAttributes, "adj", true); - SpaceArea space = new SpaceArea(txt.charAt(0), offset, adjustable); + SpaceArea space = new SpaceArea(content.charAt(0), offset, adjustable); AbstractTextArea text = getCurrentText(); space.setParentArea(text); text.addChildArea(space); @@ -789,25 +781,11 @@ public class AreaTreeParser { Area parent = (Area)areaStack.peek(); parent.addChildArea(space); } - } - } - - private class CharMaker extends AbstractMaker { - - public void endElement() { - String txt = content.toString(); - Character ch = new Character(txt.charAt(0)); - transferForeignObjects(lastAttributes, ch); - setAreaAttributes(lastAttributes, ch); - setTraits(lastAttributes, ch, SUBSET_COMMON); - setTraits(lastAttributes, ch, SUBSET_BOX); - setTraits(lastAttributes, ch, SUBSET_COLOR); - setTraits(lastAttributes, ch, SUBSET_FONT); - ch.setOffset(getAttributeAsInteger(lastAttributes, "offset", 0)); - ch.setBaselineOffset(getAttributeAsInteger(lastAttributes, "baseline", 0)); - Area parent = (Area)areaStack.peek(); - parent.addChildArea(ch); - } + } + + public boolean ignoreCharacters() { + return false; + } } private class LeaderMaker extends AbstractMaker { @@ -830,9 +808,6 @@ public class AreaTreeParser { Area parent = (Area)areaStack.peek(); parent.addChildArea(leader); } - - public void endElement() { - } } private class ViewportMaker extends AbstractMaker { @@ -854,7 +829,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), Viewport.class); - } + } } private class ImageMaker extends AbstractMaker { @@ -1097,7 +1072,7 @@ public class AreaTreeParser { } } - private boolean getAttributeAsBoolean(Attributes attributes, String name, + private static boolean getAttributeAsBoolean(Attributes attributes, String name, boolean defaultValue) { String s = attributes.getValue(name); if (s == null) { @@ -1107,7 +1082,7 @@ public class AreaTreeParser { } } - private int getAttributeAsInteger(Attributes attributes, String name, + private static int getAttributeAsInteger(Attributes attributes, String name, int defaultValue) { String s = attributes.getValue(name); if (s == null) { @@ -1117,36 +1092,30 @@ public class AreaTreeParser { } } - private CTM getAttributeAsCTM(Attributes attributes, String name) { + private static CTM getAttributeAsCTM(Attributes attributes, String name) { String s = attributes.getValue(name).trim(); if (s.startsWith("[") && s.endsWith("]")) { s = s.substring(1, s.length() - 1); - StringTokenizer tokenizer = new StringTokenizer(s, " "); - double[] values = new double[] { - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken())}; + double[] values = ConversionUtils.toDoubleArray(s, "\\s"); + if (values.length != 6) { + throw new IllegalArgumentException("CTM must consist of 6 double values!"); + } return new CTM(values[0], values[1], values[2], values[3], values[4], values[5]); } else { - throw new IllegalArgumentException("CTM must be surrounded by square brackets"); + throw new IllegalArgumentException("CTM must be surrounded by square brackets!"); } } - private Rectangle2D getAttributeAsRectangle2D(Attributes attributes, String name) { + private static Rectangle2D getAttributeAsRectangle2D(Attributes attributes, String name) { String s = attributes.getValue(name).trim(); - StringTokenizer tokenizer = new StringTokenizer(s, " "); - double[] values = new double[] { - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken())}; + double[] values = ConversionUtils.toDoubleArray(s, "\\s"); + if (values.length != 4) { + throw new IllegalArgumentException("Rectangle must consist of 4 double values!"); + } return new Rectangle2D.Double(values[0], values[1], values[2], values[3]); } - private void transferForeignObjects(Attributes atts, AreaTreeObject ato) { + private static void transferForeignObjects(Attributes atts, AreaTreeObject ato) { for (int i = 0, c = atts.getLength(); i < c; i++) { String ns = atts.getURI(i); if (ns.length() > 0) { @@ -1163,11 +1132,25 @@ public class AreaTreeParser { public void characters(char[] ch, int start, int length) throws SAXException { if (delegate != null) { delegate.characters(ch, start, length); - } else { - content.append(ch, start, length); + } else if (!ignoreCharacters) { + int maxLength = this.content.capacity() - this.content.position(); + if (maxLength < length) { + // allocate a larger buffer and transfer content + CharBuffer newContent + = CharBuffer.allocate(this.content.position() + length); + this.content.flip(); + newContent.put(this.content); + this.content = newContent; + } + // make sure the full capacity is used + this.content.limit(this.content.capacity()); + // add characters to the buffer + this.content.put(ch, start, length); + // decrease the limit, if necessary + if (this.content.position() < this.content.limit()) { + this.content.limit(this.content.position()); + } } } - } - } diff --git a/src/java/org/apache/fop/area/Page.java b/src/java/org/apache/fop/area/Page.java index 64a6db576..ddc2a95ab 100644 --- a/src/java/org/apache/fop/area/Page.java +++ b/src/java/org/apache/fop/area/Page.java @@ -126,6 +126,10 @@ public class Page extends AreaTreeObject implements Serializable, Cloneable { } else { rr = new RegionReference(r, rvp); } + // set borders and padding traits + // (a little extensions wrt what prescribed by the specs at 6.4.14) + TraitSetter.addBorders(rr, r.getCommonBorderPaddingBackground(), false, false, false, false, null); + TraitSetter.addPadding(rr, r.getCommonBorderPaddingBackground(), false, false, false, false, null); setRegionReferencePosition(rr, r, rvp.getViewArea()); rvp.setRegionReference(rr); setRegionViewport(r.getNameId(), rvp); @@ -205,27 +209,28 @@ public class Page extends AreaTreeObject implements Serializable, Cloneable { /** * Get the region from this page. * - * @param areaclass the region area class + * @param areaClass the region area class * @return the region viewport or null if none */ - public RegionViewport getRegionViewport(int areaclass) { - if (areaclass == Constants.FO_REGION_BEFORE) { + public RegionViewport getRegionViewport(int areaClass) { + switch (areaClass) { + case Constants.FO_REGION_BEFORE: return regionBefore; - } else if (areaclass == Constants.FO_REGION_START) { + case Constants.FO_REGION_START: return regionStart; - } else if (areaclass == Constants.FO_REGION_BODY) { - return regionBody; - } else if (areaclass == Constants.FO_REGION_END) { + case Constants.FO_REGION_BODY: + return regionBody; + case Constants.FO_REGION_END: return regionEnd; - } else if (areaclass == Constants.FO_REGION_AFTER) { + case Constants.FO_REGION_AFTER: return regionAfter; + default: + throw new IllegalArgumentException("No such area class with ID = " + areaClass); } - throw new IllegalArgumentException("No such area class with ID = " - + areaclass); } /** - * indicates whether any FOs have been added to the body region + * Indicates whether any FOs have been added to the body region * * @return whether any FOs have been added to the body region */ @@ -289,3 +294,4 @@ public class Page extends AreaTreeObject implements Serializable, Cloneable { } + diff --git a/src/java/org/apache/fop/area/RegionReference.java b/src/java/org/apache/fop/area/RegionReference.java index c41de7c7a..467aadd85 100644 --- a/src/java/org/apache/fop/area/RegionReference.java +++ b/src/java/org/apache/fop/area/RegionReference.java @@ -73,6 +73,18 @@ public class RegionReference extends Area implements Cloneable { blocks.add(child); } + /** {@inheritDoc} */ + public int getBPD() { + // subtract bpd of borders and padding before / after + return super.getBPD() - getBorderAndPaddingWidthBefore() - getBorderAndPaddingWidthAfter(); + } + + /** {@inheritDoc} */ + public int getIPD() { + // subtract ipd of borders and padding start / end + return super.getIPD() - getBorderAndPaddingWidthStart() - getBorderAndPaddingWidthEnd(); + } + /** * Set the Coordinate Transformation Matrix which transforms content * coordinates in this region reference area which are specified in @@ -133,7 +145,7 @@ public class RegionReference extends Area implements Cloneable { public void addBlock(Block block) { addChildArea(block); } - + /** * Clone this region. * This is used when cloning the page by the page master. diff --git a/src/java/org/apache/fop/area/inline/Character.java b/src/java/org/apache/fop/area/inline/Character.java deleted file mode 100644 index 6b6f9744f..000000000 --- a/src/java/org/apache/fop/area/inline/Character.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.area.inline; - -/** - * Single character inline area. - * This inline area holds a single character. - * @deprecated A TextArea with a single WordArea as its child should be used instead. - */ -public class Character extends AbstractTextArea { - // use a String instead of a character because if this character - // ends a syllable the hyphenation character must be added - private String character; - - /** - * Create a new character inline area with the given character. - * - * @param ch the character for this inline area - */ - public Character(char ch) { - character = new String() + ch; - } - - /** - * Get the character for this inline character area. - * - * @return the character - */ - public String getChar() { - return character; - } - - /** - * Add the hyphenation character and its length. - * - * @param hyphChar the hyphenation character - * @param hyphSize the size of the hyphenation character - */ - public void addHyphen(char hyphChar, int hyphSize) { - character += hyphChar; - this.setIPD(this.getIPD() + hyphSize); - } - -} - diff --git a/src/java/org/apache/fop/area/inline/InlineArea.java b/src/java/org/apache/fop/area/inline/InlineArea.java index 0655cabe4..10ea4e304 100644 --- a/src/java/org/apache/fop/area/inline/InlineArea.java +++ b/src/java/org/apache/fop/area/inline/InlineArea.java @@ -182,22 +182,22 @@ public class InlineArea extends Area { *@return true if the inline area is underlined. */ public boolean hasUnderline() { - return getBooleanTrait(Trait.UNDERLINE); + return getTraitAsBoolean(Trait.UNDERLINE); } /** @return true if the inline area is overlined. */ public boolean hasOverline() { - return getBooleanTrait(Trait.OVERLINE); + return getTraitAsBoolean(Trait.OVERLINE); } /** @return true if the inline area has a line through. */ public boolean hasLineThrough() { - return getBooleanTrait(Trait.LINETHROUGH); + return getTraitAsBoolean(Trait.LINETHROUGH); } /** @return true if the inline area is blinking. */ public boolean isBlinking() { - return getBooleanTrait(Trait.BLINK); + return getTraitAsBoolean(Trait.BLINK); } /** diff --git a/src/java/org/apache/fop/events/EventExceptionManager.java b/src/java/org/apache/fop/events/EventExceptionManager.java index 093ae7010..44b1ef7b1 100644 --- a/src/java/org/apache/fop/events/EventExceptionManager.java +++ b/src/java/org/apache/fop/events/EventExceptionManager.java @@ -25,7 +25,7 @@ import java.util.Map; import org.apache.xmlgraphics.util.Service; /** - * This class is reponsible for converting events into exceptions. + * This class is responsible for converting events into exceptions. */ public class EventExceptionManager { diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml index 4bff75f85..3e6cc181e 100644 --- a/src/java/org/apache/fop/events/EventFormatter.xml +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -65,6 +65,7 @@ Any reference to it will be considered a reference to the first occurrence in th <message key="org.apache.fop.fo.flow.table.TableEventProducer.warnImplicitColumns">table-layout=\"fixed\" and column-width unspecified => falling back to proportional-column-width(1){{locator}}</message> <message key="org.apache.fop.fo.flow.table.TableEventProducer.paddingNotApplicable">padding-* properties are not applicable to {elementName}, but a non-zero value for padding was found.{{locator}}</message> <message key="org.apache.fop.fo.flow.table.TableEventProducer.cellOverlap">{elementName} overlaps in column {column}.<!-- no locator here, exception will be wrapped --></message> + <message key="org.apache.fop.fo.flow.table.TableEventProducer.forceNextColumnNumber">Negative value {propValue} of property column-number of element {elementName} forced into the next available column number {columnNumber}.{{locator}}</message> <message key="org.apache.fop.fo.flow.table.TableEventProducer.breakIgnoredDueToRowSpanning">{breakBefore,if,break-before,break-after} ignored on {elementName} because of row spanning in progress (See XSL 1.1, {breakBefore,if,7.20.2,7.20.1}){{locator}}</message> <message key="org.apache.fop.events.ResourceEventProducer.imageNotFound">Image not found.[ URI: {uri}.]{{locator}}</message> <message key="org.apache.fop.events.ResourceEventProducer.imageError">Image not available.[ URI: {uri}.] Reason:[ {reason}][ {e}]{{locator}}</message> diff --git a/src/java/org/apache/fop/events/EventListener.java b/src/java/org/apache/fop/events/EventListener.java index f8293aed9..cb2d8b965 100644 --- a/src/java/org/apache/fop/events/EventListener.java +++ b/src/java/org/apache/fop/events/EventListener.java @@ -28,7 +28,7 @@ public interface EventListener extends java.util.EventListener { * This method is called for each event that is generated. With the event's ID it is possible * to react to certain events. Events can also simply be recorded and presented to a user. * It is possible to throw an (unchecked) exception if the processing needs to be aborted - * because some special event occured. This way the client can configure the behaviour of + * because some special event occurred. This way the client can configure the behaviour of * the observed application. * @param event the event */ diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java index 2a7f7e0c9..ae4c11229 100644 --- a/src/java/org/apache/fop/fo/Constants.java +++ b/src/java/org/apache/fop/fo/Constants.java @@ -24,9 +24,9 @@ package org.apache.fop.fo; * There are sets of constants describing: * <ul> * <li>Input and output formats</li> - * <li>Formatting objects</li> - * <li>Formatting properties</li> - * <li>Enumerated values used in formatting properties</li> + * <li>Formatting objects (<em>FO_XXX</em>)</li> + * <li>Formatting properties (<em>PR_XXX</em>)</li> + * <li>Enumerated values used in formatting properties (<em>EN_XXX</em>)</li> * </ul> */ public interface Constants { @@ -45,124 +45,162 @@ public interface Constants { int FO_BLOCK = 3; /** FO element constant */ int FO_BLOCK_CONTAINER = 4; + /** FO element constant - XSL 1.1 */ + int FO_BOOKMARK_TREE = 5; + /** FO element constant - XSL 1.1 */ + int FO_BOOKMARK = 6; + /** FO element constant - XSL 1.1 */ + int FO_BOOKMARK_TITLE = 7; + /** FO element constant - XSL 1.1 */ + int FO_CHANGE_BAR_BEGIN = 8; + /** FO element constant - XSL 1.1 */ + int FO_CHANGE_BAR_END = 9; /** FO element constant */ - int FO_CHARACTER = 5; + int FO_CHARACTER = 10; /** FO element constant */ - int FO_COLOR_PROFILE = 6; + int FO_COLOR_PROFILE = 11; /** FO element constant */ - int FO_CONDITIONAL_PAGE_MASTER_REFERENCE = 7; + int FO_CONDITIONAL_PAGE_MASTER_REFERENCE = 12; /** FO element constant */ - int FO_DECLARATIONS = 8; + int FO_DECLARATIONS = 13; /** FO element constant */ - int FO_EXTERNAL_GRAPHIC = 9; + int FO_EXTERNAL_GRAPHIC = 14; /** FO element constant */ - int FO_FLOAT = 10; + int FO_FLOAT = 15; /** FO element constant */ - int FO_FLOW = 11; + int FO_FLOW = 16; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_ASSIGNMENT = 17; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_MAP = 18; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_NAME_SPECIFIER = 19; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_SOURCE_LIST = 20; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_TARGET_LIST = 21; + /** FO element constant - XSL 1.1 */ + int FO_FOLIO_PREFIX = 22; + /** FO element constant - XSL 1.1 */ + int FO_FOLIO_SUFFIX = 23; /** FO element constant */ - int FO_FOOTNOTE = 12; + int FO_FOOTNOTE = 24; /** FO element constant */ - int FO_FOOTNOTE_BODY = 13; + int FO_FOOTNOTE_BODY = 25; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_KEY_REFERENCE = 26; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_NUMBER_PREFIX = 27; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_NUMBER_SUFFIX = 28; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_CITATION_LIST = 29; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_CITATION_LIST_SEPARATOR = 30; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_CITATION_RANGE_SEPARATOR = 31; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_RANGE_BEGIN = 32; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_RANGE_END = 33; /** FO element constant */ - int FO_INITIAL_PROPERTY_SET = 14; + int FO_INITIAL_PROPERTY_SET = 34; /** FO element constant */ - int FO_INLINE = 15; + int FO_INLINE = 35; /** FO element constant */ - int FO_INLINE_CONTAINER = 16; + int FO_INLINE_CONTAINER = 36; /** FO element constant */ - int FO_INSTREAM_FOREIGN_OBJECT = 17; + int FO_INSTREAM_FOREIGN_OBJECT = 37; /** FO element constant */ - int FO_LAYOUT_MASTER_SET = 18; + int FO_LAYOUT_MASTER_SET = 38; /** FO element constant */ - int FO_LEADER = 19; + int FO_LEADER = 39; /** FO element constant */ - int FO_LIST_BLOCK = 20; + int FO_LIST_BLOCK = 40; /** FO element constant */ - int FO_LIST_ITEM = 21; + int FO_LIST_ITEM = 41; /** FO element constant */ - int FO_LIST_ITEM_BODY = 22; + int FO_LIST_ITEM_BODY = 42; /** FO element constant */ - int FO_LIST_ITEM_LABEL = 23; + int FO_LIST_ITEM_LABEL = 43; /** FO element constant */ - int FO_MARKER = 24; + int FO_MARKER = 44; /** FO element constant */ - int FO_MULTI_CASE = 25; + int FO_MULTI_CASE = 45; /** FO element constant */ - int FO_MULTI_PROPERTIES = 26; + int FO_MULTI_PROPERTIES = 46; /** FO element constant */ - int FO_MULTI_PROPERTY_SET = 27; + int FO_MULTI_PROPERTY_SET = 47; /** FO element constant */ - int FO_MULTI_SWITCH = 28; + int FO_MULTI_SWITCH = 48; /** FO element constant */ - int FO_MULTI_TOGGLE = 29; + int FO_MULTI_TOGGLE = 49; /** FO element constant */ - int FO_PAGE_NUMBER = 30; + int FO_PAGE_NUMBER = 50; /** FO element constant */ - int FO_PAGE_NUMBER_CITATION = 31; + int FO_PAGE_NUMBER_CITATION = 51; + /** FO element constant - XSL 1.1 */ + int FO_PAGE_NUMBER_CITATION_LAST = 52; /** FO element constant */ - int FO_PAGE_SEQUENCE = 32; + int FO_PAGE_SEQUENCE = 53; /** FO element constant */ - int FO_PAGE_SEQUENCE_MASTER = 33; + int FO_PAGE_SEQUENCE_MASTER = 54; + /** FO element constant - XSL 1.1 */ + int FO_PAGE_SEQUENCE_WRAPPER = 55; /** FO element constant */ - int FO_REGION_AFTER = 34; + int FO_REGION_AFTER = 56; /** FO element constant */ - int FO_REGION_BEFORE = 35; + int FO_REGION_BEFORE = 57; /** FO element constant */ - int FO_REGION_BODY = 36; + int FO_REGION_BODY = 58; /** FO element constant */ - int FO_REGION_END = 37; + int FO_REGION_END = 59; + /** FO element constant - XSL 1.1 */ + int FO_REGION_NAME_SPECIFIER = 60; /** FO element constant */ - int FO_REGION_START = 38; + int FO_REGION_START = 61; /** FO element constant */ - int FO_REPEATABLE_PAGE_MASTER_ALTERNATIVES = 39; + int FO_REPEATABLE_PAGE_MASTER_ALTERNATIVES = 62; /** FO element constant */ - int FO_REPEATABLE_PAGE_MASTER_REFERENCE = 40; + int FO_REPEATABLE_PAGE_MASTER_REFERENCE = 63; /** FO element constant */ - int FO_RETRIEVE_MARKER = 41; + int FO_RETRIEVE_MARKER = 64; + /** FO element constant - XSL 1.1 */ + int FO_RETRIEVE_TABLE_MARKER = 65; /** FO element constant */ - int FO_ROOT = 42; + int FO_ROOT = 66; + /** FO element constant - XSL 1.1 */ + int FO_SCALING_VALUE_CITATION = 67; /** FO element constant */ - int FO_SIMPLE_PAGE_MASTER = 43; + int FO_SIMPLE_PAGE_MASTER = 68; /** FO element constant */ - int FO_SINGLE_PAGE_MASTER_REFERENCE = 44; + int FO_SINGLE_PAGE_MASTER_REFERENCE = 69; /** FO element constant */ - int FO_STATIC_CONTENT = 45; + int FO_STATIC_CONTENT = 70; /** FO element constant */ - int FO_TABLE = 46; + int FO_TABLE = 71; /** FO element constant */ - int FO_TABLE_AND_CAPTION = 47; + int FO_TABLE_AND_CAPTION = 72; /** FO element constant */ - int FO_TABLE_BODY = 48; + int FO_TABLE_BODY = 73; /** FO element constant */ - int FO_TABLE_CAPTION = 49; + int FO_TABLE_CAPTION = 74; /** FO element constant */ - int FO_TABLE_CELL = 50; + int FO_TABLE_CELL = 75; /** FO element constant */ - int FO_TABLE_COLUMN = 51; + int FO_TABLE_COLUMN = 76; /** FO element constant */ - int FO_TABLE_FOOTER = 52; + int FO_TABLE_FOOTER = 77; /** FO element constant */ - int FO_TABLE_HEADER = 53; + int FO_TABLE_HEADER = 78; /** FO element constant */ - int FO_TABLE_ROW = 54; + int FO_TABLE_ROW = 79; /** FO element constant */ - int FO_TITLE = 55; + int FO_TITLE = 80; /** FO element constant */ - int FO_WRAPPER = 56; - /** FO element constant - XSL 1.1 */ - int FO_BOOKMARK_TREE = 57; - /** FO element constant - XSL 1.1 */ - int FO_BOOKMARK = 58; - /** FO element constant - XSL 1.1 */ - int FO_BOOKMARK_TITLE = 59; - /** FO element constant - XSL 1.1 */ - int FO_PAGE_SEQUENCE_WRAPPER = 60; - /** FO element constant - XSL 1.1 */ - int FO_PAGE_NUMBER_CITATION_LAST = 61; - /** FO element constant - XSL 1.1 */ - int FO_RETRIEVE_TABLE_MARKER = 62; + int FO_WRAPPER = 81; /** Number of FO element constants defined */ - int FRM_OBJ_COUNT = 62; + int FRM_OBJ_COUNT = 81; // Masks /** @@ -308,394 +346,428 @@ public interface Constants { int PR_CASE_NAME = 61; /** Property constant */ int PR_CASE_TITLE = 62; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_CLASS = 63; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_COLOR = 64; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_OFFSET = 65; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_PLACEMENT = 66; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_STYLE = 67; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_WIDTH = 68; /** Property constant */ - int PR_CHARACTER = 63; + int PR_CHARACTER = 69; /** Property constant */ - int PR_CLEAR = 64; + int PR_CLEAR = 70; /** Property constant */ - int PR_CLIP = 65; + int PR_CLIP = 71; /** Property constant */ - int PR_COLOR = 66; + int PR_COLOR = 72; /** Property constant */ - int PR_COLOR_PROFILE_NAME = 67; + int PR_COLOR_PROFILE_NAME = 73; /** Property constant */ - int PR_COLUMN_COUNT = 68; + int PR_COLUMN_COUNT = 74; /** Property constant */ - int PR_COLUMN_GAP = 69; + int PR_COLUMN_GAP = 75; /** Property constant */ - int PR_COLUMN_NUMBER = 70; + int PR_COLUMN_NUMBER = 76; /** Property constant */ - int PR_COLUMN_WIDTH = 71; + int PR_COLUMN_WIDTH = 77; /** Property constant */ - int PR_CONTENT_HEIGHT = 72; + int PR_CONTENT_HEIGHT = 78; /** Property constant */ - int PR_CONTENT_TYPE = 73; + int PR_CONTENT_TYPE = 79; /** Property constant */ - int PR_CONTENT_WIDTH = 74; + int PR_CONTENT_WIDTH = 80; /** Property constant */ - int PR_COUNTRY = 75; + int PR_COUNTRY = 81; /** Property constant */ - int PR_CUE = 76; + int PR_CUE = 82; /** Property constant */ - int PR_CUE_AFTER = 77; + int PR_CUE_AFTER = 83; /** Property constant */ - int PR_CUE_BEFORE = 78; + int PR_CUE_BEFORE = 84; /** Property constant */ - int PR_DESTINATION_PLACEMENT_OFFSET = 79; + int PR_DESTINATION_PLACEMENT_OFFSET = 85; /** Property constant */ - int PR_DIRECTION = 80; + int PR_DIRECTION = 86; /** Property constant */ - int PR_DISPLAY_ALIGN = 81; + int PR_DISPLAY_ALIGN = 87; /** Property constant */ - int PR_DOMINANT_BASELINE = 82; + int PR_DOMINANT_BASELINE = 88; /** Property constant */ - int PR_ELEVATION = 83; + int PR_ELEVATION = 89; /** Property constant */ - int PR_EMPTY_CELLS = 84; + int PR_EMPTY_CELLS = 90; /** Property constant */ - int PR_END_INDENT = 85; + int PR_END_INDENT = 91; /** Property constant */ - int PR_ENDS_ROW = 86; + int PR_ENDS_ROW = 92; /** Property constant */ - int PR_EXTENT = 87; + int PR_EXTENT = 93; /** Property constant */ - int PR_EXTERNAL_DESTINATION = 88; + int PR_EXTERNAL_DESTINATION = 94; /** Property constant */ - int PR_FLOAT = 89; + int PR_FLOAT = 95; + /** Property constant -- XSL 1.1 */ + int PR_FLOW_MAP_NAME = 96; + /** Property constant -- XSL 1.1 */ + int PR_FLOW_MAP_REFERENCE = 97; /** Property constant */ - int PR_FLOW_NAME = 90; + int PR_FLOW_NAME = 98; + /** Property constant -- XSL 1.1 */ + int PR_FLOW_NAME_REFERENCE = 99; /** Property constant */ - int PR_FONT = 91; + int PR_FONT = 100; /** Property constant */ - int PR_FONT_FAMILY = 92; + int PR_FONT_FAMILY = 101; /** Property constant */ - int PR_FONT_SELECTION_STRATEGY = 93; + int PR_FONT_SELECTION_STRATEGY = 102; /** Property constant */ - int PR_FONT_SIZE = 94; + int PR_FONT_SIZE = 103; /** Property constant */ - int PR_FONT_SIZE_ADJUST = 95; + int PR_FONT_SIZE_ADJUST = 104; /** Property constant */ - int PR_FONT_STRETCH = 96; + int PR_FONT_STRETCH = 105; /** Property constant */ - int PR_FONT_STYLE = 97; + int PR_FONT_STYLE = 106; /** Property constant */ - int PR_FONT_VARIANT = 98; + int PR_FONT_VARIANT = 107; /** Property constant */ - int PR_FONT_WEIGHT = 99; + int PR_FONT_WEIGHT = 108; /** Property constant */ - int PR_FORCE_PAGE_COUNT = 100; + int PR_FORCE_PAGE_COUNT = 109; /** Property constant */ - int PR_FORMAT = 101; + int PR_FORMAT = 110; /** Property constant */ - int PR_GLYPH_ORIENTATION_HORIZONTAL = 102; + int PR_GLYPH_ORIENTATION_HORIZONTAL = 111; /** Property constant */ - int PR_GLYPH_ORIENTATION_VERTICAL = 103; + int PR_GLYPH_ORIENTATION_VERTICAL = 112; /** Property constant */ - int PR_GROUPING_SEPARATOR = 104; + int PR_GROUPING_SEPARATOR = 113; /** Property constant */ - int PR_GROUPING_SIZE = 105; + int PR_GROUPING_SIZE = 114; /** Property constant */ - int PR_HEIGHT = 106; + int PR_HEIGHT = 115; /** Property constant */ - int PR_HYPHENATE = 107; + int PR_HYPHENATE = 116; /** Property constant */ - int PR_HYPHENATION_CHARACTER = 108; + int PR_HYPHENATION_CHARACTER = 117; /** Property constant */ - int PR_HYPHENATION_KEEP = 109; + int PR_HYPHENATION_KEEP = 118; /** Property constant */ - int PR_HYPHENATION_LADDER_COUNT = 110; + int PR_HYPHENATION_LADDER_COUNT = 119; /** Property constant */ - int PR_HYPHENATION_PUSH_CHARACTER_COUNT = 111; + int PR_HYPHENATION_PUSH_CHARACTER_COUNT = 120; /** Property constant */ - int PR_HYPHENATION_REMAIN_CHARACTER_COUNT = 112; + int PR_HYPHENATION_REMAIN_CHARACTER_COUNT = 121; /** Property constant */ - int PR_ID = 113; + int PR_ID = 122; /** Property constant */ - int PR_INDICATE_DESTINATION = 114; + int PR_INDICATE_DESTINATION = 123; + /** Property constant - XSL 1.1 */ + int PR_INDEX_CLASS = 124; + /** Property constant - XSL 1.1 */ + int PR_INDEX_KEY = 125; /** Property constant */ - int PR_INITIAL_PAGE_NUMBER = 115; + int PR_INITIAL_PAGE_NUMBER = 126; /** Property constant */ - int PR_INLINE_PROGRESSION_DIMENSION = 116; + int PR_INLINE_PROGRESSION_DIMENSION = 127; /** Property constant */ - int PR_INTERNAL_DESTINATION = 117; + int PR_INTERNAL_DESTINATION = 128; + /** Property constant - XSL 1.1 */ + int PR_INTRINSIC_SCALE_VALUE = 129; /** Property constant */ - int PR_KEEP_TOGETHER = 118; + int PR_INTRUSION_DISPLACE = 130; /** Property constant */ - int PR_KEEP_WITH_NEXT = 119; + int PR_KEEP_TOGETHER = 131; /** Property constant */ - int PR_KEEP_WITH_PREVIOUS = 120; + int PR_KEEP_WITH_NEXT = 132; /** Property constant */ - int PR_LANGUAGE = 121; + int PR_KEEP_WITH_PREVIOUS = 133; /** Property constant */ - int PR_LAST_LINE_END_INDENT = 122; + int PR_LANGUAGE = 134; /** Property constant */ - int PR_LEADER_ALIGNMENT = 123; + int PR_LAST_LINE_END_INDENT = 135; /** Property constant */ - int PR_LEADER_LENGTH = 124; + int PR_LEADER_ALIGNMENT = 136; /** Property constant */ - int PR_LEADER_PATTERN = 125; + int PR_LEADER_LENGTH = 137; /** Property constant */ - int PR_LEADER_PATTERN_WIDTH = 126; + int PR_LEADER_PATTERN = 138; /** Property constant */ - int PR_LEFT = 127; + int PR_LEADER_PATTERN_WIDTH = 139; /** Property constant */ - int PR_LETTER_SPACING = 128; + int PR_LEFT = 140; /** Property constant */ - int PR_LETTER_VALUE = 129; + int PR_LETTER_SPACING = 141; /** Property constant */ - int PR_LINEFEED_TREATMENT = 130; + int PR_LETTER_VALUE = 142; /** Property constant */ - int PR_LINE_HEIGHT = 131; + int PR_LINEFEED_TREATMENT = 143; /** Property constant */ - int PR_LINE_HEIGHT_SHIFT_ADJUSTMENT = 132; + int PR_LINE_HEIGHT = 144; /** Property constant */ - int PR_LINE_STACKING_STRATEGY = 133; + int PR_LINE_HEIGHT_SHIFT_ADJUSTMENT = 145; /** Property constant */ - int PR_MARGIN = 134; + int PR_LINE_STACKING_STRATEGY = 146; /** Property constant */ - int PR_MARGIN_BOTTOM = 135; + int PR_MARGIN = 147; /** Property constant */ - int PR_MARGIN_LEFT = 136; + int PR_MARGIN_BOTTOM = 148; /** Property constant */ - int PR_MARGIN_RIGHT = 137; + int PR_MARGIN_LEFT = 149; /** Property constant */ - int PR_MARGIN_TOP = 138; + int PR_MARGIN_RIGHT = 150; /** Property constant */ - int PR_MARKER_CLASS_NAME = 139; + int PR_MARGIN_TOP = 151; /** Property constant */ - int PR_MASTER_NAME = 140; + int PR_MARKER_CLASS_NAME = 152; /** Property constant */ - int PR_MASTER_REFERENCE = 141; + int PR_MASTER_NAME = 153; /** Property constant */ - int PR_MAX_HEIGHT = 142; + int PR_MASTER_REFERENCE = 154; /** Property constant */ - int PR_MAXIMUM_REPEATS = 143; + int PR_MAX_HEIGHT = 155; /** Property constant */ - int PR_MAX_WIDTH = 144; + int PR_MAXIMUM_REPEATS = 156; /** Property constant */ - int PR_MEDIA_USAGE = 145; + int PR_MAX_WIDTH = 157; + /** Property constant - XSL 1.1 */ + int PR_MERGE_PAGES_ACROSS_INDEX_KEY_REFERENCES = 158; + /** Property constant - XSL 1.1 */ + int PR_MERGE_RANGES_ACROSS_INDEX_KEY_REFERENCES = 159; + /** Property constant - XSL 1.1 */ + int PR_MERGE_SEQUENTIAL_PAGE_NUMBERS = 160; /** Property constant */ - int PR_MIN_HEIGHT = 146; + int PR_MEDIA_USAGE = 161; /** Property constant */ - int PR_MIN_WIDTH = 147; + int PR_MIN_HEIGHT = 162; /** Property constant */ - int PR_NUMBER_COLUMNS_REPEATED = 148; + int PR_MIN_WIDTH = 163; /** Property constant */ - int PR_NUMBER_COLUMNS_SPANNED = 149; + int PR_NUMBER_COLUMNS_REPEATED = 164; /** Property constant */ - int PR_NUMBER_ROWS_SPANNED = 150; + int PR_NUMBER_COLUMNS_SPANNED = 165; /** Property constant */ - int PR_ODD_OR_EVEN = 151; + int PR_NUMBER_ROWS_SPANNED = 166; /** Property constant */ - int PR_ORPHANS = 152; + int PR_ODD_OR_EVEN = 167; /** Property constant */ - int PR_OVERFLOW = 153; + int PR_ORPHANS = 168; /** Property constant */ - int PR_PADDING = 154; + int PR_OVERFLOW = 169; /** Property constant */ - int PR_PADDING_AFTER = 155; + int PR_PADDING = 170; /** Property constant */ - int PR_PADDING_BEFORE = 156; + int PR_PADDING_AFTER = 171; /** Property constant */ - int PR_PADDING_BOTTOM = 157; + int PR_PADDING_BEFORE = 172; /** Property constant */ - int PR_PADDING_END = 158; + int PR_PADDING_BOTTOM = 173; /** Property constant */ - int PR_PADDING_LEFT = 159; + int PR_PADDING_END = 174; /** Property constant */ - int PR_PADDING_RIGHT = 160; + int PR_PADDING_LEFT = 175; /** Property constant */ - int PR_PADDING_START = 161; + int PR_PADDING_RIGHT = 176; /** Property constant */ - int PR_PADDING_TOP = 162; + int PR_PADDING_START = 177; /** Property constant */ - int PR_PAGE_BREAK_AFTER = 163; + int PR_PADDING_TOP = 178; /** Property constant */ - int PR_PAGE_BREAK_BEFORE = 164; + int PR_PAGE_BREAK_AFTER = 179; /** Property constant */ - int PR_PAGE_BREAK_INSIDE = 165; + int PR_PAGE_BREAK_BEFORE = 180; /** Property constant */ - int PR_PAGE_HEIGHT = 166; + int PR_PAGE_BREAK_INSIDE = 181; + /** Property constant - XSL 1.1 */ + int PR_PAGE_CITATION_STRATEGY = 182; /** Property constant */ - int PR_PAGE_POSITION = 167; + int PR_PAGE_HEIGHT = 183; + /** Property constant - XSL 1.1 */ + int PR_PAGE_NUMBER_TREATMENT = 184; /** Property constant */ - int PR_PAGE_WIDTH = 168; + int PR_PAGE_POSITION = 185; /** Property constant */ - int PR_PAUSE = 169; + int PR_PAGE_WIDTH = 186; /** Property constant */ - int PR_PAUSE_AFTER = 170; + int PR_PAUSE = 187; /** Property constant */ - int PR_PAUSE_BEFORE = 171; + int PR_PAUSE_AFTER = 188; /** Property constant */ - int PR_PITCH = 172; + int PR_PAUSE_BEFORE = 189; /** Property constant */ - int PR_PITCH_RANGE = 173; + int PR_PITCH = 190; /** Property constant */ - int PR_PLAY_DURING = 174; + int PR_PITCH_RANGE = 191; /** Property constant */ - int PR_POSITION = 175; + int PR_PLAY_DURING = 192; /** Property constant */ - int PR_PRECEDENCE = 176; + int PR_POSITION = 193; /** Property constant */ - int PR_PROVISIONAL_DISTANCE_BETWEEN_STARTS = 177; + int PR_PRECEDENCE = 194; /** Property constant */ - int PR_PROVISIONAL_LABEL_SEPARATION = 178; + int PR_PROVISIONAL_DISTANCE_BETWEEN_STARTS = 195; /** Property constant */ - int PR_REFERENCE_ORIENTATION = 179; + int PR_PROVISIONAL_LABEL_SEPARATION = 196; /** Property constant */ - int PR_REF_ID = 180; + int PR_REFERENCE_ORIENTATION = 197; /** Property constant */ - int PR_REGION_NAME = 181; + int PR_REF_ID = 198; /** Property constant */ - int PR_RELATIVE_ALIGN = 182; + int PR_REGION_NAME = 199; + /** Property constant - XSL 1.1 */ + int PR_REGION_NAME_REFERENCE = 200; + /** Property constant - XSL 1.1 */ + int PR_REF_INDEX_KEY = 201; /** Property constant */ - int PR_RELATIVE_POSITION = 183; + int PR_RELATIVE_ALIGN = 202; /** Property constant */ - int PR_RENDERING_INTENT = 184; + int PR_RELATIVE_POSITION = 203; /** Property constant */ - int PR_RETRIEVE_BOUNDARY = 185; + int PR_RENDERING_INTENT = 204; /** Property constant */ - int PR_RETRIEVE_CLASS_NAME = 186; + int PR_RETRIEVE_BOUNDARY = 205; + /** Property constant - XSL 1.1 */ + int PR_RETRIEVE_BOUNDARY_WITHIN_TABLE = 206; /** Property constant */ - int PR_RETRIEVE_POSITION = 187; + int PR_RETRIEVE_CLASS_NAME = 207; /** Property constant */ - int PR_RICHNESS = 188; + int PR_RETRIEVE_POSITION = 208; + /** Property constant - XSL 1.1 */ + int PR_RETRIEVE_POSITION_WITHIN_TABLE = 209; /** Property constant */ - int PR_RIGHT = 189; + int PR_RICHNESS = 210; /** Property constant */ - int PR_ROLE = 190; + int PR_RIGHT = 211; /** Property constant */ - int PR_RULE_STYLE = 191; + int PR_ROLE = 212; /** Property constant */ - int PR_RULE_THICKNESS = 192; + int PR_RULE_STYLE = 213; /** Property constant */ - int PR_SCALING = 193; + int PR_RULE_THICKNESS = 214; /** Property constant */ - int PR_SCALING_METHOD = 194; + int PR_SCALING = 215; /** Property constant */ - int PR_SCORE_SPACES = 195; + int PR_SCALING_METHOD = 216; /** Property constant */ - int PR_SCRIPT = 196; + int PR_SCORE_SPACES = 217; /** Property constant */ - int PR_SHOW_DESTINATION = 197; + int PR_SCRIPT = 218; /** Property constant */ - int PR_SIZE = 198; + int PR_SHOW_DESTINATION = 219; /** Property constant */ - int PR_SOURCE_DOCUMENT = 199; + int PR_SIZE = 220; /** Property constant */ - int PR_SPACE_AFTER = 200; + int PR_SOURCE_DOCUMENT = 221; /** Property constant */ - int PR_SPACE_BEFORE = 201; + int PR_SPACE_AFTER = 222; /** Property constant */ - int PR_SPACE_END = 202; + int PR_SPACE_BEFORE = 223; /** Property constant */ - int PR_SPACE_START = 203; + int PR_SPACE_END = 224; /** Property constant */ - int PR_SPAN = 204; + int PR_SPACE_START = 225; /** Property constant */ - int PR_SPEAK = 205; + int PR_SPAN = 226; /** Property constant */ - int PR_SPEAK_HEADER = 206; + int PR_SPEAK = 227; /** Property constant */ - int PR_SPEAK_NUMERAL = 207; + int PR_SPEAK_HEADER = 228; /** Property constant */ - int PR_SPEAK_PUNCTUATION = 208; + int PR_SPEAK_NUMERAL = 229; /** Property constant */ - int PR_SPEECH_RATE = 209; + int PR_SPEAK_PUNCTUATION = 230; /** Property constant */ - int PR_SRC = 210; + int PR_SPEECH_RATE = 231; /** Property constant */ - int PR_START_INDENT = 211; + int PR_SRC = 232; /** Property constant */ - int PR_STARTING_STATE = 212; + int PR_START_INDENT = 233; /** Property constant */ - int PR_STARTS_ROW = 213; + int PR_STARTING_STATE = 234; /** Property constant */ - int PR_STRESS = 214; + int PR_STARTS_ROW = 235; /** Property constant */ - int PR_SUPPRESS_AT_LINE_BREAK = 215; + int PR_STRESS = 236; /** Property constant */ - int PR_SWITCH_TO = 216; + int PR_SUPPRESS_AT_LINE_BREAK = 237; /** Property constant */ - int PR_TABLE_LAYOUT = 217; + int PR_SWITCH_TO = 238; /** Property constant */ - int PR_TABLE_OMIT_FOOTER_AT_BREAK = 218; + int PR_TABLE_LAYOUT = 239; /** Property constant */ - int PR_TABLE_OMIT_HEADER_AT_BREAK = 219; + int PR_TABLE_OMIT_FOOTER_AT_BREAK = 240; /** Property constant */ - int PR_TARGET_PRESENTATION_CONTEXT = 220; + int PR_TABLE_OMIT_HEADER_AT_BREAK = 241; /** Property constant */ - int PR_TARGET_PROCESSING_CONTEXT = 221; + int PR_TARGET_PRESENTATION_CONTEXT = 242; /** Property constant */ - int PR_TARGET_STYLESHEET = 222; + int PR_TARGET_PROCESSING_CONTEXT = 243; /** Property constant */ - int PR_TEXT_ALIGN = 223; + int PR_TARGET_STYLESHEET = 244; /** Property constant */ - int PR_TEXT_ALIGN_LAST = 224; + int PR_TEXT_ALIGN = 245; /** Property constant */ - int PR_TEXT_ALTITUDE = 225; + int PR_TEXT_ALIGN_LAST = 246; /** Property constant */ - int PR_TEXT_DECORATION = 226; + int PR_TEXT_ALTITUDE = 247; /** Property constant */ - int PR_TEXT_DEPTH = 227; + int PR_TEXT_DECORATION = 248; /** Property constant */ - int PR_TEXT_INDENT = 228; + int PR_TEXT_DEPTH = 249; /** Property constant */ - int PR_TEXT_SHADOW = 229; + int PR_TEXT_INDENT = 250; /** Property constant */ - int PR_TEXT_TRANSFORM = 230; + int PR_TEXT_SHADOW = 251; /** Property constant */ - int PR_TOP = 231; + int PR_TEXT_TRANSFORM = 252; /** Property constant */ - int PR_TREAT_AS_WORD_SPACE = 232; + int PR_TOP = 253; /** Property constant */ - int PR_UNICODE_BIDI = 233; + int PR_TREAT_AS_WORD_SPACE = 254; /** Property constant */ - int PR_VERTICAL_ALIGN = 234; + int PR_UNICODE_BIDI = 255; /** Property constant */ - int PR_VISIBILITY = 235; + int PR_VERTICAL_ALIGN = 256; /** Property constant */ - int PR_VOICE_FAMILY = 236; + int PR_VISIBILITY = 257; /** Property constant */ - int PR_VOLUME = 237; + int PR_VOICE_FAMILY = 258; /** Property constant */ - int PR_WHITE_SPACE = 238; + int PR_VOLUME = 259; /** Property constant */ - int PR_WHITE_SPACE_COLLAPSE = 239; + int PR_WHITE_SPACE = 260; /** Property constant */ - int PR_WHITE_SPACE_TREATMENT = 240; + int PR_WHITE_SPACE_COLLAPSE = 261; /** Property constant */ - int PR_WIDOWS = 241; + int PR_WHITE_SPACE_TREATMENT = 262; /** Property constant */ - int PR_WIDTH = 242; + int PR_WIDOWS = 263; /** Property constant */ - int PR_WORD_SPACING = 243; + int PR_WIDTH = 264; /** Property constant */ - int PR_WRAP_OPTION = 244; + int PR_WORD_SPACING = 265; /** Property constant */ - int PR_WRITING_MODE = 245; + int PR_WRAP_OPTION = 266; /** Property constant */ - int PR_XML_LANG = 246; + int PR_WRITING_MODE = 267; /** Property constant */ - int PR_Z_INDEX = 247; + int PR_XML_LANG = 268; /** Property constant */ - int PR_INTRUSION_DISPLACE = 248; - /** Property constant - XSL 1.1 */ - int PR_INDEX_CLASS = 249; - /** Property constant - XSL 1.1 */ - int PR_INDEX_KEY = 250; + int PR_Z_INDEX = 269; /** Property constant - FOP proprietary: Custom extension for line alignment */ - int PR_X_BLOCK_PROGRESSION_UNIT = 251; + int PR_X_BLOCK_PROGRESSION_UNIT = 270; /** Property constant - FOP proprietary: limit for widow content in lists and tables */ - int PR_X_WIDOW_CONTENT_LIMIT = 252; + int PR_X_WIDOW_CONTENT_LIMIT = 271; /** Property constant - FOP proprietary: limit for orphan content in lists and tables */ - int PR_X_ORPHAN_CONTENT_LIMIT = 253; - /** Property constant */ - int PR_RETRIEVE_POSITION_WITHIN_TABLE = 254; - /** Property constant */ - int PR_RETRIEVE_BOUNDARY_WITHIN_TABLE = 255; + int PR_X_ORPHAN_CONTENT_LIMIT = 272; /** Number of property constants defined */ - int PROPERTY_COUNT = 255; + int PROPERTY_COUNT = 272; // compound property constants @@ -1113,6 +1185,16 @@ public interface Constants { int EN_TABLE = 194; /** Enumeration constant -- for fo:retrieve-table-marker */ int EN_TABLE_FRAGMENT = 195; + /** Enumeration constant -- XSL 1.1 */ + int EN_MERGE = 196; + /** Enumeration constant -- XSL 1.1 */ + int EN_LEAVE_SEPARATE = 197; + /** Enumeration constant -- XSL 1.1 */ + int EN_LINK = 198; + /** Enumeration constant -- XSL 1.1 */ + int EN_NO_LINK = 199; + /** Enumeration constant -- XSL 1.1 */ + int EN_ALTERNATE = 200; /** Number of enumeration constants defined */ - int ENUM_COUNT = 195; + int ENUM_COUNT = 200; } diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index 7521d398c..90856d57a 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -19,9 +19,6 @@ package org.apache.fop.fo; -import java.util.HashSet; -import java.util.Set; - import org.xml.sax.SAXException; import org.apache.fop.apps.FOUserAgent; @@ -43,6 +40,9 @@ import org.apache.fop.fo.flow.PageNumberCitation; import org.apache.fop.fo.flow.PageNumberCitationLast; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TableFooter; +import org.apache.fop.fo.flow.table.TableHeader; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableRow; @@ -75,27 +75,6 @@ public abstract class FOEventHandler { protected FontInfo fontInfo; /** - * The current set of id's in the FO tree. - * This is used so we know if the FO tree contains duplicates. - */ - private Set idReferences = new HashSet(); - - /** - * The property list maker. - */ - protected PropertyListMaker propertyListMaker; - - /** - * The XMLWhitespaceHandler for this tree - */ - protected XMLWhiteSpaceHandler whiteSpaceHandler = new XMLWhiteSpaceHandler(); - - /** - * Indicates whether processing descendants of a marker - */ - private boolean inMarker = false; - - /** * Main constructor * @param foUserAgent the apps.FOUserAgent instance for this process */ @@ -106,14 +85,6 @@ public abstract class FOEventHandler { } /** - * Retuns the set of ID references. - * @return the ID references - */ - public Set getIDReferences() { - return idReferences; - } - - /** * Returns the User Agent object associated with this FOEventHandler. * @return the User Agent object */ @@ -130,54 +101,6 @@ public abstract class FOEventHandler { } /** - * Return the propertyListMaker. - * - * @return the currently active {@link PropertyListMaker} - */ - public PropertyListMaker getPropertyListMaker() { - return propertyListMaker; - } - - /** - * Set a new propertyListMaker. - * - * @param propertyListMaker the new {@link PropertyListMaker} to use - */ - public void setPropertyListMaker(PropertyListMaker propertyListMaker) { - this.propertyListMaker = propertyListMaker; - } - - /** - * Return the XMLWhiteSpaceHandler - * @return the whiteSpaceHandler - */ - public XMLWhiteSpaceHandler getXMLWhiteSpaceHandler() { - return whiteSpaceHandler; - } - - /** - * Switch to or from marker context - * (used by FOTreeBuilder when processing - * a marker) - * - * @param inMarker true if a marker is being processed; - * false otherwise - * - */ - protected void switchMarkerContext(boolean inMarker) { - this.inMarker = inMarker; - } - - /** - * Check whether in marker context - * - * @return true if a marker is being processed - */ - protected boolean inMarker() { - return this.inMarker; - } - - /** * This method is called to indicate the start of a new document run. * @throws SAXException In case of a problem */ @@ -337,44 +260,44 @@ public abstract class FOEventHandler { /** * - * @param th TableBody that is starting; + * @param header TableHeader that is starting; */ - public void startHeader(TableBody th) { + public void startHeader(TableHeader header) { } /** * - * @param th TableBody that is ending. + * @param header TableHeader that is ending. */ - public void endHeader(TableBody th) { + public void endHeader(TableHeader header) { } /** * - * @param tf TableFooter that is starting. + * @param footer TableFooter that is starting. */ - public void startFooter(TableBody tf) { + public void startFooter(TableFooter footer) { } /** * - * @param tf TableFooter that is ending. + * @param footer TableFooter that is ending. */ - public void endFooter(TableBody tf) { + public void endFooter(TableFooter footer) { } /** * - * @param tb TableBody that is starting. + * @param body TableBody that is starting. */ - public void startBody(TableBody tb) { + public void startBody(TableBody body) { } /** * - * @param tb TableBody that is ending. + * @param body TableBody that is ending. */ - public void endBody(TableBody tb) { + public void endBody(TableBody body) { } /** @@ -566,7 +489,7 @@ public abstract class FOEventHandler { * @param start Offset for characters to process. * @param length Portion of array to process. */ - public void characters(char data[], int start, int length) { + public void characters(char[] data, int start, int length) { } /** diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index 951e4c430..87d3bfa3c 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -22,7 +22,6 @@ package org.apache.fop.fo; // Java import java.util.ListIterator; import java.util.Map; -import java.util.NoSuchElementException; import org.xml.sax.Attributes; import org.xml.sax.Locator; @@ -158,11 +157,19 @@ public abstract class FONode implements Cloneable { } /** + * Returns the context class providing information used during FO tree building. + * @return the builder context + */ + public FOTreeBuilderContext getBuilderContext() { + return parent.getBuilderContext(); + } + + /** * Indicates whether this node is a child of an fo:marker. * @return true if this node is a child of an fo:marker */ protected boolean inMarker() { - return getFOEventHandler().inMarker(); + return getBuilderContext().inMarker(); } /** @@ -267,12 +274,12 @@ public abstract class FONode implements Cloneable { * * @param data array of characters containing text to be added * @param start starting array element to add - * @param end ending array element to add + * @param length number of elements to add * @param pList currently applicable PropertyList * @param locator location in the XSL-FO source file. * @throws FOPException if there's a problem during processing */ - protected void addCharacters(char[] data, int start, int end, + protected void addCharacters(char[] data, int start, int length, PropertyList pList, Locator locator) throws FOPException { // ignore @@ -291,11 +298,16 @@ public abstract class FONode implements Cloneable { * Primarily used for making final content model validation checks * and/or informing the {@link FOEventHandler} that the end of this FO * has been reached. + * The default implementation simply calls {@link #finalizeNode()}, without + * sending any event to the {@link FOEventHandler}. + * <br/><i>Note: the recommended way to override this method in subclasses is</i> + * <br/><br/><code>super.endOfNode(); // invoke finalizeNode() + * <br/>getFOEventHandler().endXXX(); // send endOfNode() notification</code> * * @throws FOPException if there's a problem during processing */ protected void endOfNode() throws FOPException { - // do nothing by default + this.finalizeNode(); } /** @@ -320,6 +332,20 @@ public abstract class FONode implements Cloneable { } /** + * Finalize this node. + * This method can be overridden by subclasses to perform finishing + * tasks (cleanup, validation checks, ...) without triggering + * endXXX() events in the {@link FOEventHandler}. + * The method is called by the default {@link #endOfNode()} + * implementation. + * + * @throws FOPException in case there was an error + */ + public void finalizeNode() throws FOPException { + // do nothing by default + } + + /** * Return the parent node of this node * * @return the parent node of this node diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index 8c85bb039..217997ace 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -20,6 +20,7 @@ package org.apache.fop.fo; import java.awt.Color; +import java.nio.CharBuffer; import java.util.NoSuchElementException; import org.xml.sax.Locator; @@ -33,48 +34,17 @@ import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.SpaceProperty; +import org.apache.fop.util.CharUtilities; /** * A text node (PCDATA) in the formatting object tree. - * - * Unfortunately the BufferManager implementatation holds - * onto references to the character data in this object - * longer than the lifetime of the object itself, causing - * excessive memory consumption and OOM errors. */ -public class FOText extends FONode { +public class FOText extends FONode implements CharSequence { - /** - * the character array containing the text - */ - public char[] ca; - - /** - * The starting valid index of the ca array - * to be processed. - * - * This value is originally equal to 0, but becomes - * incremented during leading whitespace removal by the flow.Block class, - * via the TextCharIterator.remove() method below. - */ - public int startIndex = 0; + /** the <code>CharBuffer</code> containing the text */ + private CharBuffer charBuffer; - /** - * The ending valid index of the ca array - * to be processed. - * - * This value is originally equal to ca.length, but becomes - * decremented during between-word whitespace removal by the - * XMLWhiteSpaceHandler via the TextCharIterator.remove() - * method below. - */ - public int endIndex = 0; - - /** properties relevant for PCDATA */ - /* TODO: these are basically always the same as the parent FObj or FObjMixed - * so maybe those can be removed, and the accessors could - * dispatch the call to the parent? - */ + /** properties relevant for #PCDATA */ private CommonFont commonFont; private CommonHyphenation commonHyphenation; private Color color; @@ -105,10 +75,10 @@ public class FOText extends FONode { * which FOText nodes are descendants of the same block. */ private Block ancestorBlock = null; - + /** Holds the text decoration values. May be null */ private CommonTextDecoration textDecoration; - + private static final int IS_WORD_CHAR_FALSE = 0; private static final int IS_WORD_CHAR_TRUE = 1; private static final int IS_WORD_CHAR_MAYBE = 2; @@ -123,37 +93,61 @@ public class FOText extends FONode { } /** {@inheritDoc} */ - protected void addCharacters(char[] data, int start, int end, + protected void addCharacters(char[] data, int start, int length, PropertyList list, Locator locator) throws FOPException { - int length = end - start; - int calength = 0; - char[] nca; - if (ca != null) { - calength = ca.length; - nca = new char[calength + length]; - System.arraycopy(ca, 0, nca, 0, calength); + if (this.charBuffer == null) { + // buffer not yet initialized, do so now + this.charBuffer = CharBuffer.allocate(length); } else { - nca = new char[length]; + // allocate a larger buffer, and transfer contents + int newLength = this.charBuffer.limit() + length; + CharBuffer newBuffer = CharBuffer.allocate(newLength); + this.charBuffer.rewind(); + newBuffer.put(this.charBuffer); + this.charBuffer = newBuffer; } - System.arraycopy(data, start, nca, calength, length); - endIndex = nca.length; - this.ca = nca; - } + // append characters + this.charBuffer.put(data, start, length); + + } /** - * {@inheritDoc} + * Return the array of characters for this instance. + * + * @return a char array containing the text */ + public char[] getCharArray() { + + if (this.charBuffer == null) { + return null; + } + + if (this.charBuffer.hasArray()) { + return this.charBuffer.array(); + } + + // only if the buffer implementation has + // no accessible backing array, return a new one + char[] ca = new char[this.charBuffer.limit()]; + this.charBuffer.rewind(); + this.charBuffer.get(ca); + return ca; + + } + + /** {@inheritDoc} */ public FONode clone(FONode parent, boolean removeChildren) throws FOPException { FOText ft = (FOText) super.clone(parent, removeChildren); if (removeChildren) { - //not really removing, but just make sure the char array - //pointed to is really a different one, and reset any - //possible whitespace-handling effects - if (ca != null) { - ft.ca = new char[ca.length]; - System.arraycopy(ca, 0, ft.ca, 0, ca.length); + // not really removing, just make sure the char buffer + // pointed to is really a different one + if (this.charBuffer != null) { + ft.charBuffer = CharBuffer.allocate(this.charBuffer.limit()); + this.charBuffer.rewind(); + ft.charBuffer.put(this.charBuffer); + ft.charBuffer.rewind(); } } ft.prevFOTextThisBlock = null; @@ -162,29 +156,33 @@ public class FOText extends FONode { return ft; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { - commonFont = pList.getFontProps(); - commonHyphenation = pList.getHyphenationProps(); - color = pList.get(Constants.PR_COLOR).getColor(getUserAgent()); - keepTogether = pList.get(Constants.PR_KEEP_TOGETHER).getKeep(); - lineHeight = pList.get(Constants.PR_LINE_HEIGHT).getSpace(); - letterSpacing = pList.get(Constants.PR_LETTER_SPACING); - whiteSpaceCollapse = pList.get(Constants.PR_WHITE_SPACE_COLLAPSE).getEnum(); - whiteSpaceTreatment = pList.get(Constants.PR_WHITE_SPACE_TREATMENT).getEnum(); - textTransform = pList.get(Constants.PR_TEXT_TRANSFORM).getEnum(); - wordSpacing = pList.get(Constants.PR_WORD_SPACING); - wrapOption = pList.get(Constants.PR_WRAP_OPTION).getEnum(); - textDecoration = pList.getTextDecorationProps(); - baselineShift = pList.get(Constants.PR_BASELINE_SHIFT).getLength(); + this.commonFont = pList.getFontProps(); + this.commonHyphenation = pList.getHyphenationProps(); + this.color = pList.get(Constants.PR_COLOR).getColor(getUserAgent()); + this.keepTogether = pList.get(Constants.PR_KEEP_TOGETHER).getKeep(); + this.lineHeight = pList.get(Constants.PR_LINE_HEIGHT).getSpace(); + this.letterSpacing = pList.get(Constants.PR_LETTER_SPACING); + this.whiteSpaceCollapse = pList.get(Constants.PR_WHITE_SPACE_COLLAPSE).getEnum(); + this.whiteSpaceTreatment = pList.get(Constants.PR_WHITE_SPACE_TREATMENT).getEnum(); + this.textTransform = pList.get(Constants.PR_TEXT_TRANSFORM).getEnum(); + this.wordSpacing = pList.get(Constants.PR_WORD_SPACING); + this.wrapOption = pList.get(Constants.PR_WRAP_OPTION).getEnum(); + this.textDecoration = pList.getTextDecorationProps(); + this.baselineShift = pList.get(Constants.PR_BASELINE_SHIFT).getLength(); } /** {@inheritDoc} */ protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().characters( + this.getCharArray(), 0, this.charBuffer.limit()); + } + + /** {@inheritDoc} */ + public void finalizeNode() { textTransform(); - getFOEventHandler().characters(ca, startIndex, endIndex); } /** @@ -198,16 +196,20 @@ public class FOText extends FONode { */ public boolean willCreateArea() { if (whiteSpaceCollapse == Constants.EN_FALSE - && endIndex - startIndex > 0) { + && this.charBuffer.limit() > 0) { return true; } - for (int i = startIndex; i < endIndex; i++) { - char ch = ca[i]; - if (!((ch == ' ') - || (ch == '\n') - || (ch == '\r') - || (ch == '\t'))) { // whitespace + char ch; + this.charBuffer.rewind(); + while (this.charBuffer.hasRemaining()) { + ch = this.charBuffer.get(); + if (!((ch == CharUtilities.SPACE) + || (ch == CharUtilities.LINEFEED_CHAR) + || (ch == CharUtilities.CARRIAGE_RETURN) + || (ch == CharUtilities.TAB))) { + // not whitespace + this.charBuffer.rewind(); return true; } } @@ -222,7 +224,7 @@ public class FOText extends FONode { } /** - * This method is run as part of the ancestor Block's flushText(), to + * This method is run as part of the ancestor Block's flushText(), to * create xref pointers to the previous FOText objects within the same Block * @param ancestorBlock the ancestor fo:block */ @@ -230,7 +232,7 @@ public class FOText extends FONode { this.ancestorBlock = ancestorBlock; // if the last FOText is a sibling, point to it, and have it point here if (ancestorBlock.lastFOTextProcessed != null) { - if (ancestorBlock.lastFOTextProcessed.ancestorBlock + if (ancestorBlock.lastFOTextProcessed.ancestorBlock == this.ancestorBlock) { prevFOTextThisBlock = ancestorBlock.lastFOTextProcessed; prevFOTextThisBlock.nextFOTextThisBlock = this; @@ -241,16 +243,47 @@ public class FOText extends FONode { } /** - * This method is run as part of the Constructor, to handle the - * text-transform property. + * This method is run as part of endOfNode(), to handle the + * text-transform property for accumulated FOText */ private void textTransform() { - if (getFOEventHandler().inMarker() + if (getBuilderContext().inMarker() || textTransform == Constants.EN_NONE) { return; } - for (int i = 0; i < endIndex; i++) { - ca[i] = charTransform(i); + + this.charBuffer.rewind(); + CharBuffer tmp = this.charBuffer.slice(); + char c; + int lim = this.charBuffer.limit(); + int pos = -1; + while (++pos < lim) { + c = this.charBuffer.get(); + switch (textTransform) { + case Constants.EN_UPPERCASE: + tmp.put(Character.toUpperCase(c)); + break; + case Constants.EN_LOWERCASE: + tmp.put(Character.toLowerCase(c)); + break; + case Constants.EN_CAPITALIZE: + if (isStartOfWord(pos)) { + /* + Use toTitleCase here. Apparently, some languages use + a different character to represent a letter when using + initial caps than when all of the letters in the word + are capitalized. We will try to let Java handle this. + */ + tmp.put(Character.toTitleCase(c)); + } else { + tmp.put(c); + } + break; + default: + //should never happen as the property subsystem catches that case + assert false; + //nop + } } } @@ -261,7 +294,7 @@ public class FOText extends FONode { * well, such as word-spacing. The definition of "word" is somewhat ambiguous * and appears to be definable by the user agent. * - * @param i index into ca[] + * @param i index into charBuffer * * @return True if the character at this location is the start of a new * word. @@ -269,33 +302,33 @@ public class FOText extends FONode { private boolean isStartOfWord(int i) { char prevChar = getRelativeCharInBlock(i, -1); /* All we are really concerned about here is of what type prevChar - is. If inputChar is not part of a word, then the Java - conversions will (we hope) simply return inputChar. - */ - switch (isWordChar(prevChar)) { - case IS_WORD_CHAR_TRUE: - return false; - case IS_WORD_CHAR_FALSE: - return true; - /* "MAYBE" implies that additional context is needed. An example is a - * single-quote, either straight or closing, which might be interpreted - * as a possessive or a contraction, or might be a closing quote. + * is. If inputChar is not part of a word, then the Java + * conversions will (we hope) simply return inputChar. */ - case IS_WORD_CHAR_MAYBE: - char prevPrevChar = getRelativeCharInBlock(i, -2); - switch (isWordChar(prevPrevChar)) { + switch (isWordChar(prevChar)) { case IS_WORD_CHAR_TRUE: return false; case IS_WORD_CHAR_FALSE: return true; + /* "MAYBE" implies that additional context is needed. An example is a + * single-quote, either straight or closing, which might be interpreted + * as a possessive or a contraction, or might be a closing quote. + */ case IS_WORD_CHAR_MAYBE: - return true; + char prevPrevChar = getRelativeCharInBlock(i, -2); + switch (isWordChar(prevPrevChar)) { + case IS_WORD_CHAR_TRUE: + return false; + case IS_WORD_CHAR_FALSE: + return true; + case IS_WORD_CHAR_MAYBE: + return true; + default: + return false; + } default: return false; } - default: - return false; - } } /** @@ -304,7 +337,7 @@ public class FOText extends FONode { * block as one unit, allowing text in adjoining FOText objects to be * returned if the parameters are outside of the current object. * - * @param i index into ca[] + * @param i index into the CharBuffer * @param offset signed integer with relative position within the * block of the character to return. To return the character immediately * preceding i, pass -1. To return the character immediately after i, @@ -313,30 +346,34 @@ public class FOText extends FONode { * the offset points to an area outside of the block. */ private char getRelativeCharInBlock(int i, int offset) { + + int charIndex = i + offset; // The easy case is where the desired character is in the same FOText - if (((i + offset) >= 0) && ((i + offset) <= this.endIndex)) { - return ca[i + offset]; + if (charIndex >= 0 && charIndex < this.length()) { + return this.charAt(i + offset); } + // For now, we can't look at following FOText nodes if (offset > 0) { - return '\u0000'; - } + return CharUtilities.NULL_CHAR; + } + // Remaining case has the text in some previous FOText node boolean foundChar = false; - char charToReturn = '\u0000'; + char charToReturn = CharUtilities.NULL_CHAR; FOText nodeToTest = this; int remainingOffset = offset + i; while (!foundChar) { if (nodeToTest.prevFOTextThisBlock == null) { - foundChar = true; break; } nodeToTest = nodeToTest.prevFOTextThisBlock; - if ((nodeToTest.endIndex + remainingOffset) >= 0) { - charToReturn = nodeToTest.ca[nodeToTest.endIndex + remainingOffset]; + int diff = nodeToTest.length() + remainingOffset - 1; + if (diff >= 0) { + charToReturn = nodeToTest.charAt(diff); foundChar = true; } else { - remainingOffset = remainingOffset + nodeToTest.endIndex; + remainingOffset += diff; } } return charToReturn; @@ -367,39 +404,6 @@ public class FOText extends FONode { } /** - * Transforms one character in ca[] using the text-transform property. - * - * @param i the index into ca[] - * @return char with transformed value - */ - private char charTransform(int i) { - switch (textTransform) { - /* put NONE first, as this is probably the common case */ - case Constants.EN_NONE: - return ca[i]; - case Constants.EN_UPPERCASE: - return Character.toUpperCase(ca[i]); - case Constants.EN_LOWERCASE: - return Character.toLowerCase(ca[i]); - case Constants.EN_CAPITALIZE: - if (isStartOfWord(i)) { - /* - Use toTitleCase here. Apparently, some languages use - a different character to represent a letter when using - initial caps than when all of the letters in the word - are capitalized. We will try to let Java handle this. - */ - return Character.toTitleCase(ca[i]); - } else { - return ca[i]; - } - default: - assert false; //should never happen as the property subsystem catches that case - return ca[i]; - } - } - - /** * Determines whether the input char should be considered part of a * "word". This is used primarily to determine whether the character * immediately following starts a new word, but may have other uses. @@ -484,57 +488,64 @@ public class FOText extends FONode { } private class TextCharIterator extends CharIterator { - private int curIndex = 0; - - /* Current space removal process: just increment the startIndex - to "remove" leading spaces from ca, until an unremoved character - is found. Then perform arraycopy's to remove extra spaces - between words. nextCharCalled is used to determine if an - unremoved character has already been found--if its value > 2 - than it means that has occurred (it is reset to zero each time we - remove a space via incrementing the startIndex.) */ - private int nextCharCalled = 0; - + + int currentPosition = 0; + + boolean canRemove = false; + boolean canReplace = false; + + /** {@inheritDoc} */ public boolean hasNext() { - if (curIndex == 0) { -// log.debug("->" + new String(ca) + "<-"); - } - return (curIndex < endIndex); + return (this.currentPosition < charBuffer.limit()); } + /** {@inheritDoc} */ public char nextChar() { - if (curIndex < endIndex) { - nextCharCalled++; - // Just a char class? Don't actually care about the value! - return ca[curIndex++]; + + if (this.currentPosition < charBuffer.limit()) { + this.canRemove = true; + this.canReplace = true; + return charBuffer.get(currentPosition++); } else { throw new NoSuchElementException(); } + } + /** {@inheritDoc} */ public void remove() { - if (curIndex < endIndex && nextCharCalled < 2) { - startIndex++; - nextCharCalled = 0; -// log.debug("removeA: " + new String(ca, startIndex, endIndex - startIndex)); - } else if (curIndex < endIndex) { - // copy from curIndex to end to curIndex-1 - System.arraycopy(ca, curIndex, ca, curIndex - 1, - endIndex - curIndex); - endIndex--; - curIndex--; -// log.debug("removeB: " + new String(ca, startIndex, endIndex - startIndex)); - } else if (curIndex == endIndex) { -// log.debug("removeC: " + new String(ca, startIndex, endIndex - startIndex)); - endIndex--; - curIndex--; + + if (this.canRemove) { + charBuffer.position(currentPosition); + // Slice the buffer at the current position + CharBuffer tmp = charBuffer.slice(); + // Reset position to before current character + charBuffer.position(--currentPosition); + if (tmp.hasRemaining()) { + // Transfer any remaining characters + charBuffer.mark(); + charBuffer.put(tmp); + charBuffer.reset(); + } + // Decrease limit + charBuffer.limit(charBuffer.limit() - 1); + // Make sure following calls fail, unless nextChar() was called + this.canRemove = false; + } else { + throw new IllegalStateException(); } + } + /** {@inheritDoc} */ public void replaceChar(char c) { - if (curIndex > 0 && curIndex <= endIndex) { - ca[curIndex - 1] = c; + + if (this.canReplace) { + charBuffer.put(currentPosition - 1, c); + } else { + throw new IllegalStateException(); } + } } @@ -560,7 +571,7 @@ public class FOText extends FONode { return color; } - /** + /** * @return the "keep-together" property. */ public KeepProperty getKeepTogether() { @@ -571,40 +582,40 @@ public class FOText extends FONode { * @return the "letter-spacing" property. */ public Property getLetterSpacing() { - return letterSpacing; + return letterSpacing; } - + /** * @return the "line-height" property. */ public SpaceProperty getLineHeight() { return lineHeight; } - + /** * @return the "white-space-treatment" property */ public int getWhitespaceTreatment() { return whiteSpaceTreatment; } - + /** * @return the "word-spacing" property. */ public Property getWordSpacing() { - return wordSpacing; + return wordSpacing; } - + /** * @return the "wrap-option" property. */ public int getWrapOption() { - return wrapOption; + return wrapOption; } - + /** @return the "text-decoration" property. */ public CommonTextDecoration getTextDecoration() { - return textDecoration; + return textDecoration; } /** @return the baseline-shift property */ @@ -614,14 +625,12 @@ public class FOText extends FONode { /** {@inheritDoc} */ public String toString() { - StringBuffer sb = new StringBuffer(super.toString()); - sb.append(" (").append(ca).append(")"); - return sb.toString(); + return (this.charBuffer == null) ? "" : this.charBuffer.toString(); } - + /** {@inheritDoc} */ public String getLocalName() { - return null; + return "#PCDATA"; } /** {@inheritDoc} */ @@ -631,10 +640,34 @@ public class FOText extends FONode { /** {@inheritDoc} */ protected String gatherContextInfo() { - if (getLocator() != null) { + if (this.locator != null) { return super.gatherContextInfo(); } else { - return new String(ca).trim(); + return this.toString(); + } + } + + /** {@inheritDoc} */ + public char charAt(int position) { + return this.charBuffer.get(position); + } + + /** {@inheritDoc} */ + public CharSequence subSequence(int start, int end) { + return this.charBuffer.subSequence(start, end); + } + + /** {@inheritDoc} */ + public int length() { + return this.charBuffer.limit(); + } + + /** + * Resets the backing <code>java.nio.CharBuffer</code> + */ + public void resetBuffer() { + if (this.charBuffer != null) { + this.charBuffer.rewind(); } - } -}
\ No newline at end of file + } +} diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index 84abc4b8b..6682ff703 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -66,6 +66,9 @@ public class FOTreeBuilder extends DefaultHandler { /** Current delegate ContentHandler to receive the SAX events */ protected ContentHandler delegate; + + /** Provides information used during tree building stage. */ + private FOTreeBuilderContext builderContext; /** The object that handles formatting and rendering to a stream */ private FOEventHandler foEventHandler; @@ -101,7 +104,8 @@ public class FOTreeBuilder extends DefaultHandler { //one of the RTF-, MIF- etc. Handlers. foEventHandler = foUserAgent.getRendererFactory().createFOEventHandler( foUserAgent, outputFormat, stream); - foEventHandler.setPropertyListMaker(new PropertyListMaker() { + builderContext = new FOTreeBuilderContext(); + builderContext.setPropertyListMaker(new PropertyListMaker() { public PropertyList make(FObj fobj, PropertyList parentPropertyList) { return new StaticPropertyList(fobj, parentPropertyList); } @@ -140,7 +144,7 @@ public class FOTreeBuilder extends DefaultHandler { log.debug("Building formatting object tree"); } foEventHandler.startDocument(); - this.mainFOHandler = new MainFOHandler(); + this.mainFOHandler = new MainFOHandler(); this.mainFOHandler.startDocument(); this.delegate = this.mainFOHandler; } @@ -150,8 +154,7 @@ public class FOTreeBuilder extends DefaultHandler { this.delegate.endDocument(); if (this.rootFObj == null && empty) { FOValidationEventProducer eventProducer - = FOValidationEventProducer.Provider.get( - foEventHandler.getUserAgent().getEventBroadcaster()); + = FOValidationEventProducer.Provider.get(userAgent.getEventBroadcaster()); eventProducer.emptyDocument(this); } rootFObj = null; @@ -221,7 +224,7 @@ public class FOTreeBuilder extends DefaultHandler { } else { //No formatting results available for output formats no //involving the layout engine. - return null; + return null; } } @@ -254,7 +257,7 @@ public class FOTreeBuilder extends DefaultHandler { || !localName.equals("root")) { FOValidationEventProducer eventProducer = FOValidationEventProducer.Provider.get( - foEventHandler.getUserAgent().getEventBroadcaster()); + userAgent.getEventBroadcaster()); eventProducer.invalidFORoot(this, FONode.getNodeString(namespaceURI, localName), getEffectiveLocator()); } @@ -271,6 +274,7 @@ public class FOTreeBuilder extends DefaultHandler { foNode = fobjMaker.make(currentFObj); if (rootFObj == null) { rootFObj = (Root) foNode; + rootFObj.setBuilderContext(builderContext); rootFObj.setFOEventHandler(foEventHandler); } propertyList = foNode.createPropertyList( @@ -278,13 +282,12 @@ public class FOTreeBuilder extends DefaultHandler { foNode.processNode(localName, getEffectiveLocator(), attlist, propertyList); if (foNode.getNameId() == Constants.FO_MARKER) { - if (foEventHandler.inMarker()) { + if (builderContext.inMarker()) { nestedMarkerDepth++; } else { - foEventHandler.switchMarkerContext(true); + builderContext.switchMarkerContext(true); } } - foNode.startOfNode(); } catch (IllegalArgumentException e) { throw new SAXException(e); } @@ -310,9 +313,16 @@ public class FOTreeBuilder extends DefaultHandler { } currentFObj = foNode; - if (propertyList != null && !foEventHandler.inMarker()) { + if (propertyList != null && !builderContext.inMarker()) { currentPropertyList = propertyList; } + + // fo:characters can potentially be removed during + // white-space handling. + // Do not notify the FOEventHandler. + if (currentFObj.getNameId() != Constants.FO_CHARACTER) { + currentFObj.startOfNode(); + } } /** {@inheritDoc} */ @@ -329,17 +339,22 @@ public class FOTreeBuilder extends DefaultHandler { + ") vs. " + localName + " (" + uri + ")"); } - currentFObj.endOfNode(); + // fo:characters can potentially be removed during + // white-space handling. + // Do not notify the FOEventHandler. + if (currentFObj.getNameId() != Constants.FO_CHARACTER) { + currentFObj.endOfNode(); + } if (currentPropertyList != null && currentPropertyList.getFObj() == currentFObj - && !foEventHandler.inMarker()) { + && !builderContext.inMarker()) { currentPropertyList = currentPropertyList.getParentPropertyList(); } if (currentFObj.getNameId() == Constants.FO_MARKER) { if (nestedMarkerDepth == 0) { - foEventHandler.switchMarkerContext(false); + builderContext.switchMarkerContext(false); } else { nestedMarkerDepth--; } @@ -356,7 +371,7 @@ public class FOTreeBuilder extends DefaultHandler { public void characters(char[] data, int start, int length) throws FOPException { if (currentFObj != null) { - currentFObj.addCharacters(data, start, start + length, + currentFObj.addCharacters(data, start, length, currentPropertyList, getEffectiveLocator()); } } @@ -379,7 +394,7 @@ public class FOTreeBuilder extends DefaultHandler { if (maker instanceof UnknownXMLObj.Maker) { FOValidationEventProducer eventProducer = FOValidationEventProducer.Provider.get( - foEventHandler.getUserAgent().getEventBroadcaster()); + userAgent.getEventBroadcaster()); eventProducer.unknownFormattingObject(this, currentFObj.getName(), new QName(namespaceURI, localName), getEffectiveLocator()); diff --git a/src/java/org/apache/fop/fo/FOTreeBuilderContext.java b/src/java/org/apache/fop/fo/FOTreeBuilderContext.java new file mode 100644 index 000000000..0cbdd7797 --- /dev/null +++ b/src/java/org/apache/fop/fo/FOTreeBuilderContext.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo; + +import java.util.HashSet; +import java.util.Set; + +/** + * Context class providing information needed while building the FO tree. + */ +public class FOTreeBuilderContext { + + /** + * The current set of id's in the FO tree. + * This is used so we know if the FO tree contains duplicates. + */ + private Set idReferences = new HashSet(); + + /** + * The property list maker. + */ + protected PropertyListMaker propertyListMaker; + + /** + * The XMLWhitespaceHandler for this tree + */ + protected XMLWhiteSpaceHandler whiteSpaceHandler = new XMLWhiteSpaceHandler(); + + /** + * Indicates whether processing descendants of a marker + */ + private boolean inMarker = false; + + /** + * Returns the set of ID references. + * @return the ID references + */ + public Set getIDReferences() { + return idReferences; + } + + /** + * Return the propertyListMaker. + * + * @return the currently active {@link PropertyListMaker} + */ + public PropertyListMaker getPropertyListMaker() { + return propertyListMaker; + } + + /** + * Set a new propertyListMaker. + * + * @param propertyListMaker the new {@link PropertyListMaker} to use + */ + public void setPropertyListMaker(PropertyListMaker propertyListMaker) { + this.propertyListMaker = propertyListMaker; + } + + /** + * Return the XMLWhiteSpaceHandler + * @return the whiteSpaceHandler + */ + public XMLWhiteSpaceHandler getXMLWhiteSpaceHandler() { + return whiteSpaceHandler; + } + + /** + * Switch to or from marker context + * (used by FOTreeBuilder when processing + * a marker) + * + * @param inMarker true if a marker is being processed; + * false otherwise + * + */ + protected void switchMarkerContext(boolean inMarker) { + this.inMarker = inMarker; + } + + /** + * Check whether in marker context + * + * @return true if a marker is being processed + */ + protected boolean inMarker() { + return this.inMarker; + } + +} diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index 0bbec4d47..45b89dc8a 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -130,7 +130,7 @@ public abstract class FObj extends FONode implements Constants { */ protected PropertyList createPropertyList(PropertyList parent, FOEventHandler foEventHandler) throws FOPException { - return foEventHandler.getPropertyListMaker().make(this, parent); + return getBuilderContext().getPropertyListMaker().make(this, parent); } /** @@ -165,7 +165,7 @@ public abstract class FObj extends FONode implements Constants { */ private void checkId(String id) throws ValidationException { if (!inMarker() && !id.equals("")) { - Set idrefs = getFOEventHandler().getIDReferences(); + Set idrefs = getBuilderContext().getIDReferences(); if (!idrefs.contains(id)) { idrefs.add(id); } else { diff --git a/src/java/org/apache/fop/fo/FObjMixed.java b/src/java/org/apache/fop/fo/FObjMixed.java index bf7383398..068c2d635 100644 --- a/src/java/org/apache/fop/fo/FObjMixed.java +++ b/src/java/org/apache/fop/fo/FObjMixed.java @@ -28,29 +28,29 @@ import org.apache.fop.apps.FOPException; * (= those that can contain both child {@link FONode}s and <code>#PCDATA</code>). */ public abstract class FObjMixed extends FObj { - + /** Represents accumulated, pending FO text. See {@link #flushText()}. */ - protected FOText ft = null; - + private FOText ft = null; + /** Used for white-space handling; start CharIterator at node ... */ protected FONode currentTextNode; - + /** Used in creating pointers between subsequent {@link FOText} nodes - * in the same {@link org.apache.fop.fo.flow.Block} + * in the same {@link org.apache.fop.fo.flow.Block} * (for handling text-transform) */ protected FOText lastFOTextProcessed = null; - + /** * Base constructor - * + * * @param parent FONode that is the parent of this object */ protected FObjMixed(FONode parent) { super(parent); } - + /** {@inheritDoc} */ - protected void addCharacters(char[] data, int start, int end, + protected void addCharacters(char[] data, int start, int length, PropertyList pList, Locator locator) throws FOPException { if (ft == null) { @@ -60,113 +60,124 @@ public abstract class FObjMixed extends FObj { ft.bind(pList); } } - ft.addCharacters(data, start, end, null, null); + ft.addCharacters(data, start, length, null, null); } /** {@inheritDoc} */ protected void endOfNode() throws FOPException { - flushText(); - if (!inMarker() - || getNameId() == FO_MARKER) { - getFOEventHandler().whiteSpaceHandler - .handleWhiteSpace(this, currentTextNode); - } + super.endOfNode(); + if (!inMarker() || getNameId() == FO_MARKER) { + // send character[s]() events to the FOEventHandler + sendCharacters(); + } + } /** - * Handles white-space for the node that is passed in, + * Handles white-space for the node that is passed in, * starting at its current text-node - * (used by {@link org.apache.fop.fo.flow.RetrieveMarker} + * (used by {@link org.apache.fop.fo.flow.RetrieveMarker} * to trigger 'end-of-node' white-space handling) - * + * * @param fobj the node for which to handle white-space + * @param nextChild the next child to be added */ - protected static void handleWhiteSpaceFor(FObjMixed fobj) { - fobj.getFOEventHandler().getXMLWhiteSpaceHandler() - .handleWhiteSpace(fobj, fobj.currentTextNode); + protected static void handleWhiteSpaceFor(FObjMixed fobj, FONode nextChild) { + fobj.getBuilderContext().getXMLWhiteSpaceHandler() + .handleWhiteSpace(fobj, fobj.currentTextNode, nextChild); } - + /** - * Adds accumulated text as one FOText instance, unless - * the one instance's <code>char</code> array contains more than - * <code>Short.MAX_VALUE</code> characters. In the latter case the - * instance is split up into more manageable chunks. - * + * Creates block-pointers between subsequent FOText nodes + * in the same Block. (used for handling text-transform) + * + * TODO: !! Revisit: does not take into account fo:characters !! + * * @throws FOPException if there is a problem during processing */ - protected void flushText() throws FOPException { + private void flushText() throws FOPException { if (ft != null) { FOText lft = ft; /* make sure nested calls to itself have no effect */ ft = null; - FOText tmpText; - int indexStart = 0; - int indexEnd = (lft.ca.length > Short.MAX_VALUE - ? Short.MAX_VALUE : lft.ca.length) - 1; - int charCount = 0; - short tmpSize; - while (charCount < lft.ca.length) { - tmpSize = (short) (indexEnd - indexStart + 1); - charCount += tmpSize; - tmpText = (FOText) lft.clone(this, false); - tmpText.ca = new char[tmpSize]; - tmpText.startIndex = 0; - tmpText.endIndex = tmpSize; - System.arraycopy(lft.ca, indexStart, - tmpText.ca, 0, indexEnd - indexStart + 1); - if (getNameId() == FO_BLOCK) { - tmpText.createBlockPointers((org.apache.fop.fo.flow.Block) this); - this.lastFOTextProcessed = tmpText; - } else if (getNameId() != FO_MARKER - && getNameId() != FO_TITLE - && getNameId() != FO_BOOKMARK_TITLE) { - FONode fo = parent; - int foNameId = fo.getNameId(); - while (foNameId != FO_BLOCK - && foNameId != FO_MARKER - && foNameId != FO_TITLE - && foNameId != FO_BOOKMARK_TITLE - && foNameId != FO_PAGE_SEQUENCE) { - fo = fo.getParent(); - foNameId = fo.getNameId(); - } - if (foNameId == FO_BLOCK) { - tmpText.createBlockPointers((org.apache.fop.fo.flow.Block) fo); - ((FObjMixed) fo).lastFOTextProcessed = tmpText; - } else if (foNameId == FO_PAGE_SEQUENCE - && tmpText.willCreateArea()) { - log.error("Could not create block pointers." - + " FOText w/o Block ancestor."); - } + if (getNameId() == FO_BLOCK) { + lft.createBlockPointers((org.apache.fop.fo.flow.Block) this); + this.lastFOTextProcessed = lft; + } else if (getNameId() != FO_MARKER + && getNameId() != FO_TITLE + && getNameId() != FO_BOOKMARK_TITLE) { + FONode fo = parent; + int foNameId = fo.getNameId(); + while (foNameId != FO_BLOCK + && foNameId != FO_MARKER + && foNameId != FO_TITLE + && foNameId != FO_BOOKMARK_TITLE + && foNameId != FO_PAGE_SEQUENCE) { + fo = fo.getParent(); + foNameId = fo.getNameId(); + } + if (foNameId == FO_BLOCK) { + lft.createBlockPointers((org.apache.fop.fo.flow.Block) fo); + ((FObjMixed) fo).lastFOTextProcessed = lft; + } else if (foNameId == FO_PAGE_SEQUENCE + && lft.willCreateArea()) { + log.error("Could not create block pointers." + + " FOText w/o Block ancestor."); + } + } + this.addChildNode(lft); + } + } + + private void sendCharacters() throws FOPException { + + if (this.currentTextNode != null) { + FONodeIterator nodeIter + = this.getChildNodes(this.currentTextNode); + FONode node; + while (nodeIter.hasNext()) { + node = nodeIter.nextNode(); + assert (node instanceof FOText + || node.getNameId() == FO_CHARACTER); + if (node.getNameId() == FO_CHARACTER) { + node.startOfNode(); } - tmpText.endOfNode(); - addChildNode(tmpText); - indexStart = indexEnd + 1; - indexEnd = (((lft.ca.length - charCount) < Short.MAX_VALUE) - ? lft.ca.length : charCount + Short.MAX_VALUE) - 1; + node.endOfNode(); } } + this.currentTextNode = null; } /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { + flushText(); if (!inMarker()) { if (child instanceof FOText || child.getNameId() == FO_CHARACTER) { - if (currentTextNode == null) { - currentTextNode = child; + if (this.currentTextNode == null) { + this.currentTextNode = child; } } else { // handle white-space for all text up to here - getFOEventHandler().whiteSpaceHandler - .handleWhiteSpace(this, currentTextNode, child); - currentTextNode = null; + handleWhiteSpaceFor(this, child); + // send character[s]() events to the FOEventHandler + sendCharacters(); } } super.addChildNode(child); } - + + /** {@inheritDoc} */ + public void finalizeNode() throws FOPException { + + flushText(); + if (!inMarker() || getNameId() == FO_MARKER) { + handleWhiteSpaceFor(this, null); + } + + } + /** * Returns a {@link CharIterator} over this FO's character content * diff --git a/src/java/org/apache/fop/fo/RecursiveCharIterator.java b/src/java/org/apache/fop/fo/RecursiveCharIterator.java index 22ece76f3..a4aa28e37 100644 --- a/src/java/org/apache/fop/fo/RecursiveCharIterator.java +++ b/src/java/org/apache/fop/fo/RecursiveCharIterator.java @@ -113,7 +113,7 @@ public class RecursiveCharIterator extends CharIterator { */ public boolean hasNext() { while (curCharIter != null) { - if (curCharIter.hasNext() == false) { + if (!curCharIter.hasNext()) { getNextCharIter(); } else { return true; diff --git a/src/java/org/apache/fop/fo/XMLObj.java b/src/java/org/apache/fop/fo/XMLObj.java index da610f0e3..683ca5a03 100644 --- a/src/java/org/apache/fop/fo/XMLObj.java +++ b/src/java/org/apache/fop/fo/XMLObj.java @@ -214,7 +214,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { */ protected void addCharacters(char[] data, int start, int length, PropertyList pList, Locator locator) { - String str = new String(data, start, length - start); + String str = new String(data, start, length); org.w3c.dom.Text text = doc.createTextNode(str); element.appendChild(text); } diff --git a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java index 557a1778e..d8915b124 100644 --- a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java +++ b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java @@ -87,39 +87,49 @@ public class XMLWhiteSpaceHandler { * @param nextChild the node that will be added to the list * after firstTextNode */ - public void handleWhiteSpace(FObjMixed fo, FONode firstTextNode, FONode nextChild) { - + public void handleWhiteSpace(FObjMixed fo, + FONode firstTextNode, + FONode nextChild) { + Block currentBlock = null; int foId = fo.getNameId(); - if (foId == Constants.FO_BLOCK) { - currentBlock = (Block) fo; - if (nestedBlockStack.isEmpty() || fo != nestedBlockStack.peek()) { - if (nextChild != null) { - /* if already in a block, push the current block - * onto the stack of nested blocks - */ - nestedBlockStack.push(currentBlock); + /* set the current block */ + switch (foId) { + case Constants.FO_BLOCK: + currentBlock = (Block) fo; + if (nestedBlockStack.empty() || fo != nestedBlockStack.peek()) { + if (nextChild != null) { + /* if already in a block, push the current block + * onto the stack of nested blocks + */ + nestedBlockStack.push(currentBlock); + } + } else { + if (nextChild == null) { + nestedBlockStack.pop(); + } } - } else { - if (nextChild == null) { - nestedBlockStack.pop(); + break; + + case Constants.FO_RETRIEVE_MARKER: + /* look for the nearest block ancestor, if any */ + FONode ancestor = fo; + do { + ancestor = ancestor.getParent(); + } while (ancestor.getNameId() != Constants.FO_BLOCK + && ancestor.getNameId() != Constants.FO_STATIC_CONTENT); + + if (ancestor.getNameId() == Constants.FO_BLOCK) { + currentBlock = (Block) ancestor; + nestedBlockStack.push(currentBlock); } - } - } else if (foId == Constants.FO_RETRIEVE_MARKER) { - /* look for the nearest block ancestor, if any */ - FONode ancestor = fo; - do { - ancestor = ancestor.getParent(); - } while (ancestor.getNameId() != Constants.FO_BLOCK - && ancestor.getNameId() != Constants.FO_STATIC_CONTENT); + break; - if (ancestor.getNameId() == Constants.FO_BLOCK) { - currentBlock = (Block) ancestor; - nestedBlockStack.push(currentBlock); - } - } else if (!nestedBlockStack.isEmpty()) { - currentBlock = (Block) nestedBlockStack.peek(); + default: + if (!nestedBlockStack.empty()) { + currentBlock = (Block) nestedBlockStack.peek(); + } } if (currentBlock != null) { @@ -132,8 +142,15 @@ public class XMLWhiteSpaceHandler { whiteSpaceTreatment = Constants.EN_IGNORE_IF_SURROUNDING_LINEFEED; } + endOfBlock = (nextChild == null && fo == currentBlock); + if (firstTextNode == null) { - //nothing to do but initialize related properties + //no text means no white-space to handle; return early + afterLinefeed = (fo == currentBlock && fo.firstChild == null); + nonWhiteSpaceCount = 0; + if (endOfBlock) { + handlePendingInlines(); + } return; } @@ -144,13 +161,32 @@ public class XMLWhiteSpaceHandler { || currentBlock == null || (foId == Constants.FO_RETRIEVE_MARKER && fo.getParent() == currentBlock)) { - afterLinefeed = ( - (firstTextNode == fo.firstChild) - || (firstTextNode.siblings[0].getNameId() - == Constants.FO_BLOCK)); + if (firstTextNode == fo.firstChild) { + afterLinefeed = true; + } else { + int previousChildId = firstTextNode.siblings[0].getNameId(); + afterLinefeed = (previousChildId == Constants.FO_BLOCK + || previousChildId == Constants.FO_TABLE_AND_CAPTION + || previousChildId == Constants.FO_TABLE + || previousChildId == Constants.FO_LIST_BLOCK + || previousChildId == Constants.FO_BLOCK_CONTAINER); + } } - endOfBlock = (nextChild == null && fo == currentBlock); + if (foId == Constants.FO_WRAPPER) { + FONode parent = fo.parent; + int parentId = parent.getNameId(); + while (parentId == Constants.FO_WRAPPER) { + parent = parent.parent; + parentId = parent.getNameId(); + } + if (parentId == Constants.FO_FLOW + || parentId == Constants.FO_STATIC_CONTENT + || parentId == Constants.FO_BLOCK_CONTAINER + || parentId == Constants.FO_TABLE_CELL) { + endOfBlock = (nextChild == null); + } + } if (nextChild != null) { int nextChildId = nextChild.getNameId(); @@ -167,26 +203,8 @@ public class XMLWhiteSpaceHandler { handleWhiteSpace(); if (fo == currentBlock - && pendingInlines != null - && !pendingInlines.isEmpty()) { - /* current FO is a block, and has pending inlines */ - if (endOfBlock || nextChildIsBlockLevel) { - if (nonWhiteSpaceCount == 0) { - /* handle white-space for all pending inlines*/ - PendingInline p; - for (int i = pendingInlines.size(); --i >= 0;) { - p = (PendingInline)pendingInlines.get(i); - charIter = (RecursiveCharIterator)p.firstTrailingWhiteSpace; - handleWhiteSpace(); - pendingInlines.remove(p); - } - } else { - /* there is non-white-space text between the pending - * inline(s) and the end of the block; - * clear list of pending inlines */ - pendingInlines.clear(); - } - } + && (endOfBlock || nextChildIsBlockLevel)) { + handlePendingInlines(); } if (nextChild == null) { @@ -333,6 +351,26 @@ public class XMLWhiteSpaceHandler { pendingInlines.add(new PendingInline(fo, firstWhiteSpaceInSeq)); } + private void handlePendingInlines() { + if (!(pendingInlines == null || pendingInlines.isEmpty())) { + if (nonWhiteSpaceCount == 0) { + /* handle white-space for all pending inlines*/ + PendingInline p; + for (int i = pendingInlines.size(); --i >= 0;) { + p = (PendingInline)pendingInlines.get(i); + charIter = (RecursiveCharIterator)p.firstTrailingWhiteSpace; + handleWhiteSpace(); + pendingInlines.remove(p); + } + } else { + /* there is non-white-space text between the pending + * inline(s) and the end of the block; + * clear list of pending inlines */ + pendingInlines.clear(); + } + } + } + /** * Helper class, used during white-space handling to look ahead, and * see if the next character is a linefeed (or if there will be diff --git a/src/java/org/apache/fop/fo/expr/PropertyException.java b/src/java/org/apache/fop/fo/expr/PropertyException.java index 16055a738..d16d1c8ff 100644 --- a/src/java/org/apache/fop/fo/expr/PropertyException.java +++ b/src/java/org/apache/fop/fo/expr/PropertyException.java @@ -37,7 +37,7 @@ public class PropertyException extends FOPException { /** * Constructor - * @param the Exception causing this PropertyException + * @param cause the Exception causing this PropertyException */ public PropertyException(Exception cause) { super(cause); diff --git a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java index f08b1f433..bdfd1fc29 100644 --- a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java +++ b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java @@ -22,7 +22,7 @@ package org.apache.fop.fo.extensions.xmp; import java.io.Serializable; import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.apache.fop.util.XMLizable; +import org.apache.xmlgraphics.util.XMLizable; import org.apache.xmlgraphics.xmp.Metadata; import org.apache.xmlgraphics.xmp.XMPConstants; import org.xml.sax.ContentHandler; diff --git a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java index b45f21348..8849d4d1c 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java +++ b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java @@ -22,6 +22,7 @@ package org.apache.fop.fo.flow; import java.awt.Color; import org.xml.sax.Locator; +import org.xml.sax.Attributes; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; @@ -104,9 +105,9 @@ public abstract class AbstractPageNumberCitation extends FObj { } /** {@inheritDoc} */ - protected void startOfNode() throws FOPException { - super.startOfNode(); - if (refId.equals("")) { + public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + super.processNode(elementName, locator, attlist, pList); + if (!inMarker() && (refId == null || "".equals(refId))) { missingPropertyError("ref-id"); } } diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java index 83a0ddbdc..c88147350 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -16,20 +16,22 @@ */ /* $Id$ */ + package org.apache.fop.fo.flow; +import java.util.Iterator; + +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FOText; import org.apache.fop.fo.FObj; import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.flow.table.TableFObj; import org.apache.fop.fo.flow.table.Table; -import org.apache.fop.apps.FOPException; -import org.xml.sax.Locator; - -import java.util.Iterator; +import org.apache.fop.fo.flow.table.TableFObj; /** * Abstract base class for the <a href="http://www.w3.org/TR/xsl/#fo_retrieve-marker"> @@ -80,7 +82,7 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { } private PropertyList createPropertyListFor(FObj fo, PropertyList parent) { - return getFOEventHandler().getPropertyListMaker().make(fo, parent); + return getBuilderContext().getPropertyListMaker().make(fo, parent); } private void cloneSingleNode(FONode child, FONode newParent, @@ -100,16 +102,10 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { getLocator(), pList, newPropertyList); - if (newChild instanceof TableFObj) { - // TODO calling startOfNode (and endOfNode, below) on other fobjs may - // have undesirable side-effects. This is really ugly and will need to - // be addressed sooner or later - ((TableFObj) newChild).startOfNode(); - } addChildTo(newChild, (FObj) newParent); if (newChild.getNameId() == FO_TABLE) { Table t = (Table) child; - cloneSubtree(t.getColumns().listIterator(), + cloneSubtree(t.getColumns().iterator(), newChild, marker, newPropertyList); cloneSingleNode(t.getTableHeader(), newChild, marker, newPropertyList); @@ -118,18 +114,15 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { } cloneSubtree(child.getChildNodes(), newChild, marker, newPropertyList); - if (newChild instanceof TableFObj) { - // TODO this is ugly - ((TableFObj) newChild).endOfNode(); - } } else if (child instanceof FOText) { FOText ft = (FOText) newChild; ft.bind(parentPropertyList); addChildTo(newChild, (FObj) newParent); } - if (newChild instanceof FObjMixed) { - handleWhiteSpaceFor((FObjMixed) newChild); - } + + // trigger end-of-node white-space handling + // and finalization for table-FOs + newChild.finalizeNode(); } } @@ -167,7 +160,7 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { } cloneSubtree(marker.getChildNodes(), this, marker, propertyList); - handleWhiteSpaceFor(this); + handleWhiteSpaceFor(this, null); } /** diff --git a/src/java/org/apache/fop/fo/flow/Marker.java b/src/java/org/apache/fop/fo/flow/Marker.java index 7eda2101e..ea6721686 100644 --- a/src/java/org/apache/fop/fo/flow/Marker.java +++ b/src/java/org/apache/fop/fo/flow/Marker.java @@ -26,8 +26,8 @@ import org.xml.sax.Attributes; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOTreeBuilderContext; import org.apache.fop.fo.FObj; import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; @@ -84,10 +84,10 @@ public class Marker extends FObjMixed { /** {@inheritDoc} */ protected void startOfNode() { - FOEventHandler foEventHandler = getFOEventHandler(); + FOTreeBuilderContext builderContext = getBuilderContext(); // Push a new property list maker which will make MarkerPropertyLists. - savePropertyListMaker = foEventHandler.getPropertyListMaker(); - foEventHandler.setPropertyListMaker(new PropertyListMaker() { + savePropertyListMaker = builderContext.getPropertyListMaker(); + builderContext.setPropertyListMaker(new PropertyListMaker() { public PropertyList make(FObj fobj, PropertyList parentPropertyList) { PropertyList pList = new MarkerPropertyList(fobj, parentPropertyList); descendantPropertyLists.put(fobj, pList); @@ -100,7 +100,7 @@ public class Marker extends FObjMixed { protected void endOfNode() throws FOPException { super.endOfNode(); // Pop the MarkerPropertyList maker. - getFOEventHandler().setPropertyListMaker(savePropertyListMaker); + getBuilderContext().setPropertyListMaker(savePropertyListMaker); savePropertyListMaker = null; } diff --git a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java index 5322b08d3..82bdac845 100644 --- a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java @@ -40,7 +40,7 @@ interface BorderResolver { * * @param part the part that has started */ - void startPart(TableBody part); + void startPart(TablePart part); /** * Receives notification of the end of a table-header/footer/body. diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java index 2d48380ee..3a887166a 100644 --- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java @@ -73,7 +73,7 @@ class CollapsingBorderResolver implements BorderResolver { */ private abstract class Resolver { - protected TableBody tablePart; + protected TablePart tablePart; protected boolean firstInPart; @@ -177,7 +177,7 @@ class CollapsingBorderResolver implements BorderResolver { } } - void startPart(TableBody part) { + void startPart(TablePart part) { tablePart = part; firstInPart = true; borderStartTableAndBody = collapsingBorderModel.determineWinner(table.borderStart, @@ -415,8 +415,8 @@ class CollapsingBorderResolver implements BorderResolver { } /** {@inheritDoc} */ - public void startPart(TableBody part) { - if (part.isTableHeader()) { + public void startPart(TablePart part) { + if (part instanceof TableHeader) { delegate = new ResolverInHeader(); } else { if (leadingBorders == null || table.omitHeaderAtBreak()) { @@ -427,7 +427,7 @@ class CollapsingBorderResolver implements BorderResolver { leadingBorders.add(border); } } - if (part.isTableFooter()) { + if (part instanceof TableFooter) { resolverInFooter = new ResolverInFooter(); delegate = resolverInFooter; } else { diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java index 0d24491d9..a7719528a 100644 --- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java @@ -143,8 +143,8 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void endRow(TableBody body) { - handleRowEnd(body); + void endRow(TablePart part) { + handleRowEnd(part); } private void handleRowEnd(TableCellContainer container) { @@ -172,7 +172,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void startTablePart(TableBody part) { + void startTablePart(TablePart part) { firstInPart = true; borderResolver.startPart(part); } diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 55bcfa44e..a4b064a53 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -38,7 +38,7 @@ public class PrimaryGridUnit extends GridUnit { /** Cell layout manager. */ private TableCellLayoutManager cellLM; /** List of Knuth elements representing the contents of the cell. */ - private LinkedList elements; + private List elements; /** Index of the row where this cell starts. */ private int rowIndex; @@ -78,12 +78,12 @@ public class PrimaryGridUnit extends GridUnit { * * @return the enclosing table part */ - public TableBody getTableBody() { + public TablePart getTablePart() { FONode node = cell.getParent(); if (node instanceof TableRow) { node = node.getParent(); } - return (TableBody) node; + return (TablePart) node; } public TableCellLayoutManager getCellLM() { @@ -106,11 +106,11 @@ public class PrimaryGridUnit extends GridUnit { * * @param elements a list of ListElement (?) */ - public void setElements(LinkedList elements) { + public void setElements(List elements) { this.elements = elements; } - public LinkedList getElements() { + public List getElements() { return this.elements; } diff --git a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java index c954be711..9748a77aa 100644 --- a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java @@ -57,7 +57,7 @@ abstract class RowGroupBuilder { /** * Receives notification of the end of the current row. If the current row finishes - * the row group, the {@link TableBody#addRowGroup(List)} method of the parent table + * the row group, the {@link TablePart#addRowGroup(List)} method of the parent table * part will be called. */ abstract void endTableRow(); @@ -65,21 +65,21 @@ abstract class RowGroupBuilder { /** * Receives notification of the end of the current row, when the source contains no * fo:table-row element. If the current row finishes the row group, the - * {@link TableBody#addRowGroup(List)} method of the given table part will be called. + * {@link TablePart#addRowGroup(List)} method of the given table part will be called. * * <p>If the source does contain explicit fo:table-row elements, then the * {@link #endTableRow()} method will be called instead.</p> * * @param part the part containing the current row */ - abstract void endRow(TableBody part); + abstract void endRow(TablePart part); /** * Receives notification of the start of a table-header/footer/body. * * @param part the part being started */ - abstract void startTablePart(TableBody part); + abstract void startTablePart(TablePart part); /** * Receives notification of the end of a table-header/footer/body. The current diff --git a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java index c6d46ecf5..afd05823b 100644 --- a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java @@ -31,7 +31,7 @@ class SeparateBorderResolver implements BorderResolver { } /** {@inheritDoc} */ - public void startPart(TableBody part) { + public void startPart(TablePart part) { } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index 5b96a668e..9feb77c9c 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -76,8 +76,8 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { private ColumnNumberManager columnNumberManager = new ColumnNumberManager(); /** the table-header and -footer */ - private TableBody tableHeader = null; - private TableBody tableFooter = null; + private TableHeader tableHeader = null; + private TableFooter tableFooter = null; /** used for validation */ private boolean tableColumnFound = false; @@ -157,10 +157,8 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { this.propList = pList; } - /** - * {@inheritDoc} - */ - public void startOfNode() throws FOPException { + /** {@inheritDoc} */ + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startTable(this); } @@ -200,7 +198,9 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } else { tableFooterFound = true; if (tableBodyFound) { - nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)", true); + if (getUserAgent().validateStrictly()) { + nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)", true); + } if (!isSeparateBorderModel()) { TableEventProducer eventProducer = TableEventProducer.Provider.get( getUserAgent().getEventBroadcaster()); @@ -216,11 +216,15 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } } - /** - * {@inheritDoc} - */ - public void endOfNode() throws FOPException { + /** {@inheritDoc} */ + protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().endTable(this); + } + /** {@inheritDoc} */ + public void finalizeNode() throws FOPException { + if (!tableBodyFound) { missingChildElementError( "(marker*,table-column*,table-header?,table-footer?" @@ -242,13 +246,10 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { this.propList = null; rowGroupBuilder = null; } - getFOEventHandler().endTable(this); - + } - - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { int childId = child.getNameId(); @@ -277,10 +278,10 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } switch (childId) { case FO_TABLE_FOOTER: - tableFooter = (TableBody) child; + tableFooter = (TableFooter) child; break; case FO_TABLE_HEADER: - tableHeader = (TableBody) child; + tableHeader = (TableHeader) child; break; default: super.addChildNode(child); @@ -402,12 +403,12 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } /** @return the body for the table-header. */ - public TableBody getTableHeader() { + public TableHeader getTableHeader() { return tableHeader; } /** @return the body for the table-footer. */ - public TableBody getTableFooter() { + public TableFooter getTableFooter() { return tableFooter; } @@ -521,17 +522,17 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { return FO_TABLE; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public FONode clone(FONode parent, boolean removeChildren) throws FOPException { Table clone = (Table) super.clone(parent, removeChildren); - clone.columnsFinalized = false; if (removeChildren) { clone.columns = new ArrayList(); + clone.columnsFinalized = false; + clone.columnNumberManager = new ColumnNumberManager(); clone.tableHeader = null; clone.tableFooter = null; + clone.rowGroupBuilder = null; } return clone; } diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index b4e48d2e6..b4071e255 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -15,53 +15,18 @@ * limitations under the License. */ -/* $Id$ */ +/* $Id: $ */ package org.apache.fop.fo.flow.table; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import org.xml.sax.Attributes; -import org.xml.sax.Locator; - -import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.PropertyList; -import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.apps.FOPException; /** * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-body"> * <code>fo:table-body</code></a> object. */ -public class TableBody extends TableCellContainer { - // The value of properties relevant for fo:table-body. - private CommonBorderPaddingBackground commonBorderPaddingBackground; - // Unused but valid items, commented out for performance: - // private CommonAccessibility commonAccessibility; - // private CommonAural commonAural; - // private CommonRelativePosition commonRelativePosition; - // private int visibility; - // End of property values - - /** - * used for validation - */ - protected boolean tableRowsFound = false; - protected boolean tableCellsFound = false; - - private boolean firstRow = true; - - private boolean rowsStarted = false; - - private boolean lastCellEndsRow = true; - - /** The last encountered table-row. */ - private TableRow lastRow; - - private List rowGroups = new LinkedList(); +public class TableBody extends TablePart { /** * Create a TableBody instance with the given {@link FONode} @@ -73,159 +38,15 @@ public class TableBody extends TableCellContainer { } /** {@inheritDoc} */ - public void bind(PropertyList pList) throws FOPException { - commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); - super.bind(pList); - } - - /** {@inheritDoc} */ - public void processNode(String elementName, Locator locator, - Attributes attlist, PropertyList pList) - throws FOPException { - if (!inMarker()) { - Table t = getTable(); - if (t.hasExplicitColumns()) { - int size = t.getNumberOfColumns(); - pendingSpans = new ArrayList(size); - for (int i = 0; i < size; i++) { - pendingSpans.add(null); - } - } else { - pendingSpans = new ArrayList(); - } - columnNumberManager = new ColumnNumberManager(); - } - super.processNode(elementName, locator, attlist, pList); - } - - /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startBody(this); } /** {@inheritDoc} */ - public void endOfNode() throws FOPException { - - if (!inMarker()) { - pendingSpans = null; - columnNumberManager = null; - } - + protected void endOfNode() throws FOPException { + super.endOfNode(); getFOEventHandler().endBody(this); - - if (!(tableRowsFound || tableCellsFound)) { - missingChildElementError("marker* (table-row+|table-cell+)", true); - getParent().removeChild(this); - } else { - finishLastRowGroup(); - } - } - - /** {@inheritDoc} */ - TableBody getTablePart() { - return this; - } - - protected void finishLastRowGroup() throws ValidationException { - if (!inMarker()) { - RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder(); - if (tableRowsFound) { - rowGroupBuilder.endTableRow(); - } else if (!lastCellEndsRow) { - rowGroupBuilder.endRow(this); - } - try { - rowGroupBuilder.endTablePart(); - } catch (ValidationException e) { - e.setLocator(locator); - throw e; - } - } - } - - /** - * {@inheritDoc} - * <br>XSL Content Model: marker* (table-row+|table-cell+) - */ - protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI)) { - if (localName.equals("marker")) { - if (tableRowsFound || tableCellsFound) { - nodesOutOfOrderError(loc, "fo:marker", "(table-row+|table-cell+)"); - } - } else if (localName.equals("table-row")) { - tableRowsFound = true; - if (tableCellsFound) { - TableEventProducer eventProducer = TableEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.noMixRowsAndCells(this, getName(), getLocator()); - } - } else if (localName.equals("table-cell")) { - tableCellsFound = true; - if (tableRowsFound) { - TableEventProducer eventProducer = TableEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.noMixRowsAndCells(this, getName(), getLocator()); - } - } else { - invalidChildError(loc, nsURI, localName); - } - } - } - - /** {@inheritDoc} */ - protected void addChildNode(FONode child) throws FOPException { - if (!inMarker()) { - switch (child.getNameId()) { - case FO_TABLE_ROW: - if (!rowsStarted) { - getTable().getRowGroupBuilder().startTablePart(this); - } else { - columnNumberManager.prepareForNextRow(pendingSpans); - getTable().getRowGroupBuilder().endTableRow(); - } - rowsStarted = true; - lastRow = (TableRow) child; - getTable().getRowGroupBuilder().startTableRow(lastRow); - break; - case FO_TABLE_CELL: - if (!rowsStarted) { - getTable().getRowGroupBuilder().startTablePart(this); - } - rowsStarted = true; - TableCell cell = (TableCell) child; - addTableCellChild(cell, firstRow); - lastCellEndsRow = cell.endsRow(); - if (lastCellEndsRow) { - firstRow = false; - columnNumberManager.prepareForNextRow(pendingSpans); - getTable().getRowGroupBuilder().endRow(this); - } - break; - default: - //nop - } - } - super.addChildNode(child); - } - - void addRowGroup(List rowGroup) { - rowGroups.add(rowGroup); - } - - public List getRowGroups() { - return rowGroups; - } - - /** - * Get the {@link CommonBorderPaddingBackground} instance attached - * to this TableBody. - * @return the {@link CommonBorderPaddingBackground} instance. - */ - public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { - return commonBorderPaddingBackground; } /** {@inheritDoc} */ @@ -240,32 +61,4 @@ public class TableBody extends TableCellContainer { public int getNameId() { return FO_TABLE_BODY; } - - protected boolean isTableHeader() { - return false; - } - - protected boolean isTableFooter() { - return false; - } - - /** - * @param obj table row in question - * @return true if the given table row is the first row of this body. - */ - public boolean isFirst(TableRow obj) { - return (firstChild == null - || firstChild == obj); - } - - void signalNewRow() { - if (rowsStarted) { - firstRow = false; - if (!lastCellEndsRow) { - columnNumberManager.prepareForNextRow(pendingSpans); - getTable().getRowGroupBuilder().endRow(this); - } - } - } - } diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java index 2781bf082..21da54128 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCell.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java @@ -81,7 +81,7 @@ public class TableCell extends TableFObj { startsRow = pList.get(PR_STARTS_ROW).getEnum(); // For properly computing columnNumber if (startsRow() && getParent().getNameId() != FO_TABLE_ROW) { - ((TableBody) getParent()).signalNewRow(); + ((TablePart) getParent()).signalNewRow(); } endsRow = pList.get(PR_ENDS_ROW).getEnum(); columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric().getValue(); @@ -91,17 +91,24 @@ public class TableCell extends TableFObj { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startCell(this); } /** * Make sure content model satisfied, if so then tell the - * FOEventHandler that we are at the end of the flow. + * FOEventHandler that we are at the end of the table-cell. * {@inheritDoc} */ - public void endOfNode() throws FOPException { + protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().endCell(this); + } + + /** {@inheritDoc} */ + public void finalizeNode() throws FOPException { + if (!blockItemFound) { missingChildElementError("marker* (%block;)+", true); } @@ -111,9 +118,9 @@ public class TableCell extends TableFObj { getUserAgent().getEventBroadcaster()); eventProducer.startEndRowUnderTableRowWarning(this, getLocator()); } - getFOEventHandler().endCell(this); + } - + /** * {@inheritDoc} * <br>XSL Content Model: marker* (%block;)+ diff --git a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java index de9f271b5..1d1a29b35 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java @@ -95,9 +95,9 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb /** * Returns the enclosing table-header/footer/body of this container. * - * @return <code>this</code> for TableBody, or the parent element for TableRow + * @return <code>this</code> for TablePart, or the parent element for TableRow */ - abstract TableBody getTablePart(); + abstract TablePart getTablePart(); /** {@inheritDoc} */ public ColumnNumberManager getColumnNumberManager() { diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java index 6916e090b..025f5a74f 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java +++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java @@ -239,7 +239,7 @@ public class TableColumn extends TableFObj { sb.append(" number-columns-spanned=") .append(getNumberColumnsSpanned()); } - sb.append(" column-width=").append(getColumnWidth()); + sb.append(" column-width=").append(((Property)getColumnWidth()).getString()); return sb.toString(); } diff --git a/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java b/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java index 44ddcc038..9c4a82dd6 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java +++ b/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java @@ -145,6 +145,17 @@ public interface TableEventProducer extends EventProducer { Locator loc) throws PropertyException; /** + * @param source the event source + * @param elementName the name of the context node + * @param propValue the user-specified value of the column-number property + * @param columnNumber the generated value for the column-number property + * @param loc the location of the error or null + * @event.severity WARN + */ + void forceNextColumnNumber(Object source, String elementName, Number propValue, + int columnNumber, Locator loc); + + /** * Break ignored due to row spanning. * @param source the event source * @param elementName the name of the context node diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 6bc113fd0..faf1f7aba 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -34,6 +34,8 @@ import org.apache.fop.fo.properties.NumberProperty; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.PropertyMaker; import org.apache.fop.layoutmgr.table.CollapsingBorderModel; +import org.xml.sax.Locator; +import org.xml.sax.Attributes; /** * Common base class for table-related FOs @@ -53,9 +55,10 @@ public abstract class TableFObj extends FObj { CollapsingBorderModel collapsingBorderModel; /** - * Main constructor + * Create a TableFObj instance that is a child + * of the given {@link FONode} * - * @param parent the parent node + * @param parent the parent {@link FONode} */ public TableFObj(FONode parent) { super(parent); @@ -79,6 +82,8 @@ public abstract class TableFObj extends FObj { } /** + * Return the value for the "border-precedence" property + * for the given side. * * @param side the side for which to return the border precedence * @return the "border-precedence" value for the given side @@ -100,13 +105,13 @@ public abstract class TableFObj extends FObj { /** * Convenience method to returns a reference - * to the base Table instance + * to the base {@link Table} instance. * * @return the base table instance * */ public Table getTable() { - // Will be overridden in Table; for any other Table-node, recursive call to + // Overridden in Table; for any other Table-node, recursive call to // parent.getTable() return ((TableFObj) parent).getTable(); } @@ -117,13 +122,13 @@ public abstract class TableFObj extends FObj { public abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground(); /** - * PropertyMaker subclass for the column-number property - * + * {@link PropertyMaker} subclass for the column-number property */ public static class ColumnNumberPropertyMaker extends PropertyMaker { /** * Constructor + * * @param propId the id of the property for which the maker should * be created */ @@ -142,47 +147,50 @@ public abstract class TableFObj extends FObj { /** + * {@inheritDoc} * Check the value of the column-number property. - * Return the parent's column index (initial value) in case - * of a negative or zero value - * - * @see org.apache.fop.fo.properties.PropertyMaker#make(PropertyList, String, FObj) */ public Property make(PropertyList propertyList, String value, FObj fo) throws PropertyException { + Property p = super.make(propertyList, value, fo); - ColumnNumberManagerHolder parent - = (ColumnNumberManagerHolder) propertyList.getParentFObj(); - ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); int columnIndex = p.getNumeric().getValue(); int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED) .getNumeric().getValue(); - - int i = columnIndex - 1; - int lastIndex = (columnIndex + colSpan) - 1; - while (++i < lastIndex) { - if (columnIndexManager.isColumnNumberUsed(i)) { - /* if column-number is already in use by another - * cell/column => error! - */ - TableEventProducer eventProducer = TableEventProducer.Provider.get( - fo.getUserAgent().getEventBroadcaster()); - eventProducer.cellOverlap(this, propertyList.getFObj().getName(), - i, fo.getLocator()); + + // only check whether the column-number is occupied in case it was + // specified on a fo:table-cell or fo:table-column + int foId = propertyList.getFObj().getNameId(); + if (foId == FO_TABLE_COLUMN || foId == FO_TABLE_CELL) { + ColumnNumberManagerHolder parent + = (ColumnNumberManagerHolder) propertyList.getParentFObj(); + ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); + int lastIndex = columnIndex - 1 + colSpan; + for (int i = columnIndex; i <= lastIndex; ++i) { + if (columnIndexManager.isColumnNumberUsed(i)) { + /* if column-number is already in use by another + * cell/column => error! + */ + TableEventProducer eventProducer + = TableEventProducer.Provider.get( + fo.getUserAgent().getEventBroadcaster()); + eventProducer.cellOverlap( + this, propertyList.getFObj().getName(), + i, propertyList.getFObj().getLocator()); + } } } - return p; } - + /** - * If the value is not positive, return a property whose value is the next column number - * * {@inheritDoc} + * If the value is not positive, return a property whose value + * is the next column number. */ - public Property convertProperty(Property p, - PropertyList propertyList, FObj fo) + public Property convertProperty(Property p, + PropertyList propertyList, FObj fo) throws PropertyException { if (p instanceof EnumProperty) { return EnumNumber.getInstance(p); @@ -190,11 +198,24 @@ public abstract class TableFObj extends FObj { Number val = p.getNumber(); if (val != null) { int i = Math.round(val.floatValue()); + int foId = propertyList.getFObj().getNameId(); if (i <= 0) { - ColumnNumberManagerHolder parent = - (ColumnNumberManagerHolder) propertyList.getParentFObj(); - ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); - i = columnIndexManager.getCurrentColumnNumber(); + if (foId == FO_TABLE_CELL || foId == FO_TABLE_COLUMN) { + ColumnNumberManagerHolder parent = + (ColumnNumberManagerHolder) propertyList.getParentFObj(); + ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); + i = columnIndexManager.getCurrentColumnNumber(); + } else { + /* very exceptional case: + * negative column-number specified on + * a FO that is not a fo:table-cell or fo:table-column + */ + i = 1; + } + TableEventProducer eventProducer = + TableEventProducer.Provider.get(fo.getUserAgent().getEventBroadcaster()); + eventProducer.forceNextColumnNumber(this, propertyList.getFObj().getName(), + val, i, propertyList.getFObj().getLocator()); } return NumberProperty.getInstance(i); } @@ -204,8 +225,8 @@ public abstract class TableFObj extends FObj { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { - super.startOfNode(); + public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + super.processNode(elementName, locator, attlist, pList); Table table = getTable(); if (!inMarker() && !table.isSeparateBorderModel()) { collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table @@ -213,15 +234,7 @@ public abstract class TableFObj extends FObj { setCollapsedBorders(); } } - - /* - * TODO made public so that RetrieveMarker can access it. - */ - /** {@inheritDoc} */ - public void endOfNode() throws FOPException { - super.endOfNode(); - } - + /** * Prepares the borders of this element if the collapsing-border model is in use. * Conflict resolution with parent elements is done where applicable. @@ -236,26 +249,26 @@ public abstract class TableFObj extends FObj { /** * Creates a BorderSpecification from the border set on the given side. If no border * is set, a BorderSpecification with border-style none is created. - * + * * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END */ private void createBorder(int side) { BorderSpecification borderSpec = new BorderSpecification( getCommonBorderPaddingBackground().getBorderInfo(side), getNameId()); switch (side) { - case CommonBorderPaddingBackground.BEFORE: - borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel); - break; - case CommonBorderPaddingBackground.AFTER: - borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel); - break; - case CommonBorderPaddingBackground.START: - borderStart = borderSpec; - break; - case CommonBorderPaddingBackground.END: - borderEnd = borderSpec; - break; - default: assert false; + case CommonBorderPaddingBackground.BEFORE: + borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.AFTER: + borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.START: + borderStart = borderSpec; + break; + case CommonBorderPaddingBackground.END: + borderEnd = borderSpec; + break; + default: assert false; } } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableFooter.java b/src/java/org/apache/fop/fo/flow/table/TableFooter.java index d05824e95..a89a2e431 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFooter.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFooter.java @@ -28,7 +28,7 @@ import org.apache.fop.fo.FONode; * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-footer"> * <code>fo:table-footer</code></a> object. */ -public class TableFooter extends TableBody { +public class TableFooter extends TablePart { /** * Create a TableFooter instance with the given {@link FONode} @@ -41,17 +41,15 @@ public class TableFooter extends TableBody { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); + getFOEventHandler().startFooter(this); } /** {@inheritDoc} */ - public void endOfNode() throws FOPException { - if (!(tableRowsFound || tableCellsFound)) { - missingChildElementError("marker* (table-row+|table-cell+)"); - } else { - finishLastRowGroup(); - } + protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().endFooter(this); } /** {@inheritDoc} */ @@ -67,8 +65,4 @@ public class TableFooter extends TableBody { return FO_TABLE_FOOTER; } - /** {@inheritDoc} */ - protected boolean isTableFooter() { - return true; - } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java index 252ba1b8b..7f4173754 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java +++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java @@ -28,7 +28,7 @@ import org.apache.fop.fo.FONode; * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-header"> * <code>fo:table-header</code></a> object. */ -public class TableHeader extends TableBody { +public class TableHeader extends TablePart { /** * Create a TableHeader instance with the given {@link FONode} @@ -40,17 +40,15 @@ public class TableHeader extends TableBody { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); + getFOEventHandler().startHeader(this); } /** {@inheritDoc} */ - public void endOfNode() throws FOPException { - if (!(tableRowsFound || tableCellsFound)) { - missingChildElementError("marker* (table-row+|table-cell+)"); - } else { - finishLastRowGroup(); - } + protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().endHeader(this); } /** {@inheritDoc} */ @@ -66,8 +64,4 @@ public class TableHeader extends TableBody { return FO_TABLE_HEADER; } - /** {@inheritDoc} */ - protected boolean isTableHeader() { - return true; - } } diff --git a/src/java/org/apache/fop/fo/flow/table/TablePart.java b/src/java/org/apache/fop/fo/flow/table/TablePart.java new file mode 100644 index 000000000..4d20db8c4 --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/table/TablePart.java @@ -0,0 +1,239 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id: TableBody.java 655614 2008-05-12 19:37:39Z vhennebert $ */ + +package org.apache.fop.fo.flow.table; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; + +/** + * An abstract base class modelling a TablePart + * (i.e. fo:table-header, fo:table-footer and fo:table-body). + */ +public abstract class TablePart extends TableCellContainer { + // The value of properties relevant for fo:table-body. + private CommonBorderPaddingBackground commonBorderPaddingBackground; + // Unused but valid items, commented out for performance: + // private CommonAccessibility commonAccessibility; + // private CommonAural commonAural; + // private CommonRelativePosition commonRelativePosition; + // private int visibility; + // End of property values + + /** + * used for validation + */ + protected boolean tableRowsFound = false; + protected boolean tableCellsFound = false; + + private boolean firstRow = true; + + private boolean rowsStarted = false; + + private boolean lastCellEndsRow = true; + + private List rowGroups = new LinkedList(); + + /** + * Create a TablePart instance with the given {@link FONode} + * as parent. + * @param parent FONode that is the parent of the object + */ + public TablePart(FONode parent) { + super(parent); + } + + /** {@inheritDoc} */ + public void bind(PropertyList pList) throws FOPException { + commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); + super.bind(pList); + } + + /** {@inheritDoc} */ + public void processNode(String elementName, Locator locator, + Attributes attlist, PropertyList pList) + throws FOPException { + + super.processNode(elementName, locator, attlist, pList); + if (!inMarker()) { + Table t = getTable(); + if (t.hasExplicitColumns()) { + int size = t.getNumberOfColumns(); + pendingSpans = new ArrayList(size); + for (int i = 0; i < size; i++) { + pendingSpans.add(null); + } + } else { + pendingSpans = new ArrayList(); + } + columnNumberManager = new ColumnNumberManager(); + } + + } + + /** {@inheritDoc} */ + public void finalizeNode() throws FOPException { + if (!inMarker()) { + pendingSpans = null; + columnNumberManager = null; + } + + if (!(tableRowsFound || tableCellsFound)) { + missingChildElementError("marker* (table-row+|table-cell+)", true); + getParent().removeChild(this); + } else { + finishLastRowGroup(); + } + } + + /** {@inheritDoc} */ + TablePart getTablePart() { + return this; + } + + protected void finishLastRowGroup() throws ValidationException { + if (!inMarker()) { + RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder(); + if (tableRowsFound) { + rowGroupBuilder.endTableRow(); + } else if (!lastCellEndsRow) { + rowGroupBuilder.endRow(this); + } + try { + rowGroupBuilder.endTablePart(); + } catch (ValidationException e) { + e.setLocator(locator); + throw e; + } + } + } + + /** + * {@inheritDoc} + * <br>XSL Content Model: marker* (table-row+|table-cell+) + */ + protected void validateChildNode(Locator loc, String nsURI, String localName) + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (tableRowsFound || tableCellsFound) { + nodesOutOfOrderError(loc, "fo:marker", "(table-row+|table-cell+)"); + } + } else if (localName.equals("table-row")) { + tableRowsFound = true; + if (tableCellsFound) { + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noMixRowsAndCells(this, getName(), getLocator()); + } + } else if (localName.equals("table-cell")) { + tableCellsFound = true; + if (tableRowsFound) { + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noMixRowsAndCells(this, getName(), getLocator()); + } + } else { + invalidChildError(loc, nsURI, localName); + } + } + } + + /** {@inheritDoc} */ + protected void addChildNode(FONode child) throws FOPException { + if (!inMarker()) { + switch (child.getNameId()) { + case FO_TABLE_ROW: + if (!rowsStarted) { + getTable().getRowGroupBuilder().startTablePart(this); + } else { + columnNumberManager.prepareForNextRow(pendingSpans); + getTable().getRowGroupBuilder().endTableRow(); + } + rowsStarted = true; + getTable().getRowGroupBuilder().startTableRow((TableRow)child); + break; + case FO_TABLE_CELL: + if (!rowsStarted) { + getTable().getRowGroupBuilder().startTablePart(this); + } + rowsStarted = true; + TableCell cell = (TableCell) child; + addTableCellChild(cell, firstRow); + lastCellEndsRow = cell.endsRow(); + if (lastCellEndsRow) { + firstRow = false; + columnNumberManager.prepareForNextRow(pendingSpans); + getTable().getRowGroupBuilder().endRow(this); + } + break; + default: + //nop + } + } + super.addChildNode(child); + } + + void addRowGroup(List rowGroup) { + rowGroups.add(rowGroup); + } + + public List getRowGroups() { + return rowGroups; + } + + /** + * Get the {@link CommonBorderPaddingBackground} instance attached + * to this TableBody. + * @return the {@link CommonBorderPaddingBackground} instance. + */ + public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { + return commonBorderPaddingBackground; + } + + /** + * @param obj table row in question + * @return true if the given table row is the first row of this body. + */ + public boolean isFirst(TableRow obj) { + return (firstChild == null + || firstChild == obj); + } + + void signalNewRow() { + if (rowsStarted) { + firstRow = false; + if (!lastCellEndsRow) { + columnNumberManager.prepareForNextRow(pendingSpans); + getTable().getRowGroupBuilder().endRow(this); + } + } + } + +} diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java index 3be794fbd..ac6eafc2f 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableRow.java +++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java @@ -78,32 +78,38 @@ public class TableRow extends TableCellContainer { /** {@inheritDoc} */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + super.processNode(elementName, locator, attlist, pList); if (!inMarker()) { - TableBody body = (TableBody) parent; - pendingSpans = body.pendingSpans; - columnNumberManager = body.columnNumberManager; + TablePart part = (TablePart) parent; + pendingSpans = part.pendingSpans; + columnNumberManager = part.columnNumberManager; } - super.processNode(elementName, locator, attlist, pList); } /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { if (!inMarker()) { TableCell cell = (TableCell) child; - TableBody body = (TableBody) getParent(); - addTableCellChild(cell, body.isFirst(this)); + TablePart part = (TablePart) getParent(); + addTableCellChild(cell, part.isFirst(this)); } super.addChildNode(child); } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startRow(this); } /** {@inheritDoc} */ - public void endOfNode() throws FOPException { + protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().endRow(this); + } + + /** {@inheritDoc} */ + public void finalizeNode() throws FOPException { if (firstChild == null) { missingChildElementError("(table-cell+)"); } @@ -111,9 +117,8 @@ public class TableRow extends TableCellContainer { pendingSpans = null; columnNumberManager = null; } - getFOEventHandler().endRow(this); } - + /** * {@inheritDoc} String, String) * <br>XSL Content Model: (table-cell+) @@ -129,8 +134,8 @@ public class TableRow extends TableCellContainer { } /** {@inheritDoc} */ - TableBody getTablePart() { - return (TableBody) parent; + TablePart getTablePart() { + return (TablePart) parent; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java index d59870f0a..23c16d1f2 100644 --- a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java @@ -82,7 +82,7 @@ class VariableColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void endRow(final TableBody part) { + void endRow(final TablePart part) { events.add(new Event() { public void play(RowGroupBuilder rowGroupBuilder) { rowGroupBuilder.endRow(part); @@ -91,7 +91,7 @@ class VariableColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void startTablePart(final TableBody part) { + void startTablePart(final TablePart part) { events.add(new Event() { public void play(RowGroupBuilder rowGroupBuilder) { rowGroupBuilder.startTablePart(part); diff --git a/src/java/org/apache/fop/fo/pagination/Flow.java b/src/java/org/apache/fop/fo/pagination/Flow.java index 8e114c47f..d3682fa81 100644 --- a/src/java/org/apache/fop/fo/pagination/Flow.java +++ b/src/java/org/apache/fop/fo/pagination/Flow.java @@ -50,6 +50,7 @@ public class Flow extends FObj { /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { + super.bind(pList); flowName = pList.get(PR_FLOW_NAME).getString(); } diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java index 04014f6fc..c6346e9fb 100644 --- a/src/java/org/apache/fop/fo/pagination/Root.java +++ b/src/java/org/apache/fop/fo/pagination/Root.java @@ -27,6 +27,7 @@ import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOTreeBuilderContext; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; @@ -59,6 +60,11 @@ public class Root extends FObj { private int totalPagesGenerated = 0; /** + * Context class used while building the FO tree. + */ + private FOTreeBuilderContext builderContext; + + /** * FOEventHandler object for this FO Tree */ private FOEventHandler foEventHandler = null; @@ -164,10 +170,23 @@ public class Root extends FObj { return foEventHandler; } - /** - * Gets the last page number generated by the previous page-sequence - * @return the last page number, 0 if no page sequences yet generated + /** + * Sets the builder context for this FO tree. + * @param context the builder context to be used */ + public void setBuilderContext(FOTreeBuilderContext context) { + this.builderContext = context; + } + + /** {@inheritDoc} */ + public FOTreeBuilderContext getBuilderContext() { + return this.builderContext; + } + + /** + * Gets the last page number generated by the previous page-sequence + * @return the last page number, 0 if no page sequences yet generated + */ public int getEndingPageNumberOfPreviousSequence() { return endingPageNumberOfPreviousSequence; } diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java index c4cc73efc..6cee46752 100644 --- a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java +++ b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java @@ -51,13 +51,13 @@ public class BookmarkTitle extends FObj { * * @param data the character data * @param start the start position in the data array - * @param end the end position in the character array + * @param length the length of the character array * @param locator location in fo source file. */ - protected void addCharacters(char[] data, int start, int end, + protected void addCharacters(char[] data, int start, int length, PropertyList pList, Locator locator) { - title += new String(data, start, end - start); + title += new String(data, start, length); } /** diff --git a/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java b/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java index 839ac7022..542dcac32 100644 --- a/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java +++ b/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java @@ -23,7 +23,6 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; -import org.apache.fop.fo.properties.LengthProperty; /** * Custom Maker for page-height / page-width @@ -54,8 +53,8 @@ public class PageDimensionMaker extends LengthProperty.Maker { Property p = super.get(0, propertyList, tryInherit, tryDefault); FObj fo = propertyList.getFObj(); String fallbackValue = (propId == Constants.PR_PAGE_HEIGHT) - ? fo.getFOEventHandler().getUserAgent().getPageHeight() - : fo.getFOEventHandler().getUserAgent().getPageWidth(); + ? fo.getUserAgent().getPageHeight() + : fo.getUserAgent().getPageWidth(); if (p.getEnum() == Constants.EN_INDEFINITE) { int otherId = (propId == Constants.PR_PAGE_HEIGHT) diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java index f6bb52cb3..1f782b2ea 100644 --- a/src/java/org/apache/fop/fonts/CustomFont.java +++ b/src/java/org/apache/fop/fonts/CustomFont.java @@ -190,12 +190,17 @@ public abstract class CustomFont extends Typeface return fontBBox; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getFlags() { return flags; } + + /** {@inheritDoc} */ + public boolean isSymbolicFont() { + return ((getFlags() & 4) != 0) || "ZapfDingbatsEncoding".equals(getEncodingName()); + //Note: The check for ZapfDingbats is necessary as the PFM does not reliably indicate + //if a font is symbolic. + } /** * Returns the font weight (100, 200...800, 900). This value may be different from the diff --git a/src/java/org/apache/fop/fonts/FontDescriptor.java b/src/java/org/apache/fop/fonts/FontDescriptor.java index 841d99de2..fb9c7d02e 100644 --- a/src/java/org/apache/fop/fonts/FontDescriptor.java +++ b/src/java/org/apache/fop/fonts/FontDescriptor.java @@ -53,7 +53,11 @@ public interface FontDescriptor extends FontMetrics { */ int getFlags(); - + /** + * Indicates whether the font is a symbolic font. + * @return true if the font is a symbolic font (i.e. Symbol or ZapfDingbats) + */ + boolean isSymbolicFont(); /** * Returns the font's bounding box. * @return the bounding box diff --git a/src/java/org/apache/fop/fonts/FontReader.java b/src/java/org/apache/fop/fonts/FontReader.java index 51d90c7e5..6f148f503 100644 --- a/src/java/org/apache/fop/fonts/FontReader.java +++ b/src/java/org/apache/fop/fonts/FontReader.java @@ -27,8 +27,6 @@ import java.util.Set; import javax.xml.parsers.SAXParserFactory; -import org.apache.fop.apps.FOPException; -import org.apache.fop.fonts.apps.TTFReader; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.Locator; @@ -36,6 +34,9 @@ import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; +import org.apache.fop.apps.FOPException; +import org.apache.fop.fonts.apps.TTFReader; + /** * Class for reading a metric.xml file and creating a font object. * Typical usage: @@ -228,11 +229,11 @@ public class FontReader extends DefaultHandler { if ("font-name".equals(localName)) { returnFont.setFontName(content); } else if ("full-name".equals(localName)) { - multiFont.setFullName(content); + returnFont.setFullName(content); } else if ("family-name".equals(localName)) { Set s = new java.util.HashSet(); s.add(content); - multiFont.setFamilyNames(s); + returnFont.setFamilyNames(s); } else if ("ttc-name".equals(localName) && isCID) { multiFont.setTTCName(content); } else if ("encoding".equals(localName)) { diff --git a/src/java/org/apache/fop/fonts/FontSelector.java b/src/java/org/apache/fop/fonts/FontSelector.java new file mode 100644 index 000000000..5e3ed816e --- /dev/null +++ b/src/java/org/apache/fop/fonts/FontSelector.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fonts; + +import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOText; +import org.apache.fop.fo.flow.Character; +import org.apache.fop.fo.properties.CommonFont; + +/** + * Helper class for automatic font selection. + * <p> + * TODO: Check if this could be merged with another font class, such as + * {@link FontManager}. + */ +public final class FontSelector { + private FontSelector() { + // Static since this is an utility class. + } + + private static Font selectFontForCharacter(char c, FONode fonode, + CommonFont commonFont, PercentBaseContext context) { + FontInfo fi = fonode.getFOEventHandler().getFontInfo(); + FontTriplet[] fontkeys = commonFont.getFontState(fi); + for (int i = 0; i < fontkeys.length; i++) { + Font font = fi.getFontInstance(fontkeys[i], commonFont.fontSize + .getValue(context)); + if (font.hasChar(c)) { + return font; + } + } + return fi.getFontInstance(fontkeys[0], commonFont.fontSize + .getValue(context)); + + } + + /** + * Selects a font which is able to display the given character. + * + * @param fobj + * a Character object containing the character and its + * attributes. + * @param context + * the Percent-based context needed for creating the actual font. + * @return a Font object. + */ + public static Font selectFontForCharacter(Character fobj, + PercentBaseContext context) { + return FontSelector.selectFontForCharacter(fobj.getCharacter(), fobj, + fobj.getCommonFont(), context); + } + + /** + * Selects a font which is able to display the given character. + * + * @param c + * character to find. + * @param text + * the text object which contains the character + * @param context + * the Percent-based context needed for creating the actual font. + * @return a Font object. + */ + public static Font selectFontForCharacterInText(char c, FOText text, + PercentBaseContext context) { + return FontSelector.selectFontForCharacter(c, text, text + .getCommonFont(), context); + } + + /** + * Selects a font which is able to display the most of the given characters. + * + * @param charSeq + * Text to go through + * @param firstIndex + * first index within text. + * @param breakIndex + * last index +1 within text. + * @param text + * the text object which contains the character + * @param context + * the Percent-based context needed for creating the actual font. + * @return a Font object. + */ + public static Font selectFontForCharactersInText(CharSequence charSeq, + int firstIndex, int breakIndex, FOText text, + PercentBaseContext context) { + + final FontInfo fi = text.getFOEventHandler().getFontInfo(); + final CommonFont commonFont = text.getCommonFont(); + final FontTriplet[] fontkeys = commonFont.getFontState(fi); + final int numFonts = fontkeys.length; + final Font[] fonts = new Font[numFonts]; + final int[] fontCount = new int[numFonts]; + + for (int fontnum = 0; fontnum < numFonts; fontnum++) { + final Font font = fi.getFontInstance(fontkeys[fontnum], + commonFont.fontSize.getValue(context)); + fonts[fontnum] = font; + for (int pos = firstIndex; pos < breakIndex; pos++) { + if (font.hasChar(charSeq.charAt(pos))) { + fontCount[fontnum]++; + } + } + + // quick fall through if all characters can be displayed + if (fontCount[fontnum] == (breakIndex - firstIndex)) { + return font; + } + } + + Font font = fonts[0]; + int max = fontCount[0]; + + for (int fontnum = 1; fontnum < numFonts; fontnum++) { + final int curCount = fontCount[fontnum]; + if (curCount > max) { + font = fonts[fontnum]; + max = curCount; + } + } + return font; + } + +} diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index b4f7773a3..70b971fff 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -321,14 +321,18 @@ public class LazyFont extends Typeface implements FontDescriptor { return realFontDescriptor.getAscender(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getFlags() { load(true); return realFontDescriptor.getFlags(); } + /** {@inheritDoc} */ + public boolean isSymbolicFont() { + load(true); + return realFontDescriptor.isSymbolicFont(); + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index f1b7b1b48..bdf0acc32 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -50,8 +50,8 @@ public class SingleByteFont extends CustomFont { /** {@inheritDoc} */ public boolean isEmbeddable() { - return (getEmbedFileName() == null && getEmbedResourceName() == null) ? false - : true; + return (!(getEmbedFileName() == null + && getEmbedResourceName() == null)); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java b/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java index 55a7ae1c0..d59fd5c7e 100644 --- a/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java @@ -32,6 +32,7 @@ public class UnixFontDirFinder extends NativeFontDirFinder { return new String[] { System.getProperty("user.home") + "/.fonts", // user "/usr/local/fonts", // local + "/usr/local/share/fonts", // local shared "/usr/share/fonts", // system "/usr/X11R6/lib/X11/fonts" // X }; diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java index 7fd289c05..27189bf86 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java @@ -34,17 +34,17 @@ import org.apache.fop.fo.FObj; public abstract class AbstractBaseLayoutManager implements LayoutManager, PercentBaseContext { - /** Indicator if this LM generates reference areas */ + /** Indicator if this LM generates reference areas. */ protected boolean generatesReferenceArea = false; - /** Indicator if this LM generates block areas */ + /** Indicator if this LM generates block areas. */ protected boolean generatesBlockArea = false; - /** The formatting object for this LM */ + /** The formatting object for this LM. */ protected final FObj fobj; /** * logging instance */ - private static Log log = LogFactory.getLog(AbstractBaseLayoutManager.class); + private static final Log LOG = LogFactory.getLog(AbstractBaseLayoutManager.class); /** * Abstract base layout manager. @@ -69,8 +69,8 @@ public abstract class AbstractBaseLayoutManager // --------- Property Resolution related functions --------- // /** {@inheritDoc} */ - public int getBaseLength(int lengthBase, FObj fobj) { - if (fobj == this.fobj) { + public int getBaseLength(int lengthBase, FObj fobjx) { + if (fobjx == this.fobj) { switch (lengthBase) { case LengthBase.CONTAINING_BLOCK_WIDTH: return getAncestorBlockAreaIPD(); @@ -81,20 +81,20 @@ public abstract class AbstractBaseLayoutManager case LengthBase.CONTAINING_REFAREA_WIDTH: return getReferenceAreaIPD(); default: - log.error("Unknown base type for LengthBase:" + lengthBase); + LOG.error("Unknown base type for LengthBase:" + lengthBase); return 0; } } else { LayoutManager lm = getParent(); - while (lm != null && fobj != lm.getFObj()) { + while (lm != null && fobjx != lm.getFObj()) { lm = lm.getParent(); } if (lm != null) { - return lm.getBaseLength(lengthBase, fobj); + return lm.getBaseLength(lengthBase, fobjx); } } - log.error("Cannot find LM to handle given FO for LengthBase. (" - + fobj.getContextInfo() + ")"); + LOG.error("Cannot find LM to handle given FO for LengthBase. (" + + fobjx.getContextInfo() + ")"); return 0; } @@ -111,7 +111,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -128,7 +128,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -141,7 +141,7 @@ public abstract class AbstractBaseLayoutManager if (lm != null) { return lm.getContentAreaIPD(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -154,7 +154,7 @@ public abstract class AbstractBaseLayoutManager if (lm != null) { return lm.getContentAreaBPD(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -171,7 +171,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -188,7 +188,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 4ef0579f2..c830220e7 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -28,6 +28,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.Constants; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * Abstract base class for breakers (page breakers, static region handlers etc.). @@ -116,8 +117,8 @@ public abstract class AbstractBreaker { public KnuthSequence endSequence(Position breakPosition) { // remove glue and penalty item at the end of the paragraph while (this.size() > ignoreAtStart - && !((KnuthElement)this.get(this.size() - 1)).isBox()) { - this.remove(this.size() - 1); + && !((KnuthElement) ListUtil.getLast(this)).isBox()) { + ListUtil.removeLast(this); } if (this.size() > ignoreAtStart) { // add the elements representing the space at the end of the last line @@ -211,11 +212,11 @@ public abstract class AbstractBreaker { * getNextKnuthElements() implementation(s) that are to be called. * @return LinkedList of Knuth elements. */ - protected abstract LinkedList getNextKnuthElements(LayoutContext context, int alignment); + protected abstract List getNextKnuthElements(LayoutContext context, int alignment); /** @return true if there's no content that could be handled. */ public boolean isEmpty() { - return (this.blockLists.size() == 0); + return (this.blockLists.isEmpty()); } protected void startPart(BlockSequence list, int breakClass) { @@ -549,9 +550,9 @@ public abstract class AbstractBreaker { childLC.signalSpanChange(Constants.NOT_SET); BlockSequence blockList; - LinkedList returnedList = getNextKnuthElements(childLC, alignment); + List returnedList = getNextKnuthElements(childLC, alignment); if (returnedList != null) { - if (returnedList.size() == 0) { + if (returnedList.isEmpty()) { nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn); return nextSequenceStartsOn; } @@ -561,8 +562,9 @@ public abstract class AbstractBreaker { nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn); Position breakPosition = null; - if (((KnuthElement) returnedList.getLast()).isForcedBreak()) { - KnuthPenalty breakPenalty = (KnuthPenalty)returnedList.removeLast(); + if (((KnuthElement) ListUtil.getLast(returnedList)).isForcedBreak()) { + KnuthPenalty breakPenalty = (KnuthPenalty) ListUtil + .removeLast(returnedList); breakPosition = breakPenalty.getPosition(); switch (breakPenalty.getBreakClass()) { case Constants.EN_PAGE: @@ -743,12 +745,12 @@ public abstract class AbstractBreaker { if (!bBoxSeen) { // this is the first box met in this page bBoxSeen = true; - } else if (unconfirmedList.size() > 0) { - // glue items in unconfirmedList were not after - // the last box - // in this page; they must be added to - // blockSpaceList - while (unconfirmedList.size() > 0) { + } else { + while (!unconfirmedList.isEmpty()) { + // glue items in unconfirmedList were not after + // the last box + // in this page; they must be added to + // blockSpaceList KnuthGlue blockSpace = (KnuthGlue) unconfirmedList .removeFirst(); spaceMaxAdjustment.max += ((KnuthGlue) blockSpace) diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index 3f2143bae..13ea66d1f 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -20,14 +20,12 @@ package org.apache.fop.layoutmgr; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.area.Area; import org.apache.fop.area.PageViewport; import org.apache.fop.fo.Constants; @@ -152,7 +150,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, + public List getNextKnuthElements(LayoutContext context, int alignment) { log.warn("null implementation of getNextKnuthElements() called!"); setFinished(true); @@ -160,7 +158,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, int alignment) { log.warn("null implementation of getChangeKnuthElement() called!"); return null; diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 0e6c2cb40..732cb1ae7 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -39,6 +39,7 @@ import org.apache.fop.fo.flow.BlockContainer; import org.apache.fop.fo.properties.CommonAbsolutePosition; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; +import org.apache.fop.util.ListUtil; /** * LayoutManager for a block-container FO. @@ -189,7 +190,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { resetSpaces(); if (isAbsoluteOrFixed()) { return getNextKnuthElementsAbsolute(context, alignment); @@ -247,9 +248,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager MinOptMax stackLimit = new MinOptMax(relDims.bpd); - LinkedList returnedList; - LinkedList contentList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList; + List contentList = new LinkedList(); + List returnList = new LinkedList(); if (!breakBeforeServed) { try { @@ -285,13 +286,13 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // get elements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); - if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) { + if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { //Propagate keep-with-previous up from the first child context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); childLC.clearKeepWithPreviousPending(); } if (returnedList.size() == 1 - && ((ListElement)returnedList.getFirst()).isForcedBreak()) { + && ((ListElement)returnedList.get(0)).isForcedBreak()) { // a descendant of this block has break-before /* if (returnList.size() == 0) { @@ -317,11 +318,12 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager addInBetweenBreak(contentList, context, childLC); } contentList.addAll(returnedList); - if (returnedList.size() == 0) { + if (returnedList.isEmpty()) { //Avoid NoSuchElementException below (happens with empty blocks) continue; } - if (((ListElement)returnedList.getLast()).isForcedBreak()) { + if (((ListElement) ListUtil.getLast(returnedList)) + .isForcedBreak()) { // a descendant of this block has break-after if (curLM.isFinished()) { // there is no other content in this block; @@ -392,7 +394,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return returnList; } - private LinkedList getNextKnuthElementsAbsolute(LayoutContext context, int alignment) { + private List getNextKnuthElementsAbsolute(LayoutContext context, int alignment) { autoHeight = false; boolean switchedProgressionDirection @@ -515,7 +517,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } updateRelDims(0, 0, false); } - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); if (!breaker.isEmpty()) { Position bcPosition = new BlockContainerPosition(this, breaker); returnList.add(new KnuthBox(0, notifyPos(bcPosition), false)); @@ -622,9 +624,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return lc; } - protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + protected List getNextKnuthElements(LayoutContext context, int alignment) { LayoutManager curLM; // currently active LM - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); @@ -632,7 +634,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); - LinkedList returnedList = null; + List returnedList = null; if (!curLM.isFinished()) { returnedList = curLM.getNextKnuthElements(childLC, alignment); } @@ -723,7 +725,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // "unwrap" the NonLeafPositions stored in parentIter // and put them in a new list; - LinkedList positionList = new LinkedList(); + List positionList = new LinkedList(); Position pos; boolean bSpaceBefore = false; boolean bSpaceAfter = false; @@ -753,7 +755,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // pos was created by this BCLM and was inside an element // representing space before or after // this means the space was not discarded - if (positionList.size() == 0 && bcpos == null) { + if (positionList.isEmpty() && bcpos == null) { // pos was in the element representing space-before bSpaceBefore = true; } else { @@ -798,10 +800,12 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // // the last item inside positionList is a Position; // // this means that the paragraph has been split // // between consecutive pages - LinkedList splitList = new LinkedList(); + List splitList = new LinkedList(); int splitLength = 0; - int iFirst = ((MappingPosition) positionList.getFirst()).getFirstIndex(); - int iLast = ((MappingPosition) positionList.getLast()).getLastIndex(); + int iFirst = ((MappingPosition) positionList.get(0)) + .getFirstIndex(); + int iLast = ((MappingPosition) ListUtil.getLast(positionList)) + .getLastIndex(); // copy from storedList to splitList all the elements from // iFirst to iLast ListIterator storedListIterator = storedList.listIterator(iFirst); diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index c5c7d9445..b6b6f921f 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -113,7 +113,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { resetSpaces(); return super.getNextKnuthElements(context, alignment); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index b208e4e9b..4360f62e9 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -36,6 +36,7 @@ import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.layoutmgr.inline.InlineLayoutManager; import org.apache.fop.layoutmgr.inline.LineLayoutManager; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * Base LayoutManager class for all areas which stack their child @@ -63,7 +64,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /** space-after value adjusted for block-progression-unit handling */ protected int adjustedSpaceAfter = 0; /** Only used to store the original list when createUnitElements is called */ - protected LinkedList storedList = null; + protected List storedList = null; /** Indicates whether break before has been served or not */ protected boolean breakBeforeServed = false; /** Indicates whether the first visible mark has been returned by this LM, yet */ @@ -235,7 +236,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { //log.debug("BLM.getNextKnuthElements> keep-together = " // + layoutProps.keepTogether.getType()); //log.debug(" keep-with-previous = " + @@ -249,9 +250,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager updateContentAreaIPDwithOverconstrainedAdjust(); - LinkedList returnedList = null; - LinkedList contentList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList = null; + List contentList = new LinkedList(); + List returnList = new LinkedList(); if (!breakBeforeServed) { try { @@ -296,23 +297,23 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // get elements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); - if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) { + if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { //Propagate keep-with-previous up from the first child context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); childLC.clearKeepWithPreviousPending(); } if (returnedList != null && returnedList.size() == 1 - && ((ListElement) returnedList.getFirst()).isForcedBreak()) { + && ((ListElement) returnedList.get(0)).isForcedBreak()) { if (curLM.isFinished() && !hasNextChildLM()) { // a descendant of this block has break-before - forcedBreakAfterLast = (BreakElement) returnedList.getFirst(); + forcedBreakAfterLast = (BreakElement) returnedList.get(0); context.clearPendingMarks(); break; } - if (contentList.size() == 0) { + if (contentList.isEmpty()) { // Empty fo:block, zero-length box makes sure the IDs and/or markers // are registered and borders/padding are painted. returnList.add(new KnuthBox(0, notifyPos(new Position(this)), false)); @@ -339,15 +340,17 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // before the one handled by curLM addInBetweenBreak(contentList, context, childLC); } - if (returnedList == null || returnedList.size() == 0) { + if (returnedList == null || returnedList.isEmpty()) { //Avoid NoSuchElementException below (happens with empty blocks) continue; } contentList.addAll(returnedList); - if (((ListElement) returnedList.getLast()).isForcedBreak()) { + if (((ListElement) ListUtil.getLast(returnedList)) + .isForcedBreak()) { // a descendant of this block has break-after if (curLM.isFinished() && !hasNextChildLM()) { - forcedBreakAfterLast = (BreakElement)contentList.removeLast(); + forcedBreakAfterLast = (BreakElement) ListUtil + .removeLast(contentList); context.clearPendingMarks(); break; } @@ -379,7 +382,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /* end of extension */ returnedList = new LinkedList(); - if (contentList.size() > 0) { + if (!contentList.isEmpty()) { wrapPositionElements(contentList, returnList); } else if (forcedBreakAfterLast == null) { // Empty fo:block, zero-length box makes sure the IDs and/or markers @@ -414,7 +417,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param context the current layout context * @param childLC the currently active child layout context */ - protected void addInBetweenBreak(LinkedList contentList, LayoutContext context, + protected void addInBetweenBreak(List contentList, LayoutContext context, LayoutContext childLC) { if (mustKeepTogether() || context.isKeepWithNextPending() @@ -438,7 +441,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager return; } - ListElement last = (ListElement)contentList.getLast(); + ListElement last = (ListElement) ListUtil.getLast(contentList); if (last.isGlue()) { // the last element in contentList is a glue; // it is a feasible breakpoint, there is no need to add @@ -585,7 +588,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { /*LF*/ //log.debug(""); /*LF*/ //log.debug(" BLM.getChangedKnuthElements> inizio: oldList.size() = " // + oldList.size()); @@ -593,8 +596,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager KnuthElement returnedElement; KnuthElement currElement = null; KnuthElement prevElement = null; - LinkedList returnedList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList = new LinkedList(); + List returnList = new LinkedList(); int fromIndex = 0; // "unwrap" the Positions stored in the elements @@ -691,7 +694,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // add an infinite penalty to forbid a break between blocks returnedList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new Position(this), false)); - } else if (bSomethingAdded && !((KnuthElement) returnedList.getLast()).isGlue()) { + } else if (bSomethingAdded + && !((KnuthElement) ListUtil.getLast(returnedList)) + .isGlue()) { // add a null penalty to allow a break between blocks returnedList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } @@ -710,8 +715,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // currLM == this // there are no more elements to add // remove the last penalty added to returnedList - if (returnedList.size() > 0) { - returnedList.removeLast(); + if (!returnedList.isEmpty()) { + ListUtil.removeLast(returnedList); } //log.debug(" BLM.getChangedKnuthElements> elementi propri, ignorati, da " // + fromIndex + " a " + workList.size()); @@ -943,7 +948,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param isFirst true if this is the first time a layout manager instance needs to generate * border and padding */ - protected void addKnuthElementsForBorderPaddingBefore(LinkedList returnList, boolean isFirst) { + protected void addKnuthElementsForBorderPaddingBefore(List returnList, boolean isFirst) { //Border and Padding (before) CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground(); if (borderAndPadding != null) { @@ -970,7 +975,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param isLast true if this is the last time a layout manager instance needs to generate * border and padding */ - protected void addKnuthElementsForBorderPaddingAfter(LinkedList returnList, boolean isLast) { + protected void addKnuthElementsForBorderPaddingAfter(List returnList, boolean isLast) { //Border and Padding (after) CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground(); if (borderAndPadding != null) { @@ -997,7 +1002,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param context the layout context * @return true if an element has been added due to a break-before. */ - protected boolean addKnuthElementsForBreakBefore(LinkedList returnList, + protected boolean addKnuthElementsForBreakBefore(List returnList, LayoutContext context) { int breakBefore = -1; if (fobj instanceof org.apache.fop.fo.flow.Block) { @@ -1030,7 +1035,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param context the layout context * @return true if an element has been added due to a break-after. */ - protected boolean addKnuthElementsForBreakAfter(LinkedList returnList, + protected boolean addKnuthElementsForBreakAfter(List returnList, LayoutContext context) { int breakAfter = -1; if (fobj instanceof org.apache.fop.fo.flow.Block) { @@ -1062,7 +1067,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param returnList return list to add the additional elements to * @param alignment vertical alignment */ - protected void addKnuthElementsForSpaceBefore(LinkedList returnList/*, + protected void addKnuthElementsForSpaceBefore(List returnList/*, Position returnPosition*/, int alignment) { SpaceProperty spaceBefore = getSpaceBeforeProperty(); // append elements representing space-before @@ -1111,7 +1116,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param returnList return list to add the additional elements to * @param alignment vertical alignment */ - protected void addKnuthElementsForSpaceAfter(LinkedList returnList/*, Position returnPosition*/, + protected void addKnuthElementsForSpaceAfter(List returnList/*, Position returnPosition*/, int alignment) { SpaceProperty spaceAfter = getSpaceAfterProperty(); // append elements representing space-after @@ -1156,22 +1161,22 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager }*/ } - protected LinkedList createUnitElements(LinkedList oldList) { + protected List createUnitElements(List oldList) { //log.debug("Start conversion: " + oldList.size() // + " elements, space-before.min=" + layoutProps.spaceBefore.getSpace().min // + " space-after.min=" + layoutProps.spaceAfter.getSpace().min); // add elements at the beginning and at the end of oldList // representing minimum spaces - LayoutManager lm = ((KnuthElement)oldList.getFirst()).getLayoutManager(); + LayoutManager lm = ((KnuthElement)oldList.get(0)).getLayoutManager(); boolean bAddedBoxBefore = false; boolean bAddedBoxAfter = false; if (adjustedSpaceBefore > 0) { - oldList.addFirst(new KnuthBox(adjustedSpaceBefore, + oldList.add(0, new KnuthBox(adjustedSpaceBefore, new Position(lm), true)); bAddedBoxBefore = true; } if (adjustedSpaceAfter > 0) { - oldList.addLast(new KnuthBox(adjustedSpaceAfter, + oldList.add(new KnuthBox(adjustedSpaceAfter, new Position(lm), true)); bAddedBoxAfter = true; } @@ -1399,10 +1404,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // remove elements at the beginning and at the end of oldList // representing minimum spaces if (adjustedSpaceBefore > 0) { - oldList.removeFirst(); + oldList.remove(0); } if (adjustedSpaceAfter > 0) { - oldList.removeLast(); + ListUtil.removeLast(oldList); } // if space-before.conditionality is "discard", correct newList @@ -1459,7 +1464,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager newList.addLast(new KnuthBox(wrongBox.getW() - decreasedLength, wrongBox.getPosition(), false)); // add preserved elements - if (preserveList.size() > 0) { + if (!preserveList.isEmpty()) { newList.addAll(preserveList); } // insert the correct glue diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java index 9a87e71c4..c04d197e4 100644 --- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java +++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java @@ -19,16 +19,20 @@ package org.apache.fop.layoutmgr; -import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * Utilities for Knuth element lists. */ -public class ElementListUtils { +public final class ElementListUtils { + + private ElementListUtils() { + // Utility class. + } /** * Removes legal breaks in an element list. A constraint can be specified to limit the @@ -38,7 +42,7 @@ public class ElementListUtils { * @param constraint min/opt/max value to restrict the range in which the breaks are removed. * @return true if the opt constraint is bigger than the list contents */ - public static boolean removeLegalBreaks(LinkedList elements, MinOptMax constraint) { + public static boolean removeLegalBreaks(List elements, MinOptMax constraint) { return removeLegalBreaks(elements, constraint.opt); } @@ -50,7 +54,7 @@ public class ElementListUtils { * @param constraint value to restrict the range in which the breaks are removed. * @return true if the constraint is bigger than the list contents */ - public static boolean removeLegalBreaks(LinkedList elements, int constraint) { + public static boolean removeLegalBreaks(List elements, int constraint) { int len = 0; ListIterator iter = elements.listIterator(); while (iter.hasNext()) { @@ -97,7 +101,7 @@ public class ElementListUtils { * @param constraint value to restrict the range in which the breaks are removed. * @return true if the constraint is bigger than the list contents */ - public static boolean removeLegalBreaksFromEnd(LinkedList elements, int constraint) { + public static boolean removeLegalBreaksFromEnd(List elements, int constraint) { int len = 0; ListIterator i = elements.listIterator(elements.size()); while (i.hasPrevious()) { @@ -184,8 +188,8 @@ public class ElementListUtils { * @param elems the element list * @return true if the list ends with a forced break */ - public static boolean endsWithForcedBreak(LinkedList elems) { - ListElement last = (ListElement)elems.getLast(); + public static boolean endsWithForcedBreak(List elems) { + ListElement last = (ListElement) ListUtil.getLast(elems); return last.isForcedBreak(); } @@ -195,8 +199,8 @@ public class ElementListUtils { * @param elems the element list * @return true if the list ends with a non-infinite penalty */ - public static boolean endsWithNonInfinitePenalty(LinkedList elems) { - ListElement last = (ListElement)elems.getLast(); + public static boolean endsWithNonInfinitePenalty(List elems) { + ListElement last = (ListElement) ListUtil.getLast(elems); if (last.isPenalty() && ((KnuthPenalty)last).getP() < KnuthElement.INFINITE) { return true; } else if (last instanceof BreakElement diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 9cd5c622d..1c8fb679f 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -64,16 +64,16 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { // set layout dimensions int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth(); - int flowBPD = (int) getCurrentPV().getBodyRegion().getBPD(); + int flowBPD = getCurrentPV().getBodyRegion().getBPD(); // currently active LM LayoutManager curLM; - LinkedList returnedList; - LinkedList returnList = new LinkedList(); + List returnedList; + List returnList = new LinkedList(); while ((curLM = getChildLM()) != null) { if (!(curLM instanceof WrapperLayoutManager) @@ -114,7 +114,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } // "wrap" the Position inside each element - LinkedList tempList = returnedList; + List tempList = returnedList; returnedList = new LinkedList(); wrapPositionElements(tempList, returnedList); @@ -213,11 +213,11 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, /*int flaggedPenalty,*/ int alignment) { + public List getChangedKnuthElements(List oldList, /*int flaggedPenalty,*/ int alignment) { ListIterator oldListIterator = oldList.listIterator(); KnuthElement returnedElement; - LinkedList returnedList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList = new LinkedList(); + List returnList = new LinkedList(); KnuthElement prevElement = null; KnuthElement currElement = null; int fromIndex = 0; @@ -257,7 +257,8 @@ public class FlowLayoutManager extends BlockStackingLayoutManager // add an infinite penalty to forbid a break between blocks returnedList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new Position(this), false)); - } else if (!((KnuthElement) returnedList.getLast()).isGlue()) { + } else if (!((KnuthElement) returnedList.get(returnedList + .size() - 1)).isGlue()) { // add a null penalty to allow a break between blocks returnedList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } diff --git a/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java b/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java index 53f285377..364c896ad 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java @@ -19,9 +19,10 @@ package org.apache.fop.layoutmgr; -import org.apache.fop.traits.MinOptMax; - import java.util.LinkedList; +import java.util.List; + +import org.apache.fop.traits.MinOptMax; /** * Knuth box used to represent a line in block-progression-dimension (i.e. the width is its height). @@ -34,9 +35,9 @@ public class KnuthBlockBox extends KnuthBox { * it isn't possible to get the opt value stored in a MinOptMax object. */ private int bpd; - private LinkedList footnoteList; + private List footnoteList; /** List of Knuth elements. This is a list of LinkedList elements. */ - private LinkedList elementLists = null; + private List elementLists = null; /** * Creates a new box. @@ -61,7 +62,7 @@ public class KnuthBlockBox extends KnuthBox { * @param pos the Position stored in this box * @param bAux is this box auxiliary? */ - public KnuthBlockBox(int w, LinkedList list, Position pos, boolean bAux) { + public KnuthBlockBox(int w, List list, Position pos, boolean bAux) { super(w, pos, bAux); ipdRange = new MinOptMax(0); bpd = 0; @@ -71,7 +72,7 @@ public class KnuthBlockBox extends KnuthBox { /** * @return the LMs for the footnotes cited in this box. */ - public LinkedList getFootnoteBodyLMs() { + public List getFootnoteBodyLMs() { return footnoteList; } @@ -86,7 +87,7 @@ public class KnuthBlockBox extends KnuthBox { * Adds the given list of Knuth elements to this box' list of elements. * @param list elements corresponding to a footnote body */ - public void addElementList(LinkedList list) { + public void addElementList(List list) { if (elementLists == null) { elementLists = new LinkedList(); } @@ -98,7 +99,7 @@ public class KnuthBlockBox extends KnuthBox { * @return a list of KnuthElement sequences corresponding to footnotes cited in this * box */ - public LinkedList getElementLists() { + public List getElementLists() { return elementLists; } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManager.java b/src/java/org/apache/fop/layoutmgr/LayoutManager.java index 0b17c9a27..ad0d9f69c 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManager.java @@ -19,7 +19,6 @@ package org.apache.fop.layoutmgr; -import java.util.LinkedList; import java.util.List; import org.apache.fop.area.Area; @@ -135,10 +134,10 @@ public interface LayoutManager extends PercentBaseContext { * of the node assigned to the LM * * @param context the LayoutContext used to store layout information - * @param alignment the desired text alignement + * @param alignment the desired text alignment * @return the list of KnuthElements */ - LinkedList getNextKnuthElements(LayoutContext context, int alignment); + List getNextKnuthElements(LayoutContext context, int alignment); /** * Get a sequence of KnuthElements representing the content @@ -146,7 +145,7 @@ public interface LayoutManager extends PercentBaseContext { * * In the context of line breaking, this method is called after hyphenation has * been performed, in order to receive the sequence of elements representing the - * text together with all possibile hyphenation points. + * text together with all possible hyphenation points. * For example, if the text "representation" originates a single box element * when getNextKnuthElements() is called, it will be now split in syllables * (rep-re-sen-ta-tion) each one originating a box and divided by additional @@ -175,7 +174,7 @@ public interface LayoutManager extends PercentBaseContext { * @param alignment the desired text alignment * @return the updated list of KnuthElements */ - LinkedList getChangedKnuthElements(List oldList, int alignment); + List getChangedKnuthElements(List oldList, int alignment); /** * Returns the IPD of the content area diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java index 087963013..862c0a4be 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java @@ -41,8 +41,8 @@ import org.apache.fop.fo.flow.Character; import org.apache.fop.fo.flow.ExternalGraphic; import org.apache.fop.fo.flow.Footnote; import org.apache.fop.fo.flow.Inline; -import org.apache.fop.fo.flow.InlineLevel; import org.apache.fop.fo.flow.InlineContainer; +import org.apache.fop.fo.flow.InlineLevel; import org.apache.fop.fo.flow.InstreamForeignObject; import org.apache.fop.fo.flow.Leader; import org.apache.fop.fo.flow.ListBlock; @@ -224,7 +224,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { public static class FOTextLayoutManagerMaker extends Maker { public void make(FONode node, List lms) { FOText foText = (FOText) node; - if (foText.endIndex - foText.startIndex > 0) { + if (foText.length() > 0) { lms.add(new TextLayoutManager(foText)); } } diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index d6be75758..b25e4bd4f 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -135,8 +135,8 @@ public class PageBreaker extends AbstractBreaker { } /** {@inheritDoc} */ - protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) { - LinkedList contentList = null; + protected List getNextKnuthElements(LayoutContext context, int alignment) { + List contentList = null; while (!childFLM.isFinished() && contentList == null) { contentList = childFLM.getNextKnuthElements(context, alignment); @@ -156,7 +156,7 @@ public class PageBreaker extends AbstractBreaker { footnoteContext.setStackLimitBP(context.getStackLimitBP()); footnoteContext.setRefIPD(pslm.getCurrentPV() .getRegionReference(Constants.FO_REGION_BODY).getIPD()); - LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs(); + List footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs(); ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator(); // store the lists of elements representing the footnote bodies // in the box representing the line containing their references diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index 5e3d0a887..9e0b42ecb 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -21,11 +21,11 @@ package org.apache.fop.layoutmgr; import java.util.ArrayList; import java.util.LinkedList; +import java.util.List; import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; import org.apache.fop.layoutmgr.AbstractBreaker.PageBreakPosition; @@ -230,7 +230,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { * @param elementLists list of KnuthElement sequences corresponding to the footnotes * bodies */ - private void handleFootnotes(LinkedList elementLists) { + private void handleFootnotes(List elementLists) { // initialization if (!footnotesPending) { footnotesPending = true; @@ -286,7 +286,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { return returnValue; } - private void resetFootnotes(LinkedList elementLists) { + private void resetFootnotes(List elementLists) { for (int i = 0; i < elementLists.size(); i++) { /*LinkedList removedList = (LinkedList)*/footnotesList.remove(footnotesList.size() - 1); lengthList.remove(lengthList.size() - 1); @@ -325,7 +325,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // this page contains some footnote citations // add the footnote separator width actualWidth += footnoteSeparatorLength.opt; - if (actualWidth + allFootnotes <= getLineWidth()) { + if (actualWidth + allFootnotes <= getLineWidth(activeNode.line)) { // there is enough space to insert all footnotes: // add the whole allFootnotes length actualWidth += allFootnotes; @@ -337,7 +337,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { = checkCanDeferOldFootnotes(pageNode, elementIndex)) || newFootnotes) && (footnoteSplit = getFootnoteSplit(pageNode, - getLineWidth() - actualWidth, canDeferOldFootnotes)) > 0) { + getLineWidth(activeNode.line) - actualWidth, canDeferOldFootnotes)) > 0) { // it is allowed to break or even defer footnotes if either: // - there are new footnotes in the last piece of content, and // there is space to add at least a piece of the first one @@ -683,7 +683,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { insertedFootnotesLength = lastNode.totalFootnotes; footnoteListIndex = lastNode.footnoteListIndex; footnoteElementIndex = lastNode.footnoteElementIndex; - int availableBPD = getLineWidth(); + int availableBPD = getLineWidth(lastNode.line); int split = 0; KnuthPageNode prevNode = lastNode; @@ -718,7 +718,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { removeNode(prevNode.line, prevNode); prevNode = node; - availableBPD = getLineWidth(); + availableBPD = getLineWidth(node.line); } } // create the last node diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java index 5816fe482..c5a3bdeec 100644 --- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java @@ -102,18 +102,17 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager curPage = makeNewPage(false, false); PageBreaker breaker = new PageBreaker(this); - int flowBPD = (int)getCurrentPV().getBodyRegion().getRemainingBPD(); + int flowBPD = getCurrentPV().getBodyRegion().getRemainingBPD(); breaker.doLayout(flowBPD); finishPage(); } - + /** {@inheritDoc} */ public void finishPageSequence() { if (pageSeq.hasId()) { idTracker.signalIDProcessed(pageSeq.getId()); } - pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum, (currentPageNum - startPageNum) + 1); areaTreeHandler.notifyPageSequenceFinished(pageSeq, @@ -150,9 +149,9 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager return; } - StaticContentLayoutManager lm = (StaticContentLayoutManager) - getLayoutManagerMaker().makeStaticContentLayoutManager( - this, sc, reg); + StaticContentLayoutManager lm = getLayoutManagerMaker() + .makeStaticContentLayoutManager( + this, sc, reg); lm.doLayout(); } @@ -166,5 +165,5 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager super.finishPage(); } - + } diff --git a/src/java/org/apache/fop/layoutmgr/SpaceResolver.java b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java index 58de6a980..051f76d7f 100644 --- a/src/java/org/apache/fop/layoutmgr/SpaceResolver.java +++ b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java @@ -614,7 +614,7 @@ public class SpaceResolver { * Resolves unresolved elements applying the space resolution rules defined in 4.3.1. * @param elems the element list */ - public static void resolveElementList(LinkedList elems) { + public static void resolveElementList(List elems) { if (log.isTraceEnabled()) { log.trace(elems); } diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 42ddcc220..44e0cc476 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -38,6 +38,7 @@ import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; import org.apache.fop.layoutmgr.inline.TextLayoutManager; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * LayoutManager for an fo:flow object. @@ -87,7 +88,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { if (true) { throw new UnsupportedOperationException( "Shouldn't this method be emptied because it's never called at all?"); @@ -102,8 +103,8 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { BlockLevelLayoutManager curLM; BlockLevelLayoutManager prevLM = null; MinOptMax stackSize = new MinOptMax(); - LinkedList returnedList; - LinkedList returnList = new LinkedList(); + List returnedList; + List returnList = new LinkedList(); while ((curLM = ((BlockLevelLayoutManager) getChildLM())) != null) { if (curLM instanceof InlineLevelLayoutManager) { @@ -125,7 +126,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { // + returnedList.size()); // "wrap" the Position inside each element - LinkedList tempList = returnedList; + List tempList = returnedList; KnuthElement tempElement; returnedList = new LinkedList(); ListIterator listIter = tempList.listIterator(); @@ -136,13 +137,13 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { } if (returnedList.size() == 1 - && ((KnuthElement)returnedList.getFirst()).isPenalty() - && ((KnuthPenalty)returnedList.getFirst()).getP() == -KnuthElement.INFINITE) { + && ((KnuthElement)returnedList.get(0)).isPenalty() + && ((KnuthPenalty)returnedList.get(0)).getP() == -KnuthElement.INFINITE) { // a descendant of this flow has break-before returnList.addAll(returnedList); return returnList; } else { - if (returnList.size() > 0) { + if (!returnList.isEmpty()) { // there is a block before this one if (prevLM.mustKeepWithNext() || curLM.mustKeepWithPrevious()) { @@ -150,16 +151,18 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new Position(this), false)); - } else if (!((KnuthElement) returnList.getLast()).isGlue()) { + } else if (!((KnuthElement) ListUtil.getLast(returnList)) + .isGlue()) { // add a null penalty to allow a break between blocks returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } } -/*LF*/ if (returnedList.size() > 0) { // controllare! +/*LF*/ if (!returnedList.isEmpty()) { // controllare! returnList.addAll(returnedList); - if (((KnuthElement)returnedList.getLast()).isPenalty() - && ((KnuthPenalty)returnedList.getLast()).getP() - == -KnuthElement.INFINITE) { + final KnuthElement last = (KnuthElement) ListUtil + .getLast(returnedList); + if (last.isPenalty() + && ((KnuthPenalty) last).getP() == -KnuthElement.INFINITE) { // a descendant of this flow has break-after /*LF*/ //log.debug("FLM - break after!!"); return returnList; @@ -171,10 +174,10 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { setFinished(true); - if (returnList.size() > 0) { - return returnList; - } else { + if (returnList.isEmpty()) { return null; + } else { + return returnList; } } @@ -325,9 +328,9 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { return lc; } - protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + protected List getNextKnuthElements(LayoutContext context, int alignment) { LayoutManager curLM; // currently active LM - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); @@ -335,7 +338,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(context.getWritingMode()); - LinkedList returnedList = null; + List returnedList = null; //The following is a HACK! Ignore leading and trailing white space boolean ignore = curLM instanceof TextLayoutManager; if (!curLM.isFinished()) { @@ -364,6 +367,12 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { protected void doPhase3(PageBreakingAlgorithm alg, int partCount, BlockSequence originalList, BlockSequence effectiveList) { + if (partCount > 1) { + PageBreakPosition pos = (PageBreakPosition)alg.getPageBreaks().getFirst(); + int firstPartLength = ElementListUtils.calcContentLength(effectiveList, + effectiveList.ignoreAtStart, pos.getLeafPos()); + overflow += alg.totalWidth - firstPartLength; + } //Rendering all parts (not just the first) at once for the case where the parts that //overflow should be visible. alg.removeAllPageBreaks(); diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index 38e0c35bc..76002da2f 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -21,7 +21,7 @@ package org.apache.fop.layoutmgr.inline; import java.awt.Dimension; import java.awt.Rectangle; -import java.util.LinkedList; +import java.util.List; import org.apache.fop.area.Area; import org.apache.fop.area.inline.Viewport; @@ -39,16 +39,14 @@ import org.apache.fop.layoutmgr.TraitSetter; */ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManager { - /** The graphics object this LM deals with */ - protected AbstractGraphics fobj; - /** - * Constructor - * @param node the formatting object that creates this area + * Constructor. + * + * @param node + * the formatting object that creates this area */ public AbstractGraphicsLayoutManager(AbstractGraphics node) { super(node); - fobj = node; } /** @@ -57,6 +55,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage * @return the viewport inline area */ private Viewport getInlineArea() { + final AbstractGraphics fobj = (AbstractGraphics)this.fobj; Dimension intrinsicSize = new Dimension( fobj.getIntrinsicWidth(), fobj.getIntrinsicHeight()); @@ -104,7 +103,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, + public List getNextKnuthElements(LayoutContext context, int alignment) { Viewport areaCurrent = getInlineArea(); setCurrentArea(areaCurrent); @@ -113,6 +112,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage /** {@inheritDoc} */ protected AlignmentContext makeAlignmentContext(LayoutContext context) { + final AbstractGraphics fobj = (AbstractGraphics)this.fobj; return new AlignmentContext( get(context).getAllocBPD() , fobj.getAlignmentAdjust() @@ -128,7 +128,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage * the viewport. * @return the appropriate area */ - abstract Area getChildArea(); + protected abstract Area getChildArea(); // --------- Property Resolution related functions --------- // @@ -138,31 +138,14 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage public int getBaseLength(int lengthBase, FObj fobj) { switch (lengthBase) { case LengthBase.IMAGE_INTRINSIC_WIDTH: - return getIntrinsicWidth(); + return ((AbstractGraphics)fobj).getIntrinsicWidth(); case LengthBase.IMAGE_INTRINSIC_HEIGHT: - return getIntrinsicHeight(); + return ((AbstractGraphics)fobj).getIntrinsicHeight(); case LengthBase.ALIGNMENT_ADJUST: return get(null).getBPD(); default: // Delegate to super class return super.getBaseLength(lengthBase, fobj); } } - - /** - * Returns the intrinsic width of the e-g. - * @return the width of the element - */ - protected int getIntrinsicWidth() { - return fobj.getIntrinsicWidth(); - } - - /** - * Returns the intrinsic height of the e-g. - * @return the height of the element - */ - protected int getIntrinsicHeight() { - return fobj.getIntrinsicHeight(); - } - } diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index b292d97bf..c81a23a9c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -26,8 +26,7 @@ import org.apache.fop.area.Trait; import org.apache.fop.fo.flow.Character; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fonts.Font; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.FontSelector; import org.apache.fop.layoutmgr.InlineKnuthSequence; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; @@ -62,7 +61,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public void initialize() { Character fobj = (Character)this.fobj; - font = this.selectFontForCharacter(fobj); + font = FontSelector.selectFontForCharacter(fobj, this); SpaceVal ls = SpaceVal.makeLetterSpacing(fobj.getLetterSpacing()); letterSpaceIPD = ls.getSpace(); hyphIPD = fobj.getCommonHyphenation().getHyphIPD(font); @@ -72,33 +71,6 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { chArea.setBaselineOffset(font.getAscender()); setCurrentArea(chArea); } - - /** - * Selects a font which is able to display the given character. - * <p> - * Please note: this implements the font-selection-strategy - * character-by-character. - * <p> - * TODO: The same function could apply to other elements as well. - * - * @param fobj - * a Character object containing the character and its - * attributed. - * @return a Font object. - */ - private Font selectFontForCharacter(Character fobj) { - FontInfo fi = fobj.getFOEventHandler().getFontInfo(); - FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); - for (int i = 0; i < fontkeys.length; i++) { - font = fi.getFontInstance(fontkeys[i], - fobj.getCommonFont().fontSize.getValue(this)); - if (font.hasChar(fobj.getCharacter())) { - return font; - } - } - return fi.getFontInstance(fontkeys[0], - fobj.getCommonFont().fontSize.getValue(this)); - } private org.apache.fop.area.inline.TextArea getCharacterInlineArea(Character node) { org.apache.fop.area.inline.TextArea text @@ -118,7 +90,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { MinOptMax ipd; curArea = get(context); KnuthSequence seq = new InlineKnuthSequence(); @@ -207,7 +179,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { if (isFinished()) { return null; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index 2af844c5c..b43c4c841 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -27,8 +27,6 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - -import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.LineArea; @@ -131,7 +129,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager stackSize = 0; - LinkedList contentList = + List contentList = getNextKnuthElements(childLC, Constants.EN_START); ListIterator contentIter = contentList.listIterator(); while (contentIter.hasNext()) { @@ -254,9 +252,9 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager } } - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { - LinkedList contentList = new LinkedList(); - LinkedList returnedList; + public List getNextKnuthElements(LayoutContext context, int alignment) { + List contentList = new LinkedList(); + List returnedList; childLM.initialize(); while (!childLM.isFinished()) { @@ -267,7 +265,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager // move elements to contentList, and accumulate their size KnuthElement contentElement; while (returnedList.size() > 0) { - Object obj = returnedList.removeFirst(); + Object obj = returnedList.remove(0); if (obj instanceof KnuthSequence) { KnuthSequence ks = (KnuthSequence)obj; for (Iterator it = ks.iterator(); it.hasNext(); ) { @@ -312,7 +310,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager return false; } - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, /*int flaggedPenalty,*/ int alignment) { return null; diff --git a/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java index ab05d60c3..d7bff5a5c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java @@ -29,20 +29,20 @@ import org.apache.fop.fo.flow.ExternalGraphic; */ public class ExternalGraphicLayoutManager extends AbstractGraphicsLayoutManager { - private ExternalGraphic fobj; - /** - * Constructor - * @param node the fo:external-graphic formatting object that creates the area + * Constructor. + * + * @param node + * the fo:external-graphic formatting object that creates the + * area */ public ExternalGraphicLayoutManager(ExternalGraphic node) { super(node); - fobj = node; } /** {@inheritDoc} */ protected Area getChildArea() { - return new Image(fobj.getSrc()); + return new Image(((ExternalGraphic) fobj).getSrc()); } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java index adb0e5a73..a02cfee89 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java @@ -71,7 +71,7 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, + public List getNextKnuthElements(LayoutContext context, int alignment) { // for the moment, this LM is set as the citationLM's parent // later on, when this LM will have nothing more to do, the citationLM's parent @@ -82,9 +82,9 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { bodyLM.initialize(); // get Knuth elements representing the footnote citation - LinkedList returnedList = new LinkedList(); + List returnedList = new LinkedList(); while (!citationLM.isFinished()) { - LinkedList partialList = citationLM.getNextKnuthElements(context, alignment); + List partialList = citationLM.getNextKnuthElements(context, alignment); if (partialList != null) { returnedList.addAll(partialList); } @@ -122,9 +122,9 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, int alignment) { - LinkedList returnedList = super.getChangedKnuthElements(oldList, alignment); + List returnedList = super.getChangedKnuthElements(oldList, alignment); addAnchor(returnedList); return returnedList; } @@ -164,7 +164,7 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { * Find the last box in the sequence, and add a reference to the FootnoteBodyLM * @param citationList the list of elements representing the footnote citation */ - private void addAnchor(LinkedList citationList) { + private void addAnchor(List citationList) { KnuthInlineBox lastBox = null; // the list of elements is searched backwards, until we find a box ListIterator citationIterator = citationList.listIterator(citationList.size()); diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 7c2e4748a..d0874d626 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -56,6 +56,7 @@ import org.apache.fop.layoutmgr.SpaceSpecifier; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; +import org.apache.fop.util.ListUtil; /** * LayoutManager for objects which stack children in the inline direction, @@ -233,14 +234,14 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { LayoutManager curLM; // the list returned by child LM - LinkedList returnedList; + List returnedList; // the list which will be returned to the parent LM - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); KnuthSequence lastSequence = null; SpaceSpecifier leadingSpace = context.getLeadingSpace(); @@ -312,11 +313,11 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // get KnuthElements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); - if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) { + if (returnList.isEmpty() && childLC.isKeepWithPreviousPending()) { childLC.clearKeepWithPreviousPending(); } if (returnedList == null - || returnedList.size() == 0) { + || returnedList.isEmpty()) { // curLM returned null or an empty list, because it finished; // just iterate once more to see if there is another child continue; @@ -335,7 +336,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { returnedList.remove(0); } // add border and padding to the first complete sequence of this LM - if (!borderAdded && returnedList.size() != 0) { + if (!borderAdded && !returnedList.isEmpty()) { addKnuthElementsForBorderPaddingStart((KnuthSequence) returnedList.get(0)); borderAdded = true; } @@ -367,7 +368,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); childLC.clearKeepsPending(); } - lastSequence = (KnuthSequence) returnList.getLast(); + lastSequence = (KnuthSequence) ListUtil.getLast(returnList); lastChildLM = curLM; } @@ -378,7 +379,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { setFinished(true); log.trace(trace); - if (returnList.size() == 0) { + if (returnList.isEmpty()) { /* * if the FO itself is empty, but has an id specified * or associated fo:markers, then we still need a dummy @@ -395,7 +396,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } } - return returnList.size() == 0 ? null : returnList; + return returnList.isEmpty() ? null : returnList; } /** @@ -432,7 +433,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // set in the layout context, it must be also set in the // layout context given to lastLM, but must be cleared in the // layout context given to the other LMs. - LinkedList positionList = new LinkedList(); + List positionList = new LinkedList(); NonLeafPosition pos; LayoutManager lastLM = null;// last child LM in this iterator Position lastPos = null; @@ -533,8 +534,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { - LinkedList returnedList = new LinkedList(); + public List getChangedKnuthElements(List oldList, int alignment) { + List returnedList = new LinkedList(); addKnuthElementsForBorderPaddingStart(returnedList); returnedList.addAll(super.getChangedKnuthElements(oldList, alignment)); addKnuthElementsForBorderPaddingEnd(returnedList); diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index bf1538a7c..81fc7901d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -364,7 +364,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { // "unwrap" the Positions stored in the elements ListIterator oldListIterator = oldList.listIterator(); KnuthElement oldElement; diff --git a/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java b/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java index e7da50a9a..5f9365f83 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java @@ -29,20 +29,19 @@ import org.apache.fop.fo.flow.InstreamForeignObject; */ public class InstreamForeignObjectLM extends AbstractGraphicsLayoutManager { - private InstreamForeignObject fobj; - /** - * Constructor - * @param node the formatting object that creates this area + * Constructor. + * + * @param node + * the formatting object that creates this area */ public InstreamForeignObjectLM(InstreamForeignObject node) { super(node); - fobj = node; } /** {@inheritDoc} */ protected Area getChildArea() { - XMLObj child = (XMLObj) fobj.getChildXMLObj(); + XMLObj child = ((InstreamForeignObject) fobj).getChildXMLObj(); org.w3c.dom.Document doc = child.getDOMDocument(); String ns = child.getNamespaceURI(); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index 1e7c793df..3bb82aa11 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -52,7 +52,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { private Leader fobj; private Font font = null; - private LinkedList contentList = null; + private List contentList = null; private ContentLayoutManager clm = null; private int contentAreaIPD = 0; @@ -230,7 +230,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, + public List getNextKnuthElements(LayoutContext context, int alignment) { MinOptMax ipd; curArea = get(context); @@ -305,13 +305,13 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, int alignment) { if (isFinished()) { return null; } - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); addKnuthElementsForBorderPaddingStart(returnList); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index fb5e9ee4d..19a8cdf2d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -91,7 +91,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager /** - * Create a Leaf node layout mananger. + * Create a Leaf node layout manager. * @param node the FObj to attach to this LM. */ public LeafNodeLayoutManager(FObj node) { @@ -99,7 +99,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager } /** - * Create a Leaf node layout mananger. + * Create a Leaf node layout manager. */ public LeafNodeLayoutManager() { } @@ -249,7 +249,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { curArea = get(context); if (curArea == null) { @@ -313,7 +313,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, int alignment) { if (isFinished()) { return null; diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 8c46796eb..87077ee77 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -46,6 +46,7 @@ import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.BreakingAlgorithm; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.InlineKnuthSequence; +import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -386,9 +387,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager InlineLevelEventProducer eventProducer = InlineLevelEventProducer.Provider.get( getFObj().getUserAgent().getEventBroadcaster()); - eventProducer.lineOverflows(this, addedPositions + 1, + eventProducer.lineOverflows(this, bestActiveNode.line, -lack, getFObj().getLocator()); - String textDiff = (lack < -50000 ? "more than 50 points" : (-lack) + "mpt"); } } @@ -573,7 +573,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { FontInfo fi = fobj.getFOEventHandler().getFontInfo(); FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); Font fs = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this)); @@ -643,7 +643,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager LayoutContext inlineLC = new LayoutContext(context); InlineLevelLayoutManager curLM; - LinkedList returnedList = null; + List returnedList = null; iLineWidth = context.getStackLimitIP().opt; // convert all the text in a sequence of paragraphs made @@ -665,7 +665,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } if (lastPar != null) { - KnuthSequence firstSeq = (KnuthSequence) returnedList.getFirst(); + KnuthSequence firstSeq = (KnuthSequence) returnedList.get(0); // finish last paragraph before a new block sequence if (!firstSeq.isInlineSequence()) { @@ -900,7 +900,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param context the layout context * @return a list of Knuth elements representing broken lines */ - private LinkedList createLineBreaks(int alignment, LayoutContext context) { + private List createLineBreaks(int alignment, LayoutContext context) { // find the optimal line breaking points for each paragraph ListIterator paragraphsIterator @@ -1047,16 +1047,19 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param context the layout context * @return the newly built element list */ - private LinkedList postProcessLineBreaks(int alignment, LayoutContext context) { + private List postProcessLineBreaks(int alignment, LayoutContext context) { - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); for (int p = 0; p < knuthParagraphs.size(); p++) { - // null penalty between paragraphs - if (p > 0 && !((BlockLevelLayoutManager) parentLM).mustKeepTogether()) { - returnList.add(new BreakElement( - new Position(this), 0, context)); - //returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); + // penalty between paragraphs + if (p > 0) { + int strength = getKeepTogetherStrength(); + int penalty = KeepUtil.getPenaltyForKeep(strength); + if (penalty < KnuthElement.INFINITE) { + returnList.add(new BreakElement( + new Position(this), penalty, context)); + } } LineLayoutPossibilities llPoss; @@ -1064,7 +1067,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(p); if (!seq.isInlineSequence()) { - LinkedList targetList = new LinkedList(); + List targetList = new LinkedList(); ListIterator listIter = seq.listIterator(); while (listIter.hasNext()) { ListElement tempElement; @@ -1090,20 +1093,23 @@ public class LineLayoutManager extends InlineStackingLayoutManager for (int i = 0; i < llPoss.getChosenLineCount(); i++) { - if (!((BlockLevelLayoutManager) parentLM).mustKeepTogether() + if (returnList.size() > 0 + && i > 0 //if i==0 break generated above already && i >= fobj.getOrphans() - && i <= llPoss.getChosenLineCount() - fobj.getWidows() - && returnList.size() > 0) { - // null penalty allowing a page break between lines - returnList.add(new BreakElement( - returnPosition, 0, context)); - //returnList.add(new KnuthPenalty(0, 0, false, returnPosition, false)); + && i <= llPoss.getChosenLineCount() - fobj.getWidows()) { + // penalty allowing a page break between lines + int strength = getKeepTogetherStrength(); + int penalty = KeepUtil.getPenaltyForKeep(strength); + if (penalty < KnuthElement.INFINITE) { + returnList.add(new BreakElement( + returnPosition, penalty, context)); + } } int endIndex = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos(); // create a list of the FootnoteBodyLM handling footnotes // whose citations are in this line - LinkedList footnoteList = new LinkedList(); + List footnoteList = new LinkedList(); ListIterator elementIterator = seq.listIterator(startIndex); while (elementIterator.nextIndex() <= endIndex) { KnuthElement element = (KnuthElement) elementIterator.next(); @@ -1327,8 +1333,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { - LinkedList returnList = new LinkedList(); + public List getChangedKnuthElements(List oldList, int alignment) { + List returnList = new LinkedList(); for (int p = 0; p < knuthParagraphs.size(); p++) { LineLayoutPossibilities llPoss; llPoss = (LineLayoutPossibilities)lineLayoutsList.get(p); @@ -1377,7 +1383,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager ListIterator currParIterator = currPar.listIterator(currPar.ignoreAtStart); // list of TLM involved in hyphenation - LinkedList updateList = new LinkedList(); + List updateList = new LinkedList(); KnuthElement firstElement = null; KnuthElement nextElement = null; // current InlineLevelLayoutManager @@ -1490,7 +1496,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager .applyChanges(currPar.subList(fromIndex + iAddedElements, toIndex + iAddedElements))) { // insert the new KnuthElements - LinkedList newElements = null; + List newElements = null; newElements = currUpdate.inlineLM.getChangedKnuthElements (currPar.subList(fromIndex + iAddedElements, diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java index 4f5c78540..8e6633ab8 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java @@ -44,7 +44,7 @@ public class PageNumberCitationLayoutManager extends AbstractPageNumberCitationL /** {@inheritDoc} */ public InlineArea get(LayoutContext context) { - curArea = getPageNumberCitationInlineArea(parentLM); + curArea = getPageNumberCitationInlineArea(); return curArea; } @@ -52,7 +52,7 @@ public class PageNumberCitationLayoutManager extends AbstractPageNumberCitationL * if id can be resolved then simply return a word, otherwise * return a resolvable area */ - private InlineArea getPageNumberCitationInlineArea(LayoutManager parentLM) { + private InlineArea getPageNumberCitationInlineArea() { PageViewport page = getPSLM().getFirstPVWithID(fobj.getRefId()); TextArea text = null; if (page != null) { diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index be8a13d50..c6210edce 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,7 +19,6 @@ package org.apache.fop.layoutmgr.inline; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -31,8 +30,7 @@ import org.apache.fop.area.inline.TextArea; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FOText; import org.apache.fop.fonts.Font; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.FontSelector; import org.apache.fop.layoutmgr.InlineKnuthSequence; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -48,6 +46,7 @@ import org.apache.fop.text.linebreak.LineBreakStatus; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; import org.apache.fop.util.CharUtilities; +import org.apache.fop.util.ListUtil; /** * LayoutManager for text (a sequence of characters) which generates one @@ -62,23 +61,25 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * Number of word-spaces? */ private class AreaInfo { - private short startIndex; - private short breakIndex; - private short wordSpaceCount; - private short letterSpaceCount; - private MinOptMax areaIPD; - private boolean isHyphenated; - private boolean isSpace; + private final int startIndex; + private final int breakIndex; + private final int wordSpaceCount; + private int letterSpaceCount; + private final MinOptMax areaIPD; + private final boolean isHyphenated; + private final boolean isSpace; private boolean breakOppAfter; - - AreaInfo(short startIndex, - short breakIndex, - short wordSpaceCount, - short letterSpaceCount, - MinOptMax areaIPD, - boolean isHyphenated, - boolean isSpace, - boolean breakOppAfter) { + private final Font font; + + AreaInfo(final int startIndex, + final int breakIndex, + final int wordSpaceCount, + final int letterSpaceCount, + final MinOptMax areaIPD, + final boolean isHyphenated, + final boolean isSpace, + final boolean breakOppAfter, + final Font font) { this.startIndex = startIndex; this.breakIndex = breakIndex; this.wordSpaceCount = wordSpaceCount; @@ -87,16 +88,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { this.isHyphenated = isHyphenated; this.isSpace = isSpace; this.breakOppAfter = breakOppAfter; + this.font = font; } public String toString() { - return "[ lscnt=" + letterSpaceCount - + ", wscnt=" + wordSpaceCount - + ", ipd=" + areaIPD.toString() - + ", sidx=" + startIndex - + ", bidx=" + breakIndex - + ", hyph=" + isHyphenated - + ", space=" + isSpace + return "[ lscnt=" + this.letterSpaceCount + + ", wscnt=" + this.wordSpaceCount + + ", ipd=" + this.areaIPD.toString() + + ", sidx=" + this.startIndex + + ", bidx=" + this.breakIndex + + ", hyph=" + this.isHyphenated + + ", space=" + this.isSpace + + ", font=" + this.font + "]"; } @@ -104,11 +107,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // this class stores information about changes in vecAreaInfo // which are not yet applied - private class PendingChange { - public AreaInfo ai; - public int index; + private final class PendingChange { + private final AreaInfo ai; + private final int index; - public PendingChange(AreaInfo ai, int index) { + private PendingChange(final AreaInfo ai, final int index) { this.ai = ai; this.index = index; } @@ -117,10 +120,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** * logging instance */ - private static Log log = LogFactory.getLog(TextLayoutManager.class); + private static final Log LOG = LogFactory.getLog(TextLayoutManager.class); // Hold all possible breaks for the text in this LM's FO. - private ArrayList vecAreaInfo; + private final List vecAreaInfo; /** Non-space characters on which we can end a line. */ private static final String BREAK_CHARS = "-/"; @@ -128,20 +131,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** Used to reduce instantiation of MinOptMax with zero length. Do not modify! */ private static final MinOptMax ZERO_MINOPTMAX = new MinOptMax(0); - private FOText foText; - private char[] textArray; + private final FOText foText; + /** * Contains an array of widths to adjust for kerning. The first entry can * be used to influence the start position of the first letter. The entry i+1 defines the * cursor advancement after the character i. A null entry means no special advancement. */ - private MinOptMax[] letterAdjustArray; //size = textArray.length + 1 + private final MinOptMax[] letterAdjustArray; //size = textArray.length + 1 - private static final char NEWLINE = '\n'; - - private Font font = null; + /** Font used for the space between words. */ + private Font spaceFont = null; /** Start index of next TextArea */ - private short nextStart = 0; + private int nextStart = 0; /** size of a space character (U+0020) glyph in current font */ private int spaceCharIPD; private MinOptMax wordSpaceIPD; @@ -150,16 +152,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private int hyphIPD; /** 1/1 of word-spacing value */ private SpaceVal ws; - /** 1/2 of word-spacing value */ - private SpaceVal halfWS; - /** 1/2 of letter-spacing value */ - private SpaceVal halfLS; private boolean hasChanged = false; private int returnedIndex = 0; - private short thisStart = 0; - private short tempStart = 0; - private LinkedList changeList = null; + private int thisStart = 0; + private int tempStart = 0; + private List changeList = null; private AlignmentContext alignmentContext = null; @@ -175,24 +173,21 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * * @param node The FOText object to be rendered */ - public TextLayoutManager(FOText node) { + public TextLayoutManager(final FOText node) { super(); - foText = node; + this.foText = node; - textArray = new char[node.endIndex - node.startIndex]; - System.arraycopy(node.ca, node.startIndex, textArray, 0, - node.endIndex - node.startIndex); - letterAdjustArray = new MinOptMax[textArray.length + 1]; + this.letterAdjustArray = new MinOptMax[node.length() + 1]; - vecAreaInfo = new java.util.ArrayList(); + this.vecAreaInfo = new java.util.ArrayList(); } - private KnuthPenalty makeZeroWidthPenalty(int penaltyValue) { + private KnuthPenalty makeZeroWidthPenalty(final int penaltyValue) { return new KnuthPenalty( 0, penaltyValue, false, - auxiliaryPosition, + this.auxiliaryPosition, true); } @@ -200,29 +195,27 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return new KnuthInlineBox( 0, null, - notifyPos(new LeafPosition(this, -1)), + this.notifyPos(new LeafPosition(this, -1)), true); } /** {@inheritDoc} */ public void initialize() { - FontInfo fi = foText.getFOEventHandler().getFontInfo(); - FontTriplet[] fontkeys = foText.getCommonFont().getFontState(fi); - font = fi.getFontInstance(fontkeys[0], foText.getCommonFont().fontSize.getValue(this)); + + this.foText.resetBuffer(); + + this.spaceFont = FontSelector.selectFontForCharacterInText(' ', this.foText, this); // With CID fonts, space isn't neccesary currentFontState.width(32) - spaceCharIPD = font.getCharWidth(' '); + this.spaceCharIPD = this.spaceFont.getCharWidth(' '); // Use hyphenationChar property - hyphIPD = foText.getCommonHyphenation().getHyphIPD(font); - SpaceVal ls = SpaceVal.makeLetterSpacing(foText.getLetterSpacing()); - halfLS = new SpaceVal(MinOptMax.multiply(ls.getSpace(), 0.5), - ls.isConditional(), ls.isForcing(), ls.getPrecedence()); + // TODO: Use hyphen based on actual font used! + this.hyphIPD = this.foText.getCommonHyphenation().getHyphIPD(this.spaceFont); - ws = SpaceVal.makeWordSpacing(foText.getWordSpacing(), ls, font); - // Make half-space: <space> on either side of a word-space) - halfWS = new SpaceVal(MinOptMax.multiply(ws.getSpace(), 0.5), - ws.isConditional(), ws.isForcing(), ws.getPrecedence()); + final SpaceVal ls = SpaceVal.makeLetterSpacing(this.foText.getLetterSpacing()); + + this.ws = SpaceVal.makeWordSpacing(this.foText.getWordSpacing(), ls, this.spaceFont); // letter space applies only to consecutive non-space characters, // while word space applies to space characters; @@ -235,10 +228,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // set letter space and word space dimension; // the default value "normal" was converted into a MinOptMax value // in the SpaceVal.makeWordSpacing() method - letterSpaceIPD = ls.getSpace(); - wordSpaceIPD = MinOptMax.add(new MinOptMax(spaceCharIPD), ws.getSpace()); + this.letterSpaceIPD = ls.getSpace(); + this.wordSpaceIPD = MinOptMax.add(new MinOptMax(this.spaceCharIPD), this.ws.getSpace()); - keepTogether = foText.getKeepTogether().getWithinLine().getEnum() == Constants.EN_ALWAYS; + this.keepTogether = this.foText.getKeepTogether().getWithinLine() + .getEnum() == Constants.EN_ALWAYS; } @@ -252,10 +246,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * by this LayoutManager. * @param context LayoutContext for adjustments */ - public void addAreas(PositionIterator posIter, LayoutContext context) { + public void addAreas(final PositionIterator posIter, final LayoutContext context) { // Add word areas - AreaInfo ai = null; + AreaInfo ai; int wordSpaceCount = 0; int letterSpaceCount = 0; int firstAreaInfoIndex = -1; @@ -265,36 +259,57 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /* On first area created, add any leading space. * Calculate word-space stretch value. */ + AreaInfo lastAi = null; while (posIter.hasNext()) { - LeafPosition tbpNext = (LeafPosition) posIter.next(); + final LeafPosition tbpNext = (LeafPosition) posIter.next(); if (tbpNext == null) { continue; //Ignore elements without Positions } if (tbpNext.getLeafPos() != -1) { - ai = (AreaInfo) vecAreaInfo.get(tbpNext.getLeafPos()); - if (firstAreaInfoIndex == -1) { + ai = (AreaInfo) this.vecAreaInfo.get(tbpNext.getLeafPos()); + if (lastAi == null || ai.font != lastAi.font) { + if (lastAi != null) { + this.addAreaInfoAreas(lastAi, wordSpaceCount, + letterSpaceCount, firstAreaInfoIndex, + lastAreaInfoIndex, realWidth, context); + } firstAreaInfoIndex = tbpNext.getLeafPos(); + wordSpaceCount = 0; + letterSpaceCount = 0; + realWidth = new MinOptMax(0); } wordSpaceCount += ai.wordSpaceCount; letterSpaceCount += ai.letterSpaceCount; realWidth.add(ai.areaIPD); lastAreaInfoIndex = tbpNext.getLeafPos(); + lastAi = ai; } } - if (ai == null) { - return; + if (lastAi != null) { + this.addAreaInfoAreas(lastAi, wordSpaceCount, letterSpaceCount, + firstAreaInfoIndex, lastAreaInfoIndex, realWidth, context); } - int textLength = ai.breakIndex - ai.startIndex; + } + + private void addAreaInfoAreas(final AreaInfo ai, final int wordSpaceCount, + int letterSpaceCount, final int firstAreaInfoIndex, + final int lastAreaInfoIndex, final MinOptMax realWidth, final LayoutContext context) { + + // TODO: These two statements (if, for) were like this before my recent + // changes. However, it seems as if they should use the AreaInfo from + // firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last ai. + // This needs to be checked. + final int textLength = ai.breakIndex - ai.startIndex; if (ai.letterSpaceCount == textLength && !ai.isHyphenated && context.isLastArea()) { // the line ends at a character like "/" or "-"; // remove the letter space after the last character - realWidth.add(MinOptMax.multiply(letterSpaceIPD, -1)); + realWidth.add(MinOptMax.multiply(this.letterSpaceIPD, -1)); letterSpaceCount--; } for (int i = ai.startIndex; i < ai.breakIndex; i++) { - MinOptMax ladj = letterAdjustArray[i + 1]; + final MinOptMax ladj = this.letterAdjustArray[i + 1]; if (ladj != null && ladj.isElastic()) { letterSpaceCount++; } @@ -302,60 +317,57 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // add hyphenation character if the last word is hyphenated if (context.isLastArea() && ai.isHyphenated) { - realWidth.add(new MinOptMax(hyphIPD)); + realWidth.add(new MinOptMax(this.hyphIPD)); } // Calculate adjustments int difference = 0; int totalAdjust = 0; - int wordSpaceDim = wordSpaceIPD.opt; - int letterSpaceDim = letterSpaceIPD.opt; - double ipdAdjust = context.getIPDAdjust(); - double dSpaceAdjust = context.getSpaceAdjust(); // not used + int wordSpaceDim = this.wordSpaceIPD.opt; + int letterSpaceDim = this.letterSpaceIPD.opt; + final double ipdAdjust = context.getIPDAdjust(); // calculate total difference between real and available width if (ipdAdjust > 0.0) { - difference = (int) ((double) (realWidth.max - realWidth.opt) + difference = (int) ((realWidth.max - realWidth.opt) * ipdAdjust); } else { - difference = (int) ((double) (realWidth.opt - realWidth.min) + difference = (int) ((realWidth.opt - realWidth.min) * ipdAdjust); } // set letter space adjustment if (ipdAdjust > 0.0) { letterSpaceDim - += (int) ((double) (letterSpaceIPD.max - letterSpaceIPD.opt) + += (int) ((this.letterSpaceIPD.max - this.letterSpaceIPD.opt) * ipdAdjust); } else { letterSpaceDim - += (int) ((double) (letterSpaceIPD.opt - letterSpaceIPD.min) + += (int) ((this.letterSpaceIPD.opt - this.letterSpaceIPD.min) * ipdAdjust); } - totalAdjust += (letterSpaceDim - letterSpaceIPD.opt) * letterSpaceCount; + totalAdjust += (letterSpaceDim - this.letterSpaceIPD.opt) * letterSpaceCount; // set word space adjustment // if (wordSpaceCount > 0) { wordSpaceDim += (difference - totalAdjust) / wordSpaceCount; - } else { - // there are no word spaces in this area } - totalAdjust += (wordSpaceDim - wordSpaceIPD.opt) * wordSpaceCount; + totalAdjust += (wordSpaceDim - this.wordSpaceIPD.opt) * wordSpaceCount; if (totalAdjust != difference) { // the applied adjustment is greater or smaller than the needed one - log.trace("TextLM.addAreas: error in word / letter space adjustment = " - + (totalAdjust - difference)); + TextLayoutManager.LOG + .trace("TextLM.addAreas: error in word / letter space adjustment = " + + (totalAdjust - difference)); // set totalAdjust = difference, so that the width of the TextArea // will counterbalance the error and the other inline areas will be // placed correctly totalAdjust = difference; } - TextArea t = createTextArea(realWidth, totalAdjust, context, - wordSpaceIPD.opt - spaceCharIPD, - firstAreaInfoIndex, lastAreaInfoIndex, - context.isLastArea()); + final TextArea t = this.createTextArea(realWidth, totalAdjust, context, + this.wordSpaceIPD.opt - this.spaceCharIPD, firstAreaInfoIndex, + lastAreaInfoIndex, context.isLastArea(), ai.font); // wordSpaceDim is computed in relation to wordSpaceIPD.opt // but the renderer needs to know the adjustment in relation @@ -370,14 +382,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // + (wordSpaceDim - spaceCharIPD - 2 * letterSpaceAdjust) // = wordSpaceDim - letterSpaceAdjust t.setTextLetterSpaceAdjust(letterSpaceDim); - t.setTextWordSpaceAdjust(wordSpaceDim - spaceCharIPD + t.setTextWordSpaceAdjust(wordSpaceDim - this.spaceCharIPD - 2 * t.getTextLetterSpaceAdjust()); if (context.getIPDAdjust() != 0) { // add information about space width - t.setSpaceDifference(wordSpaceIPD.opt - spaceCharIPD + t.setSpaceDifference(this.wordSpaceIPD.opt - this.spaceCharIPD - 2 * t.getTextLetterSpaceAdjust()); } - parentLM.addChildArea(t); + this.parentLM.addChildArea(t); } /** @@ -391,11 +403,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * @param firstIndex the index of the first AreaInfo used for the TextArea * @param lastIndex the index of the last AreaInfo used for the TextArea * @param isLastArea is this TextArea the last in a line? + * @param font Font to be used in this particular TextArea * @return the new text area */ - protected TextArea createTextArea(MinOptMax width, int adjust, - LayoutContext context, int spaceDiff, - int firstIndex, int lastIndex, boolean isLastArea) { + protected TextArea createTextArea(final MinOptMax width, final int adjust, + final LayoutContext context, final int spaceDiff, final int firstIndex, + final int lastIndex, final boolean isLastArea, final Font font) { TextArea textArea; if (context.getIPDAdjust() == 0.0) { // create just a TextArea @@ -409,11 +422,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } textArea.setIPD(width.opt + adjust); textArea.setBPD(font.getAscender() - font.getDescender()); + textArea.setBaselineOffset(font.getAscender()); - if (textArea.getBPD() == alignmentContext.getHeight()) { + if (textArea.getBPD() == this.alignmentContext.getHeight()) { textArea.setOffset(0); } else { - textArea.setOffset(alignmentContext.getOffset()); + textArea.setOffset(this.alignmentContext.getOffset()); } // set the text of the TextArea, split into words and spaces @@ -421,12 +435,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { AreaInfo areaInfo; int len = 0; for (int i = firstIndex; i <= lastIndex; i++) { - areaInfo = (AreaInfo) vecAreaInfo.get(i); + areaInfo = (AreaInfo) this.vecAreaInfo.get(i); if (areaInfo.isSpace) { // areaInfo stores information about spaces // add the spaces - except zero-width spaces - to the TextArea for (int j = areaInfo.startIndex; j < areaInfo.breakIndex; j++) { - char spaceChar = textArray[j]; + final char spaceChar = this.foText.charAt(j); if (!CharUtilities.isZeroWidthSpace(spaceChar)) { textArea.addSpace(spaceChar, 0, CharUtilities.isAdjustableSpace(spaceChar)); @@ -440,7 +454,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { len = 0; } len += areaInfo.breakIndex - areaInfo.startIndex; - if (i == lastIndex || ((AreaInfo) vecAreaInfo.get(i + 1)).isSpace) { + if (i == lastIndex || ((AreaInfo) this.vecAreaInfo.get(i + 1)).isSpace) { // here ends a new word // add a word to the TextArea if (isLastArea @@ -448,17 +462,26 @@ public class TextLayoutManager extends LeafNodeLayoutManager { && areaInfo.isHyphenated) { len++; } - StringBuffer wordChars = new StringBuffer(len); - int[] letterAdjust = new int[len]; + final StringBuffer wordChars = new StringBuffer(len); + final int[] letterAdjust = new int[len]; int letter = 0; for (int j = wordStartIndex; j <= i; j++) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(j); + final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(j); int lsCount = ai.letterSpaceCount; - wordChars.append(textArray, ai.startIndex, ai.breakIndex - ai.startIndex); + /* TODO: in Java 5, StringBuffer has an append() variant + * for CharSequence, so the below iteration can be replaced + * by: + * wordChars.append(this.foText, ai.startIndex, + * ai.breakIndex - ai.startIndex); + */ + for (int ci = ai.startIndex; ci < ai.breakIndex; ci++) { + wordChars.append(this.foText.charAt(ci)); + } for (int k = 0; k < ai.breakIndex - ai.startIndex; k++) { - MinOptMax adj = letterAdjustArray[ai.startIndex + k]; + final MinOptMax adj = this.letterAdjustArray[ai.startIndex + k]; if (letter > 0) { - letterAdjust[letter] = (adj != null ? adj.opt : 0); + letterAdjust[letter] = adj == null ? 0 + : adj.opt; } if (lsCount > 0) { letterAdjust[letter] += textArea.getTextLetterSpaceAdjust(); @@ -472,7 +495,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { && i == lastIndex && areaInfo.isHyphenated) { // add the hyphenation character - wordChars.append(foText.getCommonHyphenation().getHyphChar(font)); + wordChars.append(this.foText.getCommonHyphenation().getHyphChar(font)); } textArea.addWord(wordChars.toString(), 0, letterAdjust); wordStartIndex = -1; @@ -480,18 +503,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } TraitSetter.addFontTraits(textArea, font); - textArea.addTrait(Trait.COLOR, foText.getColor()); + textArea.addTrait(Trait.COLOR, this.foText.getColor()); - TraitSetter.addTextDecoration(textArea, foText.getTextDecoration()); + TraitSetter.addTextDecoration(textArea, this.foText.getTextDecoration()); return textArea; } - private void addToLetterAdjust(int index, int width) { - if (letterAdjustArray[index] == null) { - letterAdjustArray[index] = new MinOptMax(width); + private void addToLetterAdjust(final int index, final int width) { + if (this.letterAdjustArray[index] == null) { + this.letterAdjustArray[index] = new MinOptMax(width); } else { - letterAdjustArray[index].add(width); + this.letterAdjustArray[index].add(width); } } @@ -507,26 +530,27 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { - lineStartBAP = context.getLineStartBorderAndPaddingWidth(); - lineEndBAP = context.getLineEndBorderAndPaddingWidth(); - alignmentContext = context.getAlignmentContext(); + public List getNextKnuthElements(final LayoutContext context, final int alignment) { + this.lineStartBAP = context.getLineStartBorderAndPaddingWidth(); + this.lineEndBAP = context.getLineEndBorderAndPaddingWidth(); + this.alignmentContext = context.getAlignmentContext(); - LinkedList returnList = new LinkedList(); + final List returnList = new LinkedList(); KnuthSequence sequence = new InlineKnuthSequence(); AreaInfo ai = null; AreaInfo prevAi = null; returnList.add(sequence); - LineBreakStatus lbs = new LineBreakStatus(); - thisStart = nextStart; + final LineBreakStatus lbs = new LineBreakStatus(); + this.thisStart = this.nextStart; boolean inWord = false; boolean inWhitespace = false; char ch = 0; - while (nextStart < textArray.length) { - ch = textArray[nextStart]; + while (this.nextStart < this.foText.length()) { + ch = this.foText.charAt(this.nextStart); boolean breakOpportunity = false; - byte breakAction = keepTogether ? LineBreakStatus.PROHIBITED_BREAK : lbs.nextChar(ch); + final byte breakAction = this.keepTogether ? LineBreakStatus.PROHIBITED_BREAK + : lbs.nextChar(ch); switch (breakAction) { case LineBreakStatus.COMBINING_PROHIBITED_BREAK: case LineBreakStatus.PROHIBITED_BREAK: @@ -539,253 +563,247 @@ public class TextLayoutManager extends LeafNodeLayoutManager { breakOpportunity = true; break; default: - log.error("Unexpected breakAction: " + breakAction); + TextLayoutManager.LOG.error("Unexpected breakAction: " + breakAction); } if (inWord) { - if (breakOpportunity || isSpace(ch) || ch == NEWLINE) { - //Word boundary found, process widths and kerning - short lastIndex = nextStart; - while (lastIndex > 0 && textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) { - lastIndex--; - } - int wordLength = lastIndex - thisStart; - boolean kerning = font.hasKerning(); - MinOptMax wordIPD = new MinOptMax(0); - for (int i = thisStart; i < lastIndex; i++) { - char c = textArray[i]; - - //character width - int charWidth = font.getCharWidth(c); - wordIPD.add(charWidth); - - //kerning - if (kerning) { - int kern = 0; - if (i > thisStart) { - char previous = textArray[i - 1]; - kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { - char previous = textArray[prevAi.breakIndex - 1]; - kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } - if (kern != 0) { - //log.info("Kerning between " + previous + " and " + c + ": " + kern); - addToLetterAdjust(i, kern); - wordIPD.add(kern); - } - } - } - if (kerning && breakOpportunity && !isSpace(ch) && lastIndex > 0 && textArray[lastIndex] == CharUtilities.SOFT_HYPHEN) { - int kern = font.getKernValue(textArray[lastIndex - 1], ch) * font.getFontSize() / 1000; - if (kern != 0) { - addToLetterAdjust(lastIndex, kern); - } - } - int iLetterSpaces = wordLength - 1; - // if there is a break opportunity and the next one - // is not a space, it could be used as a line end; - // add one more letter space, in case other text follows - if (breakOpportunity && !isSpace(ch)) { - iLetterSpaces++; - } - wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); - - // create the AreaInfo object - ai = new AreaInfo(thisStart, lastIndex, (short) 0, - (short) iLetterSpaces, - wordIPD, textArray[lastIndex] == CharUtilities.SOFT_HYPHEN, false, breakOpportunity); - prevAi = ai; - vecAreaInfo.add(ai); - tempStart = nextStart; - - //add the elements - addElementsForAWordFragment(sequence, alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD); - ai = null; - thisStart = nextStart; + if (breakOpportunity + || TextLayoutManager.isSpace(ch) + || CharUtilities.isExplicitBreak(ch)) { + // this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN + prevAi = this.processWord(alignment, sequence, prevAi, ch, + breakOpportunity, true); } } else if (inWhitespace) { if (ch != CharUtilities.SPACE || breakOpportunity) { - // End of whitespace - // create the AreaInfo object - ai = new AreaInfo(thisStart, nextStart, - (short) (nextStart - thisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), - false, true, breakOpportunity); - vecAreaInfo.add(ai); - prevAi = ai; - - // create the elements - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); - ai = null; - - thisStart = nextStart; + prevAi = this.processWhitespace(alignment, sequence, + breakOpportunity); } } else { if (ai != null) { - vecAreaInfo.add(ai); prevAi = ai; - ai.breakOppAfter = (ch == CharUtilities.SPACE) || breakOpportunity; - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); - ai = null; + ai = this.processLeftoverAi(alignment, sequence, ai, ch, + ch == CharUtilities.SPACE || breakOpportunity); } if (breakAction == LineBreakStatus.EXPLICIT_BREAK) { - if (lineEndBAP != 0) { - sequence.add( - new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, true)); - } - sequence.endSequence(); - sequence = new InlineKnuthSequence(); - returnList.add(sequence); + sequence = this.processLinebreak(returnList, sequence); } } - if ((ch == CharUtilities.SPACE - && foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) + if (ch == CharUtilities.SPACE + && this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE || ch == CharUtilities.NBSPACE) { // preserved space or non-breaking space: // create the AreaInfo object - ai = new AreaInfo(nextStart, (short) (nextStart + 1), - (short) 1, (short) 0, - wordSpaceIPD, false, true, breakOpportunity); - thisStart = (short) (nextStart + 1); + ai = new AreaInfo(this.nextStart, this.nextStart + 1, + 1, 0, this.wordSpaceIPD, false, true, + breakOpportunity, this.spaceFont); + this.thisStart = this.nextStart + 1; } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) { // create the AreaInfo object - MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); - ai = new AreaInfo(nextStart, (short) (nextStart + 1), - (short) 0, (short) 0, - ipd, false, true, breakOpportunity); - thisStart = (short) (nextStart + 1); - } else if (ch == NEWLINE) { - // linefeed; this can happen when linefeed-treatment="preserve" - thisStart = (short) (nextStart + 1); + final Font font = FontSelector.selectFontForCharacterInText(ch, + this.foText, this); + final MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); + ai = new AreaInfo(this.nextStart, this.nextStart + 1, + 0, 0, ipd, false, true, + breakOpportunity, font); + this.thisStart = this.nextStart + 1; + } else if (CharUtilities.isExplicitBreak(ch)) { + //mandatory break-character: only advance index + this.thisStart = this.nextStart + 1; } - inWord = !isSpace(ch) && ch != NEWLINE; - inWhitespace = ch == CharUtilities.SPACE && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; - nextStart++; + + inWord = !TextLayoutManager.isSpace(ch) + && !CharUtilities.isExplicitBreak(ch); + inWhitespace = ch == CharUtilities.SPACE + && this.foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; + this.nextStart++; } // end of while // Process any last elements if (inWord) { - int lastIndex = nextStart; - if (textArray[nextStart - 1] == CharUtilities.SOFT_HYPHEN) { - lastIndex--; - } - int wordLength = lastIndex - thisStart; - boolean kerning = font.hasKerning(); - MinOptMax wordIPD = new MinOptMax(0); - for (int i = thisStart; i < lastIndex; i++) { - char c = textArray[i]; - - //character width - int charWidth = font.getCharWidth(c); - wordIPD.add(charWidth); - - //kerning - if (kerning) { - int kern = 0; - if (i > thisStart) { - char previous = textArray[i - 1]; - kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } else if (prevAi != null && !prevAi.isSpace) { - char previous = textArray[prevAi.breakIndex - 1]; - kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } - if (kern != 0) { - //log.info("Kerning between " + previous + " and " + c + ": " + kern); - addToLetterAdjust(i, kern); - wordIPD.add(kern); - } - } - } - int iLetterSpaces = wordLength - 1; - wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); - - // create the AreaInfo object - ai = new AreaInfo(thisStart, (short)lastIndex, (short) 0, - (short) iLetterSpaces, - wordIPD, false, false, false); - vecAreaInfo.add(ai); - tempStart = nextStart; - - // create the elements - addElementsForAWordFragment(sequence, alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD); - ai = null; + this.processWord(alignment, sequence, prevAi, ch, false, false); } else if (inWhitespace) { - ai = new AreaInfo(thisStart, (short) (nextStart), - (short) (nextStart - thisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), - false, true, true); - vecAreaInfo.add(ai); - - // create the elements - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); - ai = null; + this.processWhitespace(alignment, sequence, true); } else if (ai != null) { - vecAreaInfo.add(ai); - ai.breakOppAfter = ch == CharUtilities.ZERO_WIDTH_SPACE; - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); - ai = null; - } else if (ch == NEWLINE) { - if (lineEndBAP != 0) { - sequence.add - (new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, true)); - } - sequence.endSequence(); - sequence = new InlineKnuthSequence(); - returnList.add(sequence); + this.processLeftoverAi(alignment, sequence, ai, ch, + ch == CharUtilities.ZERO_WIDTH_SPACE); + } else if (CharUtilities.isExplicitBreak(ch)) { + this.processLinebreak(returnList, sequence); } - if (((List)returnList.getLast()).size() == 0) { + if (((List) ListUtil.getLast(returnList)).isEmpty()) { //Remove an empty sequence because of a trailing newline - returnList.removeLast(); + ListUtil.removeLast(returnList); } - setFinished(true); - if (returnList.size() > 0) { - return returnList; - } else { + + this.setFinished(true); + if (returnList.isEmpty()) { return null; + } else { + return returnList; + } + } + + private KnuthSequence processLinebreak(final List returnList, + KnuthSequence sequence) { + if (this.lineEndBAP != 0) { + sequence.add( + new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, true)); + } + sequence.endSequence(); + sequence = new InlineKnuthSequence(); + returnList.add(sequence); + return sequence; + } + + private AreaInfo processLeftoverAi(final int alignment, + final KnuthSequence sequence, AreaInfo ai, final char ch, + final boolean breakOpportunityAfter) { + this.vecAreaInfo.add(ai); + ai.breakOppAfter = breakOpportunityAfter; + this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); + ai = null; + return ai; + } + + private AreaInfo processWhitespace(final int alignment, + final KnuthSequence sequence, final boolean breakOpportunity) { + // End of whitespace + // create the AreaInfo object + AreaInfo ai = new AreaInfo(this.thisStart, this.nextStart, + this.nextStart - this.thisStart, 0, + MinOptMax.multiply(this.wordSpaceIPD, this.nextStart + - this.thisStart), false, true, + breakOpportunity, this.spaceFont); + this.vecAreaInfo.add(ai); + + // create the elements + this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); + + this.thisStart = this.nextStart; + return ai; + } + + private AreaInfo processWord(final int alignment, final KnuthSequence sequence, + AreaInfo prevAi, final char ch, final boolean breakOpportunity, + final boolean checkEndsWithHyphen) { + AreaInfo ai; + //Word boundary found, process widths and kerning + int lastIndex = this.nextStart; + while (lastIndex > 0 + && this.foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) { + lastIndex--; + } + final boolean endsWithHyphen = checkEndsWithHyphen + && this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; + final Font font = FontSelector + .selectFontForCharactersInText(this.foText, + this.thisStart, lastIndex, this.foText, this); + final int wordLength = lastIndex - this.thisStart; + final boolean kerning = font.hasKerning(); + final MinOptMax wordIPD = new MinOptMax(0); + for (int i = this.thisStart; i < lastIndex; i++) { + final char c = this.foText.charAt(i); + + //character width + final int charWidth = font.getCharWidth(c); + wordIPD.add(charWidth); + + //kerning + if (kerning) { + int kern = 0; + if (i > this.thisStart) { + final char previous = this.foText.charAt(i - 1); + kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; + } else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { + final char previous = this.foText.charAt(prevAi.breakIndex - 1); + kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; + } + if (kern != 0) { + this.addToLetterAdjust(i, kern); + wordIPD.add(kern); + } + } + } + if (kerning + && breakOpportunity + && !TextLayoutManager.isSpace(ch) + && lastIndex > 0 + && endsWithHyphen) { + final int kern = font.getKernValue( + this.foText.charAt(lastIndex - 1), ch) + * font.getFontSize() / 1000; + if (kern != 0) { + this.addToLetterAdjust(lastIndex, kern); + } } + int iLetterSpaces = wordLength - 1; + // if there is a break opportunity and the next one + // is not a space, it could be used as a line end; + // add one more letter space, in case other text follows + if (breakOpportunity && !TextLayoutManager.isSpace(ch)) { + iLetterSpaces++; + } + wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); + + // create the AreaInfo object + ai = new AreaInfo(this.thisStart, lastIndex, 0, + iLetterSpaces, wordIPD, + endsWithHyphen, + false, breakOpportunity, font); + prevAi = ai; + this.vecAreaInfo.add(ai); + this.tempStart = this.nextStart; + + //add the elements + this.addElementsForAWordFragment(sequence, alignment, ai, + this.vecAreaInfo.size() - 1, this.letterSpaceIPD); + ai = null; + this.thisStart = this.nextStart; + return prevAi; } /** {@inheritDoc} */ - public List addALetterSpaceTo(List oldList) { + public List addALetterSpaceTo(final List oldList) { // old list contains only a box, or the sequence: box penalty glue box; // look at the Position stored in the first element in oldList // which is always a box ListIterator oldListIterator = oldList.listIterator(); - KnuthElement el = (KnuthElement)oldListIterator.next(); - LeafPosition pos = (LeafPosition) ((KnuthBox) el).getPosition(); - int idx = pos.getLeafPos(); + final KnuthElement el = (KnuthElement)oldListIterator.next(); + final LeafPosition pos = (LeafPosition) ((KnuthBox) el).getPosition(); + final int idx = pos.getLeafPos(); //element could refer to '-1' position, for non-collapsed spaces (?) if (idx > -1) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(idx); + final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(idx); ai.letterSpaceCount++; - ai.areaIPD.add(letterSpaceIPD); - if (BREAK_CHARS.indexOf(textArray[tempStart - 1]) >= 0) { + ai.areaIPD.add(this.letterSpaceIPD); + if (TextLayoutManager.BREAK_CHARS.indexOf(this.foText.charAt(this.tempStart - 1)) >= 0) { // the last character could be used as a line break // append new elements to oldList oldListIterator = oldList.listIterator(oldList.size()); oldListIterator.add(new KnuthPenalty(0, KnuthPenalty.FLAGGED_PENALTY, true, - auxiliaryPosition, false)); - oldListIterator.add(new KnuthGlue(letterSpaceIPD.opt, - letterSpaceIPD.max - letterSpaceIPD.opt, - letterSpaceIPD.opt - letterSpaceIPD.min, - auxiliaryPosition, false)); - } else if (letterSpaceIPD.min == letterSpaceIPD.max) { + this.auxiliaryPosition, false)); + oldListIterator.add(new KnuthGlue(this.letterSpaceIPD.opt, + this.letterSpaceIPD.max - this.letterSpaceIPD.opt, + this.letterSpaceIPD.opt - this.letterSpaceIPD.min, + this.auxiliaryPosition, false)); + } else if (this.letterSpaceIPD.min == this.letterSpaceIPD.max) { // constant letter space: replace the box - oldListIterator.set(new KnuthInlineBox(ai.areaIPD.opt, alignmentContext, pos, false)); + oldListIterator.set(new KnuthInlineBox(ai.areaIPD.opt, + this.alignmentContext, pos, false)); } else { // adjustable letter space: replace the glue oldListIterator.next(); // this would return the penalty element oldListIterator.next(); // this would return the glue element - oldListIterator.set(new KnuthGlue(ai.letterSpaceCount * letterSpaceIPD.opt, - ai.letterSpaceCount * (letterSpaceIPD.max - letterSpaceIPD.opt), - ai.letterSpaceCount * (letterSpaceIPD.opt - letterSpaceIPD.min), - auxiliaryPosition, true)); + oldListIterator + .set(new KnuthGlue( + ai.letterSpaceCount * this.letterSpaceIPD.opt, + ai.letterSpaceCount + * (this.letterSpaceIPD.max - this.letterSpaceIPD.opt), + ai.letterSpaceCount + * (this.letterSpaceIPD.opt - this.letterSpaceIPD.min), + this.auxiliaryPosition, true)); } } return oldList; @@ -798,10 +816,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * * @param oldList the elements representing the word space */ - public void removeWordSpace(List oldList) { + public void removeWordSpace(final List oldList) { // find the element storing the Position whose value // points to the AreaInfo object - ListIterator oldListIterator = oldList.listIterator(); + final ListIterator oldListIterator = oldList.listIterator(); if (((KnuthElement) ((LinkedList) oldList).getFirst()).isPenalty()) { // non breaking space: oldList starts with a penalty oldListIterator.next(); @@ -812,30 +830,31 @@ public class TextLayoutManager extends LeafNodeLayoutManager { oldListIterator.next(); oldListIterator.next(); } - int leafValue = ((LeafPosition) ((KnuthElement) oldListIterator.next()).getPosition()).getLeafPos(); + final int leafValue = ((LeafPosition) ((KnuthElement) oldListIterator + .next()).getPosition()).getLeafPos(); // only the last word space can be a trailing space! - if (leafValue == vecAreaInfo.size() - 1) { - vecAreaInfo.remove(leafValue); + if (leafValue == this.vecAreaInfo.size() - 1) { + this.vecAreaInfo.remove(leafValue); } else { - log.error("trying to remove a non-trailing word space"); + TextLayoutManager.LOG.error("trying to remove a non-trailing word space"); } } /** {@inheritDoc} */ - public void hyphenate(Position pos, HyphContext hc) { - AreaInfo ai - = (AreaInfo) vecAreaInfo.get(((LeafPosition) pos).getLeafPos()); + public void hyphenate(final Position pos, final HyphContext hc) { + final AreaInfo ai + = (AreaInfo) this.vecAreaInfo.get(((LeafPosition) pos).getLeafPos()); int startIndex = ai.startIndex; int stopIndex; boolean nothingChanged = true; + final Font font = ai.font; while (startIndex < ai.breakIndex) { - MinOptMax newIPD = new MinOptMax(0); + final MinOptMax newIPD = new MinOptMax(0); boolean hyphenFollows; - if (hc.hasMoreHyphPoints() - && (stopIndex = startIndex + hc.getNextHyphPoint()) - <= ai.breakIndex) { + stopIndex = startIndex + hc.getNextHyphPoint(); + if (hc.hasMoreHyphPoints() && stopIndex <= ai.breakIndex) { // stopIndex is the index of the first character // after a hyphenation point hyphenFollows = true; @@ -850,12 +869,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { //log.info("Word: " + new String(textArray, startIndex, stopIndex - startIndex)); for (int i = startIndex; i < stopIndex; i++) { - char c = textArray[i]; + final char c = this.foText.charAt(i); newIPD.add(new MinOptMax(font.getCharWidth(c))); //if (i > startIndex) { if (i < stopIndex) { MinOptMax la = this.letterAdjustArray[i + 1]; - if ((i == stopIndex - 1) && hyphenFollows) { + if (i == stopIndex - 1 && hyphenFollows) { //the letter adjust here needs to be handled further down during //element generation because it depends on hyph/no-hyph condition la = null; @@ -866,115 +885,115 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } // add letter spaces - boolean isWordEnd + final boolean isWordEnd = stopIndex == ai.breakIndex - && ai.letterSpaceCount < (ai.breakIndex - ai.startIndex); - newIPD.add(MinOptMax.multiply(letterSpaceIPD, + && ai.letterSpaceCount < ai.breakIndex - ai.startIndex; + newIPD.add(MinOptMax.multiply(this.letterSpaceIPD, (isWordEnd - ? (stopIndex - startIndex - 1) - : (stopIndex - startIndex)))); + ? stopIndex - startIndex - 1 + : stopIndex - startIndex))); if (!(nothingChanged && stopIndex == ai.breakIndex && !hyphenFollows)) { // the new AreaInfo object is not equal to the old one - if (changeList == null) { - changeList = new LinkedList(); + if (this.changeList == null) { + this.changeList = new LinkedList(); } - changeList.add - (new PendingChange - (new AreaInfo((short) startIndex, (short) stopIndex, - (short) 0, - (short) (isWordEnd - ? (stopIndex - startIndex - 1) - : (stopIndex - startIndex)), - newIPD, hyphenFollows, false, false), - ((LeafPosition) pos).getLeafPos())); + this.changeList.add(new PendingChange(new AreaInfo( + startIndex, stopIndex, 0, + (isWordEnd ? stopIndex - startIndex - 1 + : stopIndex - startIndex), newIPD, + hyphenFollows, false, false, font), + ((LeafPosition) pos).getLeafPos())); nothingChanged = false; } startIndex = stopIndex; } - hasChanged = !nothingChanged; + this.hasChanged = !nothingChanged; } /** {@inheritDoc} */ - public boolean applyChanges(List oldList) { - setFinished(false); + public boolean applyChanges(final List oldList) { + this.setFinished(false); - if (changeList != null && !changeList.isEmpty()) { + if (this.changeList != null && !this.changeList.isEmpty()) { int areaInfosAdded = 0; int areaInfosRemoved = 0; int oldIndex = -1, changeIndex; PendingChange currChange; - ListIterator changeListIterator = changeList.listIterator(); + final ListIterator changeListIterator = this.changeList.listIterator(); while (changeListIterator.hasNext()) { currChange = (PendingChange) changeListIterator.next(); - if (currChange.index != oldIndex) { - areaInfosRemoved++; + if (currChange.index == oldIndex) { areaInfosAdded++; - oldIndex = currChange.index; changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; - vecAreaInfo.remove(changeIndex); } else { + areaInfosRemoved++; areaInfosAdded++; + oldIndex = currChange.index; changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; + this.vecAreaInfo.remove(changeIndex); } - vecAreaInfo.add(changeIndex, currChange.ai); + this.vecAreaInfo.add(changeIndex, currChange.ai); } - changeList.clear(); + this.changeList.clear(); } - returnedIndex = 0; - return hasChanged; + this.returnedIndex = 0; + return this.hasChanged; } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, - int alignment) { - if (isFinished()) { + public List getChangedKnuthElements(final List oldList, + final int alignment) { + if (this.isFinished()) { return null; } - LinkedList returnList = new LinkedList(); + final LinkedList returnList = new LinkedList(); - while (returnedIndex < vecAreaInfo.size()) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(returnedIndex); + while (this.returnedIndex < this.vecAreaInfo.size()) { + final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(this.returnedIndex); if (ai.wordSpaceCount == 0) { // ai refers either to a word or a word fragment - addElementsForAWordFragment(returnList, alignment, ai, returnedIndex, letterSpaceIPD); + this.addElementsForAWordFragment(returnList, alignment, ai, + this.returnedIndex, this.letterSpaceIPD); } else { // ai refers to a space - addElementsForASpace(returnList, alignment, ai, returnedIndex); + this.addElementsForASpace(returnList, alignment, ai, this.returnedIndex); } - returnedIndex++; + this.returnedIndex++; } // end of while - setFinished(true); + this.setFinished(true); //ElementListObserver.observe(returnList, "text-changed", null); return returnList; } /** {@inheritDoc} */ - public void getWordChars(StringBuffer sbChars, Position pos) { - int leafValue = ((LeafPosition) pos).getLeafPos(); + public void getWordChars(final StringBuffer sbChars, final Position pos) { + final int leafValue = ((LeafPosition) pos).getLeafPos(); if (leafValue != -1) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(leafValue); - sbChars.append(textArray, ai.startIndex, ai.breakIndex - ai.startIndex); + final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(leafValue); + for (int i = ai.startIndex; i < ai.breakIndex; ++i) { + sbChars.append(this.foText.charAt(i)); + } } } - private void addElementsForASpace(List baseList, - int alignment, - AreaInfo ai, - int leafValue) { - LeafPosition mainPosition = new LeafPosition(this, leafValue); + private void addElementsForASpace(final List baseList, + final int alignment, + final AreaInfo ai, + final int leafValue) { + final LeafPosition mainPosition = new LeafPosition(this, leafValue); if (!ai.breakOppAfter) { // a non-breaking space - if (alignment == EN_JUSTIFY) { + if (alignment == Constants.EN_JUSTIFY) { // the space can stretch and shrink, and must be preserved // when starting a line - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); } else { @@ -984,195 +1003,129 @@ public class TextLayoutManager extends LeafNodeLayoutManager { mainPosition, true)); } } else { - if (textArray[ai.startIndex] != CharUtilities.SPACE - || foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { + if (this.foText.charAt(ai.startIndex) != CharUtilities.SPACE + || this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { // a breaking space that needs to be preserved - switch (alignment) { - case EN_CENTER: - // centered text: - // if the second element is chosen as a line break these elements - // add a constant amount of stretch at the end of a line and at the - // beginning of the next one, otherwise they don't add any stretch - baseList.add(new KnuthGlue(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), -6 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); - break; - - case EN_START: // fall through - case EN_END: - // left- or right-aligned text: - // if the second element is chosen as a line break these elements - // add a constant amount of stretch at the end of a line, otherwise - // they don't add any stretch - baseList.add(new KnuthGlue(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), -3 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, 0, 0, - mainPosition, false)); - break; - - case EN_JUSTIFY: - // justified text: - // the stretch and shrink depends on the space width - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), ai.areaIPD.max - - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, - mainPosition, false)); - break; - - default: - // last line justified, the other lines unjustified: - // use only the space stretch - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), ai.areaIPD.max - - ai.areaIPD.opt, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, - mainPosition, false)); - } + this.addElementsForBreakingSpace(baseList, alignment, ai, + this.auxiliaryPosition, 0, mainPosition, + ai.areaIPD.opt, true); } else { // a (possible block) of breaking spaces - switch (alignment) { - case EN_CENTER: - // centered text: - // if the second element is chosen as a line break these elements - // add a constant amount of stretch at the end of a line and at the - // beginning of the next one, otherwise they don't add any stretch - baseList.add(new KnuthGlue(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(ai.areaIPD.opt - - (lineStartBAP + lineEndBAP), -6 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - break; + this.addElementsForBreakingSpace(baseList, alignment, ai, + mainPosition, ai.areaIPD.opt, + this.auxiliaryPosition, 0, false); + } + } + } + + private void addElementsForBreakingSpace(final List baseList, + final int alignment, final AreaInfo ai, final Position pos2, + final int p2WidthOffset, final Position pos3, + final int p3WidthOffset, final boolean skipZeroCheck) { + switch (alignment) { + case EN_CENTER: + // centered text: + // if the second element is chosen as a line break these elements + // add a constant amount of stretch at the end of a line and at the + // beginning of the next one, otherwise they don't add any stretch + baseList.add(new KnuthGlue(this.lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(p2WidthOffset + - (this.lineStartBAP + this.lineEndBAP), -6 + * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos3, false)); + break; - case EN_START: // fall through - case EN_END: - // left- or right-aligned text: - // if the second element is chosen as a line break these elements - // add a constant amount of stretch at the end of a line, otherwise - // they don't add any stretch - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(new KnuthGlue(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(ai.areaIPD.opt - - (lineStartBAP + lineEndBAP), -3 + case EN_START: // fall through + case EN_END: + // left- or right-aligned text: + // if the second element is chosen as a line break these elements + // add a constant amount of stretch at the end of a line, otherwise + // they don't add any stretch + if (skipZeroCheck || this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(new KnuthGlue(this.lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(p2WidthOffset + - (this.lineStartBAP + this.lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); - } else { - baseList.add(new KnuthGlue(0, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(ai.areaIPD.opt, -3 + pos2, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, + 0, 0, pos3, false)); + } else { + baseList.add(new KnuthGlue(0, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(ai.areaIPD.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); - } - break; + pos2, false)); + } + break; - case EN_JUSTIFY: - // justified text: - // the stretch and shrink depends on the space width - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - ai.areaIPD.opt - (lineStartBAP + lineEndBAP), - ai.areaIPD.max - ai.areaIPD.opt, - ai.areaIPD.opt - ai.areaIPD.min, - mainPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); - } else { - baseList.add(new KnuthGlue(ai.areaIPD.opt, - ai.areaIPD.max - ai.areaIPD.opt, - ai.areaIPD.opt - ai.areaIPD.min, - mainPosition, false)); - } - break; + case EN_JUSTIFY: + // justified text: + // the stretch and shrink depends on the space width + if (skipZeroCheck || this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(p2WidthOffset + - (this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max + - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, + pos2, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, + 0, 0, pos3, false)); + } else { + baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max + - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, + pos2, false)); + } + break; - default: - // last line justified, the other lines unjustified: - // use only the space stretch - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - ai.areaIPD.opt - (lineStartBAP + lineEndBAP), - ai.areaIPD.max - ai.areaIPD.opt, - 0, mainPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); - } else { - baseList.add(new KnuthGlue(ai.areaIPD.opt, - ai.areaIPD.max - ai.areaIPD.opt, 0, - mainPosition, false)); - } - } + default: + // last line justified, the other lines unjustified: + // use only the space stretch + if (skipZeroCheck || this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(p2WidthOffset + - (this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max + - ai.areaIPD.opt, 0, pos2, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, + 0, 0, pos3, false)); + } else { + baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max + - ai.areaIPD.opt, 0, pos2, false)); } } } - private void addElementsForAWordFragment(List baseList, - int alignment, - AreaInfo ai, - int leafValue, - MinOptMax letterSpaceWidth) { + private void addElementsForAWordFragment(final List baseList, + final int alignment, + final AreaInfo ai, + final int leafValue, + final MinOptMax letterSpaceWidth) { - LeafPosition mainPosition = new LeafPosition(this, leafValue); + final LeafPosition mainPosition = new LeafPosition(this, leafValue); // if the last character of the word fragment is '-' or '/', // the fragment could end a line; in this case, it loses one // of its letter spaces; - boolean suppressibleLetterSpace = ai.breakOppAfter && !ai.isHyphenated; + final boolean suppressibleLetterSpace = ai.breakOppAfter && !ai.isHyphenated; if (letterSpaceWidth.min == letterSpaceWidth.max) { // constant letter spacing @@ -1180,138 +1133,152 @@ public class TextLayoutManager extends LeafNodeLayoutManager { suppressibleLetterSpace ? ai.areaIPD.opt - letterSpaceWidth.opt : ai.areaIPD.opt, - alignmentContext, - notifyPos(mainPosition), false)); + this.alignmentContext, + this.notifyPos(mainPosition), false)); } else { // adjustable letter spacing - int unsuppressibleLetterSpaces + final int unsuppressibleLetterSpaces = suppressibleLetterSpace ? ai.letterSpaceCount - 1 : ai.letterSpaceCount; baseList.add (new KnuthInlineBox(ai.areaIPD.opt - ai.letterSpaceCount * letterSpaceWidth.opt, - alignmentContext, - notifyPos(mainPosition), false)); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + this.alignmentContext, + this.notifyPos(mainPosition), false)); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); baseList.add (new KnuthGlue(unsuppressibleLetterSpaces * letterSpaceWidth.opt, unsuppressibleLetterSpaces * (letterSpaceWidth.max - letterSpaceWidth.opt), unsuppressibleLetterSpaces * (letterSpaceWidth.opt - letterSpaceWidth.min), - auxiliaryPosition, true)); - baseList.add(makeAuxiliaryZeroWidthBox()); + this.auxiliaryPosition, true)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); } // extra-elements if the word fragment is the end of a syllable, // or it ends with a character that can be used as a line break if (ai.isHyphenated) { MinOptMax widthIfNoBreakOccurs = null; - if (ai.breakIndex < textArray.length) { + if (ai.breakIndex < this.foText.length()) { //Add in kerning in no-break condition - widthIfNoBreakOccurs = letterAdjustArray[ai.breakIndex]; + widthIfNoBreakOccurs = this.letterAdjustArray[ai.breakIndex]; } //if (ai.breakIndex) // the word fragment ends at the end of a syllable: // if a break occurs the content width increases, // otherwise nothing happens - addElementsForAHyphen(baseList, alignment, hyphIPD, widthIfNoBreakOccurs, ai.breakOppAfter && ai.isHyphenated); + this.addElementsForAHyphen(baseList, alignment, this.hyphIPD, + widthIfNoBreakOccurs, ai.breakOppAfter && ai.isHyphenated); } else if (suppressibleLetterSpace) { // the word fragment ends with a character that acts as a hyphen // if a break occurs the width does not increase, // otherwise there is one more letter space - addElementsForAHyphen(baseList, alignment, 0, letterSpaceWidth, true); + this.addElementsForAHyphen(baseList, alignment, 0, letterSpaceWidth, true); } } // static final int SOFT_HYPHEN_PENALTY = KnuthPenalty.FLAGGED_PENALTY / 10; - static final int SOFT_HYPHEN_PENALTY = 1; + private static final int SOFT_HYPHEN_PENALTY = 1; - private void addElementsForAHyphen(List baseList, - int alignment, - int widthIfBreakOccurs, + private void addElementsForAHyphen(final List baseList, + final int alignment, + final int widthIfBreakOccurs, MinOptMax widthIfNoBreakOccurs, - boolean unflagged) { + final boolean unflagged) { if (widthIfNoBreakOccurs == null) { - widthIfNoBreakOccurs = ZERO_MINOPTMAX; + widthIfNoBreakOccurs = TextLayoutManager.ZERO_MINOPTMAX; } switch (alignment) { case EN_CENTER : // centered text: - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, true)); - baseList.add(new KnuthPenalty(hyphIPD, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); - baseList.add(new KnuthGlue(-(lineEndBAP + lineStartBAP), - -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, true)); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, true)); + baseList.add(new KnuthPenalty(this.hyphIPD, + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); + baseList.add(new KnuthGlue(-(this.lineEndBAP + this.lineStartBAP), + -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, true)); break; case EN_START : // fall through case EN_END : // left- or right-aligned text: - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); + if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); - baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), - -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt + - (this.lineStartBAP + this.lineEndBAP), -3 + * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, + this.auxiliaryPosition, false)); } else { - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); baseList.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); + this.auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); + this.auxiliaryPosition, false)); } break; default: // justified text, or last line justified: // just a flagged penalty - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); + if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 || widthIfNoBreakOccurs.max != 0) { - baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), - widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, - widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, - auxiliaryPosition, false)); + baseList + .add(new KnuthGlue(widthIfNoBreakOccurs.opt + - (this.lineStartBAP + this.lineEndBAP), + widthIfNoBreakOccurs.max + - widthIfNoBreakOccurs.opt, + widthIfNoBreakOccurs.opt + - widthIfNoBreakOccurs.min, + this.auxiliaryPosition, false)); } else { - baseList.add(new KnuthGlue(-(lineStartBAP + lineEndBAP), 0, 0, - auxiliaryPosition, false)); + baseList.add(new KnuthGlue(-(this.lineStartBAP + this.lineEndBAP), 0, 0, + this.auxiliaryPosition, false)); } - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, + this.auxiliaryPosition, false)); } else { baseList.add(new KnuthPenalty(widthIfBreakOccurs, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 @@ -1319,11 +1286,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, - auxiliaryPosition, false)); + this.auxiliaryPosition, false)); } } } - + } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index a5bbdb33c..342e0a6f1 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -20,9 +20,7 @@ package org.apache.fop.layoutmgr.inline; import org.apache.fop.area.inline.InlineArea; -import org.apache.fop.area.inline.InlineParent; import org.apache.fop.area.Block; -import org.apache.fop.area.LineArea; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.layoutmgr.BlockLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; @@ -30,20 +28,19 @@ import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; +import java.util.LinkedList; + /** * This is the layout manager for the fo:wrapper formatting object. */ public class WrapperLayoutManager extends LeafNodeLayoutManager { - private Wrapper fobj; - /** * Creates a new LM for fo:wrapper. * @param node the fo:wrapper */ public WrapperLayoutManager(Wrapper node) { super(node); - fobj = node; } /** {@inheritDoc} */ @@ -70,13 +67,13 @@ public class WrapperLayoutManager extends LeafNodeLayoutManager { public void addAreas(PositionIterator posIter, LayoutContext context) { if (fobj.hasId()) { addId(); - InlineArea area = getEffectiveArea(); if (parentLM instanceof BlockStackingLayoutManager && !(parentLM instanceof BlockLayoutManager)) { Block helperBlock = new Block(); TraitSetter.setProducerID(helperBlock, fobj.getId()); parentLM.addChildArea(helperBlock); } else { + InlineArea area = getEffectiveArea(); parentLM.addChildArea(area); } } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index dfffbdd04..11e69970e 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -115,9 +115,9 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { resetSpaces(); - LinkedList returnList = super.getNextKnuthElements(context, alignment); + List returnList = super.getNextKnuthElements(context, alignment); //fox:widow-content-limit int widowRowLimit = getListBlockFO().getWidowContentLimit().getValue(); @@ -135,7 +135,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { //log.debug("LBLM.getChangedKnuthElements>"); return super.getChangedKnuthElements(oldList, alignment); } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 549244267..124827976 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -98,7 +98,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { //log.debug(" ListItemContentLayoutManager.getChanged>"); return super.getChangedKnuthElements(oldList, alignment); } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 6a3a38db1..37ec4964d 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -26,7 +26,6 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.fo.flow.ListItem; @@ -39,12 +38,14 @@ import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.ListElement; import org.apache.fop.layoutmgr.NonLeafPosition; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; @@ -71,8 +72,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager private Block curBlockArea = null; - private LinkedList labelList = null; - private LinkedList bodyList = null; + private List labelList = null; + private List bodyList = null; private boolean discardBorderBefore; private boolean discardBorderAfter; @@ -189,11 +190,11 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { referenceIPD = context.getRefIPD(); LayoutContext childLC; - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); if (!breakBeforeServed) { try { @@ -242,7 +243,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager this.keepWithNextPendingOnBody = childLC.getKeepWithNextPending(); // create a combined list - LinkedList returnedList = getCombinedKnuthElementsForListItem(labelList, bodyList, context); + List returnedList = getCombinedKnuthElementsForListItem(labelList, bodyList, context); // "wrap" the Position inside each element wrapPositionElements(returnedList, returnList, true); @@ -261,10 +262,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager return returnList; } - private LinkedList getCombinedKnuthElementsForListItem(LinkedList labelElements, - LinkedList bodyElements, - LayoutContext context) { - //Copy elements to array lists to improve element access performance + private List getCombinedKnuthElementsForListItem(List labelElements, + List bodyElements, LayoutContext context) { + // Copy elements to array lists to improve element access performance List[] elementLists = {new ArrayList(labelElements), new ArrayList(bodyElements)}; int[] fullHeights = {ElementListUtils.calcContentLength(elementLists[0]), @@ -279,8 +279,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO; LinkedList returnList = new LinkedList(); - while ((step = getNextStep(elementLists, start, end, partialHeights)) - > 0) { + while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) { if (end[0] + 1 == elementLists[0].size()) { keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel); @@ -312,11 +311,33 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int boxHeight = step - addedBoxHeight - penaltyHeight; penaltyHeight += additionalPenaltyHeight; //Add AFTER calculating boxHeight! + // collect footnote information + // TODO this should really not be done like this. ListItemLM should remain as + // footnote-agnostic as possible + LinkedList footnoteList = null; + ListElement el; + for (int i = 0; i < elementLists.length; i++) { + for (int j = start[i]; j <= end[i]; j++) { + el = (ListElement) elementLists[i].get(j); + if (el instanceof KnuthBlockBox && ((KnuthBlockBox) el).hasAnchors()) { + if (footnoteList == null) { + footnoteList = new LinkedList(); + } + footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs()); + } + } + } + // add the new elements addedBoxHeight += boxHeight; ListItemPosition stepPosition = new ListItemPosition(this, start[0], end[0], start[1], end[1]); - returnList.add(new KnuthBox(boxHeight, stepPosition, false)); + if (footnoteList == null) { + returnList.add(new KnuthBox(boxHeight, stepPosition, false)); + } else { + returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false)); + } + if (addedBoxHeight < totalHeight) { int strength = BlockLevelLayoutManager.KEEP_AUTO; strength = Math.max(strength, keepWithNextActive); @@ -407,7 +428,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { //log.debug(" LILM.getChanged> label"); // label labelList = label.getChangedKnuthElements(labelList, alignment); @@ -436,9 +457,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } } - LinkedList returnedList = body.getChangedKnuthElements(oldList, alignment); + List returnedList = body.getChangedKnuthElements(oldList, alignment); // "wrap" the Position inside each element - LinkedList tempList = returnedList; + List tempList = returnedList; KnuthElement tempElement; returnedList = new LinkedList(); ListIterator listIter = tempList.listIterator(); diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index feb4b67ac..4012b0c00 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -19,12 +19,12 @@ package org.apache.fop.layoutmgr.table; +import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.EffRow; @@ -32,6 +32,7 @@ import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.ElementListUtils; +import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPenalty; @@ -101,6 +102,8 @@ class ActiveCell { private int penaltyLength; /** Value of the penalty ending this step, 0 if the step does not end on a penalty. */ private int penaltyValue; + /** List of footnotes for this step. */ + private List footnoteList; /** * One of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, @@ -130,6 +133,7 @@ class ActiveCell { this.totalLength = other.totalLength; this.penaltyLength = other.penaltyLength; this.penaltyValue = other.penaltyValue; + this.footnoteList = other.footnoteList; this.condBeforeContentLength = other.condBeforeContentLength; this.breakClass = other.breakClass; } @@ -293,6 +297,7 @@ class ActiveCell { afterNextStep.penaltyValue = 0; afterNextStep.condBeforeContentLength = 0; afterNextStep.breakClass = Constants.EN_AUTO; + afterNextStep.footnoteList = null; boolean breakFound = false; boolean prevIsBox = false; boolean boxFound = false; @@ -322,6 +327,12 @@ class ActiveCell { } prevIsBox = false; } else { + if (el instanceof KnuthBlockBox && ((KnuthBlockBox) el).hasAnchors()) { + if (afterNextStep.footnoteList == null) { + afterNextStep.footnoteList = new LinkedList(); + } + afterNextStep.footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs()); + } prevIsBox = true; boxFound = true; afterNextStep.contentLength += el.getW(); @@ -543,6 +554,18 @@ class ActiveCell { } } + /** + * Adds the footnotes (if any) that are part of the next step, if this cell + * contributes content to the next step. + * + * @param footnoteList the list to which this cell must add its footnotes + */ + void addFootnotes(List footnoteList) { + if (includedInLastStep() && nextStep.footnoteList != null) { + footnoteList.addAll(nextStep.footnoteList); + } + } + int getKeepWithNextStrength() { return keepWithNextStrength; } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 19b97322c..7f91808d0 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -21,10 +21,10 @@ package org.apache.fop.layoutmgr.table; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; @@ -88,7 +88,6 @@ class RowGroupLayoutManager { * @param alignment alignment indicator * @param bodyType Indicates what kind of body is being processed (BODY, HEADER or FOOTER) * @param returnList List to received the generated elements - * @param rowGroup row group to process */ private void createElementsForRowGroup(LayoutContext context, int alignment, int bodyType, LinkedList returnList) { @@ -116,7 +115,7 @@ class RowGroupLayoutManager { childLC.setRefIPD(spanWidth); //Get the element list for the cell contents - LinkedList elems = primary.getCellLM().getNextKnuthElements( + List elems = primary.getCellLM().getNextKnuthElements( childLC, alignment); ElementListObserver.observe(elems, "table-cell", primary.getCell().getId()); primary.setElements(elems); @@ -124,7 +123,7 @@ class RowGroupLayoutManager { } } computeRowHeights(); - LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context, + List elements = tableStepper.getCombinedKnuthElementsForRowGroup(context, rowGroup, bodyType); returnList.addAll(elements); } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index bed9c53ae..38f1a7b30 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -32,7 +32,7 @@ import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; -import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthElement; @@ -94,7 +94,7 @@ class RowPainter { this.firstRowOnPageIndex = -1; } - void startTablePart(TableBody tablePart) { + void startTablePart(TablePart tablePart) { CommonBorderPaddingBackground background = tablePart.getCommonBorderPaddingBackground(); if (background.hasBackground()) { tablePartBackground = background; @@ -229,8 +229,12 @@ class RowPainter { // Then add areas for cells finishing on the current row for (int i = 0; i < colCount; i++) { - GridUnit currentGU = currentRow.getGridUnit(i); - if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 + GridUnit currentGU = currentRow.getGridUnit(i); + if (currentGU.isEmpty()) { + // TODO remove once missing cells are properly implemented (i.e., replaced + // by an fo:table-cell element containing an empty fo:block) + firstCellOnPage[i] = false; + } else if (currentGU.getColSpanIndex() == 0 && (lastInPart || currentGU.isLastGridUnitRowSpan()) && firstCellParts[i] != null) { assert firstCellParts[i].pgu == currentGU.getPrimary(); @@ -260,7 +264,8 @@ class RowPainter { actualRowHeight, borderBeforeWhich, borderAfterWhich, lastOnPage); firstCellParts[i] = null; - firstCellOnPage[i] = false; + Arrays.fill(firstCellOnPage, i, i + currentGU.getCell().getNumberColumnsSpanned(), + false); } } currentRowOffset += actualRowHeight; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 6afb57dca..52915c008 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -20,10 +20,10 @@ package org.apache.fop.layoutmgr.table; import java.util.LinkedList; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.Trait; @@ -31,7 +31,7 @@ import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.flow.table.Table; -import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableRow; @@ -52,6 +52,7 @@ import org.apache.fop.layoutmgr.SpaceResolver; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * LayoutManager for a table-cell FO. @@ -126,16 +127,16 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager /** * {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { MinOptMax stackLimit = new MinOptMax(context.getStackLimitBP()); referenceIPD = context.getRefIPD(); cellIPD = referenceIPD; cellIPD -= getIPIndents(); - LinkedList returnedList; - LinkedList contentList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList; + List contentList = new LinkedList(); + List returnList = new LinkedList(); BlockLevelLayoutManager curLM; // currently active LM BlockLevelLayoutManager prevLM = null; // previously active LM @@ -151,7 +152,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager if (childLC.isKeepWithNextPending()) { log.debug("child LM signals pending keep with next"); } - if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) { + if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { primaryGridUnit.setKeepWithPreviousStrength(childLC.getKeepWithPreviousPending()); childLC.clearKeepWithPreviousPending(); } @@ -162,7 +163,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager addInBetweenBreak(contentList, context, childLC); } contentList.addAll(returnedList); - if (returnedList.size() == 0) { + if (returnedList.isEmpty()) { //Avoid NoSuchElementException below (happens with empty blocks) continue; } @@ -176,7 +177,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager primaryGridUnit.setKeepWithNextStrength(context.getKeepWithNextPending()); returnedList = new LinkedList(); - if (contentList.size() > 0) { + if (!contentList.isEmpty()) { wrapPositionElements(contentList, returnList); } else { // In relaxed validation mode, table-cells having no children are authorised. @@ -187,13 +188,15 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } //Space resolution SpaceResolver.resolveElementList(returnList); - if (((KnuthElement) returnList.getFirst()).isForcedBreak()) { - primaryGridUnit.setBreakBefore(((KnuthPenalty) returnList.getFirst()).getBreakClass()); - returnList.removeFirst(); + if (((KnuthElement) returnList.get(0)).isForcedBreak()) { + primaryGridUnit.setBreakBefore(((KnuthPenalty) returnList.get(0)).getBreakClass()); + returnList.remove(0); assert !returnList.isEmpty(); } - if (((KnuthElement) returnList.getLast()).isForcedBreak()) { - KnuthPenalty p = (KnuthPenalty) returnList.getLast(); + final KnuthElement lastItem = (KnuthElement) ListUtil + .getLast(returnList); + if (((KnuthElement) lastItem).isForcedBreak()) { + KnuthPenalty p = (KnuthPenalty) lastItem; primaryGridUnit.setBreakAfter(p.getBreakClass()); p.setP(0); } @@ -436,7 +439,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager -startIndent); } - TableBody body = primaryGridUnit.getTableBody(); + TablePart body = primaryGridUnit.getTablePart(); if (body.getCommonBorderPaddingBackground().hasBackground()) { painter.registerPartBackgroundArea( getBackgroundArea(paddingRectBPD, borderBeforeWidth)); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 7a2ee171c..80e904f8f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -19,10 +19,10 @@ package org.apache.fop.layoutmgr.table; -import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.ListIterator; import java.util.Map; import org.apache.commons.logging.Log; @@ -34,13 +34,14 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.flow.table.Table; -import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; +import org.apache.fop.layoutmgr.KnuthGlue; import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.ListElement; @@ -232,6 +233,17 @@ public class TableContentLayoutManager implements PercentBaseContext { //Get elements for next row group nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); + /* + * The last break element produced by TableStepper (for the previous row + * group) may be used to represent the break between the two row groups. + * Its penalty value and break class must just be overridden by the + * characteristics of the keep or break between the two. + * + * However, we mustn't forget that if the after border of the last row of + * the row group is thicker in the normal case than in the trailing case, + * an additional glue will be appended to the element list. So we may have + * to go two steps backwards in the list. + */ //Determine keep constraints int penaltyStrength = BlockLevelLayoutManager.KEEP_AUTO; @@ -246,24 +258,35 @@ public class TableContentLayoutManager implements PercentBaseContext { if (breakBetween != Constants.EN_AUTO) { penaltyValue = -KnuthElement.INFINITE; } - TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM()); - int penaltyLen = 0; - if (bodyType == TableRowIterator.BODY) { - if (!getTableLM().getTable().omitHeaderAtBreak()) { - penaltyLen += getHeaderNetHeight(); - penaltyPos.headerElements = getHeaderElements(); - } - if (!getTableLM().getTable().omitFooterAtBreak()) { - penaltyLen += getFooterNetHeight(); - penaltyPos.footerElements = getFooterElements(); - } + BreakElement breakElement; + ListIterator elemIter = returnList.listIterator(returnList.size()); + ListElement elem = (ListElement) elemIter.previous(); + if (elem instanceof KnuthGlue) { + breakElement = (BreakElement) elemIter.previous(); + } else { + breakElement = (BreakElement) elem; } - returnList.add(new BreakElement(penaltyPos, - penaltyLen, penaltyValue, breakBetween, context)); + breakElement.setPenaltyValue(penaltyValue); + breakElement.setBreakClass(breakBetween); returnList.addAll(nextRowGroupElems); breakBetween = context.getBreakAfter(); } } + /* + * The last break produced for the last row-group of this table part must be + * removed, because the breaking after the table will be handled by TableLM. + * Unless the element list ends with a glue, which must be kept to accurately + * represent the content. In such a case the break is simply disabled by setting + * its penalty to infinite. + */ + ListIterator elemIter = returnList.listIterator(returnList.size()); + ListElement elem = (ListElement) elemIter.previous(); + if (elem instanceof KnuthGlue) { + BreakElement breakElement = (BreakElement) elemIter.previous(); + breakElement.setPenaltyValue(KnuthElement.INFINITE); + } else { + elemIter.remove(); + } context.updateKeepWithPreviousPending(keepWithPrevious); context.setBreakBefore(breakBefore); @@ -300,7 +323,7 @@ public class TableContentLayoutManager implements PercentBaseContext { this.usedBPD = 0; RowPainter painter = new RowPainter(this, layoutContext); - List tablePositions = new ArrayList(); + List tablePositions = new java.util.ArrayList(); List headerElements = null; List footerElements = null; Position firstPos = null; @@ -393,9 +416,9 @@ public class TableContentLayoutManager implements PercentBaseContext { } } - private void addHeaderFooterAreas(List elements, TableBody part, RowPainter painter, + private void addHeaderFooterAreas(List elements, TablePart part, RowPainter painter, boolean lastOnPage) { - List lst = new ArrayList(elements.size()); + List lst = new java.util.ArrayList(elements.size()); for (Iterator iter = new KnuthPossPosIter(elements); iter.hasNext();) { Position pos = (Position) iter.next(); /* @@ -422,32 +445,32 @@ public class TableContentLayoutManager implements PercentBaseContext { private void addBodyAreas(Iterator iterator, RowPainter painter, boolean lastOnPage) { painter.startBody(); - List lst = new ArrayList(); + List lst = new java.util.ArrayList(); TableContentPosition pos = (TableContentPosition) iterator.next(); boolean isFirstPos = pos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP) && pos.getRow().getFlag(EffRow.FIRST_IN_PART); - TableBody body = pos.getTableBody(); + TablePart part = pos.getTablePart(); lst.add(pos); while (iterator.hasNext()) { pos = (TableContentPosition) iterator.next(); - if (pos.getTableBody() != body) { - addTablePartAreas(lst, painter, body, isFirstPos, true, false, false); + if (pos.getTablePart() != part) { + addTablePartAreas(lst, painter, part, isFirstPos, true, false, false); isFirstPos = true; lst.clear(); - body = pos.getTableBody(); + part = pos.getTablePart(); } lst.add(pos); } boolean isLastPos = pos.getFlag(TableContentPosition.LAST_IN_ROWGROUP) && pos.getRow().getFlag(EffRow.LAST_IN_PART); - addTablePartAreas(lst, painter, body, isFirstPos, isLastPos, true, lastOnPage); + addTablePartAreas(lst, painter, part, isFirstPos, isLastPos, true, lastOnPage); painter.endBody(); } /** * Adds the areas corresponding to a single fo:table-header/footer/body element. */ - private void addTablePartAreas(List positions, RowPainter painter, TableBody body, + private void addTablePartAreas(List positions, RowPainter painter, TablePart body, boolean isFirstPos, boolean isLastPos, boolean lastInBody, boolean lastOnPage) { getTableLM().getCurrentPV().addMarkers(body.getMarkers(), true, isFirstPos, isLastPos); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java index 260b8cfdf..62d25fcb1 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java @@ -22,7 +22,7 @@ package org.apache.fop.layoutmgr.table; import java.util.List; import org.apache.fop.fo.flow.table.EffRow; -import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.Position; @@ -80,8 +80,8 @@ class TableContentPosition extends Position { return row; } - TableBody getTableBody() { - return ((CellPart) cellParts.get(0)).pgu.getTableBody(); + TablePart getTablePart() { + return ((CellPart) cellParts.get(0)).pgu.getTablePart(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 0fe47d7b4..d370dc37f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -178,9 +178,9 @@ public class TableLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); /* * Compute the IPD and adjust it if necessary (overconstrained) @@ -271,8 +271,8 @@ public class TableLayoutManager extends BlockStackingLayoutManager int breakBefore = BreakUtil.compareBreakClasses(getTable().getBreakBefore(), childLC.getBreakBefore()); if (breakBefore != Constants.EN_AUTO) { - returnList.addFirst(new BreakElement(getAuxiliaryPosition(), - 0, -KnuthElement.INFINITE, breakBefore, context)); + returnList.add(0, new BreakElement(getAuxiliaryPosition(), 0, + -KnuthElement.INFINITE, breakBefore, context)); } //addKnuthElementsForBreakAfter(returnList, context); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java index 62e308c13..282cd0fd5 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java @@ -28,6 +28,7 @@ import org.apache.fop.fo.FONode.FONodeIterator; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TablePart; /** @@ -69,7 +70,7 @@ public class TableRowIterator { case FOOTER: rowGroupsIter = table.getTableFooter().getRowGroups().iterator(); break; - default: + case BODY: List rowGroupsList = new LinkedList(); // TODO this is ugly for (FONodeIterator iter = table.getChildNodes(); iter.hasNext();) { @@ -79,6 +80,9 @@ public class TableRowIterator { } } rowGroupsIter = rowGroupsList.iterator(); + break; + default: + throw new IllegalArgumentException("Unrecognised TablePart: " + tablePart); } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index f514844ac..6aa619368 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -33,6 +33,7 @@ import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; @@ -199,12 +200,14 @@ public class TableStepper { } } + LinkedList footnoteList = new LinkedList(); //Put all involved grid units into a list List cellParts = new java.util.ArrayList(columnCount); for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); CellPart part = activeCell.createCellPart(); cellParts.add(part); + activeCell.addFootnotes(footnoteList); } //Create elements for step @@ -217,7 +220,13 @@ public class TableStepper { tcpos.setFlag(TableContentPosition.FIRST_IN_ROWGROUP, true); } lastTCPos = tcpos; - returnList.add(new KnuthBox(boxLen, tcpos, false)); + + // TODO TableStepper should remain as footnote-agnostic as possible + if (footnoteList.isEmpty()) { + returnList.add(new KnuthBox(boxLen, tcpos, false)); + } else { + returnList.add(new KnuthBlockBox(boxLen, footnoteList, tcpos, false)); + } int effPenaltyLen = Math.max(0, penaltyOrGlueLen); TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM()); @@ -273,13 +282,8 @@ public class TableStepper { laststep = step; step = getNextStep(); } while (step >= 0); - if (!returnList.isEmpty()) { - lastTCPos.setFlag(TableContentPosition.LAST_IN_ROWGROUP, true); - // It's not up to TableStepper to decide whether there can/must be a break - // after the row group or not, but to ancestor stacking elements - assert returnList.getLast() instanceof BreakElement; - returnList.removeLast(); - } + assert !returnList.isEmpty(); + lastTCPos.setFlag(TableContentPosition.LAST_IN_ROWGROUP, true); return returnList; } diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java index bd44595fb..020a594b4 100644 --- a/src/java/org/apache/fop/pdf/PDFDocument.java +++ b/src/java/org/apache/fop/pdf/PDFDocument.java @@ -528,10 +528,10 @@ public class PDFDocument { public void setEncryption(PDFEncryptionParams params) { getProfile().verifyEncryptionAllowed(); this.encryption = PDFEncryptionManager.newInstance(++this.objectcount, params); - ((PDFObject)this.encryption).setDocument(this); if (encryption != null) { - /**@todo this cast is ugly. PDFObject should be transformed to an interface. */ - addTrailerObject((PDFObject)this.encryption); + PDFObject pdfObject = (PDFObject)encryption; + pdfObject.setDocument(this); + addTrailerObject(pdfObject); } else { log.warn( "PDF encryption is unavailable. PDF will be " diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index 02f0c2cdb..6211b5da7 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -1203,10 +1203,11 @@ public class PDFFactory { PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor); PDFFont font = null; - font = PDFFont.createFont(fontname, fonttype, basefont, encoding); + font = PDFFont.createFont(fontname, fonttype, basefont, null); getDocument().registerObject(font); if (fonttype == FontType.TYPE0) { + font.setEncoding(encoding); CIDFont cidMetrics; if (metrics instanceof LazyFont) { cidMetrics = (CIDFont)((LazyFont) metrics).getRealFont(); @@ -1252,7 +1253,9 @@ public class PDFFactory { //Handle encoding SingleByteEncoding mapping = singleByteFont.getEncoding(); - if (PDFEncoding.isPredefinedEncoding(mapping.getName())) { + if (singleByteFont.isSymbolicFont()) { + //no encoding, use the font's encoding + } else if (PDFEncoding.isPredefinedEncoding(mapping.getName())) { font.setEncoding(mapping.getName()); } else { Object pdfEncoding = createPDFEncoding(mapping, diff --git a/src/java/org/apache/fop/pdf/PDFFont.java b/src/java/org/apache/fop/pdf/PDFFont.java index 14f1a657c..1f76f1e11 100644 --- a/src/java/org/apache/fop/pdf/PDFFont.java +++ b/src/java/org/apache/fop/pdf/PDFFont.java @@ -62,8 +62,6 @@ public class PDFFont extends PDFDictionary { setEncoding((PDFEncoding)encoding); } else if (encoding instanceof String) { setEncoding((String)encoding); - } else { - throw new IllegalArgumentException("Illegal value for encoding"); } } diff --git a/src/java/org/apache/fop/pdf/PDFResources.java b/src/java/org/apache/fop/pdf/PDFResources.java index b0c0128e1..da213bb87 100644 --- a/src/java/org/apache/fop/pdf/PDFResources.java +++ b/src/java/org/apache/fop/pdf/PDFResources.java @@ -28,6 +28,8 @@ import java.util.Set; import org.apache.fop.fonts.FontDescriptor; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.Typeface; +import org.apache.fop.fonts.base14.Symbol; +import org.apache.fop.fonts.base14.ZapfDingbats; import org.apache.fop.util.ColorProfileUtil; /** @@ -109,8 +111,12 @@ public class PDFResources extends PDFObject { if (font instanceof FontDescriptor) { desc = (FontDescriptor)font; } + String encoding = font.getEncodingName(); + if (font instanceof Symbol || font instanceof ZapfDingbats) { + encoding = null; //Symbolic fonts shouldn't specify an encoding value in PDF + } addFont(doc.getFactory().makeFont( - f, font.getEmbedFontName(), font.getEncodingName(), font, desc)); + f, font.getEmbedFontName(), encoding, font, desc)); } } } diff --git a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java index bc7bb95a1..e91947ba5 100644 --- a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java @@ -32,12 +32,13 @@ import java.awt.image.ComponentColorModel; import java.awt.image.DataBuffer; import java.awt.image.Raster; import java.awt.image.WritableRaster; +import java.io.IOException; import org.apache.fop.render.RendererContext.RendererContextWrapper; import org.apache.fop.util.UnitConv; /** - * Graphics2DAdapter implementation for PCL and HP GL/2. + * Abstract base class for Graphics2DAdapter implementations. */ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter { @@ -135,4 +136,12 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter { RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); } + /** {@inheritDoc} */ + public void paintImage(Graphics2DImagePainter painter, + RendererContext context, + int x, int y, int width, int height) throws IOException { + paintImage((org.apache.xmlgraphics.java2d.Graphics2DImagePainter)painter, + context, x, y, width, height); + } + } diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index b38d973c5..a6c08747f 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -37,6 +37,8 @@ import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.CTM; +import org.apache.fop.area.NormalFlow; +import org.apache.fop.area.RegionReference; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.ForeignObject; @@ -95,19 +97,20 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { */ protected void handleRegionTraits(RegionViewport region) { Rectangle2D viewArea = region.getViewArea(); + RegionReference referenceArea = region.getRegionReference(); float startx = (float)(viewArea.getX() / 1000f); float starty = (float)(viewArea.getY() / 1000f); float width = (float)(viewArea.getWidth() / 1000f); float height = (float)(viewArea.getHeight() / 1000f); - if (region.getRegionReference().getRegionClass() == FO_REGION_BODY) { - currentBPPosition = region.getBorderAndPaddingWidthBefore(); - currentIPPosition = region.getBorderAndPaddingWidthStart(); - } - drawBackAndBorders(region, startx, starty, width, height); + // adjust the current position according to region borders and padding + currentBPPosition = referenceArea.getBorderAndPaddingWidthBefore(); + currentIPPosition = referenceArea.getBorderAndPaddingWidthStart(); + // draw background (traits are in the RegionViewport) + // and borders (traits are in the RegionReference) + drawBackAndBorders(region, referenceArea, startx, starty, width, height); } - /** * Draw the background and borders. * This draws the background and border traits for an area given @@ -122,15 +125,57 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { protected void drawBackAndBorders(Area area, float startx, float starty, float width, float height) { + drawBackAndBorders(area, area, startx, starty, width, height); + } + + /** + * Draw the background and borders. + * This draws the background and border traits for an area given + * the position. + * + * @param backgroundArea the area to get the background traits from + * @param borderArea the area to get the border traits from + * @param startx the start x position + * @param starty the start y position + * @param width the width of the area + * @param height the height of the area + */ + protected void drawBackAndBorders(Area backgroundArea, Area borderArea, + float startx, float starty, + float width, float height) { // draw background then border - BorderProps bpsBefore = (BorderProps)area.getTrait(Trait.BORDER_BEFORE); - BorderProps bpsAfter = (BorderProps)area.getTrait(Trait.BORDER_AFTER); - BorderProps bpsStart = (BorderProps)area.getTrait(Trait.BORDER_START); - BorderProps bpsEnd = (BorderProps)area.getTrait(Trait.BORDER_END); + BorderProps bpsBefore = (BorderProps)borderArea.getTrait(Trait.BORDER_BEFORE); + BorderProps bpsAfter = (BorderProps)borderArea.getTrait(Trait.BORDER_AFTER); + BorderProps bpsStart = (BorderProps)borderArea.getTrait(Trait.BORDER_START); + BorderProps bpsEnd = (BorderProps)borderArea.getTrait(Trait.BORDER_END); - Trait.Background back; - back = (Trait.Background)area.getTrait(Trait.BACKGROUND); + drawBackground(startx, starty, width, height, + (Trait.Background) backgroundArea.getTrait(Trait.BACKGROUND), + bpsBefore, bpsAfter, bpsStart, bpsEnd); + drawBorders(startx, starty, width, height, + bpsBefore, bpsAfter, bpsStart, bpsEnd); + } + + /** + * Draw the background. + * This draws the background given the position and the traits. + * + * @param startx the start x position + * @param starty the start y position + * @param width the width of the area + * @param height the height of the area + * @param back the background traits + * @param bpsBefore the border-before traits + * @param bpsAfter the border-after traits + * @param bpsStart the border-start traits + * @param bpsEnd the border-end traits + */ + protected void drawBackground(float startx, float starty, + float width, float height, + Trait.Background back, + BorderProps bpsBefore, BorderProps bpsAfter, + BorderProps bpsStart, BorderProps bpsEnd) { if (back != null) { endTextObject(); @@ -201,7 +246,25 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { restoreGraphicsState(); } } + } + /** + * Draw the borders. + * This draws the border traits given the position and the traits. + * + * @param startx the start x position + * @param starty the start y position + * @param width the width of the area + * @param height the height of the area + * @param bpsBefore the border-before traits + * @param bpsAfter the border-after traits + * @param bpsStart the border-start traits + * @param bpsEnd the border-end traits + */ + protected void drawBorders(float startx, float starty, + float width, float height, + BorderProps bpsBefore, BorderProps bpsAfter, + BorderProps bpsStart, BorderProps bpsEnd) { Rectangle2D.Float borderRect = new Rectangle2D.Float(startx, starty, width, height); drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd); } @@ -521,6 +584,69 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { } } + /** {@inheritDoc} */ + protected void renderReferenceArea(Block block) { + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + at.translate(block.getXOffset(), block.getYOffset()); + at.translate(0, block.getSpaceBefore()); + + if (!at.isIdentity()) { + saveGraphicsState(); + concatenateTransformationMatrix(mptToPt(at)); + } + + currentIPPosition = 0; + currentBPPosition = 0; + handleBlockTraits(block); + + List children = block.getChildAreas(); + if (children != null) { + renderBlocks(block, children); + } + + if (!at.isIdentity()) { + restoreGraphicsState(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + + /** {@inheritDoc} */ + protected void renderFlow(NormalFlow flow) { + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + + if (!at.isIdentity()) { + saveGraphicsState(); + concatenateTransformationMatrix(mptToPt(at)); + } + + currentIPPosition = 0; + currentBPPosition = 0; + super.renderFlow(flow); + + if (!at.isIdentity()) { + restoreGraphicsState(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + /** * Concatenates the current transformation matrix with the given one, therefore establishing * a new coordinate system. diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 816fa4067..ebff5323b 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -54,7 +54,6 @@ import org.apache.fop.area.RegionReference; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Span; import org.apache.fop.area.Trait; -import org.apache.fop.area.inline.Character; import org.apache.fop.area.inline.Container; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; @@ -246,15 +245,25 @@ public abstract class AbstractRenderer last here. */ RegionViewport viewport; viewport = page.getRegionViewport(FO_REGION_BEFORE); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_START); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_END); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_AFTER); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_BODY); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } } /** @@ -266,27 +275,25 @@ public abstract class AbstractRenderer * @param port The region viewport to be rendered */ protected void renderRegionViewport(RegionViewport port) { - if (port != null) { - Rectangle2D view = port.getViewArea(); - // The CTM will transform coordinates relative to - // this region-reference area into page coords, so - // set origin for the region to 0,0. - currentBPPosition = 0; - currentIPPosition = 0; - - RegionReference regionReference = port.getRegionReference(); - handleRegionTraits(port); - - // shouldn't the viewport have the CTM - startVParea(regionReference.getCTM(), port.isClip() ? view : null); - // do after starting viewport area - if (regionReference.getRegionClass() == FO_REGION_BODY) { - renderBodyRegion((BodyRegion) regionReference); - } else { - renderRegion(regionReference); - } - endVParea(); + Rectangle2D view = port.getViewArea(); + // The CTM will transform coordinates relative to + // this region-reference area into page coords, so + // set origin for the region to 0,0. + currentBPPosition = 0; + currentIPPosition = 0; + + RegionReference regionReference = port.getRegionReference(); + handleRegionTraits(port); + + // shouldn't the viewport have the CTM + startVParea(regionReference.getCTM(), port.isClip() ? view : null); + // do after starting viewport area + if (regionReference.getRegionClass() == FO_REGION_BODY) { + renderBodyRegion((BodyRegion) regionReference); + } else { + renderRegion(regionReference); } + endVParea(); } /** @@ -320,8 +327,7 @@ public abstract class AbstractRenderer * @param region The region reference area */ protected void renderRegion(RegionReference region) { - List blocks = region.getBlocks(); - renderBlocks(null, blocks); + renderBlocks(null, region.getBlocks()); } /** @@ -398,7 +404,7 @@ public abstract class AbstractRenderer for (int count = 0; count < spans.size(); count++) { span = (Span) spans.get(count); for (int c = 0; c < span.getColumnCount(); c++) { - NormalFlow flow = (NormalFlow) span.getNormalFlow(c); + NormalFlow flow = span.getNormalFlow(c); if (flow != null) { currentBPPosition = saveSpanBPPos; @@ -484,6 +490,13 @@ public abstract class AbstractRenderer } /** + * Renders a block area that represents a reference area. The reference area establishes + * a new coordinate system. + * @param block the block area + */ + protected abstract void renderReferenceArea(Block block); + + /** * Renders a list of block areas. * * @param parent the parent block if the parent is a block, otherwise @@ -495,7 +508,7 @@ public abstract class AbstractRenderer int saveBP = currentBPPosition; // Calculate the position of the content rectangle. - if (parent != null && !Boolean.TRUE.equals(parent.getTrait(Trait.IS_VIEWPORT_AREA))) { + if (parent != null && !parent.getTraitAsBoolean(Trait.IS_VIEWPORT_AREA)) { currentBPPosition += parent.getBorderAndPaddingWidthBefore(); /* This is unnecessary now as we're going to use the *-indent traits currentIPPosition += parent.getBorderAndPaddingWidthStart(); @@ -551,6 +564,8 @@ public abstract class AbstractRenderer // simply move position currentBPPosition += block.getAllocBPD(); } + } else if (block.getTraitAsBoolean(Trait.IS_REFERENCE_AREA)) { + renderReferenceArea(block); } else { // save position and offset int saveIP = currentIPPosition; @@ -622,15 +637,6 @@ public abstract class AbstractRenderer } } - /** - * Render the given Character. - * @param ch the character to render - * @deprecated Only TextArea should be used. This method will be removed eventually. - */ - protected void renderCharacter(Character ch) { - currentIPPosition += ch.getAllocIPD(); - } - /** * Common method to render the background and borders for any inline area. * The all borders and padding are drawn outside the specified area. @@ -738,6 +744,8 @@ public abstract class AbstractRenderer renderContainer((Container) content); } else if (content instanceof ForeignObject) { renderForeignObject((ForeignObject) content, contpos); + } else if (content instanceof InlineBlockParent) { + renderInlineBlockParent((InlineBlockParent) content); } currentIPPosition += viewport.getAllocIPD(); currentBPPosition = saveBP; @@ -776,7 +784,7 @@ public abstract class AbstractRenderer * @param pos The target position of the foreign object * (todo) Make renderForeignObject() protected */ - public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { + protected void renderForeignObject(ForeignObject fo, Rectangle2D pos) { // Default: do nothing. // Some renderers (ex. Text) don't support foreign objects. } @@ -801,8 +809,9 @@ public abstract class AbstractRenderer handler.handleXML(ctx, doc, namespace); } catch (Exception e) { // could not handle document - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - ctx.getUserAgent().getEventBroadcaster()); + ResourceEventProducer eventProducer + = ResourceEventProducer.Provider.get( + ctx.getUserAgent().getEventBroadcaster()); eventProducer.foreignXMLProcessingError(this, doc, namespace, e); } } else { diff --git a/src/java/org/apache/fop/render/Graphics2DAdapter.java b/src/java/org/apache/fop/render/Graphics2DAdapter.java index 0123e04a1..4fbdbe09a 100644 --- a/src/java/org/apache/fop/render/Graphics2DAdapter.java +++ b/src/java/org/apache/fop/render/Graphics2DAdapter.java @@ -47,4 +47,23 @@ public interface Graphics2DAdapter { RendererContext context, int x, int y, int width, int height) throws IOException; + /** + * Paints an arbitrary images on a given Graphics2D instance. The renderer + * providing this functionality must set up a Graphics2D instance so that + * the image with the given extents (in mpt) can be painted by the painter + * passed to this method. The Graphics2DImagePainter is then passed this + * Graphics2D instance so the image can be painted. + * @param painter the painter which will paint the actual image + * @param context the renderer context for the current renderer + * @param x X position of the image + * @param y Y position of the image + * @param width width of the image + * @param height height of the image + * @throws IOException In case of an I/O error while writing the output format + * @deprecated Use the variant with the Graphics2DImagePainter from XML Graphics Commons instead + */ + void paintImage(Graphics2DImagePainter painter, + RendererContext context, + int x, int y, int width, int height) throws IOException; + } diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 045ba9835..5c8e80312 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -59,6 +59,7 @@ import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BodyRegion; import org.apache.fop.area.CTM; +import org.apache.fop.area.NormalFlow; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionReference; @@ -467,9 +468,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void renderBlockViewport(BlockViewport bv, List children) { // clip and position viewport if necessary @@ -591,6 +590,76 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } /** {@inheritDoc} */ + protected void renderReferenceArea(Block block) { + //TODO Remove this method once concatenateTransformationMatrix() is implemented + + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + at.translate(block.getXOffset(), block.getYOffset()); + at.translate(0, block.getSpaceBefore()); + + if (!at.isIdentity()) { + Rectangle2D contentRect + = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(), + block.getAllocIPD(), block.getAllocBPD()); + pushViewPortPos(new ViewPortPos(contentRect, new CTM(at))); + } + + currentIPPosition = 0; + currentBPPosition = 0; + handleBlockTraits(block); + + List children = block.getChildAreas(); + if (children != null) { + renderBlocks(block, children); + } + + if (!at.isIdentity()) { + popViewPortPos(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + + /** {@inheritDoc} */ + protected void renderFlow(NormalFlow flow) { + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + + if (!at.isIdentity()) { + Rectangle2D contentRect + = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(), + flow.getAllocIPD(), flow.getAllocBPD()); + pushViewPortPos(new ViewPortPos(contentRect, new CTM(at))); + } + + currentIPPosition = 0; + currentBPPosition = 0; + super.renderFlow(flow); + + if (!at.isIdentity()) { + popViewPortPos(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + + + /** {@inheritDoc} */ protected void concatenateTransformationMatrix(AffineTransform at) { //Not used here since AFPRenderer defines its own renderBlockViewport() method. throw new UnsupportedOperationException("NYI"); @@ -1218,20 +1287,24 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } } - /** - * Restores the state stack after a break out. - * @param breakOutList the state stack to restore. - */ - public void restoreStateStackAfterBreakOut(List breakOutList) { - + /** {@inheritDoc} */ + public List breakOutOfStateStack() { + log.debug("Block.FIXED --> break out"); + List breakOutList = new java.util.ArrayList(); + //Don't pop the last ViewPortPos (created by renderPage()) + while (this.viewPortPositions.size() > 1) { + breakOutList.add(0, popViewPortPos()); + } + return breakOutList; } - /** - * Breaks out of the state stack to handle fixed block-containers. - * @return the saved state stack to recreate later - */ - public List breakOutOfStateStack() { - return null; + /** {@inheritDoc} */ + public void restoreStateStackAfterBreakOut(List breakOutList) { + log.debug("Block.FIXED --> restoring context after break-out"); + for (int i = 0, c = breakOutList.size(); i < c; i++) { + ViewPortPos vps = (ViewPortPos)breakOutList.get(i); + pushViewPortPos(vps); + } } /** Saves the graphics state of the rendering engine. */ @@ -1755,12 +1828,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot); } - private void popViewPortPos() { - viewPortPositions.remove(viewPortPositions.size() - 1); + private ViewPortPos popViewPortPos() { + ViewPortPos current = (ViewPortPos)viewPortPositions.remove(viewPortPositions.size() - 1); if (viewPortPositions.size() > 0) { ViewPortPos vpp = (ViewPortPos)viewPortPositions.get(viewPortPositions.size() - 1); afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot); } + return current; } /** diff --git a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java index 48feba135..b29378a96 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java @@ -28,13 +28,13 @@ import java.io.IOException; import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; -import org.apache.fop.render.Graphics2DAdapter; +import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.RendererContext; /** * Graphics2DAdapter implementation for Java2D. */ -public class Java2DGraphics2DAdapter implements Graphics2DAdapter { +public class Java2DGraphics2DAdapter extends AbstractGraphics2DAdapter { /** {@inheritDoc} */ public void paintImage(Graphics2DImagePainter painter, diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index e39ae5831..5996c5d0c 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -539,7 +539,9 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem protected void drawBorderLine(float x1, float y1, float x2, float y2, boolean horz, boolean startOrBefore, int style, Color col) { Graphics2D g2d = state.getGraph(); - drawBorderLine(new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1), + float width = x2 - x1; + float height = y2 - y1; + drawBorderLine(new Rectangle2D.Float(x1, y1, width, height), horz, startOrBefore, style, col, g2d); } diff --git a/src/java/org/apache/fop/render/pcl/PCLGenerator.java b/src/java/org/apache/fop/render/pcl/PCLGenerator.java index 5ca9a8bf9..6a4425012 100644 --- a/src/java/org/apache/fop/render/pcl/PCLGenerator.java +++ b/src/java/org/apache/fop/render/pcl/PCLGenerator.java @@ -230,6 +230,19 @@ public class PCLGenerator { } /** + * Selects the duplexing mode for the page. + * The parameter is usually printer-specific. + * "0" means Simplex, + * "1" means Duplex, Long-Edge Binding, + * "2" means Duplex, Short-Edge Binding. + * @param selector the integer representing the duplexing mode of the page + * @throws IOException In case of an I/O error + */ + public void selectDuplexMode(int selector) throws IOException { + writeCommand("&l" + selector + "S"); + } + + /** * Clears the horizontal margins. * @throws IOException In case of an I/O error */ diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 007ce4828..7ab46c24e 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -66,6 +66,7 @@ import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.CTM; +import org.apache.fop.area.NormalFlow; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; @@ -395,9 +396,7 @@ public class PCLRenderer extends PrintRenderer { return MIME_TYPE; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderPage(PageViewport page) throws IOException, FOPException { saveGraphicsState(); @@ -408,6 +407,13 @@ public class PCLRenderer extends PrintRenderer { gen.selectPaperSource(Integer.parseInt(paperSource)); } + // Is Page duplex? + String pageDuplex = page.getForeignAttributeValue( + new QName(PCLElementMapping.NAMESPACE, null, "duplex-mode")); + if (pageDuplex != null) { + gen.selectDuplexMode(Integer.parseInt(pageDuplex)); + } + //Page size final long pagewidth = Math.round(page.getViewArea().getWidth()); final long pageheight = Math.round(page.getViewArea().getHeight()); @@ -1023,6 +1029,79 @@ public class PCLRenderer extends PrintRenderer { //currentFontName = saveFontName; } + /** {@inheritDoc} */ + protected void renderReferenceArea(Block block) { + //TODO This is the same code as in AbstractPathOrientedRenderer + //So there's some optimization potential but not otherwise PCLRenderer is a little + //difficult to derive from AbstractPathOrientedRenderer. Maybe an additional layer + //between PrintRenderer and AbstractPathOrientedRenderer is necessary. + + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + at.translate(block.getXOffset(), block.getYOffset()); + at.translate(0, block.getSpaceBefore()); + + if (!at.isIdentity()) { + saveGraphicsState(); + concatenateTransformationMatrix(mptToPt(at)); + } + + currentIPPosition = 0; + currentBPPosition = 0; + handleBlockTraits(block); + + List children = block.getChildAreas(); + if (children != null) { + renderBlocks(block, children); + } + + if (!at.isIdentity()) { + restoreGraphicsState(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + + /** {@inheritDoc} */ + protected void renderFlow(NormalFlow flow) { + //TODO This is the same code as in AbstractPathOrientedRenderer + //So there's some optimization potential but not otherwise PCLRenderer is a little + //difficult to derive from AbstractPathOrientedRenderer. Maybe an additional layer + //between PrintRenderer and AbstractPathOrientedRenderer is necessary. + + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + + if (!at.isIdentity()) { + saveGraphicsState(); + concatenateTransformationMatrix(mptToPt(at)); + } + + currentIPPosition = 0; + currentBPPosition = 0; + super.renderFlow(flow); + + if (!at.isIdentity()) { + restoreGraphicsState(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + /** * Concatenates the current transformation matrix with the given one, therefore establishing * a new coordinate system. diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 06f5921cc..154365209 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -1415,7 +1415,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { updateColor(ct, true); beginTextObject(); - StringBuffer pdf = new StringBuffer(); String fontName = getInternalFontNameForArea(text); int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); @@ -1434,8 +1433,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, rx / 1000f, bl / 1000f)); - currentStream.add(pdf.toString()); - super.renderText(text); textutil.writeTJ(); @@ -1844,5 +1841,13 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { public void setFilterMap(Map filterMap) { this.filterMap = filterMap; } + + /** + * Sets the encryption parameters used by the PDF renderer. + * @param encryptionParams the encryption parameters + */ + public void setEncryptionParams(PDFEncryptionParams encryptionParams) { + this.encryptionParams = encryptionParams; + } } diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java index 2fce8859a..51e13dde1 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java @@ -28,6 +28,7 @@ import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.pdf.PDFAMode; +import org.apache.fop.pdf.PDFEncryptionParams; import org.apache.fop.pdf.PDFFilterList; import org.apache.fop.pdf.PDFXMode; import org.apache.fop.render.PrintRendererConfigurator; @@ -78,13 +79,54 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator { if (s != null) { pdfRenderer.setXMode(PDFXMode.valueOf(s)); } + Configuration encryptionParamsConfig = cfg.getChild(PDFRenderer.ENCRYPTION_PARAMS, false); + if (encryptionParamsConfig != null) { + PDFEncryptionParams encryptionParams = new PDFEncryptionParams(); + Configuration ownerPasswordConfig = encryptionParamsConfig.getChild( + PDFRenderer.OWNER_PASSWORD, false); + if (ownerPasswordConfig != null) { + String ownerPassword = ownerPasswordConfig.getValue(null); + if (ownerPassword != null) { + encryptionParams.setOwnerPassword(ownerPassword); + } + } + Configuration userPasswordConfig = encryptionParamsConfig.getChild( + PDFRenderer.USER_PASSWORD, false); + if (userPasswordConfig != null) { + String userPassword = userPasswordConfig.getValue(null); + if (userPassword != null) { + encryptionParams.setUserPassword(userPassword); + } + } + Configuration noPrintConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_PRINT, false); + if (noPrintConfig != null) { + encryptionParams.setAllowPrint(false); + } + Configuration noCopyContentConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_COPY_CONTENT, false); + if (noCopyContentConfig != null) { + encryptionParams.setAllowCopyContent(false); + } + Configuration noEditContentConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_EDIT_CONTENT, false); + if (noEditContentConfig != null) { + encryptionParams.setAllowEditContent(false); + } + Configuration noAnnotationsConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_ANNOTATIONS, false); + if (noAnnotationsConfig != null) { + encryptionParams.setAllowEditAnnotations(false); + } + pdfRenderer.setEncryptionParams(encryptionParams); + } s = cfg.getChild(PDFRenderer.KEY_OUTPUT_PROFILE, true).getValue(null); if (s != null) { pdfRenderer.setOutputProfileURI(s); } - Configuration child = cfg.getChild(PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false); - if (child != null) { - pdfRenderer.disableSRGBColorSpace = child.getValueAsBoolean(false); + Configuration disableColorSpaceConfig = cfg.getChild(PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false); + if (disableColorSpaceConfig != null) { + pdfRenderer.disableSRGBColorSpace = disableColorSpaceConfig.getValueAsBoolean(false); } } } diff --git a/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java b/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java index ab39966d4..d5b2d2a23 100644 --- a/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java +++ b/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java @@ -25,6 +25,7 @@ import java.io.OutputStream; import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; import org.apache.xmlgraphics.ps.ImageEncoder; +import org.apache.xmlgraphics.ps.PSDictionary; /** * ImageEncoder implementation for CCITT encoded images. diff --git a/src/java/org/apache/fop/render/ps/PSDictionary.java b/src/java/org/apache/fop/render/ps/PSDictionary.java deleted file mode 100644 index 5a8f1ea14..000000000 --- a/src/java/org/apache/fop/render/ps/PSDictionary.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.ps; - -import java.util.Iterator; -import java.util.List; -import java.util.StringTokenizer; - -/** - * This class is used to encapsulate postscript dictionary objects. - */ -public class PSDictionary extends java.util.HashMap { - - private static final long serialVersionUID = 815367222496219197L; - - /** - * This class is used to parse dictionary strings. - */ - private static class Maker { - - /** - * Simple token holding class - */ - private class Token { - /** - * start index in string - */ - private int startIndex = -1; - - /** - * end index in string - */ - private int endIndex = -1; - - /** - * token string value - */ - private String value; - } - - private static final String[][] BRACES = { - {"<<", ">>"}, - {"[", "]"}, - {"{", "}"} - }; - - private static final int OPENING = 0; - private static final int CLOSING = 1; - private static final int DICTIONARY = 0; - private static final int ARRAY = 1; - private static final int PROCEDURE = 2; - - /** - * Returns a Token containing the start, end index and value of the next token - * found in a given string - * - * @param str - * string to search - * @param fromIndex - * search from index - * @return Token containing the start, end index and value of the next token - */ - protected Token nextToken(String str, int fromIndex) { - Token t = null; - for (int i = fromIndex; i < str.length(); i++) { - boolean isWhitespace = Character.isWhitespace(str.charAt(i)); - // start index found - if (t == null && !isWhitespace) { - t = new Token(); - t.startIndex = i; - // end index found - } else if (t != null && isWhitespace) { - t.endIndex = i; - break; - } - } - // start index found - if (t != null) { - // end index not found so take end of string - if (t.endIndex == -1) { - t.endIndex = str.length(); - } - t.value = str.substring(t.startIndex, t.endIndex); - } - return t; - } - - /** - * Returns the closing brace index from a given string searches from a - * given index - * - * @param str - * string to search - * @param braces - * string array of opening and closing brace - * @param fromIndex - * searches from index - * @return matching brace index - * @throws org.apache.fop.render.ps.PSDictionaryFormatException - * thrown in the event that a parsing error occurred - */ - private int indexOfMatchingBrace(String str, String[] braces, - int fromIndex) throws PSDictionaryFormatException { - final int len = str.length(); - if (braces.length != 2) { - throw new PSDictionaryFormatException("Wrong number of braces"); - } - for (int openCnt = 0, closeCnt = 0; fromIndex < len; fromIndex++) { - if (str.startsWith(braces[OPENING], fromIndex)) { - openCnt++; - } else if (str.startsWith(braces[CLOSING], fromIndex)) { - closeCnt++; - if (openCnt > 0 && openCnt == closeCnt) { - return fromIndex; // found - } - } - } - return -1; // not found - } - - /** - * Strips braces from complex object string - * - * @param str - * String to parse - * @param braces - * String array containing opening and closing braces - * @return String with braces stripped - * @throws - * org.apache.fop.render.ps.PSDictionaryFormatException object format exception - */ - private String stripBraces(String str, String[] braces) throws PSDictionaryFormatException { - // find first opening brace - int firstIndex = str.indexOf(braces[OPENING]); - if (firstIndex == -1) { - throw new PSDictionaryFormatException( - "Failed to find opening parameter '" + braces[OPENING] - + ""); - } - - // find last matching brace - int lastIndex = indexOfMatchingBrace(str, braces, firstIndex); - if (lastIndex == -1) { - throw new PSDictionaryFormatException( - "Failed to find matching closing parameter '" - + braces[CLOSING] + "'"); - } - - // strip brace and trim - int braceLen = braces[OPENING].length(); - str = str.substring(firstIndex + braceLen, lastIndex).trim(); - return str; - } - - /** - * Parses a dictionary string and provides a dictionary object - * - * @param str a dictionary string - * @return A postscript dictionary object - * @throws - * PSDictionaryFormatException thrown if a dictionary format exception occurs - */ - public PSDictionary parseDictionary(String str) throws PSDictionaryFormatException { - PSDictionary dictionary = new PSDictionary(); - str = stripBraces(str.trim(), BRACES[DICTIONARY]); - // length of dictionary string - final int len = str.length(); - - Token keyToken; - for (int currIndex = 0; (keyToken = nextToken(str, currIndex)) != null - && currIndex <= len;) { - if (keyToken.value == null) { - throw new PSDictionaryFormatException("Failed to parse object key"); - } - Token valueToken = nextToken(str, keyToken.endIndex + 1); - String[] braces = null; - for (int i = 0; i < BRACES.length; i++) { - if (valueToken.value.startsWith(BRACES[i][OPENING])) { - braces = BRACES[i]; - break; - } - } - Object obj = null; - if (braces != null) { - // find closing brace - valueToken.endIndex = indexOfMatchingBrace(str, braces, - valueToken.startIndex) - + braces[OPENING].length(); - if (valueToken.endIndex < 0) { - throw new PSDictionaryFormatException("Closing value brace '" - + braces[CLOSING] + "' not found for key '" - + keyToken.value + "'"); - } - valueToken.value = str.substring(valueToken.startIndex, valueToken.endIndex); - } - if (braces == null || braces == BRACES[PROCEDURE]) { - obj = valueToken.value; - } else if (BRACES[ARRAY] == braces) { - List objList = new java.util.ArrayList(); - String objString = stripBraces(valueToken.value, braces); - StringTokenizer tokenizer = new StringTokenizer(objString, ","); - while (tokenizer.hasMoreTokens()) { - objList.add(tokenizer.nextToken()); - } - obj = objList; - } else if (BRACES[DICTIONARY] == braces) { - obj = parseDictionary(valueToken.value); - } - dictionary.put(keyToken.value, obj); - currIndex = valueToken.endIndex + 1; - } - return dictionary; - } - } - - /** - * Parses a given a dictionary string and returns an object - * - * @param str dictionary string - * @return dictionary object - * @throws PSDictionaryFormatException object format exception - */ - public static PSDictionary valueOf(String str) throws PSDictionaryFormatException { - return (new Maker()).parseDictionary(str); - } - - /** - * @param obj object to test equality against - * @return whether a given object is equal to this dictionary object - * @see java.lang.Object#equals(Object) - */ - public boolean equals(Object obj) { - if (!(obj instanceof PSPageDeviceDictionary)) { - return false; - } - PSDictionary dictionaryObj = (PSDictionary) obj; - if (dictionaryObj.size() != size()) { - return false; - } - for (Iterator it = keySet().iterator(); it.hasNext();) { - String key = (String) it.next(); - if (!dictionaryObj.containsKey(key)) { - return false; - } - if (!dictionaryObj.get(key).equals(get(key))) { - return false; - } - } - return true; - } - - /** - * @return a hash code value for this object. - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - int hashCode = 7; - for (Iterator it = values().iterator(); it.hasNext();) { - Object value = it.next(); - hashCode += value.hashCode(); - } - return hashCode; - } - - /** - * @return a string representation of this dictionary - * @see java.lang.String#toString() - */ - public String toString() { - if (isEmpty()) { - return ""; - } - StringBuffer sb = new StringBuffer("<<\n"); - for (Iterator it = super.keySet().iterator(); it.hasNext();) { - String key = (String) it.next(); - sb.append(" " + key + " "); - Object obj = super.get(key); - if (obj instanceof java.util.ArrayList) { - List array = (List)obj; - String str = "["; - for (int i = 0; i < array.size(); i++) { - Object element = array.get(i); - str += element + " "; - } - str = str.trim(); - str += "]"; - sb.append(str + "\n"); - } else { - sb.append(obj.toString() + "\n"); - } - } - sb.append(">>"); - return sb.toString(); - } -} diff --git a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java index a592b4f44..994481d59 100644 --- a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java @@ -28,13 +28,13 @@ import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; import org.apache.xmlgraphics.ps.PSGenerator; -import org.apache.fop.render.Graphics2DAdapter; +import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.RendererContext; /** * Graphics2DAdapter implementation for PostScript. */ -public class PSGraphics2DAdapter implements Graphics2DAdapter { +public class PSGraphics2DAdapter extends AbstractGraphics2DAdapter { private PSGenerator gen; private boolean clip = true; diff --git a/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java b/src/java/org/apache/fop/render/ps/PSImageUtils.java index 1a0171d68..27eb736d8 100644 --- a/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java +++ b/src/java/org/apache/fop/render/ps/PSImageUtils.java @@ -16,22 +16,14 @@ */ /* $Id$ */ - + package org.apache.fop.render.ps; /** - * Thrown to indicate that a formatting error has occured when - * trying to parse a postscript dictionary object + * Utility code for rendering images in PostScript. + * @deprecated Kept for compatibility with older FOP extensions (like Barcode4J). Use the + * super-class instead. */ -public class PSDictionaryFormatException extends Exception { - - private static final long serialVersionUID = 6492321557297860931L; +public class PSImageUtils extends org.apache.xmlgraphics.ps.PSImageUtils { - /** - * Default constructor - * @param string error message - */ - public PSDictionaryFormatException(String string) { - super(string); - } } diff --git a/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java b/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java deleted file mode 100644 index 88667c24d..000000000 --- a/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.ps; - -/** - * Postscript page device dictionary object - * - * This object is used by the postscript renderer to hold postscript page device - * values. It can also be used to minimize the number of setpagedevice calls when - * DSC compliance is false. - */ -public class PSPageDeviceDictionary extends PSDictionary { - - private static final long serialVersionUID = 845943256485806509L; - - /** - * Whether or not the contents of the dictionary are flushed on retrieval - */ - private boolean flushOnRetrieval = false; - - /** - * Dictionary content that has not been output/written yet - */ - private PSDictionary unRetrievedContentDictionary; - - /** - * @param key key with which the specified value is to be associated. - * @param value value to be associated with the specified key. - * @return the previous value associated with the key or null - * @see java.util.Map#put(Object, Object) - */ - public Object put(Object key, Object value) { - Object previousValue = super.put(key, value); - if (flushOnRetrieval) { - if (previousValue == null || !previousValue.equals(value)) { - unRetrievedContentDictionary.put(key, value); - } - } - return previousValue; - } - - /** - * @see java.util.Map#clear() - */ - public void clear() { - super.clear(); - if (unRetrievedContentDictionary != null) { - unRetrievedContentDictionary.clear(); - } - } - - /** - * Returns <tt>true</tt> if this map contains no key-value mappings. - * - * @return <tt>true</tt> if this map contains no key-value mappings. - */ - public boolean isEmpty() { - if (flushOnRetrieval) { - return unRetrievedContentDictionary.isEmpty(); - } - return super.isEmpty(); - } - - /** - * The contents of the dictionary are flushed when written - * @param flushOnRetrieval boolean value - */ - public void setFlushOnRetrieval(boolean flushOnRetrieval) { - this.flushOnRetrieval = flushOnRetrieval; - if (flushOnRetrieval) { - unRetrievedContentDictionary = new PSDictionary(); - } - } - - /** - * Returns a dictionary string with containing all unwritten content note: - * unnecessary writes are important as there is a device specific - * initgraphics call by the underlying postscript interpreter on every - * setpagedevice call which can result in blank pages etc. - * - * @return unwritten content dictionary string - */ - public String getContent() { - String content; - if (flushOnRetrieval) { - content = unRetrievedContentDictionary.toString(); - unRetrievedContentDictionary.clear(); - } else { - content = super.toString(); - } - return content; - } -} diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index a94c8b0aa..3f1769295 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -57,6 +57,9 @@ import org.apache.xmlgraphics.image.loader.pipeline.ImageProviderPipeline; import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.ps.DSCConstants; import org.apache.xmlgraphics.ps.ImageEncoder; +import org.apache.xmlgraphics.ps.PSDictionary; +import org.apache.xmlgraphics.ps.PSPageDeviceDictionary; +import org.apache.xmlgraphics.ps.PSDictionaryFormatException; import org.apache.xmlgraphics.ps.PSGenerator; import org.apache.xmlgraphics.ps.PSImageUtils; import org.apache.xmlgraphics.ps.PSProcSets; diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java index 3fccf4f67..9da2b0911 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java @@ -78,7 +78,7 @@ public abstract class PSExtensionAttachment implements ExtensionAttachment, XMLi * * @param handler ContentHandler instance to send the SAX events to * @throws SAXException if there's a problem generating the SAX events - * @see org.apache.fop.util.XMLizable#toSAX(org.xml.sax.ContentHandler) + * @see org.apache.xmlgraphics.util.XMLizable#toSAX(org.xml.sax.ContentHandler) */ public void toSAX(ContentHandler handler) throws SAXException { AttributesImpl atts = new AttributesImpl(); diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 05aade551..6171e68b4 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -76,6 +76,8 @@ import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.fo.flow.PageNumber; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TableFooter; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableHeader; @@ -611,25 +613,29 @@ public class RTFHandler extends FOEventHandler { /** * {@inheritDoc} */ - public void startHeader(TableBody th) { + public void startHeader(TableHeader header) { + startPart(header); } /** * {@inheritDoc} */ - public void endHeader(TableBody th) { + public void endHeader(TableHeader header) { + endPart(header); } /** * {@inheritDoc} */ - public void startFooter(TableBody tf) { + public void startFooter(TableFooter footer) { + startPart(footer); } /** * {@inheritDoc} */ - public void endFooter(TableBody tf) { + public void endFooter(TableFooter footer) { + endPart(footer); } /** @@ -687,31 +693,25 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ - public void startBody(TableBody tb) { + private void startPart(TablePart part) { if (bDefer) { return; } try { - RtfAttributes atts = TableAttributesConverter.convertTableBodyAttributes(tb); + RtfAttributes atts = TableAttributesConverter.convertTablePartAttributes(part); RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this); tbl.setHeaderAttribs(atts); } catch (IOException ioe) { handleIOTrouble(ioe); } catch (Exception e) { - log.error("startBody: " + e.getMessage()); + log.error("startPart: " + e.getMessage()); throw new RuntimeException(e.getMessage()); - } + } } - /** - * {@inheritDoc} - */ - public void endBody(TableBody tb) { + private void endPart(TablePart tb) { if (bDefer) { return; } @@ -722,9 +722,25 @@ public class RTFHandler extends FOEventHandler { } catch (IOException ioe) { handleIOTrouble(ioe); } catch (Exception e) { - log.error("endBody: " + e.getMessage()); + log.error("endPart: " + e.getMessage()); throw new RuntimeException(e.getMessage()); - } + } + } + + + /** + * {@inheritDoc} + */ + public void startBody(TableBody body) { + startPart(body); + } + + + /** + * {@inheritDoc} + */ + public void endBody(TableBody body) { + endPart(body); } /** @@ -1552,7 +1568,7 @@ public class RTFHandler extends FOEventHandler { } else if (foNode instanceof FOText) { if (bStart) { FOText text = (FOText) foNode; - text(text, text.ca, text.startIndex, text.endIndex); + text(text, text.getCharArray(), 0, text.length()); } } else if (foNode instanceof Character) { if (bStart) { @@ -1607,6 +1623,18 @@ public class RTFHandler extends FOEventHandler { } else { endTable( (Table) foNode); } + } else if (foNode instanceof TableHeader) { + if (bStart) { + startHeader( (TableHeader) foNode); + } else { + endHeader( (TableHeader) foNode); + } + } else if (foNode instanceof TableFooter) { + if (bStart) { + startFooter( (TableFooter) foNode); + } else { + endFooter( (TableFooter) foNode); + } } else if (foNode instanceof TableBody) { if (bStart) { startBody( (TableBody) foNode); diff --git a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java index 677832418..a28d91d36 100644 --- a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java +++ b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java @@ -24,12 +24,11 @@ import java.awt.Color; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.Table; -import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableHeader; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; -import org.apache.fop.fo.properties.FixedLength; import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes; @@ -91,7 +90,7 @@ public final class TableAttributesConverter { * * @throws ConverterException On convertion error */ - static RtfAttributes convertTableBodyAttributes(TableBody fobj) + static RtfAttributes convertTablePartAttributes(TablePart part) throws FOPException { FOPRtfAttributes attrib = new FOPRtfAttributes(); return attrib; diff --git a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java new file mode 100644 index 000000000..7aa22e080 --- /dev/null +++ b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java @@ -0,0 +1,268 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.render.xml; + +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.apache.fop.area.BookmarkData; +import org.apache.fop.area.OffDocumentExtensionAttachment; +import org.apache.fop.area.OffDocumentItem; +import org.apache.fop.area.PageViewport; +import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.fop.render.PrintRenderer; +import org.apache.fop.render.RendererContext; +import org.apache.xmlgraphics.util.QName; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.helpers.AttributesImpl; + +public abstract class AbstractXMLRenderer extends PrintRenderer { + /** Main namespace in use. */ + public static final String NS = ""; + + /** CDATA type */ + public static final String CDATA = "CDATA"; + + /** An empty Attributes object used when no attributes are needed. */ + public static final Attributes EMPTY_ATTS = new AttributesImpl(); + + /** AttributesImpl instance that can be used during XML generation. */ + protected AttributesImpl atts = new AttributesImpl(); + + /** ContentHandler that the generated XML is written to */ + protected ContentHandler handler; + + /** The OutputStream to write the generated XML to. */ + protected OutputStream out; + + protected RendererContext context; + + /** A list of ExtensionAttachements received through processOffDocumentItem() */ + protected List extensionAttachments; + + /** + * Handles SAXExceptions. + * @param saxe the SAXException to handle + */ + protected void handleSAXException(SAXException saxe) { + throw new RuntimeException(saxe.getMessage()); + } + + /** + * Handles page extension attachments + * @param page the page viewport + */ + protected void handlePageExtensionAttachments(PageViewport page) { + handleExtensionAttachments(page.getExtensionAttachments()); + } + + /** + * Writes a comment to the generated XML. + * @param comment the comment + */ + protected void comment(String comment) { + if (handler instanceof LexicalHandler) { + try { + ((LexicalHandler) handler).comment(comment.toCharArray(), 0, comment.length()); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + } + + /** + * Starts a new element (without attributes). + * @param tagName tag name of the element + */ + protected void startElement(String tagName) { + startElement(tagName, EMPTY_ATTS); + } + + /** + * Starts a new element. + * @param tagName tag name of the element + * @param atts attributes to add + */ + protected void startElement(String tagName, Attributes atts) { + try { + handler.startElement(NS, tagName, tagName, atts); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + + /** + * Ends an element. + * @param tagName tag name of the element + */ + protected void endElement(String tagName) { + try { + handler.endElement(NS, tagName, tagName); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + + /** + * Sends plain text to the XML + * @param text the text + */ + protected void characters(String text) { + try { + char[] ca = text.toCharArray(); + handler.characters(ca, 0, ca.length); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + + /** + * Adds a new attribute to the protected member variable "atts". + * @param name name of the attribute + * @param value value of the attribute + */ + protected void addAttribute(String name, String value) { + atts.addAttribute(NS, name, name, CDATA, value); + } + + /** + * Adds a new attribute to the protected member variable "atts". + * @param name name of the attribute + * @param value value of the attribute + */ + protected void addAttribute(QName name, String value) { + atts.addAttribute(name.getNamespaceURI(), name.getLocalName(), name.getQName(), + CDATA, value); + } + + /** + * Adds a new attribute to the protected member variable "atts". + * @param name name of the attribute + * @param value value of the attribute + */ + protected void addAttribute(String name, int value) { + addAttribute(name, Integer.toString(value)); + } + + private String createString(Rectangle2D rect) { + return "" + (int) rect.getX() + " " + (int) rect.getY() + " " + + (int) rect.getWidth() + " " + (int) rect.getHeight(); + } + + /** + * Adds a new attribute to the protected member variable "atts". + * @param name name of the attribute + * @param rect a Rectangle2D to format and use as attribute value + */ + protected void addAttribute(String name, Rectangle2D rect) { + addAttribute(name, createString(rect)); + } + + /** {@inheritDoc} */ + public void startRenderer(OutputStream outputStream) + throws IOException { + if (this.handler == null) { + SAXTransformerFactory factory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + try { + TransformerHandler transformerHandler = factory.newTransformerHandler(); + setContentHandler(transformerHandler); + StreamResult res = new StreamResult(outputStream); + transformerHandler.setResult(res); + } catch (TransformerConfigurationException tce) { + throw new RuntimeException(tce.getMessage()); + } + this.out = outputStream; + } + + try { + handler.startDocument(); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + + /** {@inheritDoc} */ + public void stopRenderer() throws IOException { + try { + handler.endDocument(); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + if (this.out != null) { + this.out.flush(); + } + } + + /** {@inheritDoc} */ + public void processOffDocumentItem(OffDocumentItem oDI) { + if (oDI instanceof BookmarkData) { + renderBookmarkTree((BookmarkData) oDI); + } else if (oDI instanceof OffDocumentExtensionAttachment) { + ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)oDI).getAttachment(); + if (extensionAttachments == null) { + extensionAttachments = new java.util.ArrayList(); + } + extensionAttachments.add(attachment); + } else { + String warn = "Ignoring OffDocumentItem: " + oDI; + log.warn(warn); + } + } + + /** {@inheritDoc} */ + protected void handleDocumentExtensionAttachments() { + if (extensionAttachments != null && extensionAttachments.size() > 0) { + handleExtensionAttachments(extensionAttachments); + extensionAttachments.clear(); + } + } + + /** + * Sets an outside TransformerHandler to use instead of the default one + * create in this class in startRenderer(). + * @param handler Overriding TransformerHandler + */ + public void setContentHandler(ContentHandler handler) { + this.handler = handler; + } + + /** + * Handles a list of extension attachments + * @param attachments a list of extension attachments + */ + protected abstract void handleExtensionAttachments(List attachments); + + /** + * Renders a bookmark tree + * @param odi the bookmark data + */ + protected abstract void renderBookmarkTree(BookmarkData odi); +} diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index eb3c92e1b..b41de7387 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -35,11 +35,7 @@ import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; -import org.xml.sax.ext.LexicalHandler; -import org.xml.sax.helpers.AttributesImpl; import org.apache.xmlgraphics.util.QName; import org.apache.xmlgraphics.util.XMLizable; @@ -99,39 +95,17 @@ import org.apache.fop.util.ColorUtil; * The output can be used to build a new area tree which can be * rendered to any renderer. */ -public class XMLRenderer extends PrintRenderer { +public class XMLRenderer extends AbstractXMLRenderer { /** XML MIME type */ public static final String XML_MIME_TYPE = MimeConstants.MIME_FOP_AREA_TREE; - /** Main namespace in use. */ - public static final String NS = ""; - - /** CDATA type */ - public static final String CDATA = "CDATA"; - - /** An empty Attributes object used when no attributes are needed. */ - public static final Attributes EMPTY_ATTS = new AttributesImpl(); - private boolean startedSequence = false; - private RendererContext context; private boolean compactFormat = false; /** If not null, the XMLRenderer will mimic another renderer by using its font setup. */ protected Renderer mimic; - /** ContentHandler that the generated XML is written to */ - protected ContentHandler handler; - - /** AttributesImpl instance that can be used during XML generation. */ - protected AttributesImpl atts = new AttributesImpl(); - - /** The OutputStream to write the generated XML to. */ - protected OutputStream out; - - /** A list of ExtensionAttachements received through processOffDocumentItem() */ - protected List extensionAttachments; - /** * Creates a new XML renderer. */ @@ -171,15 +145,6 @@ public class XMLRenderer extends PrintRenderer { } } - /** - * Sets an outside TransformerHandler to use instead of the default one - * create in this class in startRenderer(). - * @param handler Overriding TransformerHandler - */ - public void setContentHandler(ContentHandler handler) { - this.handler = handler; - } - public void setCompactFormat(boolean compact) { this.compactFormat = compact; } @@ -189,111 +154,6 @@ public class XMLRenderer extends PrintRenderer { } /** - * Handles SAXExceptions. - * @param saxe the SAXException to handle - */ - protected void handleSAXException(SAXException saxe) { - throw new RuntimeException(saxe.getMessage()); - } - - /** - * Writes a comment to the generated XML. - * @param comment the comment - */ - protected void comment(String comment) { - if (handler instanceof LexicalHandler) { - try { - ((LexicalHandler) handler).comment(comment.toCharArray(), 0, comment.length()); - } catch (SAXException saxe) { - handleSAXException(saxe); - } - } - } - - /** - * Starts a new element (without attributes). - * @param tagName tag name of the element - */ - protected void startElement(String tagName) { - startElement(tagName, EMPTY_ATTS); - } - - /** - * Starts a new element. - * @param tagName tag name of the element - * @param atts attributes to add - */ - protected void startElement(String tagName, Attributes atts) { - try { - handler.startElement(NS, tagName, tagName, atts); - } catch (SAXException saxe) { - handleSAXException(saxe); - } - } - - /** - * Ends an element. - * @param tagName tag name of the element - */ - protected void endElement(String tagName) { - try { - handler.endElement(NS, tagName, tagName); - } catch (SAXException saxe) { - handleSAXException(saxe); - } - } - - /** - * Sends plain text to the XML - * @param text the text - */ - protected void characters(String text) { - try { - char[] ca = text.toCharArray(); - handler.characters(ca, 0, ca.length); - } catch (SAXException saxe) { - handleSAXException(saxe); - } - } - - /** - * Adds a new attribute to the protected member variable "atts". - * @param name name of the attribute - * @param value value of the attribute - */ - protected void addAttribute(String name, String value) { - atts.addAttribute(NS, name, name, CDATA, value); - } - - /** - * Adds a new attribute to the protected member variable "atts". - * @param name name of the attribute - * @param value value of the attribute - */ - protected void addAttribute(QName name, String value) { - atts.addAttribute(name.getNamespaceURI(), name.getLocalName(), name.getQName(), - CDATA, value); - } - - /** - * Adds a new attribute to the protected member variable "atts". - * @param name name of the attribute - * @param value value of the attribute - */ - protected void addAttribute(String name, int value) { - addAttribute(name, Integer.toString(value)); - } - - /** - * Adds a new attribute to the protected member variable "atts". - * @param name name of the attribute - * @param rect a Rectangle2D to format and use as attribute value - */ - protected void addAttribute(String name, Rectangle2D rect) { - addAttribute(name, createString(rect)); - } - - /** * Adds the general Area attributes. * @param area Area to extract attributes from */ @@ -406,18 +266,6 @@ public class XMLRenderer extends PrintRenderer { } } - private String createString(Rectangle2D rect) { - return "" + (int) rect.getX() + " " + (int) rect.getY() + " " - + (int) rect.getWidth() + " " + (int) rect.getHeight(); - } - - private void handleDocumentExtensionAttachments() { - if (extensionAttachments != null && extensionAttachments.size() > 0) { - handleExtensionAttachments(extensionAttachments); - extensionAttachments.clear(); - } - } - /** {@inheritDoc} */ public void processOffDocumentItem(OffDocumentItem oDI) { if (oDI instanceof BookmarkData) { @@ -518,9 +366,7 @@ public class XMLRenderer extends PrintRenderer { startElement("areaTree"); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void stopRenderer() throws IOException { endPageSequence(); endElement("areaTree"); @@ -535,9 +381,7 @@ public class XMLRenderer extends PrintRenderer { log.debug("Written out Area Tree XML"); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderPage(PageViewport page) throws IOException, FOPException { atts.clear(); addAttribute("bounds", page.getViewArea()); @@ -561,7 +405,8 @@ public class XMLRenderer extends PrintRenderer { endElement("pageViewport"); } - private void handleExtensionAttachments(List attachments) { + /** {@inheritDoc} */ + protected void handleExtensionAttachments(List attachments) { if (attachments != null && attachments.size() > 0) { startElement("extension-attachments"); Iterator i = attachments.iterator(); @@ -582,10 +427,6 @@ public class XMLRenderer extends PrintRenderer { } } - private void handlePageExtensionAttachments(PageViewport page) { - handleExtensionAttachments(page.getExtensionAttachments()); - } - /** {@inheritDoc} */ public void startPageSequence(PageSequence pageSequence) { handleDocumentExtensionAttachments(); @@ -754,9 +595,17 @@ public class XMLRenderer extends PrintRenderer { endElement("flow"); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ + protected void renderReferenceArea(Block block) { + handleBlockTraits(block); + + List children = block.getChildAreas(); + if (children != null) { + renderBlocks(block, children); + } + } + + /** {@inheritDoc} */ protected void renderBlock(Block block) { atts.clear(); addAreaAttributes(block); diff --git a/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java b/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java index 2f513c59c..94e018c75 100644 --- a/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java +++ b/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java @@ -61,88 +61,152 @@ public class LineBreakStatus { } /** - * Check whether a line break may happen. - * The function returns the line breaking status of the point before the given character. - * The algorithm is the table driven algorithm described in the Unicode - * <a href="http://unicode.org/reports/tr14/#PairBasedImplementation">technical report #14</a>. - * The pair table is taken from @see LineBreakUtils + * Check whether a line break may happen according to the rules described in + * the <a href="http://unicode.org/reports/tr14/#Algorithm">Unicode Line Breaking Algorithm</a>. + * The function returns the line breaking status of the point <em>before</em> the given character. + * The algorithm is the table-driven algorithm, as described in + * <a href="http://unicode.org/reports/tr14/#PairBasedImplementation"> + * Unicode Technical Report #14</a>. + * The pair table is taken from {@link LineBreakUtils}. * - * TODO: Better handling for AI, SA, CB and other line break classes. + * TODO: Better handling for AI, SA, SG and XX line break classes. * - * @param c The character. + * @param c the character to check * @return the break action to be taken + * one of: {@link #DIRECT_BREAK}, + * {@link #INDIRECT_BREAK}, + * {@link #COMBINING_INDIRECT_BREAK}, + * {@link #COMBINING_PROHIBITED_BREAK}, + * {@link #PROHIBITED_BREAK}, + * {@link #EXPLICIT_BREAK} */ public byte nextChar(char c) { + byte currentClass = LineBreakUtils.getLineBreakProperty(c); - if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_AI - || leftClass == LineBreakUtils.LINE_BREAK_PROPERTY_XX) { - currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_AL; - } else if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_NL) { - currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_BK; + + /* Initial conversions */ + switch (currentClass) { + case LineBreakUtils.LINE_BREAK_PROPERTY_AI: + case LineBreakUtils.LINE_BREAK_PROPERTY_SG: + case LineBreakUtils.LINE_BREAK_PROPERTY_XX: + // LB 1: Resolve AI, ... SG and XX into other line breaking classes + // depending on criteria outside the scope of this algorithm. + // In the absence of such criteria, it is recommended that + // classes AI, ... SG and XX be resolved to AL + currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_AL; + break; + + case LineBreakUtils.LINE_BREAK_PROPERTY_SA: + // LB 1: Resolve ... SA ... into other line breaking classes + // depending on criteria outside the scope of this algorithm. + // In the absence of such criteria, it is recommended that + // ... SA be resolved to AL, except that characters of + // class SA that have General_Category Mn or Mc be resolved to CM + switch (Character.getType(c)) { + case Character.COMBINING_SPACING_MARK: //General_Category "Mc" + case Character.NON_SPACING_MARK: //General_Category "Mn" + currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_CM; + break; + default: + currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_AL; + } + + default: + //nop } - if (leftClass == -1) { - if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_LF) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_BK; - } else { + + /* Check 1: First character or initial character after a reset/mandatory break? */ + switch (leftClass) { + case -1: + //first character or initial character after a reset() leftClass = currentClass; if (leftClass == LineBreakUtils.LINE_BREAK_PROPERTY_CM) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_ID; + // LB 10: Treat any remaining combining marks as AL + leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_AL; } - } - // LB 2a - return PROHIBITED_BREAK; - } else if (!(leftClass != LineBreakUtils.LINE_BREAK_PROPERTY_BK - && (leftClass != LineBreakUtils.LINE_BREAK_PROPERTY_CR - || currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_LF) - )) { - reset(); - if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_LF) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_BK; - } - return EXPLICIT_BREAK; - } else if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_BK - || currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_LF) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_BK; - return PROHIBITED_BREAK; - } else if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_CR) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_CR; - return PROHIBITED_BREAK; - } else if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_SP) { - hadSpace = true; - return PROHIBITED_BREAK; - } else { - boolean savedHadSpace = hadSpace; - hadSpace = false; - switch (LineBreakUtils.getLineBreakPairProperty(leftClass, currentClass)) { - case LineBreakUtils.PROHIBITED_BREAK : + // LB 2: Never break at the start of text + return PROHIBITED_BREAK; + + case LineBreakUtils.LINE_BREAK_PROPERTY_BK: + case LineBreakUtils.LINE_BREAK_PROPERTY_LF: + case LineBreakUtils.LINE_BREAK_PROPERTY_NL: + //first character after mandatory break + // LB 4: Always break after hard line breaks + // LB 5: Treat ... LF and NL has hard line breaks + reset(); + leftClass = currentClass; + return EXPLICIT_BREAK; + + case LineBreakUtils.LINE_BREAK_PROPERTY_CR: + //first character after a carriage return: + // LB 5: Treat CR followed by LF, as well as CR ... as hard line breaks + // If current is LF, then fall through to Check 2 (see below), + // and the hard break will be signaled for the character after LF (see above) + if (currentClass != LineBreakUtils.LINE_BREAK_PROPERTY_LF) { + reset(); leftClass = currentClass; + return EXPLICIT_BREAK; + } + + default: + //nop + } + + /* Check 2: current is a mandatory break or space? */ + switch (currentClass) { + case LineBreakUtils.LINE_BREAK_PROPERTY_BK: + case LineBreakUtils.LINE_BREAK_PROPERTY_LF: + case LineBreakUtils.LINE_BREAK_PROPERTY_NL: + case LineBreakUtils.LINE_BREAK_PROPERTY_CR: + // LB 6: Do not break before a hard break + leftClass = currentClass; + return PROHIBITED_BREAK; + + case LineBreakUtils.LINE_BREAK_PROPERTY_SP: + // LB 7: Do not break before spaces ... + // Zero-width spaces are in the pair-table (see below) + hadSpace = true; + return PROHIBITED_BREAK; + + default: + //nop + } + + /* Normal treatment, if the first two checks did not return */ + boolean savedHadSpace = hadSpace; + hadSpace = false; + byte breakAction = LineBreakUtils.getLineBreakPairProperty(leftClass, currentClass); + switch (breakAction) { + case PROHIBITED_BREAK: + case DIRECT_BREAK: + leftClass = currentClass; + return breakAction; + + case INDIRECT_BREAK: + leftClass = currentClass; + if (savedHadSpace) { + return INDIRECT_BREAK; + } else { return PROHIBITED_BREAK; - case LineBreakUtils.DIRECT_BREAK : + } + + case COMBINING_INDIRECT_BREAK: + if (savedHadSpace) { leftClass = currentClass; - return DIRECT_BREAK; - case LineBreakUtils.INDIRECT_BREAK : + return COMBINING_INDIRECT_BREAK; + } else { + return PROHIBITED_BREAK; + } + + case COMBINING_PROHIBITED_BREAK: + if (savedHadSpace) { leftClass = currentClass; - if (savedHadSpace) { - return INDIRECT_BREAK; - } else { - return PROHIBITED_BREAK; - } - case LineBreakUtils.COMBINING_INDIRECT_BREAK : - if (savedHadSpace) { - leftClass = currentClass; - return COMBINING_INDIRECT_BREAK; - } else { - return PROHIBITED_BREAK; - } - case LineBreakUtils.COMBINING_PROHIBITED_BREAK : - if (savedHadSpace) { - leftClass = currentClass; - } - return COMBINING_PROHIBITED_BREAK; - default : - throw new RuntimeException("duh"); - } - + } + return COMBINING_PROHIBITED_BREAK; + + default: + assert false; + return breakAction; } } diff --git a/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java b/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java index 30883ffb2..5e84e1004 100644 --- a/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java +++ b/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java @@ -20,621 +20,669 @@ package org.apache.fop.text.linebreak; /* - * This is a generated file, DO NOT CHANGE! + * !!! THIS IS A GENERATED FILE !!! + * If updates to the source are needed, then: + * - apply the necessary modifications to + * 'src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java' + * - run 'ant codegen-unicode', which will generate a new LineBreakUtils.java + * in 'src/java/org/apache/fop/text/linebreak' + * - commit BOTH changed files */ -class LineBreakUtils { +public final class LineBreakUtils { + /** Break class constant */ public static final byte DIRECT_BREAK = 0; + /** Break class constant */ public static final byte INDIRECT_BREAK = 1; + /** Break class constant */ public static final byte COMBINING_INDIRECT_BREAK = 2; + /** Break class constant */ public static final byte COMBINING_PROHIBITED_BREAK = 3; + /** Break class constant */ public static final byte PROHIBITED_BREAK = 4; + /** Break class constant */ public static final byte EXPLICIT_BREAK = 5; private static final byte PAIR_TABLE[][] = { - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,1,1,0,0,1,0,0,0,4,4,0,4}, - {0,0,4,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,1,1,1,0,0,4,2,0,4,1,1,1,1,1,1,4,1,1,1,0,0,1,1,1,1,1,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,4,1,0,1,1,1,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,1,0,0,0,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,1,1,1,0,0,4,2,0,4,1,1,1,1,1,1,4,1,1,1,0,0,1,1,1,1,1,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,1,1,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,1,0,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,1,0,0,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,1,0,0,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,1,1,1,0,1,4,1,0,1,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,1,0,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,1,1,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,1,1,1,1,1,0,0,0,4,4,0,4}, - {0,4,4,4,4,0,0,4,3,0,4,4,4,4,4,4,4,4,4,4,4,0,0,4,4,4,4,4,4,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,1,1,0,0,1,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,1,1,1,1,0,4,1,1,1,0,0,1,1,1,0,0,1,0,0,0,4,4,0,4}, - {0,1,1,1,1,0,0,4,2,0,4,1,1,1,1,1,1,4,1,1,1,0,0,1,1,4,1,1,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,1,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,1,1,1,0,0,4,2,0,4,1,1,1,1,1,1,4,1,1,1,0,0,1,1,1,1,1,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4}}; + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 4, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 1, 1, 1, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 4, 1, 0, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 1, 1, 1, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 0, 1, 4, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 4, 4, 4, 4, 0, 0, 4, 3, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 0, 4, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 1, 1, 1, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 0, 0, 1, 1, 4, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 1, 1, 1, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}}; private static byte lineBreakProperties[][] = new byte[512][]; private static void init_0() { - lineBreakProperties[0] = new byte[] { 9,9,9,9,9,9,9,9,9,4,22,6,6,10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,32,11,29,2,28,27,2,29,26,8,2,28,18,15,18,33,25,25,25,25,25,25,25,25,25,25,18,18,2,2,2,11,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,28,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,4,8,2,9}; - lineBreakProperties[1] = new byte[] { 9,9,9,9,9,23,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,12,1,27,28,28,28,2,1,1,2,1,29,2,4,2,2,27,28,1,1,5,2,1,1,1,1,1,29,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2}; - lineBreakProperties[2] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[5] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,5,1,1,1,5,1,2,2,1,2,2,2,2,2,2,2,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[6] = new byte[] { 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,12,9,9,9,9,9,9,9,9,9,9,9,9,12,12,12,12,12,12,12,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,2,2,0,0,0,0,2,2,2,2,18,0}; - lineBreakProperties[7] = new byte[] { 0,0,0,0,2,2,2,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[9] = new byte[] { 2,2,2,9,9,9,9,0,9,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[10] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[11] = new byte[] { 2,2,2,2,2,2,2,2,0,18,4,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,4,9,2,9,9,2,9,9,11,9,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[12] = new byte[] { 2,2,2,2,0,0,0,0,0,0,0,27,11,18,2,2,9,9,9,9,9,9,0,0,0,0,0,11,0,0,11,11,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,25,25,25,25,25,25,25,25,25,25,11,25,25,2,2,2,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[13] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,11,2,9,9,9,9,9,9,9,2,9,9,9,9,9,9,9,2,2,9,9,2,9,9,9,9,2,2,25,25,25,25,25,25,25,25,25,25,2,2,2,2,2,2}; - lineBreakProperties[14] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[15] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,2,2,2,2,18,11,2,0,0,0,0,0}; - lineBreakProperties[16] = new byte[] { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[18] = new byte[] { 0,9,9,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,9,2,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,2,9,9,9,9,0,0,0,2,2,2,2,2,2,2,2,2,2,9,9,4,4,25,25,25,25,25,25,25,25,25,25,2,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2}; - lineBreakProperties[19] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,2,2,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,0,0,0,2,2,2,2,0,0,9,2,9,9,9,9,9,9,9,0,0,9,9,0,0,9,9,9,2,0,0,0,0,0,0,0,0,9,0,0,0,0,2,2,0,2,2,2,9,9,0,0,25,25,25,25,25,25,25,25,25,25,2,2,28,28,2,2,2,2,2,2,2,0,0,0,0,0}; - lineBreakProperties[20] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,0,0,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,0,2,2,0,0,9,0,9,9,9,9,9,0,0,0,0,9,9,0,0,9,9,9,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,0,2,0,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,9,9,2,2,2,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[21] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,0,0,9,2,9,9,9,9,9,9,9,9,0,9,9,9,0,9,9,9,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,9,9,0,0,25,25,25,25,25,25,25,25,25,25,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[22] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,2,2,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,0,0,9,2,9,9,9,9,9,9,0,0,0,9,9,0,0,9,9,9,0,0,0,0,0,0,0,0,9,9,0,0,0,0,2,2,0,2,2,2,0,0,0,0,25,25,25,25,25,25,25,25,25,25,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[23] = new byte[] { 0,0,9,2,0,2,2,2,2,2,2,0,0,0,2,2,2,0,2,2,2,2,0,0,0,2,2,0,2,0,2,2,0,0,0,2,2,0,0,0,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,9,9,9,9,9,0,0,0,9,9,9,0,9,9,9,9,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,2,2,2,2,2,2,2,2,2,28,2,0,0,0,0,0}; - lineBreakProperties[24] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,0,0,0,9,9,9,9,9,9,9,0,9,9,9,0,9,9,9,9,0,0,0,0,0,0,0,9,9,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[25] = new byte[] { 0,0,9,9,0,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,0,9,2,9,9,9,9,9,9,9,0,9,9,9,0,9,9,9,9,0,0,0,0,0,0,0,9,9,0,0,0,0,0,0,0,2,0,2,2,9,9,0,0,25,25,25,25,25,25,25,25,25,25,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[26] = new byte[] { 0,0,9,9,0,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,9,9,9,9,9,9,0,0,9,9,9,0,9,9,9,9,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,2,2,0,0,0,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[27] = new byte[] { 0,0,9,9,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,0,2,0,0,2,2,2,2,2,2,2,0,0,0,9,0,0,0,0,9,9,9,9,9,9,0,9,0,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,2,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[28] = new byte[] { 0,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,0,0,0,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,2,25,25,25,25,25,25,25,25,25,25,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[29] = new byte[] { 0,30,30,0,30,0,0,30,30,0,30,0,0,30,0,0,0,0,0,0,30,30,30,30,0,30,30,30,30,30,30,30,0,30,30,30,0,30,0,30,0,0,30,30,0,30,30,30,30,30,30,30,30,30,30,30,30,30,0,30,30,30,0,0,30,30,30,30,30,0,30,0,30,30,30,30,30,30,0,0,25,25,25,25,25,25,25,25,25,25,0,0,30,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[30] = new byte[] { 2,5,5,5,5,2,5,5,12,5,5,4,12,11,11,11,11,11,12,2,11,2,2,2,9,9,2,2,2,2,2,2,25,25,25,25,25,25,25,25,25,25,2,2,2,2,2,2,2,2,2,2,4,9,2,9,2,9,26,8,26,8,9,9,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,4}; - lineBreakProperties[31] = new byte[] { 9,9,9,9,9,4,9,9,2,2,2,2,0,0,0,0,9,9,9,9,9,9,9,9,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,4,4,2,2,2,2,2,2,9,2,2,2,2,2,2,0,0,2,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[32] = new byte[] { 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,30,30,30,30,30,0,30,30,0,30,30,30,30,30,30,30,0,0,0,30,30,30,30,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,4,4,2,2,2,2,30,30,30,30,30,30,30,30,30,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[33] = new byte[] { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0}; - lineBreakProperties[34] = new byte[] { 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,0,0,0,0,0,19,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21}; - lineBreakProperties[35] = new byte[] { 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,0,0,0,0,0,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0}; - lineBreakProperties[36] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[37] = new byte[] { 2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[38] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,9,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0}; - lineBreakProperties[39] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[40] = new byte[] { 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[44] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[45] = new byte[] { 4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[46] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,9,9,9,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,4,4,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,0,9,9,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[47] = new byte[] { 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,4,4,24,30,4,2,4,28,30,30,0,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0}; - lineBreakProperties[48] = new byte[] { 2,2,4,4,4,4,5,2,4,4,2,9,9,9,12,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0}; - lineBreakProperties[49] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[50] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,2,0,0,0,11,11,25,25,25,25,25,25,25,25,25,25,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,0,30,30,30,30,30,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[51] = new byte[] { 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,0,0,0,0,0,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,30,30,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[52] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,0,0,4,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[54] = new byte[] { 9,9,9,9,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,2,2,2,2,2,2,2,0,0,0,0,25,25,25,25,25,25,25,25,25,25,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,2,2,2,2,2,2,2,2,2,0,0,0}; - lineBreakProperties[59] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9}; - lineBreakProperties[61] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0}; - lineBreakProperties[62] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,0,2,0,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0}; - lineBreakProperties[63] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,0,2,2,2,2,2,2,2,2,2,0}; - lineBreakProperties[64] = new byte[] { 4,4,4,4,4,4,4,12,4,4,4,36,9,9,9,9,4,12,4,4,3,1,1,2,29,29,26,29,29,29,26,29,1,1,2,2,17,17,17,4,6,6,9,9,9,9,9,12,27,27,27,27,27,27,27,27,2,29,29,1,24,24,2,2,2,2,2,2,18,26,8,24,24,24,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,4,2,4,4,4,34,2,2,2,0,0,0,0,0,0,9,9,9,9,9,9,2,2,0,0,1,2,2,2,2,2,2,2,2,26,8,1}; - lineBreakProperties[65] = new byte[] { 2,1,1,1,1,2,2,2,2,2,2,2,2,26,8,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,28,28,28,28,28,28,28,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[66] = new byte[] { 2,2,2,27,2,1,2,2,2,27,2,2,2,2,2,2,2,2,2,1,2,2,28,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,1,1,2,2,2,2,2,1,2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2}; - lineBreakProperties[67] = new byte[] { 2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[68] = new byte[] { 1,2,1,1,2,2,2,1,1,2,2,1,2,2,2,1,2,1,28,28,2,1,2,2,2,2,1,2,2,1,1,1,1,2,2,1,2,1,2,1,1,1,1,1,1,2,1,2,2,2,2,2,1,1,1,1,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,1,2,2,2,1,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,2,1,1,1,1,2,2,1,1,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[69] = new byte[] { 2,2,1,1,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[70] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[71] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[72] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; - lineBreakProperties[73] = new byte[] { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2}; - lineBreakProperties[74] = new byte[] { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[75] = new byte[] { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,2,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1,1,1,2,2,1,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[76] = new byte[] { 2,2,2,2,2,1,1,2,2,1,2,2,2,2,1,1,2,2,2,2,1,1,1,1,2,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,1,1,1,2,1,1,1,1,2,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - }; + lineBreakProperties[0] = new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 22, 6, 6, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 11, 29, 2, 28, 27, 2, 29, 26, 8, 2, 28, 18, 15, 18, 33, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 28, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 4, 8, 2, 9}; + lineBreakProperties[1] = new byte[] { 9, 9, 9, 9, 9, 23, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 26, 27, 28, 28, 28, 2, 1, 1, 2, 1, 29, 2, 4, 2, 2, 27, 28, 1, 1, 5, 2, 1, 1, 1, 1, 1, 29, 1, 1, 1, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[2] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[5] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 1, 1, 1, 5, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 1, 2, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[6] = new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 12, 12, 12, 12, 12, 12, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 18, 0}; + lineBreakProperties[7] = new byte[] { 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[9] = new byte[] { 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[10] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[11] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 0, 18, 4, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 9, 2, 9, 9, 2, 9, 9, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[12] = new byte[] { 2, 2, 2, 2, 0, 0, 2, 2, 2, 27, 27, 27, 18, 18, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 0, 0, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 27, 25, 25, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[13] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 11, 2, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 2, 9, 9, 9, 9, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[14] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[15] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 18, 11, 2, 0, 0, 0, 0, 0}; + lineBreakProperties[16] = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[18] = new byte[] { 0, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 2, 9, 9, 9, 9, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 4, 4, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2}; + lineBreakProperties[19] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 28, 28, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0}; + lineBreakProperties[20] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 9, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 0, 0, 9, 9, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 9, 9, 2, 2, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[21] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[22] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[23] = new byte[] { 0, 0, 9, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0, 2, 0, 2, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 28, 2, 0, 0, 0, 0, 0}; + lineBreakProperties[24] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[25] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[26] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 0, 0, 0, 27, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[27] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[28] = new byte[] { 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[29] = new byte[] { 0, 30, 30, 0, 30, 0, 0, 30, 30, 0, 30, 0, 0, 30, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 0, 30, 0, 30, 0, 0, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 0, 0, 30, 30, 30, 30, 30, 0, 30, 0, 30, 30, 30, 30, 30, 30, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[30] = new byte[] { 2, 5, 5, 5, 5, 2, 5, 5, 12, 5, 5, 4, 12, 11, 11, 11, 11, 11, 12, 2, 11, 2, 2, 2, 9, 9, 2, 2, 2, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 9, 2, 9, 2, 9, 26, 8, 26, 8, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4}; + lineBreakProperties[31] = new byte[] { 9, 9, 9, 9, 9, 4, 9, 9, 2, 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 4, 4, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 0, 2, 2, 5, 5, 4, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[32] = new byte[] { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 4, 4, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}; + lineBreakProperties[33] = new byte[] { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 30, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; + lineBreakProperties[34] = new byte[] { 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 19, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}; + lineBreakProperties[35] = new byte[] { 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[36] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[37] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[38] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 9, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; + lineBreakProperties[39] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[40] = new byte[] { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[44] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[45] = new byte[] { 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[46] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[47] = new byte[] { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 4, 4, 24, 30, 4, 2, 4, 28, 30, 30, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[48] = new byte[] { 2, 2, 11, 11, 4, 4, 5, 2, 11, 11, 2, 9, 9, 9, 12, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[49] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[50] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 2, 0, 0, 0, 11, 11, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[51] = new byte[] { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 30, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[52] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[54] = new byte[] { 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; + lineBreakProperties[55] = new byte[] { 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[56] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 4, 4, 4, 4, 4, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4}; + lineBreakProperties[59] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9}; + lineBreakProperties[62] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0}; + lineBreakProperties[63] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 5, 2, 0}; + lineBreakProperties[64] = new byte[] { 4, 4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 36, 9, 9, 9, 9, 4, 12, 4, 4, 3, 1, 1, 2, 29, 29, 26, 29, 29, 29, 26, 29, 1, 1, 2, 2, 17, 17, 17, 4, 6, 6, 9, 9, 9, 9, 9, 12, 27, 27, 27, 27, 27, 27, 27, 27, 2, 29, 29, 1, 24, 24, 2, 2, 2, 2, 2, 2, 18, 26, 8, 24, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 4, 4, 4, 4, 2, 4, 4, 4, 34, 2, 2, 2, 2, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 2, 2, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 1}; + lineBreakProperties[65] = new byte[] { 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 28, 28, 28, 28, 28, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[66] = new byte[] { 2, 2, 2, 27, 2, 1, 2, 2, 2, 27, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[67] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[68] = new byte[] { 1, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 1, 2, 1, 28, 28, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[69] = new byte[] { 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[70] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[71] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[72] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + lineBreakProperties[73] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}; + lineBreakProperties[74] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[75] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + } private static void init_1() { - lineBreakProperties[77] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[78] = new byte[] { 0,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,0,0,2,0,2,2,2,29,29,29,29,0,0,2,11,11,2,2,2,2,26,8,26,8,26,8,26,8,26,8,26,8,26,8,1,1,1,1,1,1,1,1,1,1}; - lineBreakProperties[79] = new byte[] { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,26,8,2,2,2,2,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,26,8,26,8,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[83] = new byte[] { 2,2,2,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,26,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,2,2}; - lineBreakProperties[86] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[88] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0}; - lineBreakProperties[89] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,2,4,4}; - lineBreakProperties[90] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[91] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[92] = new byte[] { 29,29,29,29,29,29,29,29,29,29,29,29,29,29,4,4,4,4,4,4,4,4,2,4,0,0,0,0,29,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[93] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[94] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[95] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0}; - lineBreakProperties[96] = new byte[] { 16,8,8,16,16,24,16,16,26,8,26,8,26,8,26,8,26,8,16,16,26,8,26,8,26,8,26,8,24,26,8,8,16,16,16,16,16,16,16,16,16,16,9,9,9,9,9,9,16,16,16,16,16,16,16,16,16,16,16,24,24,16,16,16,0,24,16,24,16,24,16,24,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[97] = new byte[] { 16,16,16,24,16,24,16,24,16,16,16,16,16,16,24,16,16,16,16,16,16,24,24,0,0,9,9,24,24,24,24,16,24,24,16,24,16,24,16,24,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,24,16,24,16,24,16,16,16,16,16,16,24,16,16,16,16,16,16,24,24,16,16,16,16,24,24,24,24,16}; - lineBreakProperties[98] = new byte[] { 0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[99] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24}; - lineBreakProperties[100] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[101] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0}; - lineBreakProperties[155] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[319] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[320] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[329] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[334] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[336] = new byte[] { 2,2,9,2,2,2,9,2,2,2,2,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,5,11,11,0,0,0,0,0,0,0,0}; - lineBreakProperties[344] = new byte[] { 13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[345] = new byte[] { 14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14}; - lineBreakProperties[346] = new byte[] { 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[347] = new byte[] { 14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14}; - lineBreakProperties[348] = new byte[] { 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[349] = new byte[] { 14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[350] = new byte[] { 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[431] = new byte[] { 14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[432] = new byte[] { 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31}; - lineBreakProperties[448] = new byte[] { 35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35}; - lineBreakProperties[500] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[501] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[502] = new byte[] { 2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,2,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,2,0,2,2,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[503] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[506] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[507] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,27,2,0,0}; - lineBreakProperties[508] = new byte[] { 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,18,8,8,18,18,11,11,26,8,17,0,0,0,0,0,0,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,16,16,26,8,16,16,16,16,16,16,16,8,16,8,0,24,24,11,11,16,26,8,26,8,26,8,16,16,16,16,16,16,16,16,0,16,28,27,16,0,0,0,0,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[509] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,34}; - lineBreakProperties[510] = new byte[] { 0,11,16,16,28,27,16,16,26,8,16,16,8,16,8,16,16,16,16,16,16,16,16,16,16,16,24,24,16,16,16,11,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,26,16,8,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,26,16,8,16,26,8,8,26,8,8,24,2,24,24,24,24,24,24,24,24,24,24,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[511] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,24,24,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,0,0,0,27,28,16,16,16,28,28,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,9,9,9,7,1,0,0}; - }; + lineBreakProperties[76] = new byte[] { 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[77] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[78] = new byte[] { 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 0, 2, 2, 2, 29, 29, 29, 29, 0, 0, 2, 11, 11, 2, 2, 2, 2, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + lineBreakProperties[79] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 26, 8, 2, 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[83] = new byte[] { 2, 2, 2, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 26, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 2, 2}; + lineBreakProperties[86] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[88] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0}; + lineBreakProperties[89] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 4, 4, 4, 2, 11, 4}; + lineBreakProperties[90] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[91] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; + lineBreakProperties[92] = new byte[] { 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 26, 4, 2, 2, 29, 29, 2, 2, 29, 29, 26, 8, 26, 8, 26, 8, 26, 8, 4, 4, 4, 4, 11, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[93] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[94] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[95] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0}; + lineBreakProperties[96] = new byte[] { 16, 8, 8, 16, 16, 24, 16, 16, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 16, 16, 26, 8, 26, 8, 26, 8, 26, 8, 24, 26, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 9, 9, 9, 9, 9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 16, 16, 16, 0, 24, 16, 24, 16, 24, 16, 24, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[97] = new byte[] { 16, 16, 16, 24, 16, 24, 16, 24, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 24, 24, 0, 0, 9, 9, 24, 24, 24, 24, 16, 24, 24, 16, 24, 16, 24, 16, 24, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 16, 24, 16, 24, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 24, 24, 16, 16, 16, 16, 24, 24, 24, 24, 16}; + lineBreakProperties[98] = new byte[] { 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[99] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24}; + lineBreakProperties[100] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[101] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0}; + lineBreakProperties[155] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[319] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[320] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[329] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[332] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 11, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 2, 2}; + lineBreakProperties[333] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[335] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2}; + lineBreakProperties[336] = new byte[] { 2, 2, 9, 2, 2, 2, 9, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[337] = new byte[] { 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[338] = new byte[] { 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[340] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 2, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[344] = new byte[] { 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[345] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14}; + lineBreakProperties[346] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[347] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[348] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[349] = new byte[] { 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[350] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[431] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[432] = new byte[] { 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}; + lineBreakProperties[448] = new byte[] { 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35}; + lineBreakProperties[500] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[501] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[502] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[503] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[506] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[507] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 2, 0, 0}; + lineBreakProperties[508] = new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 8, 8, 18, 18, 11, 11, 26, 8, 17, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 16, 16, 26, 8, 16, 16, 16, 16, 16, 16, 16, 8, 16, 8, 0, 24, 24, 11, 11, 16, 26, 8, 26, 8, 26, 8, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 28, 27, 16, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[509] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 34}; + lineBreakProperties[510] = new byte[] { 0, 11, 16, 16, 28, 27, 16, 16, 26, 8, 16, 16, 8, 16, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 26, 16, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 26, 16, 8, 16, 26, 8, 8, 26, 8, 8, 24, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[511] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, 27, 28, 16, 16, 16, 28, 28, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 7, 1, 0, 0}; + } static { init_0(); init_1(); - lineBreakProperties[3]=lineBreakProperties[2]; - lineBreakProperties[4]=lineBreakProperties[2]; - lineBreakProperties[8]=lineBreakProperties[2]; - lineBreakProperties[17]=lineBreakProperties[16]; - lineBreakProperties[41]=lineBreakProperties[2]; - lineBreakProperties[42]=lineBreakProperties[2]; - lineBreakProperties[43]=lineBreakProperties[2]; - lineBreakProperties[53]=lineBreakProperties[16]; - lineBreakProperties[55]=lineBreakProperties[16]; - lineBreakProperties[56]=lineBreakProperties[16]; - lineBreakProperties[57]=lineBreakProperties[16]; - lineBreakProperties[58]=lineBreakProperties[2]; - lineBreakProperties[60]=lineBreakProperties[2]; - lineBreakProperties[80]=lineBreakProperties[2]; - lineBreakProperties[81]=lineBreakProperties[2]; - lineBreakProperties[82]=lineBreakProperties[2]; - lineBreakProperties[84]=lineBreakProperties[2]; - lineBreakProperties[85]=lineBreakProperties[2]; - lineBreakProperties[87]=lineBreakProperties[16]; - lineBreakProperties[102]=lineBreakProperties[94]; - lineBreakProperties[103]=lineBreakProperties[94]; - lineBreakProperties[104]=lineBreakProperties[94]; - lineBreakProperties[105]=lineBreakProperties[94]; - lineBreakProperties[106]=lineBreakProperties[94]; - lineBreakProperties[107]=lineBreakProperties[94]; - lineBreakProperties[108]=lineBreakProperties[94]; - lineBreakProperties[109]=lineBreakProperties[94]; - lineBreakProperties[110]=lineBreakProperties[94]; - lineBreakProperties[111]=lineBreakProperties[94]; - lineBreakProperties[112]=lineBreakProperties[94]; - lineBreakProperties[113]=lineBreakProperties[94]; - lineBreakProperties[114]=lineBreakProperties[94]; - lineBreakProperties[115]=lineBreakProperties[94]; - lineBreakProperties[116]=lineBreakProperties[94]; - lineBreakProperties[117]=lineBreakProperties[94]; - lineBreakProperties[118]=lineBreakProperties[94]; - lineBreakProperties[119]=lineBreakProperties[94]; - lineBreakProperties[120]=lineBreakProperties[94]; - lineBreakProperties[121]=lineBreakProperties[94]; - lineBreakProperties[122]=lineBreakProperties[94]; - lineBreakProperties[123]=lineBreakProperties[94]; - lineBreakProperties[124]=lineBreakProperties[94]; - lineBreakProperties[125]=lineBreakProperties[94]; - lineBreakProperties[126]=lineBreakProperties[94]; - lineBreakProperties[127]=lineBreakProperties[94]; - lineBreakProperties[128]=lineBreakProperties[94]; - lineBreakProperties[129]=lineBreakProperties[94]; - lineBreakProperties[130]=lineBreakProperties[94]; - lineBreakProperties[131]=lineBreakProperties[94]; - lineBreakProperties[132]=lineBreakProperties[94]; - lineBreakProperties[133]=lineBreakProperties[94]; - lineBreakProperties[134]=lineBreakProperties[94]; - lineBreakProperties[135]=lineBreakProperties[94]; - lineBreakProperties[136]=lineBreakProperties[94]; - lineBreakProperties[137]=lineBreakProperties[94]; - lineBreakProperties[138]=lineBreakProperties[94]; - lineBreakProperties[139]=lineBreakProperties[94]; - lineBreakProperties[140]=lineBreakProperties[94]; - lineBreakProperties[141]=lineBreakProperties[94]; - lineBreakProperties[142]=lineBreakProperties[94]; - lineBreakProperties[143]=lineBreakProperties[94]; - lineBreakProperties[144]=lineBreakProperties[94]; - lineBreakProperties[145]=lineBreakProperties[94]; - lineBreakProperties[146]=lineBreakProperties[94]; - lineBreakProperties[147]=lineBreakProperties[94]; - lineBreakProperties[148]=lineBreakProperties[94]; - lineBreakProperties[149]=lineBreakProperties[94]; - lineBreakProperties[150]=lineBreakProperties[94]; - lineBreakProperties[151]=lineBreakProperties[94]; - lineBreakProperties[152]=lineBreakProperties[94]; - lineBreakProperties[153]=lineBreakProperties[94]; - lineBreakProperties[154]=lineBreakProperties[94]; - lineBreakProperties[156]=lineBreakProperties[94]; - lineBreakProperties[157]=lineBreakProperties[94]; - lineBreakProperties[158]=lineBreakProperties[94]; - lineBreakProperties[159]=lineBreakProperties[94]; - lineBreakProperties[160]=lineBreakProperties[94]; - lineBreakProperties[161]=lineBreakProperties[94]; - lineBreakProperties[162]=lineBreakProperties[94]; - lineBreakProperties[163]=lineBreakProperties[94]; - lineBreakProperties[164]=lineBreakProperties[94]; - lineBreakProperties[165]=lineBreakProperties[94]; - lineBreakProperties[166]=lineBreakProperties[94]; - lineBreakProperties[167]=lineBreakProperties[94]; - lineBreakProperties[168]=lineBreakProperties[94]; - lineBreakProperties[169]=lineBreakProperties[94]; - lineBreakProperties[170]=lineBreakProperties[94]; - lineBreakProperties[171]=lineBreakProperties[94]; - lineBreakProperties[172]=lineBreakProperties[94]; - lineBreakProperties[173]=lineBreakProperties[94]; - lineBreakProperties[174]=lineBreakProperties[94]; - lineBreakProperties[175]=lineBreakProperties[94]; - lineBreakProperties[176]=lineBreakProperties[94]; - lineBreakProperties[177]=lineBreakProperties[94]; - lineBreakProperties[178]=lineBreakProperties[94]; - lineBreakProperties[179]=lineBreakProperties[94]; - lineBreakProperties[180]=lineBreakProperties[94]; - lineBreakProperties[181]=lineBreakProperties[94]; - lineBreakProperties[182]=lineBreakProperties[94]; - lineBreakProperties[183]=lineBreakProperties[94]; - lineBreakProperties[184]=lineBreakProperties[94]; - lineBreakProperties[185]=lineBreakProperties[94]; - lineBreakProperties[186]=lineBreakProperties[94]; - lineBreakProperties[187]=lineBreakProperties[94]; - lineBreakProperties[188]=lineBreakProperties[94]; - lineBreakProperties[189]=lineBreakProperties[94]; - lineBreakProperties[190]=lineBreakProperties[94]; - lineBreakProperties[191]=lineBreakProperties[94]; - lineBreakProperties[192]=lineBreakProperties[94]; - lineBreakProperties[193]=lineBreakProperties[94]; - lineBreakProperties[194]=lineBreakProperties[94]; - lineBreakProperties[195]=lineBreakProperties[94]; - lineBreakProperties[196]=lineBreakProperties[94]; - lineBreakProperties[197]=lineBreakProperties[94]; - lineBreakProperties[198]=lineBreakProperties[94]; - lineBreakProperties[199]=lineBreakProperties[94]; - lineBreakProperties[200]=lineBreakProperties[94]; - lineBreakProperties[201]=lineBreakProperties[94]; - lineBreakProperties[202]=lineBreakProperties[94]; - lineBreakProperties[203]=lineBreakProperties[94]; - lineBreakProperties[204]=lineBreakProperties[94]; - lineBreakProperties[205]=lineBreakProperties[94]; - lineBreakProperties[206]=lineBreakProperties[94]; - lineBreakProperties[207]=lineBreakProperties[94]; - lineBreakProperties[208]=lineBreakProperties[94]; - lineBreakProperties[209]=lineBreakProperties[94]; - lineBreakProperties[210]=lineBreakProperties[94]; - lineBreakProperties[211]=lineBreakProperties[94]; - lineBreakProperties[212]=lineBreakProperties[94]; - lineBreakProperties[213]=lineBreakProperties[94]; - lineBreakProperties[214]=lineBreakProperties[94]; - lineBreakProperties[215]=lineBreakProperties[94]; - lineBreakProperties[216]=lineBreakProperties[94]; - lineBreakProperties[217]=lineBreakProperties[94]; - lineBreakProperties[218]=lineBreakProperties[94]; - lineBreakProperties[219]=lineBreakProperties[94]; - lineBreakProperties[220]=lineBreakProperties[94]; - lineBreakProperties[221]=lineBreakProperties[94]; - lineBreakProperties[222]=lineBreakProperties[94]; - lineBreakProperties[223]=lineBreakProperties[94]; - lineBreakProperties[224]=lineBreakProperties[94]; - lineBreakProperties[225]=lineBreakProperties[94]; - lineBreakProperties[226]=lineBreakProperties[94]; - lineBreakProperties[227]=lineBreakProperties[94]; - lineBreakProperties[228]=lineBreakProperties[94]; - lineBreakProperties[229]=lineBreakProperties[94]; - lineBreakProperties[230]=lineBreakProperties[94]; - lineBreakProperties[231]=lineBreakProperties[94]; - lineBreakProperties[232]=lineBreakProperties[94]; - lineBreakProperties[233]=lineBreakProperties[94]; - lineBreakProperties[234]=lineBreakProperties[94]; - lineBreakProperties[235]=lineBreakProperties[94]; - lineBreakProperties[236]=lineBreakProperties[94]; - lineBreakProperties[237]=lineBreakProperties[94]; - lineBreakProperties[238]=lineBreakProperties[94]; - lineBreakProperties[239]=lineBreakProperties[94]; - lineBreakProperties[240]=lineBreakProperties[94]; - lineBreakProperties[241]=lineBreakProperties[94]; - lineBreakProperties[242]=lineBreakProperties[94]; - lineBreakProperties[243]=lineBreakProperties[94]; - lineBreakProperties[244]=lineBreakProperties[94]; - lineBreakProperties[245]=lineBreakProperties[94]; - lineBreakProperties[246]=lineBreakProperties[94]; - lineBreakProperties[247]=lineBreakProperties[94]; - lineBreakProperties[248]=lineBreakProperties[94]; - lineBreakProperties[249]=lineBreakProperties[94]; - lineBreakProperties[250]=lineBreakProperties[94]; - lineBreakProperties[251]=lineBreakProperties[94]; - lineBreakProperties[252]=lineBreakProperties[94]; - lineBreakProperties[253]=lineBreakProperties[94]; - lineBreakProperties[254]=lineBreakProperties[94]; - lineBreakProperties[255]=lineBreakProperties[94]; - lineBreakProperties[256]=lineBreakProperties[94]; - lineBreakProperties[257]=lineBreakProperties[94]; - lineBreakProperties[258]=lineBreakProperties[94]; - lineBreakProperties[259]=lineBreakProperties[94]; - lineBreakProperties[260]=lineBreakProperties[94]; - lineBreakProperties[261]=lineBreakProperties[94]; - lineBreakProperties[262]=lineBreakProperties[94]; - lineBreakProperties[263]=lineBreakProperties[94]; - lineBreakProperties[264]=lineBreakProperties[94]; - lineBreakProperties[265]=lineBreakProperties[94]; - lineBreakProperties[266]=lineBreakProperties[94]; - lineBreakProperties[267]=lineBreakProperties[94]; - lineBreakProperties[268]=lineBreakProperties[94]; - lineBreakProperties[269]=lineBreakProperties[94]; - lineBreakProperties[270]=lineBreakProperties[94]; - lineBreakProperties[271]=lineBreakProperties[94]; - lineBreakProperties[272]=lineBreakProperties[94]; - lineBreakProperties[273]=lineBreakProperties[94]; - lineBreakProperties[274]=lineBreakProperties[94]; - lineBreakProperties[275]=lineBreakProperties[94]; - lineBreakProperties[276]=lineBreakProperties[94]; - lineBreakProperties[277]=lineBreakProperties[94]; - lineBreakProperties[278]=lineBreakProperties[94]; - lineBreakProperties[279]=lineBreakProperties[94]; - lineBreakProperties[280]=lineBreakProperties[94]; - lineBreakProperties[281]=lineBreakProperties[94]; - lineBreakProperties[282]=lineBreakProperties[94]; - lineBreakProperties[283]=lineBreakProperties[94]; - lineBreakProperties[284]=lineBreakProperties[94]; - lineBreakProperties[285]=lineBreakProperties[94]; - lineBreakProperties[286]=lineBreakProperties[94]; - lineBreakProperties[287]=lineBreakProperties[94]; - lineBreakProperties[288]=lineBreakProperties[94]; - lineBreakProperties[289]=lineBreakProperties[94]; - lineBreakProperties[290]=lineBreakProperties[94]; - lineBreakProperties[291]=lineBreakProperties[94]; - lineBreakProperties[292]=lineBreakProperties[94]; - lineBreakProperties[293]=lineBreakProperties[94]; - lineBreakProperties[294]=lineBreakProperties[94]; - lineBreakProperties[295]=lineBreakProperties[94]; - lineBreakProperties[296]=lineBreakProperties[94]; - lineBreakProperties[297]=lineBreakProperties[94]; - lineBreakProperties[298]=lineBreakProperties[94]; - lineBreakProperties[299]=lineBreakProperties[94]; - lineBreakProperties[300]=lineBreakProperties[94]; - lineBreakProperties[301]=lineBreakProperties[94]; - lineBreakProperties[302]=lineBreakProperties[94]; - lineBreakProperties[303]=lineBreakProperties[94]; - lineBreakProperties[304]=lineBreakProperties[94]; - lineBreakProperties[305]=lineBreakProperties[94]; - lineBreakProperties[306]=lineBreakProperties[94]; - lineBreakProperties[307]=lineBreakProperties[94]; - lineBreakProperties[308]=lineBreakProperties[94]; - lineBreakProperties[309]=lineBreakProperties[94]; - lineBreakProperties[310]=lineBreakProperties[94]; - lineBreakProperties[311]=lineBreakProperties[94]; - lineBreakProperties[312]=lineBreakProperties[94]; - lineBreakProperties[313]=lineBreakProperties[94]; - lineBreakProperties[314]=lineBreakProperties[94]; - lineBreakProperties[315]=lineBreakProperties[94]; - lineBreakProperties[316]=lineBreakProperties[94]; - lineBreakProperties[317]=lineBreakProperties[94]; - lineBreakProperties[318]=lineBreakProperties[94]; - lineBreakProperties[321]=lineBreakProperties[94]; - lineBreakProperties[322]=lineBreakProperties[94]; - lineBreakProperties[323]=lineBreakProperties[94]; - lineBreakProperties[324]=lineBreakProperties[94]; - lineBreakProperties[325]=lineBreakProperties[94]; - lineBreakProperties[326]=lineBreakProperties[94]; - lineBreakProperties[327]=lineBreakProperties[94]; - lineBreakProperties[328]=lineBreakProperties[94]; - lineBreakProperties[330]=lineBreakProperties[16]; - lineBreakProperties[331]=lineBreakProperties[16]; - lineBreakProperties[332]=lineBreakProperties[16]; - lineBreakProperties[333]=lineBreakProperties[16]; - lineBreakProperties[335]=lineBreakProperties[16]; - lineBreakProperties[337]=lineBreakProperties[16]; - lineBreakProperties[338]=lineBreakProperties[16]; - lineBreakProperties[339]=lineBreakProperties[16]; - lineBreakProperties[340]=lineBreakProperties[16]; - lineBreakProperties[341]=lineBreakProperties[16]; - lineBreakProperties[342]=lineBreakProperties[16]; - lineBreakProperties[343]=lineBreakProperties[16]; - lineBreakProperties[351]=lineBreakProperties[344]; - lineBreakProperties[352]=lineBreakProperties[345]; - lineBreakProperties[353]=lineBreakProperties[346]; - lineBreakProperties[354]=lineBreakProperties[347]; - lineBreakProperties[355]=lineBreakProperties[348]; - lineBreakProperties[356]=lineBreakProperties[349]; - lineBreakProperties[357]=lineBreakProperties[350]; - lineBreakProperties[358]=lineBreakProperties[344]; - lineBreakProperties[359]=lineBreakProperties[345]; - lineBreakProperties[360]=lineBreakProperties[346]; - lineBreakProperties[361]=lineBreakProperties[347]; - lineBreakProperties[362]=lineBreakProperties[348]; - lineBreakProperties[363]=lineBreakProperties[349]; - lineBreakProperties[364]=lineBreakProperties[350]; - lineBreakProperties[365]=lineBreakProperties[344]; - lineBreakProperties[366]=lineBreakProperties[345]; - lineBreakProperties[367]=lineBreakProperties[346]; - lineBreakProperties[368]=lineBreakProperties[347]; - lineBreakProperties[369]=lineBreakProperties[348]; - lineBreakProperties[370]=lineBreakProperties[349]; - lineBreakProperties[371]=lineBreakProperties[350]; - lineBreakProperties[372]=lineBreakProperties[344]; - lineBreakProperties[373]=lineBreakProperties[345]; - lineBreakProperties[374]=lineBreakProperties[346]; - lineBreakProperties[375]=lineBreakProperties[347]; - lineBreakProperties[376]=lineBreakProperties[348]; - lineBreakProperties[377]=lineBreakProperties[349]; - lineBreakProperties[378]=lineBreakProperties[350]; - lineBreakProperties[379]=lineBreakProperties[344]; - lineBreakProperties[380]=lineBreakProperties[345]; - lineBreakProperties[381]=lineBreakProperties[346]; - lineBreakProperties[382]=lineBreakProperties[347]; - lineBreakProperties[383]=lineBreakProperties[348]; - lineBreakProperties[384]=lineBreakProperties[349]; - lineBreakProperties[385]=lineBreakProperties[350]; - lineBreakProperties[386]=lineBreakProperties[344]; - lineBreakProperties[387]=lineBreakProperties[345]; - lineBreakProperties[388]=lineBreakProperties[346]; - lineBreakProperties[389]=lineBreakProperties[347]; - lineBreakProperties[390]=lineBreakProperties[348]; - lineBreakProperties[391]=lineBreakProperties[349]; - lineBreakProperties[392]=lineBreakProperties[350]; - lineBreakProperties[393]=lineBreakProperties[344]; - lineBreakProperties[394]=lineBreakProperties[345]; - lineBreakProperties[395]=lineBreakProperties[346]; - lineBreakProperties[396]=lineBreakProperties[347]; - lineBreakProperties[397]=lineBreakProperties[348]; - lineBreakProperties[398]=lineBreakProperties[349]; - lineBreakProperties[399]=lineBreakProperties[350]; - lineBreakProperties[400]=lineBreakProperties[344]; - lineBreakProperties[401]=lineBreakProperties[345]; - lineBreakProperties[402]=lineBreakProperties[346]; - lineBreakProperties[403]=lineBreakProperties[347]; - lineBreakProperties[404]=lineBreakProperties[348]; - lineBreakProperties[405]=lineBreakProperties[349]; - lineBreakProperties[406]=lineBreakProperties[350]; - lineBreakProperties[407]=lineBreakProperties[344]; - lineBreakProperties[408]=lineBreakProperties[345]; - lineBreakProperties[409]=lineBreakProperties[346]; - lineBreakProperties[410]=lineBreakProperties[347]; - lineBreakProperties[411]=lineBreakProperties[348]; - lineBreakProperties[412]=lineBreakProperties[349]; - lineBreakProperties[413]=lineBreakProperties[350]; - lineBreakProperties[414]=lineBreakProperties[344]; - lineBreakProperties[415]=lineBreakProperties[345]; - lineBreakProperties[416]=lineBreakProperties[346]; - lineBreakProperties[417]=lineBreakProperties[347]; - lineBreakProperties[418]=lineBreakProperties[348]; - lineBreakProperties[419]=lineBreakProperties[349]; - lineBreakProperties[420]=lineBreakProperties[350]; - lineBreakProperties[421]=lineBreakProperties[344]; - lineBreakProperties[422]=lineBreakProperties[345]; - lineBreakProperties[423]=lineBreakProperties[346]; - lineBreakProperties[424]=lineBreakProperties[347]; - lineBreakProperties[425]=lineBreakProperties[348]; - lineBreakProperties[426]=lineBreakProperties[349]; - lineBreakProperties[427]=lineBreakProperties[350]; - lineBreakProperties[428]=lineBreakProperties[344]; - lineBreakProperties[429]=lineBreakProperties[345]; - lineBreakProperties[430]=lineBreakProperties[346]; - lineBreakProperties[433]=lineBreakProperties[432]; - lineBreakProperties[434]=lineBreakProperties[432]; - lineBreakProperties[435]=lineBreakProperties[432]; - lineBreakProperties[436]=lineBreakProperties[432]; - lineBreakProperties[437]=lineBreakProperties[432]; - lineBreakProperties[438]=lineBreakProperties[432]; - lineBreakProperties[439]=lineBreakProperties[432]; - lineBreakProperties[440]=lineBreakProperties[432]; - lineBreakProperties[441]=lineBreakProperties[432]; - lineBreakProperties[442]=lineBreakProperties[432]; - lineBreakProperties[443]=lineBreakProperties[432]; - lineBreakProperties[444]=lineBreakProperties[432]; - lineBreakProperties[445]=lineBreakProperties[432]; - lineBreakProperties[446]=lineBreakProperties[432]; - lineBreakProperties[447]=lineBreakProperties[432]; - lineBreakProperties[449]=lineBreakProperties[448]; - lineBreakProperties[450]=lineBreakProperties[448]; - lineBreakProperties[451]=lineBreakProperties[448]; - lineBreakProperties[452]=lineBreakProperties[448]; - lineBreakProperties[453]=lineBreakProperties[448]; - lineBreakProperties[454]=lineBreakProperties[448]; - lineBreakProperties[455]=lineBreakProperties[448]; - lineBreakProperties[456]=lineBreakProperties[448]; - lineBreakProperties[457]=lineBreakProperties[448]; - lineBreakProperties[458]=lineBreakProperties[448]; - lineBreakProperties[459]=lineBreakProperties[448]; - lineBreakProperties[460]=lineBreakProperties[448]; - lineBreakProperties[461]=lineBreakProperties[448]; - lineBreakProperties[462]=lineBreakProperties[448]; - lineBreakProperties[463]=lineBreakProperties[448]; - lineBreakProperties[464]=lineBreakProperties[448]; - lineBreakProperties[465]=lineBreakProperties[448]; - lineBreakProperties[466]=lineBreakProperties[448]; - lineBreakProperties[467]=lineBreakProperties[448]; - lineBreakProperties[468]=lineBreakProperties[448]; - lineBreakProperties[469]=lineBreakProperties[448]; - lineBreakProperties[470]=lineBreakProperties[448]; - lineBreakProperties[471]=lineBreakProperties[448]; - lineBreakProperties[472]=lineBreakProperties[448]; - lineBreakProperties[473]=lineBreakProperties[448]; - lineBreakProperties[474]=lineBreakProperties[448]; - lineBreakProperties[475]=lineBreakProperties[448]; - lineBreakProperties[476]=lineBreakProperties[448]; - lineBreakProperties[477]=lineBreakProperties[448]; - lineBreakProperties[478]=lineBreakProperties[448]; - lineBreakProperties[479]=lineBreakProperties[448]; - lineBreakProperties[480]=lineBreakProperties[448]; - lineBreakProperties[481]=lineBreakProperties[448]; - lineBreakProperties[482]=lineBreakProperties[448]; - lineBreakProperties[483]=lineBreakProperties[448]; - lineBreakProperties[484]=lineBreakProperties[448]; - lineBreakProperties[485]=lineBreakProperties[448]; - lineBreakProperties[486]=lineBreakProperties[448]; - lineBreakProperties[487]=lineBreakProperties[448]; - lineBreakProperties[488]=lineBreakProperties[448]; - lineBreakProperties[489]=lineBreakProperties[448]; - lineBreakProperties[490]=lineBreakProperties[448]; - lineBreakProperties[491]=lineBreakProperties[448]; - lineBreakProperties[492]=lineBreakProperties[448]; - lineBreakProperties[493]=lineBreakProperties[448]; - lineBreakProperties[494]=lineBreakProperties[448]; - lineBreakProperties[495]=lineBreakProperties[448]; - lineBreakProperties[496]=lineBreakProperties[448]; - lineBreakProperties[497]=lineBreakProperties[448]; - lineBreakProperties[498]=lineBreakProperties[94]; - lineBreakProperties[499]=lineBreakProperties[94]; - lineBreakProperties[504]=lineBreakProperties[2]; - lineBreakProperties[505]=lineBreakProperties[2]; - }; + lineBreakProperties[3] = lineBreakProperties[2]; + lineBreakProperties[4] = lineBreakProperties[2]; + lineBreakProperties[8] = lineBreakProperties[2]; + lineBreakProperties[17] = lineBreakProperties[16]; + lineBreakProperties[41] = lineBreakProperties[2]; + lineBreakProperties[42] = lineBreakProperties[2]; + lineBreakProperties[43] = lineBreakProperties[2]; + lineBreakProperties[53] = lineBreakProperties[16]; + lineBreakProperties[57] = lineBreakProperties[16]; + lineBreakProperties[58] = lineBreakProperties[2]; + lineBreakProperties[60] = lineBreakProperties[2]; + lineBreakProperties[61] = lineBreakProperties[2]; + lineBreakProperties[80] = lineBreakProperties[2]; + lineBreakProperties[81] = lineBreakProperties[2]; + lineBreakProperties[82] = lineBreakProperties[2]; + lineBreakProperties[84] = lineBreakProperties[2]; + lineBreakProperties[85] = lineBreakProperties[2]; + lineBreakProperties[87] = lineBreakProperties[16]; + lineBreakProperties[102] = lineBreakProperties[94]; + lineBreakProperties[103] = lineBreakProperties[94]; + lineBreakProperties[104] = lineBreakProperties[94]; + lineBreakProperties[105] = lineBreakProperties[94]; + lineBreakProperties[106] = lineBreakProperties[94]; + lineBreakProperties[107] = lineBreakProperties[94]; + lineBreakProperties[108] = lineBreakProperties[94]; + lineBreakProperties[109] = lineBreakProperties[94]; + lineBreakProperties[110] = lineBreakProperties[94]; + lineBreakProperties[111] = lineBreakProperties[94]; + lineBreakProperties[112] = lineBreakProperties[94]; + lineBreakProperties[113] = lineBreakProperties[94]; + lineBreakProperties[114] = lineBreakProperties[94]; + lineBreakProperties[115] = lineBreakProperties[94]; + lineBreakProperties[116] = lineBreakProperties[94]; + lineBreakProperties[117] = lineBreakProperties[94]; + lineBreakProperties[118] = lineBreakProperties[94]; + lineBreakProperties[119] = lineBreakProperties[94]; + lineBreakProperties[120] = lineBreakProperties[94]; + lineBreakProperties[121] = lineBreakProperties[94]; + lineBreakProperties[122] = lineBreakProperties[94]; + lineBreakProperties[123] = lineBreakProperties[94]; + lineBreakProperties[124] = lineBreakProperties[94]; + lineBreakProperties[125] = lineBreakProperties[94]; + lineBreakProperties[126] = lineBreakProperties[94]; + lineBreakProperties[127] = lineBreakProperties[94]; + lineBreakProperties[128] = lineBreakProperties[94]; + lineBreakProperties[129] = lineBreakProperties[94]; + lineBreakProperties[130] = lineBreakProperties[94]; + lineBreakProperties[131] = lineBreakProperties[94]; + lineBreakProperties[132] = lineBreakProperties[94]; + lineBreakProperties[133] = lineBreakProperties[94]; + lineBreakProperties[134] = lineBreakProperties[94]; + lineBreakProperties[135] = lineBreakProperties[94]; + lineBreakProperties[136] = lineBreakProperties[94]; + lineBreakProperties[137] = lineBreakProperties[94]; + lineBreakProperties[138] = lineBreakProperties[94]; + lineBreakProperties[139] = lineBreakProperties[94]; + lineBreakProperties[140] = lineBreakProperties[94]; + lineBreakProperties[141] = lineBreakProperties[94]; + lineBreakProperties[142] = lineBreakProperties[94]; + lineBreakProperties[143] = lineBreakProperties[94]; + lineBreakProperties[144] = lineBreakProperties[94]; + lineBreakProperties[145] = lineBreakProperties[94]; + lineBreakProperties[146] = lineBreakProperties[94]; + lineBreakProperties[147] = lineBreakProperties[94]; + lineBreakProperties[148] = lineBreakProperties[94]; + lineBreakProperties[149] = lineBreakProperties[94]; + lineBreakProperties[150] = lineBreakProperties[94]; + lineBreakProperties[151] = lineBreakProperties[94]; + lineBreakProperties[152] = lineBreakProperties[94]; + lineBreakProperties[153] = lineBreakProperties[94]; + lineBreakProperties[154] = lineBreakProperties[94]; + lineBreakProperties[156] = lineBreakProperties[94]; + lineBreakProperties[157] = lineBreakProperties[94]; + lineBreakProperties[158] = lineBreakProperties[94]; + lineBreakProperties[159] = lineBreakProperties[94]; + lineBreakProperties[160] = lineBreakProperties[94]; + lineBreakProperties[161] = lineBreakProperties[94]; + lineBreakProperties[162] = lineBreakProperties[94]; + lineBreakProperties[163] = lineBreakProperties[94]; + lineBreakProperties[164] = lineBreakProperties[94]; + lineBreakProperties[165] = lineBreakProperties[94]; + lineBreakProperties[166] = lineBreakProperties[94]; + lineBreakProperties[167] = lineBreakProperties[94]; + lineBreakProperties[168] = lineBreakProperties[94]; + lineBreakProperties[169] = lineBreakProperties[94]; + lineBreakProperties[170] = lineBreakProperties[94]; + lineBreakProperties[171] = lineBreakProperties[94]; + lineBreakProperties[172] = lineBreakProperties[94]; + lineBreakProperties[173] = lineBreakProperties[94]; + lineBreakProperties[174] = lineBreakProperties[94]; + lineBreakProperties[175] = lineBreakProperties[94]; + lineBreakProperties[176] = lineBreakProperties[94]; + lineBreakProperties[177] = lineBreakProperties[94]; + lineBreakProperties[178] = lineBreakProperties[94]; + lineBreakProperties[179] = lineBreakProperties[94]; + lineBreakProperties[180] = lineBreakProperties[94]; + lineBreakProperties[181] = lineBreakProperties[94]; + lineBreakProperties[182] = lineBreakProperties[94]; + lineBreakProperties[183] = lineBreakProperties[94]; + lineBreakProperties[184] = lineBreakProperties[94]; + lineBreakProperties[185] = lineBreakProperties[94]; + lineBreakProperties[186] = lineBreakProperties[94]; + lineBreakProperties[187] = lineBreakProperties[94]; + lineBreakProperties[188] = lineBreakProperties[94]; + lineBreakProperties[189] = lineBreakProperties[94]; + lineBreakProperties[190] = lineBreakProperties[94]; + lineBreakProperties[191] = lineBreakProperties[94]; + lineBreakProperties[192] = lineBreakProperties[94]; + lineBreakProperties[193] = lineBreakProperties[94]; + lineBreakProperties[194] = lineBreakProperties[94]; + lineBreakProperties[195] = lineBreakProperties[94]; + lineBreakProperties[196] = lineBreakProperties[94]; + lineBreakProperties[197] = lineBreakProperties[94]; + lineBreakProperties[198] = lineBreakProperties[94]; + lineBreakProperties[199] = lineBreakProperties[94]; + lineBreakProperties[200] = lineBreakProperties[94]; + lineBreakProperties[201] = lineBreakProperties[94]; + lineBreakProperties[202] = lineBreakProperties[94]; + lineBreakProperties[203] = lineBreakProperties[94]; + lineBreakProperties[204] = lineBreakProperties[94]; + lineBreakProperties[205] = lineBreakProperties[94]; + lineBreakProperties[206] = lineBreakProperties[94]; + lineBreakProperties[207] = lineBreakProperties[94]; + lineBreakProperties[208] = lineBreakProperties[94]; + lineBreakProperties[209] = lineBreakProperties[94]; + lineBreakProperties[210] = lineBreakProperties[94]; + lineBreakProperties[211] = lineBreakProperties[94]; + lineBreakProperties[212] = lineBreakProperties[94]; + lineBreakProperties[213] = lineBreakProperties[94]; + lineBreakProperties[214] = lineBreakProperties[94]; + lineBreakProperties[215] = lineBreakProperties[94]; + lineBreakProperties[216] = lineBreakProperties[94]; + lineBreakProperties[217] = lineBreakProperties[94]; + lineBreakProperties[218] = lineBreakProperties[94]; + lineBreakProperties[219] = lineBreakProperties[94]; + lineBreakProperties[220] = lineBreakProperties[94]; + lineBreakProperties[221] = lineBreakProperties[94]; + lineBreakProperties[222] = lineBreakProperties[94]; + lineBreakProperties[223] = lineBreakProperties[94]; + lineBreakProperties[224] = lineBreakProperties[94]; + lineBreakProperties[225] = lineBreakProperties[94]; + lineBreakProperties[226] = lineBreakProperties[94]; + lineBreakProperties[227] = lineBreakProperties[94]; + lineBreakProperties[228] = lineBreakProperties[94]; + lineBreakProperties[229] = lineBreakProperties[94]; + lineBreakProperties[230] = lineBreakProperties[94]; + lineBreakProperties[231] = lineBreakProperties[94]; + lineBreakProperties[232] = lineBreakProperties[94]; + lineBreakProperties[233] = lineBreakProperties[94]; + lineBreakProperties[234] = lineBreakProperties[94]; + lineBreakProperties[235] = lineBreakProperties[94]; + lineBreakProperties[236] = lineBreakProperties[94]; + lineBreakProperties[237] = lineBreakProperties[94]; + lineBreakProperties[238] = lineBreakProperties[94]; + lineBreakProperties[239] = lineBreakProperties[94]; + lineBreakProperties[240] = lineBreakProperties[94]; + lineBreakProperties[241] = lineBreakProperties[94]; + lineBreakProperties[242] = lineBreakProperties[94]; + lineBreakProperties[243] = lineBreakProperties[94]; + lineBreakProperties[244] = lineBreakProperties[94]; + lineBreakProperties[245] = lineBreakProperties[94]; + lineBreakProperties[246] = lineBreakProperties[94]; + lineBreakProperties[247] = lineBreakProperties[94]; + lineBreakProperties[248] = lineBreakProperties[94]; + lineBreakProperties[249] = lineBreakProperties[94]; + lineBreakProperties[250] = lineBreakProperties[94]; + lineBreakProperties[251] = lineBreakProperties[94]; + lineBreakProperties[252] = lineBreakProperties[94]; + lineBreakProperties[253] = lineBreakProperties[94]; + lineBreakProperties[254] = lineBreakProperties[94]; + lineBreakProperties[255] = lineBreakProperties[94]; + lineBreakProperties[256] = lineBreakProperties[94]; + lineBreakProperties[257] = lineBreakProperties[94]; + lineBreakProperties[258] = lineBreakProperties[94]; + lineBreakProperties[259] = lineBreakProperties[94]; + lineBreakProperties[260] = lineBreakProperties[94]; + lineBreakProperties[261] = lineBreakProperties[94]; + lineBreakProperties[262] = lineBreakProperties[94]; + lineBreakProperties[263] = lineBreakProperties[94]; + lineBreakProperties[264] = lineBreakProperties[94]; + lineBreakProperties[265] = lineBreakProperties[94]; + lineBreakProperties[266] = lineBreakProperties[94]; + lineBreakProperties[267] = lineBreakProperties[94]; + lineBreakProperties[268] = lineBreakProperties[94]; + lineBreakProperties[269] = lineBreakProperties[94]; + lineBreakProperties[270] = lineBreakProperties[94]; + lineBreakProperties[271] = lineBreakProperties[94]; + lineBreakProperties[272] = lineBreakProperties[94]; + lineBreakProperties[273] = lineBreakProperties[94]; + lineBreakProperties[274] = lineBreakProperties[94]; + lineBreakProperties[275] = lineBreakProperties[94]; + lineBreakProperties[276] = lineBreakProperties[94]; + lineBreakProperties[277] = lineBreakProperties[94]; + lineBreakProperties[278] = lineBreakProperties[94]; + lineBreakProperties[279] = lineBreakProperties[94]; + lineBreakProperties[280] = lineBreakProperties[94]; + lineBreakProperties[281] = lineBreakProperties[94]; + lineBreakProperties[282] = lineBreakProperties[94]; + lineBreakProperties[283] = lineBreakProperties[94]; + lineBreakProperties[284] = lineBreakProperties[94]; + lineBreakProperties[285] = lineBreakProperties[94]; + lineBreakProperties[286] = lineBreakProperties[94]; + lineBreakProperties[287] = lineBreakProperties[94]; + lineBreakProperties[288] = lineBreakProperties[94]; + lineBreakProperties[289] = lineBreakProperties[94]; + lineBreakProperties[290] = lineBreakProperties[94]; + lineBreakProperties[291] = lineBreakProperties[94]; + lineBreakProperties[292] = lineBreakProperties[94]; + lineBreakProperties[293] = lineBreakProperties[94]; + lineBreakProperties[294] = lineBreakProperties[94]; + lineBreakProperties[295] = lineBreakProperties[94]; + lineBreakProperties[296] = lineBreakProperties[94]; + lineBreakProperties[297] = lineBreakProperties[94]; + lineBreakProperties[298] = lineBreakProperties[94]; + lineBreakProperties[299] = lineBreakProperties[94]; + lineBreakProperties[300] = lineBreakProperties[94]; + lineBreakProperties[301] = lineBreakProperties[94]; + lineBreakProperties[302] = lineBreakProperties[94]; + lineBreakProperties[303] = lineBreakProperties[94]; + lineBreakProperties[304] = lineBreakProperties[94]; + lineBreakProperties[305] = lineBreakProperties[94]; + lineBreakProperties[306] = lineBreakProperties[94]; + lineBreakProperties[307] = lineBreakProperties[94]; + lineBreakProperties[308] = lineBreakProperties[94]; + lineBreakProperties[309] = lineBreakProperties[94]; + lineBreakProperties[310] = lineBreakProperties[94]; + lineBreakProperties[311] = lineBreakProperties[94]; + lineBreakProperties[312] = lineBreakProperties[94]; + lineBreakProperties[313] = lineBreakProperties[94]; + lineBreakProperties[314] = lineBreakProperties[94]; + lineBreakProperties[315] = lineBreakProperties[94]; + lineBreakProperties[316] = lineBreakProperties[94]; + lineBreakProperties[317] = lineBreakProperties[94]; + lineBreakProperties[318] = lineBreakProperties[94]; + lineBreakProperties[321] = lineBreakProperties[94]; + lineBreakProperties[322] = lineBreakProperties[94]; + lineBreakProperties[323] = lineBreakProperties[94]; + lineBreakProperties[324] = lineBreakProperties[94]; + lineBreakProperties[325] = lineBreakProperties[94]; + lineBreakProperties[326] = lineBreakProperties[94]; + lineBreakProperties[327] = lineBreakProperties[94]; + lineBreakProperties[328] = lineBreakProperties[94]; + lineBreakProperties[330] = lineBreakProperties[2]; + lineBreakProperties[331] = lineBreakProperties[2]; + lineBreakProperties[334] = lineBreakProperties[2]; + lineBreakProperties[339] = lineBreakProperties[16]; + lineBreakProperties[341] = lineBreakProperties[16]; + lineBreakProperties[342] = lineBreakProperties[16]; + lineBreakProperties[343] = lineBreakProperties[16]; + lineBreakProperties[351] = lineBreakProperties[344]; + lineBreakProperties[352] = lineBreakProperties[345]; + lineBreakProperties[353] = lineBreakProperties[346]; + lineBreakProperties[354] = lineBreakProperties[347]; + lineBreakProperties[355] = lineBreakProperties[348]; + lineBreakProperties[356] = lineBreakProperties[349]; + lineBreakProperties[357] = lineBreakProperties[350]; + lineBreakProperties[358] = lineBreakProperties[344]; + lineBreakProperties[359] = lineBreakProperties[345]; + lineBreakProperties[360] = lineBreakProperties[346]; + lineBreakProperties[361] = lineBreakProperties[347]; + lineBreakProperties[362] = lineBreakProperties[348]; + lineBreakProperties[363] = lineBreakProperties[349]; + lineBreakProperties[364] = lineBreakProperties[350]; + lineBreakProperties[365] = lineBreakProperties[344]; + lineBreakProperties[366] = lineBreakProperties[345]; + lineBreakProperties[367] = lineBreakProperties[346]; + lineBreakProperties[368] = lineBreakProperties[347]; + lineBreakProperties[369] = lineBreakProperties[348]; + lineBreakProperties[370] = lineBreakProperties[349]; + lineBreakProperties[371] = lineBreakProperties[350]; + lineBreakProperties[372] = lineBreakProperties[344]; + lineBreakProperties[373] = lineBreakProperties[345]; + lineBreakProperties[374] = lineBreakProperties[346]; + lineBreakProperties[375] = lineBreakProperties[347]; + lineBreakProperties[376] = lineBreakProperties[348]; + lineBreakProperties[377] = lineBreakProperties[349]; + lineBreakProperties[378] = lineBreakProperties[350]; + lineBreakProperties[379] = lineBreakProperties[344]; + lineBreakProperties[380] = lineBreakProperties[345]; + lineBreakProperties[381] = lineBreakProperties[346]; + lineBreakProperties[382] = lineBreakProperties[347]; + lineBreakProperties[383] = lineBreakProperties[348]; + lineBreakProperties[384] = lineBreakProperties[349]; + lineBreakProperties[385] = lineBreakProperties[350]; + lineBreakProperties[386] = lineBreakProperties[344]; + lineBreakProperties[387] = lineBreakProperties[345]; + lineBreakProperties[388] = lineBreakProperties[346]; + lineBreakProperties[389] = lineBreakProperties[347]; + lineBreakProperties[390] = lineBreakProperties[348]; + lineBreakProperties[391] = lineBreakProperties[349]; + lineBreakProperties[392] = lineBreakProperties[350]; + lineBreakProperties[393] = lineBreakProperties[344]; + lineBreakProperties[394] = lineBreakProperties[345]; + lineBreakProperties[395] = lineBreakProperties[346]; + lineBreakProperties[396] = lineBreakProperties[347]; + lineBreakProperties[397] = lineBreakProperties[348]; + lineBreakProperties[398] = lineBreakProperties[349]; + lineBreakProperties[399] = lineBreakProperties[350]; + lineBreakProperties[400] = lineBreakProperties[344]; + lineBreakProperties[401] = lineBreakProperties[345]; + lineBreakProperties[402] = lineBreakProperties[346]; + lineBreakProperties[403] = lineBreakProperties[347]; + lineBreakProperties[404] = lineBreakProperties[348]; + lineBreakProperties[405] = lineBreakProperties[349]; + lineBreakProperties[406] = lineBreakProperties[350]; + lineBreakProperties[407] = lineBreakProperties[344]; + lineBreakProperties[408] = lineBreakProperties[345]; + lineBreakProperties[409] = lineBreakProperties[346]; + lineBreakProperties[410] = lineBreakProperties[347]; + lineBreakProperties[411] = lineBreakProperties[348]; + lineBreakProperties[412] = lineBreakProperties[349]; + lineBreakProperties[413] = lineBreakProperties[350]; + lineBreakProperties[414] = lineBreakProperties[344]; + lineBreakProperties[415] = lineBreakProperties[345]; + lineBreakProperties[416] = lineBreakProperties[346]; + lineBreakProperties[417] = lineBreakProperties[347]; + lineBreakProperties[418] = lineBreakProperties[348]; + lineBreakProperties[419] = lineBreakProperties[349]; + lineBreakProperties[420] = lineBreakProperties[350]; + lineBreakProperties[421] = lineBreakProperties[344]; + lineBreakProperties[422] = lineBreakProperties[345]; + lineBreakProperties[423] = lineBreakProperties[346]; + lineBreakProperties[424] = lineBreakProperties[347]; + lineBreakProperties[425] = lineBreakProperties[348]; + lineBreakProperties[426] = lineBreakProperties[349]; + lineBreakProperties[427] = lineBreakProperties[350]; + lineBreakProperties[428] = lineBreakProperties[344]; + lineBreakProperties[429] = lineBreakProperties[345]; + lineBreakProperties[430] = lineBreakProperties[346]; + lineBreakProperties[433] = lineBreakProperties[432]; + lineBreakProperties[434] = lineBreakProperties[432]; + lineBreakProperties[435] = lineBreakProperties[432]; + lineBreakProperties[436] = lineBreakProperties[432]; + lineBreakProperties[437] = lineBreakProperties[432]; + lineBreakProperties[438] = lineBreakProperties[432]; + lineBreakProperties[439] = lineBreakProperties[432]; + lineBreakProperties[440] = lineBreakProperties[432]; + lineBreakProperties[441] = lineBreakProperties[432]; + lineBreakProperties[442] = lineBreakProperties[432]; + lineBreakProperties[443] = lineBreakProperties[432]; + lineBreakProperties[444] = lineBreakProperties[432]; + lineBreakProperties[445] = lineBreakProperties[432]; + lineBreakProperties[446] = lineBreakProperties[432]; + lineBreakProperties[447] = lineBreakProperties[432]; + lineBreakProperties[449] = lineBreakProperties[448]; + lineBreakProperties[450] = lineBreakProperties[448]; + lineBreakProperties[451] = lineBreakProperties[448]; + lineBreakProperties[452] = lineBreakProperties[448]; + lineBreakProperties[453] = lineBreakProperties[448]; + lineBreakProperties[454] = lineBreakProperties[448]; + lineBreakProperties[455] = lineBreakProperties[448]; + lineBreakProperties[456] = lineBreakProperties[448]; + lineBreakProperties[457] = lineBreakProperties[448]; + lineBreakProperties[458] = lineBreakProperties[448]; + lineBreakProperties[459] = lineBreakProperties[448]; + lineBreakProperties[460] = lineBreakProperties[448]; + lineBreakProperties[461] = lineBreakProperties[448]; + lineBreakProperties[462] = lineBreakProperties[448]; + lineBreakProperties[463] = lineBreakProperties[448]; + lineBreakProperties[464] = lineBreakProperties[448]; + lineBreakProperties[465] = lineBreakProperties[448]; + lineBreakProperties[466] = lineBreakProperties[448]; + lineBreakProperties[467] = lineBreakProperties[448]; + lineBreakProperties[468] = lineBreakProperties[448]; + lineBreakProperties[469] = lineBreakProperties[448]; + lineBreakProperties[470] = lineBreakProperties[448]; + lineBreakProperties[471] = lineBreakProperties[448]; + lineBreakProperties[472] = lineBreakProperties[448]; + lineBreakProperties[473] = lineBreakProperties[448]; + lineBreakProperties[474] = lineBreakProperties[448]; + lineBreakProperties[475] = lineBreakProperties[448]; + lineBreakProperties[476] = lineBreakProperties[448]; + lineBreakProperties[477] = lineBreakProperties[448]; + lineBreakProperties[478] = lineBreakProperties[448]; + lineBreakProperties[479] = lineBreakProperties[448]; + lineBreakProperties[480] = lineBreakProperties[448]; + lineBreakProperties[481] = lineBreakProperties[448]; + lineBreakProperties[482] = lineBreakProperties[448]; + lineBreakProperties[483] = lineBreakProperties[448]; + lineBreakProperties[484] = lineBreakProperties[448]; + lineBreakProperties[485] = lineBreakProperties[448]; + lineBreakProperties[486] = lineBreakProperties[448]; + lineBreakProperties[487] = lineBreakProperties[448]; + lineBreakProperties[488] = lineBreakProperties[448]; + lineBreakProperties[489] = lineBreakProperties[448]; + lineBreakProperties[490] = lineBreakProperties[448]; + lineBreakProperties[491] = lineBreakProperties[448]; + lineBreakProperties[492] = lineBreakProperties[448]; + lineBreakProperties[493] = lineBreakProperties[448]; + lineBreakProperties[494] = lineBreakProperties[448]; + lineBreakProperties[495] = lineBreakProperties[448]; + lineBreakProperties[496] = lineBreakProperties[448]; + lineBreakProperties[497] = lineBreakProperties[448]; + lineBreakProperties[498] = lineBreakProperties[94]; + lineBreakProperties[499] = lineBreakProperties[94]; + lineBreakProperties[504] = lineBreakProperties[2]; + lineBreakProperties[505] = lineBreakProperties[2]; + } - public static final byte LINE_BREAK_PROPERTY_AI=1; - public static final byte LINE_BREAK_PROPERTY_AL=2; - public static final byte LINE_BREAK_PROPERTY_B2=3; - public static final byte LINE_BREAK_PROPERTY_BA=4; - public static final byte LINE_BREAK_PROPERTY_BB=5; - public static final byte LINE_BREAK_PROPERTY_BK=6; - public static final byte LINE_BREAK_PROPERTY_CB=7; - public static final byte LINE_BREAK_PROPERTY_CL=8; - public static final byte LINE_BREAK_PROPERTY_CM=9; - public static final byte LINE_BREAK_PROPERTY_CR=10; - public static final byte LINE_BREAK_PROPERTY_EX=11; - public static final byte LINE_BREAK_PROPERTY_GL=12; - public static final byte LINE_BREAK_PROPERTY_H2=13; - public static final byte LINE_BREAK_PROPERTY_H3=14; - public static final byte LINE_BREAK_PROPERTY_HY=15; - public static final byte LINE_BREAK_PROPERTY_ID=16; - public static final byte LINE_BREAK_PROPERTY_IN=17; - public static final byte LINE_BREAK_PROPERTY_IS=18; - public static final byte LINE_BREAK_PROPERTY_JL=19; - public static final byte LINE_BREAK_PROPERTY_JT=20; - public static final byte LINE_BREAK_PROPERTY_JV=21; - public static final byte LINE_BREAK_PROPERTY_LF=22; - public static final byte LINE_BREAK_PROPERTY_NL=23; - public static final byte LINE_BREAK_PROPERTY_NS=24; - public static final byte LINE_BREAK_PROPERTY_NU=25; - public static final byte LINE_BREAK_PROPERTY_OP=26; - public static final byte LINE_BREAK_PROPERTY_PO=27; - public static final byte LINE_BREAK_PROPERTY_PR=28; - public static final byte LINE_BREAK_PROPERTY_QU=29; - public static final byte LINE_BREAK_PROPERTY_SA=30; - public static final byte LINE_BREAK_PROPERTY_SG=31; - public static final byte LINE_BREAK_PROPERTY_SP=32; - public static final byte LINE_BREAK_PROPERTY_SY=33; - public static final byte LINE_BREAK_PROPERTY_WJ=34; - public static final byte LINE_BREAK_PROPERTY_XX=35; - public static final byte LINE_BREAK_PROPERTY_ZW=36; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_AI = 1; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_AL = 2; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_B2 = 3; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_BA = 4; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_BB = 5; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_BK = 6; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_CB = 7; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_CL = 8; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_CM = 9; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_CR = 10; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_EX = 11; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_GL = 12; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_H2 = 13; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_H3 = 14; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_HY = 15; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_ID = 16; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_IN = 17; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_IS = 18; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_JL = 19; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_JT = 20; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_JV = 21; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_LF = 22; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_NL = 23; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_NS = 24; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_NU = 25; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_OP = 26; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_PO = 27; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_PR = 28; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_QU = 29; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_SA = 30; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_SG = 31; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_SP = 32; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_SY = 33; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_WJ = 34; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_XX = 35; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_ZW = 36; - private static String lineBreakPropertyShortNames[] = {"AI","AL","B2","BA","BB","BK","CB","CL","CM","CR","EX", - "GL","H2","H3","HY","ID","IN","IS","JL","JT","JV","LF","NL","NS","NU","OP","PO","PR","QU","SA","SG","SP", - "SY","WJ","XX","ZW"}; + private static String lineBreakPropertyShortNames[] = {"AI", "AL", "B2", "BA", "BB", "BK", "CB", "CL", "CM", "CR", "EX", + "GL", "H2", "H3", "HY", "ID", "IN", "IS", "JL", "JT", "JV", "LF", "NL", "NS", "NU", "OP", "PO", "PR", "QU", "SA", "SG", "SP", + "SY", "WJ", "XX", "ZW"}; private static String lineBreakPropertyLongNames[] = {"Ambiguous","Alphabetic","Break_Both","Break_After","Break_Before", "Mandatory_Break","Contingent_Break","Close_Punctuation","Combining_Mark","Carriage_Return","Exclamation", @@ -642,28 +690,58 @@ class LineBreakUtils { "Nonstarter","Numeric","Open_Punctuation","Postfix_Numeric","Prefix_Numeric","Quotation","Complex_Context", "Surrogate","Space","Break_Symbols","Word_Joiner","Unknown","ZWSpace"}; + /** + * Return the short name for the linebreak property corresponding + * to the given symbolic constant. + * + * @param i the numeric value of the linebreak property + * @return the short name of the linebreak property + */ public static String getLineBreakPropertyShortName(byte i) { - if (i>0 && i<=lineBreakPropertyShortNames.length) { - return lineBreakPropertyShortNames[i-1]; + if (i > 0 && i <= lineBreakPropertyShortNames.length) { + return lineBreakPropertyShortNames[i - 1]; } else { return null; } } + /** + * Return the long name for the linebreak property corresponding + * to the given symbolic constant. + * + * @param i the numeric value of the linebreak property + * @return the long name of the linebreak property + */ public static String getLineBreakPropertyLongName(byte i) { - if (i>0 && i<=lineBreakPropertyLongNames.length) { - return lineBreakPropertyLongNames[i-1]; + if (i > 0 && i <= lineBreakPropertyLongNames.length) { + return lineBreakPropertyLongNames[i - 1]; } else { return null; } } + /** + * Return the linebreak property constant for the given <code>char</code> + * + * @param c the <code>char</code> whose linebreak property to return + * @return the constant representing the linebreak property + */ public static byte getLineBreakProperty(char c) { - return lineBreakProperties[c/128][c%128]; + return lineBreakProperties[c / 128][c % 128]; } - public static byte getLineBreakPairProperty(int lineBreakPropertyBefore,int lineBreakPropertyAfter) { - return PAIR_TABLE[lineBreakPropertyBefore-1][lineBreakPropertyAfter-1]; + /** + * Return the break class constant for the given pair of linebreak + * property constants. + * + * @param lineBreakPropertyBefore the linebreak property for the first character + * in a two-character sequence + * @param lineBreakPropertyAfter the linebreak property for the second character + * in a two-character sequence + * @return the constant representing the break class + */ + public static byte getLineBreakPairProperty(int lineBreakPropertyBefore, int lineBreakPropertyAfter) { + return PAIR_TABLE[lineBreakPropertyBefore - 1][lineBreakPropertyAfter - 1]; } -}; +} diff --git a/src/java/org/apache/fop/util/CharUtilities.java b/src/java/org/apache/fop/util/CharUtilities.java index 4910a371c..eb56cd331 100644 --- a/src/java/org/apache/fop/util/CharUtilities.java +++ b/src/java/org/apache/fop/util/CharUtilities.java @@ -54,10 +54,20 @@ public class CharUtilities { public static final int XMLWHITESPACE = 4; + /** null char */ + public static final char NULL_CHAR = '\u0000'; + /** linefeed character */ + public static final char LINEFEED_CHAR = '\n'; + /** carriage return */ + public static final char CARRIAGE_RETURN = '\r'; + /** normal tab */ + public static final char TAB = '\t'; /** normal space */ public static final char SPACE = '\u0020'; /** non-breaking space */ public static final char NBSPACE = '\u00A0'; + /** next line control character */ + public static final char NEXT_LINE = '\u0085'; /** zero-width space */ public static final char ZERO_WIDTH_SPACE = '\u200B'; /** word joiner */ @@ -68,11 +78,18 @@ public class CharUtilities { public static final char ZERO_WIDTH_NOBREAK_SPACE = '\uFEFF'; /** soft hyphen */ public static final char SOFT_HYPHEN = '\u00AD'; + /** line-separator */ + public static final char LINE_SEPARATOR = '\u2028'; + /** paragraph-separator */ + public static final char PARAGRAPH_SEPARATOR = '\u2029'; /** missing ideograph */ public static final char MISSING_IDEOGRAPH = '\u25A1'; + /** Ideogreaphic space */ + public static final char IDEOGRAPHIC_SPACE = '\u3000'; /** Unicode value indicating the the character is "not a character". */ public static final char NOT_A_CHARACTER = '\uFFFF'; + /** * Utility class: Constructor prevents instantiating when subclassed. */ @@ -87,11 +104,18 @@ public class CharUtilities { * @return the determined character class */ public static int classOf(char c) { - if (c == CODE_EOT) { return EOT; } - if (c == '\n') { return LINEFEED; } - if (c == ' ' || c == '\r' || c == '\t') { return XMLWHITESPACE; } - if (isAnySpace(c)) { return UCWHITESPACE; } - return NONWHITESPACE; + switch (c) { + case CODE_EOT: + return EOT; + case LINEFEED_CHAR: + return LINEFEED; + case SPACE: + case CARRIAGE_RETURN: + case TAB: + return XMLWHITESPACE; + default: + return isAnySpace(c) ? UCWHITESPACE : NONWHITESPACE; + } } @@ -174,8 +198,7 @@ public class CharUtilities { * @return True if the character represents any kind of space */ public static boolean isAnySpace(char c) { - boolean ret = (isBreakableSpace(c) || isNonBreakableSpace(c)); - return ret; + return (isBreakableSpace(c) || isNonBreakableSpace(c)); } /** @@ -188,19 +211,31 @@ public class CharUtilities { //Generated from: Other_Alphabetic + Lu + Ll + Lt + Lm + Lo + Nl int generalCategory = Character.getType(ch); switch (generalCategory) { - case Character.UPPERCASE_LETTER: //Lu - case Character.LOWERCASE_LETTER: //Ll - case Character.TITLECASE_LETTER: //Lt - case Character.MODIFIER_LETTER: //Lm - case Character.OTHER_LETTER: //Lo - case Character.LETTER_NUMBER: //Nl - return true; - default: - //TODO if (ch in Other_Alphabetic) return true; (Probably need ICU4J for that) - //Other_Alphabetic contains mostly more exotic characters - return false; + case Character.UPPERCASE_LETTER: //Lu + case Character.LOWERCASE_LETTER: //Ll + case Character.TITLECASE_LETTER: //Lt + case Character.MODIFIER_LETTER: //Lm + case Character.OTHER_LETTER: //Lo + case Character.LETTER_NUMBER: //Nl + return true; + default: + //TODO if (ch in Other_Alphabetic) return true; (Probably need ICU4J for that) + //Other_Alphabetic contains mostly more exotic characters + return false; } } - + + /** + * Indicates whether the given character is an explicit break-character + * @param ch the character to check + * @return true if the character represents an explicit break + */ + public static boolean isExplicitBreak(char ch) { + return (ch == LINEFEED_CHAR + || ch == CARRIAGE_RETURN + || ch == NEXT_LINE + || ch == LINE_SEPARATOR + || ch == PARAGRAPH_SEPARATOR); + } } diff --git a/src/java/org/apache/fop/util/CloseBlockerOutputStream.java b/src/java/org/apache/fop/util/CloseBlockerOutputStream.java index 7192e76d2..c0db8c8b7 100644 --- a/src/java/org/apache/fop/util/CloseBlockerOutputStream.java +++ b/src/java/org/apache/fop/util/CloseBlockerOutputStream.java @@ -19,25 +19,25 @@ package org.apache.fop.util; -import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; +import org.apache.commons.io.output.ProxyOutputStream; + /** * This is a decorator to block calls to close() to the underlying stream. */ -public class CloseBlockerOutputStream extends FilterOutputStream { +public class CloseBlockerOutputStream extends ProxyOutputStream { /** - * @see java.io.FilterOutputStream#FilterOutputStream(OutputStream) + * Main constructor. + * @param out the underlying stream */ public CloseBlockerOutputStream(OutputStream out) { super(out); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void close() throws IOException { try { flush(); diff --git a/src/java/org/apache/fop/util/ConversionUtils.java b/src/java/org/apache/fop/util/ConversionUtils.java new file mode 100644 index 000000000..e2d93fbd3 --- /dev/null +++ b/src/java/org/apache/fop/util/ConversionUtils.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* $Id$ */ +package org.apache.fop.util; + +/** + * This class contains utility methods for conversions, like + * a java.lang.String to an array of int or double. + */ +public final class ConversionUtils { + + /** + * Converts the given base <code>String</code> into + * an array of <code>int</code>, splitting the base along the + * given separator pattern. + * <em>Note: this method assumes the input is a string containing + * only decimal integers, signed or unsigned, that are parsable + * by <code>java.lang.Integer.parseInt(String)</code>. If this + * is not the case, the resulting <code>NumberFormatException</code> + * will have to be handled by the caller.</em> + * + * @param baseString the base string + * @param separatorPattern the pattern separating the integer values + * (if this is <code>null</code>, the baseString is parsed as one + * integer value) + * @return an array of <code>int</code> whose size is equal to the number + * values in the input string; <code>null</code> if this number + * is equal to zero. + */ + public static int[] toIntArray(String baseString, String separatorPattern) { + + if (baseString == null || "".equals(baseString)) { + return null; + } + + if (separatorPattern == null || "".equals(separatorPattern)) { + return new int[] { Integer.parseInt(baseString) }; + } + + String[] values = baseString.split(separatorPattern); + int numValues = values.length; + if (numValues == 0) { + return null; + } + + int[] returnArray = new int[numValues]; + for (int i = 0; i < numValues; ++i) { + returnArray[i] = Integer.parseInt(values[i]); + } + return returnArray; + + } + + /** + * Converts the given base <code>String</code> into + * an array of <code>double</code>, splitting the base along the + * given separator pattern. + * <em>Note: this method assumes the input is a string containing + * only decimal doubles, signed or unsigned, that are parsable + * by <code>java.lang.Double.parseDouble(String)</code>. If this + * is not the case, the resulting <code>NumberFormatException</code> + * will have to be handled by the caller.</em> + * + * @param baseString the base string + * @param separatorPattern the pattern separating the integer values + * (if this is <code>null</code>, the baseString is parsed as one + * double value) + * @return an array of <code>double</code> whose size is equal to the number + * values in the input string; <code>null</code> if this number + * is equal to zero. + */ + public static double[] toDoubleArray(String baseString, String separatorPattern) { + + if (baseString == null || "".equals(baseString)) { + return null; + } + + if (separatorPattern == null || "".equals(separatorPattern)) { + return new double[] { Double.parseDouble(baseString) }; + } + + String[] values = baseString.split(separatorPattern); + int numValues = values.length; + if (numValues == 0) { + return null; + } + + double[] returnArray = new double[numValues]; + for (int i = 0; i < numValues; ++i) { + returnArray[i] = Double.parseDouble(values[i]); + } + return returnArray; + + } + +} diff --git a/src/java/org/apache/fop/util/XMLizable.java b/src/java/org/apache/fop/util/ListUtil.java index a16131989..a6b8d490c 100644 --- a/src/java/org/apache/fop/util/XMLizable.java +++ b/src/java/org/apache/fop/util/ListUtil.java @@ -1,13 +1,13 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,17 +19,37 @@ package org.apache.fop.util; -/* - * Copied from Apache Excalibur: - * https://svn.apache.org/repos/asf/excalibur/trunk/components/xmlutil/ - * src/java/org/apache/excalibur/xml/sax/XMLizable.java - */ +import java.util.List; /** - * This interface can be implemented by classes willing to provide an XML representation - * of their current state as SAX events. - * @deprecated Use the interface in Apache XML Graphics Commons instead. + * Provides helper functions for {@link java.util.List}. + * */ -public interface XMLizable extends org.apache.xmlgraphics.util.XMLizable { - +public final class ListUtil { + + private ListUtil() { + // Utility class. + } + + /** + * Retrieve the last element from a list. + * + * @param list + * The list to work on + * @return last element + */ + public static Object getLast(List list) { + return list.get(list.size() - 1); + } + + /** + * Retrieve and remove the last element from a list. + * + * @param list + * The list to work on + * @return previous last element + */ + public static Object removeLast(List list) { + return list.remove(list.size() - 1); + } } |