class GlyphTable extends TTFTable
{
    /**
     * Tag to identify this table.
     */
    public static final String TAG = "glyf";

    private GlyphData[] glyphs;

    // lazy table reading
    private TTFDataStream data;
    private IndexToLocationTable loca;
    private int numGlyphs;

    private int cached = 0;

    private HorizontalMetricsTable hmt = null;

    /**
     * Don't even bother to cache huge fonts.
     */
    private static final int MAX_CACHE_SIZE = 5000;

    /**
     * Don't cache more glyphs than this.
     */
    private static final int MAX_CACHED_GLYPHS = 100;

    GlyphTable()
    {
        super();
    }

    /**
     * This will read the required data from the stream.
     *
     * @param ttf The font that is being read.
     * @param data The stream to read the data from.
     * @throws IOException If there is an error reading the data.
     */
    @Override
    void read(TrueTypeFont ttf, TTFDataStream data) throws IOException
    {<FILL_FUNCTION_BODY>}

    /**
     * @param glyphsValue The glyphs to set.
     */
    public void setGlyphs(GlyphData[] glyphsValue)
    {
        glyphs = glyphsValue;
    }

    /**
     * Returns the data for the glyph with the given GID.
     *
     * @param gid GID
     *
     * @return data of the glyph with the given GID or null
     *
     * @throws IOException if the font cannot be read
     */
    public GlyphData getGlyph(int gid) throws IOException
    {
        if (gid < 0 || gid >= numGlyphs)
        {
            return null;
        }

        if (glyphs != null && glyphs[gid] != null)
        {
            return glyphs[gid];
        }

        GlyphData glyph;

        // PDFBOX-4219: synchronize on data because it is accessed by several threads
        // when PDFBox is accessing a standard 14 font for the first time
        synchronized (data)
        {
            // read a single glyph
            long[] offsets = loca.getOffsets();

            if (offsets[gid] == offsets[gid + 1])
            {
                // no outline
                // PDFBOX-5135: can't return null, must return an empty glyph because
                // sometimes this is used in a composite glyph.
                glyph = new GlyphData();
                glyph.initEmptyData();
            }
            else
            {
                // save
                long currentPosition = data.getCurrentPosition();

                data.seek(offsets[gid]);

                glyph = getGlyphData(gid);

                // restore
                data.seek(currentPosition);
            }

            if (glyphs != null && glyphs[gid] == null && cached < MAX_CACHED_GLYPHS)
            {
                glyphs[gid] = glyph;
                ++cached;
            }

            return glyph;
        }
    }

    private GlyphData getGlyphData(int gid) throws IOException
    {
        GlyphData glyph = new GlyphData();
        int leftSideBearing = hmt == null ? 0 : hmt.getLeftSideBearing(gid);
        glyph.initData(this, data, leftSideBearing);
        // resolve composite glyph
        if (glyph.getDescription().isComposite())
        {
            glyph.getDescription().resolve();
        }
        return glyph;
    }
}

        loca = ttf.getIndexToLocation();
        numGlyphs = ttf.getNumberOfGlyphs();

        if (numGlyphs < MAX_CACHE_SIZE)
        {
            // don't cache the huge fonts to save memory
            glyphs = new GlyphData[numGlyphs];
        }

        // we don't actually read the complete table here because it can contain tens of thousands of glyphs
        // cache the relevant part of the font data so that the data stream can be closed if it is no longer needed
        byte[] dataBytes = data.read((int) getLength());
        this.data = new RandomAccessReadDataStream(new RandomAccessReadBuffer(dataBytes));

        // PDFBOX-5460: read hmtx table early to avoid deadlock if getGlyph() locks "data"
        // and then locks TrueTypeFont to read this table, while another thread
        // locks TrueTypeFont and then tries to lock "data"
        hmt = ttf.getHorizontalMetrics();

        initialized = true;
    
<methods>public long getCheckSum() ,public boolean getInitialized() ,public long getLength() ,public long getOffset() ,public java.lang.String getTag() <variables>private long checkSum,protected boolean initialized,private long length,private long offset,private java.lang.String tag