123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /*
- * 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.lang.ref.WeakReference;
-
- import java.util.List;
- import java.util.Map;
-
- // CSOFF: InnerAssignmentCheck
- // CSOFF: LineLengthCheck
-
- /**
- * <p>The <code>GlyphSubtable</code> implements an abstract glyph subtable that
- * encapsulates identification, type, format, and coverage information.</p>
- *
- * <p>This work was originally authored by Glenn Adams (gadams@apache.org).</p>
- */
- public abstract class GlyphSubtable implements Comparable {
-
- /** lookup flag - right to left */
- public static final int LF_RIGHT_TO_LEFT = 0x0001;
- /** lookup flag - ignore base glyphs */
- public static final int LF_IGNORE_BASE = 0x0002;
- /** lookup flag - ignore ligatures */
- public static final int LF_IGNORE_LIGATURE = 0x0004;
- /** lookup flag - ignore marks */
- public static final int LF_IGNORE_MARK = 0x0008;
- /** lookup flag - use mark filtering set */
- public static final int LF_USE_MARK_FILTERING_SET = 0x0010;
- /** lookup flag - reserved */
- public static final int LF_RESERVED = 0x0E00;
- /** lookup flag - mark attachment type */
- public static final int LF_MARK_ATTACHMENT_TYPE = 0xFF00;
- /** internal flag - use reverse scan */
- public static final int LF_INTERNAL_USE_REVERSE_SCAN = 0x10000;
-
- /** lookup identifier, having form of "lu%d" where %d is index of lookup in lookup list; shared by multiple subtables in a single lookup */
- private String lookupId;
- /** subtable sequence (index) number in lookup, zero based */
- private int sequence;
- /** subtable flags */
- private int flags;
- /** subtable format */
- private int format;
- /** subtable mapping table */
- private GlyphMappingTable mapping;
- /** weak reference to parent (gsub or gpos) table */
- private WeakReference table;
-
- /**
- * Instantiate this glyph subtable.
- * @param lookupId lookup identifier, having form of "lu%d" where %d is index of lookup in lookup list
- * @param sequence subtable sequence (within lookup), starting with zero
- * @param flags subtable flags
- * @param format subtable format
- * @param mapping subtable mapping table
- */
- protected GlyphSubtable ( String lookupId, int sequence, int flags, int format, GlyphMappingTable mapping )
- {
- if ( ( lookupId == null ) || ( lookupId.length() == 0 ) ) {
- throw new AdvancedTypographicTableFormatException ( "invalid lookup identifier, must be non-empty string" );
- } else if ( mapping == null ) {
- throw new AdvancedTypographicTableFormatException ( "invalid mapping table, must not be null" );
- } else {
- this.lookupId = lookupId;
- this.sequence = sequence;
- this.flags = flags;
- this.format = format;
- this.mapping = mapping;
- }
- }
-
- /** @return this subtable's lookup identifer */
- public String getLookupId() {
- return lookupId;
- }
-
- /** @return this subtable's table type */
- public abstract int getTableType();
-
- /** @return this subtable's type */
- public abstract int getType();
-
- /** @return this subtable's type name */
- public abstract String getTypeName();
-
- /**
- * Determine if a glyph subtable is compatible with this glyph subtable. Two glyph subtables are
- * compatible if the both may appear in a single lookup table.
- * @param subtable a glyph subtable to determine compatibility
- * @return true if specified subtable is compatible with this glyph subtable, where by compatible
- * is meant that they share the same lookup type
- */
- public abstract boolean isCompatible ( GlyphSubtable subtable );
-
- /** @return true if subtable uses reverse scanning of glyph sequence, meaning from the last glyph
- * in a glyph sequence to the first glyph
- */
- public abstract boolean usesReverseScan();
-
- /** @return this subtable's sequence (index) within lookup */
- public int getSequence() {
- return sequence;
- }
-
- /** @return this subtable's flags */
- public int getFlags() {
- return flags;
- }
-
- /** @return this subtable's format */
- public int getFormat() {
- return format;
- }
-
- /** @return this subtable's governing glyph definition table or null if none available */
- public GlyphDefinitionTable getGDEF() {
- GlyphTable gt = getTable();
- if ( gt != null ) {
- return gt.getGlyphDefinitions();
- } else {
- return null;
- }
- }
-
- /** @return this subtable's coverage mapping or null if mapping is not a coverage mapping */
- public GlyphCoverageMapping getCoverage() {
- if ( mapping instanceof GlyphCoverageMapping ) {
- return (GlyphCoverageMapping) mapping;
- } else {
- return null;
- }
- }
-
- /** @return this subtable's class mapping or null if mapping is not a class mapping */
- public GlyphClassMapping getClasses() {
- if ( mapping instanceof GlyphClassMapping ) {
- return (GlyphClassMapping) mapping;
- } else {
- return null;
- }
- }
-
- /** @return this subtable's lookup entries */
- public abstract List getEntries();
-
- /** @return this subtable's parent table (or null if undefined) */
- public synchronized GlyphTable getTable() {
- WeakReference r = this.table;
- return ( r != null ) ? (GlyphTable) r.get() : null;
- }
-
- /**
- * Establish a weak reference from this subtable to its parent
- * table. If table parameter is specified as <code>null</code>, then
- * clear and remove weak reference.
- * @param table the table or null
- * @throws IllegalStateException if table is already set to non-null
- */
- public synchronized void setTable ( GlyphTable table ) throws IllegalStateException {
- WeakReference r = this.table;
- if ( table == null ) {
- this.table = null;
- if ( r != null ) {
- r.clear();
- }
- } else if ( r == null ) {
- this.table = new WeakReference ( table );
- } else {
- throw new IllegalStateException ( "table already set" );
- }
- }
-
- /**
- * Resolve references to lookup tables, e.g., in RuleLookup, to the lookup tables themselves.
- * @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables
- */
- public void resolveLookupReferences ( Map/*<String,GlyphTable.LookupTable>*/ lookupTables ) {
- }
-
- /**
- * Map glyph id to coverage index.
- * @param gid glyph id
- * @return the corresponding coverage index of the specified glyph id
- */
- public int getCoverageIndex ( int gid ) {
- if ( mapping instanceof GlyphCoverageMapping ) {
- return ( (GlyphCoverageMapping) mapping ) .getCoverageIndex ( gid );
- } else {
- return -1;
- }
- }
-
- /**
- * Map glyph id to coverage index.
- * @return the corresponding coverage index of the specified glyph id
- */
- public int getCoverageSize() {
- if ( mapping instanceof GlyphCoverageMapping ) {
- return ( (GlyphCoverageMapping) mapping ) .getCoverageSize();
- } else {
- return 0;
- }
- }
-
- /** {@inheritDoc} */
- public int hashCode() {
- int hc = sequence;
- hc = ( hc * 3 ) + ( lookupId.hashCode() ^ hc );
- return hc;
- }
-
- /**
- * {@inheritDoc}
- * @return true if the lookup identifier and the sequence number of the specified subtable is the same
- * as the lookup identifier and sequence number of this subtable
- */
- public boolean equals ( Object o ) {
- if ( o instanceof GlyphSubtable ) {
- GlyphSubtable st = (GlyphSubtable) o;
- return lookupId.equals ( st.lookupId ) && ( sequence == st.sequence );
- } else {
- return false;
- }
- }
-
- /**
- * {@inheritDoc}
- * @return the result of comparing the lookup identifier and the sequence number of the specified subtable with
- * the lookup identifier and sequence number of this subtable
- */
- public int compareTo ( Object o ) {
- int d;
- if ( o instanceof GlyphSubtable ) {
- GlyphSubtable st = (GlyphSubtable) o;
- if ( ( d = lookupId.compareTo ( st.lookupId ) ) == 0 ) {
- if ( sequence < st.sequence ) {
- d = -1;
- } else if ( sequence > st.sequence ) {
- d = 1;
- }
- }
- } else {
- d = -1;
- }
- return d;
- }
-
- /**
- * Determine if any of the specified subtables uses reverse scanning.
- * @param subtables array of glyph subtables
- * @return true if any of the specified subtables uses reverse scanning.
- */
- public static boolean usesReverseScan ( GlyphSubtable[] subtables ) {
- if ( ( subtables == null ) || ( subtables.length == 0 ) ) {
- return false;
- } else {
- for ( int i = 0, n = subtables.length; i < n; i++ ) {
- if ( subtables[i].usesReverseScan() ) {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * Determine consistent flags for a set of subtables.
- * @param subtables array of glyph subtables
- * @return consistent flags
- * @throws IllegalStateException if inconsistent flags
- */
- public static int getFlags ( GlyphSubtable[] subtables ) throws IllegalStateException {
- if ( ( subtables == null ) || ( subtables.length == 0 ) ) {
- return 0;
- } else {
- int flags = 0;
- // obtain first non-zero value of flags in array of subtables
- for ( int i = 0, n = subtables.length; i < n; i++ ) {
- int f = subtables[i].getFlags();
- if ( flags == 0 ) {
- flags = f;
- break;
- }
- }
- // enforce flag consistency
- for ( int i = 0, n = subtables.length; i < n; i++ ) {
- int f = subtables[i].getFlags();
- if ( f != flags ) {
- throw new IllegalStateException ( "inconsistent lookup flags " + f + ", expected " + flags );
- }
- }
- return flags | ( usesReverseScan ( subtables ) ? LF_INTERNAL_USE_REVERSE_SCAN : 0 );
- }
- }
-
- }
|