Add first working implementation of the cover generator
TODO: Speedup
This commit is contained in:
1 parent
388bd6310f
commit
3f4f2776be
6 files changed
+412
-10
No files matched your search
@@ -5,4 +5,42 @@
|
|||||||
<Folder>Blue</Folder>
|
<Folder>Blue</Folder>
|
||||||
<Author>flokuep</Author>
|
<Author>flokuep</Author>
|
||||||
</Info>
|
</Info>
|
||||||
|
<MissingCover>
|
||||||
|
<Default>
|
||||||
|
<Text>
|
||||||
|
<!--<Text>: Nothing or translation tag-->
|
||||||
|
<Text>%TEXT%</Text>
|
||||||
|
<!--<Font>: Text font name-->
|
||||||
|
<Font>Outline</Font>
|
||||||
|
<!--<Style>: Text style: Normal, Italic, Bold, BoldItalic-->
|
||||||
|
<Style>Bold</Style>
|
||||||
|
<Size>500</Size>
|
||||||
|
<!--<Color>: Text color from ColorScheme (high priority)-->
|
||||||
|
<!--or <R>, <G>, <B>, <A> (lower priority)-->
|
||||||
|
<R>0</R><G>1</G><B>1</B><A>0.5</A>
|
||||||
|
<Margin>24</Margin>
|
||||||
|
<Indent>100</Indent>
|
||||||
|
</Text>
|
||||||
|
<Image>EmptyCover.png</Image>
|
||||||
|
<ShowFirstCover>true</ShowFirstCover>
|
||||||
|
<ImageAlpha>0.8</ImageAlpha>
|
||||||
|
</Default>
|
||||||
|
<Folder>
|
||||||
|
<Text>
|
||||||
|
<!--<Text>: Nothing or translation tag-->
|
||||||
|
<Text>%TEXT%</Text>
|
||||||
|
<!--<Font>: Text font name-->
|
||||||
|
<Font>Outline</Font>
|
||||||
|
<!--<Style>: Text style: Normal, Italic, Bold, BoldItalic-->
|
||||||
|
<Style>Bold</Style>
|
||||||
|
<Size>500</Size>
|
||||||
|
<!--<Color>: Text color from ColorScheme (high priority)-->
|
||||||
|
<!--or <R>, <G>, <B>, <A> (lower priority)-->
|
||||||
|
<R>0</R><G>1</G><B>0</B><A>0.5</A>
|
||||||
|
<Margin>24</Margin>
|
||||||
|
<Indent>100</Indent>
|
||||||
|
</Text>
|
||||||
|
<Image>EmptyCover.png</Image>
|
||||||
|
</Folder>
|
||||||
|
</MissingCover>
|
||||||
</root>
|
</root>
|
||||||
+84
-3
@@ -20,6 +20,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using VocaluxeLib;
|
using VocaluxeLib;
|
||||||
using VocaluxeLib.Draw;
|
using VocaluxeLib.Draw;
|
||||||
|
using VocaluxeLib.Songs;
|
||||||
|
|
||||||
namespace Vocaluxe.Base
|
namespace Vocaluxe.Base
|
||||||
{
|
{
|
||||||
@@ -32,7 +33,11 @@ namespace Vocaluxe.Base
|
|||||||
|
|
||||||
static class CCover
|
static class CCover
|
||||||
{
|
{
|
||||||
|
private const string _NoCoverName = "No Cover";
|
||||||
|
private const string _NoCoverNameAlt = "NoCover";
|
||||||
|
private const string _DefaultTypeName = "Default";
|
||||||
private static readonly Dictionary<string, CTexture> _Covers = new Dictionary<string, CTexture>();
|
private static readonly Dictionary<string, CTexture> _Covers = new Dictionary<string, CTexture>();
|
||||||
|
private static readonly Dictionary<string, CNoCoverGenerator> _NoCoverThemes = new Dictionary<string, CNoCoverGenerator>();
|
||||||
private static readonly List<SCoverTheme> _CoverThemes = new List<SCoverTheme>();
|
private static readonly List<SCoverTheme> _CoverThemes = new List<SCoverTheme>();
|
||||||
|
|
||||||
public static CTexture NoCover { get; private set; }
|
public static CTexture NoCover { get; private set; }
|
||||||
@@ -92,6 +97,24 @@ namespace Vocaluxe.Base
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CTexture GenerateCover(string text, ESongSorting sorting, CCategory category)
|
||||||
|
{
|
||||||
|
CSong firstSong = category.GetSong(0);
|
||||||
|
CTexture cover = _NoCoverThemes[_SongSortingToType(sorting)].GetCover(text, firstSong != null ? Path.Combine(firstSong.Folder, firstSong.CoverFileName) : null);
|
||||||
|
if (cover == null)
|
||||||
|
cover = _NoCoverThemes[_DefaultTypeName].GetCover(text, firstSong != null ? Path.Combine(firstSong.Folder, firstSong.CoverFileName) : null);
|
||||||
|
if (cover == null)
|
||||||
|
cover = NoCover;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lock (_Covers)
|
||||||
|
{
|
||||||
|
_Covers.Add(text, cover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cover;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true if a cover with the given name exists.
|
/// Returns true if a cover with the given name exists.
|
||||||
/// MUST HOLD _Covers lock at this point
|
/// MUST HOLD _Covers lock at this point
|
||||||
@@ -121,6 +144,10 @@ namespace Vocaluxe.Base
|
|||||||
}
|
}
|
||||||
_Covers.Clear();
|
_Covers.Clear();
|
||||||
}
|
}
|
||||||
|
lock (_NoCoverThemes)
|
||||||
|
{
|
||||||
|
_NoCoverThemes.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -168,7 +195,7 @@ namespace Vocaluxe.Base
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads all cover which are defined in the cover config file.
|
/// Loads all covers from the theme
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void _LoadCovers(string coverThemeName)
|
private static void _LoadCovers(string coverThemeName)
|
||||||
{
|
{
|
||||||
@@ -184,8 +211,62 @@ namespace Vocaluxe.Base
|
|||||||
{
|
{
|
||||||
foreach (string file in files)
|
foreach (string file in files)
|
||||||
_AddCover(Path.GetFileNameWithoutExtension(file), file);
|
_AddCover(Path.GetFileNameWithoutExtension(file), file);
|
||||||
if (_CoverExists("No Cover"))
|
if (_CoverExists(_NoCoverName))
|
||||||
NoCover = _Covers["No Cover"];
|
NoCover = _Covers[_NoCoverName];
|
||||||
|
else if (_CoverExists(_NoCoverNameAlt))
|
||||||
|
NoCover = _Covers[_NoCoverNameAlt];
|
||||||
|
else
|
||||||
|
CBase.Log.LogError("Covertheme \"" + coverThemeName + "\" does not include a cover file named \"" + _NoCoverName + "\" and cannot be used!", true, true);
|
||||||
|
}
|
||||||
|
_LoadNoCoverThemes(coverTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string _SongSortingToType(ESongSorting sorting)
|
||||||
|
{
|
||||||
|
switch (sorting)
|
||||||
|
{
|
||||||
|
case ESongSorting.TR_CONFIG_NONE:
|
||||||
|
return _DefaultTypeName;
|
||||||
|
case ESongSorting.TR_CONFIG_FOLDER:
|
||||||
|
return "Folder";
|
||||||
|
case ESongSorting.TR_CONFIG_ARTIST:
|
||||||
|
return "Artist";
|
||||||
|
case ESongSorting.TR_CONFIG_ARTIST_LETTER:
|
||||||
|
case ESongSorting.TR_CONFIG_TITLE_LETTER:
|
||||||
|
return "Letter";
|
||||||
|
case ESongSorting.TR_CONFIG_EDITION:
|
||||||
|
return "Edition";
|
||||||
|
case ESongSorting.TR_CONFIG_GENRE:
|
||||||
|
return "Genre";
|
||||||
|
case ESongSorting.TR_CONFIG_LANGUAGE:
|
||||||
|
return "Language";
|
||||||
|
case ESongSorting.TR_CONFIG_YEAR:
|
||||||
|
return "Year";
|
||||||
|
case ESongSorting.TR_CONFIG_DECADE:
|
||||||
|
return "Decade";
|
||||||
|
case ESongSorting.TR_CONFIG_DATEADDED:
|
||||||
|
return "Date";
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException("sorting");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void _LoadNoCoverThemes(SCoverTheme coverTheme)
|
||||||
|
{
|
||||||
|
CXMLReader xmlReader = CXMLReader.OpenFile(Path.Combine(CSettings.ProgramFolder, CSettings.FolderNameCover, coverTheme.File));
|
||||||
|
List<String> types = new List<string>();
|
||||||
|
foreach (ESongSorting sorting in Enum.GetValues(typeof(ESongSorting)))
|
||||||
|
types.Add(_SongSortingToType(sorting));
|
||||||
|
string coverPath = Path.Combine(CSettings.ProgramFolder, CSettings.FolderNameCover, coverTheme.Folder);
|
||||||
|
lock (_NoCoverThemes)
|
||||||
|
{
|
||||||
|
foreach (string type in types)
|
||||||
|
{
|
||||||
|
if (_NoCoverThemes.ContainsKey(type))
|
||||||
|
continue;
|
||||||
|
CNoCoverGenerator el = new CNoCoverGenerator(xmlReader, "//root/MissingCover/" + type, coverPath);
|
||||||
|
_NoCoverThemes.Add(type, el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,278 @@
|
|||||||
|
#region license
|
||||||
|
// This file is part of Vocaluxe.
|
||||||
|
//
|
||||||
|
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Vocaluxe 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.Drawing.Text;
|
||||||
|
using System.IO;
|
||||||
|
using Vocaluxe.Base.Fonts;
|
||||||
|
using VocaluxeLib;
|
||||||
|
using VocaluxeLib.Draw;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Vocaluxe.Base
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class that generates Covers if the right Cover is missing
|
||||||
|
/// Themeable via the xml of the Cover theme
|
||||||
|
/// </summary>
|
||||||
|
class CNoCoverGenerator
|
||||||
|
{
|
||||||
|
private readonly bool _Valid;
|
||||||
|
private readonly string _Text;
|
||||||
|
private readonly SColorF _TextColor;
|
||||||
|
private readonly string _TextColorName;
|
||||||
|
private readonly float _TextMargin;
|
||||||
|
private readonly float _TextIndent;
|
||||||
|
private readonly int _TextSize;
|
||||||
|
private readonly string _Font;
|
||||||
|
private readonly EStyle _Style;
|
||||||
|
private readonly string _Image;
|
||||||
|
private readonly bool _ShowFirstCover;
|
||||||
|
private readonly float _ImageAlpha;
|
||||||
|
private const float _LineSpace = 5;
|
||||||
|
|
||||||
|
public CNoCoverGenerator(CXMLReader xmlReader, string xPath, string basePath)
|
||||||
|
{
|
||||||
|
_Valid = xmlReader.ItemExists(xPath);
|
||||||
|
if (!_Valid)
|
||||||
|
return;
|
||||||
|
_Valid &= xmlReader.GetValue(xPath + "/Text/Text", out _Text);
|
||||||
|
_Valid &= xmlReader.GetValue(xPath + "/Text/Font", out _Font);
|
||||||
|
_Valid &= xmlReader.TryGetEnumValue(xPath + "/Text/Style", ref _Style);
|
||||||
|
_Valid &= xmlReader.TryGetIntValue(xPath + "/Text/Size", ref _TextSize);
|
||||||
|
if (xmlReader.GetValue(xPath + "/Text/Color", out _TextColorName))
|
||||||
|
_Valid &= CBase.Theme.GetColor(_TextColorName, CBase.Theme.GetSkinIndex(-1), out _TextColor);
|
||||||
|
else
|
||||||
|
_Valid &= xmlReader.TryGetColorFromRGBA(xPath + "/Text", ref _TextColor);
|
||||||
|
_Valid &= xmlReader.TryGetFloatValue(xPath + "/Text/Margin", ref _TextMargin);
|
||||||
|
if (!xmlReader.TryGetFloatValue(xPath + "/Text/Indent", ref _TextIndent))
|
||||||
|
_TextIndent = 6 * _TextMargin;
|
||||||
|
_Valid &= xmlReader.GetValue(xPath + "/Image", out _Image);
|
||||||
|
string tmp;
|
||||||
|
if (xmlReader.GetValue(xPath + "/ShowFirstCover", out tmp))
|
||||||
|
Boolean.TryParse(tmp, out _ShowFirstCover);
|
||||||
|
else
|
||||||
|
_ShowFirstCover = false;
|
||||||
|
if (!xmlReader.TryGetFloatValue(xPath + "/ImageAlpha", ref _ImageAlpha))
|
||||||
|
_ImageAlpha = 0.5f;
|
||||||
|
else
|
||||||
|
_ImageAlpha = _ImageAlpha.Clamp(0f, 1f);
|
||||||
|
if (_Valid)
|
||||||
|
{
|
||||||
|
// ReSharper disable AssignNullToNotNullAttribute
|
||||||
|
_Image = Path.Combine(basePath, _Image);
|
||||||
|
// ReSharper restore AssignNullToNotNullAttribute
|
||||||
|
_Valid = File.Exists(_Image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CTexture GetCover(string text, string firstCoverPath)
|
||||||
|
{
|
||||||
|
if (!_Valid)
|
||||||
|
return null;
|
||||||
|
text = CLanguage.Translate(_Text.Replace("%TEXT%", text));
|
||||||
|
using (Bitmap bmp = new Bitmap(_Image))
|
||||||
|
using (Graphics g = Graphics.FromImage(bmp))
|
||||||
|
{
|
||||||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
g.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||||
|
|
||||||
|
if (_ShowFirstCover && !String.IsNullOrEmpty(firstCoverPath) && File.Exists(firstCoverPath))
|
||||||
|
{
|
||||||
|
ColorMatrix cm = new ColorMatrix {Matrix33 = 1f - _ImageAlpha};
|
||||||
|
ImageAttributes ia = new ImageAttributes();
|
||||||
|
ia.SetColorMatrix(cm);
|
||||||
|
using (Bitmap bmp2 = new Bitmap(firstCoverPath))
|
||||||
|
g.DrawImage(bmp2, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, bmp2.Width, bmp2.Height, GraphicsUnit.Pixel, ia);
|
||||||
|
}
|
||||||
|
if (text != "")
|
||||||
|
{
|
||||||
|
List<string> lines = _SplitText(text);
|
||||||
|
CFonts.SetFont(_Font);
|
||||||
|
CFonts.Style = _Style;
|
||||||
|
float allowedWidth = bmp.Width - 2 * _TextMargin;
|
||||||
|
if (lines.Count > 1)
|
||||||
|
allowedWidth -= _TextIndent;
|
||||||
|
float allowedHeight = bmp.Height - 2 * _TextMargin - _LineSpace * (lines.Count - 1);
|
||||||
|
CFonts.Height = allowedHeight / lines.Count;
|
||||||
|
Font fo = CFonts.GetFont();
|
||||||
|
List<SizeF> sizes = lines.Select(line => g.MeasureString(line, fo, -1, StringFormat.GenericTypographic)).ToList();
|
||||||
|
float maxWidth = sizes.Select(s => s.Width).Max();
|
||||||
|
float maxHeight = sizes.Select(s => s.Height).Max();
|
||||||
|
maxHeight = (maxHeight + CFonts.Height) / 2;
|
||||||
|
if (maxWidth > allowedWidth)
|
||||||
|
{
|
||||||
|
CFonts.Height *= allowedWidth / maxWidth;
|
||||||
|
maxHeight *= allowedWidth / maxWidth;
|
||||||
|
}
|
||||||
|
if (maxHeight > _TextSize)
|
||||||
|
{
|
||||||
|
CFonts.Height *= _TextSize / maxHeight;
|
||||||
|
maxHeight = _TextSize;
|
||||||
|
}
|
||||||
|
fo = CFonts.GetFont();
|
||||||
|
|
||||||
|
//Have to use size in em not pixels!
|
||||||
|
float emSize = fo.Size * fo.FontFamily.GetCellAscent(fo.Style) / fo.FontFamily.GetEmHeight(fo.Style);
|
||||||
|
float outlineSize = CFonts.Outline * CFonts.Height;
|
||||||
|
SColorF outlineColorF = CFonts.OutlineColor;
|
||||||
|
outlineColorF.A = outlineColorF.A * _TextColor.A;
|
||||||
|
|
||||||
|
using (var path = new GraphicsPath())
|
||||||
|
using (var pen = new Pen(outlineColorF.AsColor(), outlineSize / 2))
|
||||||
|
{
|
||||||
|
pen.LineJoin = LineJoin.Round;
|
||||||
|
pen.Alignment = PenAlignment.Outset;
|
||||||
|
float top = (allowedHeight - maxHeight * lines.Count) / 2;
|
||||||
|
for (int i = 0; i < lines.Count; i++)
|
||||||
|
{
|
||||||
|
string line = lines[i];
|
||||||
|
float left;
|
||||||
|
if (lines.Count == 1 || (i == 1 && lines.Count == 3))
|
||||||
|
{
|
||||||
|
//Center Text if this is the only line or the middle line
|
||||||
|
float width = g.MeasureString(line, fo, -1, StringFormat.GenericTypographic).Width;
|
||||||
|
left = (bmp.Width - width) / 2;
|
||||||
|
}
|
||||||
|
else if (i == lines.Count - 1)
|
||||||
|
{
|
||||||
|
//Place last line at right
|
||||||
|
float width = g.MeasureString(line, fo, -1, StringFormat.GenericTypographic).Width;
|
||||||
|
left = bmp.Width - width - _TextMargin;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
left = _TextMargin;
|
||||||
|
//g.DrawString(line, fo, new SolidBrush(_TextColor.AsColor()), left, top, StringFormat.GenericTypographic);
|
||||||
|
path.AddString(line, fo.FontFamily, (int)fo.Style, emSize, new PointF(left, top), StringFormat.GenericTypographic);
|
||||||
|
top += maxHeight + _LineSpace;
|
||||||
|
}
|
||||||
|
g.DrawPath(pen, path);
|
||||||
|
// ReSharper disable ImpureMethodCallOnReadonlyValueField
|
||||||
|
g.FillPath(new SolidBrush(_TextColor.AsColor()), path);
|
||||||
|
// ReSharper restore ImpureMethodCallOnReadonlyValueField
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CDraw.AddTexture(bmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> _SplitText(string text)
|
||||||
|
{
|
||||||
|
text = text.Replace(".", ". ").Replace("-", "- ").Replace(" ", " ");
|
||||||
|
string[] parts = text.Split(' ');
|
||||||
|
List<string> lines = new List<string>();
|
||||||
|
string line = "";
|
||||||
|
bool appendingName = false;
|
||||||
|
foreach (string part in parts)
|
||||||
|
{
|
||||||
|
if (part.Length == 1 && !Char.IsLetter(part, 0))
|
||||||
|
{
|
||||||
|
//Add non-letter chars to the end of the line (e.g. in "19 - 20")
|
||||||
|
line = (line != "" ? " " : "") + part;
|
||||||
|
appendingName = false;
|
||||||
|
}
|
||||||
|
else if (part.Length == 1 || (part.Length == 2 && part[1] == '.'))
|
||||||
|
{
|
||||||
|
//We have something like the initials (e.g. "J. R. R. Tolkien") - Keep them together
|
||||||
|
if (!appendingName && line != "")
|
||||||
|
{
|
||||||
|
//When we are not already appending those, add the last line and start a new one
|
||||||
|
lines.Add(line);
|
||||||
|
line = part;
|
||||||
|
}
|
||||||
|
line = (line != "" ? " " : "") + part;
|
||||||
|
appendingName = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (line != "")
|
||||||
|
lines.Add(line);
|
||||||
|
line = part;
|
||||||
|
appendingName = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (line != "")
|
||||||
|
lines.Add(line);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
//If we have more than 3 lines try to distribute them evenly
|
||||||
|
if (lines.Count > 3)
|
||||||
|
{
|
||||||
|
int len = lines.Sum(el => el.Length) + lines.Count - 1;
|
||||||
|
int avgLen = (int)Math.Ceiling(len / 3d);
|
||||||
|
i = 1;
|
||||||
|
while (i < lines.Count)
|
||||||
|
{
|
||||||
|
string prev = lines[i - 1];
|
||||||
|
string cur = lines[i];
|
||||||
|
if (prev.Length + cur.Length <= avgLen)
|
||||||
|
{
|
||||||
|
lines[i - 1] += " " + cur;
|
||||||
|
lines.RemoveAt(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Further reduce the lines by taking the longest line as the max length
|
||||||
|
i = 1;
|
||||||
|
while (i < lines.Count)
|
||||||
|
{
|
||||||
|
string prev = lines[i - 1];
|
||||||
|
string cur = lines[i];
|
||||||
|
if (prev.Length + cur.Length <= lines.Max(el => el.Length))
|
||||||
|
{
|
||||||
|
lines[i - 1] += " " + cur;
|
||||||
|
lines.RemoveAt(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we still have more than 3 lines be more agressive
|
||||||
|
while (lines.Count > 3)
|
||||||
|
{
|
||||||
|
//Join the shortest line with shortest neighbour
|
||||||
|
int minLen = lines.Min(el => el.Length);
|
||||||
|
for (i = 0; i < lines.Count; i++)
|
||||||
|
{
|
||||||
|
if (lines[i].Length != minLen)
|
||||||
|
continue;
|
||||||
|
int other;
|
||||||
|
if (i == 0)
|
||||||
|
other = 1;
|
||||||
|
else if (i == lines.Count - 1)
|
||||||
|
other = i - 1;
|
||||||
|
else if (lines[i - 1].Length < lines[i + 1].Length)
|
||||||
|
other = i - 1;
|
||||||
|
else
|
||||||
|
other = i + 1;
|
||||||
|
lines[i] += " " + lines[other];
|
||||||
|
lines.RemoveAt(other);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -178,7 +178,11 @@ namespace Vocaluxe.Base
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach (CCategory cat in _Categories)
|
foreach (CCategory cat in _Categories)
|
||||||
|
{
|
||||||
cat.CoverTextureSmall = CCover.Cover(cat.Name);
|
cat.CoverTextureSmall = CCover.Cover(cat.Name);
|
||||||
|
if (cat.CoverTextureSmall == CCover.NoCover)
|
||||||
|
cat.CoverTextureSmall = CCover.GenerateCover(cat.Name, CSongs.Sorter.SongSorting, cat);
|
||||||
|
}
|
||||||
_Changed = false;
|
_Changed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -180,13 +180,6 @@ namespace Vocaluxe
|
|||||||
|
|
||||||
Application.DoEvents();
|
Application.DoEvents();
|
||||||
|
|
||||||
// Load Cover
|
|
||||||
CLog.StartBenchmark("Init Cover");
|
|
||||||
CCover.Init();
|
|
||||||
CLog.StopBenchmark("Init Cover");
|
|
||||||
|
|
||||||
Application.DoEvents();
|
|
||||||
|
|
||||||
// Theme System
|
// Theme System
|
||||||
CLog.StartBenchmark("Init Theme");
|
CLog.StartBenchmark("Init Theme");
|
||||||
if (!CTheme.Init())
|
if (!CTheme.Init())
|
||||||
@@ -195,6 +188,13 @@ namespace Vocaluxe
|
|||||||
|
|
||||||
Application.DoEvents();
|
Application.DoEvents();
|
||||||
|
|
||||||
|
// Load Cover
|
||||||
|
CLog.StartBenchmark("Init Cover");
|
||||||
|
CCover.Init();
|
||||||
|
CLog.StopBenchmark("Init Cover");
|
||||||
|
|
||||||
|
Application.DoEvents();
|
||||||
|
|
||||||
// Init Screens
|
// Init Screens
|
||||||
CLog.StartBenchmark("Init Screens");
|
CLog.StartBenchmark("Init Screens");
|
||||||
CGraphics.Init();
|
CGraphics.Init();
|
||||||
|
|||||||
@@ -216,6 +216,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Base\CBackgroundMusic.cs" />
|
<Compile Include="Base\CBackgroundMusic.cs" />
|
||||||
|
<Compile Include="Base\CNoCoverGenerator.cs" />
|
||||||
<Compile Include="Base\CPlaylistElement.cs" />
|
<Compile Include="Base\CPlaylistElement.cs" />
|
||||||
<Compile Include="Base\CRecord.cs" />
|
<Compile Include="Base\CRecord.cs" />
|
||||||
<Compile Include="Base\CVideoPlayer.cs" />
|
<Compile Include="Base\CVideoPlayer.cs" />
|
||||||
|
|||||||
Reference in new issue
Block a user