Ejemplo n.º 1
0
        public static void Crop(Glyph glyph)
        {
            // Crop the top.
            while ((glyph.Subrect.Height > 1) && BitmapUtils.IsAlphaEntirely(0, glyph.Bitmap, new Rectangle(glyph.Subrect.X, glyph.Subrect.Y, glyph.Subrect.Width, 1)))
            {
                glyph.Subrect.Y++;
                glyph.Subrect.Height--;

                glyph.YOffset++;
            }

            // Crop the bottom.
            while ((glyph.Subrect.Height > 1) && BitmapUtils.IsAlphaEntirely(0, glyph.Bitmap, new Rectangle(glyph.Subrect.X, glyph.Subrect.Bottom - 1, glyph.Subrect.Width, 1)))
            {
                glyph.Subrect.Height--;
            }

            // Crop the left.
            while ((glyph.Subrect.Width > 1) && BitmapUtils.IsAlphaEntirely(0, glyph.Bitmap, new Rectangle(glyph.Subrect.X, glyph.Subrect.Y, 1, glyph.Subrect.Height)))
            {
                glyph.Subrect.X++;
                glyph.Subrect.Width--;

                glyph.XOffset++;
            }

            // Crop the right.
            while ((glyph.Subrect.Width > 1) && BitmapUtils.IsAlphaEntirely(0, glyph.Bitmap, new Rectangle(glyph.Subrect.Right - 1, glyph.Subrect.Y, 1, glyph.Subrect.Height)))
            {
                glyph.Subrect.Width--;

                glyph.XAdvance++;
            }
        }
        /// <summary>
        ///  This method for loading/saving a font file generated from MakeSpriteFont.
        /// </summary>
        /// <param name="serializer">The binary serializer to use.</param>
        /// <returns></returns>
        private void SerializeMakeSpriteFont(BinarySerializer serializer)
        {
            FourCC magicCode2 = "font";
            serializer.Serialize(ref magicCode2);
            if (magicCode2 != "font")
                return;

            // Writes the version
            if (serializer.Mode == SerializerMode.Read)
            {
                int version = serializer.Reader.ReadInt32();
                if (version != Version)
                {
                    throw new NotSupportedException(string.Format("SpriteFontData version [0x{0:X}] is not supported. Expecting [0x{1:X}]", version, Version));
                }
            }
            else
            {
                serializer.Writer.Write(Version);
            }
            
            // Deserialize Glyphs
            int glyphCount = 0;
            serializer.Serialize(ref glyphCount);

            // For MakeSpriteFont, there is only one GlyphPage.
            Glyphs = new Glyph[glyphCount];
            for (int i = 0; i < glyphCount; i++)
            {
                serializer.Serialize(ref Glyphs[i].Character);
                serializer.Serialize(ref Glyphs[i].Subrect);
                serializer.Serialize(ref Glyphs[i].Offset);
                serializer.Serialize(ref Glyphs[i].XAdvance);

                // Fix XAdvance with Right/Left for MakeSpriteFont
                Glyphs[i].XAdvance += Glyphs[i].Subrect.Right - Glyphs[i].Subrect.Left;
            }

            serializer.Serialize(ref LineSpacing);
            serializer.Serialize(ref DefaultCharacter);

            var image = new BitmapData();
            Bitmaps = new Bitmap[1] {new Bitmap()};
            Bitmaps[0].Data = image;

            serializer.Serialize(ref image.Width);
            serializer.Serialize(ref image.Height);
            serializer.SerializeEnum(ref image.PixelFormat);
            serializer.Serialize(ref image.RowStride);
            serializer.Serialize(ref image.CompressedHeight);
            serializer.Serialize(ref image.Data, image.RowStride * image.CompressedHeight);
        }
Ejemplo n.º 3
0
        public static Bitmap ArrangeGlyphs(Glyph[] sourceGlyphs)
        {
            // Build up a list of all the glyphs needing to be arranged.
            List<ArrangedGlyph> glyphs = new List<ArrangedGlyph>();

            for (int i = 0; i < sourceGlyphs.Length; i++)
            {
                ArrangedGlyph glyph = new ArrangedGlyph();

                glyph.Source = sourceGlyphs[i];

                // Leave a one pixel border around every glyph in the output bitmap.
                glyph.Width = sourceGlyphs[i].Subrect.Width + 2;
                glyph.Height = sourceGlyphs[i].Subrect.Height + 2;

                glyphs.Add(glyph);
            }

            // Sort so the largest glyphs get arranged first.
            glyphs.Sort(CompareGlyphSizes);

            // Work out how big the output bitmap should be.
            int outputWidth = GuessOutputWidth(sourceGlyphs);
            int outputHeight = 0;

            // Choose positions for each glyph, one at a time.
            for (int i = 0; i < glyphs.Count; i++)
            {
                PositionGlyph(glyphs, i, outputWidth);

                outputHeight = Math.Max(outputHeight, glyphs[i].Y + glyphs[i].Height);
            }

            // Create the merged output bitmap.
            outputHeight = MakeValidTextureSize(outputHeight, false);

            return CopyGlyphsToOutput(glyphs, outputWidth, outputHeight);
        }
        /// <summary>
        ///  This method for loading/saving a font file generated from MakeSpriteFont.
        /// </summary>
        /// <param name="serializer">The binaryserializer to use.</param>
        /// <returns></returns>
        private void SerializeMakeSpriteFont(BinarySerializer serializer)
        {
            FourCC magicCode2 = "font";
            serializer.Serialize(ref magicCode2);
            if (magicCode2 != "font")
                return;

            // Deserialize Glyphs
            int glyphCount = 0;
            serializer.Serialize(ref glyphCount);

            // For MakeSpriteFont, there is only one GlyphPage.
            Glyphs = new Glyph[glyphCount];
            for (int i = 0; i < glyphCount; i++)
            {
                serializer.Serialize(ref Glyphs[i].Character);
                serializer.Serialize(ref Glyphs[i].Subrect);
                serializer.Serialize(ref Glyphs[i].Offset);
                serializer.Serialize(ref Glyphs[i].XAdvance);

                // Fix XAdvance with Right/Left for MakeSpriteFont
                Glyphs[i].XAdvance += Glyphs[i].Subrect.Right - Glyphs[i].Subrect.Left;
            }

            serializer.Serialize(ref LineSpacing);
            serializer.Serialize(ref DefaultCharacter);

            var image = new BitmapData();
            Bitmaps = new Bitmap[1] {new Bitmap()};
            Bitmaps[0].Data = image;

            serializer.Serialize(ref image.Width);
            serializer.Serialize(ref image.Height);
            serializer.SerializeEnum(ref image.PixelFormat);
            serializer.Serialize(ref image.RowStride);
            serializer.Serialize(ref image.CompressedHeight);
            serializer.Serialize(ref image.Data, image.RowStride * image.CompressedHeight);
        }
Ejemplo n.º 5
0
        // Heuristic guesses what might be a good output width for a list of glyphs.
        static int GuessOutputWidth(Glyph[] sourceGlyphs)
        {
            int maxWidth = 0;
            int totalSize = 0;

            foreach (Glyph glyph in sourceGlyphs)
            {
                maxWidth = Math.Max(maxWidth, glyph.Subrect.Width);
                totalSize += glyph.Subrect.Width * glyph.Subrect.Height;
            }

            int width = Math.Max((int)Math.Sqrt(totalSize), maxWidth);

            return MakeValidTextureSize(width, true);
        }
Ejemplo n.º 6
0
 public static void WriteSpriteFont(FontDescription options, string outputFilename, Glyph[] glyphs, float lineSpacing, Bitmap bitmap)
 {
     using (var stream = new NativeFileStream(outputFilename, NativeFileMode.Create, NativeFileAccess.Write))
     {
         WriteSpriteFont(options, stream, glyphs, lineSpacing, bitmap);
     }
 }
Ejemplo n.º 7
0
        static void WriteGlyphs(BinaryWriter writer, Glyph[] glyphs)
        {
            writer.Write(glyphs.Length);

            foreach (Glyph glyph in glyphs)
            {
                writer.Write((int)glyph.Character);

                writer.Write(glyph.Subrect.Left);
                writer.Write(glyph.Subrect.Top);
                writer.Write(glyph.Subrect.Right);
                writer.Write(glyph.Subrect.Bottom);

                writer.Write(glyph.XOffset);
                writer.Write(glyph.YOffset);
                writer.Write(glyph.XAdvance);
            }
        }
Ejemplo n.º 8
0
        public static void WriteSpriteFont(FontDescription options, Stream outputStream, Glyph[] glyphs, float lineSpacing, Bitmap bitmap)
        {
            var writer = new BinaryWriter(outputStream);
            WriteMagic(writer);
            writer.Write(SpriteFontData.Version);
            WriteGlyphs(writer, glyphs);

            writer.Write(lineSpacing);
            writer.Write(options.DefaultCharacter);

            WriteBitmap(writer, options, bitmap);
            writer.Flush();
        }
Ejemplo n.º 9
0
        private Glyph ImportGlyph(Factory factory, FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize, bool activateAntiAliasDetection)
        {
            var indices = fontFace.GetGlyphIndices(new int[] {character});

            var metrics = fontFace.GetDesignGlyphMetrics(indices, false);
            var metric = metrics[0];

            var width = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;
            var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;

            var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize;
            var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize;

            var advanceWidth = (float)(metric.AdvanceWidth) / fontMetrics.DesignUnitsPerEm * fontSize;
            var advanceHeight = (float)(metric.AdvanceHeight) / fontMetrics.DesignUnitsPerEm * fontSize;

            var pixelWidth = (int)Math.Ceiling(width + 2);
            var pixelHeight = (int)Math.Ceiling(height + 2);

            Bitmap bitmap;
            if(char.IsWhiteSpace(character))
            {
                bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
            }
            else
            {
                var glyphRun = new GlyphRun()
                               {
                                   FontFace = fontFace,
                                   Advances = new[] { (float)Math.Round(advanceWidth) },
                                   FontSize = fontSize,
                                   BidiLevel = 0,
                                   Indices = indices,
                                   IsSideways = false,
                                   Offsets = new[] {new GlyphOffset()}
                               };

                var matrix = SharpDX.Matrix.Identity;
                matrix.M41 = -(float)Math.Floor(xOffset - 1);
                matrix.M42 = -(float)Math.Floor(yOffset - 1);

                RenderingMode renderingMode;
                if (activateAntiAliasDetection)
                {
                    var rtParams = new RenderingParams(factory);
                    renderingMode = fontFace.GetRecommendedRenderingMode(fontSize, 1.0f, MeasuringMode.Natural, rtParams);
                    rtParams.Dispose();
                }
                else
                {
                    renderingMode = RenderingMode.Aliased;
                }

                using(var runAnalysis = new GlyphRunAnalysis(factory,
                    glyphRun,
                    1.0f,
                    matrix,
                    renderingMode,
                    MeasuringMode.Natural,
                    0.0f,
                    0.0f))
                {
                    var bounds = new SharpDX.Rectangle(0, 0, pixelWidth, pixelHeight);
                    bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);

                    if(renderingMode == RenderingMode.Aliased)
                    {
                        var texture = new byte[bounds.Width * bounds.Height];
                        runAnalysis.CreateAlphaTexture(TextureType.Aliased1x1, bounds, texture, texture.Length);
                        bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
                        for (int y = 0; y < bounds.Height; y++)
                        {
                            for (int x = 0; x < bounds.Width; x++)
                            {
                                int pixelX = y * bounds.Width + x;
                                var grey = texture[pixelX];
                                var color = Color.FromArgb(grey, grey, grey);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }
                    else
                    {
                        var texture = new byte[bounds.Width * bounds.Height * 3];
                        runAnalysis.CreateAlphaTexture(TextureType.Cleartype3x1, bounds, texture, texture.Length);
                        for (int y = 0; y < bounds.Height; y++)
                        {
                            for (int x = 0; x < bounds.Width; x++)
                            {
                                int pixelX = (y * bounds.Width + x) * 3;
                                var red = texture[pixelX];
                                var green = texture[pixelX + 1];
                                var blue = texture[pixelX + 2];
                                var color = Color.FromArgb(red, green, blue);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }

                    //var positionUnderline = (float)fontMetrics.UnderlinePosition / fontMetrics.DesignUnitsPerEm * fontSize;
                    //var positionUnderlineSize = (float)fontMetrics.UnderlineThickness / fontMetrics.DesignUnitsPerEm * fontSize;
                }
            }

            var glyph = new Glyph(character, bitmap)
                        {
                            XOffset = (float)Math.Floor(xOffset-1),
                            XAdvance = (float)Math.Round(advanceWidth),
                            YOffset = (float)Math.Floor(yOffset-1),
                        };
            return glyph;
        }
        /// <summary>
        ///  This method for loading/saving a font file generated from AngelCode BMFont.
        /// </summary>
        /// <param name="serializer">The binaryserializer to use.</param>
        private void SerializeBMFFont(BinarySerializer serializer)
        {
            // ----------------------------------------------------------
            // Read block Info (1)
            // ----------------------------------------------------------
            byte blockType = 1;
            serializer.Serialize(ref blockType);
            if (blockType != 1)
                return;

            // Skip Info block
            int expectedBlockSize = 0;
            serializer.Serialize(ref expectedBlockSize);
            serializer.Stream.Seek(expectedBlockSize, SeekOrigin.Current);

            // ----------------------------------------------------------
            // Read block Common (2)
            // ----------------------------------------------------------
            serializer.Serialize(ref blockType);
            if (blockType != 2)
                return;
            var common = new BMFCommon();
            common.Serialize(serializer);

            // Copy the base offset.
            BaseOffset = common.Base;
            LineSpacing = common.LineHeight;

            // ----------------------------------------------------------
            // Read block page names (3)
            // ----------------------------------------------------------
            serializer.Serialize(ref blockType);
            if (blockType != 3)
                return;
            serializer.Serialize(ref expectedBlockSize);

            // Create bitmap array.
            Bitmaps = new Bitmap[common.PageCount];
            for (int i = 0; i < Bitmaps.Length; i++)
            {
                string name = null;
                serializer.Serialize(ref name, true);
                // Store the name in data
                Bitmaps[i] = new Bitmap { Data = name };
            }

            // ----------------------------------------------------------
            // Read block glyphs (4)
            // ----------------------------------------------------------
            serializer.Serialize(ref blockType);
            if (blockType != 4)
                return;
            serializer.Serialize(ref expectedBlockSize);

            int countChars = expectedBlockSize/20;

            var bmfGlyph = new BMFGlyph();

            Glyphs = new Glyph[countChars];
            for (int i = 0; i < Glyphs.Length; i++)
            {
                bmfGlyph.Serialize(serializer);

                Glyphs[i] = new Glyph
                                {
                                    Character = bmfGlyph.Id, 
                                    Subrect = new Rectangle(bmfGlyph.X, bmfGlyph.Y, bmfGlyph.Width, bmfGlyph.Height), 
                                    Offset = {X = bmfGlyph.OffsetX, Y = bmfGlyph.OffsetY}, 
                                    XAdvance = bmfGlyph.AdvanceX,
                                    BitmapIndex = bmfGlyph.PageIndex
                                };
            }

            // ----------------------------------------------------------
            // Read block kernings (5) optional
            // ----------------------------------------------------------
            if (serializer.Stream.Position < serializer.Stream.Length)
            {
                // If there is still some data to read, there is probably some kernings
                serializer.Serialize(ref blockType);
                if (blockType != 5)
                    return;
                serializer.Serialize(ref expectedBlockSize);
                int kernelCount = expectedBlockSize/10;

                Kernings = new Kerning[kernelCount];
                for (int i = 0; i < Kernings.Length; i++)
                {
                    serializer.Serialize(ref Kernings[i].First);
                    serializer.Serialize(ref Kernings[i].Second);
                    short offset = 0;
                    serializer.Serialize(ref offset);
                    Kernings[i].Offset = offset;
                }
            }
        }
Ejemplo n.º 11
0
        public static void WriteSpriteFont(CommandLineOptions options, Glyph[] glyphs, float lineSpacing, Bitmap bitmap)
        {
            using (FileStream file = File.OpenWrite(options.OutputFile))
            using (BinaryWriter writer = new BinaryWriter(file))
            {
                WriteMagic(writer);
                WriteGlyphs(writer, glyphs);

                writer.Write(lineSpacing);
                writer.Write(options.DefaultCharacter);
                
                WriteBitmap(writer, options, bitmap);
            }
        }
Ejemplo n.º 12
0
        private Glyph ImportGlyph(Factory factory, FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize, FontAntiAliasMode antiAliasMode)
        {
            var indices = fontFace.GetGlyphIndices(new int[] { character });

            var metrics = fontFace.GetDesignGlyphMetrics(indices, false);
            var metric  = metrics[0];

            var width  = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;
            var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize;

            var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize;
            var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize;

            var advanceWidth  = (float)metric.AdvanceWidth / fontMetrics.DesignUnitsPerEm * fontSize;
            var advanceHeight = (float)metric.AdvanceHeight / fontMetrics.DesignUnitsPerEm * fontSize;

            var pixelWidth  = (int)Math.Ceiling(width + 4);
            var pixelHeight = (int)Math.Ceiling(height + 4);

            var matrix = Matrix.Identity;

            matrix.M41 = -(float)Math.Floor(xOffset) + 1;
            matrix.M42 = -(float)Math.Floor(yOffset) + 1;

            Bitmap bitmap;

            if (char.IsWhiteSpace(character))
            {
                bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
            }
            else
            {
                var glyphRun = new GlyphRun()
                {
                    FontFace   = fontFace,
                    Advances   = new[] { (float)Math.Ceiling(advanceWidth) },
                    FontSize   = fontSize,
                    BidiLevel  = 0,
                    Indices    = indices,
                    IsSideways = false,
                    Offsets    = new[] { new GlyphOffset() }
                };


                RenderingMode renderingMode;
                if (antiAliasMode != FontAntiAliasMode.Aliased)
                {
                    var rtParams = new RenderingParams(factory);
                    renderingMode = fontFace.GetRecommendedRenderingMode(fontSize, 1.0f, MeasuringMode.Natural, rtParams);
                    rtParams.Dispose();
                }
                else
                {
                    renderingMode = RenderingMode.Aliased;
                }

                using (var runAnalysis = new GlyphRunAnalysis(factory,
                                                              glyphRun,
                                                              1.0f,
                                                              (Matrix3x2)matrix,
                                                              renderingMode,
                                                              MeasuringMode.Natural,
                                                              0.0f,
                                                              0.0f))
                {
                    var bounds = new SharpDX.Rectangle(0, 0, pixelWidth, pixelHeight);
                    bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);

                    if (renderingMode == RenderingMode.Aliased)
                    {
                        var texture = new byte[bounds.Width * bounds.Height];
                        runAnalysis.CreateAlphaTexture(TextureType.Aliased1x1, bounds, texture, texture.Length);
                        for (int y = 0; y < bounds.Height; y++)
                        {
                            for (int x = 0; x < bounds.Width; x++)
                            {
                                int pixelX = y * bounds.Width + x;
                                var grey   = texture[pixelX];
                                var color  = Color.FromArgb(grey, grey, grey);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }
                    else
                    {
                        var texture = new byte[bounds.Width * bounds.Height * 3];
                        runAnalysis.CreateAlphaTexture(TextureType.Cleartype3x1, bounds, texture, texture.Length);
                        for (int y = 0; y < bounds.Height; y++)
                        {
                            for (int x = 0; x < bounds.Width; x++)
                            {
                                int pixelX = (y * bounds.Width + x) * 3;
                                var red    = LinearToGamma(texture[pixelX]);
                                var green  = LinearToGamma(texture[pixelX + 1]);
                                var blue   = LinearToGamma(texture[pixelX + 2]);
                                var color  = Color.FromArgb(red, green, blue);

                                bitmap.SetPixel(x, y, color);
                            }
                        }
                    }
                }
            }

            var glyph = new Glyph(character, bitmap)
            {
                XOffset  = -matrix.M41,
                XAdvance = advanceWidth,
                YOffset  = -matrix.M42,
            };

            return(glyph);
        }
Ejemplo n.º 13
0
        /// <summary>
        ///  This method for loading/saving a font file generated from AngelCode BMFont.
        /// </summary>
        /// <param name="serializer">The binaryserializer to use.</param>
        private void SerializeBMFFont(BinarySerializer serializer)
        {
            // ----------------------------------------------------------
            // Read block Info (1)
            // ----------------------------------------------------------
            byte blockType = 1;

            serializer.Serialize(ref blockType);
            if (blockType != 1)
            {
                return;
            }

            // Skip Info block
            int expectedBlockSize = 0;

            serializer.Serialize(ref expectedBlockSize);
            serializer.Stream.Seek(expectedBlockSize, SeekOrigin.Current);

            // ----------------------------------------------------------
            // Read block Common (2)
            // ----------------------------------------------------------
            serializer.Serialize(ref blockType);
            if (blockType != 2)
            {
                return;
            }
            var common = new BMFCommon();

            common.Serialize(serializer);

            // Copy the base offset.
            BaseOffset  = common.Base;
            LineSpacing = common.LineHeight;

            // ----------------------------------------------------------
            // Read block page names (3)
            // ----------------------------------------------------------
            serializer.Serialize(ref blockType);
            if (blockType != 3)
            {
                return;
            }
            serializer.Serialize(ref expectedBlockSize);

            // Create bitmap array.
            Bitmaps = new Bitmap[common.PageCount];
            for (int i = 0; i < Bitmaps.Length; i++)
            {
                string name = null;
                serializer.Serialize(ref name, true);
                // Store the name in data
                Bitmaps[i] = new Bitmap {
                    Data = name
                };
            }

            // ----------------------------------------------------------
            // Read block glyphs (4)
            // ----------------------------------------------------------
            serializer.Serialize(ref blockType);
            if (blockType != 4)
            {
                return;
            }
            serializer.Serialize(ref expectedBlockSize);

            int countChars = expectedBlockSize / 20;

            var bmfGlyph = new BMFGlyph();

            Glyphs = new Glyph[countChars];
            for (int i = 0; i < Glyphs.Length; i++)
            {
                bmfGlyph.Serialize(serializer);

                Glyphs[i] = new Glyph
                {
                    Character   = bmfGlyph.Id,
                    Subrect     = new Rectangle(bmfGlyph.X, bmfGlyph.Y, bmfGlyph.Width, bmfGlyph.Height),
                    Offset      = { X = bmfGlyph.OffsetX, Y = bmfGlyph.OffsetY },
                    XAdvance    = bmfGlyph.AdvanceX,
                    BitmapIndex = bmfGlyph.PageIndex
                };
            }

            // ----------------------------------------------------------
            // Read block kernings (5) optional
            // ----------------------------------------------------------
            if (serializer.Stream.Position < serializer.Stream.Length)
            {
                // If there is still some data to read, there is probably some kernings
                serializer.Serialize(ref blockType);
                if (blockType != 5)
                {
                    return;
                }
                serializer.Serialize(ref expectedBlockSize);
                int kernelCount = expectedBlockSize / 10;

                Kernings = new Kerning[kernelCount];
                for (int i = 0; i < Kernings.Length; i++)
                {
                    serializer.Serialize(ref Kernings[i].First);
                    serializer.Serialize(ref Kernings[i].Second);
                    short offset = 0;
                    serializer.Serialize(ref offset);
                    Kernings[i].Offset = offset;
                }
            }
        }