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 [6/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/java/org/apache/fop/complexscripts/fonts/GlyphCoverageMapping.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageMapping.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageMapping.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageMapping.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,46 @@
+/*
+ * 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.complexscripts.fonts;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * The <code>GlyphCoverageMapping</code> interface provides glyph identifier to coverage
+ * index mapping support.
+ * @author Glenn Adams
+ */
+public interface GlyphCoverageMapping {
+
+    /**
+     * Obtain size of coverage table, i.e., ciMax + 1, where ciMax is the maximum
+     * coverage index.
+     * @return size of coverage table
+     */
+    int getCoverageSize();
+
+    /**
+     * Map glyph identifier (code) to coverge index. Returns -1 if glyph identifier is not in the domain of
+     * the coverage table.
+     * @param gid glyph identifier (code)
+     * @return non-negative glyph coverage index or -1 if glyph identifiers is not mapped by table
+     */
+    int getCoverageIndex ( int gid );
+
+}

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,233 @@
+/*
+ * 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.complexscripts.fonts;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+// CSOFF: LineLengthCheck
+// CSOFF: InnerAssignmentCheck
+// CSOFF: NoWhitespaceAfterCheck
+
+/**
+ * Base class implementation of glyph coverage table.
+ * @author Glenn Adams
+ */
+public final class GlyphCoverageTable extends GlyphMappingTable implements GlyphCoverageMapping {
+
+    /* logging instance */
+    private static final Log log = LogFactory.getLog(GlyphCoverageTable.class);                                         // CSOK: ConstantNameCheck
+
+    /** empty mapping table */
+    public static final int GLYPH_COVERAGE_TYPE_EMPTY = GLYPH_MAPPING_TYPE_EMPTY;
+
+    /** mapped mapping table */
+    public static final int GLYPH_COVERAGE_TYPE_MAPPED = GLYPH_MAPPING_TYPE_MAPPED;
+
+    /** range based mapping table */
+    public static final int GLYPH_COVERAGE_TYPE_RANGE = GLYPH_MAPPING_TYPE_RANGE;
+
+    private GlyphCoverageMapping cm;
+
+    private GlyphCoverageTable ( GlyphCoverageMapping cm ) {
+        assert cm != null;
+        assert cm instanceof GlyphMappingTable;
+        this.cm = cm;
+    }
+
+    /** {@inheritDoc} */
+    public int getType() {
+        return ( (GlyphMappingTable) cm ) .getType();
+    }
+
+    /** {@inheritDoc} */
+    public List getEntries() {
+        return ( (GlyphMappingTable) cm ) .getEntries();
+    }
+
+    /** {@inheritDoc} */
+    public int getCoverageSize() {
+        return cm.getCoverageSize();
+    }
+
+    /** {@inheritDoc} */
+    public int getCoverageIndex ( int gid ) {
+        return cm.getCoverageIndex ( gid );
+    }
+
+    /**
+     * Create glyph coverage table.
+     * @param entries list of mapped or ranged coverage entries, or null or empty list
+     * @return a new covera table instance
+     */
+    public static GlyphCoverageTable createCoverageTable ( List entries ) {
+        GlyphCoverageMapping cm;
+        if ( ( entries == null ) || ( entries.size() == 0 ) ) {
+            cm = new EmptyCoverageTable ( entries );
+        } else if ( isMappedCoverage ( entries ) ) {
+            cm = new MappedCoverageTable ( entries );
+        } else if ( isRangeCoverage ( entries ) ) {
+            cm = new RangeCoverageTable ( entries );
+        } else {
+            cm = null;
+        }
+        assert cm != null : "unknown coverage type";
+        return new GlyphCoverageTable ( cm );
+    }
+
+    private static boolean isMappedCoverage ( List entries ) {
+        if ( ( entries == null ) || ( entries.size() == 0 ) ) {
+            return false;
+        } else {
+            for ( Iterator it = entries.iterator(); it.hasNext();) {
+                Object o = it.next();
+                if ( ! ( o instanceof Integer ) ) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    private static boolean isRangeCoverage ( List entries ) {
+        if ( ( entries == null ) || ( entries.size() == 0 ) ) {
+            return false;
+        } else {
+            for ( Iterator it = entries.iterator(); it.hasNext();) {
+                Object o = it.next();
+                if ( ! ( o instanceof MappingRange ) ) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    private static class EmptyCoverageTable extends GlyphMappingTable.EmptyMappingTable implements GlyphCoverageMapping {
+        public EmptyCoverageTable ( List entries ) {
+            super ( entries );
+        }
+        /** {@inheritDoc} */
+        public int getCoverageSize() {
+            return 0;
+        }
+        /** {@inheritDoc} */
+        public int getCoverageIndex ( int gid ) {
+            return -1;
+        }
+    }
+
+    private static class MappedCoverageTable extends GlyphMappingTable.MappedMappingTable implements GlyphCoverageMapping {
+        private int[] map;
+        public MappedCoverageTable ( List entries ) {
+            populate ( entries );
+        }
+        /** {@inheritDoc} */
+        public List getEntries() {
+            List entries = new java.util.ArrayList();
+            if ( map != null ) {
+                for ( int i = 0, n = map.length; i < n; i++ ) {
+                    entries.add ( Integer.valueOf ( map [ i ] ) );
+                }
+            }
+            return entries;
+        }
+        /** {@inheritDoc} */
+        public int getMappingSize() {
+            return ( map != null ) ? map.length : 0;
+        }
+        public int getMappedIndex ( int gid ) {
+            int i;
+            if ( ( i = Arrays.binarySearch ( map, gid ) ) >= 0 ) {
+                return i;
+            } else {
+                return -1;
+            }
+        }
+        /** {@inheritDoc} */
+        public int getCoverageSize() {
+            return getMappingSize();
+        }
+        /** {@inheritDoc} */
+        public int getCoverageIndex ( int gid ) {
+            return getMappedIndex ( gid );
+        }
+        private void populate ( List entries ) {
+            int i = 0, n = entries.size(), gidMax = -1;
+            int[] map = new int [ n ];
+            for ( Iterator it = entries.iterator(); it.hasNext();) {
+                Object o = it.next();
+                if ( o instanceof Integer ) {
+                    int gid = ( (Integer) o ) . intValue();
+                    if ( ( gid >= 0 ) && ( gid < 65536 ) ) {
+                        if ( gid > gidMax ) {
+                            map [ i++ ] = gidMax = gid;
+                        } else {
+                            log.info ( "ignoring out of order or duplicate glyph index: " + gid );
+                        }
+                    } else {
+                        throw new AdvancedTypographicTableFormatException ( "illegal glyph index: " + gid );
+                    }
+                } else {
+                    throw new AdvancedTypographicTableFormatException ( "illegal coverage entry, must be Integer: " + o );
+                }
+            }
+            assert i == n;
+            assert this.map == null;
+            this.map = map;
+        }
+        /** {@inheritDoc} */
+        public String toString() {
+            StringBuffer sb = new StringBuffer();
+            sb.append('{');
+            for ( int i = 0, n = map.length; i < n; i++ ) {
+                if ( i > 0 ) {
+                    sb.append(',');
+                }
+                sb.append ( Integer.toString ( map [ i ] ) );
+            }
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class RangeCoverageTable extends GlyphMappingTable.RangeMappingTable implements GlyphCoverageMapping {
+        public RangeCoverageTable ( List entries ) {
+            super ( entries );
+        }
+        /** {@inheritDoc} */
+        public int getMappedIndex ( int gid, int s, int m ) {
+            return m + gid - s;
+        }
+        /** {@inheritDoc} */
+        public int getCoverageSize() {
+            return getMappingSize();
+        }
+        /** {@inheritDoc} */
+        public int getCoverageIndex ( int gid ) {
+            return getMappedIndex ( gid );
+        }
+    }
+
+}

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinition.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinition.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinition.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinition.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,38 @@
+/*
+ * 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.complexscripts.fonts;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * The <code>GlyphDefinition</code> interface is a marker interface implemented by a glyph definition
+ * subtable.
+ * @author Glenn Adams
+ */
+public interface GlyphDefinition {
+
+    /**
+     * Determine if some definition is available for a specific glyph.
+     * @param gi a glyph index
+     * @return true if some (unspecified) definition is available for the specified glyph
+     */
+    boolean hasDefinition ( int gi );
+
+}

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,76 @@
+/*
+ * 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.complexscripts.fonts;
+
+// CSOFF: LineLengthCheck
+// CSOFF: InnerAssignmentCheck
+
+/**
+ * The <code>GlyphDefinitionSubtable</code> implements an abstract base of a glyph definition subtable,
+ * providing a default implementation of the <code>GlyphDefinition</code> interface.
+ * @author Glenn Adams
+ */
+public abstract class GlyphDefinitionSubtable extends GlyphSubtable implements GlyphDefinition {
+
+    /**
+     * Instantiate a <code>GlyphDefinitionSubtable</code>.
+     * @param id subtable identifier
+     * @param sequence subtable sequence
+     * @param flags subtable flags
+     * @param format subtable format
+     * @param mapping subtable coverage table
+     */
+    protected GlyphDefinitionSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping ) {
+        super ( id, sequence, flags, format, mapping );
+    }
+
+    /** {@inheritDoc} */
+    public int getTableType() {
+        return GlyphTable.GLYPH_TABLE_TYPE_DEFINITION;
+    }
+
+    /** {@inheritDoc} */
+    public String getTypeName() {
+        return GlyphDefinitionTable.getLookupTypeName ( getType() );
+    }
+
+    /** {@inheritDoc} */
+    public boolean usesReverseScan() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    public boolean hasDefinition ( int gi ) {
+        GlyphCoverageMapping cvm;
+        if ( ( cvm = getCoverage() ) != null ) {
+            if ( cvm.getCoverageIndex ( gi ) >= 0 ) {
+                return true;
+            }
+        }
+        GlyphClassMapping clm;
+        if ( ( clm = getClasses() ) != null ) {
+            if ( clm.getClassIndex ( gi, 0 ) >= 0 ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,451 @@
+/*
+ * 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.complexscripts.fonts;
+
+import java.nio.CharBuffer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.complexscripts.scripts.ScriptProcessor;
+import org.apache.fop.complexscripts.util.GlyphSequence;
+
+// CSOFF: InnerAssignmentCheck
+// CSOFF: LineLengthCheck
+
+/**
+ * The <code>GlyphDefinitionTable</code> class is a glyph table that implements
+ * glyph definition functionality according to the OpenType GDEF table.
+ * @author Glenn Adams
+ */
+public class GlyphDefinitionTable extends GlyphTable {
+
+    /** logging instance */
+    private static final Log log = LogFactory.getLog(GlyphDefinitionTable.class);                                       // CSOK: ConstantNameCheck
+
+    /** glyph class subtable type */
+    public static final int GDEF_LOOKUP_TYPE_GLYPH_CLASS = 1;
+    /** attachment point subtable type */
+    public static final int GDEF_LOOKUP_TYPE_ATTACHMENT_POINT = 2;
+    /** ligature caret subtable type */
+    public static final int GDEF_LOOKUP_TYPE_LIGATURE_CARET = 3;
+    /** mark attachment subtable type */
+    public static final int GDEF_LOOKUP_TYPE_MARK_ATTACHMENT = 4;
+
+    /** pre-defined glyph class - base glyph */
+    public static final int GLYPH_CLASS_BASE = 1;
+    /** pre-defined glyph class - ligature glyph */
+    public static final int GLYPH_CLASS_LIGATURE = 2;
+    /** pre-defined glyph class - mark glyph */
+    public static final int GLYPH_CLASS_MARK = 3;
+    /** pre-defined glyph class - component glyph */
+    public static final int GLYPH_CLASS_COMPONENT = 4;
+
+    /** singleton glyph class table */
+    private GlyphClassSubtable gct;
+    /** singleton attachment point table */
+    // private AttachmentPointSubtable apt; // NOT YET USED
+    /** singleton ligature caret table */
+    // private LigatureCaretSubtable lct;   // NOT YET USED
+    /** singleton mark attachment table */
+    private MarkAttachmentSubtable mat;
+
+    /**
+     * Instantiate a <code>GlyphDefinitionTable</code> object using the specified subtables.
+     * @param subtables a list of identified subtables
+     */
+    public GlyphDefinitionTable ( List subtables ) {
+        super ( null, new HashMap(0) );
+        if ( ( subtables == null ) || ( subtables.size() == 0 ) ) {
+            throw new AdvancedTypographicTableFormatException ( "subtables must be non-empty" );
+        } else {
+            for ( Iterator it = subtables.iterator(); it.hasNext();) {
+                Object o = it.next();
+                if ( o instanceof GlyphDefinitionSubtable ) {
+                    addSubtable ( (GlyphSubtable) o );
+                } else {
+                    throw new AdvancedTypographicTableFormatException ( "subtable must be a glyph definition subtable" );
+                }
+            }
+            freezeSubtables();
+        }
+    }
+
+    /**
+     * Reorder combining marks in glyph sequence so that they precede (within the sequence) the base
+     * character to which they are applied. N.B. In the case of LTR segments, marks are not reordered by this,
+     * method since when the segment is reversed by BIDI processing, marks are automatically reordered to precede
+     * their base glyph.
+     * @param gs an input glyph sequence
+     * @param gpa associated glyph position adjustments (also reordered)
+     * @param script a script identifier
+     * @param language a language identifier
+     * @return the reordered (output) glyph sequence
+     */
+    public GlyphSequence reorderCombiningMarks ( GlyphSequence gs, int[][] gpa, String script, String language ) {
+        ScriptProcessor sp = ScriptProcessor.getInstance ( script );
+        return sp.reorderCombiningMarks ( this, gs, gpa, script, language );
+    }
+
+    /** {@inheritDoc} */
+    protected void addSubtable ( GlyphSubtable subtable ) {
+        if ( subtable instanceof GlyphClassSubtable ) {
+            this.gct = (GlyphClassSubtable) subtable;
+        } else if ( subtable instanceof AttachmentPointSubtable ) {
+            // TODO - not yet used
+            // this.apt = (AttachmentPointSubtable) subtable;
+        } else if ( subtable instanceof LigatureCaretSubtable ) {
+            // TODO - not yet used
+            // this.lct = (LigatureCaretSubtable) subtable;
+        } else if ( subtable instanceof MarkAttachmentSubtable ) {
+            this.mat = (MarkAttachmentSubtable) subtable;
+        } else {
+            throw new UnsupportedOperationException ( "unsupported glyph definition subtable type: " + subtable );
+        }
+    }
+
+    /**
+     * Determine if glyph belongs to pre-defined glyph class.
+     * @param gid a glyph identifier (index)
+     * @param gc a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT).
+     * @return true if glyph belongs to specified glyph class
+     */
+    public boolean isGlyphClass ( int gid, int gc ) {
+        if ( gct != null ) {
+            return gct.isGlyphClass ( gid, gc );
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Determine glyph class.
+     * @param gid a glyph identifier (index)
+     * @return a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT). 
+     */
+    public int getGlyphClass ( int gid ) {
+        if ( gct != null ) {
+            return gct.getGlyphClass ( gid );
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * Determine if glyph belongs to (font specific) mark attachment class.
+     * @param gid a glyph identifier (index)
+     * @param mac a (font specific) mark attachment class
+     * @return true if glyph belongs to specified mark attachment class
+     */
+    public boolean isMarkAttachClass ( int gid, int mac ) {
+        if ( mat != null ) {
+            return mat.isMarkAttachClass ( gid, mac );
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Determine mark attachment class.
+     * @param gid a glyph identifier (index)
+     * @return a non-negative mark attachment class, or -1 if no class defined
+     */
+    public int getMarkAttachClass ( int gid ) {
+        if ( mat != null ) {
+            return mat.getMarkAttachClass ( gid );
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * Map a lookup type name to its constant (integer) value.
+     * @param name lookup type name
+     * @return lookup type
+     */
+    public static int getLookupTypeFromName ( String name ) {
+        int t;
+        String s = name.toLowerCase();
+        if ( "glyphclass".equals ( s ) ) {
+            t = GDEF_LOOKUP_TYPE_GLYPH_CLASS;
+        } else if ( "attachmentpoint".equals ( s ) ) {
+            t = GDEF_LOOKUP_TYPE_ATTACHMENT_POINT;
+        } else if ( "ligaturecaret".equals ( s ) ) {
+            t = GDEF_LOOKUP_TYPE_LIGATURE_CARET;
+        } else if ( "markattachment".equals ( s ) ) {
+            t = GDEF_LOOKUP_TYPE_MARK_ATTACHMENT;
+        } else {
+            t = -1;
+        }
+        return t;
+    }
+
+    /**
+     * Map a lookup type constant (integer) value to its name.
+     * @param type lookup type
+     * @return lookup type name
+     */
+    public static String getLookupTypeName ( int type ) {
+        String tn = null;
+        switch ( type ) {
+        case GDEF_LOOKUP_TYPE_GLYPH_CLASS:
+            tn = "glyphclass";
+            break;
+        case GDEF_LOOKUP_TYPE_ATTACHMENT_POINT:
+            tn = "attachmentpoint";
+            break;
+        case GDEF_LOOKUP_TYPE_LIGATURE_CARET:
+            tn = "ligaturecaret";
+            break;
+        case GDEF_LOOKUP_TYPE_MARK_ATTACHMENT:
+            tn = "markattachment";
+            break;
+        default:
+            tn = "unknown";
+            break;
+        }
+        return tn;
+    }
+
+    /**
+     * Create a definition subtable according to the specified arguments.
+     * @param type subtable type
+     * @param id subtable identifier
+     * @param sequence subtable sequence
+     * @param flags subtable flags (must be zero)
+     * @param format subtable format
+     * @param mapping subtable mapping table
+     * @param entries subtable entries
+     * @return a glyph subtable instance
+     */
+    public static GlyphSubtable createSubtable ( int type, String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+        GlyphSubtable st = null;
+        switch ( type ) {
+        case GDEF_LOOKUP_TYPE_GLYPH_CLASS:
+            st = GlyphClassSubtable.create ( id, sequence, flags, format, mapping, entries );
+            break;
+        case GDEF_LOOKUP_TYPE_ATTACHMENT_POINT:
+            st = AttachmentPointSubtable.create ( id, sequence, flags, format, mapping, entries );
+            break;
+        case GDEF_LOOKUP_TYPE_LIGATURE_CARET:
+            st = LigatureCaretSubtable.create ( id, sequence, flags, format, mapping, entries );
+            break;
+        case GDEF_LOOKUP_TYPE_MARK_ATTACHMENT:
+            st = MarkAttachmentSubtable.create ( id, sequence, flags, format, mapping, entries );
+            break;
+        default:
+            break;
+        }
+        return st;
+    }
+
+    private abstract static class GlyphClassSubtable extends GlyphDefinitionSubtable {
+        GlyphClassSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            super ( id, sequence, flags, format, mapping );
+        }
+        /** {@inheritDoc} */
+        public int getType() {
+            return GDEF_LOOKUP_TYPE_GLYPH_CLASS;
+        }
+        /**
+         * Determine if glyph belongs to pre-defined glyph class.
+         * @param gid a glyph identifier (index)
+         * @param gc a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT).
+         * @return true if glyph belongs to specified glyph class
+         */
+        public abstract boolean isGlyphClass ( int gid, int gc );
+        /**
+         * Determine glyph class.
+         * @param gid a glyph identifier (index)
+         * @return a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT).
+         */
+        public abstract int getGlyphClass ( int gid );
+        static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            if ( format == 1 ) {
+                return new GlyphClassSubtableFormat1 ( id, sequence, flags, format, mapping, entries );
+            } else {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+
+    private static class GlyphClassSubtableFormat1 extends GlyphClassSubtable {
+        GlyphClassSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            super ( id, sequence, flags, format, mapping, entries );
+        }
+        /** {@inheritDoc} */
+        public List getEntries() {
+            return null;
+        }
+        /** {@inheritDoc} */
+        public boolean isCompatible ( GlyphSubtable subtable ) {
+            return subtable instanceof GlyphClassSubtable;
+        }
+        /** {@inheritDoc} */
+        public boolean isGlyphClass ( int gid, int gc ) {
+            GlyphClassMapping cm = getClasses();
+            if ( cm != null ) {
+                return cm.getClassIndex ( gid, 0 ) == gc;
+            } else {
+                return false;
+            }
+        }
+        /** {@inheritDoc} */
+        public int getGlyphClass ( int gid ) {
+            GlyphClassMapping cm = getClasses();
+            if ( cm != null ) {
+                return cm.getClassIndex ( gid, 0 );
+            } else {
+                return -1;
+            }
+        }
+    }
+
+    private abstract static class AttachmentPointSubtable extends GlyphDefinitionSubtable {
+        AttachmentPointSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            super ( id, sequence, flags, format, mapping );
+        }
+        /** {@inheritDoc} */
+        public int getType() {
+            return GDEF_LOOKUP_TYPE_ATTACHMENT_POINT;
+        }
+        static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            if ( format == 1 ) {
+                return new AttachmentPointSubtableFormat1 ( id, sequence, flags, format, mapping, entries );
+            } else {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+
+    private static class AttachmentPointSubtableFormat1 extends AttachmentPointSubtable {
+        AttachmentPointSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            super ( id, sequence, flags, format, mapping, entries );
+        }
+        /** {@inheritDoc} */
+        public List getEntries() {
+            return null;
+        }
+        /** {@inheritDoc} */
+        public boolean isCompatible ( GlyphSubtable subtable ) {
+            return subtable instanceof AttachmentPointSubtable;
+        }
+    }
+
+    private abstract static class LigatureCaretSubtable extends GlyphDefinitionSubtable {
+        LigatureCaretSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            super ( id, sequence, flags, format, mapping );
+        }
+        /** {@inheritDoc} */
+        public int getType() {
+            return GDEF_LOOKUP_TYPE_LIGATURE_CARET;
+        }
+        static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            if ( format == 1 ) {
+                return new LigatureCaretSubtableFormat1 ( id, sequence, flags, format, mapping, entries );
+            } else {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+
+    private static class LigatureCaretSubtableFormat1 extends LigatureCaretSubtable {
+        LigatureCaretSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            super ( id, sequence, flags, format, mapping, entries );
+        }
+        /** {@inheritDoc} */
+        public List getEntries() {
+            return null;
+        }
+        /** {@inheritDoc} */
+        public boolean isCompatible ( GlyphSubtable subtable ) {
+            return subtable instanceof LigatureCaretSubtable;
+        }
+    }
+
+    private abstract static class MarkAttachmentSubtable extends GlyphDefinitionSubtable {
+        MarkAttachmentSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            super ( id, sequence, flags, format, mapping );
+        }
+        /** {@inheritDoc} */
+        public int getType() {
+            return GDEF_LOOKUP_TYPE_MARK_ATTACHMENT;
+        }
+        /**
+         * Determine if glyph belongs to (font specific) mark attachment class.
+         * @param gid a glyph identifier (index)
+         * @param mac a (font specific) mark attachment class
+         * @return true if glyph belongs to specified mark attachment class
+         */
+        public abstract boolean isMarkAttachClass ( int gid, int mac );
+        /**
+         * Determine mark attachment class.
+         * @param gid a glyph identifier (index)
+         * @return a non-negative mark attachment class, or -1 if no class defined
+         */
+        public abstract int getMarkAttachClass ( int gid );
+        static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            if ( format == 1 ) {
+                return new MarkAttachmentSubtableFormat1 ( id, sequence, flags, format, mapping, entries );
+            } else {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+
+    private static class MarkAttachmentSubtableFormat1 extends MarkAttachmentSubtable {
+        MarkAttachmentSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
+            super ( id, sequence, flags, format, mapping, entries );
+        }
+        /** {@inheritDoc} */
+        public List getEntries() {
+            return null;
+        }
+        /** {@inheritDoc} */
+        public boolean isCompatible ( GlyphSubtable subtable ) {
+            return subtable instanceof MarkAttachmentSubtable;
+        }
+        /** {@inheritDoc} */
+        public boolean isMarkAttachClass ( int gid, int mac ) {
+            GlyphClassMapping cm = getClasses();
+            if ( cm != null ) {
+                return cm.getClassIndex ( gid, 0 ) == mac;
+            } else {
+                return false;
+            }
+        }
+        /** {@inheritDoc} */
+        public int getMarkAttachClass ( int gid ) {
+            GlyphClassMapping cm = getClasses();
+            if ( cm != null ) {
+                return cm.getClassIndex ( gid, 0 );
+            } else {
+                return -1;
+            }
+        }
+    }
+
+}

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,322 @@
+/*
+ * 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.complexscripts.fonts;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Iterator;
+
+// CSOFF: NoWhitespaceAfterCheck
+// CSOFF: InnerAssignmentCheck
+// CSOFF: LineLengthCheck
+
+/**
+ * Base class implementation of glyph mapping table. This base
+ * class maps glyph indices to arbitrary integers (mappping indices), and
+ * is used to implement both glyph coverage and glyph class maps.
+ * @author Glenn Adams
+ */
+public class GlyphMappingTable {
+
+    /** empty mapping table */
+    public static final int GLYPH_MAPPING_TYPE_EMPTY = 0;
+
+    /** mapped mapping table */
+    public static final int GLYPH_MAPPING_TYPE_MAPPED = 1;
+
+    /** range based mapping table */
+    public static final int GLYPH_MAPPING_TYPE_RANGE = 2;
+
+    /**
+     * Obtain mapping type.
+     * @return mapping format type
+     */
+    public int getType() {
+        return -1;
+    }
+
+    /**
+     * Obtain mapping entries.
+     * @return list of mapping entries
+     */
+    public List getEntries() {
+        return null;
+    }
+
+    /**
+     * Obtain size of mapping table, i.e., ciMax + 1, where ciMax is the maximum
+     * mapping index.
+     * @return size of mapping table
+     */
+    public int getMappingSize() {
+        return 0;
+    }
+
+    /**
+     * Map glyph identifier (code) to coverge index. Returns -1 if glyph identifier is not in the domain of
+     * the mapping table.
+     * @param gid glyph identifier (code)
+     * @return non-negative glyph mapping index or -1 if glyph identifiers is not mapped by table
+     */
+    public int getMappedIndex ( int gid ) {
+        return -1;
+    }
+
+    /** empty mapping table base class */
+    protected static class EmptyMappingTable extends GlyphMappingTable {
+        /**
+         * Construct empty mapping table.
+         */
+        public EmptyMappingTable() {
+            this ( (List) null );
+        }
+        /**
+         * Construct empty mapping table with entries (ignored).
+         * @param entries list of entries (ignored)
+         */
+        public EmptyMappingTable ( List entries ) {
+        }
+        /** {@inheritDoc} */
+        public int getType() {
+            return GLYPH_MAPPING_TYPE_EMPTY;
+        }
+        /** {@inheritDoc} */
+        public List getEntries() {
+            return new java.util.ArrayList();
+        }
+        /** {@inheritDoc} */
+        public int getMappingSize() {
+            return 0;
+        }
+        /** {@inheritDoc} */
+        public int getMappedIndex ( int gid ) {
+            return -1;
+        }
+    }
+
+    /** mapped mapping table base class */
+    protected static class MappedMappingTable extends GlyphMappingTable {
+        /**
+         * Construct mapped mapping table.
+         */
+        public MappedMappingTable() {
+        }
+        /** {@inheritDoc} */
+        public int getType() {
+            return GLYPH_MAPPING_TYPE_MAPPED;
+        }
+    }
+
+    /** range mapping table base class */
+    protected abstract static class RangeMappingTable extends GlyphMappingTable {
+        private int[] sa = null;                                                // array of range (inclusive) starts
+        private int[] ea = null;                                                // array of range (inclusive) ends
+        private int[] ma = null;                                                // array of range mapped values
+        private int miMax = -1;
+        /**
+         * Construct range mapping table.
+         * @param entries of mapping ranges
+         */
+        public RangeMappingTable ( List entries ) {
+            populate ( entries );
+        }
+        /** {@inheritDoc} */
+        public int getType() {
+            return GLYPH_MAPPING_TYPE_RANGE;
+        }
+        /** {@inheritDoc} */
+        public List getEntries() {
+            List entries = new java.util.ArrayList();
+            if ( sa != null ) {
+                for ( int i = 0, n = sa.length; i < n; i++ ) {
+                    entries.add ( new MappingRange ( sa [ i ], ea [ i ], ma [ i ] ) );
+                }
+            }
+            return entries;
+        }
+        /** {@inheritDoc} */
+        public int getMappingSize() {
+            return miMax + 1;
+        }
+        /** {@inheritDoc} */
+        public int getMappedIndex ( int gid ) {
+            int i, mi;
+            if ( ( i = Arrays.binarySearch ( sa, gid ) ) >= 0 ) {
+                mi = getMappedIndex ( gid, sa [ i ], ma [ i ] );                // matches start of (some) range
+            } else if ( ( i = - ( i + 1 ) ) == 0 ) {
+                mi = -1;                                                        // precedes first range 
+            } else if ( gid > ea [ --i ] ) {
+                mi = -1;                                                        // follows preceding (or last) range
+            } else {
+                mi = getMappedIndex ( gid, sa [ i ], ma [ i ] );                // intersects (some) range
+            }
+            return mi;
+        }
+        /**
+         * Map glyph identifier (code) to coverge index. Returns -1 if glyph identifier is not in the domain of
+         * the mapping table.
+         * @param gid glyph identifier (code)
+         * @param s start of range
+         * @param m mapping value
+         * @return non-negative glyph mapping index or -1 if glyph identifiers is not mapped by table
+         */
+        public abstract int getMappedIndex ( int gid, int s, int m );
+        private void populate ( List entries ) {
+            int i = 0, n = entries.size(), gidMax = -1, miMax = -1;
+            int[] sa = new int [ n ];
+            int[] ea = new int [ n ];
+            int[] ma = new int [ n ];
+            for ( Iterator it = entries.iterator(); it.hasNext();) {
+                Object o = it.next();
+                if ( o instanceof MappingRange ) {
+                    MappingRange r = (MappingRange) o;
+                    int gs = r.getStart();
+                    int ge = r.getEnd();
+                    int mi = r.getIndex();
+                    if ( ( gs < 0 ) || ( gs > 65535 ) ) {
+                        throw new AdvancedTypographicTableFormatException ( "illegal glyph range: [" + gs + "," + ge + "]: bad start index" );
+                    } else if ( ( ge < 0 ) || ( ge > 65535 ) ) {
+                        throw new AdvancedTypographicTableFormatException ( "illegal glyph range: [" + gs + "," + ge + "]: bad end index" );
+                    } else if ( gs > ge ) {
+                        throw new AdvancedTypographicTableFormatException ( "illegal glyph range: [" + gs + "," + ge + "]: start index exceeds end index" );
+                    } else if ( gs < gidMax ) {
+                        throw new AdvancedTypographicTableFormatException ( "out of order glyph range: [" + gs + "," + ge + "]" );
+                    } else if ( mi < 0 ) {
+                        throw new AdvancedTypographicTableFormatException ( "illegal mapping index: " + mi );
+                    } else {
+                        int miLast;
+                        sa [ i ] = gs;
+                        ea [ i ] = gidMax = ge;
+                        ma [ i ] = mi;
+                        if ( ( miLast = mi + ( ge - gs ) ) > miMax ) {
+                            miMax = miLast;
+                        }
+                        i++;
+                    }
+                } else {
+                    throw new AdvancedTypographicTableFormatException ( "illegal mapping entry, must be Integer: " + o );
+                }
+            }
+            assert i == n;
+            assert this.sa == null;
+            assert this.ea == null;
+            assert this.ma == null;
+            this.sa = sa;
+            this.ea = ea;
+            this.ma = ma;
+            this.miMax = miMax;
+        }
+        /** {@inheritDoc} */
+        public String toString() {
+            StringBuffer sb = new StringBuffer();
+            sb.append('{');
+            for ( int i = 0, n = sa.length; i < n; i++ ) {
+                if ( i > 0 ) {
+                    sb.append(',');
+                }
+                sb.append ( '[' );
+                sb.append ( Integer.toString ( sa [ i ] ) );
+                sb.append ( Integer.toString ( ea [ i ] ) );
+                sb.append ( "]:" );
+                sb.append ( Integer.toString ( ma [ i ] ) );
+            }
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    /**
+     * The <code>MappingRange</code> class encapsulates a glyph [start,end] range and
+     * a mapping index.
+     */
+    public static class MappingRange {
+
+        private final int gidStart;                     // first glyph in range (inclusive)
+        private final int gidEnd;                       // last glyph in range (inclusive)
+        private final int index;                        // mapping index;
+
+        /**
+         * Instantiate a mapping range.
+         */
+        public MappingRange() {
+            this ( 0, 0, 0 );
+        }
+
+        /**
+         * Instantiate a specific mapping range.
+         * @param gidStart start of range
+         * @param gidEnd end of range
+         * @param index mapping index
+         */
+        public MappingRange ( int gidStart, int gidEnd, int index ) {
+            if ( ( gidStart < 0 ) || ( gidEnd < 0 ) || ( index < 0 ) ) {
+                throw new AdvancedTypographicTableFormatException();
+            } else if ( gidStart > gidEnd ) {
+                throw new AdvancedTypographicTableFormatException();
+            } else {
+                this.gidStart = gidStart;
+                this.gidEnd = gidEnd;
+                this.index = index;
+            }
+        }
+
+        /** @return start of range */
+        public int getStart() {
+            return gidStart;
+        }
+
+        /** @return end of range */
+        public int getEnd() {
+            return gidEnd;
+        }
+
+        /** @return mapping index */
+        public int getIndex() {
+            return index;
+        }
+
+        /** @return interval as a pair of integers */
+        public int[] getInterval() {
+            return new int[] { gidStart, gidEnd };
+        }
+
+        /**
+         * Obtain interval, filled into first two elements of specified array, or returning new array.
+         * @param interval an array of length two or greater or null
+         * @return interval as a pair of integers, filled into specified array
+         */
+        public int[] getInterval ( int[] interval ) {
+            if ( ( interval == null ) || ( interval.length != 2 ) ) {
+                throw new IllegalArgumentException();
+            } else {
+                interval[0] = gidStart;
+                interval[1] = gidEnd;
+            }
+            return interval;
+        }
+
+        /** @return length of interval */
+        public int getLength() {
+            return gidStart - gidEnd;
+        }
+
+    }
+
+}

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioning.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioning.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioning.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioning.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,43 @@
+/*
+ * 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.complexscripts.fonts;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * The <code>GlyphPositioning</code> interface is implemented by a glyph positioning subtable
+ * that supports the determination of glyph positioning information based on script and
+ * language of the corresponding character content.
+ * @author Glenn Adams
+ */
+public interface GlyphPositioning {
+
+    /**
+     * Perform glyph positioning at the current index, mutating the positioning state object as required.
+     * Only the context associated with the current index is processed.
+     * @param ps glyph positioning state object
+     * @return true if the glyph subtable applies, meaning that the current context matches the
+     * associated input context glyph coverage table; note that returning true does not mean any position
+     * adjustment occurred; it only means that no further glyph subtables for the current lookup table
+     * should be applied.
+     */
+    boolean position ( GlyphPositioningState ps );
+
+}

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,208 @@
+/*
+ * 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.complexscripts.fonts;
+
+import org.apache.fop.complexscripts.util.GlyphSequence;
+import org.apache.fop.complexscripts.util.ScriptContextTester;
+
+// CSOFF: LineLengthCheck
+// CSOFF: ParameterNumberCheck
+
+/**
+ * The <code>GlyphPositioningState</code> implements an state object used during glyph positioning
+ * processing.
+ * @author Glenn Adams
+ */
+
+public class GlyphPositioningState extends GlyphProcessingState {
+
+    /** font size */
+    private int fontSize;
+    /** default advancements */
+    private int[] widths;
+    /** current adjustments */
+    private int[][] adjustments;
+    /** if true, then some adjustment was applied */
+    private boolean adjusted;
+
+    /**
+     * Construct glyph positioning state.
+     * @param gs input glyph sequence
+     * @param script script identifier
+     * @param language language identifier
+     * @param feature feature identifier
+     * @param fontSize font size (in micropoints)
+     * @param widths array of design advancements (in glyph index order)
+     * @param adjustments positioning adjustments to which positioning is applied
+     * @param sct script context tester (or null)
+     */
+    public GlyphPositioningState ( GlyphSequence gs, String script, String language, String feature, int fontSize, int[] widths, int[][] adjustments, ScriptContextTester sct ) {
+        super ( gs, script, language, feature, sct );
+        this.fontSize = fontSize;
+        this.widths = widths;
+        this.adjustments = adjustments;
+    }
+
+    /**
+     * Construct glyph positioning state using an existing state object using shallow copy
+     * except as follows: input glyph sequence is copied deep except for its characters array.
+     * @param ps existing positioning state to copy from
+     */
+    public GlyphPositioningState ( GlyphPositioningState ps ) {
+        super ( ps );
+        this.fontSize = ps.fontSize;
+        this.widths = ps.widths;
+        this.adjustments = ps.adjustments;
+    }
+
+    /**
+     * Obtain design advancement (width) of glyph at specified index.
+     * @param gi glyph index
+     * @return design advancement, or zero if glyph index is not present
+     */
+    public int getWidth ( int gi ) {
+        if ( ( widths != null ) && ( gi < widths.length ) ) {
+            return widths [ gi ];
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * Perform adjustments at current position index.
+     * @param v value containing adjustments
+     * @return true if a non-zero adjustment was made
+     */
+    public boolean adjust ( GlyphPositioningTable.Value v ) {
+        return adjust ( v, 0 );
+    }
+
+    /**
+     * Perform adjustments at specified offset from current position index.
+     * @param v value containing adjustments
+     * @param offset from current position index
+     * @return true if a non-zero adjustment was made
+     */
+    public boolean adjust ( GlyphPositioningTable.Value v, int offset ) {
+        assert v != null;
+        if ( ( index + offset ) < indexLast ) {
+            return v.adjust ( adjustments [ index + offset ], fontSize );
+        } else {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+    /**
+     * Obtain current adjustments at current position index.
+     * @return array of adjustments (int[4]) at current position
+     */
+    public int[] getAdjustment() {
+        return getAdjustment ( 0 );
+    }
+
+    /**
+     * Obtain current adjustments at specified offset from current position index.
+     * @param offset from current position index
+     * @return array of adjustments (int[4]) at specified offset
+     * @throws IndexOutOfBoundsException if offset is invalid
+     */
+    public int[] getAdjustment ( int offset ) throws IndexOutOfBoundsException {
+        if ( ( index + offset ) < indexLast ) {
+            return adjustments [ index + offset ];
+        } else {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+    /**
+     * Apply positioning subtable to current state at current position (only),
+     * resulting in the consumption of zero or more input glyphs.
+     * @param st the glyph positioning subtable to apply
+     * @return true if subtable applied, or false if it did not (e.g., its
+     * input coverage table did not match current input context)
+     */
+    public boolean apply ( GlyphPositioningSubtable st ) {
+        assert st != null;
+        updateSubtableState ( st );
+        boolean applied = st.position ( this );
+        resetSubtableState();
+        return applied;
+    }
+
+    /**
+     * Apply a sequence of matched rule lookups to the <code>nig</code> input glyphs
+     * starting at the current position. If lookups are non-null and non-empty, then
+     * all input glyphs specified by <code>nig</code> are consumed irregardless of
+     * whether any specified lookup applied.
+     * @param lookups array of matched lookups (or null)
+     * @param nig number of glyphs in input sequence, starting at current position, to which
+     * the lookups are to apply, and to be consumed once the application has finished
+     * @return true if lookups are non-null and non-empty; otherwise, false
+     */
+    public boolean apply ( GlyphTable.RuleLookup[] lookups, int nig ) {
+        if ( ( lookups != null ) && ( lookups.length > 0 ) ) {
+            // apply each rule lookup to extracted input glyph array
+            for ( int i = 0, n = lookups.length; i < n; i++ ) {
+                GlyphTable.RuleLookup l = lookups [ i ];
+                if ( l != null ) {
+                    GlyphTable.LookupTable lt = l.getLookup();
+                    if ( lt != null ) {
+                        // perform positioning on a copy of previous state
+                        GlyphPositioningState ps = new GlyphPositioningState ( this );
+                        // apply lookup table positioning
+                        if ( lt.position ( ps, l.getSequenceIndex() ) ) {
+                            setAdjusted ( true );
+                        }
+                    }
+                }
+            }
+            consume ( nig );
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Apply default application semantices; namely, consume one input glyph.
+     */
+    public void applyDefault() {
+        super.applyDefault();
+    }
+
+    /**
+     * Set adjusted state, used to record effect of non-zero adjustment.
+     * @param adjusted true if to set adjusted state, otherwise false to
+     * clear adjusted state
+     */
+    public void setAdjusted ( boolean adjusted ) {
+        this.adjusted = adjusted;
+    }
+
+    /**
+     * Get adjusted state.
+     * @return adjusted true if some non-zero adjustment occurred and
+     * was recorded by {@link #setAdjusted}; otherwise, false.
+     */
+    public boolean getAdjusted() {
+        return adjusted;
+    }
+
+}

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java?rev=1293736&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java Sun Feb 26 02:29:01 2012
@@ -0,0 +1,129 @@
+/*
+ * 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.complexscripts.fonts;
+
+import java.util.List;
+
+import org.apache.fop.complexscripts.util.GlyphSequence;
+import org.apache.fop.complexscripts.util.ScriptContextTester;
+
+// CSOFF: LineLengthCheck
+// CSOFF: NoWhitespaceAfterCheck
+// CSOFF: ParameterNumberCheck
+
+/**
+ * The <code>GlyphPositioningSubtable</code> implements an abstract base of a glyph subtable,
+ * providing a default implementation of the <code>GlyphPositioning</code> interface.
+ * @author Glenn Adams
+ */
+public abstract class GlyphPositioningSubtable extends GlyphSubtable implements GlyphPositioning {
+
+    /**
+     * Instantiate a <code>GlyphPositioningSubtable</code>.
+     * @param id subtable identifier
+     * @param sequence subtable sequence
+     * @param flags subtable flags
+     * @param format subtable format
+     * @param coverage subtable coverage table
+     */
+    protected GlyphPositioningSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage ) {
+        super ( id, sequence, flags, format, coverage );
+    }
+
+    /** {@inheritDoc} */
+    public int getTableType() {
+        return GlyphTable.GLYPH_TABLE_TYPE_POSITIONING;
+    }
+
+    /** {@inheritDoc} */
+    public String getTypeName() {
+        return GlyphPositioningTable.getLookupTypeName ( getType() );
+    }
+
+    /** {@inheritDoc} */
+    public boolean isCompatible ( GlyphSubtable subtable ) {
+        return subtable instanceof GlyphPositioningSubtable;
+    }
+
+    /** {@inheritDoc} */
+    public boolean usesReverseScan() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    public boolean position ( GlyphPositioningState ps ) {
+        return false;
+    }
+
+    /**
+     * Apply positioning using specified state and subtable array. For each position in input sequence,
+     * apply subtables in order until some subtable applies or none remain. If no subtable applied or no
+     * input was consumed for a given position, then apply default action (no adjustments and advance).
+     * If <code>sequenceIndex</code> is non-negative, then apply subtables only when current position
+     * matches <code>sequenceIndex</code> in relation to the starting position. Furthermore, upon
+     * successful application at <code>sequenceIndex</code>, then discontinue processing the remaining
+     * @param ps positioning state
+     * @param sta array of subtables to apply
+     * @param sequenceIndex if non negative, then apply subtables only at specified sequence index
+     * @return true if a non-zero adjustment occurred
+     */
+    public static final boolean position ( GlyphPositioningState ps, GlyphPositioningSubtable[] sta, int sequenceIndex ) {
+        int sequenceStart = ps.getPosition();
+        boolean appliedOneShot = false;
+        while ( ps.hasNext() ) {
+            boolean applied = false;
+            if ( ! appliedOneShot && ps.maybeApplicable() ) {
+                for ( int i = 0, n = sta.length; ! applied && ( i < n ); i++ ) {
+                    if ( sequenceIndex < 0 ) {
+                        applied = ps.apply ( sta [ i ] );
+                    } else if ( ps.getPosition() == ( sequenceStart + sequenceIndex ) ) {
+                        applied = ps.apply ( sta [ i ] );
+                        if ( applied ) {
+                            appliedOneShot = true;
+                        }
+                    }
+                }
+            }
+            if ( ! applied || ! ps.didConsume() ) {
+                ps.applyDefault();
+            }
+            ps.next();
+        }
+        return ps.getAdjusted();
+    }
+
+    /**
+     * Apply positioning.
+     * @param gs input glyph sequence
+     * @param script tag
+     * @param language tag
+     * @param feature tag
+     * @param fontSize the font size
+     * @param sta subtable array
+     * @param widths array
+     * @param adjustments array (receives output adjustments)
+     * @param sct script context tester
+     * @return true if a non-zero adjustment occurred
+     */
+    public static final boolean position ( GlyphSequence gs, String script, String language, String feature, int fontSize, GlyphPositioningSubtable[] sta, int[] widths, int[][] adjustments, ScriptContextTester sct ) {
+        return position ( new GlyphPositioningState ( gs, script, language, feature, fontSize, widths, adjustments, sct ), sta, -1 );
+    }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org