internal PreviewFontInfo ReadPreviewFontInfo(TableEntryCollection tables, BinaryReader input) { var rd = new EntriesReaderHelper(tables, input); NameEntry nameEntry = rd.Read(new NameEntry()); OS2Table os2Table = rd.Read(new OS2Table()); //for preview, read ONLY script list from gsub and gpos (set OnlyScriptList). Meta metaTable = rd.Read(new Meta()); GSUB gsub = rd.Read(new GSUB() { OnlyScriptList = true }); GPOS gpos = rd.Read(new GPOS() { OnlyScriptList = true }); Cmap cmap = rd.Read(new Cmap()); //gsub and gpos contains actual script_list that are in the typeface Languages langs = new Languages(); langs.Update(os2Table, metaTable, cmap, gsub, gpos); return(new PreviewFontInfo( nameEntry, os2Table, langs)); }
internal Typeface ReadTableEntryCollection(TableEntryCollection tables, BinaryReader input) { OS2Table os2Table = ReadTableIfExists(tables, input, new OS2Table()); NameEntry nameEntry = ReadTableIfExists(tables, input, new NameEntry()); Head header = ReadTableIfExists(tables, input, new Head()); MaxProfile maximumProfile = ReadTableIfExists(tables, input, new MaxProfile()); HorizontalHeader horizontalHeader = ReadTableIfExists(tables, input, new HorizontalHeader()); HorizontalMetrics horizontalMetrics = ReadTableIfExists(tables, input, new HorizontalMetrics(horizontalHeader.HorizontalMetricsCount, maximumProfile.GlyphCount)); //--- PostTable postTable = ReadTableIfExists(tables, input, new PostTable()); CFFTable ccf = ReadTableIfExists(tables, input, new CFFTable()); //-------------- Cmap cmaps = ReadTableIfExists(tables, input, new Cmap()); GlyphLocations glyphLocations = ReadTableIfExists(tables, input, new GlyphLocations(maximumProfile.GlyphCount, header.WideGlyphLocations)); Glyf glyf = ReadTableIfExists(tables, input, new Glyf(glyphLocations)); //-------------- Gasp gaspTable = ReadTableIfExists(tables, input, new Gasp()); VerticalDeviceMetrics vdmx = ReadTableIfExists(tables, input, new VerticalDeviceMetrics()); //-------------- Kern kern = ReadTableIfExists(tables, input, new Kern()); //-------------- //advanced typography GDEF gdef = ReadTableIfExists(tables, input, new GDEF()); GSUB gsub = ReadTableIfExists(tables, input, new GSUB()); GPOS gpos = ReadTableIfExists(tables, input, new GPOS()); BASE baseTable = ReadTableIfExists(tables, input, new BASE()); COLR colr = ReadTableIfExists(tables, input, new COLR()); CPAL cpal = ReadTableIfExists(tables, input, new CPAL()); VerticalHeader vhea = ReadTableIfExists(tables, input, new VerticalHeader()); if (vhea != null) { VerticalMetrics vmtx = ReadTableIfExists(tables, input, new VerticalMetrics(vhea.NumOfLongVerMetrics)); } //test math table MathTable mathtable = ReadTableIfExists(tables, input, new MathTable()); EBLCTable fontBmpTable = ReadTableIfExists(tables, input, new EBLCTable()); //--------------------------------------------- //about truetype instruction init //--------------------------------------------- Typeface typeface = null; bool isPostScriptOutline = false; if (glyf == null) { //check if this is cff table ? if (ccf == null) { //TODO: review here throw new NotSupportedException(); } //... //PostScript outline font isPostScriptOutline = true; typeface = new Typeface( nameEntry, header.Bounds, header.UnitsPerEm, ccf, horizontalMetrics, os2Table); } else { typeface = new Typeface( nameEntry, header.Bounds, header.UnitsPerEm, glyf.Glyphs, horizontalMetrics, os2Table); } //---------------------------- typeface.CmapTable = cmaps; typeface.KernTable = kern; typeface.GaspTable = gaspTable; typeface.MaxProfile = maximumProfile; typeface.HheaTable = horizontalHeader; //---------------------------- if (!isPostScriptOutline) { FpgmTable fpgmTable = ReadTableIfExists(tables, input, new FpgmTable()); //control values table CvtTable cvtTable = ReadTableIfExists(tables, input, new CvtTable()); if (cvtTable != null) { typeface.ControlValues = cvtTable._controlValues; } if (fpgmTable != null) { typeface.FpgmProgramBuffer = fpgmTable._programBuffer; } PrepTable propProgramTable = ReadTableIfExists(tables, input, new PrepTable()); if (propProgramTable != null) { typeface.PrepProgramBuffer = propProgramTable._programBuffer; } } //------------------------- typeface.LoadOpenFontLayoutInfo( gdef, gsub, gpos, baseTable, colr, cpal); //------------ //test { SvgTable svgTable = ReadTableIfExists(tables, input, new SvgTable()); if (svgTable != null) { typeface._svgTable = svgTable; } } typeface.PostTable = postTable; if (mathtable != null) { var mathGlyphLoader = new MathGlyphLoader(); mathGlyphLoader.LoadMathGlyph(typeface, mathtable); } #if DEBUG //test //int found = typeface.GetGlyphIndexByName("Uacute"); if (typeface.IsCffFont) { //optional typeface.UpdateAllCffGlyphBounds(); } #endif return(typeface); }
public TtfTypeface Read(Stream stream, ReadFlags readFlags = ReadFlags.Full) { var little = BitConverter.IsLittleEndian; using (var input = new ByteOrderSwappingBinaryReader(stream)) { ushort majorVersion = input.ReadUInt16(); ushort minorVersion = input.ReadUInt16(); ushort tableCount = input.ReadUInt16(); ushort searchRange = input.ReadUInt16(); ushort entrySelector = input.ReadUInt16(); ushort rangeShift = input.ReadUInt16(); var tables = new TableEntryCollection(); for (int i = 0; i < tableCount; i++) { tables.AddEntry(new UnreadTableEntry(ReadTableHeader(input))); } //------------------------------------------------------------------ OS2Table os2Table = ReadTableIfExists(tables, input, new OS2Table()); NameEntry nameEntry = ReadTableIfExists(tables, input, new NameEntry()); Head header = ReadTableIfExists(tables, input, new Head()); MaxProfile maximumProfile = ReadTableIfExists(tables, input, new MaxProfile()); HorizontalHeader horizontalHeader = ReadTableIfExists(tables, input, new HorizontalHeader()); HorizontalMetrics horizontalMetrics = ReadTableIfExists(tables, input, new HorizontalMetrics(horizontalHeader.HorizontalMetricsCount, maximumProfile.GlyphCount)); //-------------- Cmap cmaps = ReadTableIfExists(tables, input, new Cmap()); GlyphLocations glyphLocations = ReadTableIfExists(tables, input, new GlyphLocations(maximumProfile.GlyphCount, header.WideGlyphLocations)); Glyf glyf = ReadTableIfExists(tables, input, new Glyf(glyphLocations)); //-------------- Gasp gaspTable = ReadTableIfExists(tables, input, new Gasp()); VerticalDeviceMetrics vdmx = ReadTableIfExists(tables, input, new VerticalDeviceMetrics()); //-------------- PostTable postTable = ReadTableIfExists(tables, input, new PostTable()); Kern kern = ReadTableIfExists(tables, input, new Kern()); //-------------- //advanced typography GDEF gdef = ReadTableIfExists(tables, input, new GDEF()); GSUB gsub = ReadTableIfExists(tables, input, new GSUB()); GPOS gpos = ReadTableIfExists(tables, input, new GPOS()); BASE baseTable = ReadTableIfExists(tables, input, new BASE()); COLR colr = ReadTableIfExists(tables, input, new COLR()); CPAL cpal = ReadTableIfExists(tables, input, new CPAL()); VerticalHeader vhea = ReadTableIfExists(tables, input, new VerticalHeader()); if (vhea != null) { VerticalMatric vmtx = ReadTableIfExists(tables, input, new VerticalMatric(vhea.NumOfLongVerMetrics)); } EBLCTable fontBmpTable = ReadTableIfExists(tables, input, new EBLCTable()); //--------------------------------------------- //about truetype instruction init //--------------------------------------------- var typeface = new TtfTypeface( nameEntry, header.Bounds, header.UnitsPerEm, glyf.Glyphs, horizontalMetrics, os2Table); //---------------------------- typeface.CmapTable = cmaps; typeface.KernTable = kern; typeface.GaspTable = gaspTable; typeface.MaxProfile = maximumProfile; typeface.HheaTable = horizontalHeader; //---------------------------- FpgmTable fpgmTable = ReadTableIfExists(tables, input, new FpgmTable()); //control values table CvtTable cvtTable = ReadTableIfExists(tables, input, new CvtTable()); if (cvtTable != null) { typeface.ControlValues = cvtTable.controlValues; } if (fpgmTable != null) { typeface.FpgmProgramBuffer = fpgmTable.programBuffer; } PrepTable propProgramTable = ReadTableIfExists(tables, input, new PrepTable()); if (propProgramTable != null) { typeface.PrepProgramBuffer = propProgramTable.programBuffer; } //------------------------- typeface.LoadOpenFontLayoutInfo( gdef, gsub, gpos, baseTable, colr, cpal); return(typeface); } }
/// <summary> /// 显示各种Header信息,并返回字符Image的数据 /// </summary> /// <param name="byteData"></param> private byte[] SetHeadersInfo(byte[] byData) { try { #region " 读取Rfnt Header " // 先读取Rfnt Header Array.Copy(byData, 0, byRfntHeader, 0, byRfntHeader.Length); this.rfntHeader.FileMagic = Util.GetHeaderString(byData, 0, 3); this.rfntHeader.Endianess = Util.GetBytesString(byData, 0x4, 0x5); this.rfntHeader.VersionMinor = Util.GetBytesString(byData, 0x6, 0x7); this.rfntHeader.LengthOfFileInBytes = Util.GetOffset(byData, 0x8, 0xb); this.rfntHeader.OffsetToFinfHeader = Util.GetOffset(byData, 0xc, 0xd); this.rfntHeader.NumberOfSections = Util.GetOffset(byData, 0xe, 0xf); #endregion #region " 获取FINF Section信息 " // 获取FINF Section信息 Array.Copy(byData, this.rfntHeader.OffsetToFinfHeader, byPinfHeader, 0, byPinfHeader.Length); // 获取FINF Section中相关信息 this.finfHeader.Magic = Util.GetHeaderString(byPinfHeader, 0, 3); this.finfHeader.LengthOfSectionInBytes = Util.GetOffset(byPinfHeader, 0x4, 0x7); this.finfHeader.Fonttype = Util.GetBytesString(byPinfHeader, 0x8, 0x8); this.finfHeader.Leading = Util.GetBytesString(byPinfHeader, 0x9, 0x9); this.finfHeader.Leftmargin = Util.GetOffset(byPinfHeader, 0xc, 0xc); this.finfHeader.CharWidth = Util.GetOffset(byPinfHeader, 0xd, 0xd); this.finfHeader.FullWidth = Util.GetOffset(byPinfHeader, 0xe, 0xe); this.finfHeader.Encoding = Util.GetOffset(byPinfHeader, 0xf, 0xf); this.finfHeader.DefaultChar = Util.GetStrFromNumber(Util.GetOffset(byPinfHeader, 0xa, 0xb), this.finfHeader.Encoding, this.rfntHeader.Endianess); this.finfHeader.TglpDataOffset = Util.GetOffset(byPinfHeader, 0x10, 0x13); this.finfHeader.CwdhDataOffset = Util.GetOffset(byPinfHeader, 0x14, 0x17); this.finfHeader.CMapDataOffset = Util.GetOffset(byPinfHeader, 0x18, 0x1b); this.finfHeader.Height = Util.GetOffset(byPinfHeader, 0x1c, 0x1c); this.finfHeader.Width = Util.GetOffset(byPinfHeader, 0x1d, 0x1d); #endregion #region " 获取TGLP Header的字节信息 " // 获取TGLP Header的字节信息 Array.Copy(byData, this.finfHeader.TglpDataOffset - 8, byTgplHeader, 0, byTgplHeader.Length); // 获取TGLP Header的具体信息 this.tglpHeader.Magic = Util.GetHeaderString(byTgplHeader, 0, 3); this.tglpHeader.LengthOfSection = Util.GetOffset(byTgplHeader, 0x4, 0x7); this.tglpHeader.CellWidth = Util.GetOffset(byTgplHeader, 0x8, 0x8); this.tglpHeader.CellHeight = Util.GetOffset(byTgplHeader, 0x9, 0x9); this.tglpHeader.FontCharacterWidth = Util.GetOffset(byTgplHeader, 0xa, 0xa); this.tglpHeader.FontCharacterHeight = Util.GetOffset(byTgplHeader, 0xb, 0xb); this.tglpHeader.TextureSize = Util.GetOffset(byTgplHeader, 0xc, 0xf); this.tglpHeader.TextureNum = Util.GetOffset(byTgplHeader, 0x10, 0x11); this.tglpHeader.ImageFormat = Util.GetImageFormat(Util.GetOffset(byTgplHeader, 0x12, 0x13)); this.tglpHeader.CharactersPerRow = Util.GetOffset(byTgplHeader, 0x14, 0x15); this.tglpHeader.CharactersPerColumn = Util.GetOffset(byTgplHeader, 0x16, 0x17); this.tglpHeader.ImageWidth = Util.GetOffset(byTgplHeader, 0x18, 0x19); this.tglpHeader.ImageHeight = Util.GetOffset(byTgplHeader, 0x1a, 0x1b); this.tglpHeader.PositionOfData = Util.GetOffset(byTgplHeader, 0x1c, 0x1f); #endregion #region " 取得TGLP Data信息 " // 取得TGLP Data信息 byte[] byteTglpData = new byte[tglpHeader.LengthOfSection - 48]; Array.Copy(byData, tglpHeader.PositionOfData, byteTglpData, 0, byteTglpData.Length); #endregion #region " 取得CWDH Section信息 " // 取得CWDH Section信息 this.cwdhSection = new CwdhSection(); Array.Copy(byData, this.finfHeader.CwdhDataOffset - 8, byteCwdhSection, 0, byteCwdhSection.Length); this.cwdhSection.Magic = Util.GetHeaderString(byteCwdhSection, 0, 3); this.cwdhSection.LengthOfSection = Util.GetOffset(byteCwdhSection, 4, 7); this.cwdhSection.NumEntries = Util.GetOffset(byteCwdhSection, 0x8, 0xb); this.cwdhSection.FirstCharacter = Util.GetOffset(byteCwdhSection, 0xc, 0xf); if (!"CWDH".Equals(this.cwdhSection.Magic)) { MessageBox.Show("错误的CWDH!"); return(null); } #endregion #region " 获取CWDH entries信息 " this.cwdhEntriesList = new List <CwdhEntries>(); int intCwdhEntriesPos = finfHeader.CwdhDataOffset + 8; for (int i = 0; i <= cwdhSection.NumEntries; i++) { byte[] cwdhEntriesItem = new byte[3]; Array.Copy(byData, intCwdhEntriesPos, cwdhEntriesItem, 0, cwdhEntriesItem.Length); CwdhEntries item = new CwdhEntries((sbyte)cwdhEntriesItem[0], cwdhEntriesItem[1], (sbyte)cwdhEntriesItem[2]); this.cwdhEntriesList.Add(item); intCwdhEntriesPos += 3; } this.cwdhEntriesList.Add(new CwdhEntries(0, 0, 0)); #endregion #region " 取得CMap(字符映射表)信息 " this.cmapList = new List <KeyValuePair <int, int> >(); //cmapDictionary = new SortedDictionary<int, int>(); int cmapPos = finfHeader.CMapDataOffset - 8; while (cmapPos != -8) { // 取得Cmap基本信息 byte[] cmapData = new byte[24]; Array.Copy(byData, cmapPos, cmapData, 0, cmapData.Length); Cmap cmapItem = new Cmap(); cmapItem.Magic = Util.GetHeaderString(cmapData, 0, 3); if (!"CMAP".Equals(cmapItem.Magic)) { MessageBox.Show("错误的Cmap格式!"); return(null); } cmapItem.LengthOfSection = Util.GetOffset(cmapData, 4, 7); cmapItem.FirstChar = Util.GetOffset(cmapData, 8, 9); cmapItem.LastChar = Util.GetOffset(cmapData, 10, 11); cmapItem.CmapType = Util.GetOffset(cmapData, 12, 13); cmapItem.OffsetToNextCMAPdata = Util.GetOffset(cmapData, 16, 19); cmapItem.TextureEntry = Util.GetOffset(cmapData, 20, 21); oldCmapList.Add(cmapData); // 开始循环判断Cmap信息 int charIndex; switch (cmapItem.CmapType) { case 0: charIndex = cmapItem.TextureEntry; for (int i = cmapItem.FirstChar; i <= cmapItem.LastChar; i++) { this.cmapList.Add(new KeyValuePair <int, int>(charIndex++, i)); //cmapDictionary.Add(charIndex++, i); //cmapDictionary.Add(i, charIndex++); } break; case 1: byte[] indexByte = new byte[(cmapItem.LastChar - cmapItem.FirstChar + 1) * 2]; Array.Copy(byData, cmapPos + 20, indexByte, 0, indexByte.Length); this.oldCmapEntriesList.Add(indexByte); int[] indexEntries = new int[indexByte.Length / 2]; int byteIndex = 0; for (int i = 0; i < indexEntries.Length; i++) { indexEntries[i] = Util.GetOffset(indexByte, byteIndex, byteIndex + 1); byteIndex += 2; } int entriesIndex = 0; for (int i = cmapItem.FirstChar; i <= cmapItem.LastChar; i++) { charIndex = indexEntries[entriesIndex++]; if (charIndex == 0xFFFF) { this.cmapList.Add(new KeyValuePair <int, int>(charIndex, i)); } else { this.cmapList.Add(new KeyValuePair <int, int>(charIndex, i)); //cmapDictionary.Add(charIndex, i); //cmapDictionary.Add(i, charIndex); } } break; case 2: byte[] entriesByte = new byte[cmapItem.TextureEntry * 2 * 2]; Array.Copy(byData, cmapPos + 0xE + 8, entriesByte, 0, entriesByte.Length); this.oldCmapEntriesList.Add(entriesByte); entriesIndex = 0; for (int i = 0; i < cmapItem.TextureEntry; i++) { this.cmapList.Add(new KeyValuePair <int, int>( Util.GetOffset(entriesByte, entriesIndex + 2, entriesIndex + 3), Util.GetOffset(entriesByte, entriesIndex, entriesIndex + 1))); //cmapDictionary.Add( // CommonUtil.GetOffset(entriesByte, entriesIndex + 2, entriesIndex + 3), // CommonUtil.GetOffset(entriesByte, entriesIndex, entriesIndex + 1)); //cmapDictionary.Add( // (int)CommonUtil.GetOffset(entriesByte, entriesIndex, entriesIndex + 1), // (int)CommonUtil.GetOffset(entriesByte, entriesIndex + 2, entriesIndex + 3) // ); entriesIndex += 4; } break; default: MessageBox.Show("错误的Cmap格式!"); return(null); } cmapPos = cmapItem.OffsetToNextCMAPdata - 8; } // CMap(字符映射表)信息排序 this.cmapList.Sort(Util.Comparison); // 保存原来的Cmap信息 foreach (KeyValuePair <int, int> item in this.cmapList) { if (item.Key != 0xFFFF) { this.oldCharList.Add(Util.GetStrFromNumber(item.Value, this.finfHeader.Encoding, this.rfntHeader.Endianess)); } } #endregion #region " 显示信息 " // 显示RfntHeader信息 this.lblEndianess.Text = this.rfntHeader.Endianess; this.lblVersionMinor.Text = this.rfntHeader.VersionMinor; this.lblLengthOfFileInBytes.Text = this.rfntHeader.LengthOfFileInBytes.ToString(); this.lblOffsetToFinfHeader.Text = this.rfntHeader.OffsetToFinfHeader.ToString(); this.lblNumberOfSections.Text = this.rfntHeader.NumberOfSections.ToString(); // 显示FinfHeader信息 this.lblEncoding.Text = Util.GetFontEncodingStr(this.finfHeader.Encoding); this.lblFonttype.Text = this.finfHeader.Fonttype; this.lblLeading.Text = this.finfHeader.Leading; this.lblLeftmargin.Text = this.finfHeader.Leftmargin.ToString(); this.lblTglpDataOffset.Text = this.finfHeader.TglpDataOffset.ToString(); this.lblCwdhDataOffset.Text = this.finfHeader.CwdhDataOffset.ToString(); this.lblCMapDataOffset.Text = this.finfHeader.CMapDataOffset.ToString(); // 显示TglpHeader信息 this.lblLengthOfTglpSection.Text = this.tglpHeader.LengthOfSection.ToString(); this.lblFontHeight.Text = this.tglpHeader.CellHeight.ToString(); this.lblFontWidth.Text = this.tglpHeader.CellWidth.ToString(); this.lblFontCharacterHeight.Text = this.tglpHeader.FontCharacterHeight.ToString(); this.lblFontCharacterWidth.Text = this.tglpHeader.FontCharacterWidth.ToString(); this.lblLengthOfOneImage.Text = this.tglpHeader.TextureSize.ToString(); this.lblImageCount.Text = this.tglpHeader.TextureNum.ToString(); this.lblImageFormat.Text = this.tglpHeader.ImageFormat; this.lblCharactersPerRow.Text = this.tglpHeader.CharactersPerRow.ToString(); this.lblCharactersPerColumn.Text = this.tglpHeader.CharactersPerColumn.ToString(); this.lblImageHeight.Text = this.tglpHeader.ImageHeight.ToString(); this.lblImageWidth.Text = this.tglpHeader.ImageWidth.ToString(); this.lblPositionOfData.Text = this.tglpHeader.PositionOfData.ToString(); #endregion return(byteTglpData); } catch (Exception e) { MessageBox.Show(e.Message + "\n" + e.StackTrace); return(null); } }
internal void Update(OS2Table os2Tabble, Meta meta, Cmap cmap, GSUB gsub, GPOS gpos) { //https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur //This field is used to specify the Unicode blocks or ranges encompassed by the font file in 'cmap' subtables for platform 3, //encoding ID 1 (Microsoft platform, Unicode BMP) and platform 3, //encoding ID 10 (Microsoft platform, Unicode full repertoire). //If a bit is set (1), then the Unicode ranges assigned to that bit are considered functional. //If the bit is clear (0), then the range is not considered functional. //unicode BMP (Basic Multilingual Plane),OR plane0 (see https://unicode.org/roadmaps/bmp/) //Each of the bits is treated as an independent flag and the bits can be set in any combination. //The determination of “functional” is left up to the font designer, //although character set selection should attempt to be functional by ranges if at all possible. //-------------- //Different versions of the OS/2 table were created when different Unicode versions were current, //and the initial specification for a given version defined fewer bit assignments than for later versions. //Some applications may not support all assignments for fonts that have earlier OS/2 versions. //All of the bit assignments listed above are valid for any version of the OS/2 table, //though OS/2 versions 1 and 2 were specified with some assignments that did not correspond to well-defined Unicode ranges and //that conflict with later assignments — see the details below. //If a font has a version 1 or version 2 OS/2 table with one of these bits set, //the obsolete assignment may be the intended interpretation. //Because these assignments do not correspond to well-defined ranges, //however, the implied character coverage is unclear. //Version 0: When version 0 was first specified, no bit assignments were defined. //Some applications may ignore these fields in a version 0 OS/2 table. //Version 1: //Version 1 was first specified concurrent with Unicode 1.1, //and bit assigments were defined for bits 0 to 69 only. With fonts that have a version 1 table, //some applications might recognize only bits 0 to 69. //Also, version 1 was specified with some bit assignments that did not correspond to a well-defined Unicode range: // Bit 8: “Greek Symbols and Coptic” (bit 7 was specified as “Basic Greek”) // Bit 12: “Hebrew Extended” (bit 11 was specified as “Basic Hebrew”) // Bit 14: “Arabic Extended” (bit 13 was specified as “Basic Arabic”) // Bit 27: “Georgian Extended” (bit 26 was specified as “Basic Georgian”) //These assignments were discontinued as of version 2. //In addition, versions 1 and 2 were defined with bit 53 specified as “CJK Miscellaneous”, //which also does not correspond to any well-defined Unicode range. //This assignment was discontinued as of version 3. //Version 2: //Version 2 was defined in OpenType 1.1, which was concurrent with Unicode 2.1. //At that time, bit assignments were defined for bits 0 to 69 only. //Bit assignments for version 2 were updated in OpenType 1.3, //adding assignments for bits 70 to 83 corresponding to new blocks assigned in Unicode 2.0 and Unicode 3.0. //With fonts that have a version 2 table, //some applications might recognize only those bits assigned in OpenType 1.2 or OpenType 1.3. //Also, the specification for version 2 continued to use a problematic assignment for bit 53 — //see details for version 1. This assignment was discontinued as of version 3. //Version 3: Version 3 was defined in OpenType 1.4 with assignments for bits 84 to 91 corresponding to additional //ranges in Unicode 3.2. //In addition, some already-assigned bits were extended to cover additional Unicode ranges for related characters; s //ee details in the table above. //Version 4: Version 4 was defined in OpenType 1.5 with assignments for bit 58 and bits 92 to 122 corresponding to additional ranges in Unicode 5.1. //Also, bits 8, 12, 14, 27 and 53 were re-assigned (see version 1 for previous assignments). //In addition, some already-assigned bits were extended to cover additional Unicode ranges for related characters; //see details in the table above. OS2Version = os2Tabble.version; UnicodeRange1 = os2Tabble.ulUnicodeRange1; UnicodeRange2 = os2Tabble.ulUnicodeRange2; UnicodeRange3 = os2Tabble.ulUnicodeRange3; UnicodeRange4 = os2Tabble.ulUnicodeRange4; //ULONG ulUnicodeRange1 Bits 0-31 //ULONG ulUnicodeRange2 Bits 32-63 //ULONG ulUnicodeRange3 Bits 64-95 //ULONG ulUnicodeRange4 Bits 96-127 //------- //IMPORTANT:*** //All available bits were exhausted as of Unicode 5.1. *** //The bit assignments were last updated for OS/2 version 4 in OpenType 1.5. //There are many additional ranges supported in the current version of Unicode that are not supported by these fields in the OS/2 table. // //See the 'dlng' and 'slng' tags in the 'meta' table for an alternate mechanism to declare //what scripts or languages that a font can support or is designed for. //------- if (meta != null) { SupportedLangs = meta.SupportedLanguageTags; DesignLangs = meta.DesignLanguageTags; } //---- //gsub and gpos contains actual script_list that are in the typeface GSUBScriptList = gsub?.ScriptList; GPOSScriptList = gpos?.ScriptList; _cmap = cmap; }
internal bool ReadTableEntryCollection(Typeface typeface, RestoreTicket ticket, TableEntryCollection tables, BinaryReader input) { if (ticket != null) { return(ReadTableEntryCollectionOnRestoreMode(typeface, ticket, tables, input)); } typeface.SetTableEntryCollection(tables.CloneTableHeaders()); var rd = new EntriesReaderHelper(tables, input); //PART 1: basic information OS2Table os2Table = rd.Read(new OS2Table()); Meta meta = rd.Read(new Meta()); NameEntry nameEntry = rd.Read(new NameEntry()); Head head = rd.Read(new Head()); MaxProfile maxProfile = rd.Read(new MaxProfile()); HorizontalHeader horizontalHeader = rd.Read(new HorizontalHeader()); HorizontalMetrics horizontalMetrics = rd.Read(new HorizontalMetrics(horizontalHeader.NumberOfHMetrics, maxProfile.GlyphCount)); VerticalHeader vhea = rd.Read(new VerticalHeader()); if (vhea != null) { VerticalMetrics vmtx = rd.Read(new VerticalMetrics(vhea.NumOfLongVerMetrics)); } Cmap cmaps = rd.Read(new Cmap()); VerticalDeviceMetrics vdmx = rd.Read(new VerticalDeviceMetrics()); Kern kern = rd.Read(new Kern()); //------------------------------------ //PART 2: glyphs detail //2.1 True type font GlyphLocations glyphLocations = rd.Read(new GlyphLocations(maxProfile.GlyphCount, head.WideGlyphLocations)); Glyf glyf = rd.Read(new Glyf(glyphLocations)); Gasp gaspTable = rd.Read(new Gasp()); COLR colr = rd.Read(new COLR()); CPAL cpal = rd.Read(new CPAL()); //2.2 Cff font PostTable postTable = rd.Read(new PostTable()); CFFTable cff = rd.Read(new CFFTable()); //additional math table (if available) MathTable mathtable = rd.Read(new MathTable()); //------------------------------------ //PART 3: advanced typography GDEF gdef = rd.Read(new GDEF()); GSUB gsub = rd.Read(new GSUB()); GPOS gpos = rd.Read(new GPOS()); BASE baseTable = rd.Read(new BASE()); JSTF jstf = rd.Read(new JSTF()); STAT stat = rd.Read(new STAT()); if (stat != null) { //variable font FVar fvar = rd.Read(new FVar()); if (fvar != null) { GVar gvar = rd.Read(new GVar()); CVar cvar = rd.Read(new CVar()); HVar hvar = rd.Read(new HVar()); MVar mvar = rd.Read(new MVar()); AVar avar = rd.Read(new AVar()); } } bool isPostScriptOutline = false; bool isBitmapFont = false; typeface.SetBasicTypefaceTables(os2Table, nameEntry, head, horizontalMetrics); if (glyf == null) { //check if this is cff table ? if (cff == null) { //check cbdt/cblc ? CBLC cblcTable = rd.Read(new CBLC()); if (cblcTable != null) { CBDT cbdtTable = rd.Read(new CBDT()); //read cbdt //bitmap font BitmapFontGlyphSource bmpFontGlyphSrc = new BitmapFontGlyphSource(cblcTable); bmpFontGlyphSrc.LoadCBDT(cbdtTable); Glyph[] glyphs = bmpFontGlyphSrc.BuildGlyphList(); typeface.SetBitmapGlyphs(glyphs, bmpFontGlyphSrc); isBitmapFont = true; } else { //TODO: EBLC fontBmpTable = rd.Read(new EBLC()); throw new NotSupportedException(); } } else { isPostScriptOutline = true; typeface.SetCffFontSet(cff.Cff1FontSet); } } else { typeface.SetTtfGlyphs(glyf.Glyphs); } //---------------------------- typeface.CmapTable = cmaps; typeface.KernTable = kern; typeface.MaxProfile = maxProfile; typeface.HheaTable = horizontalHeader; //---------------------------- typeface.GaspTable = gaspTable; if (!isPostScriptOutline && !isBitmapFont) { //for true-type font outline FpgmTable fpgmTable = rd.Read(new FpgmTable()); //control values table CvtTable cvtTable = rd.Read(new CvtTable()); PrepTable propProgramTable = rd.Read(new PrepTable()); typeface.ControlValues = cvtTable?._controlValues; typeface.FpgmProgramBuffer = fpgmTable?._programBuffer; typeface.PrepProgramBuffer = propProgramTable?._programBuffer; } //------------------------- typeface.LoadOpenFontLayoutInfo( gdef, gsub, gpos, baseTable, colr, cpal); //------------ typeface.SetSvgTable(rd.Read(new SvgTable())); typeface.PostTable = postTable; if (mathtable != null) { MathGlyphLoader.LoadMathGlyph(typeface, mathtable); } #if DEBUG //test //int found = typeface.GetGlyphIndexByName("Uacute"); if (typeface.IsCffFont) { //optional typeface.UpdateAllCffGlyphBounds(); } #endif typeface.UpdateLangs(meta); typeface.UpdateFrequentlyUsedValues(); return(true); }
public static Top FromFile(string path, List <string> defines) { List <string> lines = new List <string>(HFile.ReadAllLines(path)); List <LineElement> elements = new List <LineElement>(); //List<Tuple<string,List<LineElement>>> elementgroup = new List<Tuple<string, List<LineElement>>>(); //Dictionary<int,Atom> atoms = new Dictionary<int, Atom>(); //List<Bond> bonds = new List<Bond>(); //List<Pair> pairs = new List<Pair>(); //List<Angle> angles = new List<Angle>(); string type = null; while (lines.Count > 0) //for(int i=0; i<lines.Length; i++) { string line = lines[0]; lines.RemoveAt(0); //LineElement element = new LineElement(lines[i]); string typei = LineElement.GetType(line); if (typei != null) { type = typei; //elementgroup.Add(new Tuple<string, List<LineElement>>(type, new List<LineElement>())); continue; } { line = line.Trim(); if (line.EndsWith("\\")) { while (lines.Count > 0) { line = line + "\n" + lines[0].Trim(); lines.RemoveAt(0); if (line.EndsWith("\\") == false) { break; } } //line = ""; //for(; i<lines.Length; i++) //{ // string lline = lines[i].Trim(); // line = line + lline + "\n"; // if(lline.EndsWith("\\") == false) // break; //} } line = (line.IndexOf(';') == -1) ? line.Trim() : line.Substring(0, line.IndexOf(';')).Trim(); if (line.Length == 0) { continue; } if (line[0] == '*') { continue; } if (line.StartsWith("#define")) { string define = line.Replace("#define", "").Trim(); defines.Add(define); continue; } if (line.StartsWith("#include")) { string includepath; { includepath = line.Replace("#include", "").Trim().Replace("\"", "").Trim(); if (HFile.Exists(includepath) == false) { includepath = @"C:\Program Files (x86)\Gromacs\share\gromacs\top\" + line.Replace("#include", "").Trim().Replace("\"", "").Trim(); } if (HFile.Exists(includepath) == false) { includepath = HDirectory.GetParent(path).FullName + "\\" //path.Substring(0, path.LastIndexOf('/')+1) + line.Replace("#include", "").Trim().Replace("\"", "").Trim(); } HDebug.Assert(HFile.Exists(includepath)); } Top includetop = FromFile(includepath, defines); elements.AddRange(includetop.elements); type = null; continue; } if (line.StartsWith("#ifdef")) { FromFile_ifdef(defines, lines, line); continue; } if (line.StartsWith("#")) { HDebug.Assert(false); } if (type == "moleculetype") { LineElement element = new Moleculetype(line, path); elements.Add(element); continue; } if (type == "atoms") { LineElement element = new Atom(line, path); elements.Add(element); continue; } if (type == "bonds") { LineElement element = new Bond(line, path); elements.Add(element); continue; } if (type == "pairs") { LineElement element = new Pair(line, path); elements.Add(element); continue; } if (type == "angles") { LineElement element = new Angle(line, path); elements.Add(element); continue; } if (type == "dihedrals") { LineElement element = new Dihedral(line, path); elements.Add(element); continue; } if (type == "cmap") { LineElement element = new Cmap(line, path); elements.Add(element); continue; } if (type == "position_restraints") { LineElement element = new Position_restraints(line, path); elements.Add(element); continue; } if (type == "system") { LineElement element = new System(line, path); elements.Add(element); continue; } if (type == "molecules") { LineElement element = new Molecules(line, path); elements.Add(element); continue; } if (type == "defaults") { LineElement element = new Defaults(line, path); elements.Add(element); continue; } if (type == "atomtypes") { LineElement element = new Atomtypes(line, path); elements.Add(element); continue; } if (type == "pairtypes") { LineElement element = new Pairtypes(line, path); elements.Add(element); continue; } if (type == "bondtypes") { LineElement element = new Bondtypes(line, path); elements.Add(element); continue; } if (type == "constrainttypes") { LineElement element = new Constrainttypes(line, path); elements.Add(element); continue; } if (type == "angletypes") { LineElement element = new Angletypes(line, path); elements.Add(element); continue; } if (type == "dihedraltypes") { LineElement element = new Dihedraltypes(line, path); elements.Add(element); continue; } if (type == "implicit_genborn_params") { LineElement element = new Implicit_genborn_params(line, path); elements.Add(element); continue; } if (type == "cmaptypes") { LineElement element = new Cmaptypes(line, path); elements.Add(element); continue; } if (type == "settles") { LineElement element = new Settles(line, path); elements.Add(element); continue; } if (type == "exclusions") { LineElement element = new Exclusions(line, path); elements.Add(element); continue; } HDebug.Assert(false); } } Top top = new Top(); top.elements = elements.ToArray(); return(top); }