Skip to content

Instantly share code, notes, and snippets.

@stromkos
Last active November 27, 2018 19:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stromkos/afaf6bebe0d3bd03737177aa0974be7f to your computer and use it in GitHub Desktop.
Save stromkos/afaf6bebe0d3bd03737177aa0974be7f to your computer and use it in GitHub Desktop.
Monogame runtime Android renderer
/*
License
MS-PL
Usage:
Add using AndroidTextDraw;
in your Draw method:
spriteBatch.DrawText(24, "Hello World 👋", new Vector2(10, 10), Color.White, Color.CornflowerBlue);
in the UnloadContent method:
spriteBatch.ClearCache(); or AndroidDrawExtension.ClearCache();
Notes:
Uses the default system font. Can be changed in line 72.
Emojis are rendered in color(Always pass Color.White as first color argument)
This uses a Dictionary to cache the textures, to speed up reuse.
If you pass a backgroud color with transparency, your text will not be anti-aliased
Changing the Position parameter type to Rectangle will scale the Text to fit( with possible aspect ratio stretching)
-----
If you wish to manage the Textures yourself, use GetDrawText
This can be called from anywhere spriteBatch exists( in and after LoadContent).
Be sure to dispose of the created textures to prevent memory leaks.
---
*/
using Android.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
namespace AndroidTextDraw
{
public static class AndroidDrawExtension
{
private static Dictionary<uint, Texture2D> TextureCache = new Dictionary<uint, Texture2D>();
// MS-PL from Monogame
private static void ConvertToABGR(int pixelHeight, int pixelWidth, int[] pixels)
{
int pixelCount = pixelWidth * pixelHeight;
for (int i = 0; i < pixelCount; ++i)
{
uint pixel = (uint)pixels[i];
pixels[i] = (int)((pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16));
}
}
public static void ClearCache(this SpriteBatch sb)
{
foreach (var item in TextureCache)
{
item.Value.Dispose();
}
TextureCache.Clear();
}
public static void ClearCache()
{
foreach (var item in TextureCache)
{
item.Value.Dispose();
}
TextureCache.Clear();
}
public static void DrawText(this SpriteBatch sb, int fontSize, string Text, Vector2 Position, Microsoft.Xna.Framework.Color color, Microsoft.Xna.Framework.Color bcolor)
{
uint hash = (uint)(Text.GetHashCode() ^ bcolor.GetHashCode());
if(TextureCache.ContainsKey(hash))
{
sb.Draw(TextureCache[hash], Position, color);
return;
}
Paint paint = new Paint();
paint.SetTypeface(Typeface.Default);
paint.TextSize = fontSize;
Paint.FontMetrics fm = paint.GetFontMetrics();
paint.Color = new Android.Graphics.Color(255, 255, 255, 255);
int height = (int)System.Math.Ceiling(fm.Descent - fm.Ascent);
int width = (int)System.Math.Ceiling(paint.MeasureText(Text));
Bitmap bmp = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bmp);
canvas.DrawColor(new Android.Graphics.Color(bcolor.R, bcolor.G, bcolor.B, bcolor.A));
canvas.DrawText(Text.ToCharArray(), 0, Text.Length, 0, -fm.Ascent, paint);
Texture2D t = new Texture2D(sb.GraphicsDevice, width, height, false, SurfaceFormat.Color);
int[] pix = new int[bmp.ByteCount / 4];
bmp.GetPixels(pix, 0, bmp.Width, 0, 0, bmp.Width, bmp.Height);
ConvertToABGR(height, width, pix);
t.SetData<int>(pix);
bmp.Recycle();
sb.Draw(t, Position, color);
TextureCache.Add(hash, t);
}
public static Texture2D GetDrawText(this SpriteBatch sb, int fontSize, string Text, Microsoft.Xna.Framework.Color color, Microsoft.Xna.Framework.Color bcolor)
{
Paint paint = new Paint();
paint.SetTypeface(Typeface.Default);
paint.TextSize = fontSize;
Paint.FontMetrics fm = paint.GetFontMetrics();
paint.Color = new Android.Graphics.Color(255, 255, 255, 255);
int height = (int)System.Math.Ceiling(fm.Descent - fm.Ascent);
int width = (int)System.Math.Ceiling(paint.MeasureText(Text));
Bitmap bmp = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bmp);
canvas.DrawColor(new Android.Graphics.Color(bcolor.R, bcolor.G, bcolor.B, bcolor.A));
canvas.DrawText(Text.ToCharArray(), 0, Text.Length, 0, -fm.Ascent, paint);
Texture2D t = new Texture2D(sb.GraphicsDevice, width, height, false, SurfaceFormat.Color);
int[] pix = new int[bmp.ByteCount / 4];
bmp.GetPixels(pix, 0, bmp.Width, 0, 0, bmp.Width, bmp.Height);
ConvertToABGR(height, width, pix);
t.SetData<int>(pix);
bmp.Recycle();
return t;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment