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