Status Badges with Maui.Graphics
Status badges are popular decorators on GitHub readme pages and project websites. Badgen.net and shields.io are popular HTTP APIs for dynamically generating SVG status badges. In this article we will use the new Microsoft.Maui.Graphics
package to generate status badges from a C# console application. This application can be downloaded: BadgeApp.zip
Microsoft.Maui.Graphics
was still in preview. See Drawing with Maui Graphics (blog post) and C# Data Visualization (website) for updated code examples and information about using this library.
Badge.cs
The Badge
class contains all the logic needed to render and save a badge as a PNG file.
This code demonstrates a few advanced topics which are worth considering:
- image scaling
- state management (save/restore)
- clipping
- rounded rectangles
- string measurement
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Graphics.Skia;
public class Badge
{
readonly string Name;
readonly string Value;
readonly SizeF NameSize;
readonly SizeF ValueSize;
// Customize these to change the style of the button
public Color BackgroundLeft = Color.FromArgb("#666");
public Color BackgroundRight = Color.FromArgb("#08C");
public Color BackgroundLiner = Colors.White.WithAlpha(.15f);
public Color FontColor = Colors.White;
public Color FontShadow = Colors.Black.WithAlpha(.5f);
public Color OverlayTop = Colors.Black.WithAlpha(0);
public Color OverlayBottom = Colors.Black.WithAlpha(.25f);
public Badge(string name, string value)
{
Name = name;
Value = value;
NameSize = MeasureString(name);
ValueSize = MeasureString(value);
}
public void SavePng(string pngFilePath, float scale = 1)
{
float totalWidth = NameSize.Width + ValueSize.Width;
int imageWidth = (int)totalWidth + 22;
RectangleF imageRect = new(0, 0, imageWidth, 20);
int scaledWidth = (int)(imageRect.Width * scale);
int scaledHeight = (int)(imageRect.Height * scale);
BitmapExportContext bmp = SkiaGraphicsService.Instance.CreateBitmapExportContext(scaledWidth, scaledHeight);
ICanvas canvas = bmp.Canvas;
canvas.Scale(scale, scale);
// left background
canvas.FillColor = BackgroundLeft;
canvas.FillRoundedRectangle(imageRect, 5);
// right background
float bg2x = 10 + NameSize.Width;
canvas.SaveState();
canvas.ClipRectangle(bg2x, 0, bmp.Width, bmp.Height);
canvas.FillColor = BackgroundRight;
canvas.FillRoundedRectangle(imageRect, 5);
canvas.RestoreState();
// vertical line
canvas.StrokeColor = BackgroundLiner;
canvas.DrawLine(bg2x, 0, bg2x, bmp.Height);
// background overlay shadow
var pt = new LinearGradientPaint() { StartColor = OverlayTop, EndColor = OverlayBottom };
canvas.SetFillPaint(pt, new Point(0, 0), new Point(0, bmp.Height));
canvas.FillRoundedRectangle(imageRect, 5);
// draw text backgrounds
canvas.FontSize = 12;
float offsetY = 14;
float offsetX1 = 5;
float offsetX2 = 15;
float shadowOffset = 1;
// text shadow
canvas.FontColor = FontShadow;
canvas.DrawString(Name, offsetX1 + shadowOffset, offsetY + shadowOffset, HorizontalAlignment.Left);
canvas.DrawString(Value, offsetX2 + NameSize.Width + shadowOffset, offsetY + shadowOffset, HorizontalAlignment.Left);
// text foreground
canvas.FontColor = FontColor;
canvas.DrawString(Name, offsetX1, offsetY, HorizontalAlignment.Left);
canvas.DrawString(Value, offsetX2 + NameSize.Width, offsetY, HorizontalAlignment.Left);
// save the output
bmp.WriteToFile(pngFilePath);
}
SizeF MeasureString(string text, string fontName = "Arial", float fontSize = 12)
{
var fontService = new SkiaFontService("", "");
using SkiaSharp.SKTypeface typeFace = fontService.GetTypeface(fontName);
using SkiaSharp.SKPaint paint = new() { Typeface = typeFace, TextSize = fontSize };
float width = paint.MeasureText(text);
float height = fontSize;
return new SizeF(width, height);
}
}
Program.cs
This simple program is all it takes to render and save a badge.
Badge myBadge = new("Maui", "Graphics");
myBadge.SavePng("demo.png");
Customization
You can reach into the Badge
class and customize styles as desired.
Badge myBadge = new("Maui", "Graphics")
{
BackgroundRight = Microsoft.Maui.Graphics.Color.FromArgb("#3cc51d"),
};
myBadge.SavePng("demo1b.png");
Image Scaling
Microsoft.Maui.Graphics
natively supports image scaling. This allows you to create large badges without any loss in quality that would come from creating a small badge and resizing the bitmap.
Badge myBadge = new("Maui", "Graphics");
myBadge.SavePng("demo1.png", scale: 1);
myBadge.SavePng("demo2.png", scale: 2);
myBadge.SavePng("demo5.png", scale: 5);