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; }
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];
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); }
private static void LoadCommonBlock(byte[] buffer, FontData font_data) { font_data.LineHeight = MemWordHelpers.MakeWordLittleEndian(buffer, 0); }
private static void LoadInfoBlock(byte[] buffer, FontData font_data) { font_data.Size = Calc.Abs(MemWordHelpers.MakeWordLittleEndian(buffer, 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"); } } }
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); }