using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Drawing.Text; using System.Runtime.InteropServices; using System.Runtime.Versioning; using MeetingAssistant.Recording; namespace MeetingAssistant.Taskbar; [SupportedOSPlatform("windows")] internal static class TaskbarIconRenderer { private const int IconSize = 16; private const float GlyphPixelGridOffsetX = -0.5f; public static Icon CreateIcon(RecordingProcessState state) { using var bitmap = RenderBitmap(state); var handle = bitmap.GetHicon(); try { return (Icon)Icon.FromHandle(handle).Clone(); } finally { DestroyIcon(handle); } } internal static Bitmap RenderBitmap(RecordingProcessState state) { var (color, text) = state switch { RecordingProcessState.Recording => (Color.FromArgb(220, 38, 38), "R"), RecordingProcessState.Summarizing => (Color.FromArgb(37, 99, 235), "S"), _ => (Color.FromArgb(75, 85, 99), "I") }; var bitmap = new Bitmap(IconSize, IconSize, PixelFormat.Format32bppArgb); using var graphics = Graphics.FromImage(bitmap); graphics.Clear(Color.Transparent); graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; using var brush = new SolidBrush(color); graphics.FillEllipse(brush, 1, 1, 14, 14); DrawCenteredGlyph(graphics, text); return bitmap; } private static void DrawCenteredGlyph(Graphics graphics, string text) { using var path = new GraphicsPath(); using var format = StringFormat.GenericTypographic; path.AddString( text, FontFamily.GenericSansSerif, (int)FontStyle.Bold, 9, Point.Empty, format); var bounds = path.GetBounds(); using var transform = new Matrix(); transform.Translate( (IconSize - bounds.Width) / 2 - bounds.Left + GlyphPixelGridOffsetX, (IconSize - bounds.Height) / 2 - bounds.Top); path.Transform(transform); using var textBrush = new SolidBrush(Color.White); graphics.FillPath(textBrush, path); } [DllImport("user32.dll", SetLastError = true)] private static extern bool DestroyIcon(IntPtr hIcon); }