diff --git a/Raylib-cs/Raylib.Utils.cs b/Raylib-cs/Raylib.Utils.cs index 96133a3..c937259 100644 --- a/Raylib-cs/Raylib.Utils.cs +++ b/Raylib-cs/Raylib.Utils.cs @@ -9,7 +9,8 @@ namespace Raylib_cs /// Initialize window and OpenGL context public static void InitWindow(int width, int height, string title) { - fixed (byte* b = title.GetUTF8Bytes()) + using var str = new UTF8Buffer(title); + fixed (byte* b = str.buffer) { InitWindow(width, height, b); } @@ -18,7 +19,8 @@ namespace Raylib_cs /// Set title for window (only PLATFORM_DESKTOP) public static void SetWindowTitle(string title) { - fixed (byte* b = title.GetUTF8Bytes()) + using var str = new UTF8Buffer(title); + fixed (byte* b = str.buffer) { SetWindowTitle(b); } @@ -39,9 +41,10 @@ namespace Raylib_cs /// Set clipboard text content public static void SetClipboardText(string text) { - fixed (byte* p = text.GetUTF8Bytes()) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - SetClipboardText(p); + SetClipboardText(b); } } @@ -147,18 +150,20 @@ namespace Raylib_cs /// Create an image from text (default font) public static Image ImageText(string text, int fontSize, Color color) { - fixed (byte* p = text.GetUTF8Bytes()) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - return ImageText(p, fontSize, color); + return ImageText(b, fontSize, color); } } /// Create an image from text (custom sprite font) public static Image ImageTextEx(Font font, string text, float fontSize, float spacing, Color tint) { - fixed (byte* p = text.GetUTF8Bytes()) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - return ImageTextEx(font, p, fontSize, spacing, tint); + return ImageTextEx(font, b, fontSize, spacing, tint); } } @@ -469,25 +474,27 @@ namespace Raylib_cs } /// Draw text (using default font) within an image (destination) - public static void ImageDrawText(ref Image dst, Utf8String text, int x, int y, int fontSize, Color color) + public static void ImageDrawText(ref Image dst, string text, int x, int y, int fontSize, Color color) { fixed (Image* p = &dst) { - fixed (byte* p1 = text) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - ImageDrawText(p, p1, x, y, fontSize, color); + ImageDrawText(p, b, x, y, fontSize, color); } } } /// Draw text (custom sprite font) within an image (destination) - public static void ImageDrawTextEx(ref Image dst, Font font, Utf8String text, Vector2 position, int fontSize, float spacing, Color color) + public static void ImageDrawTextEx(ref Image dst, Font font, string text, Vector2 position, int fontSize, float spacing, Color color) { fixed (Image* p = &dst) { - fixed (byte* p1 = text) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - ImageDrawTextEx(p, font, p1, position, fontSize, spacing, color); + ImageDrawTextEx(p, font, b, position, fontSize, spacing, color); } } } @@ -538,13 +545,14 @@ namespace Raylib_cs } /// Load model animations from file - public static ReadOnlySpan LoadModelAnimations(Utf8String fileName, ref uint animsCount) + public static ReadOnlySpan LoadModelAnimations(string fileName, ref uint animsCount) { - fixed (byte* p1 = fileName) + using var str = new UTF8Buffer(fileName); + fixed (byte* b = str.buffer) { - fixed (uint* p2 = &animsCount) + fixed (uint* p = &animsCount) { - var model = LoadModelAnimations(p1, p2); + var model = LoadModelAnimations(b, p); if ((IntPtr)model == IntPtr.Zero) { @@ -594,78 +602,88 @@ namespace Raylib_cs public static void DrawText(string text, int posX, int posY, int fontSize, Color color) { - fixed (byte* p = text.GetUTF8Bytes()) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - DrawText(p, posX, posY, fontSize, color); + DrawText(b, posX, posY, fontSize, color); } } - public static void DrawTextEx(Font font, Utf8String text, Vector2 position, float fontSize, float spacing, Color tint) + public static void DrawTextEx(Font font, string text, Vector2 position, float fontSize, float spacing, Color tint) { - fixed (byte* p = text) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - DrawTextEx(font, p, position, fontSize, spacing, tint); + DrawTextEx(font, b, position, fontSize, spacing, tint); } } - public static void DrawTextPro(Font font, Utf8String text, Vector2 position, float fontSize, float spacing, Color tint) + public static void DrawTextPro(Font font, string text, Vector2 position, float fontSize, float spacing, Color tint) { - fixed (byte* p = text) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - DrawTextEx(font, p, position, fontSize, spacing, tint); + DrawTextEx(font, b, position, fontSize, spacing, tint); } } - public static int MeasureText(Utf8String text, int fontSize) + public static int MeasureText(string text, int fontSize) { - fixed (byte* p = text) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - return MeasureText(p, fontSize); + return MeasureText(b, fontSize); } } - public static Vector2 MeasureTextEx(Font font, Utf8String text, float fontSize, float spacing) + public static Vector2 MeasureTextEx(Font font, string text, float fontSize, float spacing) { - fixed (byte* p = text) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - return MeasureTextEx(font, p, fontSize, spacing); + return MeasureTextEx(font, b, fontSize, spacing); } } - public static void TextAppend(Utf8String text, Utf8String append, int position) + public static void TextAppend(string text, string append, int position) { - fixed (byte* p1 = text) + using var str = new UTF8Buffer(text); + using var str1 = new UTF8Buffer(append); + fixed (byte* p1 = str.buffer) { - fixed (byte* p2 = append) + fixed (byte* p2 = str1.buffer) { TextAppend(p1, p2, &position); } } } - public static string TextToPascal(Utf8String text) + public static string TextToPascal(string text) { - fixed (byte* p1 = text) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - return Utf8StringUtils.GetUTF8String(TextToPascal(p1)); + return Utf8StringUtils.GetUTF8String(TextToPascal(b)); } } - public static int TextToInteger(Utf8String text) + public static int TextToInteger(string text) { - fixed (byte* p1 = text) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - return TextToInteger(p1); + return TextToInteger(b); } } public static int[] LoadCodepoints(string text, ref int count) { - fixed (byte* p1 = text.GetUTF8Bytes()) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { fixed (int* c = &count) { - var pointsPtr = LoadCodepoints(p1, c); + var pointsPtr = LoadCodepoints(b, c); var codepoints = new ReadOnlySpan(pointsPtr, count).ToArray(); UnloadCodepoints(pointsPtr); return codepoints; @@ -673,11 +691,12 @@ namespace Raylib_cs } } - public static int GetCodepointCount(Utf8String text) + public static int GetCodepointCount(string text) { - fixed (byte* p1 = text) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { - return GetCodepointCount(p1); + return GetCodepointCount(b); } } @@ -685,12 +704,13 @@ namespace Raylib_cs /// single codepoint / "char" public static int GetCodepoint(string text, ref int bytesProcessed) { - fixed (byte* p1 = text.GetUTF8Bytes()) + using var str = new UTF8Buffer(text); + fixed (byte* b = str.buffer) { // this probably wont work fixed (int* p = &bytesProcessed) { - return GetCodepoint(p1, p); + return GetCodepoint(b, p); } } } diff --git a/Raylib-cs/types/native/Utf8String.cs b/Raylib-cs/types/native/Utf8String.cs index 3701813..6ae50f1 100644 --- a/Raylib-cs/types/native/Utf8String.cs +++ b/Raylib-cs/types/native/Utf8String.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Text; using System.Runtime.InteropServices; @@ -27,6 +28,28 @@ namespace Raylib_cs #endregion + /// + /// Converts text to a UTF8 buffer for passing to native code.
+ /// Uses ArrayPool to reduce memory allocation. + ///
+ public ref struct UTF8Buffer + { + public byte[] buffer; + + public UTF8Buffer(string text) + { + int length = (text.Length * 4) + 1; + buffer = ArrayPool.Shared.Rent(length); + int count = Encoding.UTF8.GetBytes(text.AsSpan(), buffer.AsSpan()); + buffer[count] = 0; + } + + public void Dispose() + { + ArrayPool.Shared.Return(buffer); + } + } + /// /// A raw string representation suitable for passing into many core SQLite apis. These will normally be pointers to /// utf8 encoded bytes, with a trailing \0 terminator. strings can be represented as @@ -149,7 +172,7 @@ namespace Raylib_cs /// /// UTF16 String representation - /// Returns "NUL" on Null native type + /// Returns "NUL" on Null native type /// /// public override string ToString()