Ejemplo n.º 1
0
        // Reads through the SVG table copying over all of the SVG content into individual .svg files and writes those files into
        // a folder of the name, outputFolder
        public int ExportSvgContent(TableRecord rt, byte[] source, StorageFolder outputFolder)
        {
            int numberSvgs = 0;

            start   = rt.offset; // start always refer to the offset to the file head.
            current = rt.offset;

            // Read SVG Main Header
            ushort version           = ReadDataAndIncreaseIndex <ushort>(source, ref current, sizeof(ushort));
            uint   svgDocIndexOffset = ReadDataAndIncreaseIndex <uint>(source, ref current, sizeof(uint));
            uint   reserved          = ReadDataAndIncreaseIndex <uint>(source, ref current, sizeof(uint));

            // Read document Index
            uint   documentIndexOffset = start + svgDocIndexOffset;
            ushort numEntries          = ReadDataAndIncreaseIndex <ushort>(source, ref documentIndexOffset, sizeof(ushort));

            SVGDocIdxEntry[] docIdxEntries = new SVGDocIdxEntry[numEntries];
            for (int i = 0; i < docIdxEntries.Length; i++)
            {
                docIdxEntries[i] = ReadSvgDocIdxEntry(source, ref documentIndexOffset);
                string filename   = docIdxEntries[i].startID.ToString();
                byte[] svgContent = new byte[docIdxEntries[i].docLength];
                Array.Copy(source, (int)(docIdxEntries[i].docOffset + rt.offset + svgDocIndexOffset), svgContent, 0, svgContent.Length);
                WriteSvgContent(outputFolder, filename, svgContent);
                numberSvgs++;
            }
            return(numberSvgs);
        }
Ejemplo n.º 2
0
        // Parses font's table record and alters TableRecord object appropriately.
        // Also keeps track of the location of the offset for that table record.
        public TableRecord ReadTableRecord(byte[] source)
        {
            TableRecord record = new TableRecord();

            record.tagInt   = ReadData <uint>(source, ref start, sizeof(uint));
            record.tag      = ReadDataAndIncreaseIndex(source, ref start, TagLength);
            record.checksum = ReadDataAndIncreaseIndex <uint>(source, ref start, sizeof(uint));
            // Not a part of table records---just saved and used in ChangeTableRecOffsets
            // to change TableRecordOffsets easily.
            record.offsetOfOffset = start;
            record.offset         = ReadDataAndIncreaseIndex <uint>(source, ref start, sizeof(uint));
            record.length         = ReadDataAndIncreaseIndex <uint>(source, ref start, sizeof(uint));
            return(record);
        }
Ejemplo n.º 3
0
        // Parse cmap table from the font
        // Only parses cmap entries with format IDs of 0, 4, 6, or 12 (covers the vast majority of cases)
        public List <GlyphModel> ParseCMap(TableRecord tableRecord, byte[] source)
        {
            CmapHeader        header   = new CmapHeader();
            List <GlyphModel> allChars = new List <GlyphModel>();

            start            = tableRecord.offset;
            header.version   = ReadDataAndIncreaseIndex <ushort>(source, ref start, sizeof(ushort));
            header.numTables = ReadDataAndIncreaseIndex <ushort>(source, ref start, sizeof(ushort));
            for (int i = 0; i < header.numTables; i++)
            {
                CmapEncodingRecord record = new CmapEncodingRecord();
                record.platformID = ReadDataAndIncreaseIndex <ushort>(source, ref start, sizeof(ushort));
                record.encodingID = ReadDataAndIncreaseIndex <ushort>(source, ref start, sizeof(ushort));
                record.offset     = ReadDataAndIncreaseIndex <uint>(source, ref start, sizeof(uint));
                uint prevPos = start;
                start = record.offset + tableRecord.offset;
                ushort formatID = ReadData <ushort>(source, ref start, sizeof(ushort));
                switch (formatID)
                {
                case 0:
                    ParseFormat0(source, ref start, allChars);
                    break;

                case 4:
                    ParseFormat4(source, ref start, allChars);
                    break;

                case 6:
                    ParseFormat6(source, ref start, allChars);
                    break;

                case 12:
                    ParseFormat12(source, ref start, allChars);
                    break;

                default:
                    break;
                }
                start = prevPos;
            }
            return(allChars);
        }
Ejemplo n.º 4
0
        // Reads through the Name Record Table and saves each of the Name Records in an array.
        // Loops through the nameRecord array to find a record with a nameID == 1 and a length > 0.
        // If such a nameRecord is found, the family name is read and returned. If no such
        // nameRecord is found, returns null.
        public string GetFamilyName(TableRecord record, byte[] source)
        {
            start   = record.offset;
            current = record.offset;

            ushort format       = ReadDataAndIncreaseIndex <ushort>(source, ref current, sizeof(ushort));
            ushort count        = ReadDataAndIncreaseIndex <ushort>(source, ref current, sizeof(ushort));
            ushort stringOffset = ReadDataAndIncreaseIndex <ushort>(source, ref current, sizeof(ushort));

            NameRecord[] nameRecords = new NameRecord[count];
            for (int i = 0; i < nameRecords.Length; i++)
            {
                nameRecords[i] = ReadNameRecordEntry(source, ref current);
            }
            for (int i = 0; i < nameRecords.Length; i++)
            {
                if (nameRecords[i].nameID == 1 && nameRecords[i].length > 0)
                {
                    uint index = current + nameRecords[i].offset;
                    return(ReadDataAndIncreaseIndexForFamilyName(source, ref index, nameRecords[i].length));
                }
            }
            return(null);
        }
Ejemplo n.º 5
0
        // Adds the SVG defined by svgContent to the font file at the specified glyphID
        public void AssembleSvgContent(ref TableRecord record, ref byte[] source, byte[] svgContent, ushort glyphID, FontModel fontModel)
        {
            start   = record.offset; // start always refer to the offset to the file head.
            current = record.offset;

            // Read SVG Main Header
            ushort version           = ReadDataAndIncreaseIndex <ushort>(source, ref current, sizeof(ushort));
            uint   svgDocIndexOffset = ReadDataAndIncreaseIndex <uint>(source, ref current, sizeof(uint));
            uint   reserved          = ReadDataAndIncreaseIndex <uint>(source, ref current, sizeof(uint));

            // Read document Index
            uint   documentIndexOffset       = start + svgDocIndexOffset;
            uint   svgDocIndexAbsoluteOffset = start + svgDocIndexOffset;
            ushort numEntries = ReadDataAndIncreaseIndex <ushort>(source, ref documentIndexOffset, sizeof(ushort));

            int  svgLength;
            int  paddingDiff = 0;
            long diff;

            byte[] recordLength;
            byte[] newSource;
            byte[] checksum;
            uint   newDocumentIndexOffset = 0;
            uint   newPadding             = 0;
            uint   currPadding            = CalculatePadding(record.length);
            bool   firstPass = true;

            SVGDocIdxEntry[] docIdxEntries = new SVGDocIdxEntry[numEntries];
            for (int i = 0; i < docIdxEntries.Length; i++)
            {
                docIdxEntries[i] = ReadSvgDocIdxEntry(source, ref documentIndexOffset);
                // Case 0: takes into account the glyphID already having SVG content
                if (docIdxEntries[i].startID.Equals(glyphID))
                {
                    svgLength = svgContent.Length;
                    diff      = docIdxEntries[i].docLength - svgLength;
                    uint svgOffset = docIdxEntries[i].docOffset + record.offset + svgDocIndexOffset;
                    recordLength = GetBytesBigEndian((uint)(record.length - diff));
                    // Changes the SVG table record length by the difference between the length of the old SVG content and the new SVG content
                    Array.Copy(recordLength, 0, source, (int)record.offsetOfOffset + sizeof(uint), sizeof(uint));
                    newPadding  = CalculatePadding((uint)(record.length - diff));
                    paddingDiff = (int)currPadding - (int)newPadding;
                    byte[] length = GetBytesBigEndian((uint)svgLength);
                    // Changes the length of the SVG content contained in the SVG Document Index Entry to reflect the length of the new SVG content
                    Array.Copy(length, 0, source, (int)(documentIndexOffset - sizeof(uint)), sizeof(uint));
                    // Change the table record offsets for tables following the altered SVG content to reflect the change in length
                    ChangeTableRecOffsets(fontModel.TableRecords, ref source, (diff + paddingDiff), start + svgDocIndexOffset);
                    // Changes the SVG offsets in the SVG Document Index Entries for the SVG content that was written after the altered SVG content in the
                    // font file to reflect a shift of the difference in length between the old and new SVG content
                    ChangeSvgOffsets(fontModel.TableRecords, ref source, diff, docIdxEntries[i].docOffset);
                    newSource = new byte[source.Length - (diff + paddingDiff)];
                    // Copies from the beginning of source to the beginning of the altered SVG content
                    Array.Copy(source, 0, newSource, 0, (int)svgOffset);
                    // Skips the length of the new SVG content in the newSource array and copies from the beginning of the SVG content following the altered SVG content
                    // to the end of the SVG Table
                    Array.Copy(source, (int)(svgOffset + docIdxEntries[i].docLength), newSource, (int)svgOffset + svgLength, (int)(record.offset + record.length - svgOffset - docIdxEntries[i].docLength));
                    // Makes sure the padding at the end of the SVG table in the newSource array is correct and copies from the beginning o
                    Array.Copy(source, (int)(record.offset + record.length + currPadding), newSource, (int)(svgLength + record.offset + record.length - docIdxEntries[i].docLength + newPadding), (int)(source.Length - (record.offset + record.length + currPadding)));
                    // Copies from the beginning of the table following the SVG Table (after the entire SVG table and it's padding) to the end of the font file
                    Array.Copy(svgContent, 0, newSource, (int)svgOffset, svgLength);
                    source        = newSource;
                    record.length = (uint)(record.length - diff);
                    checksum      = GetBytesBigEndian(CalcTableChecksum(record.offset, record.length, ref source));
                    Array.Copy(checksum, 0, source, (int)(record.offsetOfOffset - sizeof(uint)), sizeof(uint));
                    record.checksum = BitConverter.ToUInt32(checksum, 0);
                    return;
                }
                // Case 1: takes into account the glyphID not having SVG content and not being the last glyphID
                else if (docIdxEntries[i].startID > glyphID && firstPass)
                {
                    // newDocumentIndexOffset stores the location that the new SVG Document Index Entry would have to be added
                    newDocumentIndexOffset = documentIndexOffset - (uint)Marshal.SizeOf <SVGDocIdxEntry>();
                    firstPass = false;
                    break;
                }
            }
            // Case 2: takes into account the glyphID not having SVG content and being the last glyphID
            if (firstPass)
            {
                // newDocumentIndexOffset stores the location that the new SVG Document Index Entry would have to be added
                // In this case right after the last SVG Document Index Entry
                newDocumentIndexOffset = documentIndexOffset;
            }
            svgLength = svgContent.Length;
            // In cases 1 and 2 an entirely new SVG Document Index Entry must be added, so diff is the length of the SVG content plus the length of an
            // SVG Document Index Entry
            // This is made negative because for consistency's sake diff is always subtracted
            diff         = (svgLength + Marshal.SizeOf <SVGDocIdxEntry>()) * -1;
            recordLength = GetBytesBigEndian((uint)(record.length - diff));
            // Changes the SVG table record length by diff
            Array.Copy(recordLength, 0, source, (int)record.offsetOfOffset + sizeof(uint), sizeof(uint));
            newPadding  = CalculatePadding((uint)(record.length - diff));
            paddingDiff = (int)currPadding - (int)newPadding;
            // Change the table record offsets for tables following the added SVG content to reflect the change in length
            ChangeTableRecOffsets(fontModel.TableRecords, ref source, (diff + paddingDiff), start + svgDocIndexOffset);
            // Brand new SVG content is being added to the very end of the SVG table, so the offsets contained in the SVG
            // Document Index Entries need only be changed by the length of the new SVG Document Index Entry that will be addded
            ChangeSvgOffsets(fontModel.TableRecords, ref source, diff + svgLength, 0);
            uint numEntriesOffset = start + svgDocIndexOffset;

            byte[] newNumEntries = GetBytesBigEndian((ushort)(numEntries + 1));
            // Increments the number of entries contained in the SVG document index table
            Array.Copy(newNumEntries, 0, source, (int)numEntriesOffset, sizeof(ushort));
            newSource = new byte[source.Length - (diff + paddingDiff)];
            // Copies from the begining of source to the end of the SVG Document Index Entry preceeding the one to be added
            Array.Copy(source, 0, newSource, 0, (int)newDocumentIndexOffset);
            // Assumes the start and end glyphIDs are the same because currently you can only add one SVG at a time
            byte[] startAndEndGlyphID  = GetBytesBigEndian(glyphID);
            int    newSourceCopyOffset = (int)newDocumentIndexOffset;

            // Copies the startGlyphID to the newSource array
            Array.Copy(startAndEndGlyphID, 0, newSource, newSourceCopyOffset, sizeof(ushort));
            newSourceCopyOffset += sizeof(ushort);
            // Copies the endGlyphID to the newSource array
            Array.Copy(startAndEndGlyphID, 0, newSource, newSourceCopyOffset, sizeof(ushort));
            newSourceCopyOffset += sizeof(ushort);
            byte[] svgDocOffset = GetBytesBigEndian((uint)(record.length - svgDocIndexOffset + Marshal.SizeOf <SVGDocIdxEntry>()));
            // Copies the svgDocOffset to the newSource array
            Array.Copy(svgDocOffset, 0, newSource, newSourceCopyOffset, sizeof(uint));
            newSourceCopyOffset += sizeof(uint);
            byte[] svgDocLength = GetBytesBigEndian((uint)svgLength);
            // Copies the svgDocLength to the newSource array
            Array.Copy(svgDocLength, 0, newSource, newSourceCopyOffset, sizeof(uint));
            newSourceCopyOffset += sizeof(uint);
            // Copies from the begining of the SVG Document Index Entry following the one added to the end of the SVG Table in source
            Array.Copy(source, (int)newDocumentIndexOffset, newSource, newSourceCopyOffset, (int)(record.length - svgDocIndexOffset + svgDocIndexAbsoluteOffset - newDocumentIndexOffset));
            newSourceCopyOffset += (int)(record.length - svgDocIndexOffset + svgDocIndexAbsoluteOffset - newDocumentIndexOffset);
            // Copies the new SVG content to newSource
            Array.Copy(svgContent, 0, newSource, newSourceCopyOffset, svgLength);
            // Makes sure the padding on the SVG Table remains correct
            newSourceCopyOffset += (int)(svgLength + newPadding);
            // Copies from the beginning of the table following the SVG table to the end of the file
            Array.Copy(source, (int)svgDocIndexAbsoluteOffset + (int)(record.length - svgDocIndexOffset + currPadding), newSource, newSourceCopyOffset, source.Length - ((int)svgDocIndexAbsoluteOffset + (int)(record.length - svgDocIndexOffset + currPadding)));
            source        = newSource;
            record.length = (uint)(record.length - diff);
            checksum      = GetBytesBigEndian(CalcTableChecksum(record.offset, record.length, ref source));
            Array.Copy(checksum, 0, source, (int)(record.offsetOfOffset - sizeof(uint)), sizeof(uint));
            record.checksum = BitConverter.ToUInt32(checksum, 0);
        }
Ejemplo n.º 6
0
        // Removes SVG of the specified glyph ID from the SVG table of the font.
        public void RemoveSvgContent(ref TableRecord record, ref byte[] source, ushort glyphID, FontModel fontModel)
        {
            start   = record.offset; // Start always refers to the offset to the file head.
            current = record.offset;

            // Read SVG main header.
            ushort version           = ReadDataAndIncreaseIndex <ushort>(source, ref current, sizeof(ushort));
            uint   svgDocIndexOffset = ReadDataAndIncreaseIndex <uint>(source, ref current, sizeof(uint));
            uint   reserved          = ReadDataAndIncreaseIndex <uint>(source, ref current, sizeof(uint));

            // Read document index.
            uint   documentIndexOffset       = start + svgDocIndexOffset;
            uint   svgDocIndexAbsoluteOffset = start + svgDocIndexOffset;
            ushort numEntries = ReadDataAndIncreaseIndex <ushort>(source, ref documentIndexOffset, sizeof(ushort));

            uint currPadding = CalculatePadding(record.length);

            SVGDocIdxEntry[] docIdxEntries = new SVGDocIdxEntry[numEntries];
            for (int i = 0; i < docIdxEntries.Length; i++)
            {
                docIdxEntries[i] = ReadSvgDocIdxEntry(source, ref documentIndexOffset);
                // Checks that SVG Document Index Entry matches the one to remove.
                // Note: Currently only supports one-to-one SVG/glyph ID mapping.
                if (docIdxEntries[i].startID.Equals(glyphID))
                {
                    int svgLength = (int)docIdxEntries[i].docLength;

                    // diff calculates the change in length of the font file because of removing the SVG.
                    // diff = length of the SVG content to remove + length of the SVG document index entry
                    long diff = svgLength + Marshal.SizeOf <SVGDocIdxEntry>();

                    uint svgOffset = docIdxEntries[i].docOffset + record.offset + svgDocIndexOffset; // Offset to the beginning of the SVG content

                    // Edits the SVG table length stored in the table record for SVG to the current length - diff
                    byte[] recordLength = GetBytesBigEndian((uint)(record.length - diff));
                    Array.Copy(recordLength, 0, source, (int)record.offsetOfOffset + sizeof(uint), sizeof(uint));

                    uint newPadding  = CalculatePadding((uint)(record.length - diff));
                    int  paddingDiff = (int)currPadding - (int)newPadding;
                    // Change the table record offsets for tables following the removed SVG content
                    ChangeTableRecOffsets(fontModel.TableRecords, ref source, (diff + paddingDiff), start + svgDocIndexOffset);
                    // Changes all of the SVG offsets in the SVG Document Index Entries to reflect an upward shift of 12 as caused by the removal of
                    // the specified SVG Document Index Entry
                    ChangeSvgOffsets(fontModel.TableRecords, ref source, diff - svgLength, 0);
                    // Changes the SVG offsets in the SVG Document Index Entries for the SVG content that was written after the removed SVG content in the
                    // font file to reflect an upward shift of the length of the removed SVG content
                    ChangeSvgOffsets(fontModel.TableRecords, ref source, diff - Marshal.SizeOf <SVGDocIdxEntry>(), docIdxEntries[i].docOffset);

                    uint numEntriesOffset = start + svgDocIndexOffset;

                    // Decrements the number specifying the number of SVG entries and edits font appropriately
                    byte[] newNumEntries = GetBytesBigEndian((ushort)(numEntries - 1));
                    Array.Copy(newNumEntries, 0, source, (int)numEntriesOffset, sizeof(ushort));

                    // Creates byte array for the corrected font and copies over font while removing SVG content and
                    // changing the padding of the SVG table appropriately

                    byte[] newSource = new byte[source.Length - (diff + paddingDiff)];

                    // Copies from the beginning of source to the end of the SVG Document Index Entry preceeding the one to be removed
                    int sourceIndex    = 0;
                    int newSourceIndex = 0;
                    int length         = (int)(documentIndexOffset - Marshal.SizeOf <SVGDocIdxEntry>());
                    Array.Copy(source, sourceIndex, newSource, newSourceIndex, length);

                    // Skips the DocIdxEntry to remove and copies from the beginning of the SVG DocIdxEntry following the removed one to the end of the SVG content preceeding the removed SVG content
                    sourceIndex    += (int)(documentIndexOffset);
                    newSourceIndex += length;
                    length          = (int)(svgDocIndexAbsoluteOffset + docIdxEntries[i].docOffset - documentIndexOffset);
                    Array.Copy(source, sourceIndex, newSource, newSourceIndex, length);

                    // Copies from the beginning of the SVG content following the SVG content to remove until the end of the SVG table
                    // Stops copying at this point in order to make sure the padding at the end of the SVG table is correct
                    sourceIndex    += length + (int)docIdxEntries[i].docLength;
                    newSourceIndex += length;
                    length          = (int)(record.offset + record.length - (svgDocIndexAbsoluteOffset + docIdxEntries[i].docOffset + docIdxEntries[i].docLength));
                    Array.Copy(source, sourceIndex, newSource, newSourceIndex, length);

                    // Copies from the beginning of the table following the SVG Table (after the entire SVG table and its padding) to the end of the font file
                    sourceIndex    = (int)(record.offset + record.length + currPadding);
                    newSourceIndex = (int)(record.offset + record.length - docIdxEntries[i].docLength - Marshal.SizeOf <SVGDocIdxEntry>() + newPadding);
                    length         = (int)(source.Length - (record.offset + record.length + currPadding));
                    Array.Copy(source, sourceIndex, newSource, newSourceIndex, length);

                    // Set the new source.
                    source = newSource;

                    // Alters the TableRecord object to reflect the new length of the table
                    record.length = (uint)(record.length - diff);

                    // Edits checksum of SVG table
                    byte[] checksum = GetBytesBigEndian(CalcTableChecksum(record.offset, record.length, ref source));
                    Array.Copy(checksum, 0, source, (int)(record.offsetOfOffset - sizeof(uint)), sizeof(uint));
                    record.checksum = BitConverter.ToUInt32(checksum, 0);
                    return;
                }
            }
        }
Ejemplo n.º 7
0
        public async Task AddSvgAsync(ushort glyphID, StorageFile svgFile)
        {
            // Add SVG data into a buffer.
            IBuffer buffer = await FileIO.ReadBufferAsync(svgFile);

            byte[] svgContent = new byte[buffer.Length];

            // Read buffer into bytes in svgContent.
            using (DataReader reader = DataReader.FromBuffer(buffer))
            {
                reader.ReadBytes(svgContent);
            }

            // Tweak the SVG: Add glyph ID and adjust the X/Y origin in accordance with OpenType spec.
            ChangeSvgOriginID(ref svgContent, glyphID);

            for (int i = 0; i < TableRecords.Length; i++)
            {
                if (TableRecords[i].tag == "SVG ")
                {
                    parser.AssembleSvgContent(ref TableRecords[i], ref source, svgContent, glyphID, this);
                    break;
                }
                // Checks if SVG table is not present
                else if (String.Compare(TableRecords[i].tag, "SVG ", StringComparison.Ordinal) > 0)
                {
                    // Changes offset table to reflect the addition of a new table
                    offsetTable = parser.UpdateOffsetTable(offsetTable, ref source);
                    // Changes the offsets contained in all of the table records in order to reflect the addition of a table record
                    parser.ChangeTableRecOffsets(TableRecords, ref source, ((sizeof(uint) * 4) * -1), 0);
                    byte[] newSource = new byte[source.Length + (sizeof(uint) * 6) + (sizeof(ushort) * 2)];
                    // Copies from the beginning of the source array to the end of the table record preceeding the location of the new SVG table record
                    Array.Copy(source, 0, newSource, 0, (int)(TableRecords[i].offsetOfOffset - (sizeof(uint) * 2)));
                    string tag    = "SVG ";
                    byte[] svgTag = Encoding.ASCII.GetBytes((string)tag);
                    // Adds SVG tag for the table record
                    Array.Copy(svgTag, 0, newSource, (int)(TableRecords[i].offsetOfOffset - (sizeof(uint) * 2)), sizeof(uint));
                    byte[] checksum = BitConverter.GetBytes((uint)0);
                    Array.Reverse(checksum);
                    // Adds the checksum for the table record
                    Array.Copy(checksum, 0, newSource, (int)(TableRecords[i].offsetOfOffset - sizeof(uint)), sizeof(uint));
                    byte[] offset = BitConverter.GetBytes((uint)(source.Length + (sizeof(uint) * 4)));
                    Array.Reverse(offset);
                    // Adds the offset for the table record
                    Array.Copy(offset, 0, newSource, (int)(TableRecords[i].offsetOfOffset), sizeof(uint));
                    byte[] length = BitConverter.GetBytes((uint)((sizeof(ushort) + sizeof(uint)) * 2));
                    Array.Reverse(length);
                    // Adds the length for the table record
                    Array.Copy(length, 0, newSource, (int)(TableRecords[i].offsetOfOffset + sizeof(uint)), sizeof(uint));
                    // Copies from the beginning of the table record following the new SVG table record in the source array to the end of the source array
                    Array.Copy(source, (int)(TableRecords[i].offsetOfOffset - (sizeof(uint) * 2)), newSource, (int)(TableRecords[i].offsetOfOffset + (sizeof(uint) * 2)), (int)(source.Length - (TableRecords[i].offsetOfOffset - (sizeof(uint) * 2))));
                    byte[] version = BitConverter.GetBytes((ushort)0);
                    Array.Reverse(version);
                    // Adds the SVG table at the very end of the font file
                    // Copies the version number to the newSource array (0)
                    Array.Copy(version, 0, newSource, (int)(source.Length + (sizeof(uint) * 4)), sizeof(ushort));
                    byte[] svgDocIndexOffset = BitConverter.GetBytes((uint)(sizeof(ushort) + (sizeof(uint) * 2)));
                    Array.Reverse(svgDocIndexOffset);
                    // Copies the SVG Document Index Offset to the newSource array
                    Array.Copy(svgDocIndexOffset, 0, newSource, (int)(source.Length + (sizeof(uint) * 4) + sizeof(ushort)), sizeof(uint));
                    byte[] reserved = BitConverter.GetBytes((uint)0);
                    Array.Reverse(reserved);
                    // Copies reserved to th enewSource array
                    Array.Copy(reserved, 0, newSource, (int)(source.Length + (sizeof(uint) * 5) + sizeof(ushort)), sizeof(uint));
                    byte[] numEntries = BitConverter.GetBytes((ushort)0);
                    Array.Reverse(numEntries);
                    // Copies the number of SVG Document Index Entries to the newSource array (in this case just 0 because it is a new table)
                    Array.Copy(numEntries, 0, newSource, (int)(source.Length + (sizeof(uint) * 6) + sizeof(ushort)), sizeof(ushort));
                    TableRecord svg = new TableRecord();
                    svg.tag            = "SVG ";
                    svg.checksum       = 0;
                    svg.offsetOfOffset = TableRecords[i].offsetOfOffset;
                    svg.offset         = (uint)(source.Length + (sizeof(uint) * 4));
                    svg.length         = (uint)((sizeof(ushort) + sizeof(uint)) * 2);
                    source             = newSource;
                    parser.Start       = 12; // Start is 12 because the offset table is always before the table records and is always 12 bytes in length
                    parser.Current     = 12;

                    TableRecords = new TableRecord[offsetTable.numTables];
                    for (int j = 0; j < TableRecords.Length; j++)
                    {
                        TableRecords[j] = parser.ReadTableRecord(source);
                    }
                    parser.AssembleSvgContent(ref svg, ref source, svgContent, glyphID, this);
                    break;
                }
            }

            // Create an updated font file in temp folder.
            StorageFolder tempFolder  = ApplicationData.Current.TemporaryFolder;
            StorageFile   newFontFile = await tempFolder.CreateFileAsync(FontFileName, CreationCollisionOption.GenerateUniqueName);

            await FileIO.WriteBytesAsync(newFontFile, source);

            // Hang on to the new font file.
            temporaryFontFile = newFontFile;
        }