/// <inheritdoc/>
        public override void ExportPreprocessed(ContentManager manager, IContentProcessorMetadata metadata, BinaryWriter writer, PlatformNativeSurface input, Boolean delete)
        {
            if (!metadata.IsFile)
            {
                throw new NotSupportedException();
            }

            var imgData = File.ReadAllBytes(metadata.AssetFilePath);

            writer.Write(metadata.Extension);
            writer.Write(imgData.Length);
            writer.Write(imgData);

            var glyphs = OpenGLSpriteFontHelper.IdentifyGlyphs(input);

            writer.Write(glyphs.Count());
            writer.Write('?');

            foreach (var glyph in glyphs)
            {
                writer.Write(glyph.X);
                writer.Write(glyph.Y);
                writer.Write(glyph.Width);
                writer.Write(glyph.Height);
            }
        }
        /// <inheritdoc/>
        public override SpriteFont Process(ContentManager manager, IContentProcessorMetadata metadata, PlatformNativeSurface input)
        {
            var positions = OpenGLSpriteFontHelper.IdentifyGlyphs(input);
            var texture   = manager.Process <PlatformNativeSurface, Texture2D>(input);
            var face      = new SpriteFontFace(manager.Ultraviolet, texture, null, positions, null, true);

            return(new SpriteFont(manager.Ultraviolet, face));
        }
        /// <summary>
        /// Processes the definition for a single font face.
        /// </summary>
        private static SpriteFontFace ProcessFace(Dictionary <String, PlatformNativeSurface> textures, ContentManager manager,
                                                  IContentProcessorMetadata metadata, SpriteFontFaceDescription description, String style, IEnumerable <CharacterRegion> characterRegions)
        {
            if (description == null)
            {
                return(null);
            }

            var textureName   = ResolveDependencyAssetPath(metadata, description.Texture);
            var textureRegion = description.TextureRegion;

            if (String.IsNullOrEmpty(textureName))
            {
                throw new ContentLoadException(OpenGLStrings.InvalidSpriteFontTexture);
            }

            var faceSurface = textures[textureName];
            var faceGlyphs  = OpenGLSpriteFontHelper.IdentifyGlyphs(faceSurface, textureRegion);

            var kerningDefaultAdjustment = description.Kernings?["default"] ?? 0;
            var kerningPairs             = description.Kernings?.Where(x => !String.Equals(x.Key, "default", StringComparison.InvariantCulture))
                                           .ToDictionary(x => CreateKerningPair(x.Key), x => x.Value);

            var kerning = new SpriteFontKerning()
            {
                DefaultAdjustment = kerningDefaultAdjustment
            };

            foreach (var kvp in kerningPairs)
            {
                kerning.Set(kvp.Key, kvp.Value);
            }

            var ascender  = description.Ascender;
            var descender = description.Descender;

            var faceTexture = manager.Load <Texture2D>(textureName, metadata.AssetDensity);
            var face        = new SpriteFontFace(manager.Ultraviolet,
                                                 faceTexture, characterRegions, faceGlyphs, kerning, ascender, descender, description.Glyphs?.Substitution ?? '?');

            return(face);
        }
        /// <summary>
        /// Exports a font face to the specified preprocessed asset stream.
        /// </summary>
        private static void ExportPreprocessedFace(ContentManager manager,
                                                   IContentProcessorMetadata metadata, BinaryWriter writer, SpriteFontFaceDescription description, String style, Boolean delete)
        {
            if (description == null)
            {
                writer.Write(false);
                return;
            }
            writer.Write(true);

            var textureName = ResolveDependencyAssetPath(metadata, description.Texture);

            writer.Write(textureName ?? String.Empty);

            var textureRegion = description.TextureRegion;

            writer.Write(textureRegion.HasValue);
            if (textureRegion.HasValue)
            {
                writer.Write(textureRegion.Value.X);
                writer.Write(textureRegion.Value.Y);
                writer.Write(textureRegion.Value.Width);
                writer.Write(textureRegion.Value.Height);
            }

            if (String.IsNullOrEmpty(textureName))
            {
                throw new ContentLoadException(OpenGLStrings.InvalidSpriteFontTexture);
            }

            var glyphs = default(IEnumerable <Rectangle>);

            using (var surface = manager.Import <PlatformNativeSurface>(textureName, metadata.AssetDensity))
                glyphs = OpenGLSpriteFontHelper.IdentifyGlyphs(surface, textureRegion);

            var substitution = description.Glyphs?.Substitution ?? '?';

            writer.Write(substitution);

            writer.Write(glyphs.Count());
            foreach (var glyph in glyphs)
            {
                writer.Write(glyph.X);
                writer.Write(glyph.Y);
                writer.Write(glyph.Width);
                writer.Write(glyph.Height);
            }

            var kerningDefaultAdjustment = description.Kernings?["default"] ?? 0;
            var kerning = description.Kernings?.Where(x => !String.Equals(x.Key, "default", StringComparison.InvariantCulture))
                          .ToDictionary(x => CreateKerningPair(x.Key), x => x.Value);

            writer.Write(kerningDefaultAdjustment);
            writer.Write(kerning.Count);
            foreach (var kvp in kerning)
            {
                writer.Write(kvp.Key.FirstCharacter);
                writer.Write(kvp.Key.SecondCharacter);
                writer.Write(kvp.Value);
            }

            writer.Write(description.Ascender);
            writer.Write(description.Descender);
        }