From 4e750a7e1aece26c96a4f7b68d52bfc67b9f98eb Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 15 Mar 2024 16:20:01 -0400 Subject: [PATCH] bmfont support --- BeefLibs/Beefy2D/src/gfx/Font.bf | 99 +++++++++++++++++++++++++++++-- BeefLibs/Beefy2D/src/gfx/Image.bf | 2 +- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/BeefLibs/Beefy2D/src/gfx/Font.bf b/BeefLibs/Beefy2D/src/gfx/Font.bf index 2e3f49a8..1e66d435 100644 --- a/BeefLibs/Beefy2D/src/gfx/Font.bf +++ b/BeefLibs/Beefy2D/src/gfx/Font.bf @@ -109,6 +109,11 @@ namespace Beefy.gfx public float mBottom; } + public class BitmapPage + { + public Image mImage ~ delete _; + } + enum MarkPosition { AboveC, // Center @@ -124,12 +129,14 @@ namespace Beefy.gfx const int32 LOW_CHAR_COUNT = 128; Dictionary mCharData; + List mBitmapPages ~ DeleteContainerAndItems!(_); CharData[] mLowCharData; FTFont* mFTFont; String mPath; List mAlternates; MarkRefData mMarkRefData ~ delete _; float[] mLoKerningTable; + //BitmapFont mBMFont ~ delete _; public StringView mEllipsis = "..."; public this() @@ -430,6 +437,93 @@ namespace Beefy.gfx String fontPath = scope String(mPath); if (pointSize == -1) { + if (fontName.EndsWith(".fnt")) + { + mBitmapPages = new .(); + + var contents = File.ReadAllText(fontName, .. scope .()); + contents.Replace("\r", ""); + for (var line in contents.Split('\n', .RemoveEmptyEntries)) + { + bool CheckVal(StringView text, StringView key, ref int32 val) + { + if (!text.StartsWith(key)) + return false; + if (text[key.Length] != '=') + return false; + val = int32.Parse(text.Substring(key.Length + 1)); + return true; + } + + bool CheckVal(StringView text, String key, String val) + { + if (!text.StartsWith(key)) + return false; + if (text[key.Length] != '=') + return false; + StringView sv = text.Substring(key.Length + 1); + if (sv.StartsWith('"')) + sv.RemoveFromStart(1); + if (sv.EndsWith('"')) + sv.RemoveFromEnd(1); + val.Append(sv); + return true; + } + + if (line.StartsWith("page")) + { + String imageFileName = scope .(); + + for (var text in line.Split(' ', .RemoveEmptyEntries)) + CheckVal(text, "file", imageFileName); + + var dir = Path.GetDirectoryPath(fontName, .. scope .()); + var imagePath = scope $"{dir}/{imageFileName}"; + + BitmapPage page = new .(); + + page.mImage = Image.LoadFromFile(imagePath); + mBitmapPages.Add(page); + } + + if (line.StartsWith("char ")) + { + CharData charData = null; + + for (var text in line.Split(' ', .RemoveEmptyEntries)) + { + int32 id = 0; + if (CheckVal(text, "id", ref id)) + { + charData = new .(); + if (id < LOW_CHAR_COUNT) + mLowCharData[id] = charData; + else + mCharData[(.)id] = charData; + } + + if (charData != null) + { + CheckVal(text, "x", ref charData.mX); + CheckVal(text, "y", ref charData.mY); + CheckVal(text, "width", ref charData.mWidth); + CheckVal(text, "height", ref charData.mHeight); + CheckVal(text, "xoffset", ref charData.mXOffset); + CheckVal(text, "yoffset", ref charData.mYOffset); + CheckVal(text, "xadvance", ref charData.mXAdvance); + + int32 pageIdx = -1; + CheckVal(text, "page", ref pageIdx); + + if (pageIdx != -1) + charData.mImageSegment = mBitmapPages[pageIdx].mImage.CreateImageSegment(charData.mX, charData.mY, charData.mWidth, charData.mHeight); + } + } + } + } + return true; + } + fontPath.Set(BFApp.sApp.mInstallDir); fontPath.Append("fonts/SourceCodePro-Regular.ttf"); usePointSize = 9; @@ -734,9 +828,6 @@ namespace Beefy.gfx public void Draw(Graphics g, StringView theString, FontMetrics* fontMetrics = null) { - if (mFTFont == null) - return; - float curX = 0; float curY = 0; @@ -748,8 +839,6 @@ namespace Beefy.gfx g.PushTextRenderState(); -#unwarn - float markScale = mFTFont.mHeight / 8.0f; float markTopOfs = 0; float markBotOfs = 0; diff --git a/BeefLibs/Beefy2D/src/gfx/Image.bf b/BeefLibs/Beefy2D/src/gfx/Image.bf index 8d15f1ef..5f737827 100644 --- a/BeefLibs/Beefy2D/src/gfx/Image.bf +++ b/BeefLibs/Beefy2D/src/gfx/Image.bf @@ -13,7 +13,7 @@ namespace Beefy.gfx #if !STUDIO_CLIENT public class Image : IDrawable { - enum LoadFlags + public enum LoadFlags { None = 0, Additive = 1,