/*
 * 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.fonts;

import java.awt.Rectangle;
import java.io.InputStream;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable;
import org.apache.fop.complexscripts.fonts.GlyphPositioningTable;
import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable;
import org.apache.fop.complexscripts.fonts.GlyphTable;
import org.apache.fop.complexscripts.fonts.Positionable;
import org.apache.fop.complexscripts.fonts.Substitutable;
import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.CharNormalize;
import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.util.CharUtilities;

/**
 * Generic MultiByte (CID) font
 */
public class MultiByteFont extends CIDFont implements Substitutable, Positionable {

    /** logging instance */
    private static final Log log
        = LogFactory.getLog(MultiByteFont.class);

    private String ttcName;
    private String encoding = "Identity-H";

    private int defaultWidth;
    private CIDFontType cidType = CIDFontType.CIDTYPE2;

    protected final CIDSet cidSet;

    /* advanced typographic support */
    private GlyphDefinitionTable gdef;
    private GlyphSubstitutionTable gsub;
    private GlyphPositioningTable gpos;

    /* dynamic private use (character) mappings */
    private int numMapped;
    private int numUnmapped;
    private int nextPrivateUse = 0xE000;
    private int firstPrivate;
    private int lastPrivate;
    private int firstUnmapped;
    private int lastUnmapped;

    /** Contains the character bounding boxes for all characters in the font */
    protected Rectangle[] boundingBoxes;

    private boolean isOTFFile;

    // since for most users the most likely glyphs are in the first cmap segments we store their mapping.
    private static final int NUM_MOST_LIKELY_GLYPHS = 256;
    private int[] mostLikelyGlyphs = new int[NUM_MOST_LIKELY_GLYPHS];

    //A map to store each used glyph from the CID set against the glyph name.
    private LinkedHashMap<Integer, String> usedGlyphNames = new LinkedHashMap<Integer, String>();

    /**
     * Default constructor
     */
    public MultiByteFont(InternalResourceResolver resourceResolver, EmbeddingMode embeddingMode) {
        super(resourceResolver);
        setFontType(FontType.TYPE0);
        setEmbeddingMode(embeddingMode);
        if (embeddingMode != EmbeddingMode.FULL) {
            cidSet = new CIDSubset(this);
        } else {
            cidSet = new CIDFull(this);
        }
    }

    /** {@inheritDoc} */
    @Override
    public int getDefaultWidth() {
        return defaultWidth;
    }

    /** {@inheritDoc} */
    @Override
    public String getRegistry() {
        return "Adobe";
    }

    /** {@inheritDoc} */
    @Override
    public String getOrdering() {
        return "UCS";
    }

    /** {@inheritDoc} */
    @Override
    public int getSupplement() {
        return 0;
    }

    /** {@inheritDoc} */
    @Override
    public CIDFontType getCIDType() {
        return cidType;
    }

    public void setIsOTFFile(boolean isOTFFile) {
        this.isOTFFile = isOTFFile;
    }

    public boolean isOTFFile() {
        return this.isOTFFile;
    }

    /**
     * Sets the CIDType.
     * @param cidType The cidType to set
     */
    public void setCIDType(CIDFontType cidType) {
        this.cidType = cidType;
    }

    /** {@inheritDoc} */
    @Override
    public String getEmbedFontName() {
        if (isEmbeddable()) {
            return FontUtil.stripWhiteSpace(super.getFontName());
        } else {
            return super.getFontName();
        }
    }

    /** {@inheritDoc} */
    public boolean isEmbeddable() {
        return !(getEmbedFileURI() == null && getEmbedResourceName() == null);
    }

    public boolean isSubsetEmbedded() {
        if (getEmbeddingMode() == EmbeddingMode.FULL) {
            return false;
        }
        return true;
    }

    /** {@inheritDoc} */
    @Override
    public CIDSet getCIDSet() {
        return this.cidSet;
    }

    public void mapUsedGlyphName(int gid, String value) {
        usedGlyphNames.put(gid, value);
    }

    public LinkedHashMap<Integer, String> getUsedGlyphNames() {
        return usedGlyphNames;
    }

    /** {@inheritDoc} */
    @Override
    public String getEncodingName() {
        return encoding;
    }

    /** {@inheritDoc} */
    public int getWidth(int i, int size) {
        if (isEmbeddable()) {
            int glyphIndex = cidSet.getOriginalGlyphIndex(i);
            return size * width[glyphIndex];
        } else {
            return size * width[i];
        }
    }

    /** {@inheritDoc} */
    public int[] getWidths() {
        int[] arr = new int[width.length];
        System.arraycopy(width, 0, arr, 0, width.length);
        return arr;
    }

    public Rectangle getBoundingBox(int glyphIndex, int size) {
        int index = isEmbeddable() ? cidSet.getOriginalGlyphIndex(glyphIndex) : glyphIndex;
        Rectangle bbox = boundingBoxes[index];
        return new Rectangle(bbox.x * size, bbox.y * size, bbox.width * size, bbox.height * size);
    }

    /**
     * Returns the glyph index for a Unicode character. The method returns 0 if there's no
     * such glyph in the character map.
     * @param c the Unicode character index
     * @return the glyph index (or 0 if the glyph is not available)
     */
    // [TBD] - needs optimization, i.e., change from linear search to binary search
    public int findGlyphIndex(int c) {
        int idx = c;
        int retIdx = SingleByteEncoding.NOT_FOUND_CODE_POINT;

        // for most users the most likely glyphs are in the first cmap segments (meaning the one with
        // the lowest unicode start values)
        if (idx < NUM_MOST_LIKELY_GLYPHS && mostLikelyGlyphs[idx] != 0) {
            return mostLikelyGlyphs[idx];
        }
        for (CMapSegment i : cmap) {
            if (retIdx == 0
                    && i.getUnicodeStart() <= idx
                    && i.getUnicodeEnd() >= idx) {
                retIdx = i.getGlyphStartIndex()
                    + idx
                    - i.getUnicodeStart();
                if (idx < NUM_MOST_LIKELY_GLYPHS) {
                    mostLikelyGlyphs[idx] = retIdx;
                }
                if (retIdx != 0) {
                    break;
                }
            }
        }
        return retIdx;
    }

    /**
     * Add a private use mapping {PU,GI} to the existing character map.
     * N.B. Does not insert in order, merely appends to end of existing map.
     */
    protected synchronized void addPrivateUseMapping(int pu, int gi) {
        assert findGlyphIndex(pu) == SingleByteEncoding.NOT_FOUND_CODE_POINT;
        cmap.add(new CMapSegment(pu, pu, gi));
    }

    /**
     * Given a glyph index, create a new private use mapping, augmenting the bfentries
     * table. This is needed to accommodate the presence of an (output) glyph index in a
     * complex script glyph substitution that does not correspond to a character in the
     * font's CMAP.  The creation of such private use mappings is deferred until an
     * attempt is actually made to perform the reverse lookup from the glyph index. This
     * is necessary in order to avoid exhausting the private use space on fonts containing
     * many such non-mapped glyph indices, if these mappings had been created statically
     * at font load time.
     * @param gi glyph index
     * @returns unicode scalar value
     */
    private int createPrivateUseMapping(int gi) {
        while ((nextPrivateUse < 0xF900)
                && (findGlyphIndex(nextPrivateUse) != SingleByteEncoding.NOT_FOUND_CODE_POINT)) {
            nextPrivateUse++;
        }
        if (nextPrivateUse < 0xF900) {
            int pu = nextPrivateUse;
            addPrivateUseMapping(pu, gi);
            if (firstPrivate == 0) {
                firstPrivate = pu;
            }
            lastPrivate = pu;
            numMapped++;
            if (log.isDebugEnabled()) {
                log.debug("Create private use mapping from "
                            + CharUtilities.format(pu)
                            + " to glyph index " + gi
                            + " in font '" + getFullName() + "'");
            }
            return pu;
        } else {
            if (firstUnmapped == 0) {
                firstUnmapped = gi;
            }
            lastUnmapped = gi;
            numUnmapped++;
            log.warn("Exhausted private use area: unable to map "
                       + numUnmapped + " glyphs in glyph index range ["
                       + firstUnmapped + "," + lastUnmapped
                       + "] (inclusive) of font '" + getFullName() + "'");
            return 0;
        }
    }

    /**
     * Returns the Unicode scalar value that corresponds to the glyph index. If more than
     * one correspondence exists, then the first one is returned (ordered by bfentries[]).
     * @param gi glyph index
     * @return unicode scalar value
     */
    // [TBD] - needs optimization, i.e., change from linear search to binary search
    private int findCharacterFromGlyphIndex(int gi, boolean augment) {
        int cc = 0;
        for (CMapSegment segment : cmap) {
            int s = segment.getGlyphStartIndex();
            int e = s + (segment.getUnicodeEnd() - segment.getUnicodeStart());
            if ((gi >= s) && (gi <= e)) {
                cc = segment.getUnicodeStart() + (gi - s);
                break;
            }
        }
        if ((cc == 0) && augment) {
            cc = createPrivateUseMapping(gi);
        }
        return cc;
    }

    private int findCharacterFromGlyphIndex(int gi) {
        return findCharacterFromGlyphIndex(gi, true);
    }

    protected BitSet getGlyphIndices() {
        BitSet bitset = new BitSet();
        bitset.set(0);
        bitset.set(1);
        bitset.set(2);
        for (CMapSegment i : cmap) {
            int start = i.getUnicodeStart();
            int end = i.getUnicodeEnd();
            int glyphIndex = i.getGlyphStartIndex();
            while (start++ < end + 1) {
                bitset.set(glyphIndex++);
            }
        }
        return bitset;
    }

    protected char[] getChars() {
        // the width array is set when the font is built
        char[] chars = new char[width.length];
        for (CMapSegment i : cmap) {
            int start = i.getUnicodeStart();
            int end = i.getUnicodeEnd();
            int glyphIndex = i.getGlyphStartIndex();
            while (start < end + 1) {
                chars[glyphIndex++] = (char) start++;
            }
        }
        return chars;
    }

    /** {@inheritDoc} */
    @Override
    public char mapChar(char c) {
        notifyMapOperation();
        int glyphIndex = findGlyphIndex(c);
        if (glyphIndex == SingleByteEncoding.NOT_FOUND_CODE_POINT) {
            warnMissingGlyph(c);
            if (!isOTFFile) {
                glyphIndex = findGlyphIndex(Typeface.NOT_FOUND);
            }
        }
        if (isEmbeddable()) {
            glyphIndex = cidSet.mapChar(glyphIndex, c);
        }
        if (isCID() && glyphIndex > 256) {
            mapUnencodedChar(c);
        }
        return (char) glyphIndex;
    }

    /** {@inheritDoc} */
    @Override
    public int mapCodePoint(int cp) {
        notifyMapOperation();
        int glyphIndex = findGlyphIndex(cp);
        if (glyphIndex == SingleByteEncoding.NOT_FOUND_CODE_POINT) {

            for (char ch : Character.toChars(cp)) {
                //TODO better handling for non BMP
                warnMissingGlyph(ch);
            }

            if (!isOTFFile) {
                glyphIndex = findGlyphIndex(Typeface.NOT_FOUND);
            }
        }
        if (isEmbeddable()) {
            glyphIndex = cidSet.mapCodePoint(glyphIndex, cp);
        }
        return (char) glyphIndex;
    }

    /** {@inheritDoc} */
    @Override
    public boolean hasChar(char c) {
        return hasCodePoint(c);
    }

    /** {@inheritDoc} */
    @Override
    public boolean hasCodePoint(int cp) {
        return (findGlyphIndex(cp) != SingleByteEncoding.NOT_FOUND_CODE_POINT);
    }

    /**
     * Sets the defaultWidth.
     * @param defaultWidth The defaultWidth to set
     */
    public void setDefaultWidth(int defaultWidth) {
        this.defaultWidth = defaultWidth;
    }

    /**
     * Returns the TrueType Collection Name.
     * @return the TrueType Collection Name
     */
    public String getTTCName() {
        return ttcName;
    }

    /**
     * Sets the the TrueType Collection Name.
     * @param ttcName the TrueType Collection Name
     */
    public void setTTCName(String ttcName) {
        this.ttcName = ttcName;
    }

    /**
     * Sets the width array.
     * @param wds array of widths.
     */
    public void setWidthArray(int[] wds) {
        this.width = wds;
    }

    /**
     * Sets the bounding boxes array.
     * @param boundingBoxes array of bounding boxes.
     */
    public void setBBoxArray(Rectangle[] boundingBoxes) {
        this.boundingBoxes = boundingBoxes;
    }

    /**
     * Returns a Map of used Glyphs.
     * @return Map Map of used Glyphs
     */
    public Map<Integer, Integer> getUsedGlyphs() {
        return cidSet.getGlyphs();
    }

    /**
     * Returns the character from it's original glyph index in the font
     * @param glyphIndex The original index of the character
     * @return The character
     */
    public char getUnicodeFromGID(int glyphIndex) {
        return cidSet.getUnicodeFromGID(glyphIndex);
    }

    /**
     * Gets the original glyph index in the font from a character.
     * @param ch The character
     * @return The glyph index in the font
     */
    public int getGIDFromChar(char ch) {
        return cidSet.getGIDFromChar(ch);
    }

    /**
     * Establishes the glyph definition table.
     * @param gdef the glyph definition table to be used by this font
     */
    public void setGDEF(GlyphDefinitionTable gdef) {
        if ((this.gdef == null) || (gdef == null)) {
            this.gdef = gdef;
        } else {
            throw new IllegalStateException("font already associated with GDEF table");
        }
    }

    /**
     * Obtain glyph definition table.
     * @return glyph definition table or null if none is associated with font
     */
    public GlyphDefinitionTable getGDEF() {
        return gdef;
    }

    /**
     * Establishes the glyph substitution table.
     * @param gsub the glyph substitution table to be used by this font
     */
    public void setGSUB(GlyphSubstitutionTable gsub) {
        if ((this.gsub == null) || (gsub == null)) {
            this.gsub = gsub;
        } else {
            throw new IllegalStateException("font already associated with GSUB table");
        }
    }

    /**
     * Obtain glyph substitution table.
     * @return glyph substitution table or null if none is associated with font
     */
    public GlyphSubstitutionTable getGSUB() {
        return gsub;
    }

    /**
     * Establishes the glyph positioning table.
     * @param gpos the glyph positioning table to be used by this font
     */
    public void setGPOS(GlyphPositioningTable gpos) {
        if ((this.gpos == null) || (gpos == null)) {
            this.gpos = gpos;
        } else {
            throw new IllegalStateException("font already associated with GPOS table");
        }
    }

    /**
     * Obtain glyph positioning table.
     * @return glyph positioning table or null if none is associated with font
     */
    public GlyphPositioningTable getGPOS() {
        return gpos;
    }

    /** {@inheritDoc} */
    public boolean performsSubstitution() {
        return gsub != null;
    }

    /** {@inheritDoc} */
    public CharSequence performSubstitution(CharSequence charSequence, String script, String language,
                                            List associations, boolean retainControls) {
        if (gsub != null) {
            charSequence = gsub.preProcess(charSequence, script, this, associations);
            GlyphSequence glyphSequence = charSequenceToGlyphSequence(charSequence, associations);
            GlyphSequence glyphSequenceSubstituted = gsub.substitute(glyphSequence, script, language);
            if (associations != null) {
                associations.clear();
                associations.addAll(glyphSequenceSubstituted.getAssociations());
            }
            if (!retainControls) {
                glyphSequenceSubstituted = elideControls(glyphSequenceSubstituted);
            }
            // may not contains all the characters that were in charSequence.
            // see: #createPrivateUseMapping(int gi)
            return mapGlyphsToChars(glyphSequenceSubstituted);
        } else {
            return charSequence;
        }
    }

    public GlyphSequence charSequenceToGlyphSequence(CharSequence charSequence, List associations) {
        CharSequence normalizedCharSequence = normalize(charSequence, associations);
        return mapCharsToGlyphs(normalizedCharSequence, associations);
    }

    /** {@inheritDoc} */
    public CharSequence reorderCombiningMarks(
        CharSequence cs, int[][] gpa, String script, String language, List associations) {
        if (gdef != null) {
            GlyphSequence igs = mapCharsToGlyphs(cs, associations);
            GlyphSequence ogs = gdef.reorderCombiningMarks(igs, getUnscaledWidths(igs), gpa, script, language);
            if (associations != null) {
                associations.clear();
                associations.addAll(ogs.getAssociations());
            }
            CharSequence ocs = mapGlyphsToChars(ogs);
            return ocs;
        } else {
            return cs;
        }
    }

    protected int[] getUnscaledWidths(GlyphSequence gs) {
        int[] widths = new int[gs.getGlyphCount()];
        for (int i = 0, n = widths.length; i < n; ++i) {
            if (i < width.length) {
                widths[i] = width[i];
            }
        }
        return widths;
    }

    /** {@inheritDoc} */
    public boolean performsPositioning() {
        return gpos != null;
    }

    /** {@inheritDoc} */
    public int[][]
        performPositioning(CharSequence cs, String script, String language, int fontSize) {
        if (gpos != null) {
            GlyphSequence gs = mapCharsToGlyphs(cs, null);
            int[][] adjustments = new int [ gs.getGlyphCount() ] [ 4 ];
            if (gpos.position(gs, script, language, fontSize, this.width, adjustments)) {
                return scaleAdjustments(adjustments, fontSize);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /** {@inheritDoc} */
    public int[][] performPositioning(CharSequence cs, String script, String language) {
        throw new UnsupportedOperationException();
    }


    private int[][] scaleAdjustments(int[][] adjustments, int fontSize) {
        if (adjustments != null) {
            for (int[] gpa : adjustments) {
                for (int k = 0; k < 4; k++) {
                    gpa[k] = (gpa[k] * fontSize) / 1000;
                }
            }
            return adjustments;
        } else {
            return null;
        }
    }

    /**
     * Map sequence CS, comprising a sequence of UTF-16 encoded Unicode Code Points, to
     * an output character sequence GS, comprising a sequence of Glyph Indices. N.B. Unlike
     * mapChar(), this method does not make use of embedded subset encodings.
     * @param cs a CharSequence containing UTF-16 encoded Unicode characters
     * @returns a CharSequence containing glyph indices
     */
    private GlyphSequence mapCharsToGlyphs(CharSequence cs, List associations) {
        IntBuffer cb = IntBuffer.allocate(cs.length());
        IntBuffer gb = IntBuffer.allocate(cs.length());
        int gi;
        int giMissing = findGlyphIndex(Typeface.NOT_FOUND);
        for (int i = 0, n = cs.length(); i < n; i++) {
            int cc = cs.charAt(i);
            if ((cc >= 0xD800) && (cc < 0xDC00)) {
                if ((i + 1) < n) {
                    int sh = cc;
                    int sl = cs.charAt(++i);
                    if ((sl >= 0xDC00) && (sl < 0xE000)) {
                        cc = 0x10000 + ((sh - 0xD800) << 10) + ((sl - 0xDC00) << 0);
                    } else {
                        throw new IllegalArgumentException(
                            "ill-formed UTF-16 sequence, "
                               + "contains isolated high surrogate at index " + i);
                    }
                } else {
                    throw new IllegalArgumentException(
                        "ill-formed UTF-16 sequence, "
                          + "contains isolated high surrogate at end of sequence");
                }
            } else if ((cc >= 0xDC00) && (cc < 0xE000)) {
                throw new IllegalArgumentException(
                    "ill-formed UTF-16 sequence, "
                      + "contains isolated low surrogate at index " + i);
            }
            notifyMapOperation();
            gi = findGlyphIndex(cc);
            if (gi == SingleByteEncoding.NOT_FOUND_CODE_POINT) {
                warnMissingGlyph((char) cc);
                gi = giMissing;
            }
            cb.put(cc);
            gb.put(gi);
        }
        cb.flip();
        gb.flip();
        if ((associations != null) && (associations.size() == cs.length())) {
            associations = new java.util.ArrayList(associations);
        } else {
            associations = null;
        }
        return new GlyphSequence(cb, gb, associations);
    }

    /**
     * Map sequence GS, comprising a sequence of Glyph Indices, to output sequence CS,
     * comprising a sequence of UTF-16 encoded Unicode Code Points.
     * @param gs a GlyphSequence containing glyph indices
     * @returns a CharSequence containing UTF-16 encoded Unicode characters
     */
    private CharSequence mapGlyphsToChars(GlyphSequence gs) {
        int ng = gs.getGlyphCount();
        int ccMissing = Typeface.NOT_FOUND;
        List<Character> chars = new ArrayList<Character>(gs.getUTF16CharacterCount());

        for (int i = 0, n = ng; i < n; i++) {
            int gi = gs.getGlyph(i);
            int cc = findCharacterFromGlyphIndex(gi);
            if ((cc == 0) || (cc > 0x10FFFF)) {
                cc = ccMissing;
                log.warn("Unable to map glyph index " + gi
                         + " to Unicode scalar in font '"
                         + getFullName() + "', substituting missing character '"
                         + (char) cc + "'");
            }
            if (cc > 0x00FFFF) {
                int sh;
                int sl;
                cc -= 0x10000;
                sh = ((cc >> 10) & 0x3FF) + 0xD800;
                sl = ((cc >>  0) & 0x3FF) + 0xDC00;
                chars.add((char) sh);
                chars.add((char) sl);
            } else {
                chars.add((char) cc);
            }
        }

        CharBuffer cb = CharBuffer.allocate(chars.size());

        for (char c : chars) {
            cb.put(c);
        }

        cb.flip();
        return cb;
    }

    private CharSequence normalize(CharSequence cs, List associations) {
        return hasDecomposable(cs) ? decompose(cs, associations) : cs;
    }

    private boolean hasDecomposable(CharSequence cs) {
        for (int i = 0, n = cs.length(); i < n; i++) {
            int cc = cs.charAt(i);
            if (CharNormalize.isDecomposable(cc)) {
                return true;
            }
        }
        return false;
    }

    private CharSequence decompose(CharSequence cs, List associations) {
        StringBuffer sb = new StringBuffer(cs.length());
        int[] daBuffer = new int[CharNormalize.maximumDecompositionLength()];
        for (int i = 0, n = cs.length(); i < n; i++) {
            int cc = cs.charAt(i);
            int[] da = CharNormalize.decompose(cc, daBuffer);
            for (int aDa : da) {
                if (aDa > 0) {
                    sb.append((char) aDa);
                } else {
                    break;
                }
            }
        }
        return sb;
    }

    /**
     * Removes the glyphs associated with elidable control characters.
     * All the characters in an association must be elidable in order
     * to remove the corresponding glyph.
     *
     * @param gs GlyphSequence that may contains the elidable glyphs
     * @return GlyphSequence without the elidable glyphs
     */
    private static GlyphSequence elideControls(GlyphSequence gs) {
        if (hasElidableControl(gs)) {
            int[] ca = gs.getCharacterArray(false);
            IntBuffer ngb = IntBuffer.allocate(gs.getGlyphCount());
            List nal = new java.util.ArrayList(gs.getGlyphCount());
            for (int i = 0, n = gs.getGlyphCount(); i < n; ++i) {
                CharAssociation a = gs.getAssociation(i);
                int s = a.getStart();
                int e = a.getEnd();
                while (s < e) {
                    int ch = ca [ s ];
                    if (!isElidableControl(ch)) {
                        break;
                    } else {
                        ++s;
                    }
                }
                // If there is at least one non-elidable character in the char
                // sequence then the glyph/association is kept.
                if (s != e) {
                    ngb.put(gs.getGlyph(i));
                    nal.add(a);
                }
            }
            ngb.flip();
            return new GlyphSequence(gs.getCharacters(), ngb, nal, gs.getPredications());
        } else {
            return gs;
        }
    }

    private static boolean hasElidableControl(GlyphSequence gs) {
        int[] ca = gs.getCharacterArray(false);
        for (int ch : ca) {
            if (isElidableControl(ch)) {
                return true;
            }
        }
        return false;
    }

    private static boolean isElidableControl(int ch) {
        if (ch < 0x0020) {
            return true;
        } else if ((ch >= 0x80) && (ch < 0x00A0)) {
            return true;
        } else if ((ch >= 0x2000) && (ch <= 0x206F)) {
            if ((ch >= 0x200B) && (ch <= 0x200F)) {
                return true;
            } else if ((ch >= 0x2028) && (ch <= 0x202E)) {
                return true;
            } else if (ch >= 0x2066) {
                return true;
            } else {
                return ch == 0x2060;
            }
        } else {
            return false;
        }
    }

    @Override
    public boolean hasFeature(int tableType, String script, String language, String feature) {
        GlyphTable table;
        if (tableType == GlyphTable.GLYPH_TABLE_TYPE_SUBSTITUTION) {
            table = getGSUB();
        } else if (tableType == GlyphTable.GLYPH_TABLE_TYPE_POSITIONING) {
            table = getGPOS();
        } else if (tableType == GlyphTable.GLYPH_TABLE_TYPE_DEFINITION) {
            table = getGDEF();
        } else {
            table = null;
        }
        return (table != null) && table.hasFeature(script, language, feature);
    }

    public Map<Integer, Integer> getWidthsMap() {
        return null;
    }

    public InputStream getCmapStream() {
        return null;
    }
}

