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(FontStream stream)
{
metrixTable = new longHorMetric[numberOfMetrics];
stream.Position = this.Offset;
for (int i = 0; i < numberOfMetrics; i++)
{
metrixTable[i].advanceWidth = stream.ReadUInt16();
metrixTable[i].lsb = stream.ReadInt16();
}
// 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] = stream.ReadInt16();
}
}
}
internal override uint Save(FontStream source_not_used, FontStream stream, uint offset)
{
//this.Offset = offset;
//IntPtr horizontal_header_ptr = Increment(font, (int)offset);
stream.Position = offset;
// IntPtr h_metrix_ptr = Increment(font, (int)offset);
for (int i = 0; i < numberOfMetrics; i++)
{
longHorMetric rec;
//rec.advanceWidth =
stream.WriteUInt16(this.metrixTable[i].advanceWidth); // SwapUInt16(metrixTable[i].advanceWidth);
// rec.lsb =
stream.WriteInt16(this.metrixTable[i].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]);
stream.WriteInt16(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;
}
public HorizontalMetrixClass(TrueTypeTable src)
: base(src)
{
}
}
}
//#pragma warning restore