aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.xml79
-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-xsrc/codegen/unicode/data/LineBreakPairTable.txt28
-rw-r--r--src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java659
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java642
-rw-r--r--src/java/org/apache/fop/text/linebreak/LineBreakStatus.java160
-rw-r--r--src/java/org/apache/fop/text/linebreak/LineBreakUtils.java669
-rw-r--r--status.xml3
-rw-r--r--test/java/org/apache/fop/text/linebreak/LineBreakStatusTest.java351
-rw-r--r--test/java/org/apache/fop/text/linebreak/LineBreakUtilsTest.java74
-rwxr-xr-xtest/layoutengine/standard-testcases/block_uax14_linebreaking.xml188
-rw-r--r--test/layoutengine/standard-testcases/block_white-space_4.xml272
-rw-r--r--test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml24
43 files changed, 2557 insertions, 592 deletions
diff --git a/build.xml b/build.xml
index c0fca36e6..aead809dd 100644
--- a/build.xml
+++ b/build.xml
@@ -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&#x2009;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&#x00B4;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">
+ &#x2014;Very&#x2014;Long&#x2014;Word&#x2014;With&#x2014;LotsOf&#x2014;Em&#x2014;Dashes&#x2014;Put&#x2014;InBetween&#x2014;And&#x2014;Around&#x2014;
+ </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&#x2014; &#x2014;Dashes&#x2014; &#x2014;Put&#x2014; &#x2014;In
+ </fo:block>
+ <fo:block background-color="yellow" margin="0pt 0pt 3pt 0pt">
+ AVeryLongWordWithSomeDouble&#x2014;&#x2014;Dashes&#x2014;&#x2014;Put&#x2014;&#x2014;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&#x3000;A&#x3000;Proper&#x3000;Test&#x3000;Case&#x3000;For&#x3000;This&#x3000;As&#x3000;Here&#x3000;Only&#x3000;The&#x3000;Ideographic&#x3000;Space&#x3000;Is&#x3000;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&#x2026;&#x2026;&#x2026;&#x2026;&#x2026;&#x2026;&#x2026;&#x2026;&#x2026;&#x2026;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"/>