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 @@ +