4 using System.Collections.Generic;
6 using SiliconStudio.Core;
7 using SiliconStudio.Core.Mathematics;
16 private readonly FontSystem system;
18 private readonly List<Texture2D> cacheTextures =
new List<Texture2D>();
19 private readonly LinkedList<CharacterSpecification> cachedCharacters =
new LinkedList<CharacterSpecification>();
20 private readonly GuillotinePacker packer =
new GuillotinePacker();
25 public IReadOnlyList<Texture2D> Textures {
get;
private set; }
27 public FontCacheManager(FontSystem system,
int textureDefaultSize = 1024)
30 Textures = cacheTextures;
33 var newTexture = Texture2D.New(system.GraphicsDevice, textureDefaultSize, textureDefaultSize, PixelFormat.R8_UNorm);
34 cacheTextures.Add(newTexture);
35 newTexture.Reload = ReloadCache;
39 private void ReloadCache(GraphicsResourceBase graphicsResourceBase)
41 foreach (var cacheTexture
in cacheTextures)
42 cacheTexture.Recreate();
50 public void ClearCache()
52 foreach (var character
in cachedCharacters)
53 character.IsBitmapUploaded =
false;
54 cachedCharacters.Clear();
56 packer.Clear(cacheTextures[0].Width, cacheTextures[0].Height);
63 public void UploadCharacterBitmap(CharacterSpecification character)
65 if(character.Bitmap == null)
66 throw new ArgumentNullException(
"character");
68 if(character.IsBitmapUploaded)
69 throw new InvalidOperationException(
"The character '"+character.Character+
"' upload has been requested while its current glyph is valid.");
71 var targetSize =
new Int2(character.Bitmap.Width, character.Bitmap.Rows);
72 if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))
75 RemoveLessUsedCharacters();
76 if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))
80 if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))
81 throw new InvalidOperationException(
"The rendered character is too big for the cache texture");
85 if (character.Bitmap.Rows != 0 && character.Bitmap.Width != 0)
87 var dataBox =
new DataBox(character.Bitmap.Buffer, character.Bitmap.Pitch, character.Bitmap.Pitch * character.Bitmap.Rows);
88 var region =
new ResourceRegion(character.Glyph.Subrect.Left, character.Glyph.Subrect.Top, 0, character.Glyph.Subrect.Right, character.Glyph.Subrect.Bottom, 1);
89 system.GraphicsDevice.UpdateSubresource(cacheTextures[0], 0, dataBox, region);
93 character.IsBitmapUploaded =
true;
94 character.Glyph.BitmapIndex = 0;
100 private void RemoveLessUsedCharacters(
int frameCount = 5)
102 var limitFrame = system.FrameCount - frameCount;
103 var currentNode = cachedCharacters.Last;
104 while (currentNode != null && currentNode.Value.LastUsedFrame < limitFrame)
106 currentNode.Value.IsBitmapUploaded =
false;
107 packer.Free(ref currentNode.Value.Glyph.Subrect);
108 currentNode = currentNode.Previous;
109 cachedCharacters.RemoveLast();
113 protected override void Destroy()
117 foreach (var cacheTexture
in cacheTextures)
118 cacheTexture.Dispose();
120 cacheTextures.Clear();
121 cachedCharacters.Clear();
124 public void NotifyCharacterUtilization(CharacterSpecification character)
126 character.LastUsedFrame = system.FrameCount;
128 if(character.ListNode.List != null)
129 cachedCharacters.Remove(character.ListNode);
130 cachedCharacters.AddFirst(character.ListNode);
ComponentBase.Destroy() event.
Base class for a framework component.
SharpDX.DirectWrite.Font Font
Represents a three dimensional mathematical vector.