using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
#pragma warning disable CS3001, CS3002, CS3003, CS1591
namespace FastReport.Fonts
{
///
/// HorizontalMetrix table
///
public class HorizontalMetrixClass : TrueTypeTable
{
#region "Type definition"
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct longHorMetric
{
[FieldOffset(0)]
public ushort advanceWidth;
[FieldOffset(2)]
public short lsb;
};
#endregion
longHorMetric[] metrixTable;
short[] lsbExt;
public ushort numberOfMetrics;
public longHorMetric this[int index]
{
get
{
// Microsoft say: "If the font is monospaced, only one entry need be in the array, but that entry is required"
if (index >= metrixTable.Length) index = 0;
return metrixTable[index];
}
}
public void RepackWithDictionary(ref Dictionary dict, int source_glyph_count)
{
longHorMetric[] metrix = new longHorMetric[dict.Count];
ushort[] lsb = new ushort[source_glyph_count - metrixTable.Length];
int i = 0;
foreach( ushort key in dict.Keys)
{
GlyphChar gc = dict[key];
if (key < metrixTable.Length)
{
metrix[gc.Glyph] = metrixTable[key];
}
else
{
// TODO: Correct LSB
throw new Exception("Check me in RepackWithDictionary");
// short lsb = lsbExt[key];
}
}
metrixTable = metrix;
numberOfMetrics =(ushort) metrix.Length;
}
internal override void Load(IntPtr font)
{
metrixTable = new longHorMetric[numberOfMetrics];
IntPtr h_metrix_ptr = Increment(font, (int)this.Offset);
for (int i = 0; i < numberOfMetrics; i++)
{
metrixTable[i] = (longHorMetric)Marshal.PtrToStructure(h_metrix_ptr, typeof(longHorMetric));
metrixTable[i].advanceWidth = SwapUInt16(metrixTable[i].advanceWidth);
metrixTable[i].lsb = SwapInt16(metrixTable[i].lsb);
h_metrix_ptr = Increment(h_metrix_ptr, 4);
}
// Magic of calculation of leftSideBearings items count
int lsbCount = ((int)this.Length - (numberOfMetrics * 4)) / 2;
if (lsbCount == 0)
lsbExt = null;
else
{
lsbExt = new short[lsbCount];
for (int i = 0; i < lsbCount; i++)
{
lsbExt[i] = Marshal.ReadInt16(h_metrix_ptr, i * 2);
}
}
}
internal override uint Save(IntPtr font, uint offset)
{
this.Offset = offset;
IntPtr horizontal_header_ptr = Increment(font, (int)offset);
IntPtr h_metrix_ptr = Increment(font, (int)offset);
for (int i = 0; i < numberOfMetrics; i++)
{
longHorMetric rec;
rec.advanceWidth = SwapUInt16(metrixTable[i].advanceWidth);
rec.lsb = SwapInt16(metrixTable[i].lsb);
Marshal.StructureToPtr(rec, h_metrix_ptr, false);
h_metrix_ptr = Increment(h_metrix_ptr, 4);
}
uint lsb_size = 0;
if(lsbExt != null)
{
for (int j = 0; j < lsbExt.Length; j++)
{
Marshal.WriteInt16(h_metrix_ptr, j * 2, lsbExt[j]);
}
lsb_size = ((uint)lsbExt.Length * 2);
lsb_size = ((lsb_size + 3) / 4) * 4;
}
uint len = (uint)numberOfMetrics * 4 + lsb_size;
SetLenght(len);
return offset + len;
}
internal override uint Save(IntPtr src, IntPtr dst, uint offset)
{
return base.Save(src, dst, offset);
}
public HorizontalMetrixClass(TrueTypeTable src)
: base(src)
{
}
}
}
#pragma warning restore