Пример #1
0
        internal TextureFont(Texture2D texture, FontData fontData)
        {
            _texture = texture;

            LineSpacing = fontData.LineSpacing;

            Spacing = fontData.Spacing;

            Glyphs = new Glyph[fontData.Chars.Length];

            var kernings  = fontData.GlyphKernings;
            var texRects  = fontData.GlyphRects;
            var croppings = fontData.GlyphCroppings;
            var chars     = fontData.Chars;

            var regions = new Stack <CharRegion>();

            for (int i = 0; i < chars.Length; ++i)
            {
                Glyphs[i] = new Glyph()
                {
                    TextureRect      = texRects[i],
                    Cropping         = croppings[i],
                    Character        = chars[i],
                    LeftSideBearing  = kernings[i].X,
                    Width            = kernings[i].Y,
                    RightSideBearing = kernings[i].Z,
                    WidthKerning     = kernings[i].X + kernings[i].Y + kernings[i].Z
                };

                if (regions.Count == 0 || chars[i] > (regions.Peek().End + 1))
                {
                    // New Region

                    regions.Push(new CharRegion(chars[i], i));
                }
                else if (chars[i] == (regions.Peek().End + 1))
                {
                    // Add char in current region

                    var currentRegion = regions.Pop();

                    currentRegion.End++;
                    regions.Push(currentRegion);
                }
                else
                {
                    throw new InvalidOperationException(
                              "Invalid TextureFont. Character map must be in ascending order.");
                }
            }

            _regions = regions.ToArray();

            Array.Reverse(_regions);

            DefaultCharacter = fontData.DefaultChar;
        }
Пример #2
0
        internal Font(Texture2D texture, FontData font_data)
        {
            m_texture = texture;

            m_glyphs_map = new Dictionary <char, int>();

            m_glyphs = new Glyph[font_data.Chars.Length];

            var glyph_idx = 0;

            m_font_size = font_data.Size;

            LineSpacing = font_data.LineHeight;

            Spacing = 0;

            for (int i = 0; i < font_data.Chars.Length; ++i)
            {
                var     ch     = font_data.Chars[i];
                ref var bounds = ref font_data.GlyphRects[i];
                ref var offset = ref font_data.GlyphOffsets[i];
Пример #3
0
        public static FontData Build(FontBuildParams @params)
        {
            var compile_params = new FontCompileParams()
            {
                CharRangeLevel = @params.CharRangeLevel,
                FontFilePath   = ResourceLoader.GetFullResourcePath(@params.Path),
                FontName       = @params.Id,
                FontSize       = @params.Size,
                SpacingH       = 1,
                SpacingV       = 1,
                PaddingUp      = @params.PaddingUp,
                PaddingDown    = @params.PaddingDown,
                PaddingLeft    = @params.PaddingLeft,
                PaddingRight   = @params.PaddingRight
            };

            Console.WriteLine($"Compiling Font: {@params.Id}, Size: {@params.Size}");

            if (@params.DropShadow)
            {
                if (Calc.Abs(@params.ShadowOffsetX) > @params.PaddingLeft + @params.PaddingRight)
                {
                    @params.PaddingLeft  = Calc.Abs(@params.ShadowOffsetX);
                    @params.PaddingRight = Calc.Abs(@params.ShadowOffsetX);
                }

                if (Calc.Abs(@params.ShadowOffsetY) > @params.PaddingUp + @params.PaddingDown)
                {
                    @params.PaddingUp   = Calc.Abs(@params.ShadowOffsetY);
                    @params.PaddingDown = Calc.Abs(@params.ShadowOffsetY);
                }

                compile_params.PaddingUp    = @params.PaddingUp;
                compile_params.PaddingDown  = @params.PaddingDown;
                compile_params.PaddingLeft  = @params.PaddingLeft;
                compile_params.PaddingRight = @params.PaddingRight;
            }

            var compile_result = FontCompiler.Compile(compile_params);

            if (@params.DropShadow)
            {
                Blitter.Begin(compile_result.FontImageData, compile_result.FontImageWidth, compile_result.FontImageHeight);

                Blitter.DropShadow(@params.ShadowOffsetX, @params.ShadowOffsetY, new Color(@params.ShadowColor));

                Blitter.End();
            }

            var font_data = new FontData()
            {
                Id        = @params.Id,
                FontSheet = new ImageData()
                {
                    Id     = @params.Id + "_texture",
                    Data   = compile_result.FontImageData,
                    Width  = compile_result.FontImageWidth,
                    Height = compile_result.FontImageHeight
                },
            };

            FontDescrParser.ParseAndFillData(font_data, compile_result.FontDescrData);

            return(font_data);
        }
Пример #4
0
 private static void LoadCommonBlock(byte[] buffer, FontData font_data)
 {
     font_data.LineHeight = MemWordHelpers.MakeWordLittleEndian(buffer, 0);
 }
Пример #5
0
 private static void LoadInfoBlock(byte[] buffer, FontData font_data)
 {
     font_data.Size = Calc.Abs(MemWordHelpers.MakeWordLittleEndian(buffer, 0));
 }
Пример #6
0
        public static void ParseAndFillData(FontData font_data, byte[] font_descr_content)
        {
            using var stream = new MemoryStream(font_descr_content);

            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            var buffer = new byte[1024];

            stream.Read(buffer, 0, 4);

            if (buffer[0] != 66 || buffer[1] != 77 || buffer[2] != 70)
            {
                throw new InvalidDataException("Source steam does not contain BMFont data.");
            }

            if (buffer[3] != 3)
            {
                throw new InvalidDataException("Only BMFont version 3 format data is supported.");
            }

            // Following the first four bytes is a series of blocks with information. Each block starts with a one byte block type identifier, followed by a 4 byte integer that gives the size of the block, not including the block type identifier and the size value.
            while (stream.Read(buffer, 0, 5) != 0)
            {
                byte block_type;
                int  block_size;

                block_type = buffer[0];

                block_size = MemWordHelpers.MakeDWordLittleEndian(buffer, 1);
                if (block_size > buffer.Length)
                {
                    buffer = new byte[block_size];
                }

                if (stream.Read(buffer, 0, block_size) != block_size)
                {
                    throw new InvalidDataException("Failed to read enough data to fill block.");
                }

                switch (block_type)
                {
                case 1:     // Block type 1: info
                    LoadInfoBlock(buffer, font_data);
                    break;

                case 2:     // Block type 2: common
                    LoadCommonBlock(buffer, font_data);
                    break;

                case 3:     // Block type 3: pages

                    break;

                case 4:     // Block type 4: chars
                    LoadCharsBlock(buffer, block_size, font_data);
                    break;

                case 5:     // Block type 5: kerning pairs
                    //LoadKerningsBlock(buffer, block_size);
                    break;

                default: throw new InvalidDataException("Block type " + block_type + " is not a valid BMFont block");
                }
            }
        }
Пример #7
0
        public static ResourcePak Load(string path)
        {
            var fileBytes = File.ReadAllBytes(path);

            var pakReader = new MessagePackReader(fileBytes);

            // Read Into Nested Object
            pakReader.ReadArrayHeader();

            var pakeName = pakReader.ReadString();

            var pak = new ResourcePak(pakeName);

            int numberImages = pakReader.ReadMapHeader();

            if (numberImages > 0)
            {
                pak.Images = new Dictionary <string, ImageData>();

                for (int i = 0; i < numberImages; ++i)
                {
                    var key = pakReader.ReadString();

                    pakReader.ReadArrayHeader();

                    var imageId = pakReader.ReadString();

                    var imageData   = pakReader.ReadBytes();
                    int imageWidth  = pakReader.ReadInt32();
                    int imageHeight = pakReader.ReadInt32();

                    pak.Images.Add(key, new ImageData()
                    {
                        Id     = imageId,
                        Data   = imageData?.ToArray(),
                        Width  = imageWidth,
                        Height = imageHeight
                    });
                }
            }

            int numberAtlases = pakReader.ReadMapHeader();

            if (numberAtlases > 0)
            {
                pak.Atlases = new Dictionary <string, TextureAtlasData>();

                for (int i = 0; i < numberAtlases; i++)
                {
                    var key = pakReader.ReadString();
                    pakReader.ReadArrayHeader();
                    var atlasId        = pakReader.ReadString();
                    var atlasImageData = pakReader.ReadBytes();
                    int imageWidth     = pakReader.ReadInt32();
                    int imageHeight    = pakReader.ReadInt32();

                    var atlasData = new TextureAtlasData()
                    {
                        Id     = atlasId,
                        Data   = atlasImageData?.ToArray(),
                        Atlas  = new Dictionary <string, SRect>(),
                        Width  = imageWidth,
                        Height = imageHeight,
                    };

                    int rectsCount = pakReader.ReadMapHeader();

                    if (rectsCount > 0)
                    {
                        for (int j = 0; j < rectsCount; ++j)
                        {
                            var rectKey = pakReader.ReadString();

                            pakReader.ReadArrayHeader();
                            var rectX = pakReader.ReadInt32();
                            var rectY = pakReader.ReadInt32();
                            var rectW = pakReader.ReadInt32();
                            var rectH = pakReader.ReadInt32();

                            atlasData.Atlas.Add(rectKey, new SRect(rectX, rectY, rectW, rectH));
                        }
                    }

                    atlasData.RuntimeUpdatable = pakReader.ReadBoolean();


                    pak.Atlases.Add(key, atlasData);
                }
            }

            int shadersCount = pakReader.ReadMapHeader();

            if (shadersCount > 0)
            {
                pak.Shaders = new Dictionary <string, ShaderProgramData>();

                for (int i = 0; i < shadersCount; ++i)
                {
                    var shaderKey = pakReader.ReadString();

                    pakReader.ReadArrayHeader();

                    var      shaderId         = pakReader.ReadString();
                    var      vertexShaderData = pakReader.ReadBytes();
                    var      fragShaderData   = pakReader.ReadBytes();
                    string[] samplers         = null;
                    string[] @params          = null;

                    int samplersCount = pakReader.ReadArrayHeader();

                    if (samplersCount > 0)
                    {
                        samplers = new string[samplersCount];

                        for (int j = 0; j < samplersCount; ++j)
                        {
                            samplers[j] = pakReader.ReadString();
                        }
                    }

                    int paramsCount = pakReader.ReadArrayHeader();

                    if (paramsCount > 0)
                    {
                        @params = new string[paramsCount];

                        for (int k = 0; k < paramsCount; ++k)
                        {
                            @params[k] = pakReader.ReadString();
                        }
                    }

                    pak.Shaders.Add(shaderKey, new ShaderProgramData()
                    {
                        Id             = shaderId,
                        VertexShader   = vertexShaderData?.ToArray(),
                        FragmentShader = fragShaderData?.ToArray(),
                        Samplers       = samplers,
                        Params         = @params
                    });
                }
            }

            int fontsSize = pakReader.ReadMapHeader();

            if (fontsSize > 0)
            {
                pak.Fonts = new Dictionary <string, FontData>();

                for (int i = 0; i < fontsSize; ++i)
                {
                    var fontKey = pakReader.ReadString();

                    pakReader.ReadArrayHeader();

                    var fontId = pakReader.ReadString();

                    var fontData = new FontData()
                    {
                        Id = fontId
                    };

                    pakReader.ReadArrayHeader();

                    var fontImageDataId = pakReader.ReadString();
                    var fontImageData   = pakReader.ReadBytes();
                    int fontImageWidth  = pakReader.ReadInt32();
                    int fontImageHeight = pakReader.ReadInt32();

                    fontData.FontSheet = new ImageData()
                    {
                        Id     = fontImageDataId,
                        Width  = fontImageWidth,
                        Height = fontImageHeight,
                        Data   = fontImageData?.ToArray()
                    };

                    int charCount = pakReader.ReadArrayHeader();

                    if (charCount > 0)
                    {
                        fontData.Chars = new char[charCount];

                        for (int j = 0; j < charCount; ++j)
                        {
                            fontData.Chars[j] = pakReader.ReadChar();
                        }
                    }

                    int glyphRectCount = pakReader.ReadArrayHeader();

                    if (glyphRectCount > 0)
                    {
                        fontData.GlyphRects = new SRect[glyphRectCount];

                        for (int k = 0; k < glyphRectCount; ++k)
                        {
                            pakReader.ReadArrayHeader();

                            int x = pakReader.ReadInt32();
                            int y = pakReader.ReadInt32();
                            int w = pakReader.ReadInt32();
                            int h = pakReader.ReadInt32();

                            fontData.GlyphRects[k] = new SRect(x, y, w, h);
                        }
                    }

                    int glyphCroppingsCount = pakReader.ReadArrayHeader();

                    if (glyphCroppingsCount > 0)
                    {
                        fontData.GlyphCroppings = new SRect[glyphCroppingsCount];

                        for (int l = 0; l < glyphCroppingsCount; ++l)
                        {
                            pakReader.ReadArrayHeader();

                            int x = pakReader.ReadInt32();
                            int y = pakReader.ReadInt32();
                            int w = pakReader.ReadInt32();
                            int h = pakReader.ReadInt32();

                            fontData.GlyphCroppings[l] = new SRect(x, y, w, h);
                        }
                    }

                    int glyphKerningsCount = pakReader.ReadArrayHeader();

                    if (glyphKerningsCount > 0)
                    {
                        fontData.GlyphKernings = new SVec3[glyphKerningsCount];

                        for (int k = 0; k < glyphKerningsCount; ++k)
                        {
                            pakReader.ReadArrayHeader();

                            float x = (float)pakReader.ReadDouble();
                            float y = (float)pakReader.ReadDouble();
                            float z = (float)pakReader.ReadDouble();

                            fontData.GlyphKernings[k] = new SVec3(x, y, z);
                        }
                    }

                    fontData.LineSpacing = pakReader.ReadInt32();
                    fontData.Spacing     = pakReader.ReadInt32();
                    fontData.DefaultChar = pakReader.ReadChar();

                    pak.Fonts.Add(fontKey, fontData);
                }
            }

            int textCount = pakReader.ReadMapHeader();

            if (textCount > 0)
            {
                pak.TextFiles = new Dictionary <string, TextFileData>();

                var textKey = pakReader.ReadString();

                pakReader.ReadArrayHeader();

                var textId = pakReader.ReadString();

                int textRowCount = pakReader.ReadArrayHeader();

                var textData = new TextFileData()
                {
                    Id       = textId,
                    TextData = new byte[textRowCount][]
                };

                for (int i = 0; i < textRowCount; ++i)
                {
                    textData.TextData[i] = pakReader.ReadBytes().Value.ToArray();
                }

                pak.TextFiles.Add(textKey, textData);
            }

            pak.TotalResourcesCount = pakReader.ReadInt32();

            return(pak);
        }