4 using System.Collections.Generic;
5 using System.Threading;
8 using SiliconStudio.Core.Diagnostics;
9 using SiliconStudio.Core.IO;
10 using SiliconStudio.Core.Mathematics;
11 using SiliconStudio.Core.Serialization.Assets;
18 internal class FontManager : IDisposable
23 private readonly
object dataStructuresLock =
new object();
28 private readonly Dictionary<string, Face> cachedFontFaces =
new Dictionary<string, Face>();
33 private readonly List<CharacterSpecification> generatedBitmaps =
new List<CharacterSpecification>();
38 private readonly Queue<CharacterSpecification> bitmapsToGenerate =
new Queue<CharacterSpecification>();
43 private readonly AutoResetEvent bitmapBuildSignal =
new AutoResetEvent(
false);
45 #if !SILICONSTUDIO_PLATFORM_WINDOWS_RUNTIME
49 private readonly Thread bitmapBuilderThread;
55 private bool bitmapShouldEndThread;
60 private Library freetypeLibrary;
74 private Int2 borderSize = Int2.One;
84 Core.NativeLibrary.PreloadLibrary(
"freetype.dll");
87 freetypeLibrary =
new Library();
89 #if SILICONSTUDIO_PLATFORM_WINDOWS_RUNTIME
90 Windows.System.Threading.ThreadPool.RunAsync(operation => SafeAction.Wrap(BuildBitmapThread)());
93 bitmapBuilderThread =
new Thread(
SafeAction.
Wrap(BuildBitmapThread)) { IsBackground =
true, Name =
"Bitmap Builder thread" };
94 bitmapBuilderThread.Start();
104 public void GenerateBitmap(CharacterSpecification characterSpecification,
bool synchronously)
107 GenerateCharacterGlyph(characterSpecification, synchronously);
112 lock (dataStructuresLock)
114 if (characterSpecification.Bitmap == null && !bitmapsToGenerate.Contains(characterSpecification))
116 bitmapsToGenerate.Enqueue(characterSpecification);
117 bitmapBuildSignal.Set();
123 private void GenerateCharacterGlyph(CharacterSpecification character,
bool renderBitmap)
126 ResetGlyph(character);
129 if (character.Size.X < 1 || character.Size.Y < 1)
133 var fontFace = GetOrCreateFontFace(character.FontName, character.Style);
134 lock (freetypeLibrary)
137 SetFontFaceSize(fontFace, character.Size);
140 var glyphIndex = fontFace.GetCharIndex(character.Character);
147 fontFace.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
150 character.Glyph.XAdvance = fontFace.Glyph.Advance.X / 64f;
154 RenderBitmap(character, fontFace);
158 private void RenderBitmap(CharacterSpecification character, Face fontFace)
161 var renderingMode = character.AntiAlias == FontAntiAliasMode.Aliased ? RenderMode.Mono : RenderMode.Normal;
162 fontFace.Glyph.RenderGlyph(renderingMode);
165 var bitmap = fontFace.Glyph.Bitmap;
166 if (bitmap.Width != 0 && bitmap.Rows != 0)
167 character.Bitmap =
new CharacterBitmap(bitmap.Buffer, ref borderSize, bitmap.Width, bitmap.Rows, bitmap.Pitch, bitmap.GrayLevels, bitmap.PixelMode);
169 character.Bitmap =
new CharacterBitmap();
172 character.Glyph.Offset =
new Vector2(fontFace.Glyph.BitmapLeft - borderSize.X, -fontFace.Glyph.BitmapTop - borderSize.Y);
175 private static void ResetGlyph(CharacterSpecification character)
177 character.Glyph.Offset = Vector2.Zero;
178 character.Glyph.XAdvance = 0;
179 character.Glyph.BitmapIndex = 0;
180 character.Glyph.Subrect.X = 0;
181 character.Glyph.Subrect.Y = 0;
182 character.Glyph.Subrect.Width = 0;
183 character.Glyph.Subrect.Height = 0;
186 private void SetFontFaceSize(Face fontFace,
Vector2 size)
191 fontFace.SetCharSize((int)Math.Ceiling(size.
X * 64), (int)Math.Ceiling(size.
Y * 64), 72, 72);
203 public void GetFontInfo(
string fontFamily,
FontStyle fontStyle, out
float lineSpacing, out
float baseLine, out
float maxWidth, out
float maxHeight)
206 var fontData = GetOrCreateFontFace(fontFamily, fontStyle);
208 lineSpacing = fontData.Height / (float)fontData.UnitsPerEM;
209 baseLine = (fontData.Height + fontData.Descender) / (float)fontData.UnitsPerEM;
210 maxWidth = (fontData.BBox.Right - fontData.BBox.Left) / (float)fontData.UnitsPerEM;
211 maxHeight = (fontData.BBox.Top - fontData.BBox.Bottom) / (float)fontData.UnitsPerEM;
221 public bool DoesFontContains(
string fontFamily,
FontStyle fontStyle,
char character)
223 var fontFace = GetOrCreateFontFace(fontFamily, fontStyle);
227 glyphIndex = fontFace.GetCharIndex(character);
230 return glyphIndex != 0;
233 public
void Dispose()
236 bitmapShouldEndThread =
true;
237 bitmapBuildSignal.Set();
238 #if !SILICONSTUDIO_PLATFORM_WINDOWS_RUNTIME
239 bitmapBuilderThread.Join();
243 foreach (var character
in generatedBitmaps)
245 if (character.Bitmap != null)
247 character.Bitmap.Dispose();
248 character.Bitmap = null;
251 generatedBitmaps.Clear();
254 foreach (var font
in cachedFontFaces.Values)
256 cachedFontFaces.Clear();
259 if (freetypeLibrary != null)
260 freetypeLibrary.Dispose();
261 freetypeLibrary = null;
264 private Face GetOrCreateFontFace(
string fontFamily,
FontStyle fontStyle)
266 var fontPath = FontHelper.GetFontPath(fontFamily, fontStyle);
269 LoadFontInMemory(fontPath);
271 return cachedFontFaces[fontPath];
274 private void LoadFontInMemory(
string fontPath)
277 if (cachedFontFaces.ContainsKey(fontPath))
281 using (var fontStream = assetManager.OpenAsStream(fontPath, StreamFlags.None))
284 var newFontData =
new byte[fontStream.Length];
285 fontStream.Read(newFontData, 0, newFontData.Length);
287 lock (freetypeLibrary)
288 cachedFontFaces[fontPath] = freetypeLibrary.NewMemoryFace(newFontData, 0);
295 private
void BuildBitmapThread()
297 while (!bitmapShouldEndThread)
299 bitmapBuildSignal.WaitOne();
301 while (bitmapsToGenerate.Count > 0)
303 var character = bitmapsToGenerate.Peek();
306 if (character.Size.X < 1 || character.Size.Y < 1)
310 var fontFace = GetOrCreateFontFace(character.FontName, character.Style);
312 lock (freetypeLibrary)
315 SetFontFaceSize(fontFace, character.Size);
318 var glyphIndex = fontFace.GetCharIndex(character.Character);
325 fontFace.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
328 RenderBitmap(character, fontFace);
334 lock (dataStructuresLock)
335 bitmapsToGenerate.Dequeue();
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
Represents a two dimensional mathematical vector.
static ThreadStart Wrap(ThreadStart action, [CallerFilePath] string sourceFilePath="", [CallerMemberName] string memberName="", [CallerLineNumber] int sourceLineNumber=0)
SharpDX.DirectWrite.Font Font
float Y
The Y component of the vector.
Represents a three dimensional mathematical vector.
float X
The X component of the vector.
SiliconStudio.Paradox.Graphics.Font.FontStyle FontStyle
_In_ size_t _In_ size_t size