You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ga...@apache.org on 2012/02/26 03:29:29 UTC
svn commit: r1293736 [3/38] - in /xmlgraphics/fop/trunk: ./
src/codegen/java/org/apache/fop/tools/
src/codegen/unicode/java/org/apache/fop/complexscripts/
src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/
src/documentation/content/xdocs/trun...
Added: xmlgraphics/fop/trunk/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java (added)
+++ xmlgraphics/fop/trunk/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,1269 @@
+/*
+ * 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.bidi;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.ObjectOutputStream;
+import java.io.PrintWriter;
+
+import java.net.URL;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.fop.complexscripts.bidi.BidiConstants;
+import org.apache.fop.util.License;
+
+// CSOFF: LineLengthCheck
+// CSOFF: NoWhitespaceAfterCheck
+// CSOFF: InnerAssignmentCheck
+// CSOFF: SimplifyBooleanReturnCheck
+// CSOFF: EmptyForIteratorPadCheck
+
+/**
+ * <p>Utility for generating a Java class and associated data files representing
+ * bidirectional confomance test data from the Unicode Character Database and
+ * Unicode BidiTest data files.</p>
+ *
+ * <p>This code is derived in part from GenerateBidiClassUtils.java.</p>
+ *
+ * @author Glenn Adams
+ */
+public final class GenerateBidiTestData {
+
+ // local constants
+ private static final String PFX_TYPE = "@Type:";
+ private static final String PFX_LEVELS = "@Levels:";
+ private static final String PFX_REORDER = "@Reorder:";
+
+ // command line options
+ private static boolean ignoreDeprecatedTypeData;
+ private static boolean verbose;
+
+ // instrumentation
+ private static int lineNumber;
+ private static int numTypeRanges;
+ private static int numLevelSpecs;
+ private static int numTestSpecs;
+
+ // compiled data
+ private static int[][] td; // types data
+ private static int[][] ld; // levels data
+
+ // ensure non-instantiation
+ private GenerateBidiTestData() {
+ }
+
+ /**
+ * Generate a class managing bidi test data for Unicode characters.
+ *
+ * @param ucdFileName name (as URL) of file containing unicode character database data
+ * @param bidiFileName name (as URL) of file containing bidi test data
+ * @param outFileName name of the output class file
+ * @throws Exception
+ */
+ private static void convertBidiTestData(String ucdFileName, String bidiFileName, String outFileName) throws Exception {
+
+ // read type data from UCD if ignoring deprecated type data
+ if ( ignoreDeprecatedTypeData ) {
+ readBidiTypeData(ucdFileName);
+ }
+
+ // read bidi test data
+ readBidiTestData(bidiFileName);
+
+ // generate class
+ PrintWriter out = new PrintWriter(new FileWriter(outFileName));
+ License.writeJavaLicenseId(out);
+ out.println();
+ out.println("package org.apache.fop.complexscripts.bidi;");
+ out.println();
+ out.println("import java.io.IOException;");
+ out.println("import java.io.InputStream;");
+ out.println("import java.io.ObjectInputStream;");
+ out.println();
+ out.println("// CSOFF: WhitespaceAfterCheck");
+ out.println();
+ out.println("/*");
+ out.println(" * !!! THIS IS A GENERATED FILE !!!");
+ out.println(" * If updates to the source are needed, then:");
+ out.println(" * - apply the necessary modifications to");
+ out.println(" * 'src/codegen/unicode/java/org/apache/fop/text/bidi/GenerateBidiTestData.java'");
+ out.println(" * - run 'ant codegen-unicode', which will generate a new BidiTestData.java");
+ out.println(" * in 'test/java/org/apache/fop/complexscripts/bidi'");
+ out.println(" * - commit BOTH changed files");
+ out.println(" */");
+ out.println();
+ out.println("/** Bidirectional test data. */");
+ out.println("public final class BidiTestData {");
+ out.println();
+ out.println(" private BidiTestData() {");
+ out.println(" }");
+ out.println();
+ dumpData ( out, outFileName );
+ out.println(" public static final int NUM_TEST_SEQUENCES = " + numTestSpecs + ";");
+ out.println();
+ out.println(" public static int[] readTestData ( String prefix, int index ) {");
+ out.println(" int[] data = null;");
+ out.println(" InputStream is = null;");
+ out.println(" Class btc = BidiTestData.class;");
+ out.println(" String name = btc.getSimpleName() + \"$\" + prefix + index + \".ser\";");
+ out.println(" try {");
+ out.println(" if ( ( is = btc.getResourceAsStream ( name ) ) != null ) {");
+ out.println(" ObjectInputStream ois = new ObjectInputStream ( is );");
+ out.println(" data = (int[]) ois.readObject();");
+ out.println(" ois.close();");
+ out.println(" }");
+ out.println(" } catch ( IOException e ) {");
+ out.println(" data = null;");
+ out.println(" } catch ( ClassNotFoundException e ) {");
+ out.println(" data = null;");
+ out.println(" } finally {");
+ out.println(" if ( is != null ) {");
+ out.println(" try { is.close(); } catch ( Exception e ) {}");
+ out.println(" }");
+ out.println(" }");
+ out.println(" return data;");
+ out.println(" }");
+ out.println("}");
+ out.flush();
+ out.close();
+
+ }
+
+ /**
+ * Read bidi type data.
+ *
+ * @param ucdFileName name (as URL) of unicode character database data
+ */
+ private static void readBidiTypeData(String ucdFileName) throws Exception {
+ BufferedReader b = new BufferedReader(new InputStreamReader(new URL(ucdFileName).openStream()));
+ String line;
+ int n;
+ // singleton map - derived from single char entry
+ Map/*<Integer,List>*/ sm = new HashMap/*<Integer,List>*/();
+ // interval map - derived from pair of block endpoint entries
+ Map/*<String,int[3]>*/ im = new HashMap/*<String,int[3]>*/();
+ if ( verbose ) {
+ System.out.print("Reading bidi type data...");
+ }
+ for ( lineNumber = 0; ( line = b.readLine() ) != null; ) {
+ lineNumber++;
+ if ( line.length() == 0 ) {
+ continue;
+ } else if ( line.startsWith("#") ) {
+ continue;
+ } else {
+ parseTypeProperties ( line, sm, im );
+ }
+ }
+ // extract type data list
+ List tdl = processTypeData ( sm, im, new ArrayList() );
+ // dump instrumentation
+ if ( verbose ) {
+ System.out.println();
+ System.out.println("Read type ranges : " + numTypeRanges );
+ System.out.println("Read lines : " + lineNumber );
+ }
+ td = (int[][]) tdl.toArray ( new int [ tdl.size() ] [] );
+ }
+
+ private static void parseTypeProperties ( String line, Map/*<Integer,List>*/ sm, Map/*<String,int[3]>*/ im ) {
+ String[] sa = line.split(";");
+ if ( sa.length >= 5 ) {
+ int uc = Integer.parseInt ( sa[0], 16 );
+ int bc = parseBidiClassAny ( sa[4] );
+ if ( bc >= 0 ) {
+ String ucName = sa[1];
+ if ( isBlockStart ( ucName ) ) {
+ String ucBlock = getBlockName ( ucName );
+ if ( ! im.containsKey ( ucBlock ) ) {
+ im.put ( ucBlock, new int[] { uc, -1, bc } );
+ } else {
+ throw new IllegalArgumentException ( "duplicate start of block '" + ucBlock + "' at entry: " + line );
+ }
+ } else if ( isBlockEnd ( ucName ) ) {
+ String ucBlock = getBlockName ( ucName );
+ if ( im.containsKey ( ucBlock ) ) {
+ int[] ba = (int[]) im.get ( ucBlock );
+ assert ba.length == 3;
+ if ( ba[1] < 0 ) {
+ ba[1] = uc;
+ } else {
+ throw new IllegalArgumentException ( "duplicate end of block '" + ucBlock + "' at entry: " + line );
+ }
+ } else {
+ throw new IllegalArgumentException ( "missing start of block '" + ucBlock + "' at entry: " + line );
+ }
+ } else {
+ Integer k = Integer.valueOf ( bc );
+ List sl;
+ if ( ! sm.containsKey ( k ) ) {
+ sl = new ArrayList();
+ sm.put ( k, sl );
+ } else {
+ sl = (List) sm.get ( k );
+ }
+ assert sl != null;
+ sl.add ( Integer.valueOf ( uc ) );
+ }
+ } else {
+ throw new IllegalArgumentException ( "invalid bidi class '" + sa[4] + "' at entry: " + line );
+ }
+ } else {
+ throw new IllegalArgumentException ( "invalid unicode character database entry: " + line );
+ }
+ }
+
+ private static boolean isBlockStart ( String s ) {
+ return s.startsWith("<") && s.endsWith("First>");
+ }
+
+ private static boolean isBlockEnd ( String s ) {
+ return s.startsWith("<") && s.endsWith("Last>");
+ }
+
+ private static String getBlockName ( String s ) {
+ String[] sa = s.substring ( 1, s.length() - 1 ).split(",");
+ assert ( sa != null ) && ( sa.length > 0 );
+ return sa[0].trim();
+ }
+
+ private static List processTypeData ( Map/*<Integer,List>*/ sm, Map/*<String,int[3]>*/ im, List tdl ) {
+ for ( int i = BidiConstants.FIRST, k = BidiConstants.LAST; i <= k; i++ ) {
+ Map/*<Integer,Integer>*/ rm = new TreeMap/*<Integer,Integer>*/();
+ // populate intervals from singleton map
+ List sl = (List) sm.get ( Integer.valueOf ( i ) );
+ if ( sl != null ) {
+ for ( Iterator it = sl.iterator(); it.hasNext(); ) {
+ Integer s = (Integer) it.next();
+ int uc = s.intValue();
+ rm.put ( Integer.valueOf ( uc ), Integer.valueOf ( uc + 1 ) );
+ }
+ }
+ // populate intervals from (block) interval map
+ if ( ! im.isEmpty() ) {
+ for ( Iterator it = im.values().iterator(); it.hasNext(); ) {
+ int[] ba = (int[]) it.next();
+ assert ( ba != null ) && ( ba.length > 2 );
+ if ( ba[2] == i ) {
+ rm.put ( Integer.valueOf ( ba[0] ), Integer.valueOf ( ba[1] + 1 ) );
+ }
+ }
+ }
+ tdl.add ( createTypeData ( i, extractRanges ( rm ) ) );
+ }
+ return tdl;
+ }
+
+ private static List extractRanges ( Map/*<Integer,Integer>*/ rm ) {
+ List ranges = new ArrayList();
+ int sLast = 0;
+ int eLast = 0;
+ for ( Iterator it = rm.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry/*<Integer,Integer>*/ me = (Map.Entry/*<Integer,Integer>*/) it.next();
+ int s = ((Integer) me.getKey()).intValue();
+ int e = ((Integer) me.getValue()).intValue();
+ if ( s > eLast ) {
+ if ( eLast > sLast ) {
+ ranges.add ( new int[] { sLast, eLast } );
+ if ( verbose ) {
+ if ( ( ++numTypeRanges % 10 ) == 0 ) {
+ System.out.print("#");
+ }
+ }
+ }
+ sLast = s;
+ eLast = e;
+ } else if ( ( s >= sLast ) && ( e >= eLast ) ) {
+ eLast = e;
+ }
+ }
+ if ( eLast > sLast ) {
+ ranges.add ( new int[] { sLast, eLast } );
+ if ( verbose ) {
+ if ( ( ++numTypeRanges % 10 ) == 0 ) {
+ System.out.print("#");
+ }
+ }
+ }
+ return ranges;
+ }
+
+ /**
+ * Read biditest data.
+ *
+ * @param bidiFileName name (as URL) of bidi test data
+ */
+ private static void readBidiTestData(String bidiFileName) throws Exception {
+ BufferedReader b = new BufferedReader(new InputStreamReader(new URL(bidiFileName).openStream()));
+ String line;
+ int n;
+ List tdl = new ArrayList();
+ List ldl = new ArrayList();
+ if ( verbose ) {
+ System.out.print("Reading bidi test data...");
+ }
+ for ( lineNumber = 0; ( line = b.readLine() ) != null; ) {
+ lineNumber++;
+ if ( line.length() == 0 ) {
+ continue;
+ } else if ( line.startsWith("#") ) {
+ continue;
+ } else if ( line.startsWith(PFX_TYPE) && ! ignoreDeprecatedTypeData ) {
+ List lines = new ArrayList();
+ if ( ( n = readType ( line, b, lines ) ) < 0 ) {
+ break;
+ } else {
+ lineNumber += n;
+ tdl.add ( parseType ( lines ) );
+ }
+ } else if ( line.startsWith(PFX_LEVELS) ) {
+ List lines = new ArrayList();
+ if ( ( n = readLevels ( line, b, lines ) ) < 0 ) {
+ break;
+ } else {
+ lineNumber += n;
+ ldl.add ( parseLevels ( lines ) );
+ }
+ }
+ }
+ // dump instrumentation
+ if ( verbose ) {
+ System.out.println();
+ if ( ! ignoreDeprecatedTypeData ) {
+ System.out.println("Read type ranges : " + numTypeRanges );
+ }
+ System.out.println("Read level specs : " + numLevelSpecs );
+ System.out.println("Read test specs : " + numTestSpecs );
+ System.out.println("Read lines : " + lineNumber );
+ }
+ if ( ! ignoreDeprecatedTypeData ) {
+ td = (int[][]) tdl.toArray ( new int [ tdl.size() ] [] );
+ }
+ ld = (int[][]) ldl.toArray ( new int [ ldl.size() ] [] );
+ }
+
+ private static int readType ( String line, BufferedReader b, List lines ) throws IOException {
+ lines.add ( line );
+ return 0;
+ }
+
+ private static int readLevels ( String line, BufferedReader b, List lines ) throws IOException {
+ boolean done = false;
+ int n = 0;
+ lines.add ( line );
+ while ( ! done ) {
+ switch ( testPrefix ( b, PFX_LEVELS ) ) {
+ case 0: // within current levels
+ if ( ( line = b.readLine() ) != null ) {
+ n++;
+ if ( ( line.length() > 0 ) && ! line.startsWith("#") ) {
+ lines.add ( line );
+ }
+ } else {
+ done = true;
+ }
+ break;
+ case 1: // end of current levels
+ case -1: // eof
+ default:
+ done = true;
+ break;
+ }
+ }
+ return n;
+ }
+
+ private static int testPrefix ( BufferedReader b, String pfx ) throws IOException {
+ int rv = 0;
+ int pfxLen = pfx.length();
+ b.mark ( pfxLen );
+ for ( int i = 0, n = pfxLen; i < n; i++ ) {
+ int c = b.read();
+ if ( c < 0 ) {
+ rv = -1;
+ break;
+ } else if ( c != pfx.charAt ( i ) ) {
+ rv = 0;
+ break;
+ } else {
+ rv = 1;
+ }
+ }
+ b.reset();
+ return rv;
+ }
+
+ private static int[] parseType ( List lines ) {
+ if ( ( lines != null ) && ( lines.size() >= 1 ) ) {
+ String line = (String) lines.get(0);
+ if ( line.startsWith(PFX_TYPE) ) {
+ // @Type: BIDI_CLASS ':' LWSP CHARACTER_CLASS
+ String[] sa = line.split ( ":" );
+ if ( sa.length == 3 ) {
+ String bcs = sa[1].trim();
+ String crs = sa[2].trim();
+ int bc = parseBidiClass ( bcs );
+ List rl = parseCharacterRanges ( crs );
+ return createTypeData ( bc, rl );
+ }
+ }
+ }
+ return null;
+ }
+
+ private static int[] createTypeData ( int bc, List ranges ) {
+ int[] data = new int [ 1 + ( 2 * ranges.size() ) ];
+ int k = 0;
+ data [ k++ ] = bc;
+ for ( Iterator it = ranges.iterator(); it.hasNext(); ) {
+ int[] r = (int[]) it.next();
+ data [ k++ ] = r [ 0 ];
+ data [ k++ ] = r [ 1 ];
+ }
+ return data;
+ }
+
+ private static int parseBidiClass ( String bidiClass ) {
+ int bc = 0;
+ if ( "L".equals ( bidiClass ) ) {
+ bc = BidiConstants.L;
+ } else if ( "LRE".equals ( bidiClass ) ) {
+ bc = BidiConstants.LRE;
+ } else if ( "LRO".equals ( bidiClass ) ) {
+ bc = BidiConstants.LRO;
+ } else if ( "R".equals ( bidiClass ) ) {
+ bc = BidiConstants.R;
+ } else if ( "AL".equals ( bidiClass ) ) {
+ bc = BidiConstants.AL;
+ } else if ( "RLE".equals ( bidiClass ) ) {
+ bc = BidiConstants.RLE;
+ } else if ( "RLO".equals ( bidiClass ) ) {
+ bc = BidiConstants.RLO;
+ } else if ( "PDF".equals ( bidiClass ) ) {
+ bc = BidiConstants.PDF;
+ } else if ( "EN".equals ( bidiClass ) ) {
+ bc = BidiConstants.EN;
+ } else if ( "ES".equals ( bidiClass ) ) {
+ bc = BidiConstants.ES;
+ } else if ( "ET".equals ( bidiClass ) ) {
+ bc = BidiConstants.ET;
+ } else if ( "AN".equals ( bidiClass ) ) {
+ bc = BidiConstants.AN;
+ } else if ( "CS".equals ( bidiClass ) ) {
+ bc = BidiConstants.CS;
+ } else if ( "NSM".equals ( bidiClass ) ) {
+ bc = BidiConstants.NSM;
+ } else if ( "BN".equals ( bidiClass ) ) {
+ bc = BidiConstants.BN;
+ } else if ( "B".equals ( bidiClass ) ) {
+ bc = BidiConstants.B;
+ } else if ( "S".equals ( bidiClass ) ) {
+ bc = BidiConstants.S;
+ } else if ( "WS".equals ( bidiClass ) ) {
+ bc = BidiConstants.WS;
+ } else if ( "ON".equals ( bidiClass ) ) {
+ bc = BidiConstants.ON;
+ } else {
+ throw new IllegalArgumentException ( "unknown bidi class: " + bidiClass );
+ }
+ return bc;
+ }
+
+ private static int parseBidiClassAny ( String bidiClass ) {
+ try {
+ return parseBidiClass ( bidiClass );
+ } catch ( IllegalArgumentException e ) {
+ return -1;
+ }
+ }
+
+ private static List parseCharacterRanges ( String charRanges ) {
+ List ranges = new ArrayList();
+ CharacterIterator ci = new StringCharacterIterator ( charRanges );
+ // read initial list delimiter
+ skipSpace ( ci );
+ if ( ! readStartOfList ( ci ) ) {
+ badRangeSpec ( "missing initial list delimiter", charRanges );
+ }
+ // read negation token if present
+ boolean negated = false;
+ skipSpace ( ci );
+ if ( maybeReadNext ( ci, '^' ) ) {
+ negated = true;
+ }
+ // read item
+ int[] r;
+ skipSpace ( ci );
+ if ( ( r = maybeReadItem ( ci ) ) != null ) {
+ ranges.add ( r );
+ if ( verbose ) {
+ if ( ( ++numTypeRanges % 10 ) == 0 ) {
+ System.out.print("#");
+ }
+ }
+ } else {
+ badRangeSpec ( "must contain at least one item", charRanges );
+ }
+ // read more items if present
+ boolean more = true;
+ while ( more ) {
+ // read separator if present
+ String s;
+ skipSpace ( ci );
+ if ( ( s = maybeReadSeparator ( ci ) ) != null ) {
+ if ( ( s.length() != 0 ) && ! s.equals("||") ) {
+ badRangeSpec ( "invalid item separator \"" + s + "\"", charRanges );
+ }
+ }
+ // read item
+ skipSpace ( ci );
+ if ( ( r = maybeReadItem ( ci ) ) != null ) {
+ ranges.add ( r );
+ if ( verbose ) {
+ if ( ( ++numTypeRanges % 10 ) == 0 ) {
+ System.out.print("#");
+ }
+ }
+ } else {
+ more = false;
+ }
+ }
+ // read terminating list delimiter
+ skipSpace ( ci );
+ if ( ! readEndOfList ( ci ) ) {
+ badRangeSpec ( "missing terminating list delimiter", charRanges );
+ }
+ if ( ! atEnd ( ci ) ) {
+ badRangeSpec ( "extraneous content prior to end of line", ci );
+ }
+ if ( negated ) {
+ ranges = complementRanges ( ranges );
+ }
+ return removeSurrogates ( ranges );
+ }
+
+ private static boolean atEnd ( CharacterIterator ci ) {
+ return ci.getIndex() >= ci.getEndIndex();
+ }
+
+ private static boolean readStartOfList ( CharacterIterator ci ) {
+ return maybeReadNext ( ci, '[' );
+ }
+
+ private static void skipSpace ( CharacterIterator ci ) {
+ while ( ! atEnd ( ci ) ) {
+ char c = ci.current();
+ if ( ! Character.isWhitespace ( c ) ) {
+ break;
+ } else {
+ ci.next();
+ }
+ }
+ }
+
+ private static boolean maybeReadNext ( CharacterIterator ci, char next ) {
+ while ( ! atEnd ( ci ) ) {
+ char c = ci.current();
+ if ( c == next ) {
+ ci.next();
+ return true;
+ } else {
+ break;
+ }
+ }
+ return false;
+ }
+
+ private static int[] maybeReadItem ( CharacterIterator ci ) {
+ // read first code point
+ int p1 = -1;
+ skipSpace ( ci );
+ if ( ( p1 = maybeReadCodePoint ( ci ) ) < 0 ) {
+ return null;
+ }
+ // read second code point if present
+ int p2 = -1;
+ skipSpace ( ci );
+ if ( maybeReadNext ( ci, '-' ) ) {
+ skipSpace ( ci );
+ if ( ( p2 = maybeReadCodePoint ( ci ) ) < 0 ) {
+ badRangeSpec ( "incomplete item range, requires second item", ci );
+ }
+ }
+ if ( p2 < 0 ) {
+ return new int[] { p1, p1 + 1 }; // convert to half open interval [ P1, P1+1 )
+ } else if ( p1 <= p2 ) {
+ return new int[] { p1, p2 + 1 }; // convert to half open interval [ P1, P2+2 )
+ } else {
+ badRangeSpec ( "invalid item range, second item must be greater than or equal to first item", ci );
+ return null;
+ }
+ }
+
+ private static int maybeReadCodePoint ( CharacterIterator ci ) {
+ if ( maybeReadNext ( ci, '\\' ) ) {
+ if ( maybeReadNext ( ci, 'u' ) ) {
+ String s = maybeReadHexDigits ( ci, 4 );
+ if ( s != null ) {
+ return Integer.parseInt ( s, 16 );
+ } else {
+ badRangeSpec ( "incomplete escaped code point, requires 4 hex digits", ci );
+ }
+ } else if ( maybeReadNext ( ci, 'U' ) ) {
+ String s = maybeReadHexDigits ( ci, 8 );
+ if ( s != null ) {
+ return Integer.parseInt ( s, 16 );
+ } else {
+ badRangeSpec ( "incomplete escaped code point, requires 8 hex digits", ci );
+ }
+ } else {
+ char c = ci.current();
+ if ( c == CharacterIterator.DONE ) {
+ badRangeSpec ( "incomplete escaped code point", ci );
+ } else {
+ ci.next();
+ return (int) c;
+ }
+ }
+ } else {
+ char c = ci.current();
+ if ( ( c == CharacterIterator.DONE ) || ( c == ']' ) ) {
+ return -1;
+ } else {
+ ci.next();
+ return (int) c;
+ }
+ }
+ return -1;
+ }
+
+ private static String maybeReadHexDigits ( CharacterIterator ci, int numDigits ) {
+ StringBuffer sb = new StringBuffer();
+ while ( ( numDigits < 0 ) || ( sb.length() < numDigits ) ) {
+ char c = ci.current();
+ if ( c != CharacterIterator.DONE ) {
+ if ( isHexDigit ( c ) ) {
+ ci.next();
+ sb.append ( c );
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if ( ( ( numDigits < 0 ) && ( sb.length() > 0 ) ) || ( sb.length() == numDigits ) ) {
+ return sb.toString();
+ } else {
+ return null;
+ }
+ }
+
+ private static boolean isHexDigit ( char c ) {
+ return ( ( c >= '0' ) && ( c <= '9' ) ) || ( ( c >= 'a' ) && ( c <= 'f' ) ) || ( ( c >= 'A' ) && ( c <= 'F' ) );
+ }
+
+ private static String maybeReadSeparator ( CharacterIterator ci ) {
+ if ( maybeReadNext ( ci, '|' ) ) {
+ if ( maybeReadNext ( ci, '|' ) ) {
+ return "||";
+ } else {
+ return "|";
+ }
+ } else {
+ return "";
+ }
+ }
+
+ private static boolean readEndOfList ( CharacterIterator ci ) {
+ return maybeReadNext ( ci, ']' );
+ }
+
+ private static List complementRanges ( List ranges ) {
+ Map/*<Integer,Integer>*/ rm = new TreeMap/*<Integer,Integer>*/();
+ for ( Iterator it = ranges.iterator(); it.hasNext(); ) {
+ int[] r = (int[]) it.next();
+ rm.put ( Integer.valueOf ( r[0] ), Integer.valueOf ( r[1] ) );
+ }
+ // add complement ranges save last
+ int s, e, cs = 0;
+ List compRanges = new ArrayList ( rm.size() + 1 );
+ for ( Iterator it = rm.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry/*<Integer,Integer>*/ me = (Map.Entry/*<Integer,Integer>*/) it.next();
+ s = ( (Integer) me.getKey() ).intValue();
+ e = ( (Integer) me.getValue() ).intValue();
+ if ( s > cs ) {
+ compRanges.add ( new int[] { cs, s } );
+ }
+ cs = e;
+ }
+ // add trailing complement range
+ if ( cs < 0x110000 ) {
+ compRanges.add ( new int[] { cs, 0x110000 } );
+ }
+ return compRanges;
+ }
+
+ private static final int[] SURROGATES = new int[] { 0xD800, 0xE000 };
+
+ private static List removeSurrogates ( List ranges ) {
+ List rsl = new ArrayList ( ranges.size() );
+ for ( Iterator it = ranges.iterator(); it.hasNext(); ) {
+ int[] r = (int[]) it.next();
+ if ( intersectsRange ( r, SURROGATES ) ) {
+ rsl.addAll ( removeRange ( r, SURROGATES ) );
+ } else {
+ rsl.add ( r );
+ }
+ }
+ return rsl;
+ }
+
+ /**
+ * Determine if range r2 intersects with range r1.
+ */
+ private static boolean intersectsRange ( int[] r1, int[] r2 ) {
+ if ( r1[1] <= r2[0] ) { // r1 precedes r2 or abuts r2 on right
+ return false;
+ } else if ( r1[0] >= r2[1] ) { // r2 precedes r1 or abuts r1 on left
+ return false;
+ } else if ( ( r1[0] < r2[0] ) && ( r1[1] > r2[1] ) ) { // r1 encloses r2
+ return true;
+ } else if ( r1[0] < r2[0] ) { // r1 precedes and overlaps r2
+ return true;
+ } else if ( r2[1] < r1[1] ) { // r2 precedes and overlaps r1
+ return true;
+ } else { // r2 encloses r1
+ return true;
+ }
+ }
+
+ /**
+ * Remove range r2 from range r1, leaving zero, one, or two
+ * remaining ranges.
+ */
+ private static List removeRange ( int[] r1, int[] r2 ) {
+ List rl = new ArrayList();
+ if ( r1[1] <= r2[0] ) { // r1 precedes r2 or abuts r2 on right
+ rl.add ( r1 );
+ } else if ( r1[0] >= r2[1] ) { // r2 precedes r1 or abuts r1 on left
+ rl.add ( r1 );
+ } else if ( ( r1[0] < r2[0] ) && ( r1[1] > r2[1] ) ) { // r1 encloses r2
+ rl.add ( new int[] { r1[0], r2[0] } );
+ rl.add ( new int[] { r2[1], r1[1] } );
+ } else if ( r1[0] < r2[0] ) { // r1 precedes and overlaps r2
+ rl.add ( new int[] { r1[0], r2[0] } );
+ } else if ( r2[1] < r1[1] ) { // r2 precedes and overlaps r1
+ rl.add ( new int[] { r2[1], r1[1] } );
+ }
+ return rl;
+ }
+
+ private static void badRangeSpec ( String reason, String charRanges ) throws IllegalArgumentException {
+ if ( verbose ) {
+ System.out.println();
+ }
+ throw new IllegalArgumentException ( "bad range specification: " + reason + ": \"" + charRanges + "\"" );
+ }
+
+ private static void badRangeSpec ( String reason, CharacterIterator ci ) throws IllegalArgumentException {
+ if ( verbose ) {
+ System.out.println();
+ }
+ throw new IllegalArgumentException ( "bad range specification: " + reason + ": starting at \"" + remainder ( ci ) + "\"" );
+ }
+
+ private static String remainder ( CharacterIterator ci ) {
+ StringBuffer sb = new StringBuffer();
+ for ( char c; ( c = ci.current() ) != CharacterIterator.DONE; ) {
+ ci.next();
+ sb.append ( c );
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Parse levels segment, consisting of multiple lines as follows:
+ *
+ * LEVEL_SPEC \n
+ * REORDER_SPEC \n
+ * ( TEST_SPEC \n )+
+ */
+ private static int[] parseLevels ( List lines ) {
+ int[] la = null; // levels array
+ int[] ra = null; // reorder array
+ List tal = new ArrayList();
+ if ( ( lines != null ) && ( lines.size() >= 3 ) ) {
+ for ( Iterator it = lines.iterator(); it.hasNext(); ) {
+ String line = (String) it.next();
+ if ( line.startsWith(PFX_LEVELS) ) {
+ if ( la == null ) {
+ la = parseLevelSpec ( line );
+ if ( verbose ) {
+ if ( ( ++numLevelSpecs % 10 ) == 0 ) {
+ System.out.print("&");
+ }
+ }
+ } else {
+ throw new IllegalArgumentException ( "redundant levels array: \"" + line + "\"" );
+ }
+ } else if ( line.startsWith(PFX_REORDER) ) {
+ if ( la == null ) {
+ throw new IllegalArgumentException ( "missing levels array before: \"" + line + "\"" );
+ } else if ( ra == null ) {
+ ra = parseReorderSpec ( line, la );
+ } else {
+ throw new IllegalArgumentException ( "redundant reorder array: \"" + line + "\"" );
+ }
+ } else if ( ( la != null ) && ( ra != null ) ) {
+ int[] ta = parseTestSpec ( line, la );
+ if ( ta != null ) {
+ if ( verbose ) {
+ if ( ( ++numTestSpecs % 100 ) == 0 ) {
+ System.out.print("!");
+ }
+ }
+ tal.add ( ta );
+ }
+ } else if ( la == null ) {
+ throw new IllegalArgumentException ( "missing levels array before: \"" + line + "\"" );
+ } else if ( ra == null ) {
+ throw new IllegalArgumentException ( "missing reorder array before: \"" + line + "\"" );
+ }
+ }
+ }
+ if ( ( la != null ) && ( ra != null ) ) {
+ return createLevelData ( la, ra, tal );
+ } else {
+ return null;
+ }
+ }
+
+ private static int[] createLevelData ( int[] la, int[] ra, List tal ) {
+ int nl = la.length;
+ int[] data = new int [ 1 + nl * 2 + ( ( nl + 1 ) * tal.size() ) ];
+ int k = 0;
+ data [ k++ ] = nl;
+ for ( int i = 0, n = nl; i < n; i++ ) {
+ data [ k++ ] = la [ i ];
+ }
+ int nr = ra.length;
+ for ( int i = 0, n = nr; i < n; i++ ) {
+ data [ k++ ] = ra [ i ];
+ }
+ for ( Iterator it = tal.iterator(); it.hasNext(); ) {
+ int[] ta = (int[]) it.next();
+ if ( ta == null ) {
+ throw new IllegalStateException ( "null test array" );
+ } else if ( ta.length == ( nl + 1 ) ) {
+ for ( int i = 0, n = ta.length; i < n; i++ ) {
+ data [ k++ ] = ta [ i ];
+ }
+ } else {
+ throw new IllegalStateException ( "test array length error, expected " + ( nl + 1 ) + " entries, got " + ta.length + " entries" );
+ }
+ }
+ assert k == data.length;
+ return data;
+ }
+
+ /**
+ * Parse level specification, which follows the following syntax:
+ *
+ * @Levels: ( LWSP ( NUMBER | 'x' ) )+
+ */
+ private static int[] parseLevelSpec ( String line ) {
+ CharacterIterator ci = new StringCharacterIterator ( line );
+ List ll = new ArrayList();
+ // read prefix
+ skipSpace ( ci );
+ if ( ! maybeReadToken ( ci, PFX_LEVELS ) ) {
+ badLevelSpec ( "missing prefix \"" + PFX_LEVELS + "\"", ci );
+ }
+ // read level values
+ boolean more = true;
+ while ( more ) {
+ Integer l;
+ skipSpace ( ci );
+ if ( ( l = maybeReadInteger ( ci ) ) != null ) {
+ ll.add ( l );
+ } else if ( maybeReadToken ( ci, "x" ) ) {
+ ll.add ( Integer.valueOf ( -1 ) );
+ } else {
+ more = false;
+ }
+ }
+ // read to end of line
+ skipSpace ( ci );
+ if ( ! atEnd ( ci ) ) {
+ badLevelSpec ( "extraneous content prior to end of line", ci );
+ }
+ if ( ll.size() == 0 ) {
+ badLevelSpec ( "must have at least one level value", ci );
+ }
+ return createLevelsArray ( ll );
+ }
+
+ private static Integer maybeReadInteger ( CharacterIterator ci ) {
+ // read optional minus sign if present
+ boolean negative;
+ if ( maybeReadNext ( ci, '-' ) ) {
+ negative = true;
+ } else {
+ negative = false;
+ }
+ // read digits
+ StringBuffer sb = new StringBuffer();
+ while ( true ) {
+ char c = ci.current();
+ if ( ( c != CharacterIterator.DONE ) && isDigit ( c ) ) {
+ ci.next();
+ sb.append ( c );
+ } else {
+ break;
+ }
+ }
+ if ( sb.length() == 0 ) {
+ return null;
+ } else {
+ int value = Integer.parseInt ( sb.toString() );
+ if ( negative ) {
+ value = -value;
+ }
+ return Integer.valueOf ( value );
+ }
+ }
+
+ private static boolean isDigit ( char c ) {
+ return ( ( c >= '0' ) && ( c <= '9' ) );
+ }
+
+ private static boolean maybeReadToken ( CharacterIterator ci, String s ) {
+ int startIndex = ci.getIndex();
+ for ( int i = 0, n = s.length(); i < n; i++ ) {
+ char c = s.charAt ( i );
+ if ( ci.current() == c ) {
+ ci.next();
+ } else {
+ ci.setIndex ( startIndex );
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static void badLevelSpec ( String reason, CharacterIterator ci ) throws IllegalArgumentException {
+ if ( verbose ) {
+ System.out.println();
+ }
+ throw new IllegalArgumentException ( "bad level specification: " + reason + ": starting at \"" + remainder ( ci ) + "\"" );
+ }
+
+ private static int[] createLevelsArray ( List levels ) {
+ int[] la = new int [ levels.size() ];
+ int k = 0;
+ for ( Iterator it = levels.iterator(); it.hasNext(); ) {
+ la [ k++ ] = ( (Integer) it.next() ).intValue();
+ }
+ return la;
+ }
+
+ /**
+ * Parse reorder specification, which follows the following syntax:
+ *
+ * @Reorder: ( LWSP NUMBER )*
+ */
+ private static int[] parseReorderSpec ( String line, int[] levels ) {
+ CharacterIterator ci = new StringCharacterIterator ( line );
+ List rl = new ArrayList();
+ // read prefix
+ skipSpace ( ci );
+ if ( ! maybeReadToken ( ci, PFX_REORDER ) ) {
+ badReorderSpec ( "missing prefix \"" + PFX_REORDER + "\"", ci );
+ }
+ // read reorder values
+ boolean more = true;
+ while ( more ) {
+ skipSpace ( ci );
+ Integer l;
+ if ( ( l = maybeReadInteger ( ci ) ) != null ) {
+ rl.add ( l );
+ } else {
+ more = false;
+ }
+ }
+ // read to end of line
+ skipSpace ( ci );
+ if ( ! atEnd ( ci ) ) {
+ badReorderSpec ( "extraneous content prior to end of line", ci );
+ }
+ return createReorderArray ( rl, levels );
+ }
+
+ private static void badReorderSpec ( String reason, CharacterIterator ci ) throws IllegalArgumentException {
+ if ( verbose ) {
+ System.out.println();
+ }
+ throw new IllegalArgumentException ( "bad reorder specification: " + reason + ": starting at \"" + remainder ( ci ) + "\"" );
+ }
+
+ private static int[] createReorderArray ( List reorders, int[] levels ) {
+ int nr = reorders.size();
+ int nl = levels.length;
+ if ( nr <= nl ) {
+ int[] ra = new int [ nl ];
+ Iterator it = reorders.iterator();
+ for ( int i = 0, n = nl; i < n; i++ ) {
+ int r = -1;
+ if ( levels [ i ] >= 0 ) {
+ if ( it.hasNext() ) {
+ r = ( (Integer) it.next() ).intValue();
+ }
+ }
+ ra [ i ] = r;
+ }
+ return ra;
+ } else {
+ throw new IllegalArgumentException ( "excessive number of reorder array entries, expected no more than " + nl + ", but got " + nr + " entries" );
+ }
+ }
+
+ /**
+ * Parse test specification, which follows the following syntax:
+ *
+ * BIDI_CLASS ( LWSP BIDI_CLASS )+ ';' LWSP NUMBER
+ */
+ private static int[] parseTestSpec ( String line, int[] levels ) {
+ CharacterIterator ci = new StringCharacterIterator ( line );
+ List cl = new ArrayList();
+ // read bidi class identifier sequence
+ while ( ! atEnd ( ci ) && ! maybeReadNext ( ci, ';' ) ) {
+ skipSpace ( ci );
+ int bc;
+ if ( ( bc = maybeReadBidiClass ( ci ) ) >= 0 ) {
+ cl.add ( Integer.valueOf ( bc ) );
+ } else {
+ break;
+ }
+ }
+ // read bit set
+ skipSpace ( ci );
+ String s;
+ int bs = 0;
+ if ( ( s = maybeReadHexDigits ( ci, -1 ) ) != null ) {
+ bs = Integer.parseInt ( s, 16 );
+ } else {
+ badTestSpec ( "missing bit set", ci );
+ }
+ // read to end of line
+ skipSpace ( ci );
+ if ( ! atEnd ( ci ) ) {
+ badTestSpec ( "extraneous content prior to end of line", ci );
+ }
+ return createTestArray ( cl, bs, levels );
+ }
+
+ private static String maybeReadIdentifier ( CharacterIterator ci ) {
+ // read keyword chars ([A-Z])
+ StringBuffer sb = new StringBuffer();
+ while ( true ) {
+ char c = ci.current();
+ if ( c == CharacterIterator.DONE ) {
+ break;
+ } else if ( sb.length() == 0 ) {
+ if ( Character.isUnicodeIdentifierStart ( c ) ) {
+ ci.next();
+ sb.append ( c );
+ } else {
+ break;
+ }
+ } else {
+ if ( Character.isUnicodeIdentifierPart ( c ) ) {
+ ci.next();
+ sb.append ( c );
+ } else {
+ break;
+ }
+ }
+ }
+ if ( sb.length() == 0 ) {
+ return null;
+ } else {
+ return sb.toString();
+ }
+ }
+
+ private static int maybeReadBidiClass ( CharacterIterator ci ) {
+ int bc = -1;
+ int i = ci.getIndex();
+ String s;
+ if ( ( s = maybeReadIdentifier ( ci ) ) != null ) {
+ try {
+ bc = parseBidiClass ( s );
+ } catch ( IllegalArgumentException e ) {
+ throw e;
+ }
+ }
+ if ( bc < 0 ) {
+ ci.setIndex ( i );
+ }
+ return bc;
+ }
+
+ private static void badTestSpec ( String reason, CharacterIterator ci ) throws IllegalArgumentException {
+ if ( verbose ) {
+ System.out.println();
+ }
+ throw new IllegalArgumentException ( "bad test specification: " + reason + ": starting at \"" + remainder ( ci ) + "\"" );
+ }
+
+ private static int[] createTestArray ( List classes, int bitset, int[] levels ) {
+ int nc = classes.size();
+ if ( nc <= levels.length ) {
+ int[] ta = new int [ 1 + nc ];
+ int k = 0;
+ ta [ k++ ] = bitset;
+ for ( Iterator it = classes.iterator(); it.hasNext(); ) {
+ ta [ k++ ] = ( (Integer) it.next() ).intValue();
+ }
+ return ta;
+ } else {
+ throw new IllegalArgumentException ( "excessive number of test array entries, expected no more than " + levels.length + ", but got " + nc + " entries" );
+ }
+ }
+
+ /**
+ * Dump data arrays to output and resource files.
+ * @param out - bidi test data java class file print writer
+ * @param outFileName - (full path) name of bidi test data java class file
+ */
+ private static void dumpData ( PrintWriter out, String outFileName ) throws IOException {
+ File f = new File ( outFileName );
+ File p = f.getParentFile();
+ if ( td != null ) {
+ String pfxTD = "TD";
+ dumpResourcesDescriptor ( out, pfxTD, td.length );
+ dumpResourcesData ( p, f.getName(), pfxTD, td );
+ }
+ if ( ld != null ) {
+ String pfxTD = "LD";
+ dumpResourcesDescriptor ( out, pfxTD, ld.length );
+ dumpResourcesData ( p, f.getName(), pfxTD, ld );
+ }
+ }
+
+ private static void dumpResourcesDescriptor ( PrintWriter out, String prefix, int numResources ) {
+ out.println ( " public static final String " + prefix + "_PFX = \"" + prefix + "\";" );
+ out.println ( " public static final int " + prefix + "_CNT = " + numResources + ";" );
+ out.println("");
+ }
+
+ private static void dumpResourcesData ( File btcDir, String btcName, String prefix, int[][] data ) throws IOException {
+ String btdName = extractDataFileName ( btcName );
+ for ( int i = 0, n = data.length; i < n; i++ ) {
+ File f = new File ( btcDir, btdName + "$" + prefix + i + ".ser" );
+ ObjectOutputStream os = new ObjectOutputStream ( new FileOutputStream ( f ) );
+ os.writeObject ( data[i] );
+ os.close();
+ }
+ }
+
+ private static final String JAVA_EXT = ".java";
+
+ private static String extractDataFileName ( String btcName ) {
+ if ( btcName.endsWith ( JAVA_EXT ) ) {
+ return btcName.substring ( 0, btcName.length() - JAVA_EXT.length() );
+ } else {
+ return btcName;
+ }
+ }
+
+ /**
+ * Main entry point for generator.
+ * @param args array of command line arguments
+ */
+ public static void main(String[] args) {
+ String bidiFileName = "http://www.unicode.org/Public/UNIDATA/BidiTest.txt";
+ String ucdFileName = "http://www.unicode.org/Public/UNIDATA/BidiTest.txt";
+ String outFileName = "BidiTestData.java";
+ boolean ok = true;
+ for (int i = 0; ok && ( i < args.length ); i++) {
+ String opt = args[i];
+ if ("-b".equals(opt)) {
+ if ( ( i + 1 ) <= args.length ) {
+ bidiFileName = args[++i];
+ } else {
+ ok = false;
+ }
+ } else if ("-d".equals(opt)) {
+ if ( ( i + 1 ) <= args.length ) {
+ ucdFileName = args[++i];
+ } else {
+ ok = false;
+ }
+ } else if ("-i".equals(opt)) {
+ ignoreDeprecatedTypeData = true;
+ } else if ("-o".equals(opt)) {
+ if ( ( i + 1 ) <= args.length ) {
+ outFileName = args[++i];
+ } else {
+ ok = false;
+ }
+ } else if ("-v".equals(opt)) {
+ verbose = true;
+ } else {
+ ok = false;
+ }
+ }
+ if ( ! ok ) {
+ System.out.println("Usage: GenerateBidiTestData [-v] [-i] [-d <ucdFile>] [-b <bidiFile>] [-o <outputFile>]");
+ System.out.println(" defaults:");
+ if ( ignoreDeprecatedTypeData ) {
+ System.out.println(" <ucdFile> : " + ucdFileName);
+ }
+ System.out.println(" <bidiFile> : " + bidiFileName);
+ System.out.println(" <outputFile> : " + outFileName);
+ } else {
+ try {
+ convertBidiTestData(ucdFileName, bidiFileName, outFileName);
+ System.out.println("Generated " + outFileName + " from");
+ if ( ignoreDeprecatedTypeData ) {
+ System.out.println(" <ucdFile> : " + ucdFileName);
+ }
+ System.out.println(" <bidiFile> : " + bidiFileName);
+ } catch (Exception e) {
+ System.out.println("An unexpected error occured at line: " + lineNumber );
+ e.printStackTrace();
+ }
+ }
+ }
+}
Modified: xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml (original)
+++ xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml Sun Feb 26 02:29:01 2012
@@ -152,6 +152,21 @@
<td>false</td>
</tr>
<tr>
+ <td>complex-scripts</td>
+ <td>attribute disabled (optional)</td>
+ <td>
+ If present and if an attribute 'disabled' is specified with the value 'false', then
+ complex script features are disabled. The same result can be obtained on an FOP
+ per-invocation basis by specifying a '-nocs' command line option when invoking FOP.
+ When complex script features are disabled, all bidirectional processing and complex
+ character to glyph mapping processing is disabled; in addition, the loading of
+ GDEF, GSUB, and GPOS advanced typographic tables is disabled for OpenType and
+ TrueType fonts. Unless disabled by this mechanism or by use of the '-nocs' command
+ line option, complex script features will be enabled by default.
+ </td>
+ <td>n/a</td>
+ </tr>
+ <tr>
<td>default-page-settings</td>
<td>n/a</td>
<td>
Modified: xmlgraphics/fop/trunk/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd (original)
+++ xmlgraphics/fop/trunk/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd Sun Feb 26 02:29:01 2012
@@ -100,10 +100,10 @@
<xs:element name="border-rect">
<xs:complexType>
<xs:attributeGroup ref="mf:rectAtts"/>
- <xs:attribute name="start" type="mf:borderDef"/>
- <xs:attribute name="end" type="mf:borderDef"/>
- <xs:attribute name="before" type="mf:borderDef"/>
- <xs:attribute name="after" type="mf:borderDef"/>
+ <xs:attribute name="left" type="mf:borderDef"/>
+ <xs:attribute name="right" type="mf:borderDef"/>
+ <xs:attribute name="top" type="mf:borderDef"/>
+ <xs:attribute name="bottom" type="mf:borderDef"/>
</xs:complexType>
</xs:element>
<xs:element name="image">
Modified: xmlgraphics/fop/trunk/src/foschema/fop-configuration.xsd
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/foschema/fop-configuration.xsd?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/foschema/fop-configuration.xsd (original)
+++ xmlgraphics/fop/trunk/src/foschema/fop-configuration.xsd Sun Feb 26 02:29:01 2012
@@ -48,6 +48,11 @@
<xsd:attribute name="height" type="xsd:string"></xsd:attribute>
</xsd:complexType>
</xsd:element>
+ <xsd:element name="complex-scripts" minOccurs="0"
+ <xsd:complexType>
+ <xsd:attribute name="disabled" type="xsd:boolean"/>
+ </xsd:complexType>
+ </xsd:element>
<xsd:element name="renderers" minOccurs="0">
<xsd:complexType>
<xsd:sequence>
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOUserAgent.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOUserAgent.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOUserAgent.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOUserAgent.java Sun Feb 26 02:29:01 2012
@@ -654,6 +654,24 @@ public class FOUserAgent {
}
/**
+ * Check whether complex script features are enabled.
+ *
+ * @return true if FOP is to use complex script features
+ */
+ public boolean isComplexScriptFeaturesEnabled() {
+ return factory.isComplexScriptFeaturesEnabled();
+ }
+
+ /**
+ * Control whether complex script features should be enabled
+ *
+ * @param useComplexScriptFeatures true if FOP is to use complex script features
+ */
+ public void setComplexScriptFeaturesEnabled(boolean useComplexScriptFeatures) {
+ factory.setComplexScriptFeaturesEnabled ( useComplexScriptFeatures );
+ }
+
+ /**
* Activates accessibility (for output formats that support it).
*
* @param accessibility <code>true</code> to enable accessibility support
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FopFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FopFactory.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FopFactory.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FopFactory.java Sun Feb 26 02:29:01 2012
@@ -143,6 +143,10 @@ public class FopFactory implements Image
/** Page width */
private String pageWidth = FopFactoryConfigurator.DEFAULT_PAGE_WIDTH;
+ /** Complex scripts support enabled */
+ private boolean useComplexScriptFeatures
+ = FopFactoryConfigurator.DEFAULT_COMPLEX_SCRIPT_FEATURES;
+
/** @see #setBreakIndentInheritanceOnReferenceAreaBoundary(boolean) */
private boolean breakIndentInheritanceOnReferenceAreaBoundary
= FopFactoryConfigurator.DEFAULT_BREAK_INDENT_INHERITANCE;
@@ -212,6 +216,19 @@ public class FopFactory implements Image
}
/**
+ * Sets complex script support.
+ * @param value <code>true</code> to enable complex script features,
+ * <code>false</code> otherwise
+ */
+ void setComplexScriptFeaturesEnabled(boolean value) {
+ this.useComplexScriptFeatures = value;
+ }
+
+ boolean isComplexScriptFeaturesEnabled() {
+ return useComplexScriptFeatures;
+ }
+
+ /**
* Returns a new {@link Fop} instance. FOP will be configured with a default user agent
* instance.
* <p>
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FopFactoryConfigurator.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FopFactoryConfigurator.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FopFactoryConfigurator.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FopFactoryConfigurator.java Sun Feb 26 02:29:01 2012
@@ -69,6 +69,9 @@ public class FopFactoryConfigurator {
/** Defines the default target resolution (72dpi) for FOP */
public static final float DEFAULT_TARGET_RESOLUTION = GraphicsConstants.DEFAULT_DPI; //dpi
+ /** Defines the default complex script support */
+ public static final boolean DEFAULT_COMPLEX_SCRIPT_FEATURES = true;
+
private static final String PREFER_RENDERER = "prefer-renderer";
/** logger instance */
@@ -269,6 +272,13 @@ public class FopFactoryConfigurator {
}
}
+ // configure complex script support
+ Configuration csConfig = cfg.getChild("complex-scripts");
+ if (csConfig != null) {
+ this.factory.setComplexScriptFeaturesEnabled
+ (!csConfig.getAttributeAsBoolean ( "disabled", false ));
+ }
+
// configure font manager
new FontManagerConfigurator(cfg, baseURI).configure(factory.getFontManager(), strict);
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Area.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Area.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Area.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Area.java Sun Feb 26 02:29:01 2012
@@ -25,6 +25,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.traits.BorderProps;
+import org.apache.fop.traits.WritingModeTraitsGetter;
// If the area appears more than once in the output
// or if the area has external data it is cached
@@ -41,27 +42,6 @@ public class Area extends AreaTreeObject
private static final long serialVersionUID = 6342888466142626492L;
- // stacking directions
- /**
- * Stacking left to right
- */
- public static final int LR = 0;
-
- /**
- * Stacking right to left
- */
- public static final int RL = 1;
-
- /**
- * Stacking top to bottom
- */
- public static final int TB = 2;
-
- /**
- * Stacking bottom to top
- */
- public static final int BT = 3;
-
// orientations for reference areas
/**
* Normal orientation
@@ -130,16 +110,20 @@ public class Area extends AreaTreeObject
protected int bpd;
/**
+ * Resolved bidirectional level for area.
+ */
+ protected int bidiLevel = -1;
+
+ /**
* Traits for this area stored in a HashMap
*/
- protected Map<Integer, Object> props = null;
+ protected transient Map<Integer, Object> traits = null;
/**
* logging instance
*/
protected static final Log log = LogFactory.getLog(Area.class);
-
/**
* Get the area class of this area.
*
@@ -226,6 +210,32 @@ public class Area extends AreaTreeObject
}
/**
+ * Set the bidirectional embedding level.
+ *
+ * @param bidiLevel the bidirectional embedding level
+ */
+ public void setBidiLevel ( int bidiLevel ) {
+ this.bidiLevel = bidiLevel;
+ }
+
+ /**
+ * Reset the bidirectional embedding level to default
+ * value (-1).
+ */
+ public void resetBidiLevel() {
+ setBidiLevel(-1);
+ }
+
+ /**
+ * Get the bidirectional embedding level.
+ *
+ * @return the bidirectional embedding level
+ */
+ public int getBidiLevel() {
+ return bidiLevel;
+ }
+
+ /**
* Return the sum of region border- and padding-before
*
* @return width in millipoints
@@ -379,10 +389,23 @@ public class Area extends AreaTreeObject
* @param prop the value of the trait
*/
public void addTrait(Integer traitCode, Object prop) {
- if (props == null) {
- props = new java.util.HashMap<Integer, Object>(20);
+ if (traits == null) {
+ traits = new java.util.HashMap<Integer, Object>(20);
+ }
+ traits.put(traitCode, prop);
+ }
+
+ /**
+ * Set traits on this area, copying from an existing traits map.
+ *
+ * @param traits the map of traits
+ */
+ public void setTraits ( Map traits ) {
+ if ( traits != null ) {
+ this.traits = new java.util.HashMap ( traits );
+ } else {
+ this.traits = null;
}
- props.put(traitCode, prop);
}
/**
@@ -391,12 +414,12 @@ public class Area extends AreaTreeObject
* @return the map of traits
*/
public Map<Integer, Object> getTraits() {
- return this.props;
+ return this.traits;
}
/** @return true if the area has traits */
public boolean hasTraits() {
- return (this.props != null);
+ return (this.traits != null);
}
/**
@@ -406,7 +429,7 @@ public class Area extends AreaTreeObject
* @return the trait value
*/
public Object getTrait(Integer traitCode) {
- return (props != null ? props.get(traitCode) : null);
+ return (traits != null ? traits.get(traitCode) : null);
}
/**
@@ -445,6 +468,14 @@ public class Area extends AreaTreeObject
}
/**
+ * Sets the writing mode traits for this area. Default implementation
+ * does nothing.
+ * @param wmtg a WM traits getter
+ */
+ public void setWritingModeTraits(WritingModeTraitsGetter wmtg) {
+ }
+
+ /**
* {@inheritDoc}
* @return ipd and bpd of area
*/
@@ -457,4 +488,3 @@ public class Area extends AreaTreeObject
return sb.toString();
}
}
-
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/AreaTreeHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/AreaTreeHandler.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/AreaTreeHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/AreaTreeHandler.java Sun Feb 26 02:29:01 2012
@@ -73,6 +73,9 @@ public class AreaTreeHandler extends FOE
/** The AreaTreeModel in use */
protected AreaTreeModel model;
+ // Flag for controlling complex script features (default: true).
+ private boolean useComplexScriptFeatures = true;
+
// Keeps track of all meaningful id references
private IDTracker idTracker;
@@ -108,6 +111,8 @@ public class AreaTreeHandler extends FOE
this.idTracker = new IDTracker();
+ this.useComplexScriptFeatures = userAgent.isComplexScriptFeaturesEnabled();
+
if (log.isDebugEnabled()) {
statistics = new Statistics();
}
@@ -169,6 +174,15 @@ public class AreaTreeHandler extends FOE
}
/**
+ * Check whether complex script features are enabled.
+ *
+ * @return true if using complex script features
+ */
+ public boolean isComplexScriptFeaturesEnabled() {
+ return useComplexScriptFeatures;
+ }
+
+ /**
* Prepare AreaTreeHandler for document processing This is called from
* FOTreeBuilder.startDocument()
*
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/AreaTreeParser.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/AreaTreeParser.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/AreaTreeParser.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/AreaTreeParser.java Sun Feb 26 02:29:01 2012
@@ -700,7 +700,7 @@ public class AreaTreeParser {
public void startElement(Attributes attributes) {
InlineArea inl = new InlineArea();
transferForeignObjects(attributes, inl);
- inl.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
+ inl.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
setAreaAttributes(attributes, inl);
setTraits(attributes, inl, SUBSET_COMMON);
setTraits(attributes, inl, SUBSET_BOX);
@@ -720,7 +720,7 @@ public class AreaTreeParser {
public void startElement(Attributes attributes) {
InlineParent ip = new InlineParent();
transferForeignObjects(attributes, ip);
- ip.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
+ ip.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
setAreaAttributes(attributes, ip);
setTraits(attributes, ip, SUBSET_COMMON);
setTraits(attributes, ip, SUBSET_BOX);
@@ -741,7 +741,7 @@ public class AreaTreeParser {
public void startElement(Attributes attributes) {
InlineBlockParent ibp = new InlineBlockParent();
transferForeignObjects(attributes, ibp);
- ibp.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
+ ibp.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
setAreaAttributes(attributes, ibp);
setTraits(attributes, ibp, SUBSET_COMMON);
setTraits(attributes, ibp, SUBSET_BOX);
@@ -769,7 +769,7 @@ public class AreaTreeParser {
setTraits(attributes, text, SUBSET_COLOR);
setTraits(attributes, text, SUBSET_FONT);
text.setBaselineOffset(XMLUtil.getAttributeAsInt(attributes, "baseline", 0));
- text.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
+ text.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
text.setTextLetterSpaceAdjust(XMLUtil.getAttributeAsInt(attributes,
"tlsadjust", 0));
text.setTextWordSpaceAdjust(XMLUtil.getAttributeAsInt(attributes,
@@ -791,8 +791,14 @@ public class AreaTreeParser {
int[] letterAdjust
= ConversionUtils.toIntArray(
lastAttributes.getValue("letter-adjust"), "\\s");
+ int level = XMLUtil.getAttributeAsInt(lastAttributes, "level", -1);
+ boolean reversed = XMLUtil.getAttributeAsBoolean(lastAttributes, "reversed", false);
+ int[][] gposAdjustments
+ = XMLUtil.getAttributeAsPositionAdjustments(lastAttributes, "position-adjust");
content.flip();
- WordArea word = new WordArea(content.toString().trim(), offset, letterAdjust);
+ WordArea word = new WordArea
+ ( offset, level, content.toString().trim(), letterAdjust,
+ null, gposAdjustments, reversed );
AbstractTextArea text = getCurrentText();
word.setParentArea(text);
text.addChildArea(word);
@@ -811,7 +817,8 @@ public class AreaTreeParser {
if (content.position() > 0) {
content.flip();
boolean adjustable = XMLUtil.getAttributeAsBoolean(lastAttributes, "adj", true);
- SpaceArea space = new SpaceArea(content.charAt(0), offset, adjustable);
+ int level = XMLUtil.getAttributeAsInt(lastAttributes, "level", -1);
+ SpaceArea space = new SpaceArea(offset, level, content.charAt(0), adjustable);
AbstractTextArea text = getCurrentText();
space.setParentArea(text);
text.addChildArea(space);
@@ -821,7 +828,7 @@ public class AreaTreeParser {
setTraits(lastAttributes, space, SUBSET_COMMON);
setTraits(lastAttributes, space, SUBSET_BOX);
setTraits(lastAttributes, space, SUBSET_COLOR);
- space.setOffset(offset);
+ space.setBlockProgressionOffset(offset);
Area parent = (Area)areaStack.peek();
parent.addChildArea(space);
}
@@ -842,7 +849,8 @@ public class AreaTreeParser {
setTraits(attributes, leader, SUBSET_BOX);
setTraits(attributes, leader, SUBSET_COLOR);
setTraits(attributes, leader, SUBSET_FONT);
- leader.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
+ leader.setBlockProgressionOffset
+ ( XMLUtil.getAttributeAsInt(attributes, "offset", 0) );
String ruleStyle = attributes.getValue("ruleStyle");
if (ruleStyle != null) {
leader.setRuleStyle(ruleStyle);
@@ -857,7 +865,8 @@ public class AreaTreeParser {
private class InlineViewportMaker extends AbstractMaker {
public void startElement(Attributes attributes) {
- InlineViewport viewport = new InlineViewport(null);
+ int level = XMLUtil.getAttributeAsInt(attributes, "level", -1);
+ InlineViewport viewport = new InlineViewport(null, level);
transferForeignObjects(attributes, viewport);
setAreaAttributes(attributes, viewport);
setTraits(attributes, viewport, SUBSET_COMMON);
@@ -865,7 +874,8 @@ public class AreaTreeParser {
setTraits(attributes, viewport, SUBSET_COLOR);
viewport.setContentPosition(XMLUtil.getAttributeAsRectangle2D(attributes, "pos"));
viewport.setClip(XMLUtil.getAttributeAsBoolean(attributes, "clip", false));
- viewport.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
+ viewport.setBlockProgressionOffset
+ ( XMLUtil.getAttributeAsInt(attributes, "offset", 0) );
Area parent = (Area)areaStack.peek();
parent.addChildArea(viewport);
areaStack.push(viewport);
@@ -1025,6 +1035,7 @@ public class AreaTreeParser {
private void setAreaAttributes(Attributes attributes, Area area) {
area.setIPD(Integer.parseInt(attributes.getValue("ipd")));
area.setBPD(Integer.parseInt(attributes.getValue("bpd")));
+ area.setBidiLevel(XMLUtil.getAttributeAsInt(attributes, "level", -1));
}
private static final Object[] SUBSET_COMMON = new Object[] {
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Block.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Block.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Block.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Block.java Sun Feb 26 02:29:01 2012
@@ -58,7 +58,6 @@ public class Block extends BlockParent {
*/
public static final int FIXED = 3;
- private int stacking = TB;
private int positioning = STACK;
/** if true, allow BPD update */
@@ -133,5 +132,13 @@ public class Block extends BlockParent {
return (startIndent != null ? startIndent : 0);
}
+ /**
+ * @return the end-indent trait
+ */
+ public int getEndIndent() {
+ Integer endIndent = (Integer)getTrait(Trait.END_INDENT);
+ return (endIndent != null ? endIndent : 0);
+ }
+
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/BodyRegion.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/BodyRegion.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/BodyRegion.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/BodyRegion.java Sun Feb 26 02:29:01 2012
@@ -22,6 +22,7 @@ package org.apache.fop.area;
import java.util.List;
import org.apache.fop.fo.pagination.RegionBody;
+import org.apache.fop.traits.WritingModeTraitsGetter;
/**
* This class is a container for the areas that may be generated by
@@ -140,6 +141,17 @@ public class BodyRegion extends RegionRe
}
/**
+ * Sets the writing mode traits for the main reference area of
+ * this body region area.
+ * @param wmtg a WM traits getter
+ */
+ public void setWritingModeTraits(WritingModeTraitsGetter wmtg) {
+ if ( getMainReference() != null ) {
+ getMainReference().setWritingModeTraits ( wmtg );
+ }
+ }
+
+ /**
* Clone this object.
*
* @return a shallow copy of this object
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/CTM.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/CTM.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/CTM.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/CTM.java Sun Feb 26 02:29:01 2012
@@ -25,10 +25,12 @@ import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import org.apache.fop.datatypes.FODimension;
+import org.apache.fop.traits.WritingMode;
import static org.apache.fop.fo.Constants.EN_LR_TB;
import static org.apache.fop.fo.Constants.EN_RL_TB;
import static org.apache.fop.fo.Constants.EN_TB_RL;
+import static org.apache.fop.fo.Constants.EN_TB_LR;
/**
* Describe a PDF or PostScript style coordinate transformation matrix (CTM).
@@ -42,7 +44,7 @@ public class CTM implements Serializable
private double a, b, c, d, e, f;
private static final CTM CTM_LRTB = new CTM(1, 0, 0, 1, 0, 0);
- private static final CTM CTM_RLTB = new CTM(-1, 0, 0, 1, 0, 0);
+ private static final CTM CTM_RLTB = new CTM(1, 0, 0, 1, 0, 0);
private static final CTM CTM_TBRL = new CTM(0, 1, -1, 0, 0, 0);
/**
@@ -126,28 +128,25 @@ public class CTM implements Serializable
* Return a CTM which will transform coordinates for a particular writing-mode
* into normalized first quandrant coordinates.
* @param wm A writing mode constant from fo.properties.WritingMode, ie.
- * one of LR_TB, RL_TB, TB_RL.
+ * one of LR_TB, RL_TB, TB_RL, TB_LR.
* @param ipd The inline-progression dimension of the reference area whose
* CTM is being set..
* @param bpd The block-progression dimension of the reference area whose
* CTM is being set.
* @return a new CTM with the required transform
*/
- public static CTM getWMctm(int wm, int ipd, int bpd) {
+ public static CTM getWMctm(WritingMode wm, int ipd, int bpd) {
CTM wmctm;
- switch (wm) {
+ switch (wm.getEnumValue()) {
case EN_LR_TB:
return new CTM(CTM_LRTB);
case EN_RL_TB:
- wmctm = new CTM(CTM_RLTB);
- wmctm.e = ipd;
- return wmctm;
- //return CTM_RLTB.translate(ipd, 0);
+ return new CTM(CTM_RLTB);
case EN_TB_RL: // CJK
+ case EN_TB_LR: // CJK
wmctm = new CTM(CTM_TBRL);
wmctm.e = bpd;
return wmctm;
- //return CTM_TBRL.translate(0, ipd);
default:
return null;
}
@@ -284,7 +283,7 @@ public class CTM implements Serializable
* @return CTM the coordinate transformation matrix (CTM)
*/
public static CTM getCTMandRelDims(int absRefOrient,
- int writingMode,
+ WritingMode writingMode,
Rectangle2D absVPrect,
FODimension reldims) {
int width, height;
@@ -335,12 +334,18 @@ public class CTM implements Serializable
* can set ipd and bpd appropriately based on the writing mode.
*/
- if (writingMode == EN_LR_TB || writingMode == EN_RL_TB) {
+ switch ( writingMode.getEnumValue() ) {
+ default:
+ case EN_LR_TB:
+ case EN_RL_TB:
reldims.ipd = width;
reldims.bpd = height;
- } else {
+ break;
+ case EN_TB_LR:
+ case EN_TB_RL:
reldims.ipd = height;
reldims.bpd = width;
+ break;
}
// Set a rectangle to be the writing-mode relative version???
// Now transform for writing mode
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LineArea.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LineArea.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LineArea.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LineArea.java Sun Feb 26 02:29:01 2012
@@ -21,6 +21,7 @@ package org.apache.fop.area;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.apache.fop.area.inline.InlineArea;
@@ -125,6 +126,24 @@ public class LineArea extends Area {
}
/**
+ * <p>Set (en masse) the inline child areas of this line area.</p>
+ * <p> Used by bidirectional processing after line area consituent reordering.</p>
+ * @param inlineAreas the list of inline areas
+ */
+ public void setInlineAreas ( List inlineAreas ) {
+ for ( Iterator<InlineArea> it = inlineAreas.iterator(); it.hasNext();) {
+ InlineArea ia = it.next();
+ Area pa = ia.getParentArea();
+ if ( pa == null ) {
+ ia.setParentArea ( this );
+ } else {
+ assert pa == this;
+ }
+ }
+ this.inlineAreas = inlineAreas;
+ }
+
+ /**
* Get the inline child areas of this line area.
*
* @return the list of inline areas
@@ -149,6 +168,21 @@ public class LineArea extends Area {
}
/**
+ * Get the end indent of this line area.
+ * The end indent is used for offsetting the end of
+ * the inline areas for alignment or other indents.
+ *
+ * @return the end indent value
+ */
+ public int getEndIndent() {
+ if (hasTrait(Trait.END_INDENT)) {
+ return getTraitAsInteger(Trait.END_INDENT);
+ } else {
+ return 0;
+ }
+ }
+
+ /**
* Updates the extents of the line area from its children.
*/
public void updateExtentsFromChildren() {
@@ -178,17 +212,21 @@ public class LineArea extends Area {
* @param ipdVariation the difference between old and new ipd
*/
public void handleIPDVariation(int ipdVariation) {
+ int si = getStartIndent();
+ int ei = getEndIndent();
switch (adjustingInfo.lineAlignment) {
case EN_START:
- // nothing to do in this case
+ // adjust end indent
+ addTrait(Trait.END_INDENT, ei - ipdVariation);
break;
case EN_CENTER:
- // re-compute indent
- addTrait(Trait.START_INDENT, getStartIndent() - ipdVariation / 2);
+ // adjust start and end indents
+ addTrait(Trait.START_INDENT, si - ipdVariation / 2);
+ addTrait(Trait.END_INDENT, ei - ipdVariation / 2);
break;
case EN_END:
- // re-compute indent
- addTrait(Trait.START_INDENT, getStartIndent() - ipdVariation);
+ // adjust start indent
+ addTrait(Trait.START_INDENT, si - ipdVariation);
break;
case EN_JUSTIFY:
// compute variation factor
@@ -198,7 +236,7 @@ public class LineArea extends Area {
// if the LineArea has already been added to the area tree,
// call finalize(); otherwise, wait for the LineLM to call it
if (adjustingInfo.bAddedToAreaTree) {
- finalise();
+ finish();
}
break;
default:
@@ -211,7 +249,7 @@ public class LineArea extends Area {
* and destroy the AdjustingInfo object if there are
* no UnresolvedAreas left
*/
- public void finalise() {
+ public void finish() {
if (adjustingInfo.lineAlignment == EN_JUSTIFY) {
if (log.isTraceEnabled()) {
log.trace("Applying variation factor to justified line: " + adjustingInfo);
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LinkResolver.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LinkResolver.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LinkResolver.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LinkResolver.java Sun Feb 26 02:29:01 2012
@@ -20,6 +20,7 @@
package org.apache.fop.area;
// Java
+import java.util.ArrayList;
import java.util.List;
import java.io.Serializable;
@@ -33,6 +34,7 @@ public class LinkResolver implements Res
private boolean resolved = false;
private String idRef;
private Area area;
+ private transient List<Resolvable> dependents = null;
/**
* Create a new link resolver.
@@ -79,8 +81,35 @@ public class LinkResolver implements Res
public void resolveIDRef(String id, PageViewport pv) {
if (idRef.equals(id) && pv != null) {
resolved = true;
- Trait.InternalLink iLink = new Trait.InternalLink(pv.getKey(), idRef);
- area.addTrait(Trait.INTERNAL_LINK, iLink);
+ if ( area != null ) {
+ Trait.InternalLink iLink = new Trait.InternalLink(pv.getKey(), idRef);
+ area.addTrait(Trait.INTERNAL_LINK, iLink);
+ area = null; // break circular reference from basic link area to this resolver
+ }
+ resolveDependents(id, pv);
}
}
+
+ /**
+ * Add dependent resolvable. Used to resolve second-order resolvables that
+ * depend on resolution of this resolver.
+ * @param dependent resolvable
+ */
+ public void addDependent(Resolvable dependent) {
+ if ( dependents == null ) {
+ dependents = new ArrayList<Resolvable>();
+ }
+ dependents.add(dependent);
+ }
+
+ private void resolveDependents(String id, PageViewport pv) {
+ if ( dependents != null ) {
+ List<PageViewport> pages = new ArrayList<PageViewport>();
+ pages.add(pv);
+ for ( Resolvable r : dependents ) {
+ r.resolveIDRef(id, pages);
+ }
+ }
+ }
+
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/MainReference.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/MainReference.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/MainReference.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/MainReference.java Sun Feb 26 02:29:01 2012
@@ -19,6 +19,8 @@
package org.apache.fop.area;
+import org.apache.fop.traits.WritingModeTraitsGetter;
+
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -124,5 +126,16 @@ public class MainReference extends Area
return parent.getColumnGap();
}
+ /**
+ * Sets the writing mode traits for the spans of this main
+ * reference area.
+ * @param wmtg a WM traits getter
+ */
+ public void setWritingModeTraits(WritingModeTraitsGetter wmtg) {
+ for ( Span s : (List<Span>) getSpans() ) {
+ s.setWritingModeTraits ( wmtg );
+ }
+ }
+
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Page.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Page.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Page.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/Page.java Sun Feb 26 02:29:01 2012
@@ -33,6 +33,7 @@ import org.apache.fop.fo.pagination.Regi
import org.apache.fop.fo.pagination.SimplePageMaster;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.layoutmgr.TraitSetter;
+import org.apache.fop.traits.WritingModeTraitsGetter;
import static org.apache.fop.fo.Constants.FO_REGION_AFTER;
import static org.apache.fop.fo.Constants.FO_REGION_BEFORE;
@@ -304,6 +305,29 @@ public class Page extends AreaTreeObject
return unresolved;
}
+ /**
+ * Sets the writing mode traits for the region viewports of
+ * this page.
+ * @param wmtg a WM traits getter
+ */
+ public void setWritingModeTraits(WritingModeTraitsGetter wmtg) {
+ if (regionBefore != null) {
+ regionBefore.setWritingModeTraits(wmtg);
+ }
+ if (regionStart != null) {
+ regionStart.setWritingModeTraits(wmtg);
+ }
+ if (regionBody != null) {
+ regionBody.setWritingModeTraits(wmtg);
+ }
+ if (regionEnd != null) {
+ regionEnd.setWritingModeTraits(wmtg);
+ }
+ if (regionAfter != null) {
+ regionAfter.setWritingModeTraits(wmtg);
+ }
+ }
+
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/PageViewport.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/PageViewport.java?rev=1293736&r1=1293735&r2=1293736&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/PageViewport.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/PageViewport.java Sun Feb 26 02:29:01 2012
@@ -34,6 +34,7 @@ import org.apache.commons.logging.LogFac
import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.pagination.SimplePageMaster;
+import org.apache.fop.traits.WritingModeTraitsGetter;
import static org.apache.fop.fo.Constants.FO_REGION_BODY;
import static org.apache.fop.fo.Constants.EN_FSWP;
@@ -654,4 +655,15 @@ public class PageViewport extends AreaTr
public RegionReference getRegionReference(int id) {
return getPage().getRegionViewport(id).getRegionReference();
}
+
+ /**
+ * Sets the writing mode traits for the page associated with this viewport.
+ * @param wmtg a WM traits getter
+ */
+ public void setWritingModeTraits(WritingModeTraitsGetter wmtg) {
+ if ( page != null ) {
+ page.setWritingModeTraits(wmtg);
+ }
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org