org.apache.fop.complexscripts.fonts.GlyphTable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fop Show documentation
Show all versions of fop Show documentation
Apache FOP (Formatting Objects Processor) is the world's first print formatter driven by XSL formatting objects (XSL-FO) and the world's first output independent formatter. It is a Java application that reads a formatting object (FO) tree and renders the resulting pages to a specified output. Output formats currently supported include PDF, PCL, PS, AFP, TIFF, PNG, SVG, XML (area tree representation), Print, AWT and TXT. The primary output target is PDF.
/*
* 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.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
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;
import org.apache.fop.complexscripts.util.ScriptContextTester;
// CSOFF: LineLengthCheck
/**
* Base class for all advanced typographic glyph tables.
*
* This work was originally authored by Glenn Adams ([email protected]).
*/
public class GlyphTable {
/** logging instance */
private static final Log log = LogFactory.getLog(GlyphTable.class);
/** substitution glyph table type */
public static final int GLYPH_TABLE_TYPE_SUBSTITUTION = 1;
/** positioning glyph table type */
public static final int GLYPH_TABLE_TYPE_POSITIONING = 2;
/** justification glyph table type */
public static final int GLYPH_TABLE_TYPE_JUSTIFICATION = 3;
/** baseline glyph table type */
public static final int GLYPH_TABLE_TYPE_BASELINE = 4;
/** definition glyph table type */
public static final int GLYPH_TABLE_TYPE_DEFINITION = 5;
// (optional) glyph definition table in table types other than glyph definition table
private GlyphTable gdef;
// map from lookup specs to lists of strings, each of which identifies a lookup table (consisting of one or more subtables)
private Map> lookups;
// map from lookup identifiers to lookup tables
private Map lookupTables;
// cache for lookups matching
private Map>> matchedLookups;
// if true, then prevent further subtable addition
private boolean frozen;
protected Map processors;
/**
* Instantiate glyph table with specified lookups.
* @param gdef glyph definition table that applies
* @param lookups map from lookup specs to lookup tables
*/
public GlyphTable(GlyphTable gdef, Map> lookups,
Map processors) {
this.processors = processors;
if ((gdef != null) && !(gdef instanceof GlyphDefinitionTable)) {
throw new AdvancedTypographicTableFormatException("bad glyph definition table");
} else if (lookups == null) {
throw new AdvancedTypographicTableFormatException("lookups must be non-null map");
} else {
this.gdef = gdef;
this.lookups = lookups;
this.lookupTables = new LinkedHashMap();
this.matchedLookups = new HashMap>>();
}
}
/**
* Obtain glyph definition table.
* @return (possibly null) glyph definition table
*/
public GlyphDefinitionTable getGlyphDefinitions() {
return (GlyphDefinitionTable) gdef;
}
/**
* Obtain list of all lookup specifications.
* @return (possibly empty) list of all lookup specifications
*/
public List getLookups() {
return matchLookupSpecs("*", "*", "*");
}
/**
* Obtain ordered list of all lookup tables, where order is by lookup identifier, which
* lexicographic ordering follows the lookup list order.
* @return (possibly empty) ordered list of all lookup tables
*/
public List getLookupTables() {
TreeSet lids = new TreeSet(lookupTables.keySet());
List ltl = new ArrayList(lids.size());
for (Object lid1 : lids) {
String lid = (String) lid1;
ltl.add(lookupTables.get(lid));
}
return ltl;
}
/**
* Obtain lookup table by lookup id. This method is used by test code, and provides
* access to embedded lookups not normally accessed by {script, language, feature} lookup spec.
* @param lid lookup id
* @return table associated with lookup id or null if none
*/
public LookupTable getLookupTable(String lid) {
return lookupTables.get(lid);
}
/**
* Add a subtable.
* @param subtable a (non-null) glyph subtable
*/
protected void addSubtable(GlyphSubtable subtable) {
// ensure table is not frozen
if (frozen) {
throw new IllegalStateException("glyph table is frozen, subtable addition prohibited");
}
// set subtable's table reference to this table
subtable.setTable(this);
// add subtable to this table's subtable collection
String lid = subtable.getLookupId();
if (lookupTables.containsKey(lid)) {
LookupTable lt = lookupTables.get(lid);
lt.addSubtable(subtable);
} else {
LookupTable lt = new LookupTable(lid, subtable);
lookupTables.put(lid, lt);
}
}
/**
* Freeze subtables, i.e., do not allow further subtable addition, and
* create resulting cached state.
*/
protected void freezeSubtables() {
if (!frozen) {
for (Object o : lookupTables.values()) {
LookupTable lt = (LookupTable) o;
lt.freezeSubtables(lookupTables);
}
frozen = true;
}
}
/**
* Match lookup specifications according to