public static u64 U64(byte[] buffer, ref Int64 index)
        {
            u64 result = BigEndianRead.U64(buffer, index);

            index += 8;
            return(result);
        }
        public static u16 U16(byte[] buffer, ref Int64 index)
        {
            u16 result = BigEndianRead.U16(buffer, index);

            index += 2;
            return(result);
        }
        public static uint U32(byte[] buffer, ref Int64 index)
        {
            uint result = BigEndianRead.U32(buffer, index);

            index += 4;
            return(result);
        }
        public void GetControlPoints(string unicodeCharacter, List <Glyph> result)
        {
            #region Convert Character to glyph ID
            Profiler.BeginSample("Convert Character to Glyph ID");
            int codePoint = char.ConvertToUtf32(unicodeCharacter, 0);
            int glyphID   = 0;          // Missing Glyph
            if (codePoint > u16.MaxValue)
            {
                Debug.LogWarning("Character is not supported in Open Font format 4.");
            }
            else
            {
                for (int segmentIndex = 0; segmentIndex < _selectedEncoding.endCodes.Length; ++segmentIndex)
                {
                    if (_selectedEncoding.endCodes[segmentIndex] >= codePoint)
                    {
                        if (_selectedEncoding.startCodes[segmentIndex] <= codePoint)
                        {
                            u16 idRangeOffset = _selectedEncoding.idRangeOffsets[segmentIndex];
                            if (idRangeOffset != 0)
                            {
                                // Indexes are in an array right after the array of offsets, we'll need to convert the address to be indexed with bytes:
                                s64 relativeCodePoint       = (codePoint - _selectedEncoding.startCodes[segmentIndex]) * sizeof(u16);
                                s64 addressOfcurrentSegment = _selectedEncodingIDRangeOffsetLocation + segmentIndex * sizeof(u16);
                                s64 glyphIdArrayIndex       = addressOfcurrentSegment + relativeCodePoint + idRangeOffset;

                                glyphID = BigEndianRead.U16(_fontFileBuffer, glyphIdArrayIndex);
                                if (glyphID != 0)
                                {
                                    glyphID = (glyphID + _selectedEncoding.idDeltas[segmentIndex]) % 65536;                                    // Do modulo manually, rather than relying on 16-bit integer wrapping.
                                    break;
                                }
                                else
                                {
                                    break;                                    // Missing glyph
                                }
                            }
                            else
                            {
                                glyphID = (_selectedEncoding.idDeltas[segmentIndex] + codePoint) % 65536;
                                break;
                            }
                        }
                        else
                        {
                            break;                            // Missing Glyph
                        }
                    }
                }
            }
            Profiler.EndSample();
            #endregion

            GetControlPoints(glyphID, result);
        }
        public static u32 CalculateChecksum(byte[] fileBuffer, u32 length, s64 offsetInBuffer)
        {
            u32 padding      = length % 4 > 0u ? 4u : 0u;
            u32 paddedLength = ((length / 4) * 4) + padding;
            u32 checksum     = 0;

            for (int tableIndex = 0; tableIndex < paddedLength; tableIndex += 4)
            {
                checksum += BigEndianRead.U32(fileBuffer, offsetInBuffer + tableIndex);
            }

            return(checksum);
        }
        public static float F2Dot14(byte[] buffer, ref Int64 index)
        {
            s16 fixedPoint = BigEndianRead.S16(buffer, index);

            index += 2;

            float result = 0;
            int   twoBitTwosComplement = fixedPoint >> 14;

            if ((twoBitTwosComplement & 2) > 0)
            {
                int everythingFilledExceptTwoBits = ~3;
                twoBitTwosComplement = twoBitTwosComplement | everythingFilledExceptTwoBits;
            }

            result += twoBitTwosComplement;
            float temp = ((float)(fixedPoint & 0x3FFF)) / 0x4000;;

            result += temp;
            return(result);
        }
        public void GetControlPoints(int glyphID, List <Glyph> result)
        {
            if (glyphID >= Maximums.numberOfGlyphs)
            {
                return;
            }
            #region Parse location indexing table
            s64 offsetIntoGlyphArray = 0;
            if (_indexToLocationIndex >= 0)
            {
                var locaTableRecord = TableDirectory[_indexToLocationIndex];
                s64 arrayOffset     = locaTableRecord.offset;

                if (FontHeader.indexToLocFormat == OpenFontFormat.IndexToLocFormat.ShortOffsets)
                {
                    s64 locationIndex = arrayOffset + glyphID * sizeof(u16);
                    offsetIntoGlyphArray = BigEndianRead.U16(_fontFileBuffer, locationIndex) * sizeof(u16);
                    if (offsetIntoGlyphArray == BigEndianRead.U16(_fontFileBuffer, locationIndex + sizeof(u16)))
                    {
                        return;                        // No contours.
                    }
                }
                else if (FontHeader.indexToLocFormat == OpenFontFormat.IndexToLocFormat.LongOffsets)
                {
                    s64 locationIndex = arrayOffset + glyphID * sizeof(u32);
                    offsetIntoGlyphArray = BigEndianRead.U32(_fontFileBuffer, locationIndex);
                    if (offsetIntoGlyphArray == BigEndianRead.U32(_fontFileBuffer, locationIndex + sizeof(u32)))
                    {
                        return;                        // No Contours.
                    }
                }
            }
            #endregion

            #region Parse Glyph
            Profiler.BeginSample("Parse Glyph");
            if (_glyphDataIndex >= 0)
            {
                var glyfHeaderRecord = TableDirectory[_glyphDataIndex];
                GlyphHeader = new OpenFontFormat.GlyphHeader();

                s64 arrayOffsetOfGlyphHeader = glyfHeaderRecord.offset;
                s64 arrayOffset = arrayOffsetOfGlyphHeader + offsetIntoGlyphArray;

                GlyphHeader.numberOfContours = BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                GlyphHeader.xMin             = BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                GlyphHeader.yMin             = BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                GlyphHeader.xMax             = BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                GlyphHeader.yMax             = BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);

                if (GlyphHeader.numberOfContours == 0)
                {
                    Debug.LogError("Encountered a glyph with 0 contours, which is undefined at this stage.");
                }

                if (GlyphHeader.numberOfContours < 0)
                {
                    u16 flags = 0;
                    do
                    {
                        // Composite glyph
                        flags = BigEndianReadAndAdvance.U16(_fontFileBuffer, ref arrayOffset);
                        u16 glyphIndex = BigEndianReadAndAdvance.U16(_fontFileBuffer, ref arrayOffset);

                        s32 xOffset = 0;
                        s32 yOffset = 0;

                        s32 firstGlyphMatchPointNumber = 0;
                        s32 thisGlyphMatchPointNumber  = 0;

                        float scale   = 1.0f;
                        float yScale  = 1.0f;
                        float scale01 = 1.0f;
                        float scale10 = 1.0f;

                        bool argsAreXYOffsets = (flags & (u16)OpenFontFormat.CompositeGlyphFlags.ArgsAreXyValues) > 0;
                        bool argsAreWords     = (flags & (u16)OpenFontFormat.CompositeGlyphFlags.Args1And2AreWords) > 0;

                        if (argsAreXYOffsets)
                        {
                            if (argsAreWords)
                            {
                                xOffset += BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                                yOffset += BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                            }
                            else
                            {
                                xOffset += BigEndianReadAndAdvance.U8(_fontFileBuffer, ref arrayOffset);
                                yOffset += BigEndianReadAndAdvance.U8(_fontFileBuffer, ref arrayOffset);
                            }
                        }
                        if ((flags & (u16)OpenFontFormat.CompositeGlyphFlags.WeHaveAScale) > 0)
                        {
                            scale = BigEndianReadAndAdvance.F2Dot14(_fontFileBuffer, ref arrayOffset);
                        }
                        else if ((flags & (u16)OpenFontFormat.CompositeGlyphFlags.SeparateScale) > 0)
                        {
                            scale  = BigEndianReadAndAdvance.F2Dot14(_fontFileBuffer, ref arrayOffset);
                            yScale = BigEndianReadAndAdvance.F2Dot14(_fontFileBuffer, ref arrayOffset);
                        }
                        else if ((flags & (u16)OpenFontFormat.CompositeGlyphFlags.HasMatrix2x2) > 0)
                        {
                            scale   = BigEndianReadAndAdvance.F2Dot14(_fontFileBuffer, ref arrayOffset);
                            scale01 = BigEndianReadAndAdvance.F2Dot14(_fontFileBuffer, ref arrayOffset);
                            scale10 = BigEndianReadAndAdvance.F2Dot14(_fontFileBuffer, ref arrayOffset);
                            yScale  = BigEndianReadAndAdvance.F2Dot14(_fontFileBuffer, ref arrayOffset);
                        }
                        GetControlPoints(glyphIndex, result);
                    } while ((flags & (u16)OpenFontFormat.CompositeGlyphFlags.MoreComponents) > 0);

                    u16  instructionCount = BigEndianReadAndAdvance.U16(_fontFileBuffer, ref arrayOffset);
                    u8[] instructions     = new u8[instructionCount];

                    for (int instructionIndex = 0; instructionIndex < instructionCount; ++instructionIndex)
                    {
                        instructions[instructionIndex] = BigEndianReadAndAdvance.U8(_fontFileBuffer, ref arrayOffset);
                    }
                }

                else if (GlyphHeader.numberOfContours > 0)
                {
                    Glyph simpleGlyph = new Glyph();
                    result.Add(simpleGlyph);
                    simpleGlyph.ControlPoints = new List <Vector2>();
                    simpleGlyph.OnCurve       = new List <bool>();

                    simpleGlyph.EndIndices = new List <int>(GlyphHeader.numberOfContours);

                    for (int contourIndex = 0; contourIndex < GlyphHeader.numberOfContours; ++contourIndex)
                    {
                        simpleGlyph.EndIndices.Add(BigEndianReadAndAdvance.U16(_fontFileBuffer, ref arrayOffset));
                    }

                    u16 instructionCount = BigEndianReadAndAdvance.U16(_fontFileBuffer, ref arrayOffset);
                    arrayOffset += instructionCount;                    // skip instructions for now, instructions are one byte.

                    // Unroll the flags array:
                    int       totalPointCount = simpleGlyph.EndIndices[simpleGlyph.EndIndices.Count - 1] + 1;
                    List <u8> unrolledFlags   = new List <u8>();
                    while (unrolledFlags.Count < totalPointCount)
                    {
                        u8  flag      = _fontFileBuffer[arrayOffset++];
                        u16 flagCount = 1;
                        if ((flag & (u8)OpenFontFormat.GlyphFlags.Repeat) > 0)
                        {
                            flagCount += _fontFileBuffer[arrayOffset++];
                        }
                        for (int identicalFlagIndex = 0; identicalFlagIndex < flagCount; ++identicalFlagIndex)
                        {
                            unrolledFlags.Add(flag);
                        }
                    }

                    #region Parse X Coordinates
                    var xCoordinates = new List <s16>();
                    s16 lastX        = 0;
                    for (int flagIndex = 0; flagIndex < unrolledFlags.Count; ++flagIndex)
                    {
                        var flag   = unrolledFlags[flagIndex];
                        s16 xCoord = 0;

                        bool isOnCurve      = (flag & (u8)OpenFontFormat.GlyphFlags.OnCurvePoint) > 0;
                        bool isShort        = (flag & (u8)OpenFontFormat.GlyphFlags.X_ShortVector) > 0;
                        bool sameOrPositive = (flag & (u8)OpenFontFormat.GlyphFlags.X_IsSameOrPositive) > 0;
                        bool isRepeated     = !isShort && sameOrPositive;
                        bool isPositive     = isShort && sameOrPositive;

                        simpleGlyph.OnCurve.Add(isOnCurve);

                        if (isOnCurve)
                        {
                            if (isRepeated)
                            {
                                xCoord = lastX;
                            }
                            else if (isShort)
                            {
                                xCoord = _fontFileBuffer[arrayOffset++];
                                if (!isPositive)
                                {
                                    xCoord = (short)-xCoord;
                                }
                                xCoord += lastX;
                            }
                            else
                            {
                                xCoord  = BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                                xCoord += lastX;
                            }
                            xCoordinates.Add(xCoord);
                            lastX = xCoord;
                        }
                        else
                        {
                            if (isRepeated)
                            {
                                xCoord = lastX;
                            }
                            else if (isShort)
                            {
                                xCoord = _fontFileBuffer[arrayOffset++];
                                if (!isPositive)
                                {
                                    xCoord = (short)-xCoord;
                                }
                                xCoord += lastX;
                            }
                            else
                            {
                                xCoord  = BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                                xCoord += lastX;
                            }
                            xCoordinates.Add(xCoord);
                            lastX = xCoord;
                        }
                    }
                    #endregion
                    #region Parse Y Coordinates
                    var yCoordinates = new List <s16>();
                    s16 lastY        = 0;
                    for (int flagIndex = 0; flagIndex < unrolledFlags.Count; ++flagIndex)
                    {
                        var flag   = unrolledFlags[flagIndex];
                        s16 yCoord = 0;

                        bool isOnCurve      = (flag & (u8)OpenFontFormat.GlyphFlags.OnCurvePoint) > 0;
                        bool isShort        = (flag & (u8)OpenFontFormat.GlyphFlags.Y_ShortVector) > 0;
                        bool sameOrPositive = (flag & (u8)OpenFontFormat.GlyphFlags.Y_IsSameOrPositive) > 0;
                        bool isRepeated     = !isShort && sameOrPositive;
                        bool isPositive     = isShort && sameOrPositive;

                        if (isOnCurve)
                        {
                            if (isRepeated)
                            {
                                yCoord = lastY;
                            }
                            else if (isShort)
                            {
                                yCoord = _fontFileBuffer[arrayOffset++];
                                if (!isPositive)
                                {
                                    yCoord = (short)-yCoord;
                                }
                                yCoord += lastY;
                            }
                            else
                            {
                                yCoord  = BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                                yCoord += lastY;
                            }
                            yCoordinates.Add(yCoord);
                            lastY = yCoord;
                        }
                        else
                        {
                            if (isRepeated)
                            {
                                yCoord = lastY;
                            }
                            else if (isShort)
                            {
                                yCoord = _fontFileBuffer[arrayOffset++];
                                if (!isPositive)
                                {
                                    yCoord = (short)-yCoord;
                                }
                                yCoord += lastY;
                            }
                            else
                            {
                                yCoord  = BigEndianReadAndAdvance.S16(_fontFileBuffer, ref arrayOffset);
                                yCoord += lastY;
                            }
                            yCoordinates.Add(yCoord);
                            lastY = yCoord;
                        }
                    }
                    #endregion

                    for (int coordinateIndex = 0; coordinateIndex < xCoordinates.Count; ++coordinateIndex)
                    {
                        var x = xCoordinates[coordinateIndex] / 256f;
                        var y = yCoordinates[coordinateIndex] / 256f;
                        simpleGlyph.ControlPoints.Add(new Vector2(x, y));
                    }
                }
            }
            else
            {
                //Debug.LogError("No glyf table found", this);
            }
            Profiler.EndSample();
            #endregion

            return;
        }