FdSelect.java 4.66 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.fontengine.font.cff;

import com.adobe.fontengine.font.InvalidFontException;
import com.adobe.fontengine.font.Subset;
import com.adobe.fontengine.font.cff.CFFByteArray;

final class FdSelect {
    protected final CFFByteArray data;
    protected final int offset;
    protected final int size;

    public FdSelect(CFFByteArray data, int offset, int numGlyphs) throws InvalidFontException {
        this.data = data;
        this.offset = offset;
        this.size = this.size(numGlyphs);
    }

    public static FdSelect singleFont(int numGlyphs) throws InvalidFontException {
        CFFByteArray.CFFByteArrayBuilder bb = CFFByteArray.getCFFByteArrayBuilderInstance(8);
        bb.addCard8(3);
        bb.addCard16(1);
        bb.addCard16(0);
        bb.addCard8(0);
        bb.addCard16(numGlyphs);
        return new FdSelect(bb.toCFFByteArray(), 0, numGlyphs);
    }

    private static FdSelect format0Generator(FdSelect origSelect, Subset subset) throws InvalidFontException {
        CFFByteArray.CFFByteArrayBuilder bb = CFFByteArray.getCFFByteArrayBuilderInstance(1 + subset.getNumGlyphs());
        bb.addCard8(0);
        for (int i = 0; i < subset.getNumGlyphs(); ++i) {
            bb.addCard8(origSelect.componentOf(subset.getFullGid(i)));
        }
        return new FdSelect(bb.toCFFByteArray(), 0, subset.getNumGlyphs());
    }

    private static FdSelect format3Generator(FdSelect origSelect, Subset subset, int numRanges) throws InvalidFontException {
        CFFByteArray.CFFByteArrayBuilder bb = CFFByteArray.getCFFByteArrayBuilderInstance(5 + numRanges * 3);
        int fd = origSelect.componentOf(subset.getFullGid(0));
        bb.addCard8(3);
        bb.addCard16(numRanges);
        bb.addCard16(0);
        for (int i = 1; i < subset.getNumGlyphs(); ++i) {
            int nextFD = origSelect.componentOf(subset.getFullGid(i));
            if (fd == nextFD) continue;
            bb.addCard8(fd);
            bb.addCard16(i);
            fd = nextFD;
        }
        bb.addCard8(fd);
        bb.addCard16(subset.getNumGlyphs());
        return new FdSelect(bb.toCFFByteArray(), 0, subset.getNumGlyphs());
    }

    public static FdSelect fdSelectFromSubset(FdSelect origSelect, Subset subset) throws InvalidFontException {
        int format3Size;
        int fd = origSelect.componentOf(subset.getFullGid(0));
        int numRanges = 1;
        for (int i = 1; i < subset.getNumGlyphs(); ++i) {
            int nextFD = origSelect.componentOf(subset.getFullGid(i));
            if (fd == nextFD) continue;
            ++numRanges;
            fd = nextFD;
        }
        int format0Size = subset.getNumGlyphs();
        if (format0Size <= (format3Size = 4 + numRanges * 3)) {
            return FdSelect.format0Generator(origSelect, subset);
        }
        return FdSelect.format3Generator(origSelect, subset, numRanges);
    }

    public int componentOf(int gid) throws InvalidFontException {
        int o = this.offset;
        int format = this.data.getcard8(o);
        ++o;
        switch (format) {
            case 0: {
                return this.data.getcard8(o + gid);
            }
            case 3: {
                int nRanges = this.data.getcard16(o);
                o += 2;
                int min = 0;
                int max = nRanges - 1;
                while (min <= max) {
                    int s = (min + max) / 2;
                    int firstGid = this.data.getcard16(o + 3 * s);
                    int lastGid = this.data.getcard16(o + 3 * (s + 1));
                    if (gid < firstGid) {
                        max = s - 1;
                        continue;
                    }
                    if (lastGid <= gid) {
                        min = s + 1;
                        continue;
                    }
                    return this.data.getcard8(o + 3 * s + 2);
                }
                throw new InvalidFontException("invalid fdSelect at offset " + this.offset);
            }
        }
        throw new InvalidFontException("invalid fdSelect format at " + this.offset);
    }

    int size(int numGlyphs) throws InvalidFontException {
        int o = this.offset;
        int format = this.data.getcard8(o);
        ++o;
        switch (format) {
            case 0: {
                return 1 + numGlyphs;
            }
            case 3: {
                int nRanges = this.data.getcard16(o);
                return 3 + 3 * nRanges + 2;
            }
        }
        throw new InvalidFontException("invalid fdSelect format at " + this.offset);
    }

    public void stream(CFFByteArray.CFFByteArrayBuilder bb) throws InvalidFontException {
        bb.addBytes(this.data, this.offset, this.size);
    }
}