diff --git a/TS3AudioBot/Helper/ImageUtil.cs b/TS3AudioBot/Helper/ImageUtil.cs
new file mode 100644
index 00000000..aed8040e
--- /dev/null
+++ b/TS3AudioBot/Helper/ImageUtil.cs
@@ -0,0 +1,120 @@
+// TS3AudioBot - An advanced Musicbot for Teamspeak 3
+// Copyright (C) 2016 TS3AudioBot contributors
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace TS3AudioBot.Helper
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Drawing;
+ using System.Drawing.Drawing2D;
+ using System.Drawing.Text;
+
+ static class ImageUtil
+ {
+ private static StringFormat avatarTextFormat = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Near };
+ private static Pen avatarTextOutline = new Pen(Color.Black, 4) { LineJoin = LineJoin.Round };
+
+ public static void BuildStringImage(string str, Image img, RectangleF rect)
+ {
+ using (var graphics = Graphics.FromImage(img))
+ {
+ if (Util.IsLinux)
+ {
+ BuildStringImageLinux(str, graphics, rect);
+ }
+ else
+ {
+ using (var gp = new GraphicsPath())
+ {
+ gp.AddString(str, FontFamily.GenericSansSerif, 0, 15, rect, avatarTextFormat);
+
+ graphics.InterpolationMode = InterpolationMode.High;
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+
+ graphics.DrawPath(avatarTextOutline, gp);
+ graphics.FillPath(Brushes.White, gp);
+ }
+ }
+ }
+ }
+
+ private static void BuildStringImageLinux(string str, Graphics target, RectangleF rect)
+ {
+ const int maxMonoBugWidth = 150;
+
+ using (var gp = new GraphicsPath())
+ using (var builder = new Bitmap(maxMonoBugWidth, 100))
+ using (var bg = Graphics.FromImage(builder))
+ {
+ gp.AddString("X", FontFamily.GenericMonospace, 0, 15, rect, avatarTextFormat);
+ var bounds = gp.GetBounds();
+ var charW = bounds.Width;
+ var charH = bounds.Height * 2;
+ if (charW < 0.1e-6)
+ return;
+
+ var buildRect = new RectangleF(0, 0, maxMonoBugWidth, charH);
+
+ var sep = new List();
+
+ bg.InterpolationMode = InterpolationMode.High;
+ bg.SmoothingMode = SmoothingMode.HighQuality;
+ bg.TextRenderingHint = TextRenderingHint.AntiAlias;
+ bg.CompositingQuality = CompositingQuality.HighQuality;
+ target.CompositingQuality = CompositingQuality.HighQuality;
+
+ int lastBreak = 0;
+ int lastBreakOption = 0;
+ for (int i = 0; i < str.Length; i++)
+ {
+ if (!char.IsLetterOrDigit(str[i]))
+ {
+ lastBreakOption = i;
+ }
+
+ if ((i - lastBreak) * charW >= rect.Width && lastBreak != lastBreakOption)
+ {
+ sep.Add(str.Substring(lastBreak, lastBreakOption - lastBreak));
+ lastBreak = lastBreakOption;
+ }
+ }
+ sep.Add(str.Substring(lastBreak));
+
+ var step = (int)(maxMonoBugWidth / charW) - 1;
+ for (int i = 0; i < sep.Count; i++)
+ {
+ var line = sep[i];
+ float flLeft = 0;
+ for (int j = 0; j * step < line.Length; j++)
+ {
+ var part = line.Substring(j * step, Math.Min(step, line.Length - j * step));
+ gp.Reset();
+ gp.AddString(part, FontFamily.GenericMonospace, 0, 15, buildRect, avatarTextFormat);
+
+ bg.Clear(Color.Transparent);
+ bg.DrawPath(avatarTextOutline, gp);
+ bg.FillPath(Brushes.White, gp);
+
+ target.DrawImageUnscaled(builder, (int)(rect.X + j * (maxMonoBugWidth - 5)), (int)(rect.Y + i * charH));
+ flLeft += gp.GetBounds().Width;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/TS3AudioBot/MainBot.cs b/TS3AudioBot/MainBot.cs
index 76599313..f1644b8a 100644
--- a/TS3AudioBot/MainBot.cs
+++ b/TS3AudioBot/MainBot.cs
@@ -80,8 +80,6 @@ internal static void Main(string[] args)
public RightsManager RightsManager { get; private set; }
public bool QuizMode { get; set; }
- private StringFormat avatarTextFormat = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Near };
- private Pen avatarTextOutline = new Pen(Color.Black, 4) { LineJoin = System.Drawing.Drawing2D.LineJoin.Round };
public MainBot()
{
@@ -1606,21 +1604,10 @@ private void GenerateStatusImage(object sender, EventArgs e)
using (var bmp = thumresult.Value)
{
- using (var graphics = Graphics.FromImage(bmp))
- using (var gp = new System.Drawing.Drawing2D.GraphicsPath())
- {
- gp.AddString("Now playing: " + startEvent.ResourceData.ResourceTitle,
- FontFamily.GenericSansSerif, 0, 15,
- new RectangleF(0, 0, bmp.Width, bmp.Height), avatarTextFormat);
-
- graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
- graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
- graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
- graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
-
- graphics.DrawPath(avatarTextOutline, gp);
- graphics.FillPath(Brushes.White, gp);
- }
+ ImageUtil.BuildStringImage(
+ "Now playing: " + startEvent.ResourceData.ResourceTitle,
+ bmp,
+ new RectangleF(0, 0, bmp.Width, bmp.Height));
using (var mem = new MemoryStream())
{
bmp.Save(mem, System.Drawing.Imaging.ImageFormat.Png);
@@ -1657,9 +1644,7 @@ public void Dispose()
if (!isDisposed) isDisposed = true;
else return;
Log.Write(Log.Level.Info, "Exiting...");
-
- avatarTextOutline.Dispose();
-
+
WebManager?.Dispose(); // before: logStream,
WebManager = null;
diff --git a/TS3AudioBot/TS3AudioBot.csproj b/TS3AudioBot/TS3AudioBot.csproj
index 33f2ff60..d4209584 100644
--- a/TS3AudioBot/TS3AudioBot.csproj
+++ b/TS3AudioBot/TS3AudioBot.csproj
@@ -98,6 +98,7 @@
+