123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- /*
- * 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
-
- /**
- * <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);
- }
- }
-
- }
|