/*
i-net software provides programming examples for illustration only, without warranty
either expressed or implied, including, but not limited to, the implied warranties
of merchantability and/or fitness for a particular purpose. This programming example
assumes that you are familiar with the programming language being demonstrated and
the tools used to create and debug procedures. i-net software support professionals
can help explain the functionality of a particular procedure, but they will not modify
these examples to provide added functionality or construct procedures to meet your
specific needs.
© i-net software 1998-2013
*/
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using Inet.Viewer.Resources;
using System;
using System.Drawing;
using System.Drawing.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace Inet.Viewer.Data
{
///
/// Implementation of the Loader to specifically load the Fonts
///
public class FontLoader : Loader
{
private FontData result = null;
///
/// Ovrrides the Load function
///
///
///
protected internal override bool Load(int token)
{
switch (token)
{
case ViewerTokenConstants.TokenFontId:
result.Id = ReadInt();
break;
case ViewerTokenConstants.TokenFontRev:
result.Revision = ReadInt();
break;
case ViewerTokenConstants.TokenFontData:
bool compressFontData = ReadBoolean();
byte[] fontData = ReadByteArray();
if (compressFontData)
{
Inflater inflater = new Inflater();
InflaterInputStream input = new InflaterInputStream(new MemoryStream(fontData), inflater);
MemoryStream ustream = new MemoryStream();
int b;
while ((b=input.ReadByte())!=-1)
{
ustream.WriteByte((byte)b);
}
fontData = ustream.ToArray();
}
try
{
LoadFontFamily(fontData);
}
catch (IOException e)
{
throw new ViewerException(strings.ErrorMessage_Font_CouldNotCreate + " " + result.Id, e);
}
break;
default:
return base.Load(token);
}
return true;
}
///
/// This method Reads the byte fontData and returns the FontData of this Font
///
/// the font data in form of a byte array
/// the parsed FontData instance
public virtual FontData ReadFont(byte[] fontData)
{
this.result = new FontData();
this.Data = fontData;
ReadTokens();
if (result.Font == null && result.FontFamily == null)
{
// set default font
result.FontFamily = FontFamily.GenericSansSerif;
result.Font = new Font(FontFamily.GenericSansSerif, 150);
return result;
}
if (result.Font == null)
{
try
{
result.Font = new Font(result.FontFamily, 150);
}
catch (ArgumentException)
{
// mostelikely the Regular style is not available, so we have to look which style is available
FontStyle fStyle = GetAvailableStyle(result.FontFamily);
result.Font = new Font(result.FontFamily, 150, fStyle);
}
}
return result;
}
///
/// Returns the available Font Style.
/// Doesn't include strikethrough and underline, as all fonts support that
///
public static FontStyle GetAvailableStyle(FontFamily family)
{
// To make sure a fontstyle is set that is supported
FontStyle fStyle = FontStyle.Regular;
if (family.IsStyleAvailable(FontStyle.Bold))
{
fStyle += (int)FontStyle.Bold;
}
else if (family.IsStyleAvailable(FontStyle.Italic))
{
fStyle += (int)FontStyle.Italic;
}
else if (family.IsStyleAvailable(FontStyle.Bold | FontStyle.Italic))
{
fStyle = FontStyle.Bold | FontStyle.Italic;
}
return fStyle;
}
///
/// Helper method to load font family from a byte array
///
/// the byte array with the font data
private void LoadFontFamily(byte[] buffer)
{
string fileName = result.FileName = Path.GetTempFileName();
using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.RandomAccess))
{
fs.Write(buffer, 0, buffer.Length);
}
// Create a temp memory collection
PrivateFontCollection fontCollection = result.FontCollection = new PrivateFontCollection();
// To hold a reference
fontCollection.AddFontFile(fileName);
RemoveFontResourceEx(fileName, 16, IntPtr.Zero); // https://stackoverflow.com/questions/26671026/how-to-delete-the-file-of-a-privatefontcollection-addfontfile
result.FontFamily = fontCollection.Families[0];
}
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int RemoveFontResourceEx(string lpszFilename, int fl, IntPtr pdv);
}
}