using System; using System.Runtime.InteropServices; namespace FastReport.Fonts { /// /// OS/2 and Windows Metrics table /// public class OS2WindowsMetricsClass : TrueTypeTable { #region "Type definition" /// /// Description of FontTextMetric structure /// [StructLayout(LayoutKind.Sequential)] public struct FontTextMetric { public int tmHeight; public int tmAscent; public int tmDescent; public int tmInternalLeading; public int tmExternalLeading; public int tmAveCharWidth; public int tmMaxCharWidth; public int tmWeight; public int tmOverhang; public int tmDigitizedAspectX; public int tmDigitizedAspectY; public char tmFirstChar; public char tmLastChar; public char tmDefaultChar; public char tmBreakChar; public byte tmItalic; public byte tmUnderlined; public byte tmStruckOut; public byte tmPitchAndFamily; public byte tmCharSet; } /// /// Description of FontPanose structure /// [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct FontPanose { public byte bFamilyType; public byte bSerifStyle; public byte bWeight; public byte bProportion; public byte bContrast; public byte bStrokeVariation; public byte ArmStyle; public byte bLetterform; public byte bMidline; public byte bXHeight; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct OS2WindowsMetrics { public ushort Version; // version number 0x0004 public short xAvgCharWidth; public ushort usWeightClass; public ushort usWidthClass; public ushort fsType; public short ySubscriptXSize; public short ySubscriptYSize; public short ySubscriptXOffset; public short ySubscriptYOffset; public short ySuperscriptXSize; public short ySuperscriptYSize; public short ySuperscriptXOffset; public short ySuperscriptYOffset; public short yStrikeoutSize; public short yStrikeoutPosition; public short sFamilyClass; #if false [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] panose; // = new byte[10]; #else public FontPanose panose; #endif public uint ulUnicodeRange1; public uint ulUnicodeRange2; public uint ulUnicodeRange3; public uint ulUnicodeRange4; #if true public byte achVendID1; public byte achVendID2; public byte achVendID3; public byte achVendID4; #else [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] achVendID; // = new vyte[4]; #endif public ushort fsSelection; public ushort usFirstCharIndex; public ushort usLastCharIndex; public short sTypoAscender; public short sTypoDescender; public short sTypoLineGap; public ushort usWinAscent; public ushort usWinDescent; public uint ulCodePageRange1; public uint ulCodePageRange2; public short sxHeight; public short sCapHeight; public ushort usDefaultChar; public ushort usBreakChar; public ushort usMaxContext; } #endregion internal OS2WindowsMetrics win_metrix; internal override void Load(FontStream stream) { stream.Position = this.Offset; win_metrix.Version = stream.ReadUInt16(); // version number 0x0004 //public short win_metrix.xAvgCharWidth = stream.ReadInt16(); win_metrix.usWeightClass = stream.ReadUInt16(); win_metrix.usWidthClass = stream.ReadUInt16(); win_metrix.fsType = stream.ReadUInt16(); win_metrix.ySubscriptXSize = stream.ReadInt16(); win_metrix.ySubscriptYSize = stream.ReadInt16(); win_metrix.ySubscriptXOffset = stream.ReadInt16(); win_metrix.ySubscriptYOffset = stream.ReadInt16(); win_metrix.ySuperscriptXSize = stream.ReadInt16(); win_metrix.ySuperscriptYSize = stream.ReadInt16(); win_metrix.ySuperscriptXOffset = stream.ReadInt16(); win_metrix.ySuperscriptYOffset = stream.ReadInt16(); win_metrix.yStrikeoutSize = stream.ReadInt16(); win_metrix.yStrikeoutPosition = stream.ReadInt16(); win_metrix.sFamilyClass = stream.ReadInt16(); //FontPanose win_metrix.panose.bFamilyType = stream.ReadByte(); win_metrix.panose.bSerifStyle = stream.ReadByte(); win_metrix.panose.bWeight = stream.ReadByte(); win_metrix.panose.bProportion = stream.ReadByte(); win_metrix.panose.bContrast = stream.ReadByte(); win_metrix.panose.bStrokeVariation = stream.ReadByte(); win_metrix.panose.ArmStyle = stream.ReadByte(); win_metrix.panose.bLetterform = stream.ReadByte(); win_metrix.panose.bMidline = stream.ReadByte(); win_metrix.panose.bXHeight = stream.ReadByte(); win_metrix.ulUnicodeRange1 = stream.ReadUInt32(); win_metrix.ulUnicodeRange2 = stream.ReadUInt32(); win_metrix.ulUnicodeRange3 = stream.ReadUInt32(); win_metrix.ulUnicodeRange4 = stream.ReadUInt32(); win_metrix.achVendID1 = stream.ReadByte(); win_metrix.achVendID2 = stream.ReadByte(); win_metrix.achVendID3 = stream.ReadByte(); win_metrix.achVendID4 = stream.ReadByte(); win_metrix.fsSelection = stream.ReadUInt16(); win_metrix.usFirstCharIndex = stream.ReadUInt16(); win_metrix.usLastCharIndex = stream.ReadUInt16(); win_metrix.sTypoAscender = stream.ReadInt16(); win_metrix.sTypoDescender = stream.ReadInt16(); win_metrix.sTypoLineGap = stream.ReadInt16(); win_metrix.usWinAscent = stream.ReadUInt16(); win_metrix.usWinDescent = stream.ReadUInt16(); win_metrix.ulCodePageRange1 = stream.ReadUInt32(); win_metrix.ulCodePageRange2 = stream.ReadUInt32(); win_metrix.sxHeight = stream.ReadInt16(); win_metrix.sCapHeight = stream.ReadInt16(); win_metrix.usDefaultChar = stream.ReadUInt16(); win_metrix.usBreakChar = stream.ReadUInt16(); win_metrix.usMaxContext = stream.ReadUInt16(); } internal override uint Save(FontStream source_not_used, FontStream stream, uint offset) { stream.Position = offset; stream.WriteUInt16(win_metrix.Version); // version number 0x0004 stream.WriteInt16(win_metrix.xAvgCharWidth); stream.WriteUInt16(win_metrix.usWeightClass); stream.WriteUInt16(win_metrix.usWidthClass); stream.WriteUInt16(win_metrix.fsType); stream.WriteInt16(win_metrix.ySubscriptXSize); stream.WriteInt16(win_metrix.ySubscriptYSize); stream.WriteInt16(win_metrix.ySubscriptXOffset); stream.WriteInt16(win_metrix.ySubscriptYOffset); stream.WriteInt16(win_metrix.ySuperscriptXSize); stream.WriteInt16(win_metrix.ySuperscriptYSize); stream.WriteInt16(win_metrix.ySuperscriptXOffset); stream.WriteInt16(win_metrix.ySuperscriptYOffset); stream.WriteInt16(win_metrix.yStrikeoutSize); stream.WriteInt16(win_metrix.yStrikeoutPosition); stream.WriteInt16(win_metrix.sFamilyClass); stream.WriteByte(win_metrix.panose.bFamilyType); stream.WriteByte(win_metrix.panose.bSerifStyle); stream.WriteByte(win_metrix.panose.bWeight); stream.WriteByte(win_metrix.panose.bProportion); stream.WriteByte(win_metrix.panose.bContrast); stream.WriteByte(win_metrix.panose.bStrokeVariation); stream.WriteByte(win_metrix.panose.ArmStyle); stream.WriteByte(win_metrix.panose.bLetterform); stream.WriteByte(win_metrix.panose.bMidline); stream.WriteByte(win_metrix.panose.bXHeight); stream.WriteUInt32(win_metrix.ulUnicodeRange1); stream.WriteUInt32(win_metrix.ulUnicodeRange2); stream.WriteUInt32(win_metrix.ulUnicodeRange3); stream.WriteUInt32(win_metrix.ulUnicodeRange4); #if true stream.WriteByte(win_metrix.achVendID1); stream.WriteByte(win_metrix.achVendID2); stream.WriteByte(win_metrix.achVendID3); stream.WriteByte(win_metrix.achVendID4); #else [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] achVendID; // = new vyte[4]; #endif stream.WriteUInt16(win_metrix.fsSelection); stream.WriteUInt16(win_metrix.usFirstCharIndex); stream.WriteUInt16(win_metrix.usLastCharIndex); stream.WriteInt16(win_metrix.sTypoAscender); stream.WriteInt16(win_metrix.sTypoDescender); stream.WriteInt16(win_metrix.sTypoLineGap); stream.WriteUInt16(win_metrix.usWinAscent); stream.WriteUInt16(win_metrix.usWinDescent); stream.WriteUInt32(win_metrix.ulCodePageRange1); stream.WriteUInt32(win_metrix.ulCodePageRange2); stream.WriteInt16(win_metrix.sxHeight); stream.WriteInt16(win_metrix.sCapHeight); stream.WriteUInt16(win_metrix.usDefaultChar); stream.WriteUInt16(win_metrix.usBreakChar); stream.WriteUInt16(win_metrix.usMaxContext); offset = (offset + this.Length + 3) & 0xfffffffc; return offset; } // Public properties #pragma warning disable CS3001, CS3002, CS3003, CS1591 public bool IsBold { get { // return win_metrix.usWeightClass >= 700; return (win_metrix.fsSelection & 0x20) != 0; } } public ushort Ascent { get { return win_metrix.usWinAscent; } } public ushort Descent { get { return win_metrix.usWinDescent; } } public short LineGap { get { return win_metrix.sTypoLineGap; } } public short AvgCharWidth { get { return win_metrix.xAvgCharWidth; } } public ushort Weight { get { return win_metrix.usWeightClass; } } public ushort WidthClass { get { return win_metrix.usWidthClass; } } public short Height { get { return win_metrix.sxHeight; } } public ushort BreakChar { get { return win_metrix.usBreakChar; } } public ushort DefaultChar { get { return win_metrix.usDefaultChar; } } public ushort FirstCharIndex { get { return win_metrix.usFirstCharIndex; } } public ushort LastCharIndex { get { return win_metrix.usLastCharIndex; } } public ushort LicensingRights { get { return win_metrix.fsType; } } public OS2WindowsMetricsClass.FontPanose Panose { get { return win_metrix.panose; } } public OS2WindowsMetricsClass(TrueTypeTable src) : base(src) { } public uint UnicodeRange1 { get { return win_metrix.ulUnicodeRange1; } } public uint UnicodeRange2 { get { return win_metrix.ulUnicodeRange2; } } public uint UnicodeRange3 { get { return win_metrix.ulUnicodeRange3; } } public uint UnicodeRange4 { get { return win_metrix.ulUnicodeRange4; } } public short FamilyClass { get { return win_metrix.sFamilyClass; } } public ushort Selection { get { return win_metrix.fsSelection; } } public uint CodepageRange1 { get { return win_metrix.ulCodePageRange1; } } public uint CodepageRange2 { get { return win_metrix.ulCodePageRange2; } } public string VendorID { get { return "" + (char)win_metrix.achVendID1 + (char)win_metrix.achVendID2 + (char)win_metrix.achVendID3 + (char)win_metrix.achVendID4; } } #pragma warning restore } }