//------------------------------------------------------------------------------------------xx.02.2005 /// <summary>Reads the table "hmtx" (glyph widths).</summary> /// <remarks>The glyph widths are normalized to 1000 units.</remarks> /// <param name="openTypeReader">Open Type Reader</param> private void ReadTable_hmtx(OpenTypeReader openTypeReader) { aiGlyphWidth = new Int32[horizontalHeader.iNumberOfHMetrics]; TableDirectory tableDirectory = dict_TableDirectory["hmtx"]; openTypeReader.Seek(tableDirectory.iOffset); for (Int32 i = 0; i < aiGlyphWidth.Length; i++) { Int32 iWidth = openTypeReader.iReadUSHORT(); aiGlyphWidth[i] = iWidth; openTypeReader.iReadUSHORT(); // left side bearing } }
//------------------------------------------------------------------------------------------16.02.2005 #region Table "name" //---------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------xx.02.2005 /// <summary>Reads the table "name".</summary> /// <param name="openTypeReader">Open Type Reader</param> private void ReadTable_name(OpenTypeReader openTypeReader) { TableDirectory tableDirectory = dict_TableDirectory["name"]; openTypeReader.Seek(tableDirectory.iOffset + 2); Int32 iNumberOfRecords = openTypeReader.iReadUSHORT(); Int32 iStringOffset = openTypeReader.iReadUSHORT(); for (Int32 i = 0; i < iNumberOfRecords; i++) { openTypeReader.Seek(tableDirectory.iOffset + 6 + i * 12); Int32 iPlatformId = openTypeReader.iReadUSHORT(); Int32 iEncodingId = openTypeReader.iReadUSHORT(); Int32 iLanguageId = openTypeReader.iReadUSHORT(); Int32 iNameId = openTypeReader.iReadUSHORT(); Int32 iLength = openTypeReader.iReadUSHORT(); Int32 iOffset = openTypeReader.iReadUSHORT(); if (iNameId == 4) { openTypeReader.Seek(tableDirectory.iOffset + iStringOffset + iOffset); String sName; if (iPlatformId == 0 || (iPlatformId == 2 && iEncodingId == 1) || iPlatformId == 3) { sName = openTypeReader.sReadUnicodeString(iLength); } else { sName = openTypeReader.sReadCHAR(iLength); } sName = sName.Replace(Environment.NewLine, ";"); //Console.WriteLine(iPlatformId + "\t" + iEncodingId + "\t" + iLanguageId + "\t" + iNameId + "\t" + sName); sFullFontName = sName.Replace(' ', '_'); } else if (iNameId == 6) { openTypeReader.Seek(tableDirectory.iOffset + iStringOffset + iOffset); if (iPlatformId == 0 || iPlatformId == 3) { sBaseFontName = openTypeReader.sReadUnicodeString(iLength); } else { sBaseFontName = openTypeReader.sReadCHAR(iLength); } } } }
/// <summary>Creates the type 1 font data object.</summary> /// <param name="stream">AFM definition stream</param> /// <param name="style">Font style</param> /// <param name="bEmbedded"><see langword="true"/> if the font must be embedded in the PDF file</param> internal OpenTypeFontData(FontDef fontDef, FontStyle fontStyle) : base(fontDef, fontStyle, FontData.Encoding.Cp1252) { this.fontDef = fontDef; RegistryKey registryKey_CurrentVersion = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); if (registryKey_CurrentVersion == null) { throw new ReportException("Cannot find the directory of the font files"); } String sSystemRoot = (String)registryKey_CurrentVersion.GetValue("SystemRoot"); RegistryKey registryKey_Font = registryKey_CurrentVersion.OpenSubKey(@"Fonts"); if (registryKey_Font == null) { throw new ReportException("Cannot find the definition of the font"); } String sFontFileName = (String)registryKey_Font.GetValue(fontDef.sFontName + " (TrueType)"); String s = sFontFileName.ToLower(); if (s.EndsWith(".ttc")) { bTrueTypeCollection = true; } else if (!(s.EndsWith(".ttf") || s.EndsWith(".otf"))) { throw new ReportException("'" + fontDef.sFontName + "' is not a TTF, OTF or TTC font."); } sFontFileName = Path.Combine(sSystemRoot, @"Fonts\" + sFontFileName); using (OpenTypeReader openTypeReader = new OpenTypeReader(sFontFileName)) { ReadFontDataFromFile(openTypeReader); } }
//------------------------------------------------------------------------------------------xx.02.2005 /// <summary>Reads the font data from the file.</summary> /// <param name="openTypeReader">Open Type Reader</param> private void ReadFontDataFromFile(OpenTypeReader openTypeReader) { #region TrueType Collection if (bTrueTypeCollection) { String sTTCTag = openTypeReader.sReadTag(); if (sTTCTag != "ttcf") { throw new ReportException("'" + sFontName + " is not a valid TTC font file."); } UInt32 uVersion = openTypeReader.uReadULONG(); Int32 iNumFonts = (Int32)openTypeReader.uReadULONG(); if (iTrueTypeCollectionIndex >= iNumFonts) { throw new ReportException("'" + sFontName + " has invalid TrueType collection index."); } openTypeReader.Skip(iTrueTypeCollectionIndex * 4); Int32 iOffset = (Int32)openTypeReader.uReadULONG(); openTypeReader.Seek(iOffset); } #endregion #region Offset Table UInt32 uSfntVersion = openTypeReader.uReadULONG(); if (uSfntVersion == 0x4F54544F /* 'OTTO' */) { fontDataType = FontDataType.CFFdata; } #if DEBUG else if (uSfntVersion == 0x00010000 /* Version 1.0 */) { fontDataType = FontDataType.TrueTypeOutlines; } else { throw new ReportException("'" + sFontName + " is not a valid TTF, OTF or TTC font file."); } #endif iNumTables = (Int32)openTypeReader.iReadUSHORT(); iSearchRange = (Int32)openTypeReader.iReadUSHORT(); iEntrySelector = (Int32)openTypeReader.iReadUSHORT(); iRangeShift = (Int32)openTypeReader.iReadUSHORT(); #endregion #region Table Directory for (Int32 iTable = 0; iTable < iNumTables; iTable++) { TableDirectory tableDirectory_New = new TableDirectory(); tableDirectory_New.sTag = openTypeReader.sReadTag(); tableDirectory_New.uCheckSum = openTypeReader.uReadULONG(); tableDirectory_New.iOffset = (Int32)openTypeReader.uReadULONG(); tableDirectory_New.iLength = (Int32)openTypeReader.uReadULONG(); dict_TableDirectory.Add(tableDirectory_New.sTag, tableDirectory_New); } Boolean bCFF = dict_TableDirectory.ContainsKey("CFF"); if ((bCFF && fontDataType == FontDataType.TrueTypeOutlines) || (!bCFF && fontDataType == FontDataType.CFFdata)) { throw new ReportException("'" + sFontName + " is not a valid TTC font file."); } #endregion #region Font Header TableDirectory tableDirectory = dict_TableDirectory["head"]; fontHeader = new FontHeader(); openTypeReader.Seek(tableDirectory.iOffset); fontHeader.uTableVersionNumber = openTypeReader.uReadULONG(); Debug.Assert(fontHeader.uTableVersionNumber == 0x00010000 /* Version 1.0 */); openTypeReader.Skip(12); fontHeader.iFlags = openTypeReader.iReadUSHORT(); fontHeader.iUnitsPerEm = openTypeReader.iReadUSHORT(); openTypeReader.Skip(16); fontHeader.iXMin = openTypeReader.int16_ReadSHORT(); fontHeader.iYMin = openTypeReader.int16_ReadSHORT(); fontHeader.iXMax = openTypeReader.int16_ReadSHORT(); fontHeader.iYMax = openTypeReader.int16_ReadSHORT(); fontHeader.iMacStyle = openTypeReader.iReadUSHORT(); fontHeader.iLowestRecPPEM = openTypeReader.iReadUSHORT(); fontHeader.iFontDirectionHint = openTypeReader.int16_ReadSHORT(); fontHeader.iIndexToLocFormat = openTypeReader.int16_ReadSHORT(); fontHeader.iGlyphDataFormat = openTypeReader.int16_ReadSHORT(); #endregion #region Horizontal Header tableDirectory = dict_TableDirectory["hhea"]; horizontalHeader = new HorizontalHeader(); openTypeReader.Seek(tableDirectory.iOffset); horizontalHeader.uTableVersionNumber = openTypeReader.uReadULONG(); Debug.Assert(horizontalHeader.uTableVersionNumber == 0x00010000 /* Version 1.0 */); horizontalHeader.iAscender = openTypeReader.int16_ReadFWORD(); horizontalHeader.iDescender = openTypeReader.int16_ReadFWORD(); horizontalHeader.iLineGap = openTypeReader.int16_ReadFWORD(); horizontalHeader.iAdvanceWidthMax = openTypeReader.iReadUFWORD(); horizontalHeader.iMinLeftSideBearing = openTypeReader.int16_ReadFWORD(); horizontalHeader.iMinRightSideBearing = openTypeReader.int16_ReadFWORD(); horizontalHeader.iXMaxExtent = openTypeReader.int16_ReadFWORD(); horizontalHeader.iCaretSlopeRise = openTypeReader.int16_ReadSHORT(); horizontalHeader.iCaretSlopeRun = openTypeReader.int16_ReadSHORT(); horizontalHeader.iCaretOffset = openTypeReader.int16_ReadSHORT(); openTypeReader.Skip(10); horizontalHeader.iNumberOfHMetrics = openTypeReader.iReadUSHORT(); #endregion #region Windows Metrics (OS/2) tableDirectory = dict_TableDirectory["OS/2"]; winMetrics = new WinMetrics(); openTypeReader.Seek(tableDirectory.iOffset); winMetrics.iVersion = openTypeReader.iReadUSHORT(); winMetrics.iXAvgCharWidth = openTypeReader.int16_ReadSHORT(); winMetrics.iUsWeightClass = openTypeReader.iReadUSHORT(); winMetrics.iUsWidthClass = openTypeReader.iReadUSHORT(); winMetrics.iFsType = openTypeReader.iReadUSHORT(); winMetrics.iYSubscriptXSize = openTypeReader.int16_ReadSHORT(); winMetrics.iYSubscriptYSize = openTypeReader.int16_ReadSHORT(); winMetrics.iYSubscriptXOffset = openTypeReader.int16_ReadSHORT(); winMetrics.iYSubscriptYOffset = openTypeReader.int16_ReadSHORT(); winMetrics.iYSuperscriptXSize = openTypeReader.int16_ReadSHORT(); winMetrics.iYSuperscriptYSize = openTypeReader.int16_ReadSHORT(); winMetrics.iYSuperscriptXOffset = openTypeReader.int16_ReadSHORT(); winMetrics.iYSuperscriptYOffset = openTypeReader.int16_ReadSHORT(); winMetrics.iYStrikeoutSize = openTypeReader.int16_ReadSHORT(); winMetrics.iYStrikeoutPosition = openTypeReader.int16_ReadSHORT(); winMetrics.iSFamilyClass = openTypeReader.int16_ReadSHORT(); winMetrics.aByte_Panose = openTypeReader.aByte_ReadBYTE(10); if (winMetrics.iVersion == 0) { openTypeReader.Skip(4); // skip ulCharRange } else { winMetrics.uUlUnicodeRange1 = openTypeReader.uReadULONG(); winMetrics.uUlUnicodeRange2 = openTypeReader.uReadULONG(); winMetrics.uUlUnicodeRange3 = openTypeReader.uReadULONG(); winMetrics.uUlUnicodeRange4 = openTypeReader.uReadULONG(); } winMetrics.sAchVendID = openTypeReader.sReadTag(); winMetrics.iFsSelection = openTypeReader.iReadUSHORT(); winMetrics.iUsFirstCharIndex = openTypeReader.iReadUSHORT(); winMetrics.iUsLastCharIndex = openTypeReader.iReadUSHORT(); winMetrics.iSTypoAscender = openTypeReader.int16_ReadSHORT(); winMetrics.iSTypoDescender = openTypeReader.int16_ReadSHORT(); winMetrics.iSTypoLineGap = openTypeReader.int16_ReadSHORT(); winMetrics.iUsWinAscent = openTypeReader.iReadUSHORT(); winMetrics.iUsWinDescent = openTypeReader.iReadUSHORT(); if (winMetrics.iVersion > 0) { winMetrics.iUlCodePageRange1 = openTypeReader.uReadULONG(); winMetrics.iUlCodePageRange2 = openTypeReader.uReadULONG(); if (winMetrics.iVersion > 1) { winMetrics.iSXHeight = openTypeReader.int16_ReadSHORT(); winMetrics.iSCapHeight = openTypeReader.int16_ReadSHORT(); winMetrics.uUsDefaultChar = openTypeReader.uReadULONG(); winMetrics.uUsBreakChar = openTypeReader.uReadULONG(); winMetrics.uUsMaxContext = openTypeReader.uReadULONG(); } } #endregion #region Post tableDirectory = dict_TableDirectory["post"]; openTypeReader.Seek(tableDirectory.iOffset + 4); Double r1 = openTypeReader.int16_ReadSHORT(); Double r0 = openTypeReader.iReadUSHORT(); rItalicAngle = r1 + r0 / 16384.0; iUnderlinePosition = openTypeReader.int16_ReadFWORD(); iUnderlineThickness = openTypeReader.int16_ReadFWORD(); bFixedPitch = (openTypeReader.uReadULONG() != 0); #endregion ReadTable_name(openTypeReader); ReadTable_hmtx(openTypeReader); }