Skip to content

Commit

Permalink
[Fonts] - Updated the font factory to allow loading from a stream. Th…
Browse files Browse the repository at this point in the history
…is will enable loading from embedded resources and other containers.

[Fonts] - Fixed an issue in the font factory where the incorrect font family is returned after loading.
[Examples] - Updated font example to show loading a font from an embedded resource.
  • Loading branch information
Tape-Worm committed Mar 24, 2020
1 parent c13e940 commit 0fec394
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 2 deletions.
1 change: 1 addition & 0 deletions Examples/Gorgon.Graphics/Fonts/Fonts.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Gorgon2.ico" />
<None Include="Resources\Achafexp.ttf" />
<None Include="Resources\Gorgon_Logo_Small.DDS" />
</ItemGroup>
<ItemGroup>
Expand Down
9 changes: 9 additions & 0 deletions Examples/Gorgon.Graphics/Fonts/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,15 @@ private static void GenerateGorgonFonts(IReadOnlyList<Drawing.FontFamily> fontFa
fontFamilies.Add(externFont);
}

// Load this font from our resources section.
window.UpdateStatus($"Loading Resource Font...");
using (MemoryStream stream = new MemoryStream(Resources.Achafexp))
{
Drawing.FontFamily resFont = GorgonExample.Fonts.LoadTrueTypeFontFamily(stream);
_fontFamilies.Insert(0, resFont.Name);
fontFamilies.Add(resFont);
}

window.UpdateStatus(null);

fontFamilies.AddRange(Drawing.FontFamily.Families);
Expand Down
12 changes: 11 additions & 1 deletion Examples/Gorgon.Graphics/Fonts/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Examples/Gorgon.Graphics/Fonts/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Achafexp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Achafexp.ttf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="Gorgon_Logo_Small" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Gorgon_Logo_Small.DDS;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
Expand Down
Binary file not shown.
86 changes: 85 additions & 1 deletion Gorgon/Gorgon.Graphics.Fonts/GorgonFontFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Threading;
using System.Runtime.CompilerServices;
using Gorgon.Core;
using Gorgon.Graphics.Core;
using Gorgon.Graphics.Fonts.Properties;
Expand Down Expand Up @@ -120,6 +122,25 @@ private static bool IsFontDifferent(IGorgonFontInfo left, IGorgonFontInfo right)
|| (!left.Size.EqualsEpsilon(right.Size))
|| (!left.Characters.SequenceEqual(right.Characters)));

/// <summary>
/// Function to locate a newly loaded external font.
/// </summary>
/// <param name="currentFonts">The current list of fonts, prior to loading the external font.</param>
/// <returns>The font family for the font, or <b>null</b> if not found.</returns>
private FontFamily GetExternalFontFamily(HashSet<string> currentFonts)
{
var newFonts = new HashSet<string>(_externalFonts.Families.Select(item => item.Name), StringComparer.OrdinalIgnoreCase);
newFonts.ExceptWith(currentFonts);
string newFont = newFonts.FirstOrDefault();

if (string.IsNullOrWhiteSpace(newFont))
{
return null;
}

return _externalFonts.Families.FirstOrDefault(item => string.Equals(item.Name, newFont, StringComparison.OrdinalIgnoreCase));
}

/// <summary>
/// Function to register a font within the font cache.
/// </summary>
Expand Down Expand Up @@ -248,6 +269,67 @@ public bool HasFont(IGorgonFontInfo fontInfo)
}
}

/// <summary>
/// Function to load a try type font into the font factory for rasterization.
/// </summary>
/// <param name="stream">The stream containing the true type font data.</param>
/// <param name="size">[Optional] The size of the font data, in bytes.</param>
/// <returns>The font family for the loaded font.</returns>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is <b>null</b>.</exception>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="size"/> parameter is less than 1.</exception>
/// <exception cref="IOException">Thrown when the <paramref name="stream"/> is write only.</exception>
/// <exception cref="EndOfStreamException">Thrown when no more data can be read from the <paramref name="stream"/>.</exception>
/// <remarks>
/// <para>
/// Use this to load a true type from the disk into the factory. The factory will use this to build a <see cref="GorgonFont"/> based on your font.
/// </para>
/// <para>
/// If the <paramref name="size"/> parameter is not specified, then the entire length of the stream will be used.
/// </para>
/// </remarks>
public FontFamily LoadTrueTypeFontFamily(Stream stream, int? size = null)
{
if (stream == null)
{
throw new ArgumentNullException(nameof(stream));
}

if (!stream.CanRead)
{
throw new IOException(Resources.GORGFX_ERR_STREAM_WRITE_ONLY);
}

if (size == null)
{
size = (int)stream.Length;
}

if (size < 1)
{
throw new ArgumentOutOfRangeException(nameof(size));
}

if (stream.Position > (stream.Length - size.Value))
{
throw new EndOfStreamException();
}

var currentFonts = new HashSet<string>(_externalFonts.Families.Select(item => item.Name), StringComparer.OrdinalIgnoreCase);

byte[] data = new byte[size.Value];
stream.Read(data, 0, data.Length);

unsafe
{
fixed (byte* ptr = data)
{
_externalFonts.AddMemoryFont(new IntPtr(ptr), data.Length);
}
}

return GetExternalFontFamily(currentFonts);
}

/// <summary>
/// Function to load a try type font into the font factory for rasterization.
/// </summary>
Expand All @@ -272,9 +354,11 @@ public FontFamily LoadTrueTypeFontFamily(string path)
throw new ArgumentEmptyException(nameof(path));
}

var currentFonts = new HashSet<string>(_externalFonts.Families.Select(item => item.Name), StringComparer.OrdinalIgnoreCase);

_externalFonts.AddFontFile(path);

return _externalFonts.Families[_externalFonts.Families.Length - 1];
return GetExternalFontFamily(currentFonts);
}

/// <summary>
Expand Down

0 comments on commit 0fec394

Please sign in to comment.