using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
#pragma warning disable CS3001, CS3002, CS3003, CS1591
namespace FastReport.Fonts
{
///
/// Name table keep human friendly description about font properties, including font names, author and copyright notes
///
public class NameTableClass : TrueTypeTable, ICollection
{
#region "Structure dfinition"
public enum NameID
{
CopyrightNotice = 0,
FamilyName = 1,
SubFamilyName = 2,
UniqueID = 3,
FullName = 4,
Version = 5,
PostscriptName = 6,
Trademark = 7,
Manufacturer = 8,
Designer = 9,
Description = 10,
URL_Vendor = 11,
URL_Designer = 12,
LicenseDescription = 13,
LicenseInfoURL = 14,
PreferredFamily = 16,
PreferredSubFamily = 17,
CompatibleFull = 18,
SampleText = 19,
PostscriptCID = 20,
WWS_Family_Name = 21,
WWS_SubFamily_Name = 22
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct NamingTableHeader
{
[FieldOffset(0)]
public ushort TableVersion;
[FieldOffset(2)]
public ushort Count;
[FieldOffset(4)]
public ushort stringOffset;
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct NamingRecord
{
[FieldOffset(0)]
public ushort PlatformID;
[FieldOffset(2)]
public ushort EncodingID;
[FieldOffset(4)]
public ushort LanguageID;
[FieldOffset(6)]
public ushort NameID;
[FieldOffset(8)]
public ushort Length;
[FieldOffset(10)]
public ushort Offset;
}
#endregion
NamingTableHeader name_header;
IntPtr namerecord_ptr;
IntPtr string_storage_ptr;
Dictionary> names = new Dictionary>();
public Dictionary> NamesDict
{
get
{
return names;
}
}
public int Count
{
get
{
return name_header.Count;
}
}
public object SyncRoot
{
get
{
return null; // Names.SyncRoot;
}
}
public bool IsSynchronized
{
get
{
return true; // Names.IsSynchronized;
}
}
private void ChangeEndian()
{
name_header.TableVersion = SwapUInt16(name_header.TableVersion);
name_header.Count = SwapUInt16(name_header.Count);
name_header.stringOffset = SwapUInt16(name_header.stringOffset);
}
internal override void Load(IntPtr font)
{
IntPtr nameheader_ptr = Increment(font, (int)this.Offset);
name_header = (NamingTableHeader)Marshal.PtrToStructure(nameheader_ptr, typeof(NamingTableHeader));
ChangeEndian();
namerecord_ptr = Increment(nameheader_ptr, Marshal.SizeOf(name_header));
string_storage_ptr = Increment(nameheader_ptr, (int)name_header.stringOffset);
// Parse table to local storage
IntPtr record_ptr = namerecord_ptr;
for (int i = 0; i < name_header.Count; i++)
{
NamingRecord name_rec = (NamingRecord)Marshal.PtrToStructure(record_ptr, typeof(NamingRecord));
record_ptr = Increment(record_ptr, Marshal.SizeOf(name_rec));
name_rec.PlatformID = SwapUInt16(name_rec.PlatformID);
name_rec.EncodingID = SwapUInt16(name_rec.EncodingID);
name_rec.LanguageID = SwapUInt16(name_rec.LanguageID);
name_rec.NameID = SwapUInt16(name_rec.NameID);
name_rec.Length = SwapUInt16(name_rec.Length);
name_rec.Offset = SwapUInt16(name_rec.Offset);
byte[] Temp = new byte[name_rec.Length];
IntPtr string_ptr = Increment(string_storage_ptr, name_rec.Offset);
Marshal.Copy(string_ptr, Temp, 0, (int)Temp.Length);
string value;
if (name_rec.PlatformID == 1)
{
value = Encoding.GetEncoding("utf-8").GetString(Temp);
}
else
{
value = Encoding.GetEncoding(1201).GetString(Temp);
}
NameID id = (NameID)name_rec.NameID;
List values;
if (!names.ContainsKey(id))
{
values = new List();
names.Add(id, values);
}
else
{
values = (List)names[id];
}
if (!values.Contains(value))
{
values.Add(value);
}
#if _DEBUG
else
{
Debug.WriteLine("Skip duplicated name: " + value);
}
#endif
}
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public IEnumerator GetEnumerator()
{
return names.Keys.GetEnumerator();
}
public ICollection this[NameID Index]
{
get
{
#if true
ICollection rec = null;
if (names.ContainsKey(Index))
{
rec = names[Index] as ICollection;
}
return rec;
#else
IntPtr record_ptr = namerecord_ptr;
for (int i = 0; i < name_header.Count; i++)
{
NamingRecord name_rec = (NamingRecord)Marshal.PtrToStructure(record_ptr, typeof(NamingRecord));
record_ptr = Increment(record_ptr, Marshal.SizeOf(name_rec));
name_rec.PlatformID = SwapUInt16(name_rec.PlatformID);
name_rec.EncodingID = SwapUInt16(name_rec.EncodingID);
name_rec.LanguageID = SwapUInt16(name_rec.LanguageID);
name_rec.NameID = SwapUInt16(name_rec.NameID);
name_rec.Length = SwapUInt16(name_rec.Length);
name_rec.Offset = SwapUInt16(name_rec.Offset);
if (((name_rec.PlatformID == 3 && name_rec.EncodingID == 1) || name_rec.PlatformID == 0) &&
(NameID)name_rec.NameID == Index)
{
byte[] Temp = new byte[name_rec.Length];
IntPtr string_ptr = Increment(string_storage_ptr, name_rec.Offset);
Marshal.Copy(string_ptr, Temp, 0, (int)Temp.Length);
return Encoding.GetEncoding(1201).GetString(Temp);
}
}
#if !DEBUG_TABLE
record_ptr = namerecord_ptr;
for (int i = 0; i < name_header.Count; i++)
{
NamingRecord name_rec = (NamingRecord)Marshal.PtrToStructure(record_ptr, typeof(NamingRecord));
record_ptr = Increment(record_ptr, Marshal.SizeOf(name_rec));
name_rec.PlatformID = SwapUInt16(name_rec.PlatformID);
name_rec.EncodingID = SwapUInt16(name_rec.EncodingID);
name_rec.LanguageID = SwapUInt16(name_rec.LanguageID);
name_rec.NameID = SwapUInt16(name_rec.NameID);
name_rec.Length = SwapUInt16(name_rec.Length);
name_rec.Offset = SwapUInt16(name_rec.Offset);
if ((NameID)name_rec.NameID == Index)
{
continue;
}
}
#endif
return null;
#endif
}
}
public NameTableClass(TrueTypeTable src) : base(src) { }
}
}
#pragma warning restore