diff options
-rw-r--r-- | build.xml | 79 | ||||
-rw-r--r-- | src/codegen/fo/colorkw.xml (renamed from src/codegen/colorkw.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fo/constants.xml (renamed from src/codegen/constants.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fo/constants.xsl (renamed from src/codegen/constants.xsl) | 0 | ||||
-rw-r--r-- | src/codegen/fo/fo-property-mapping.xsl (renamed from src/codegen/fo-property-mapping.xsl) | 0 | ||||
-rw-r--r-- | src/codegen/fo/foelements.xml (renamed from src/codegen/foelements.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fo/foproperties.xml (renamed from src/codegen/foproperties.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fo/properties.dtd (renamed from src/codegen/properties.dtd) | 0 | ||||
-rw-r--r-- | src/codegen/fo/property-sets.xsl (renamed from src/codegen/property-sets.xsl) | 0 | ||||
-rw-r--r-- | src/codegen/fo/propinc.xsl (renamed from src/codegen/propinc.xsl) | 0 | ||||
-rw-r--r-- | src/codegen/fo/propmaker.xsl (renamed from src/codegen/propmaker.xsl) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/Courier.xml (renamed from src/codegen/Courier.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/CourierBold.xml (renamed from src/codegen/CourierBold.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/CourierBoldOblique.xml (renamed from src/codegen/CourierBoldOblique.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/CourierOblique.xml (renamed from src/codegen/CourierOblique.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/Helvetica.xml (renamed from src/codegen/Helvetica.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/HelveticaBold.xml (renamed from src/codegen/HelveticaBold.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/HelveticaBoldOblique.xml (renamed from src/codegen/HelveticaBoldOblique.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/HelveticaOblique.xml (renamed from src/codegen/HelveticaOblique.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/Symbol.xml (renamed from src/codegen/Symbol.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/TimesBold.xml (renamed from src/codegen/TimesBold.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/TimesBoldItalic.xml (renamed from src/codegen/TimesBoldItalic.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/TimesItalic.xml (renamed from src/codegen/TimesItalic.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/TimesRoman.xml (renamed from src/codegen/TimesRoman.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/ZapfDingbats.xml (renamed from src/codegen/ZapfDingbats.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/charlist.xml (renamed from src/codegen/charlist.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/code-point-mapping.xsl (renamed from src/codegen/code-point-mapping.xsl) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/encodings.xml (renamed from src/codegen/encodings.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/font-file.xsl (renamed from src/codegen/font-file.xsl) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/glyphlist.xml (renamed from src/codegen/glyphlist.xml) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/t1font-file.xsl (renamed from src/codegen/t1font-file.xsl) | 0 | ||||
-rw-r--r-- | src/codegen/fonts/ttffontfile.xsl (renamed from src/codegen/ttffontfile.xsl) | 0 | ||||
-rwxr-xr-x | src/codegen/unicode/data/LineBreakPairTable.txt | 28 | ||||
-rw-r--r-- | src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java | 659 | ||||
-rw-r--r-- | src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java | 642 | ||||
-rw-r--r-- | src/java/org/apache/fop/text/linebreak/LineBreakStatus.java | 160 | ||||
-rw-r--r-- | src/java/org/apache/fop/text/linebreak/LineBreakUtils.java | 669 | ||||
-rw-r--r-- | status.xml | 3 | ||||
-rw-r--r-- | test/java/org/apache/fop/text/linebreak/LineBreakStatusTest.java | 351 | ||||
-rw-r--r-- | test/java/org/apache/fop/text/linebreak/LineBreakUtilsTest.java | 74 | ||||
-rwxr-xr-x | test/layoutengine/standard-testcases/block_uax14_linebreaking.xml | 188 | ||||
-rw-r--r-- | test/layoutengine/standard-testcases/block_white-space_4.xml | 272 | ||||
-rw-r--r-- | test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml | 24 |
43 files changed, 2557 insertions, 592 deletions
@@ -162,6 +162,7 @@ list of possible build targets. <property name="src.dir" value="${basedir}/src"/> <property name="src.codegen.dir" value="${src.dir}/codegen"/> + <property name="src.codegen.fonts.dir" value="${src.codegen.dir}/fonts"/> <property name="src.java.dir" value="${src.dir}/java"/> <property name="src.sandbox.dir" value="${src.dir}/sandbox"/> <property name="src.viewer.resources.dir" value="${src.java.dir}/org/apache/fop/render/awt/viewer/resources"/> @@ -178,6 +179,7 @@ list of possible build targets. <property name="build.gensrc.dir" value="${build.dir}/gensrc"/> <property name="build.classes.dir" value="${build.dir}/classes"/> <property name="build.sandbox-classes.dir" value="${build.dir}/sandbox-classes"/> + <property name="build.codegen-classes.dir" value="${build.dir}/codegen-classes"/> <property name="build.javadocs.dir" value="${build.dir}/javadocs"/> <property name="build.examples.dir" value="${build.dir}/examples"/> @@ -319,69 +321,69 @@ list of possible build targets. <mkdir dir="${build.gensrc.dir}"/> <mkdir dir="${build.gensrc.dir}/org/apache/fop/fonts/base14"/> - <style in="${src.codegen.dir}/encodings.xml" - style="${src.codegen.dir}/code-point-mapping.xsl" + <style in="${src.codegen.fonts.dir}/encodings.xml" + style="${src.codegen.fonts.dir}/code-point-mapping.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/CodePointMapping.java"/> <!-- Task unrolled because of a bug in Xalan included in some JDK 1.4 releases <style basedir="src/codegen" includes="Helvetica*.xml,Times*.xml,Courier*.xml" - style="${src.codegen.dir}/font-file.xsl" + style="${src.codegen.fonts.dir}/font-file.xsl" destdir="${build.gensrc.dir}/org/apache/fop/fonts/base14" extension=".java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> --> - <style in="${src.codegen.dir}/Courier.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/Courier.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/Courier.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/CourierOblique.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/CourierOblique.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/CourierOblique.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/CourierBold.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/CourierBold.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/CourierBold.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/CourierBoldOblique.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/CourierBoldOblique.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/CourierBoldOblique.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/Helvetica.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/Helvetica.xml" style="${src.codegen.fonts.dir}/font-file.xsl" destdir="${build.gensrc.dir}/org/apache/fop/fonts/base14" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/Helvetica.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/HelveticaBold.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/HelveticaBold.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/HelveticaBold.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/HelveticaOblique.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/HelveticaOblique.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/HelveticaOblique.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/HelveticaBoldOblique.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/HelveticaBoldOblique.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/HelveticaBoldOblique.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/TimesRoman.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/TimesRoman.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/TimesRoman.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/TimesItalic.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/TimesItalic.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/TimesItalic.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/TimesBold.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/TimesBold.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/TimesBold.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/TimesBoldItalic.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/TimesBoldItalic.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/TimesBoldItalic.java"> <param name="encoding" expression="WinAnsiEncoding"/> </style> - <style in="${src.codegen.dir}/Symbol.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/Symbol.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/Symbol.java"/> - <style in="${src.codegen.dir}/ZapfDingbats.xml" style="${src.codegen.dir}/font-file.xsl" + <style in="${src.codegen.fonts.dir}/ZapfDingbats.xml" style="${src.codegen.fonts.dir}/font-file.xsl" out="${build.gensrc.dir}/org/apache/fop/fonts/base14/ZapfDingbats.java"/> </target> @@ -901,7 +903,26 @@ list of possible build targets. </junit> </target> - <target name="junit" depends="junit-basic, junit-transcoder, junit-layout, junit-fotree, junit-intermediate-format" description="Runs all of FOP's JUnit tests" if="junit.present"> + <target name="junit-text-linebreak" depends="junit-compile" description="Runs FOP's JUnit unicode linebreak tests" if="junit.present"> + <echo message="Running tests for Unicode UAX#14 support"/> + <junit dir="${basedir}" haltonfailure="${junit.haltonfailure}" fork="${junit.fork}" errorproperty="fop.junit.error" failureproperty="fop.junit.failure"> + <sysproperty key="basedir" value="${basedir}"/> + <sysproperty key="jawa.awt.headless" value="true"/> + <formatter type="brief" usefile="false"/> + <formatter type="plain" usefile="true"/> + <formatter type="xml" usefile="true"/> + <classpath> + <pathelement location="${build.dir}/test-classes"/> + <path refid="libs-build-classpath"/> + <fileset dir="build"> + <include name="fop.jar"/> + </fileset> + </classpath> + <test name="org.apache.fop.text.linebreak.LineBreakStatusTest" todir="${junit.reports.dir}"/> + </junit> + </target> + + <target name="junit" depends="junit-basic, junit-transcoder, junit-text-linebreak, junit-layout, junit-fotree, junit-intermediate-format" description="Runs all of FOP's JUnit tests" if="junit.present"> <fail> <condition> <or> @@ -1260,14 +1281,30 @@ NOTE: <!-- and may have updates that will *not* be generated by below. This --> <!-- target should never be part of the normal build process. --> <!-- =================================================================== --> - <target name="xsltToJava" > - <style in="src\codegen\constants.xml" style="src\codegen\constants.xsl" + <target name="codegen-fo" > + <style in="${src.codegen.dir}/fo/constants.xml" style="${src.codegen.dir}/fo/constants.xsl" out="Constants.java"/> - <style in="src/codegen/foelements.xml" style="src/codegen/property-sets.xsl" + <style in="${src.codegen.dir}/fo/foelements.xml" style="${src.codegen.dir}/fo/property-sets.xsl" out="PropertySets.java"/> </target> <!-- =================================================================== --> + <!-- Helper task to generate source files that have already been --> + <!-- checked into CVS. For these files, CVS version is the official one --> + <!-- and may have updates that will *not* be generated by below. This --> + <!-- target should never be part of the normal build process. --> + <!-- =================================================================== --> + <target name="codegen-unicode" > + <mkdir dir="${build.codegen-classes.dir}"/> + <javac destdir="${build.codegen-classes.dir}" fork="${javac.fork}" debug="${javac.debug}" + deprecation="${javac.deprecation}" optimize="${javac.optimize}" + source="${javac.source}" target="${javac.target}"> + <src path="${src.codegen.dir}/unicode/java"/> + </javac> + <java classname="org.apache.fop.text.linebreak.GenerateLineBreakUtils" classpath="${build.codegen-classes.dir}" /> + </target> + + <!-- =================================================================== --> <!-- Special target for Gump --> <!-- =================================================================== --> <target name="gump" depends="all, javadocs"/> diff --git a/src/codegen/colorkw.xml b/src/codegen/fo/colorkw.xml index 0a0c2717d..0a0c2717d 100644 --- a/src/codegen/colorkw.xml +++ b/src/codegen/fo/colorkw.xml diff --git a/src/codegen/constants.xml b/src/codegen/fo/constants.xml index d477506bb..d477506bb 100644 --- a/src/codegen/constants.xml +++ b/src/codegen/fo/constants.xml diff --git a/src/codegen/constants.xsl b/src/codegen/fo/constants.xsl index af51489af..af51489af 100644 --- a/src/codegen/constants.xsl +++ b/src/codegen/fo/constants.xsl diff --git a/src/codegen/fo-property-mapping.xsl b/src/codegen/fo/fo-property-mapping.xsl index 408144a36..408144a36 100644 --- a/src/codegen/fo-property-mapping.xsl +++ b/src/codegen/fo/fo-property-mapping.xsl diff --git a/src/codegen/foelements.xml b/src/codegen/fo/foelements.xml index db1360aab..db1360aab 100644 --- a/src/codegen/foelements.xml +++ b/src/codegen/fo/foelements.xml diff --git a/src/codegen/foproperties.xml b/src/codegen/fo/foproperties.xml index f4a19eb27..f4a19eb27 100644 --- a/src/codegen/foproperties.xml +++ b/src/codegen/fo/foproperties.xml diff --git a/src/codegen/properties.dtd b/src/codegen/fo/properties.dtd index 8ae36acb0..8ae36acb0 100644 --- a/src/codegen/properties.dtd +++ b/src/codegen/fo/properties.dtd diff --git a/src/codegen/property-sets.xsl b/src/codegen/fo/property-sets.xsl index 761a2cd23..761a2cd23 100644 --- a/src/codegen/property-sets.xsl +++ b/src/codegen/fo/property-sets.xsl diff --git a/src/codegen/propinc.xsl b/src/codegen/fo/propinc.xsl index 9f9adf9ef..9f9adf9ef 100644 --- a/src/codegen/propinc.xsl +++ b/src/codegen/fo/propinc.xsl diff --git a/src/codegen/propmaker.xsl b/src/codegen/fo/propmaker.xsl index 21cde4c53..21cde4c53 100644 --- a/src/codegen/propmaker.xsl +++ b/src/codegen/fo/propmaker.xsl diff --git a/src/codegen/Courier.xml b/src/codegen/fonts/Courier.xml index 89c7314db..89c7314db 100644 --- a/src/codegen/Courier.xml +++ b/src/codegen/fonts/Courier.xml diff --git a/src/codegen/CourierBold.xml b/src/codegen/fonts/CourierBold.xml index 92a777a50..92a777a50 100644 --- a/src/codegen/CourierBold.xml +++ b/src/codegen/fonts/CourierBold.xml diff --git a/src/codegen/CourierBoldOblique.xml b/src/codegen/fonts/CourierBoldOblique.xml index 914fdab84..914fdab84 100644 --- a/src/codegen/CourierBoldOblique.xml +++ b/src/codegen/fonts/CourierBoldOblique.xml diff --git a/src/codegen/CourierOblique.xml b/src/codegen/fonts/CourierOblique.xml index 3b043c17c..3b043c17c 100644 --- a/src/codegen/CourierOblique.xml +++ b/src/codegen/fonts/CourierOblique.xml diff --git a/src/codegen/Helvetica.xml b/src/codegen/fonts/Helvetica.xml index d63eb5a11..d63eb5a11 100644 --- a/src/codegen/Helvetica.xml +++ b/src/codegen/fonts/Helvetica.xml diff --git a/src/codegen/HelveticaBold.xml b/src/codegen/fonts/HelveticaBold.xml index c417937b4..c417937b4 100644 --- a/src/codegen/HelveticaBold.xml +++ b/src/codegen/fonts/HelveticaBold.xml diff --git a/src/codegen/HelveticaBoldOblique.xml b/src/codegen/fonts/HelveticaBoldOblique.xml index 087b225e4..087b225e4 100644 --- a/src/codegen/HelveticaBoldOblique.xml +++ b/src/codegen/fonts/HelveticaBoldOblique.xml diff --git a/src/codegen/HelveticaOblique.xml b/src/codegen/fonts/HelveticaOblique.xml index d913b6d51..d913b6d51 100644 --- a/src/codegen/HelveticaOblique.xml +++ b/src/codegen/fonts/HelveticaOblique.xml diff --git a/src/codegen/Symbol.xml b/src/codegen/fonts/Symbol.xml index 241d4d2c6..241d4d2c6 100644 --- a/src/codegen/Symbol.xml +++ b/src/codegen/fonts/Symbol.xml diff --git a/src/codegen/TimesBold.xml b/src/codegen/fonts/TimesBold.xml index 12bb17580..12bb17580 100644 --- a/src/codegen/TimesBold.xml +++ b/src/codegen/fonts/TimesBold.xml diff --git a/src/codegen/TimesBoldItalic.xml b/src/codegen/fonts/TimesBoldItalic.xml index 540e891e1..540e891e1 100644 --- a/src/codegen/TimesBoldItalic.xml +++ b/src/codegen/fonts/TimesBoldItalic.xml diff --git a/src/codegen/TimesItalic.xml b/src/codegen/fonts/TimesItalic.xml index 4868aed05..4868aed05 100644 --- a/src/codegen/TimesItalic.xml +++ b/src/codegen/fonts/TimesItalic.xml diff --git a/src/codegen/TimesRoman.xml b/src/codegen/fonts/TimesRoman.xml index 1f21290de..1f21290de 100644 --- a/src/codegen/TimesRoman.xml +++ b/src/codegen/fonts/TimesRoman.xml diff --git a/src/codegen/ZapfDingbats.xml b/src/codegen/fonts/ZapfDingbats.xml index 0420908a0..0420908a0 100644 --- a/src/codegen/ZapfDingbats.xml +++ b/src/codegen/fonts/ZapfDingbats.xml diff --git a/src/codegen/charlist.xml b/src/codegen/fonts/charlist.xml index 110714af6..110714af6 100644 --- a/src/codegen/charlist.xml +++ b/src/codegen/fonts/charlist.xml diff --git a/src/codegen/code-point-mapping.xsl b/src/codegen/fonts/code-point-mapping.xsl index 7d0d6cd71..7d0d6cd71 100644 --- a/src/codegen/code-point-mapping.xsl +++ b/src/codegen/fonts/code-point-mapping.xsl diff --git a/src/codegen/encodings.xml b/src/codegen/fonts/encodings.xml index 85aabb21f..85aabb21f 100644 --- a/src/codegen/encodings.xml +++ b/src/codegen/fonts/encodings.xml diff --git a/src/codegen/font-file.xsl b/src/codegen/fonts/font-file.xsl index 72ee81a68..72ee81a68 100644 --- a/src/codegen/font-file.xsl +++ b/src/codegen/fonts/font-file.xsl diff --git a/src/codegen/glyphlist.xml b/src/codegen/fonts/glyphlist.xml index aeb56e2b6..aeb56e2b6 100644 --- a/src/codegen/glyphlist.xml +++ b/src/codegen/fonts/glyphlist.xml diff --git a/src/codegen/t1font-file.xsl b/src/codegen/fonts/t1font-file.xsl index f5c285097..f5c285097 100644 --- a/src/codegen/t1font-file.xsl +++ b/src/codegen/fonts/t1font-file.xsl diff --git a/src/codegen/ttffontfile.xsl b/src/codegen/fonts/ttffontfile.xsl index 7231010bf..7231010bf 100644 --- a/src/codegen/ttffontfile.xsl +++ b/src/codegen/fonts/ttffontfile.xsl diff --git a/src/codegen/unicode/data/LineBreakPairTable.txt b/src/codegen/unicode/data/LineBreakPairTable.txt new file mode 100755 index 000000000..93388e1bd --- /dev/null +++ b/src/codegen/unicode/data/LineBreakPairTable.txt @@ -0,0 +1,28 @@ + OP CL QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT +OP ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ @ ^ ^ ^ ^ ^ ^ +CL _ ^ % % ^ ^ ^ ^ % % % % _ _ % % _ _ ^ # ^ _ _ _ _ _ +QU ^ ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % +GL % ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % +NS _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +EX _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +SY _ ^ % % % ^ ^ ^ _ _ % _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +IS _ ^ % % % ^ ^ ^ _ _ % % _ _ % % _ _ ^ # ^ _ _ _ _ _ +PR % ^ % % % ^ ^ ^ _ _ % % % _ % % _ _ ^ # ^ % % % % % +PO % ^ % % % ^ ^ ^ _ _ % % _ _ % % _ _ ^ # ^ _ _ _ _ _ +NU % ^ % % % ^ ^ ^ % % % % _ % % % _ _ ^ # ^ _ _ _ _ _ +AL % ^ % % % ^ ^ ^ _ _ % % _ % % % _ _ ^ # ^ _ _ _ _ _ +ID _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ _ _ +IN _ ^ % % % ^ ^ ^ _ _ _ _ _ % % % _ _ ^ # ^ _ _ _ _ _ +HY _ ^ % % % ^ ^ ^ _ _ % _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +BA _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +BB % ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % +B2 _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ ^ ^ # ^ _ _ _ _ _ +ZW _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ^ _ _ _ _ _ _ _ +CM _ ^ % % % ^ ^ ^ _ _ % % _ % % % _ _ ^ # ^ _ _ _ _ _ +WJ % ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % +H2 _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ % % +H3 _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ _ % +JL _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ % % % % _ +JV _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ % % +JT _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ _ % + diff --git a/src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java b/src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java new file mode 100644 index 000000000..b956cabff --- /dev/null +++ b/src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java @@ -0,0 +1,659 @@ +/* + * 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.text.linebreak; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * <p>Utility for generating a Java class representing line break properties + * from the Unicode property files.</p> + * <p>Customizations: + * <ul> + * <li>The pair table file is a cut+paste of the sample table from the TR14 + * HTML file into a text file.</li> + * <li>Because the sample table does not cover all line break classes, check the + * 'not in pair table' list of property value short names.</li> + * <li>Check MAX_LINE_LENGTH.</li> + * </ul> + * + */ +public class GenerateLineBreakUtils { + + private static final int MAX_LINE_LENGTH = 110; + + private static final byte DIRECT_BREAK = 0; // _ in table + private static final byte INDIRECT_BREAK = 1; // % in table + private static final byte COMBINING_INDIRECT_BREAK = 2; // # in table + private static final byte COMBINING_PROHIBITED_BREAK = 3; // @ in table + private static final byte PROHIBITED_BREAK = 4; // ^ in table + private static final byte EXPLICIT_BREAK = 5; // ! in rules + private static final String notInPairTable[] = { "AI", "BK", "CB", "CR", "LF", "NL", "SA", "SG", "SP", "XX" }; + + private static final byte lineBreakProperties[] = new byte[0x10000]; + private static final Map lineBreakPropertyValues = new HashMap(); + private static final List lineBreakPropertyShortNames = new ArrayList(); + private static final List lineBreakPropertyLongNames = new ArrayList(); + + /** + * Generate a class managing line break properties for Unicode characters and a sample + * table for the table driven line breaking algorithm described in + * <a href="http://unicode.org/reports/tr14/#PairBasedImplementation">UTR #14</a>. + * TODO: Code points above the base plane are simply ignored. + * + * @param lineBreakFileName Name of line break property file (part of Unicode files). + * @param propertyValueFileName Name of property values alias file (part of Unicode files). + * @param breakPairFileName Name of pair table file (<i>not</i> part of the unicode files). + * @param outFileName Name of the output file. + * @throws Exception in case anything goes wrong. + */ + private static void convertLineBreakProperties( + String lineBreakFileName, + String propertyValueFileName, + String breakPairFileName, + String outFileName) + throws Exception { + + readLineBreakProperties(lineBreakFileName, propertyValueFileName); + // read break pair table + int lineBreakPropertyValueCount = lineBreakPropertyValues.size(); + int tableSize = lineBreakPropertyValueCount - notInPairTable.length; + Map notInPairTableMap = new HashMap(notInPairTable.length); + for (int i = 0; i < notInPairTable.length; i++) { + Object v = lineBreakPropertyValues.get(notInPairTable[i]); + if (v == null) { + throw new Exception("'not in pair table' property not found: " + notInPairTable[i]); + } + notInPairTableMap.put(notInPairTable[i], v); + } + byte pairTable[][] = new byte[tableSize][]; + byte columnHeader[] = new byte[tableSize]; + byte rowHeader[] = new byte[tableSize]; + byte columnMap[] = new byte[lineBreakPropertyValueCount + 1]; + Arrays.fill(columnMap, (byte)255); + byte rowMap[] = new byte[lineBreakPropertyValueCount + 1]; + Arrays.fill(rowMap, (byte)255); + BufferedReader b = new BufferedReader(new FileReader(breakPairFileName)); + String line = b.readLine(); + int lineNumber = 1; + // read header + if (line != null) { + StringTokenizer tok = new StringTokenizer(line); + byte columnNumber = 0; + while (tok.hasMoreTokens()) { + String name = tok.nextToken(); + if (columnNumber >= columnHeader.length) { + throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected column header " + name); + } + if (notInPairTableMap.get(name) != null) { + throw new Exception(breakPairFileName + ':' + lineNumber + ": invalid column header " + name); + } + Byte v = (Byte)lineBreakPropertyValues.get(name); + if (v != null) { + byte vv = v.byteValue(); + columnHeader[columnNumber] = vv; + columnMap[vv] = columnNumber; + } else { + throw new Exception(breakPairFileName + ':' + lineNumber + ": unknown column header " + name); + } + columnNumber++; + } + if (columnNumber < columnHeader.length) { + StringBuffer missing = new StringBuffer(); + for (int j = 0; j < lineBreakPropertyShortNames.size(); j++) { + boolean found = false; + for (int k = 0; k < columnNumber; k++) { + if (columnHeader[k] == j + 1) { + found = true; + break; + } + } + if (!found) { + if (missing.length() > 0) { + missing.append(", "); + } + missing.append((String)lineBreakPropertyShortNames.get(j)); + } + } + throw new Exception( + breakPairFileName + ':' + lineNumber + ": missing column for properties: " + missing.toString()); + } + } else { + throw new Exception(breakPairFileName + ':' + lineNumber + ": can't read table header"); + } + line = b.readLine().trim(); + lineNumber++; + byte rowNumber = 0; + while (line != null && line.length() > 0) { + if (rowNumber >= rowHeader.length) { + throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected row " + line); + } + pairTable[rowNumber] = new byte[tableSize]; + StringTokenizer tok = new StringTokenizer(line); + if (tok.hasMoreTokens()) { + String name = tok.nextToken(); + if (notInPairTableMap.get(name) != null) { + throw new Exception(breakPairFileName + ':' + lineNumber + ": invalid row header " + name); + } + Byte v = (Byte)lineBreakPropertyValues.get(name); + if (v != null) { + byte vv = v.byteValue(); + rowHeader[rowNumber] = vv; + rowMap[vv] = rowNumber; + } else { + throw new Exception(breakPairFileName + ':' + lineNumber + ": unknown row header " + name); + } + } else { + throw new Exception(breakPairFileName + ':' + lineNumber + ": can't read row header"); + } + int columnNumber = 0; + while (tok.hasMoreTokens()) { + String token = tok.nextToken(); + if (token.length() == 1) { + switch (token.charAt(0)) { + case '^' : + pairTable[rowNumber][columnNumber] = PROHIBITED_BREAK; + break; + case '%' : + pairTable[rowNumber][columnNumber] = INDIRECT_BREAK; + break; + case '_' : + pairTable[rowNumber][columnNumber] = DIRECT_BREAK; + break; + case '#' : + pairTable[rowNumber][columnNumber] = COMBINING_INDIRECT_BREAK; + break; + case '@' : + pairTable[rowNumber][columnNumber] = COMBINING_PROHIBITED_BREAK; + break; + default : + throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected token: " + token); + } + } else { + throw new Exception(breakPairFileName + ':' + lineNumber + ": token too long: " + token); + } + columnNumber++; + } + line = b.readLine().trim(); + lineNumber++; + rowNumber++; + } + if (rowNumber < rowHeader.length) { + StringBuffer missing = new StringBuffer(); + for (int j = 0; j < lineBreakPropertyShortNames.size(); j++) { + boolean found = false; + for (int k = 0; k < rowNumber; k++) { + if (rowHeader[k] == j + 1) { + found = true; + break; + } + } + if (!found) { + if (missing.length() > 0) { + missing.append(", "); + } + missing.append((String)lineBreakPropertyShortNames.get(j)); + } + } + throw new Exception( + breakPairFileName + ':' + lineNumber + ": missing row for properties: " + missing.toString()); + } + + // generate class + int rowsize = 512; + int blocksize = lineBreakProperties.length / rowsize; + byte row[][] = new byte[rowsize][]; + int idx = 0; + StringBuffer doStaticLinkCode = new StringBuffer(); + PrintWriter out = new PrintWriter(new FileWriter(outFileName)); + out.println("/*"); + out.println(" * Licensed to the Apache Software Foundation (ASF) under one or more"); + out.println(" * contributor license agreements. See the NOTICE file distributed with"); + out.println(" * this work for additional information regarding copyright ownership."); + out.println(" * The ASF licenses this file to You under the Apache License, Version 2.0"); + out.println(" * (the \"License\"); you may not use this file except in compliance with"); + out.println(" * the License. You may obtain a copy of the License at"); + out.println(" * "); + out.println(" * http://www.apache.org/licenses/LICENSE-2.0"); + out.println(" * "); + out.println(" * Unless required by applicable law or agreed to in writing, software"); + out.println(" * distributed under the License is distributed on an \"AS IS\" BASIS,"); + out.println(" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied."); + out.println(" * See the License for the specific language governing permissions and"); + out.println(" * limitations under the License."); + out.println(" */"); + out.println(); + out.println("/* $Id$ */"); + out.println(); + out.println("package org.apache.commons.text.linebreak;"); + out.println(); + out.println("/* "); + out.println(" * This is a generated file, DO NOT CHANGE!"); + out.println(" */"); + out.println(); + out.println("class LineBreakUtils {"); + out.println(); + out.println(" public static final byte DIRECT_BREAK = " + DIRECT_BREAK + ';'); + out.println(" public static final byte INDIRECT_BREAK = " + INDIRECT_BREAK + ';'); + out.println(" public static final byte COMBINING_INDIRECT_BREAK = " + COMBINING_INDIRECT_BREAK + ';'); + out.println(" public static final byte COMBINING_PROHIBITED_BREAK = " + COMBINING_PROHIBITED_BREAK + ';'); + out.println(" public static final byte PROHIBITED_BREAK = " + PROHIBITED_BREAK + ';'); + out.println(" public static final byte EXPLICIT_BREAK = " + EXPLICIT_BREAK + ';'); + out.println(); + out.println(" private static final byte PAIR_TABLE[][] = {"); + boolean printComma = false; + for (int i = 1; i <= lineBreakPropertyValueCount; i++) { + if (printComma) { + out.println(','); + } else { + printComma = true; + } + out.print(" {"); + boolean localPrintComma = false; + for (int j = 1; j <= lineBreakPropertyValueCount; j++) { + if (localPrintComma) { + out.print(','); + } else { + localPrintComma = true; + } + if (columnMap[j] != -1 && rowMap[i] != -1) { + out.print(pairTable[rowMap[i]][columnMap[j]]); + } else { + out.print('0'); + } + } + out.print('}'); + } + out.println("};"); + out.println(); + out.println(" private static byte lineBreakProperties[][] = new byte[" + rowsize + "][];"); + out.println(); + out.println(" private static void init_0() {"); + int rowsPrinted = 0; + int initSections = 0; + for (int i = 0; i < rowsize; i++) { + boolean found = false; + for (int j = 0; j < i; j++) { + if (row[j] != null) { + boolean matched = true; + for (int k = 0; k < blocksize; k++) { + if (row[j][k] != lineBreakProperties[idx + k]) { + matched = false; + break; + } + } + if (matched) { + found = true; + doStaticLinkCode.append(" lineBreakProperties["); + doStaticLinkCode.append(i); + doStaticLinkCode.append("]=lineBreakProperties["); + doStaticLinkCode.append(j); + doStaticLinkCode.append("];\n"); + break; + } + } + } + if (!found) { + if (rowsPrinted >= 64) { + out.println(" };"); + out.println(); + initSections++; + out.println(" private static void init_" + initSections + "() {"); + rowsPrinted = 0; + } + row[i] = new byte[blocksize]; + boolean printLocalComma = false; + out.print(" lineBreakProperties[" + i + "] = new byte[] { "); + for (int k = 0; k < blocksize; k++) { + row[i][k] = lineBreakProperties[idx + k]; + if (printLocalComma) { + out.print(','); + } else { + printLocalComma = true; + } + out.print(row[i][k]); + } + out.println("};"); + rowsPrinted++; + } + idx += blocksize; + } + out.println(" };"); + out.println(); + out.println(" static {"); + for (int i = 0; i <= initSections; i++) { + out.println(" init_" + i + "();"); + } + out.print(doStaticLinkCode); + out.println(" };"); + out.println(); + for (int i = 0; i < lineBreakPropertyShortNames.size(); i++) { + String shortName = (String)lineBreakPropertyShortNames.get(i); + out.print(" public static final byte LINE_BREAK_PROPERTY_"); + out.print(shortName); + out.print('='); + out.print(i + 1); + out.println(';'); + } + out.println(); + final String shortNamePrefix = " private static String lineBreakPropertyShortNames[] = {"; + out.print(shortNamePrefix); + int lineLength = shortNamePrefix.length(); + printComma = false; + for (int i = 0; i < lineBreakPropertyShortNames.size(); i++) { + String name = (String)lineBreakPropertyShortNames.get(i); + if (printComma) { + out.print(','); + lineLength++; + } else { + printComma = true; + } + if (lineLength > MAX_LINE_LENGTH) { + out.println(); + out.print(" "); + lineLength = 8; + } + out.print('"'); + out.print(name); + out.print('"'); + lineLength += (2 + name.length()); + } + out.println("};"); + out.println(); + final String longNamePrefix = " private static String lineBreakPropertyLongNames[] = {"; + out.print(longNamePrefix); + lineLength = longNamePrefix.length(); + printComma = false; + for (int i = 0; i < lineBreakPropertyLongNames.size(); i++) { + String name = (String)lineBreakPropertyLongNames.get(i); + if (printComma) { + out.print(','); + lineLength++; + } else { + printComma = true; + } + if (lineLength > MAX_LINE_LENGTH) { + out.println(); + out.print(" "); + lineLength = 8; + } + out.print('"'); + out.print(name); + out.print('"'); + lineLength += (2 + name.length()); + } + out.println("};"); + out.println(); + out.println(" public static String getLineBreakPropertyShortName(byte i) {"); + out.println(" if (i>0 && i<=lineBreakPropertyShortNames.length) {"); + out.println(" return lineBreakPropertyShortNames[i-1];"); + out.println(" } else {"); + out.println(" return null;"); + out.println(" }"); + out.println(" }"); + out.println(); + out.println(" public static String getLineBreakPropertyLongName(byte i) {"); + out.println(" if (i>0 && i<=lineBreakPropertyLongNames.length) {"); + out.println(" return lineBreakPropertyLongNames[i-1];"); + out.println(" } else {"); + out.println(" return null;"); + out.println(" }"); + out.println(" }"); + out.println(); + out.println(" public static byte getLineBreakProperty(char c) {"); + out.println(" return lineBreakProperties[c/" + blocksize + "][c%" + blocksize + "];"); + out.println(" }"); + out.println(); + out.println( + " public static byte getLineBreakPairProperty(int lineBreakPropertyBefore,int lineBreakPropertyAfter) {"); + out.println(" return PAIR_TABLE[lineBreakPropertyBefore-1][lineBreakPropertyAfter-1];"); + out.println(" }"); + out.println(); + out.println("};"); + out.flush(); + out.close(); + } + + /** + * Read line break property value names and the actual properties for the Unicode + * characters from the respective Unicode files. + * TODO: Code points above the base plane are simply ignored. + * + * @param lineBreakFileName Name of line break property file. + * @param propertyValueFileName Name of property values alias file. + * @throws Exception in case anything goes wrong. + */ + private static void readLineBreakProperties(String lineBreakFileName, String propertyValueFileName) + throws Exception { + // read property names + BufferedReader b = new BufferedReader(new InputStreamReader(new URL(propertyValueFileName).openStream())); + String line = b.readLine(); + int lineNumber = 1; + byte propertyIndex = 1; + byte indexForUnknown = 0; + while (line != null) { + if (line.startsWith("lb")) { + String shortName; + String longName = null; + int semi = line.indexOf(';'); + if (semi < 0) { + throw new Exception( + propertyValueFileName + ':' + lineNumber + ": missing property short name in " + line); + } + line = line.substring(semi + 1); + semi = line.indexOf(';'); + if (semi > 0) { + shortName = line.substring(0, semi).trim(); + longName = line.substring(semi + 1).trim(); + semi = longName.indexOf(';'); + if (semi > 0) { + longName = longName.substring(0, semi).trim(); + } + } else { + shortName = line.trim(); + } + if (shortName.equals("XX")) { + indexForUnknown = propertyIndex; + } + lineBreakPropertyValues.put(shortName, new Byte((byte)propertyIndex)); + lineBreakPropertyShortNames.add(shortName); + lineBreakPropertyLongNames.add(longName); + propertyIndex++; + if (propertyIndex <= 0) { + throw new Exception(propertyValueFileName + ':' + lineNumber + ": property rolled over in " + line); + } + } + line = b.readLine(); + lineNumber++; + } + if (indexForUnknown == 0) { + throw new Exception("index for XX (unknown) line break property value not found"); + } + + // read property values + Arrays.fill(lineBreakProperties, (byte)0); + b = new BufferedReader(new InputStreamReader(new URL(lineBreakFileName).openStream())); + line = b.readLine(); + lineNumber = 1; + while (line != null) { + int idx = line.indexOf('#'); + if (idx >= 0) { + line = line.substring(0, idx); + } + line = line.trim(); + if (line.length() > 0) { + idx = line.indexOf(';'); + if (idx <= 0) { + throw new Exception(lineBreakFileName + ':' + lineNumber + ": No field delimiter in " + line); + } + Byte v = (Byte)lineBreakPropertyValues.get(line.substring(idx + 1).trim()); + if (v == null) { + throw new Exception(lineBreakFileName + ':' + lineNumber + ": Unknown property value in " + line); + } + String codepoint = line.substring(0, idx); + int low, high; + idx = codepoint.indexOf(".."); + try { + if (idx >= 0) { + low = Integer.parseInt(codepoint.substring(0, idx), 16); + high = Integer.parseInt(codepoint.substring(idx + 2), 16); + } else { + low = Integer.parseInt(codepoint, 16); + high = low; + } + } catch (NumberFormatException e) { + throw new Exception(lineBreakFileName + ':' + lineNumber + ": Invalid codepoint number in " + line); + } + if (high > 0xFFFF) { + // ignore non-baseplane characters for now + + } else { + if (low < 0 || high < 0) { + throw new Exception( + lineBreakFileName + ':' + lineNumber + ": Negative codepoint(s) in " + line); + } + byte vv = v.byteValue(); + for (int i = low; i <= high; i++) { + if (lineBreakProperties[i] != 0) { + throw new Exception( + lineBreakFileName + + ':' + + lineNumber + + ": Property already set for " + + ((char)i) + + " in " + + line); + } + lineBreakProperties[i] = vv; + } + } + } + line = b.readLine(); + lineNumber++; + } + } + + /** + * Determine a good block size for the two stage optimized storage of the + * line breaking properties. Note: the memory utilization calculation is a rule of thumb, + * don't take it too serious. + * + * @param lineBreakFileName Name of line break property file. + * @param propertyValueFileName Name of property values alias file. + * @throws Exception in case anything goes wrong. + */ + private static void optimizeBlocks(String lineBreakFileName, String propertyValueFileName) throws Exception { + readLineBreakProperties(lineBreakFileName, propertyValueFileName); + for (int i = 0; i < 16; i++) { + int rowsize = 1 << i; + int blocksize = lineBreakProperties.length / (rowsize); + byte row[][] = new byte[rowsize][]; + int idx = 0; + int nrOfDistinctBlocks = 0; + for (int j = 0; j < rowsize; j++) { + byte block[] = new byte[blocksize]; + for (int k = 0; k < blocksize; k++) { + block[k] = lineBreakProperties[idx]; + idx++; + } + boolean found = false; + for (int k = 0; k < j; k++) { + if (row[k] != null) { + boolean matched = true; + for (int l = 0; l < blocksize; l++) { + if (row[k][l] != block[l]) { + matched = false; + break; + } + } + if (matched) { + found = true; + break; + } + } + } + if (!found) { + row[j] = block; + nrOfDistinctBlocks++; + } else { + row[j] = null; + } + } + int size = rowsize * 4 + nrOfDistinctBlocks * blocksize; + System.out.println( + "i=" + i + " blocksize=" + blocksize + " blocks=" + nrOfDistinctBlocks + " size=" + size); + } + } + + public static void main(String[] args) { + String lineBreakFileName = "http://www.unicode.org/Public/UNIDATA/LineBreak.txt"; + String propertyValueFileName = "http://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt"; + String breakPairFileName = "src/codegen/unicode/data/LineBreakPairTable.txt"; + String outFileName = "LineBreakUtils.java"; + boolean ok = true; + for (int i = 0; i < args.length; i = i + 2) { + if (i + 1 == args.length) { + ok = false; + } else { + String opt = args[i]; + if ("-l".equals(opt)) { + lineBreakFileName = args[i+1]; + } else if ("-p".equals(opt)) { + propertyValueFileName = args[i+1]; + } else if ("-b".equals(opt)) { + breakPairFileName = args[i+1]; + } else if("-o".equals(opt)) { + outFileName = args[i+1]; + } else { + ok = false; + } + } + } + if (!ok) { + System.out.println("Usage: GenerateLineBreakUtils [-l <lineBreakFile>] [-p <propertyValueFile>] [-b <breakPairFile>] [-o <outputFile>]"); + System.out.println(" defaults:"); + System.out.println(" <lineBreakFile>: " + lineBreakFileName); + System.out.println(" <propertyValueFile>: " + propertyValueFileName); + System.out.println(" <breakPairFile>: " + breakPairFileName); + System.out.println(" <outputFile>: " + outFileName); + } else { + try { + convertLineBreakProperties(lineBreakFileName, propertyValueFileName, breakPairFileName, outFileName); + System.out.println("Generated " + outFileName + " from"); + System.out.println(" <lineBreakFile>: " + lineBreakFileName); + System.out.println(" <propertyValueFile>: " + propertyValueFileName); + System.out.println(" <breakPairFile>: " + breakPairFileName); + } catch (Exception e) { + System.out.println("An unexpected error occured"); + e.printStackTrace(); + } + } + } +} diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index bfacc777b..28ec13b6b 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.List; import java.util.LinkedList; import java.util.ListIterator; +import java.util.NoSuchElementException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -43,6 +44,7 @@ import org.apache.fop.layoutmgr.LeafPosition; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; +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; @@ -543,133 +545,201 @@ public class TextLayoutManager extends LeafNodeLayoutManager { AreaInfo ai = null; returnList.add(sequence); + LineBreakStatus lbs = new LineBreakStatus(); + iThisStart = iNextStart; + boolean inWord = false; + boolean inWhitespace = false; + char ch = 0; while (iNextStart < textArray.length) { - char ch = textArray[iNextStart]; - if (ch == CharUtilities.SPACE - && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE) { - // normal non preserved space - collect them all - // advance to the next character - iThisStart = iNextStart; - iNextStart++; - while (iNextStart < textArray.length - && textArray[iNextStart] == CharUtilities.SPACE) { - iNextStart++; - } - // create the AreaInfo object - ai = new AreaInfo(iThisStart, (short) (iNextStart), - (short) (iNextStart - iThisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, iNextStart - iThisStart), - false, true); - vecAreaInfo.add(ai); + ch = textArray[iNextStart]; + boolean breakOpportunity = false; + byte breakAction = lbs.nextChar(ch); + switch (breakAction) { + case LineBreakStatus.COMBINING_PROHIBITED_BREAK: + case LineBreakStatus.PROHIBITED_BREAK: + break; + case LineBreakStatus.EXPLICIT_BREAK: + break; + case LineBreakStatus.COMBINING_INDIRECT_BREAK: + case LineBreakStatus.DIRECT_BREAK: + case LineBreakStatus.INDIRECT_BREAK: + breakOpportunity = true; + break; + default: + log.error("Unexpected breakAction: " + breakAction); + } + if (inWord) { + if (breakOpportunity || isSpace(ch) || ch == NEWLINE) { + //Word boundary found, process widths and kerning + int wordLength = iNextStart - iThisStart; + boolean kerning = font.hasKerning(); + MinOptMax wordIPD = new MinOptMax(0); + for (int i = iThisStart; i < iNextStart; i++) { + char c = textArray[i]; + + //character width + int charWidth = font.getCharWidth(c); + wordIPD.add(charWidth); + + //kerning + int kern = 0; + if (kerning && (i > iThisStart)) { + char previous = textArray[i - 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; + // if the last character is '-' or '/' 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 elements - sequence.addAll - (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1)); + // create the AreaInfo object + ai = new AreaInfo(iThisStart, iNextStart, (short) 0, + (short) iLetterSpaces, + wordIPD, false, false); + vecAreaInfo.add(ai); + iTempStart = iNextStart; - } else if (ch == CharUtilities.SPACE || ch == CharUtilities.NBSPACE) { + // create the elements + sequence.addAll(createElementsForAWordFragment(alignment, ai, + vecAreaInfo.size() - 1, letterSpaceIPD, breakOpportunity)); + ai = null; + + iThisStart = iNextStart; + } + } else if (inWhitespace) { + if (ch != CharUtilities.SPACE || breakOpportunity) { + // End of whitespace + // create the AreaInfo object + ai = new AreaInfo(iThisStart, (short) (iNextStart), + (short) (iNextStart - iThisStart), (short) 0, + MinOptMax.multiply(wordSpaceIPD, iNextStart - iThisStart), + false, true); + vecAreaInfo.add(ai); + + // create the elements + sequence.addAll + (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1, breakOpportunity)); + ai = null; + + iThisStart = iNextStart; + } + } else { + if (ai != null) { + vecAreaInfo.add(ai); + sequence.addAll + (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1, ch == CharUtilities.SPACE || breakOpportunity)); + ai = null; + } + if (breakAction == LineBreakStatus.EXPLICIT_BREAK) { + if (lineEndBAP != 0) { + sequence.add + (new KnuthGlue(lineEndBAP, 0, 0, + new LeafPosition(this, -1), true)); + } + sequence.endSequence(); + sequence = new InlineKnuthSequence(); + returnList.add(sequence); + } + } + + if (ch == CharUtilities.SPACE && foText.getWhitespaceTreatment() == Constants.EN_PRESERVE || ch == CharUtilities.NBSPACE) { // preserved space or non-breaking space: // create the AreaInfo object ai = new AreaInfo(iNextStart, (short) (iNextStart + 1), (short) 1, (short) 0, - wordSpaceIPD, false, true); - vecAreaInfo.add(ai); - - // create the elements - sequence.addAll - (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1)); - - // advance to the next character - iNextStart++; + wordSpaceIPD, false, true); + iThisStart = (short) (iNextStart + 1); } else if (CharUtilities.isFixedWidthSpace(ch)) { // create the AreaInfo object MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); ai = new AreaInfo(iNextStart, (short) (iNextStart + 1), (short) 0, (short) 0, ipd, false, true); - vecAreaInfo.add(ai); - - // create the elements - sequence.addAll - (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1)); - - // advance to the next character - iNextStart++; + iThisStart = (short) (iNextStart + 1); } else if (ch == NEWLINE) { // linefeed; this can happen when linefeed-treatment="preserve" - // add a penalty item to the list and start a new sequence - if (lineEndBAP != 0) { - sequence.add - (new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), true)); - } - sequence.endSequence(); - sequence = new InlineKnuthSequence(); - returnList.add(sequence); + iThisStart = (short) (iNextStart + 1); + } + inWord = !isSpace(ch) && ch != NEWLINE; + inWhitespace = ch == CharUtilities.SPACE && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; + iNextStart++; + } // end of while + + // Process any last elements + if (inWord) { + int wordLength = iNextStart - iThisStart; + boolean kerning = font.hasKerning(); + MinOptMax wordIPD = new MinOptMax(0); + for (int i = iThisStart; i < iNextStart; i++) { + char c = textArray[i]; - // advance to the next character - iNextStart++; - } else { - // the beginning of a word - iThisStart = iNextStart; - iTempStart = iNextStart; - for (; iTempStart < textArray.length - && !isSpace(textArray[iTempStart]) - && textArray[iTempStart] != NEWLINE - && !(iTempStart > iNextStart - && isBreakChar(textArray[iTempStart - 1])); - iTempStart++) { - //nop, just find the word boundary - } - - //Word boundary found, process widths and kerning - int wordLength = iTempStart - iThisStart; - boolean kerning = font.hasKerning(); - MinOptMax wordIPD = new MinOptMax(0); - for (int i = iThisStart; i < iTempStart; i++) { - char c = textArray[i]; - - //character width - int charWidth = font.getCharWidth(c); - wordIPD.add(charWidth); - - //kerning - int kern = 0; - if (kerning && (i > iThisStart)) { - char previous = textArray[i - 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); + //character width + int charWidth = font.getCharWidth(c); + wordIPD.add(charWidth); + + //kerning + int kern = 0; + if (kerning && (i > iThisStart)) { + char previous = textArray[i - 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; - // if the last character is '-' or '/' 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 (isBreakChar(textArray[iTempStart - 1]) - && iTempStart < textArray.length - && !isSpace(textArray[iTempStart])) { - iLetterSpaces++; - } - wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); - - // create the AreaInfo object - ai = new AreaInfo(iThisStart, iTempStart, (short) 0, - (short) iLetterSpaces, - wordIPD, false, false); - vecAreaInfo.add(ai); - - // create the elements - sequence.addAll(createElementsForAWordFragment(alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD)); - - // advance to the next character - iNextStart = iTempStart; } - } // end of while + int iLetterSpaces = wordLength - 1; + wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); + + // create the AreaInfo object + ai = new AreaInfo(iThisStart, iNextStart, (short) 0, + (short) iLetterSpaces, + wordIPD, false, false); + vecAreaInfo.add(ai); + iTempStart = iNextStart; + + // create the elements + sequence.addAll(createElementsForAWordFragment(alignment, ai, + vecAreaInfo.size() - 1, letterSpaceIPD, false)); + ai = null; + } else if (inWhitespace) { + ai = new AreaInfo(iThisStart, (short) (iNextStart), + (short) (iNextStart - iThisStart), (short) 0, + MinOptMax.multiply(wordSpaceIPD, iNextStart - iThisStart), + false, true); + vecAreaInfo.add(ai); + + // create the elements + sequence.addAll + (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1, true)); + ai = null; + } else if (ai != null) { + vecAreaInfo.add(ai); + sequence.addAll + (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1, ch == CharUtilities.ZERO_WIDTH_SPACE)); + ai = null; + } else if (ch == NEWLINE) { + if (lineEndBAP != 0) { + sequence.add + (new KnuthGlue(lineEndBAP, 0, 0, + new LeafPosition(this, -1), true)); + } + sequence.endSequence(); + sequence = new InlineKnuthSequence(); + returnList.add(sequence); + } + if (((List)returnList.getLast()).size() == 0) { //Remove an empty sequence because of a trailing newline returnList.removeLast(); @@ -872,11 +942,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (ai.iWScount == 0) { // ai refers either to a word or a word fragment returnList.addAll - (createElementsForAWordFragment(alignment, ai, iReturnedIndex, letterSpaceIPD)); + (createElementsForAWordFragment(alignment, ai, iReturnedIndex, letterSpaceIPD, false)); } else { // ai refers to a space returnList.addAll - (createElementsForASpace(alignment, ai, iReturnedIndex)); + (createElementsForASpace(alignment, ai, iReturnedIndex, textArray[ai.iStartIndex] == CharUtilities.SPACE)); } iReturnedIndex++; } // end of while @@ -896,13 +966,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } private LinkedList createElementsForASpace(int alignment, - AreaInfo ai, int leafValue) { + AreaInfo ai, int leafValue, boolean breakOpportunity) { LinkedList spaceElements = new LinkedList(); LeafPosition mainPosition = new LeafPosition(this, leafValue); - if (textArray[ai.iStartIndex] == CharUtilities.NBSPACE) { + if (!breakOpportunity) { // a non-breaking space - //TODO: other kinds of non-breaking spaces if (alignment == EN_JUSTIFY) { // the space can stretch and shrink, and must be preserved // when starting a line @@ -918,215 +987,215 @@ public class TextLayoutManager extends LeafNodeLayoutManager { spaceElements.add(new KnuthInlineBox(ai.ipdArea.opt, null, mainPosition, true)); } - } else if (textArray[ai.iStartIndex] == CharUtilities.SPACE - && 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 - spaceElements.add(new KnuthGlue(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements - .add(new KnuthPenalty( - 0, - (textArray[ai.iStartIndex] == CharUtilities.NBSPACE - ? KnuthElement.INFINITE - : 0), false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), -6 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, - false, new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.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 - spaceElements.add(new KnuthGlue(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), -3 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, new LeafPosition( - this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt + lineStartBAP, 0, 0, - mainPosition, false)); - break; - - case EN_JUSTIFY: - // justified text: - // the stretch and shrink depends on the space width - spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), ai.ipdArea.max - - ai.ipdArea.opt, ai.ipdArea.opt - ai.ipdArea.min, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, new LeafPosition( - this, -1), false)); - spaceElements.add(new KnuthGlue(lineStartBAP + ai.ipdArea.opt, 0, 0, - mainPosition, false)); - break; - - default: - // last line justified, the other lines unjustified: - // use only the space stretch - spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), ai.ipdArea.max - - ai.ipdArea.opt, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, new LeafPosition( - this, -1), false)); - spaceElements.add(new KnuthGlue(lineStartBAP + ai.ipdArea.opt, 0, 0, - mainPosition, false)); - } } 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 - spaceElements.add(new KnuthGlue(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements - .add(new KnuthPenalty( - 0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt - - (lineStartBAP + lineEndBAP), -6 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, - false, new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(lineStartBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), 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) { + if (textArray[ai.iStartIndex] != CharUtilities.SPACE + || 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 + spaceElements.add(new KnuthGlue(lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + new LeafPosition(this, -1), false)); + spaceElements + .add(new KnuthPenalty( + 0, + 0, false, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthGlue( + - (lineStartBAP + lineEndBAP), -6 + * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthInlineBox(0, null, + notifyPos(new LeafPosition(this, -1)), false)); + spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, + false, new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthGlue(ai.ipdArea.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 spaceElements.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, new LeafPosition(this, -1), false)); spaceElements.add(new KnuthPenalty(0, 0, false, new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt + spaceElements.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); + new LeafPosition(this, -1), false)); spaceElements.add(new KnuthInlineBox(0, null, notifyPos(new LeafPosition(this, -1)), false)); spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new LeafPosition( this, -1), false)); - spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); - } else { - spaceElements.add(new KnuthGlue(0, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt, -3 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + spaceElements.add(new KnuthGlue(ai.ipdArea.opt + lineStartBAP, 0, 0, mainPosition, false)); - } - break; + break; - case EN_JUSTIFY: - // justified text: - // the stretch and shrink depends on the space width - if (lineStartBAP != 0 || lineEndBAP != 0) { + case EN_JUSTIFY: + // justified text: + // the stretch and shrink depends on the space width spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, new LeafPosition(this, -1), false)); spaceElements.add(new KnuthPenalty(0, 0, false, new LeafPosition(this, -1), false)); spaceElements.add(new KnuthGlue( - ai.ipdArea.opt - (lineStartBAP + lineEndBAP), - ai.ipdArea.max - ai.ipdArea.opt, - ai.ipdArea.opt - ai.ipdArea.min, - mainPosition, false)); + - (lineStartBAP + lineEndBAP), ai.ipdArea.max + - ai.ipdArea.opt, ai.ipdArea.opt - ai.ipdArea.min, + new LeafPosition(this, -1), false)); spaceElements.add(new KnuthInlineBox(0, null, notifyPos(new LeafPosition(this, -1)), false)); spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new LeafPosition( this, -1), false)); - spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); - } else { - spaceElements.add(new KnuthGlue(ai.ipdArea.opt, - ai.ipdArea.max - ai.ipdArea.opt, - ai.ipdArea.opt - ai.ipdArea.min, + spaceElements.add(new KnuthGlue(lineStartBAP + ai.ipdArea.opt, 0, 0, mainPosition, false)); - } - break; + break; - default: - // last line justified, the other lines unjustified: - // use only the space stretch - if (lineStartBAP != 0 || lineEndBAP != 0) { + default: + // last line justified, the other lines unjustified: + // use only the space stretch spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, new LeafPosition(this, -1), false)); spaceElements.add(new KnuthPenalty(0, 0, false, new LeafPosition(this, -1), false)); spaceElements.add(new KnuthGlue( - ai.ipdArea.opt - (lineStartBAP + lineEndBAP), - ai.ipdArea.max - ai.ipdArea.opt, - 0, mainPosition, false)); + - (lineStartBAP + lineEndBAP), ai.ipdArea.max + - ai.ipdArea.opt, 0, + new LeafPosition(this, -1), false)); spaceElements.add(new KnuthInlineBox(0, null, notifyPos(new LeafPosition(this, -1)), false)); spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new LeafPosition( this, -1), false)); - spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, + spaceElements.add(new KnuthGlue(lineStartBAP + ai.ipdArea.opt, 0, 0, + mainPosition, false)); + } + } 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 + spaceElements.add(new KnuthGlue(lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, new LeafPosition(this, -1), false)); - } else { - spaceElements.add(new KnuthGlue(ai.ipdArea.opt, - ai.ipdArea.max - ai.ipdArea.opt, 0, + spaceElements + .add(new KnuthPenalty( + 0, 0, false, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthGlue(ai.ipdArea.opt + - (lineStartBAP + lineEndBAP), -6 + * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); + spaceElements.add(new KnuthInlineBox(0, null, + notifyPos(new LeafPosition(this, -1)), false)); + spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, + false, new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthGlue(lineStartBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + new LeafPosition(this, -1), 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) { + spaceElements.add(new KnuthGlue(lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthPenalty(0, 0, false, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthGlue(ai.ipdArea.opt + - (lineStartBAP + lineEndBAP), -3 + * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + mainPosition, false)); + spaceElements.add(new KnuthInlineBox(0, null, + notifyPos(new LeafPosition(this, -1)), false)); + spaceElements.add(new KnuthPenalty(0, + KnuthElement.INFINITE, false, new LeafPosition( + this, -1), false)); + spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, + new LeafPosition(this, -1), false)); + } else { + spaceElements.add(new KnuthGlue(0, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthPenalty(0, 0, false, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthGlue(ai.ipdArea.opt, -3 + * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + mainPosition, false)); + } + break; + + case EN_JUSTIFY: + // justified text: + // the stretch and shrink depends on the space width + if (lineStartBAP != 0 || lineEndBAP != 0) { + spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthPenalty(0, 0, false, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthGlue( + ai.ipdArea.opt - (lineStartBAP + lineEndBAP), + ai.ipdArea.max - ai.ipdArea.opt, + ai.ipdArea.opt - ai.ipdArea.min, + mainPosition, false)); + spaceElements.add(new KnuthInlineBox(0, null, + notifyPos(new LeafPosition(this, -1)), false)); + spaceElements.add(new KnuthPenalty(0, + KnuthElement.INFINITE, false, new LeafPosition( + this, -1), false)); + spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, + new LeafPosition(this, -1), false)); + } else { + spaceElements.add(new KnuthGlue(ai.ipdArea.opt, + ai.ipdArea.max - ai.ipdArea.opt, + ai.ipdArea.opt - ai.ipdArea.min, + mainPosition, false)); + } + break; + + default: + // last line justified, the other lines unjustified: + // use only the space stretch + if (lineStartBAP != 0 || lineEndBAP != 0) { + spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthPenalty(0, 0, false, + new LeafPosition(this, -1), false)); + spaceElements.add(new KnuthGlue( + ai.ipdArea.opt - (lineStartBAP + lineEndBAP), + ai.ipdArea.max - ai.ipdArea.opt, + 0, mainPosition, false)); + spaceElements.add(new KnuthInlineBox(0, null, + notifyPos(new LeafPosition(this, -1)), false)); + spaceElements.add(new KnuthPenalty(0, + KnuthElement.INFINITE, false, new LeafPosition( + this, -1), false)); + spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, + new LeafPosition(this, -1), false)); + } else { + spaceElements.add(new KnuthGlue(ai.ipdArea.opt, + ai.ipdArea.max - ai.ipdArea.opt, 0, + mainPosition, false)); + } } } } @@ -1135,16 +1204,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } private LinkedList createElementsForAWordFragment(int alignment, - AreaInfo ai, int leafValue, MinOptMax letterSpaceWidth) { + AreaInfo ai, int leafValue, MinOptMax letterSpaceWidth, boolean breakOpportunity) { LinkedList wordElements = new LinkedList(); 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 bSuppressibleLetterSpace - = /*ai.iLScount == (ai.iBreakIndex - ai.iStartIndex) - &&*/ isBreakChar(textArray[ai.iBreakIndex - 1]); + boolean bSuppressibleLetterSpace = breakOpportunity; if (letterSpaceWidth.min == letterSpaceWidth.max) { // constant letter spacing @@ -1366,5 +1433,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return hyphenElements; } + } diff --git a/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java b/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java new file mode 100644 index 000000000..29583a9d0 --- /dev/null +++ b/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java @@ -0,0 +1,160 @@ +/* + * 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.text.linebreak; + +/** + * This class is meant for supporting the Unicode line breaking algorithm. + * See <a href="http://unicode.org/reports/tr14/">UTR 14</a>. + * + */ +public class LineBreakStatus { + + /** Constant indicating a Direct Break */ + public static final byte DIRECT_BREAK = LineBreakUtils.DIRECT_BREAK; + /** Constant indicating an Indirect Break */ + public static final byte INDIRECT_BREAK = LineBreakUtils.INDIRECT_BREAK; + /** Constant indicating a Combining Indirect Break */ + public static final byte COMBINING_INDIRECT_BREAK = LineBreakUtils.COMBINING_INDIRECT_BREAK; + /** Constant indicating a Combining Prohibited Break */ + public static final byte COMBINING_PROHIBITED_BREAK = LineBreakUtils.COMBINING_PROHIBITED_BREAK; + /** Constant indicating a Prohibited Break */ + public static final byte PROHIBITED_BREAK = LineBreakUtils.PROHIBITED_BREAK; + /** Constant indicating a Explicit Break */ + public static final byte EXPLICIT_BREAK = LineBreakUtils.EXPLICIT_BREAK; + + private byte leftClass; + private boolean hadSpace; + + /** + * Resets the class to the same state as if new LineBreakStatus() had just been called. + */ + public LineBreakStatus() { + reset(); + } + + + /** + * Reset the status. + * This method will reset the status to the initial state. It is meant + * for recycling objects. + */ + public void reset() { + leftClass = -1; + hadSpace = false; + } + + /** + * 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 + * + * TODO: Better handling for AI, SA, CB and other line break classes. + * + * @param c The character. + * @return the break action to be taken + */ + 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; + } + if (leftClass == -1) { + if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_LF) { + leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_BK; + } else { + leftClass = currentClass; + if (leftClass == LineBreakUtils.LINE_BREAK_PROPERTY_CM) { + leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_ID; + } + } + // 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 : + leftClass = currentClass; + return PROHIBITED_BREAK; + case LineBreakUtils.DIRECT_BREAK : + leftClass = currentClass; + return DIRECT_BREAK; + case LineBreakUtils.INDIRECT_BREAK : + 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"); + } + + } + } + + /** + * for debugging only + */ + /* + public static void main(String args[]) { + LineBreakStatus lbs = new LineBreakStatus(); + lbs.nextChar('\n'); + lbs.nextChar('\n'); + lbs.nextChar('x'); + } + */ +} diff --git a/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java b/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java new file mode 100644 index 000000000..285b8a5e6 --- /dev/null +++ b/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java @@ -0,0 +1,669 @@ +/* + * 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.commons.text.linebreak; + +/* + * This is a generated file, DO NOT CHANGE! + */ + +class LineBreakUtils { + + public static final byte DIRECT_BREAK = 0; + public static final byte INDIRECT_BREAK = 1; + public static final byte COMBINING_INDIRECT_BREAK = 2; + public static final byte COMBINING_PROHIBITED_BREAK = 3; + public static final byte PROHIBITED_BREAK = 4; + 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}}; + + 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}; + }; + + 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}; + }; + + 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]; + }; + + 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; + + 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", + "Glue","H2","H3","Hyphen","Ideographic","Inseparable","Infix_Numeric","JL","JT","JV","Line_Feed","Next_Line", + "Nonstarter","Numeric","Open_Punctuation","Postfix_Numeric","Prefix_Numeric","Quotation","Complex_Context", + "Surrogate","Space","Break_Symbols","Word_Joiner","Unknown","ZWSpace"}; + + public static String getLineBreakPropertyShortName(byte i) { + if (i>0 && i<=lineBreakPropertyShortNames.length) { + return lineBreakPropertyShortNames[i-1]; + } else { + return null; + } + } + + public static String getLineBreakPropertyLongName(byte i) { + if (i>0 && i<=lineBreakPropertyLongNames.length) { + return lineBreakPropertyLongNames[i-1]; + } else { + return null; + } + } + + public static byte getLineBreakProperty(char c) { + return lineBreakProperties[c/128][c%128]; + } + + public static byte getLineBreakPairProperty(int lineBreakPropertyBefore,int lineBreakPropertyAfter) { + return PAIR_TABLE[lineBreakPropertyBefore-1][lineBreakPropertyAfter-1]; + } + +}; diff --git a/status.xml b/status.xml index eca23defc..a8e27b53b 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ <changes> <release version="FOP Trunk"> + <action context="Code" dev="MM" type="add"> + Added support for UAX#14 type line breaking. Support does not extend across nested fo:inline elements. + </action> <action context="Code" dev="SP" type="update" fixes-bug="41044" due-to="Richard Wheeldon"> Commented out unused properties, in order to minimize memory usage. </action> diff --git a/test/java/org/apache/fop/text/linebreak/LineBreakStatusTest.java b/test/java/org/apache/fop/text/linebreak/LineBreakStatusTest.java new file mode 100644 index 000000000..6ec075a08 --- /dev/null +++ b/test/java/org/apache/fop/text/linebreak/LineBreakStatusTest.java @@ -0,0 +1,351 @@ +/* + * 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.text.linebreak; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * JUnit test case for the LineBreakStatus class + */ +public class LineBreakStatusTest extends TestCase { + + /* + * These symbols are used to indicate the break action returned + * by the paragraph breaking. Their meaning is as per Unicode + * <a href="http://unicode.org/reports/tr14/#PairBasedImplementation">technical + * report #14</a>. + */ + private static final String BREAK_ACTION = "_%#@^!"; + + /** + * Creates the test with the given name. + * @param testName The name for this test. + */ + public LineBreakStatusTest(String testName) { + super(testName); + } + + /** + * Returns an TestSuite constructed from this class. + * @return the TestSuite + * @see junit.framework.TestSuite#TestSuite(class) + */ + public static Test suite() { + TestSuite suite = new TestSuite(LineBreakStatusTest.class); + + return suite; + } + + /** + * Test of reset method, of class org.apache.commons.text.linebreak.LineBreakStatus. + */ + public void testReset() { + System.out.println("testReset"); + // TODO + } + + /** + * Test of nextChar method, of class org.apache.commons.text.linebreak.LineBreakStatus. + * Runs tests for most of the Line Breaking Properties defined in the Unicode standard. + */ + public void testNextChar() { + System.out.println("testNextChar"); + + // AL -- Ordinary Alphabetic and Symbol Characters (XP) + assertTrue(testBreak( + "Nobreak", + "^^^^^^^" + )); + + // BA -- Break Opportunity After (A) + assertTrue(testBreak( + "Thin Space" + "\u2009" + "break", + "^^^^^%^^^^" + "^" + "_^^^^" + )); + + assertTrue(testBreak( + "Shy" + "\u00AD" + "break", + "^^^" + "^" + "_^^^^" + )); + + + // BB -- Break opportunites before characters (B) + assertTrue(testBreak( + "Acute Accent" + "\u00B4" + "break", + "^^^^^^%^^^^^" + "_" + "^^^^^" + )); + + // B2 -- Break Opportunity Before and After (B/A/XP) + assertTrue(testBreak( + "Em Dash" + "\u2014" + "break", + "^^^%^^^" + "_" + "_^^^^" + )); + + assertTrue(testBreak( + "Em Dash Dash" + "\u2014" + "\u2014" + "break", + "^^^%^^^^%^^^" + "_" + "^" + "_^^^^" + )); + + // BK Mandatory Break (A) -- normative + assertTrue(testBreak( + "Form Feed" + "\u000C" + "break", + "^^^^^%^^^" + "^" + "!^^^^" + )); + + assertTrue(testBreak( + "Line Separator" + "\u2028" + "break", + "^^^^^%^^^^^^^^" + "^" + "!^^^^" + )); + + assertTrue(testBreak( + "Paragraph Separator" + "\u2029" + "break", + "^^^^^^^^^^%^^^^^^^^" + "^" + "!^^^^" + )); + + // CB Contingent Break Opportunity (B/A) -- normative + // TODO Don't know quite what to do here + + // CL -- Closing Punctuation (XB) + assertTrue(testBreak( + "Right Parenthesis ) break", + "^^^^^^%^^^^^^^^^^^^^_^^^^" + )); + + // CM -- Attached Characters and Combining Marks (XB) -- normative + assertTrue(testBreak( + "Grave Accent" + "\u0300" + " break", + "^^^^^^%^^^^^" + "^" + "^%^^^^" + )); + + // CR -- Carriage Return (A) -- normative + assertTrue(testBreak( + "CR" + "\r" + "break", + "^^" + "^" + "!^^^^" + )); + + assertTrue(testBreak( + "CRLF" + "\r\n" + "break", + "^^^^" + "^^" + "!^^^^" + )); + + // EX -- Exclamation / interrogation (XB) + assertTrue(testBreak( + "EX CL ! ) break", + "^^^%^^^^^^_^^^^" + )); + + assertTrue(testBreak( + "EX Wave Dash ! " + "\u301C" + " break", + "^^^%^^^^%^^^^^^" + "%" + "^_^^^^" + )); + + // GL -- Non-breaking ("Glue") (XB/XA) -- normative + assertTrue(testBreak( + "No" + "\u00a0" + "break", + "^^" + "^" + "^^^^^" + )); + + assertTrue(testBreak( + "Non" + "\u2011" + " Hyphen", + "^^^" + "^" + "^%^^^^^" + )); + + // H2 -- Hangul LVT Syllable (B/A) + // TODO + + // H3 -- Hangul LVT Syllable (B/A) + // TODO + + // HY -- Hyphen Minus + assertTrue(testBreak( + "Normal-Hyphen", + "^^^^^^^_^^^^^" + )); + + assertTrue(testBreak( + "Normal - Hyphen", + "^^^^^^^%^_^^^^^" + )); + + assertTrue(testBreak( + "123-456", + "^^^^^^^" + )); + + assertTrue(testBreak( + "123 - 456", + "^^^^%^%^^" + )); + + // ID -- Ideographic (B/A) + assertTrue(testBreak( + "\u4E00" + "\u3000" + "\u4E02", + "^" + "_" + "_" + )); + + // IN -- Inseperable characters (XP) + assertTrue(testBreak( + "IN " + "\u2024" + "\u2025" + "\u2026", + "^^^" + "%" + "^" + "^" + )); + + // IS -- Numeric Separator (Infix) (XB) + assertTrue(testBreak( + "123,456.00 12:59", + "^^^^^^^^^^^%^^^^" + )); + + // JL -- Hangul L Jamo (B) + // TODO + + // JT -- Hangul T Jamo (A) + // TODO + + // JV -- Hangul V Jamo (XA/XB) + // TODO + + // LF -- Line Feed (A) -- normative + assertTrue(testBreak( + "Simple" + "\n" + "\n" + "break", + "^^^^^^" + "^" + "!" + "!^^^^" + )); + + // NL -- Next Line (A) -- normative + assertTrue(testBreak( + "NL" + "\u0085" + "break", + "^^" + "^" + "!^^^^" + )); + + // NS -- Non-starters (XB) + // TODO + + // NU -- Numeric (XP) + // Tested as part of IS + + // OP -- Opening Punctuation (XA) + assertTrue(testBreak( + "[ Bracket ( Parenthesis", + "^^^^^^^^^^_^^^^^^^^^^^^" + )); + + // PO -- Postfix (Numeric) (XB) + assertTrue(testBreak( + "(12.00)%", + "^^^^^^^^" + )); + + // PR -- Prefix (Numeric) (XA) + assertTrue(testBreak( + "$1000.00", + "^^^^^^^^" + )); + + // QU -- Ambiguous Quotation (XB/XA) + assertTrue(testBreak( + "'In Quotes'", + "^^^^%^^^^^^" + )); + + assertTrue(testBreak( + "' (In Quotes) '", + "^^^^^^%^^^^^^^%" + )); + + // SA -- Complex-context Dependent Characters (South East Asian) (P) + // TODO + + // SP -- Space (A) -- normative + assertTrue(testBreak( + "Simple break", + "^^^^^^^%^^^^" + )); + + assertTrue(testBreak( + "Simple break2", + "^^^^^^^^^^%^^^^^" + )); + + // SY -- Symbols Allowing Break After (A) + assertTrue(testBreak( + "http://xmlgraphics.apache.org/fop", + "^^^^^^^_^^^^^^^^^^^^^^^^^^^^^^_^^" + )); + + assertTrue(testBreak( + "1/2 31/10/2005", + "^^^^%^^^^^^^^^" + )); + + // WJ -- Word Joiner (XA/XB) -- (normative) + assertTrue(testBreak( + "http://" + "\u2060" + "xmlgraphics.apache.org/" + "\uFEFF" + "fop", + "^^^^^^^" + "^" + "^^^^^^^^^^^^^^^^^^^^^^^" + "^" + "^^^" + )); + + assertTrue(testBreak( + "Simple " + "\u2060" + "break", + "^^^^^^^" + "^" + "^^^^^" + )); + + assertTrue(testBreak( + "Simple" + "\u200B" + "\u2060" + "break", + "^^^^^^" + "^" + "_" + "^^^^^" + )); + + // XX -- Unknown (XP) + // TODO + + // ZW -- Zero Width Space (A) -- (normative) + assertTrue(testBreak( + "Simple" + "\u200B" + "break", + "^^^^^^" + "^" + "_^^^^" + )); + + } + + /** + * Tests the paragraph break status (break actions) returned from calling + * LineBreakStatus.nextChar() on each character of paragraph against + * the expected break actions. There must be a positional match between + * the characters in paragraph and characters in breakAction. + * @param paragraph The text to be analysed for line breaks + * @param breakActions The symbolic representation of the break actions + * expected to be returned. + */ + private boolean testBreak(String paragraph, String breakActions) { + boolean result = true; + int length = paragraph.length(); + LineBreakStatus lbs = new LineBreakStatus(); + for (int i = 0; i < length; i++) { + byte breakAction = lbs.nextChar(paragraph.charAt(i)); + if (BREAK_ACTION.charAt(breakAction) != breakActions.charAt(i)) { + System.err.println(paragraph); + System.err.println(breakActions); + System.err.println("pos = " + i + + " expected '" + breakActions.charAt(i) + + "' got '" + BREAK_ACTION.charAt(breakAction) + "'"); + result = false; + } + } + return result; + } +} diff --git a/test/java/org/apache/fop/text/linebreak/LineBreakUtilsTest.java b/test/java/org/apache/fop/text/linebreak/LineBreakUtilsTest.java new file mode 100644 index 000000000..22b8f73f3 --- /dev/null +++ b/test/java/org/apache/fop/text/linebreak/LineBreakUtilsTest.java @@ -0,0 +1,74 @@ +/* + * 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.text.linebreak; + +import junit.framework.TestCase; + +/** + * TODO add javadoc + * + * + */ +public class LineBreakUtilsTest extends TestCase { + + /** + * @param name + */ + public LineBreakUtilsTest(String name) { + super(name); + } + + public void testLineBreakProperty() { + assertEquals(LineBreakUtils.getLineBreakProperty('A'), LineBreakUtils.LINE_BREAK_PROPERTY_AL); + assertEquals(LineBreakUtils.getLineBreakProperty('1'), LineBreakUtils.LINE_BREAK_PROPERTY_NU); + assertEquals(LineBreakUtils.getLineBreakProperty('\n'), LineBreakUtils.LINE_BREAK_PROPERTY_LF); + assertEquals(LineBreakUtils.getLineBreakProperty('\r'), LineBreakUtils.LINE_BREAK_PROPERTY_CR); + assertEquals(LineBreakUtils.getLineBreakProperty('('), LineBreakUtils.LINE_BREAK_PROPERTY_OP); + } + + public void testLineBreakPair() { + assertEquals( + LineBreakUtils.getLineBreakPairProperty( + LineBreakUtils.LINE_BREAK_PROPERTY_CM, + LineBreakUtils.LINE_BREAK_PROPERTY_CL), + LineBreakUtils.PROHIBITED_BREAK); + assertEquals( + LineBreakUtils.getLineBreakPairProperty( + LineBreakUtils.LINE_BREAK_PROPERTY_CL, + LineBreakUtils.LINE_BREAK_PROPERTY_CM), + LineBreakUtils.COMBINING_INDIRECT_BREAK); + assertEquals( + LineBreakUtils.getLineBreakPairProperty( + LineBreakUtils.LINE_BREAK_PROPERTY_IS, + LineBreakUtils.LINE_BREAK_PROPERTY_PR), + LineBreakUtils.DIRECT_BREAK); + assertEquals( + LineBreakUtils.getLineBreakPairProperty( + LineBreakUtils.LINE_BREAK_PROPERTY_AL, + LineBreakUtils.LINE_BREAK_PROPERTY_OP), + LineBreakUtils.DIRECT_BREAK); + assertEquals( + LineBreakUtils.getLineBreakPairProperty( + LineBreakUtils.LINE_BREAK_PROPERTY_LF, + LineBreakUtils.LINE_BREAK_PROPERTY_CM), + 0); + } + +} diff --git a/test/layoutengine/standard-testcases/block_uax14_linebreaking.xml b/test/layoutengine/standard-testcases/block_uax14_linebreaking.xml new file mode 100755 index 000000000..973891f65 --- /dev/null +++ b/test/layoutengine/standard-testcases/block_uax14_linebreaking.xml @@ -0,0 +1,188 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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$ --> +<testcase> + <info> + <p> + This test checks some of the UAX#14 breaking rules. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"> + <fo:layout-master-set> + <fo:simple-page-master master-name="normal" page-width="2.5in" page-height="10in" margin="5pt"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="normal" white-space-collapse="true"> + <fo:flow flow-name="xsl-region-body" font-size="10pt"> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + BA -- Break Opportunity After (A) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + VeryLongWordWithAThinSpace PutInTheMiddleOfIt + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + BB -- Break Opportunity Before (B) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + VeryLongWordWithAnAcuteAccent´PutInTheMiddleOfIt + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + B2 -- Break Opportunity Before and After (B/A) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + —Very—Long—Word—With—LotsOf—Em—Dashes—Put—InBetween—And—Around— + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + B2 -- Break Opportunity Before and After (B/A) - as before but don't break between consecutive Em Dashes + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + AVeryLongWordWithSomeDouble— —Dashes— —Put— —In + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + AVeryLongWordWithSomeDouble——Dashes——Put——In + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + CL -- Closing Punctuation (XB) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + Closing )brackets )even )if )preceeded )by )a )space )are )not )a )break )point + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + EX -- Exclamation / interrogation (XB) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + Question ?marks ?and exclamation !marks !even ?if !preceeded ?by !a ?space !are ?not !a ?break !point + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + HY -- Hyphen Minus (XA) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + Very-Long-Word-With-Lots-Of-Hyphens-Put-In-Between + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + Hyphens-in-numbers-do-not-123-567-890-break + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + ID -- Ideographic (B/A) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 0pt 0pt"> + Need A Proper Test Case For This As Here Only The Ideographic Space Is Used + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + IN -- Inseperable characters (XP) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + There is never a break…………………………between characters of this class + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + IS -- Numeric Separator (Infix) (XB) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + Numbers containing separators 123,345,678.00 08:00:23.15 are not broken + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + OP -- Opening Punctuation (XA) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + Opening( brackets( even( if( followed( by( a( space( are( not( a( break( point + </fo:block> + <fo:block background-color="silver" font-size="8pt" margin="3pt 0pt 0pt 0pt"> + SY -- Symbols Allowing Break After (A) + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + http://a/very/long/url/can/be/broken/after/the/solidus + </fo:block> + <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt"> + No-break-point-in-normal-dates-12/12/2006-or-fractions-12345678/67890112 + </fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="2" xpath="count(//flow/block[2]/lineArea)"/> + <eval expected="141160" xpath="//flow/block[2]/lineArea[1]/text/@ipd"/> + <eval expected="88150" xpath="//flow/block[2]/lineArea[2]/text/@ipd"/> + + <eval expected="2" xpath="count(//flow/block[4]/lineArea)"/> + <eval expected="155060" xpath="//flow/block[4]/lineArea[1]/text/@ipd"/> + <eval expected="89480" xpath="//flow/block[4]/lineArea[2]/text/@ipd"/> + + <eval expected="3" xpath="count(//flow/block[6]/lineArea)"/> + <eval expected="166150" xpath="//flow/block[6]/lineArea[1]/text/@ipd"/> + <eval expected="161160" xpath="//flow/block[6]/lineArea[2]/text/@ipd"/> + <eval expected="70030" xpath="//flow/block[6]/lineArea[3]/text/@ipd"/> + + <eval expected="2" xpath="count(//flow/block[8]/lineArea)"/> + <eval expected="151160" xpath="//flow/block[8]/lineArea[1]/text/@ipd"/> + <eval expected="125590" xpath="//flow/block[8]/lineArea[2]/text/@ipd"/> + + <eval expected="2" xpath="count(//flow/block[9]/lineArea)"/> + <eval expected="151160" xpath="//flow/block[9]/lineArea[1]/text/@ipd"/> + <eval expected="117250" xpath="//flow/block[9]/lineArea[2]/text/@ipd"/> + + <eval expected="3" xpath="count(//flow/block[11]/lineArea)"/> + <eval expected="122250" xpath="//flow/block[11]/lineArea[1]/text/@ipd"/> + <eval expected="166730" xpath="//flow/block[11]/lineArea[2]/text/@ipd"/> + <eval expected="52800" xpath="//flow/block[11]/lineArea[3]/text/@ipd"/> + + <eval expected="3" xpath="count(//flow/block[13]/lineArea)"/> + <eval expected="162290" xpath="//flow/block[13]/lineArea[1]/text/@ipd"/> + <eval expected="158970" xpath="//flow/block[13]/lineArea[2]/text/@ipd"/> + <eval expected="140640" xpath="//flow/block[13]/lineArea[3]/text/@ipd"/> + + <eval expected="2" xpath="count(//flow/block[15]/lineArea)"/> + <eval expected="136130" xpath="//flow/block[15]/lineArea[1]/text/@ipd"/> + <eval expected="111710" xpath="//flow/block[15]/lineArea[2]/text/@ipd"/> + + <eval expected="2" xpath="count(//flow/block[16]/lineArea)"/> + <eval expected="110580" xpath="//flow/block[16]/lineArea[1]/text/@ipd"/> + <eval expected="102270" xpath="//flow/block[16]/lineArea[2]/text/@ipd"/> + + <eval expected="3" xpath="count(//flow/block[18]/lineArea)"/> + <eval expected="125610" xpath="//flow/block[18]/lineArea[1]/text/@ipd"/> + <eval expected="138380" xpath="//flow/block[18]/lineArea[2]/text/@ipd"/> + <eval expected="133960" xpath="//flow/block[18]/lineArea[3]/text/@ipd"/> + + <eval expected="3" xpath="count(//flow/block[20]/lineArea)"/> + <eval expected="72250" xpath="//flow/block[20]/lineArea[1]/text/@ipd"/> + <eval expected="162810" xpath="//flow/block[20]/lineArea[2]/text/@ipd"/> + <eval expected="101700" xpath="//flow/block[20]/lineArea[3]/text/@ipd"/> + + <eval expected="3" xpath="count(//flow/block[22]/lineArea)"/> + <eval expected="138940" xpath="//flow/block[22]/lineArea[1]/text/@ipd"/> + <eval expected="159010" xpath="//flow/block[22]/lineArea[2]/text/@ipd"/> + <eval expected="30570" xpath="//flow/block[22]/lineArea[3]/text/@ipd"/> + + <eval expected="3" xpath="count(//flow/block[24]/lineArea)"/> + <eval expected="163390" xpath="//flow/block[24]/lineArea[1]/text/@ipd"/> + <eval expected="144490" xpath="//flow/block[24]/lineArea[2]/text/@ipd"/> + <eval expected="27790" xpath="//flow/block[24]/lineArea[3]/text/@ipd"/> + + <eval expected="2" xpath="count(//flow/block[26]/lineArea)"/> + <eval expected="156750" xpath="//flow/block[26]/lineArea[1]/text/@ipd"/> + <eval expected="70590" xpath="//flow/block[26]/lineArea[2]/text/@ipd"/> + + <eval expected="3" xpath="count(//flow/block[27]/lineArea)"/> + <eval expected="114460" xpath="//flow/block[27]/lineArea[1]/text/@ipd"/> + <eval expected="93380" xpath="//flow/block[27]/lineArea[2]/text/@ipd"/> + <eval expected="132860" xpath="//flow/block[27]/lineArea[3]/text/@ipd"/> + </checks> +</testcase> diff --git a/test/layoutengine/standard-testcases/block_white-space_4.xml b/test/layoutengine/standard-testcases/block_white-space_4.xml index 67285e8fd..f615e62ee 100644 --- a/test/layoutengine/standard-testcases/block_white-space_4.xml +++ b/test/layoutengine/standard-testcases/block_white-space_4.xml @@ -65,32 +65,6 @@ </fo:root> </fo> <checks> - <element-list category="line" id="l-sp"> - <box w="6672"/> - - <!-- first space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="3336" y="-10008" z="0"/> - - <box w="19344"/> - - <!-- second space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="3336" y="-10008" z="0"/> - - <box w="19344"/> - - <!-- third space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="3336" y="-10008" z="0"/> - - <box w="6672"/> - - <skip>12</skip> - </element-list> <eval expected="62040" xpath="//block[@prod-id='l-sp']/lineArea/text/@ipd"/> <eval expected="word" xpath="local-name(//block[@prod-id='l-sp']/lineArea/text/*[1])"/> <eval expected="space" xpath="local-name(//block[@prod-id='l-sp']/lineArea/text/*[2])"/> @@ -102,32 +76,6 @@ <true xpath="not(//block[@prod-id='l-sp']/lineArea/text/*[2]/@adj = 'false')"/> <true xpath="not(//block[@prod-id='l-sp']/lineArea/text/*[6]/@adj = 'false')"/> - <element-list category="line" id="l-thin-space"> - <box w="6672"/> - - <!-- first space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="2400" y="-10008" z="0"/> - - <box w="19344"/> - - <!-- second space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="3336" y="-10008" z="0"/> - - <box w="19344"/> - - <!-- third space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="2400" y="-10008" z="0"/> - - <box w="6672"/> - - <skip>16</skip> - </element-list> <eval expected="60168" xpath="//block[@prod-id='l-thin-space']/lineArea/text/@ipd"/> <eval expected="word" xpath="local-name(//block[@prod-id='l-thin-space']/lineArea/text/*[1])"/> <eval expected="space" xpath="local-name(//block[@prod-id='l-thin-space']/lineArea/text/*[2])"/> @@ -139,116 +87,16 @@ <true xpath="//block[@prod-id='l-thin-space']/lineArea/text/*[2]/@adj = 'false'"/> <true xpath="//block[@prod-id='l-thin-space']/lineArea/text/*[6]/@adj = 'false'"/> - <element-list category="line" id="l-hair-space"> - <box w="6672"/> - - <!-- first space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="1200" y="-10008" z="0"/> - - <box w="19344"/> - - <!-- second space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="3336" y="-10008" z="0"/> - - <box w="19344"/> - - <!-- third space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="1200" y="-10008" z="0"/> - - <box w="6672"/> - - <skip>16</skip> - </element-list> <eval expected="57768" xpath="//block[@prod-id='l-hair-space']/lineArea/text/@ipd"/> <true xpath="//block[@prod-id='l-hair-space']/lineArea/text/*[2]/@adj = 'false'"/> <true xpath="//block[@prod-id='l-hair-space']/lineArea/text/*[6]/@adj = 'false'"/> - <element-list category="line" id="l-zwsp"> - <box w="6672"/> - - <!-- first space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="0" y="-10008" z="0"/> - - <box w="19344"/> - - <!-- second space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="3336" y="-10008" z="0"/> - - <box w="19344"/> - - <!-- third space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="0" y="-10008" z="0"/> - - <box w="6672"/> - - <skip>20</skip> - </element-list> <eval expected="55368" xpath="//block[@prod-id='l-zwsp']/lineArea/text/@ipd"/> <true xpath="//block[@prod-id='l-zwsp']/lineArea/text/*[2]/@adj = 'false'"/> <true xpath="//block[@prod-id='l-zwsp']/lineArea/text/*[6]/@adj = 'false'"/> - <element-list category="line" id="l-nosp"> - <box w="26016"/> - - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="3336" y="-10008" z="0"/> - - <box w="26016"/> - - <skip>12</skip> - </element-list> <eval expected="55368" xpath="//block[@prod-id='l-nosp']/lineArea/text/@ipd"/> - <element-list category="line" id="c-thin-space"> - <glue w="0" y="10008" z="0"/> - - <box w="6672"/> - - <!-- first space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="2400" y="-20016" z="0"/> - <box w="0"/> - <penalty w="0" p="INF"/> - <glue w="0" y="10008" z="0"/> - - <box w="19344"/> - - <!-- second space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="3336" y="-20016" z="0"/> - <box w="0"/> - <penalty w="0" p="INF"/> - <glue w="0" y="10008" z="0"/> - - <box w="19344"/> - - <!-- third space --> - <glue w="0" y="10008" z="0"/> - <penalty w="0" p="0"/> - <glue w="2400" y="-20016" z="0"/> - <box w="0"/> - <penalty w="0" p="INF"/> - <glue w="0" y="10008" z="0"/> - - <box w="6672"/> - - <skip>24</skip> - </element-list> <eval expected="60168" xpath="//block[@prod-id='c-thin-space']/lineArea/text/@ipd"/> <eval expected="word" xpath="local-name(//block[@prod-id='c-thin-space']/lineArea/text/*[1])"/> <eval expected="space" xpath="local-name(//block[@prod-id='c-thin-space']/lineArea/text/*[2])"/> @@ -260,149 +108,29 @@ <true xpath="//block[@prod-id='c-thin-space']/lineArea/text/*[2]/@adj = 'false'"/> <true xpath="//block[@prod-id='c-thin-space']/lineArea/text/*[6]/@adj = 'false'"/> - <element-list category="line" id="j-sp"> - <box w="6672"/> - - <!-- first space --> - <glue w="3336" y="1668" z="1112"/> - - <box w="19344"/> - - <!-- second space --> - <glue w="3336" y="1668" z="1112"/> - - <box w="19344"/> - - <!-- third space --> - <glue w="3336" y="1668" z="1112"/> - - <box w="6672"/> - - <skip>6</skip> - </element-list> <eval expected="190804" xpath="//block[@prod-id='j-sp']/lineArea/text/@ipd"/> <eval expected="42921" xpath="//block[@prod-id='j-sp']/lineArea/text/@twsadjust"/> - <element-list category="line" id="j-thin-space"> - <box w="6672"/> - - <!-- first space --> - <glue w="2400" y="0" z="0"/> - - <box w="19344"/> - - <!-- second space --> - <glue w="3336" y="1668" z="1112"/> - - <box w="19344"/> - - <!-- third space --> - <glue w="2400" y="0" z="0"/> - - <box w="6672"/> - - <skip>8</skip> - </element-list> <eval expected="104277" xpath="//block[@prod-id='j-thin-space']/lineArea/text/@ipd"/> <eval expected="44109" xpath="//block[@prod-id='j-thin-space']/lineArea/text/@twsadjust"/> <true xpath="//block[@prod-id='j-thin-space']/lineArea/text/*[2]/@adj = 'false'"/> <true xpath="//block[@prod-id='j-thin-space']/lineArea/text/*[6]/@adj = 'false'"/> - <element-list category="line" id="j-zwsp"> - <box w="6672"/> - - <!-- first space --> - <glue w="0" y="0" z="0"/> - - <box w="19344"/> - - <!-- second space --> - <glue w="3336" y="1668" z="1112"/> - - <box w="19344"/> - - <!-- third space --> - <glue w="0" y="0" z="0"/> - - <box w="6672"/> - - <skip>10</skip> - </element-list> <eval expected="84280" xpath="//block[@prod-id='j-zwsp']/lineArea/text/@ipd"/> <eval expected="28912" xpath="//block[@prod-id='j-zwsp']/lineArea/text/@twsadjust"/> <true xpath="//block[@prod-id='j-zwsp']/lineArea/text/*[2]/@adj = 'false'"/> <true xpath="//block[@prod-id='j-zwsp']/lineArea/text/*[6]/@adj = 'false'"/> - <element-list category="line" id="lsj-sp"> - <box w="6672"/> - - <!-- first space --> - <glue w="7336" y="1668" z="1112"/> - - <box w="25344"/> - - <!-- second space --> - <glue w="7336" y="1668" z="1112"/> - - <box w="25344"/> - - <!-- third space --> - <glue w="7336" y="1668" z="1112"/> - - <box w="6672"/> - - <skip>6</skip> - </element-list> <eval expected="182404" xpath="//block[@prod-id='lsj-sp']/lineArea/text/@ipd"/> <eval expected="32121" xpath="//block[@prod-id='lsj-sp']/lineArea/text/@twsadjust"/> <eval expected="2000" xpath="//block[@prod-id='lsj-sp']/lineArea/text/@tlsadjust"/> - <element-list category="line" id="lsj-thin-space"> - <box w="6672"/> - - <!-- first space --> - <glue w="2400" y="0" z="0"/> - - <box w="25344"/> - - <!-- second space --> - <glue w="7336" y="1668" z="1112"/> - - <box w="25344"/> - - <!-- third space --> - <glue w="2400" y="0" z="0"/> - - <box w="6672"/> - - <skip>8</skip> - </element-list> <eval expected="104777" xpath="//block[@prod-id='lsj-thin-space']/lineArea/text/@ipd"/> <eval expected="28609" xpath="//block[@prod-id='lsj-thin-space']/lineArea/text/@twsadjust"/> <eval expected="2000" xpath="//block[@prod-id='lsj-thin-space']/lineArea/text/@tlsadjust"/> <true xpath="//block[@prod-id='lsj-thin-space']/lineArea/text/*[2]/@adj = 'false'"/> <true xpath="//block[@prod-id='lsj-thin-space']/lineArea/text/*[6]/@adj = 'false'"/> - <element-list category="line" id="lsj-zwsp"> - <box w="6672"/> - - <!-- first space --> - <glue w="0" y="0" z="0"/> - - <box w="25344"/> - - <!-- second space --> - <glue w="7336" y="1668" z="1112"/> - - <box w="25344"/> - - <!-- third space --> - <glue w="0" y="0" z="0"/> - - <box w="6672"/> - - <skip>10</skip> - </element-list> <eval expected="85480" xpath="//block[@prod-id='lsj-zwsp']/lineArea/text/@ipd"/> <eval expected="14112" xpath="//block[@prod-id='lsj-zwsp']/lineArea/text/@twsadjust"/> <eval expected="2000" xpath="//block[@prod-id='lsj-zwsp']/lineArea/text/@tlsadjust"/> diff --git a/test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml b/test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml index 0b03fba30..fd706d2f0 100644 --- a/test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml +++ b/test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml @@ -249,8 +249,8 @@ <eval expected="3000" xpath="//flow/block[4]/lineArea[3]/inlineparent/@padding-end"/>
<eval expected="5000" xpath="//flow/block[4]/lineArea[3]/inlineparent/@padding-start"/>
- <eval expected="183960" xpath="//flow/block[5]/lineArea[1]/inlineparent/@ipd"/>
- <eval expected="193960" xpath="//flow/block[5]/lineArea[1]/inlineparent/@ipda"/>
+ <eval expected="149500" xpath="//flow/block[5]/lineArea[1]/inlineparent/@ipd"/>
+ <eval expected="159500" xpath="//flow/block[5]/lineArea[1]/inlineparent/@ipda"/>
<eval expected="0" xpath="//flow/block[5]/lineArea[1]/inlineparent/@offset"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[5]/lineArea[1]/inlineparent/@border-after"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[5]/lineArea[1]/inlineparent/@border-before"/>
@@ -260,8 +260,8 @@ <eval expected="1000" xpath="//flow/block[5]/lineArea[1]/inlineparent/@padding-before"/>
<eval expected="3000" xpath="//flow/block[5]/lineArea[1]/inlineparent/@padding-end"/>
<eval expected="5000" xpath="//flow/block[5]/lineArea[1]/inlineparent/@padding-start"/>
- <eval expected="255680" xpath="//flow/block[5]/lineArea[2]/inlineparent/@ipd"/>
- <eval expected="265680" xpath="//flow/block[5]/lineArea[2]/inlineparent/@ipda"/>
+ <eval expected="237340" xpath="//flow/block[5]/lineArea[2]/inlineparent/@ipd"/>
+ <eval expected="247340" xpath="//flow/block[5]/lineArea[2]/inlineparent/@ipda"/>
<eval expected="0" xpath="//flow/block[5]/lineArea[2]/inlineparent/@offset"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[5]/lineArea[2]/inlineparent/@border-after"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[5]/lineArea[2]/inlineparent/@border-before"/>
@@ -271,8 +271,8 @@ <eval expected="1000" xpath="//flow/block[5]/lineArea[2]/inlineparent/@padding-before"/>
<eval expected="3000" xpath="//flow/block[5]/lineArea[2]/inlineparent/@padding-end"/>
<eval expected="5000" xpath="//flow/block[5]/lineArea[2]/inlineparent/@padding-start"/>
- <eval expected="186750" xpath="//flow/block[5]/lineArea[3]/inlineparent/@ipd"/>
- <eval expected="196750" xpath="//flow/block[5]/lineArea[3]/inlineparent/@ipda"/>
+ <eval expected="239550" xpath="//flow/block[5]/lineArea[3]/inlineparent/@ipd"/>
+ <eval expected="249550" xpath="//flow/block[5]/lineArea[3]/inlineparent/@ipda"/>
<eval expected="0" xpath="//flow/block[5]/lineArea[3]/inlineparent/@offset"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[5]/lineArea[3]/inlineparent/@border-after"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[5]/lineArea[3]/inlineparent/@border-before"/>
@@ -283,8 +283,8 @@ <eval expected="3000" xpath="//flow/block[5]/lineArea[3]/inlineparent/@padding-end"/>
<eval expected="5000" xpath="//flow/block[5]/lineArea[3]/inlineparent/@padding-start"/>
- <eval expected="172840" xpath="//flow/block[6]/lineArea[1]/inlineparent/@ipd"/>
- <eval expected="178840" xpath="//flow/block[6]/lineArea[1]/inlineparent/@ipda"/>
+ <eval expected="149500" xpath="//flow/block[6]/lineArea[1]/inlineparent/@ipd"/>
+ <eval expected="155500" xpath="//flow/block[6]/lineArea[1]/inlineparent/@ipda"/>
<eval expected="0" xpath="//flow/block[6]/lineArea[1]/inlineparent/@offset"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[6]/lineArea[1]/inlineparent/@border-after"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[6]/lineArea[1]/inlineparent/@border-before"/>
@@ -292,15 +292,15 @@ <eval expected="1000" xpath="//flow/block[6]/lineArea[1]/inlineparent/@padding-after"/>
<eval expected="1000" xpath="//flow/block[6]/lineArea[1]/inlineparent/@padding-before"/>
<eval expected="5000" xpath="//flow/block[6]/lineArea[1]/inlineparent/@padding-start"/>
- <eval expected="266800" xpath="//flow/block[6]/lineArea[2]/inlineparent/@ipd"/>
- <eval expected="266800" xpath="//flow/block[6]/lineArea[2]/inlineparent/@ipda"/>
+ <eval expected="237340" xpath="//flow/block[6]/lineArea[2]/inlineparent/@ipd"/>
+ <eval expected="237340" xpath="//flow/block[6]/lineArea[2]/inlineparent/@ipda"/>
<eval expected="0" xpath="//flow/block[6]/lineArea[2]/inlineparent/@offset"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[6]/lineArea[2]/inlineparent/@border-after"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[6]/lineArea[2]/inlineparent/@border-before"/>
<eval expected="1000" xpath="//flow/block[6]/lineArea[2]/inlineparent/@padding-after"/>
<eval expected="1000" xpath="//flow/block[6]/lineArea[2]/inlineparent/@padding-before"/>
- <eval expected="186750" xpath="//flow/block[6]/lineArea[3]/inlineparent/@ipd"/>
- <eval expected="190750" xpath="//flow/block[6]/lineArea[3]/inlineparent/@ipda"/>
+ <eval expected="239550" xpath="//flow/block[6]/lineArea[3]/inlineparent/@ipd"/>
+ <eval expected="243550" xpath="//flow/block[6]/lineArea[3]/inlineparent/@ipda"/>
<eval expected="0" xpath="//flow/block[6]/lineArea[3]/inlineparent/@offset"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[6]/lineArea[3]/inlineparent/@border-after"/>
<eval expected="(solid,#ff0000,1000)" xpath="//flow/block[6]/lineArea[3]/inlineparent/@border-before"/>
|