First Step to make CFonts threadsave

This commit is contained in:
Flamefire committed 2014-09-06 14:17:27 +02:00
1 parent 32241a91dc
commit 7f60e6f321
5 files changed
+135 -138

No files matched your search

@@ -19,54 +19,69 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Text; using System.Drawing.Text;
using System.Xml.Serialization;
using VocaluxeLib; using VocaluxeLib;
using VocaluxeLib.Draw; using VocaluxeLib.Draw;
namespace Vocaluxe.Base.Fonts namespace Vocaluxe.Base.Fonts
{ {
class CFont : IDisposable class CFontStyle : IDisposable
{ {
private readonly Dictionary<char, CGlyph> _Glyphs; private readonly string _FilePath;
private readonly EStyle _Style;
public readonly float Outline; //0..1, 0=not outline 1=100% outline
public readonly SColorF OutlineColor;
private readonly float _MaxGlyphHeight;
private readonly Dictionary<char, CGlyph> _Glyphs = new Dictionary<char, CGlyph>();
private PrivateFontCollection _Fonts; private PrivateFontCollection _Fonts;
private FontFamily _Family; private FontFamily _Family;
private readonly float _MaxGlyphHeight;
private readonly string _FilePath; public CFontStyle(string file, EStyle style, float outline, SColorF outlineColor)
private bool _Disposed;
public CFont(string file)
{ {
_FilePath = file; _FilePath = file;
_Style = style;
_Glyphs = new Dictionary<char, CGlyph>(); Outline = outline;
OutlineColor = outlineColor;
switch (CConfig.TextureQuality) switch (CConfig.TextureQuality)
{ {
case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST: case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
_MaxGlyphHeight = 25f; _MaxGlyphHeight = 20f;
break; break;
case ETextureQuality.TR_CONFIG_TEXTURE_LOW: case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
_MaxGlyphHeight = 50f; _MaxGlyphHeight = 40f;
break; break;
case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM: case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
_MaxGlyphHeight = 100f; _MaxGlyphHeight = 60f;
break; break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGH: case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
_MaxGlyphHeight = 200f; _MaxGlyphHeight = 80f;
break; break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST: case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
_MaxGlyphHeight = 400f;
break;
default:
_MaxGlyphHeight = 100f; _MaxGlyphHeight = 100f;
break; break;
default:
_MaxGlyphHeight = 60f;
break;
} }
_MaxGlyphHeight = 50;
} }
public Font GetFont() private FontStyle _GetSystemFontStyle()
{
switch (_Style)
{
case EStyle.Normal:
return FontStyle.Regular;
case EStyle.Italic:
return FontStyle.Italic;
case EStyle.Bold:
return FontStyle.Bold;
case EStyle.BoldItalic:
return FontStyle.Bold | FontStyle.Italic;
}
throw new ArgumentException("Invalid style: " + _Style);
}
public Font GetSystemFont(float height)
{ {
if (_Fonts == null) if (_Fonts == null)
{ {
@@ -81,99 +96,83 @@ namespace Vocaluxe.Base.Fonts
CLog.LogError("Error opening font file " + _FilePath + ": " + e.Message); CLog.LogError("Error opening font file " + _FilePath + ": " + e.Message);
} }
} }
return new Font(_Family, CFonts.Height, CFonts.GetFontStyle(), GraphicsUnit.Pixel); return new Font(_Family, height, _GetSystemFontStyle(), GraphicsUnit.Pixel);
} }
public void DrawGlyph(char chr, float x, float y, float z, SColorF color) public void DrawGlyph(char chr, float fontHeight, float x, float y, float z, SColorF color)
{ {
CTexture texture; CTexture texture;
SRectF rect; SRectF rect;
GetOrAddGlyph(chr).GetTextureAndRect(x, y, z, out texture, out rect); GetOrAddGlyph(chr, fontHeight).GetTextureAndRect(fontHeight, x, y, z, out texture, out rect);
CDraw.DrawTexture(texture, rect, color); CDraw.DrawTexture(texture, rect, color);
} }
public void DrawGlyph(char chr, float x, float y, float z, SColorF color, float begin, float end) public void DrawGlyph(char chr, float fontHeight, float x, float y, float z, SColorF color, float begin, float end)
{ {
CTexture texture; CTexture texture;
SRectF rect; SRectF rect;
GetOrAddGlyph(chr).GetTextureAndRect(x, y, z, out texture, out rect); GetOrAddGlyph(chr, fontHeight).GetTextureAndRect(fontHeight, x, y, z, out texture, out rect);
CDraw.DrawTexture(texture, rect, color, begin, end); CDraw.DrawTexture(texture, rect, color, begin, end);
} }
public void DrawGlyphReflection(char chr, float x, float y, float z, SColorF color, float rspace, float rheight) public void DrawGlyphReflection(char chr, float fontHeight, float x, float y, float z, SColorF color, float rspace, float rheight)
{ {
CTexture texture; CTexture texture;
SRectF rect; SRectF rect;
GetOrAddGlyph(chr).GetTextureAndRect(x, y, z, out texture, out rect); GetOrAddGlyph(chr, fontHeight).GetTextureAndRect(fontHeight, x, y, z, out texture, out rect);
CDraw.DrawTextureReflection(texture, rect, color, rect, rspace, rheight); CDraw.DrawTextureReflection(texture, rect, color, rect, rspace, rheight);
} }
public float GetWidth(char chr) public float GetWidth(char chr, float height)
{ {
return GetOrAddGlyph(chr).Width; return GetOrAddGlyph(chr, height).GetWidth(height);
} }
public float GetHeight(char chr) public float GetHeight(char chr, float height)
{ {
return GetOrAddGlyph(chr).Height; return GetOrAddGlyph(chr, height).GetHeight(height);
} }
public CGlyph GetOrAddGlyph(char chr) public CGlyph GetOrAddGlyph(char chr, float height)
{ {
CGlyph glyph; CGlyph glyph;
if (!_Glyphs.TryGetValue(chr, out glyph)) if (!_Glyphs.TryGetValue(chr, out glyph))
{ {
glyph = new CGlyph(chr, _MaxGlyphHeight); float maxHeight = (_MaxGlyphHeight + 50 >= height) ? _MaxGlyphHeight : (float)Math.Round(height / 50) * 50;
glyph = new CGlyph(chr, this, maxHeight);
_Glyphs.Add(chr, glyph); _Glyphs.Add(chr, glyph);
} }
if (glyph.MaxHeight + 50 < CFonts.Height) if (glyph.MaxHeight + 50 < height)
{ {
glyph.UnloadTexture(); glyph.UnloadTexture();
glyph = new CGlyph(chr, (float)Math.Round(CFonts.Height / 50) * 50); glyph = new CGlyph(chr, this, (float)Math.Round(height / 50) * 50);
_Glyphs[chr] = glyph; _Glyphs[chr] = glyph;
} }
return glyph; return glyph;
} }
public void UnloadGlyphs() private void _UnloadGlyphs()
{ {
foreach (CGlyph glyph in _Glyphs.Values) foreach (CGlyph glyph in _Glyphs.Values)
glyph.UnloadTexture(); glyph.UnloadTexture();
_Glyphs.Clear(); _Glyphs.Clear();
} }
private bool _Disposed;
public void Dispose() public void Dispose()
{ {
if (!_Disposed) if (!_Disposed)
{ {
if (_Fonts != null) if (_Fonts != null)
{
_Fonts.Dispose(); _Fonts.Dispose();
UnloadGlyphs(); _Fonts = null;
}
_UnloadGlyphs();
_Disposed = true; _Disposed = true;
} }
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
} }
struct SFontFamily
{
public string Name;
public int PartyModeID;
public string ThemeName;
public string Folder;
public string FileNormal;
public string FileItalic;
public string FileBold;
public string FileBoldItalic;
public float Outline; //0..1, 0=not outline 1=100% outline
public SColorF OutlineColor;
public CFont Normal;
public CFont Italic;
public CFont Bold;
public CFont BoldItalic;
}
} }
+56 -56
View File
@@ -15,6 +15,7 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>. // along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
@@ -25,6 +26,38 @@ using VocaluxeLib.Menu;
namespace Vocaluxe.Base.Fonts namespace Vocaluxe.Base.Fonts
{ {
struct SFont
{
public string Name;
public EStyle Style;
public float Height;
}
/// <summary>
/// Struct used for describing a font family (a type of text with 4 different styles)
/// </summary>
struct SFontFamily
{
public string Name;
public int PartyModeID;
public string ThemeName;
public string Folder;
public string FileNormal;
public string FileItalic;
public string FileBold;
public string FileBoldItalic;
public float Outline; //0..1, 0=not outline 1=100% outline
public SColorF OutlineColor;
public CFontStyle Normal;
public CFontStyle Italic;
public CFontStyle Bold;
public CFontStyle BoldItalic;
}
static class CFonts static class CFonts
{ {
private static bool _IsInitialized; private static bool _IsInitialized;
@@ -42,16 +75,6 @@ namespace Vocaluxe.Base.Fonts
set { _Height = value < 0f ? 0f : value; } set { _Height = value < 0f ? 0f : value; }
} }
public static float Outline
{
get { return _FontFamilies[_CurrentFont].Outline; }
}
public static SColorF OutlineColor
{
get { return _FontFamilies[_CurrentFont].OutlineColor; }
}
public static bool Init() public static bool Init()
{ {
if (_IsInitialized) if (_IsInitialized)
@@ -74,12 +97,7 @@ namespace Vocaluxe.Base.Fonts
_IsInitialized = false; _IsInitialized = false;
} }
public static Font GetFont() private static CFontStyle _GetCurrentFont()
{
return _GetCurrentFont().GetFont();
}
private static CFont _GetCurrentFont()
{ {
switch (Style) switch (Style)
{ {
@@ -92,8 +110,7 @@ namespace Vocaluxe.Base.Fonts
case EStyle.BoldItalic: case EStyle.BoldItalic:
return _FontFamilies[_CurrentFont].BoldItalic; return _FontFamilies[_CurrentFont].BoldItalic;
} }
//Just in case... throw new ArgumentException("Invalid Style: " + Style);
return _FontFamilies[_CurrentFont].Normal;
} }
#region DrawText #region DrawText
@@ -125,13 +142,13 @@ namespace Vocaluxe.Base.Fonts
return; return;
Height = h; Height = h;
CFont font = _GetCurrentFont(); CFontStyle font = _GetCurrentFont();
float dx = x; float dx = x;
foreach (char chr in text) foreach (char chr in text)
{ {
font.DrawGlyph(chr, dx, y, z, color); font.DrawGlyph(chr, h, dx, y, z, color);
dx += font.GetWidth(chr); dx += font.GetWidth(chr, h);
} }
} }
@@ -144,13 +161,13 @@ namespace Vocaluxe.Base.Fonts
return; return;
Height = h; Height = h;
CFont font = _GetCurrentFont(); CFontStyle font = _GetCurrentFont();
float dx = x; float dx = x;
foreach (char chr in text) foreach (char chr in text)
{ {
font.DrawGlyphReflection(chr, dx, y, z, color, rspace, rheight); font.DrawGlyphReflection(chr, h, dx, y, z, color, rspace, rheight);
dx += font.GetWidth(chr); dx += font.GetWidth(chr, h);
} }
} }
@@ -172,11 +189,11 @@ namespace Vocaluxe.Base.Fonts
float x1 = x + w * begin; float x1 = x + w * begin;
float x2 = x + w * end; float x2 = x + w * end;
CFont font = _GetCurrentFont(); CFontStyle font = _GetCurrentFont();
foreach (char chr in text) foreach (char chr in text)
{ {
float w2 = font.GetWidth(chr); float w2 = font.GetWidth(chr, h);
float b = (x1 - dx) / w2; float b = (x1 - dx) / w2;
if (b < 1f) if (b < 1f)
@@ -188,7 +205,7 @@ namespace Vocaluxe.Base.Fonts
{ {
if (e > 1f) if (e > 1f)
e = 1f; e = 1f;
font.DrawGlyph(chr, dx, y, z, color, b, e); font.DrawGlyph(chr, h, dx, y, z, color, b, e);
} }
} }
dx += w2; dx += w2;
@@ -196,23 +213,6 @@ namespace Vocaluxe.Base.Fonts
} }
#endregion DrawText #endregion DrawText
public static FontStyle GetFontStyle()
{
switch (Style)
{
case EStyle.Normal:
return FontStyle.Regular;
case EStyle.Italic:
return FontStyle.Italic;
case EStyle.Bold:
return FontStyle.Bold;
case EStyle.BoldItalic:
return FontStyle.Bold | FontStyle.Italic;
default:
return FontStyle.Regular;
}
}
public static void SetFont(string fontName) public static void SetFont(string fontName)
{ {
int index = _GetPartyFontIndex(fontName, PartyModeID); int index = _GetPartyFontIndex(fontName, PartyModeID);
@@ -259,14 +259,14 @@ namespace Vocaluxe.Base.Fonts
public static float GetTextWidth(string text) public static float GetTextWidth(string text)
{ {
CFont font = _GetCurrentFont(); CFontStyle font = _GetCurrentFont();
return text.Sum(chr => font.GetWidth(chr)); return text.Sum(chr => font.GetWidth(chr, Height));
} }
public static float GetTextHeight(string text) public static float GetTextHeight(string text)
{ {
CFont font = _GetCurrentFont(); CFontStyle font = _GetCurrentFont();
return text == "" ? 0 : text.Select(font.GetHeight).Max(); return text == "" ? 0 : text.Select(chr => font.GetHeight(chr, Height)).Max();
} }
private static int _GetFontIndex(string fontName) private static int _GetFontIndex(string fontName)
@@ -365,10 +365,10 @@ namespace Vocaluxe.Base.Fonts
if (ok) if (ok)
{ {
sf.Normal = new CFont(Path.Combine(fontFolder, sf.Folder, sf.FileNormal)); sf.Normal = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileNormal), EStyle.Normal, sf.Outline, sf.OutlineColor);
sf.Italic = new CFont(Path.Combine(fontFolder, sf.Folder, sf.FileItalic)); sf.Italic = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileItalic), EStyle.Italic, sf.Outline, sf.OutlineColor);
sf.Bold = new CFont(Path.Combine(fontFolder, sf.Folder, sf.FileBold)); sf.Bold = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileBold), EStyle.Bold, sf.Outline, sf.OutlineColor);
sf.BoldItalic = new CFont(Path.Combine(fontFolder, sf.Folder, sf.FileBoldItalic)); sf.BoldItalic = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileBoldItalic), EStyle.BoldItalic, sf.Outline, sf.OutlineColor);
_FontFamilies.Add(sf); _FontFamilies.Add(sf);
} }
else else
@@ -455,13 +455,13 @@ namespace Vocaluxe.Base.Fonts
foreach (char chr in text) foreach (char chr in text)
{ {
Style = EStyle.Normal; Style = EStyle.Normal;
_FontFamilies[_CurrentFont].Normal.GetOrAddGlyph(chr); _FontFamilies[_CurrentFont].Normal.GetOrAddGlyph(chr, Height);
Style = EStyle.Bold; Style = EStyle.Bold;
_FontFamilies[_CurrentFont].Bold.GetOrAddGlyph(chr); _FontFamilies[_CurrentFont].Bold.GetOrAddGlyph(chr, Height);
Style = EStyle.Italic; Style = EStyle.Italic;
_FontFamilies[_CurrentFont].Italic.GetOrAddGlyph(chr); _FontFamilies[_CurrentFont].Italic.GetOrAddGlyph(chr, Height);
Style = EStyle.BoldItalic; Style = EStyle.BoldItalic;
_FontFamilies[_CurrentFont].BoldItalic.GetOrAddGlyph(chr); _FontFamilies[_CurrentFont].BoldItalic.GetOrAddGlyph(chr, Height);
} }
} }
Style = EStyle.Normal; Style = EStyle.Normal;
+18 -22
View File
@@ -36,26 +36,13 @@ namespace Vocaluxe.Base.Fonts
private readonly RectangleF _DrawBounding; private readonly RectangleF _DrawBounding;
public readonly float MaxHeight; public readonly float MaxHeight;
public float Width public CGlyph(char chr, CFontStyle fontStyle, float maxHeight)
{
get { return _BoundingBox.Width * _GetFactor(); }
}
public float Height
{
get { return _BoundingBox.Height * _GetFactor(); }
}
public CGlyph(char chr, float maxHeight)
{ {
MaxHeight = maxHeight; MaxHeight = maxHeight;
float oldHeight = CFonts.Height; float outlineSize = fontStyle.Outline * maxHeight;
float outline = CFonts.Outline;
float outlineSize = outline * maxHeight;
string chrString = chr.ToString(); string chrString = chr.ToString();
CFonts.Height = maxHeight; Font fo = fontStyle.GetSystemFont(maxHeight);
Font fo = CFonts.GetFont();
SizeF fullSize; SizeF fullSize;
Size bmpSize; Size bmpSize;
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
@@ -105,7 +92,7 @@ namespace Vocaluxe.Base.Fonts
float emSize = fo.Size * fo.FontFamily.GetCellAscent(fo.Style) / fo.FontFamily.GetEmHeight(fo.Style); float emSize = fo.Size * fo.FontFamily.GetCellAscent(fo.Style) / fo.FontFamily.GetEmHeight(fo.Style);
path.AddString(chrString, fo.FontFamily, (int)fo.Style, emSize, point, new StringFormat()); path.AddString(chrString, fo.FontFamily, (int)fo.Style, emSize, point, new StringFormat());
using (var pen = new Pen(CFonts.OutlineColor.AsColor(), outlineSize)) using (var pen = new Pen(fontStyle.OutlineColor.AsColor(), outlineSize))
{ {
pen.LineJoin = LineJoin.Round; pen.LineJoin = LineJoin.Round;
g.DrawPath(pen, path); g.DrawPath(pen, path);
@@ -134,7 +121,6 @@ namespace Vocaluxe.Base.Fonts
} }
} }
} }
CFonts.Height = oldHeight;
} }
public void UnloadTexture() public void UnloadTexture()
@@ -142,15 +128,25 @@ namespace Vocaluxe.Base.Fonts
CDraw.RemoveTexture(ref _Texture); CDraw.RemoveTexture(ref _Texture);
} }
private float _GetFactor() private float _GetFactor(float fontHeight)
{ {
return CFonts.Height / _BoundingBox.Height; return fontHeight / _BoundingBox.Height;
} }
public void GetTextureAndRect(float x, float y, float z, out CTexture texture, out SRectF rect) public float GetWidth(float fontHeight)
{
return _BoundingBox.Width * _GetFactor(fontHeight);
}
public float GetHeight(float fontHeight)
{
return _BoundingBox.Height * _GetFactor(fontHeight);
}
public void GetTextureAndRect(float fontHeight, float x, float y, float z, out CTexture texture, out SRectF rect)
{ {
texture = _Texture; texture = _Texture;
float factor = _GetFactor(); float factor = _GetFactor(fontHeight);
x += _DrawBounding.X * factor; x += _DrawBounding.X * factor;
y += _DrawBounding.Y * factor; y += _DrawBounding.Y * factor;
float h = _DrawBounding.Height * factor; float h = _DrawBounding.Height * factor;
+1 -1
View File
@@ -241,7 +241,7 @@
<Compile Include="Base\CDraw.cs" /> <Compile Include="Base\CDraw.cs" />
<Compile Include="Lib\Sound\Playback\PortAudio\CPt1.cs" /> <Compile Include="Lib\Sound\Playback\PortAudio\CPt1.cs" />
<Compile Include="Lib\Sound\Playback\PortAudio\CSyncTimer.cs" /> <Compile Include="Lib\Sound\Playback\PortAudio\CSyncTimer.cs" />
<Compile Include="Base\Fonts\CFont.cs" /> <Compile Include="Base\Fonts\CFontStyle.cs" />
<Compile Include="Base\CGame.cs" /> <Compile Include="Base\CGame.cs" />
<Compile Include="Base\CController.cs" /> <Compile Include="Base\CController.cs" />
<Compile Include="Base\CLanguage.cs" /> <Compile Include="Base\CLanguage.cs" />
+2
View File
@@ -17,6 +17,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using VocaluxeLib.Songs; using VocaluxeLib.Songs;
@@ -48,6 +49,7 @@ namespace VocaluxeLib
A = color.A; A = color.A;
} }
[Pure]
public Color AsColor() public Color AsColor()
{ {
return Color.FromArgb((int)(A * 255), (int)(R * 255), (int)(G * 255), (int)(B * 255)); return Color.FromArgb((int)(A * 255), (int)(R * 255), (int)(G * 255), (int)(B * 255));