public void Transform(BigEndianReader reader)
        {
            //the glyf table is split into several substreams, to group like data together.

            //The transformed table consists of a number of fields specifying the size of each of the substreams,
            //followed by the substreams in sequence.

            //During the decoding process the reverse transformation takes place,
            //where data from various separate substreams are recombined to create a complete glyph record
            //for each entry of the original glyf table.

            //Transformed glyf Table

            //Data-Type Semantic                Description and value type(if applicable)
            //Fixed     version                 = 0x00000000
            //UInt16    numGlyphs               Number of glyphs
            //UInt16    indexFormatOffset      format for loca table,
            //                                 should be consistent with indexToLocFormat of
            //                                 the original head table(see[OFF] specification)

            //UInt32    nContourStreamSize      Size of nContour stream in bytes
            //UInt32    nPointsStreamSize       Size of nPoints stream in bytes
            //UInt32    flagStreamSize          Size of flag stream in bytes
            //UInt32    glyphStreamSize         Size of glyph stream in bytes(a stream of variable-length encoded values, see description below)
            //UInt32    compositeStreamSize     Size of composite stream in bytes(a stream of variable-length encoded values, see description below)
            //UInt32    bboxStreamSize          Size of bbox data in bytes representing combined length of bboxBitmap(a packed bit array) and bboxStream(a stream of Int16 values)
            //UInt32    instructionStreamSize   Size of instruction stream(a stream of UInt8 values)

            //Int16     nContourStream[]        Stream of Int16 values representing number of contours for each glyph record
            //255UInt16 nPointsStream[]         Stream of values representing number of outline points for each contour in glyph records
            //UInt8     flagStream[]            Stream of UInt8 values representing flag values for each outline point.
            //Vary      glyphStream[]           Stream of bytes representing point coordinate values using variable length encoding format(defined in subclause 5.2)
            //Vary      compositeStream[]       Stream of bytes representing component flag values and associated composite glyph data
            //UInt8     bboxBitmap[]            Bitmap(a numGlyphs-long bit array) indicating explicit bounding boxes
            //Int16     bboxStream[]            Stream of Int16 values representing glyph bounding box data
            //UInt8     instructionStream[]	    Stream of UInt8 values representing a set of instructions for each corresponding glyph


            uint   version           = reader.ReadUInt32();
            ushort numGlyphs         = reader.ReadUInt16();
            ushort indexFormatOffset = reader.ReadUInt16();

            uint nContourStreamSize    = reader.ReadUInt32(); //in bytes
            uint nPointsStreamSize     = reader.ReadUInt32(); //in bytes
            uint flagStreamSize        = reader.ReadUInt32(); //in bytes
            uint glyphStreamSize       = reader.ReadUInt32(); //in bytes
            uint compositeStreamSize   = reader.ReadUInt32(); //in bytes
            uint bboxStreamSize        = reader.ReadUInt32(); //in bytes
            uint instructionStreamSize = reader.ReadUInt32(); //in bytes


            long expected_nCountStartAt          = reader.BaseStream.Position;
            long expected_nPointStartAt          = expected_nCountStartAt + nContourStreamSize;
            long expected_FlagStreamStartAt      = expected_nPointStartAt + nPointsStreamSize;
            long expected_GlyphStreamStartAt     = expected_FlagStreamStartAt + flagStreamSize;
            long expected_CompositeStreamStartAt = expected_GlyphStreamStartAt + glyphStreamSize;

            long expected_BboxStreamStartAt        = expected_CompositeStreamStartAt + compositeStreamSize;
            long expected_InstructionStreamStartAt = expected_BboxStreamStartAt + bboxStreamSize;
            long expected_EndAt = expected_InstructionStreamStartAt + instructionStreamSize;

            Glyph[] glyphs = new Glyph[numGlyphs];

            TempGlyph[]   allGlyphs       = new TempGlyph[numGlyphs];
            List <ushort> compositeGlyphs = new List <ushort>();

            int contourCount = 0;

            for (ushort i = 0; i < numGlyphs; ++i)
            {
                short numContour = reader.ReadInt16();
                allGlyphs[i] = new TempGlyph(i, numContour);
                if (numContour > 0)
                {
                    contourCount += numContour;
                    //>0 => simple glyph
                    //-1 = compound
                    //0 = empty glyph
                }
                else if (numContour < 0)
                {
                    //composite glyph, resolve later
                    compositeGlyphs.Add(i);
                }
                else
                {
                }
            }

            ushort[] pntPerContours = new ushort[contourCount];
            for (int i = 0; i < contourCount; ++i)
            {
                // Each of these is the number of points of that contour.
                pntPerContours[i] = reader.Read255UInt16();
            }

            byte[] flagStream = reader.Read((int)flagStreamSize);

            //TODO: Read more from line 296 in OpenFoint.Woff2Reader

            using (var composites = new MemoryStream())
            {
                reader.Position = expected_CompositeStreamStartAt;

                var compositeData = reader.Read((int)compositeStreamSize);
                composites.Write(compositeData, 0, (int)compositeStreamSize);

                int compositeGlyphCount = compositeGlyphs.Count;
                using (var compositeReader = new BigEndianReader(composites))
                {
                    for (int i = 0; i < compositeGlyphCount; i++)
                    {
                        ushort compositeGlyphIndex = compositeGlyphs[i];
                        bool   hasInstructions     = CompositeHasInstructions(compositeReader, compositeGlyphIndex);
                        if (hasInstructions)
                        {
                            break;
                        }
                        allGlyphs[compositeGlyphIndex].compositeHasInstructions = hasInstructions;
                    }
                }
            }
        }