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.Drawing;
using System.Drawing.Text;
using System.Xml.Serialization;
using VocaluxeLib;
using VocaluxeLib.Draw;
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 FontFamily _Family;
private readonly float _MaxGlyphHeight;
private readonly string _FilePath;
private bool _Disposed;
public CFont(string file)
public CFontStyle(string file, EStyle style, float outline, SColorF outlineColor)
{
_FilePath = file;
_Glyphs = new Dictionary<char, CGlyph>();
_Style = style;
Outline = outline;
OutlineColor = outlineColor;
switch (CConfig.TextureQuality)
{
case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
_MaxGlyphHeight = 25f;
_MaxGlyphHeight = 20f;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
_MaxGlyphHeight = 50f;
_MaxGlyphHeight = 40f;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
_MaxGlyphHeight = 100f;
_MaxGlyphHeight = 60f;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
_MaxGlyphHeight = 200f;
_MaxGlyphHeight = 80f;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
_MaxGlyphHeight = 400f;
break;
default:
_MaxGlyphHeight = 100f;
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)
{
@@ -81,99 +96,83 @@ namespace Vocaluxe.Base.Fonts
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;
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);
}
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;
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);
}
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;
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);
}
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;
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);
}
if (glyph.MaxHeight + 50 < CFonts.Height)
if (glyph.MaxHeight + 50 < height)
{
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;
}
return glyph;
}
public void UnloadGlyphs()
private void _UnloadGlyphs()
{
foreach (CGlyph glyph in _Glyphs.Values)
glyph.UnloadTexture();
_Glyphs.Clear();
}
private bool _Disposed;
public void Dispose()
{
if (!_Disposed)
{
if (_Fonts != null)
{
_Fonts.Dispose();
UnloadGlyphs();
_Fonts = null;
}
_UnloadGlyphs();
_Disposed = true;
}
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/>.
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
@@ -25,6 +26,38 @@ using VocaluxeLib.Menu;
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
{
private static bool _IsInitialized;
@@ -42,16 +75,6 @@ namespace Vocaluxe.Base.Fonts
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()
{
if (_IsInitialized)
@@ -74,12 +97,7 @@ namespace Vocaluxe.Base.Fonts
_IsInitialized = false;
}
public static Font GetFont()
{
return _GetCurrentFont().GetFont();
}
private static CFont _GetCurrentFont()
private static CFontStyle _GetCurrentFont()
{
switch (Style)
{
@@ -92,8 +110,7 @@ namespace Vocaluxe.Base.Fonts
case EStyle.BoldItalic:
return _FontFamilies[_CurrentFont].BoldItalic;
}
//Just in case...
return _FontFamilies[_CurrentFont].Normal;
throw new ArgumentException("Invalid Style: " + Style);
}
#region DrawText
@@ -125,13 +142,13 @@ namespace Vocaluxe.Base.Fonts
return;
Height = h;
CFont font = _GetCurrentFont();
CFontStyle font = _GetCurrentFont();
float dx = x;
foreach (char chr in text)
{
font.DrawGlyph(chr, dx, y, z, color);
dx += font.GetWidth(chr);
font.DrawGlyph(chr, h, dx, y, z, color);
dx += font.GetWidth(chr, h);
}
}
@@ -144,13 +161,13 @@ namespace Vocaluxe.Base.Fonts
return;
Height = h;
CFont font = _GetCurrentFont();
CFontStyle font = _GetCurrentFont();
float dx = x;
foreach (char chr in text)
{
font.DrawGlyphReflection(chr, dx, y, z, color, rspace, rheight);
dx += font.GetWidth(chr);
font.DrawGlyphReflection(chr, h, dx, y, z, color, rspace, rheight);
dx += font.GetWidth(chr, h);
}
}
@@ -172,11 +189,11 @@ namespace Vocaluxe.Base.Fonts
float x1 = x + w * begin;
float x2 = x + w * end;
CFont font = _GetCurrentFont();
CFontStyle font = _GetCurrentFont();
foreach (char chr in text)
{
float w2 = font.GetWidth(chr);
float w2 = font.GetWidth(chr, h);
float b = (x1 - dx) / w2;
if (b < 1f)
@@ -188,7 +205,7 @@ namespace Vocaluxe.Base.Fonts
{
if (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;
@@ -196,23 +213,6 @@ namespace Vocaluxe.Base.Fonts
}
#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)
{
int index = _GetPartyFontIndex(fontName, PartyModeID);
@@ -259,14 +259,14 @@ namespace Vocaluxe.Base.Fonts
public static float GetTextWidth(string text)
{
CFont font = _GetCurrentFont();
return text.Sum(chr => font.GetWidth(chr));
CFontStyle font = _GetCurrentFont();
return text.Sum(chr => font.GetWidth(chr, Height));
}
public static float GetTextHeight(string text)
{
CFont font = _GetCurrentFont();
return text == "" ? 0 : text.Select(font.GetHeight).Max();
CFontStyle font = _GetCurrentFont();
return text == "" ? 0 : text.Select(chr => font.GetHeight(chr, Height)).Max();
}
private static int _GetFontIndex(string fontName)
@@ -365,10 +365,10 @@ namespace Vocaluxe.Base.Fonts
if (ok)
{
sf.Normal = new CFont(Path.Combine(fontFolder, sf.Folder, sf.FileNormal));
sf.Italic = new CFont(Path.Combine(fontFolder, sf.Folder, sf.FileItalic));
sf.Bold = new CFont(Path.Combine(fontFolder, sf.Folder, sf.FileBold));
sf.BoldItalic = new CFont(Path.Combine(fontFolder, sf.Folder, sf.FileBoldItalic));
sf.Normal = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileNormal), EStyle.Normal, sf.Outline, sf.OutlineColor);
sf.Italic = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileItalic), EStyle.Italic, sf.Outline, sf.OutlineColor);
sf.Bold = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileBold), EStyle.Bold, sf.Outline, sf.OutlineColor);
sf.BoldItalic = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileBoldItalic), EStyle.BoldItalic, sf.Outline, sf.OutlineColor);
_FontFamilies.Add(sf);
}
else
@@ -455,13 +455,13 @@ namespace Vocaluxe.Base.Fonts
foreach (char chr in text)
{
Style = EStyle.Normal;
_FontFamilies[_CurrentFont].Normal.GetOrAddGlyph(chr);
_FontFamilies[_CurrentFont].Normal.GetOrAddGlyph(chr, Height);
Style = EStyle.Bold;
_FontFamilies[_CurrentFont].Bold.GetOrAddGlyph(chr);
_FontFamilies[_CurrentFont].Bold.GetOrAddGlyph(chr, Height);
Style = EStyle.Italic;
_FontFamilies[_CurrentFont].Italic.GetOrAddGlyph(chr);
_FontFamilies[_CurrentFont].Italic.GetOrAddGlyph(chr, Height);
Style = EStyle.BoldItalic;
_FontFamilies[_CurrentFont].BoldItalic.GetOrAddGlyph(chr);
_FontFamilies[_CurrentFont].BoldItalic.GetOrAddGlyph(chr, Height);
}
}
Style = EStyle.Normal;
+18 -22
View File
@@ -36,26 +36,13 @@ namespace Vocaluxe.Base.Fonts
private readonly RectangleF _DrawBounding;
public readonly float MaxHeight;
public float Width
{
get { return _BoundingBox.Width * _GetFactor(); }
}
public float Height
{
get { return _BoundingBox.Height * _GetFactor(); }
}
public CGlyph(char chr, float maxHeight)
public CGlyph(char chr, CFontStyle fontStyle, float maxHeight)
{
MaxHeight = maxHeight;
float oldHeight = CFonts.Height;
float outline = CFonts.Outline;
float outlineSize = outline * maxHeight;
float outlineSize = fontStyle.Outline * maxHeight;
string chrString = chr.ToString();
CFonts.Height = maxHeight;
Font fo = CFonts.GetFont();
Font fo = fontStyle.GetSystemFont(maxHeight);
SizeF fullSize;
Size bmpSize;
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);
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;
g.DrawPath(pen, path);
@@ -134,7 +121,6 @@ namespace Vocaluxe.Base.Fonts
}
}
}
CFonts.Height = oldHeight;
}
public void UnloadTexture()
@@ -142,15 +128,25 @@ namespace Vocaluxe.Base.Fonts
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;
float factor = _GetFactor();
float factor = _GetFactor(fontHeight);
x += _DrawBounding.X * factor;
y += _DrawBounding.Y * factor;
float h = _DrawBounding.Height * factor;
+1 -1
View File
@@ -241,7 +241,7 @@
<Compile Include="Base\CDraw.cs" />
<Compile Include="Lib\Sound\Playback\PortAudio\CPt1.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\CController.cs" />
<Compile Include="Base\CLanguage.cs" />
+2
View File
@@ -17,6 +17,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Drawing;
using System.Windows.Forms;
using VocaluxeLib.Songs;
@@ -48,6 +49,7 @@ namespace VocaluxeLib
A = color.A;
}
[Pure]
public Color AsColor()
{
return Color.FromArgb((int)(A * 255), (int)(R * 255), (int)(G * 255), (int)(B * 255));