/*
 * 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: LineLengthCheck

The GlyphSubtable implements an abstract glyph subtable that encapsulates identification, type, format, and coverage information.

This work was originally authored by Glenn Adams (gadams@apache.org).

/** * <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
/** lookup flag - right to left */
public static final int LF_RIGHT_TO_LEFT = 0x0001;
lookup flag - ignore base glyphs
/** lookup flag - ignore base glyphs */
public static final int LF_IGNORE_BASE = 0x0002;
lookup flag - ignore ligatures
/** lookup flag - ignore ligatures */
public static final int LF_IGNORE_LIGATURE = 0x0004;
lookup flag - ignore marks
/** lookup flag - ignore marks */
public static final int LF_IGNORE_MARK = 0x0008;
lookup flag - use mark filtering set
/** lookup flag - use mark filtering set */
public static final int LF_USE_MARK_FILTERING_SET = 0x0010;
lookup flag - reserved
/** lookup flag - reserved */
public static final int LF_RESERVED = 0x0E00;
lookup flag - mark attachment type
/** lookup flag - mark attachment type */
public static final int LF_MARK_ATTACHMENT_TYPE = 0xFF00;
internal flag - use reverse scan
/** 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
/** 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
/** subtable sequence (index) number in lookup, zero based */
private int sequence;
subtable flags
/** subtable flags */
private int flags;
subtable format
/** subtable format */
private int format;
subtable mapping table
/** subtable mapping table */
private GlyphMappingTable mapping;
weak reference to parent (gsub or gpos) table
/** weak reference to parent (gsub or gpos) table */
private WeakReference table;
Instantiate this glyph subtable.
Params:
  • lookupId – lookup identifier, having form of "lu%d" where %d is index of lookup in lookup list
  • sequence – subtable sequence (within lookup), starting with zero
  • flags – subtable flags
  • format – subtable format
  • mapping – subtable mapping 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; } }
Returns:this subtable's lookup identifer
/** @return this subtable's lookup identifer */
public String getLookupId() { return lookupId; }
Returns:this subtable's table type
/** @return this subtable's table type */
public abstract int getTableType();
Returns:this subtable's type
/** @return this subtable's type */
public abstract int getType();
Returns:this subtable's type name
/** @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.
Params:
  • subtable – a glyph subtable to determine compatibility
Returns:true if specified subtable is compatible with this glyph subtable, where by compatible is meant that they share the same lookup type
/** * 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);
Returns:true if subtable uses reverse scanning of glyph sequence, meaning from the last glyph in a glyph sequence to the first glyph
/** @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();
Returns:this subtable's sequence (index) within lookup
/** @return this subtable's sequence (index) within lookup */
public int getSequence() { return sequence; }
Returns:this subtable's flags
/** @return this subtable's flags */
public int getFlags() { return flags; }
Returns:this subtable's format
/** @return this subtable's format */
public int getFormat() { return format; }
Returns:this subtable's governing glyph definition table or null if none available
/** @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; } }
Returns:this subtable's coverage mapping or null if mapping is not a coverage mapping
/** @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; } }
Returns:this subtable's class mapping or null if mapping is not a class mapping
/** @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; } }
Returns:this subtable's lookup entries
/** @return this subtable's lookup entries */
public abstract List getEntries();
Returns:this subtable's parent table (or null if undefined)
/** @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 null, then clear and remove weak reference.
Params:
  • table – the table or null
Throws:
/** * 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.
Params:
  • lookupTables – map from lookup table identifers, e.g. "lu4", to lookup tables
/** * 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.
Params:
  • gid – glyph id
Returns:the corresponding coverage index of the specified glyph id
/** * 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.
Returns:the corresponding coverage index of the specified glyph id
/** * 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}
/** {@inheritDoc} */
public int hashCode() { int hc = sequence; hc = (hc * 3) + (lookupId.hashCode() ^ hc); return hc; }
{@inheritDoc}
Returns: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
/** * {@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}
Returns: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
/** * {@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.
Params:
  • subtables – array of glyph subtables
Returns:true if any of the specified subtables uses reverse scanning.
/** * 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 (GlyphSubtable subtable : subtables) { if (subtable.usesReverseScan()) { return true; } } return false; } }
Determine consistent flags for a set of subtables.
Params:
  • subtables – array of glyph subtables
Throws:
Returns:consistent flags
/** * 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 (GlyphSubtable subtable1 : subtables) { int f = subtable1.getFlags(); if (flags == 0) { flags = f; break; } } // enforce flag consistency for (GlyphSubtable subtable : subtables) { int f = subtable.getFlags(); if (f != flags) { throw new IllegalStateException("inconsistent lookup flags " + f + ", expected " + flags); } } return flags | (usesReverseScan(subtables) ? LF_INTERNAL_USE_REVERSE_SCAN : 0); } } }