public void LoadHead() { var writer = new BigEndianBinaryWriter(); writer.WriteHeadTable(new HeadTable( HeadTable.HeadFlags.None, HeadTable.HeadMacStyle.Italic | HeadTable.HeadMacStyle.Bold, 1024, new DateTime(2017, 02, 06, 07, 47, 00), new DateTime(2017, 02, 07, 07, 47, 00), new Bounds(0, 0, 1024, 1022), 0, HeadTable.IndexLocationFormats.Offset16)); var head = HeadTable.Load(writer.GetReader()); Assert.Equal(HeadTable.HeadFlags.None, head.Flags); Assert.Equal(HeadTable.HeadMacStyle.Italic | HeadTable.HeadMacStyle.Bold, head.MacStyle); Assert.Equal(1024, head.UnitsPerEm); Assert.Equal(new DateTime(2017, 02, 06, 07, 47, 00), head.Created); Assert.Equal(new DateTime(2017, 02, 07, 07, 47, 00), head.Modified); Assert.Equal(0, head.Bounds.Min.X); Assert.Equal(0, head.Bounds.Min.Y); Assert.Equal(1024, head.Bounds.Max.X); Assert.Equal(1022, head.Bounds.Max.Y); Assert.Equal(0, head.LowestRecPPEM); Assert.Equal(HeadTable.IndexLocationFormats.Offset16, head.IndexLocationFormat); }
internal static FontInstance LoadFont(FontReader reader) { // https://www.microsoft.com/typography/otspec/recom.htm#TableOrdering // recomended order HeadTable head = reader.GetTable <HeadTable>(); // head - not saving but loading in suggested order reader.GetTable <HoizontalHeadTable>(); // hhea reader.GetTable <MaximumProfileTable>(); // maxp OS2Table os2 = reader.GetTable <OS2Table>(); // OS/2 HorizontalMetricsTable horizontalMetrics = reader.GetTable <HorizontalMetricsTable>(); // hmtx // LTSH - Linear threshold data // VDMX - Vertical device metrics // hdmx - Horizontal device metrics CMapTable cmap = reader.GetTable <CMapTable>(); // cmap // fpgm - Font Program // prep - Control Value Program // cvt - Control Value Table reader.GetTable <IndexLocationTable>(); // loca GlyphTable glyphs = reader.GetTable <GlyphTable>(); // glyf KerningTable kern = reader.GetTable <KerningTable>(); // kern - Kerning NameTable nameTable = reader.GetTable <NameTable>(); // name // post - PostScript information // gasp - Grid-fitting/Scan-conversion (optional table) // PCLT - PCL 5 data // DSIG - Digital signature return(new FontInstance(nameTable, cmap, glyphs, os2, horizontalMetrics, head, kern)); }
private static FontStyle ConvertStyle(OS2Table os2, HeadTable head) { FontStyle style = FontStyle.Regular; if (os2 != null) { if (os2.FontStyle.HasFlag(OS2Table.FontStyleSelection.BOLD)) { style |= FontStyle.Bold; } if (os2.FontStyle.HasFlag(OS2Table.FontStyleSelection.ITALIC)) { style |= FontStyle.Italic; } } else if (head != null) { if (head.MacStyle.HasFlag(HeadTable.HeadMacStyle.Bold)) { style |= FontStyle.Bold; } if (head.MacStyle.HasFlag(HeadTable.HeadMacStyle.Italic)) { style |= FontStyle.Italic; } } return(style); }
internal FakeFontInstance( NameTable nameTable, MaximumProfileTable maxpTable, CMapTable cmap, GlyphTable glyphs, OS2Table os2, HorizontalHeadTable horizontalHeadTable, HorizontalMetricsTable horizontalMetrics, VerticalHeadTable verticalHeadTable, VerticalMetricsTable verticalMetrics, HeadTable head, KerningTable kern) : base( nameTable, maxpTable, cmap, glyphs, os2, horizontalHeadTable, horizontalMetrics, verticalHeadTable, verticalMetrics, head, kern, null, null, null, null, null, null, null, null) { }
public ActionResult DeleteConfirmed(int id) { HeadTable headTable = db.DvHeadTables.Find(id); db.DvHeadTables.Remove(headTable); db.SaveChanges(); return(RedirectToAction("Index")); }
/// <summary> /// Reads a <see cref="FontDescription" /> from the specified stream. /// </summary> /// <param name="reader">The reader.</param> /// <returns> /// a <see cref="FontDescription" />. /// </returns> internal static FontDescription LoadDescription(FontReader reader) { HeadTable head = reader.GetTable <HeadTable>(); OS2Table os2 = reader.GetTable <OS2Table>(); NameTable nameTable = reader.GetTable <NameTable>(); return(new FontDescription(nameTable, os2, head)); }
public HeadTable Head(TableHeader header) { var table = new HeadTable(header); if (TablesByName.ContainsKey(table.Name)) { table.ReadFrom(reader); } return(table); }
/// <summary> /// Reads a <see cref="FontDescription" /> from the specified stream. /// </summary> /// <param name="reader">The reader.</param> /// <returns> /// a <see cref="FontDescription" />. /// </returns> internal static FontDescription LoadDescription(FontReader reader) { // NOTE: These fields are read in their optimized order // https://docs.microsoft.com/en-gb/typography/opentype/spec/recom#optimized-table-ordering HeadTable head = reader.GetTable <HeadTable>(); OS2Table os2 = reader.GetTable <OS2Table>(); NameTable nameTable = reader.GetTable <NameTable>(); return(new FontDescription(nameTable, os2, head)); }
public ActionResult Edit([Bind(Include = "Id,Idhead,Time,ConfigurationTable,ConnectedTable")] HeadTable headTable) { if (ModelState.IsValid) { db.Entry(headTable).State = EntityState.Modified; db.SaveChanges(); return(RedirectToAction("Index")); } ViewBag.Idhead = new SelectList(db.DvHeads, "Id", "Ipaddress", headTable.Idhead); return(View(headTable)); }
internal FakeFontInstance( NameTable nameTable, CMapTable cmap, GlyphTable glyphs, OS2Table os2, HorizontalHeadTable horizontalHeadTable, HorizontalMetricsTable horizontalMetrics, HeadTable head, KerningTable kern) : base(nameTable, cmap, glyphs, os2, horizontalHeadTable, horizontalMetrics, head, kern, null, null) { }
// GET: HeadTables/Details/5 public ActionResult Details(int?id) { if (id == null) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest)); } HeadTable headTable = db.DvHeadTables.Find(id); if (headTable == null) { return(HttpNotFound()); } return(View(headTable)); }
/// <summary> /// Initializes a new instance of the <see cref="FontDescription" /> class. /// </summary> /// <param name="nameTable">The name table.</param> /// <param name="cmap">The cmap.</param> /// <param name="glyphs">The glyphs.</param> /// <param name="os2">The os2.</param> /// <param name="horizontalMetrics">The horizontal metrics.</param> /// <param name="head">The head.</param> /// <param name="kern">The kern.</param> internal FontInstance(NameTable nameTable, CMapTable cmap, GlyphTable glyphs, OS2Table os2, HorizontalMetricsTable horizontalMetrics, HeadTable head, KerningTable kern) { this.cmap = cmap; this.os2 = os2; this.glyphs = glyphs; this.horizontalMetrics = horizontalMetrics; this.head = head; this.glyphCache = new GlyphInstance[this.glyphs.GlyphCount]; // https://www.microsoft.com/typography/otspec/recom.htm#tad this.LineHeight = os2.TypoAscender - os2.TypoDescender + os2.TypoLineGap; this.EmSize = this.head.UnitsPerEm; this.kerning = kern; this.Description = new FontDescription(nameTable, os2, head); }
// GET: HeadTables/Edit/5 public ActionResult Edit(int?id) { if (id == null) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest)); } HeadTable headTable = db.DvHeadTables.Find(id); if (headTable == null) { return(HttpNotFound()); } ViewBag.Idhead = new SelectList(db.DvHeads, "Id", "Ipaddress", headTable.Idhead); return(View(headTable)); }
internal Font(FontStreamReader reader, OffsetTable offsetTable) { this.reader = reader; this.offsetTable = offsetTable; HeadTable = HeadTable.Read(reader, offsetTable.Entries["head"]); if (offsetTable.Entries.ContainsKey("fpgm")) { fpgmTable = FpgmTable.Read(reader, offsetTable.Entries["fpgm"]); } cmapTable = CmapTable.Read(reader, offsetTable.Entries["cmap"]); locaTable = LocaTable.Read(this, reader, offsetTable.Entries["loca"]); glyfTable = GlyfTable.Read(reader, offsetTable.Entries["glyf"]); //TODO run fpgm }
/// <summary> /// Запросить таблицы устройств DV-HEAD OMEGA /// </summary> /// <param name="id">Идентификатор DV-HEAD</param> /// <returns></returns> public TablesDto RequestDeviceTables(int id) { TablesDto tablesDto = new TablesDto(); try { using (MainDbContext dbContext = new MainDbContext()) { HeadTable hd = dbContext.DvHeadTables.Where(t => t.Idhead == id).OrderByDescending(t => t.DgsTime).First(); tablesDto.DvHead = hd.DvHead; tablesDto.ConfigurationTable = ParseConfigTable(hd.ConfigurationTable).OrderBy(s => s); // the original was not sorted tablesDto.ExternalTable = ParseExternalTable(hd.ConnectedTable, tablesDto.ConfigurationTable); tablesDto.Address = hd.DvHead.Address; tablesDto.Failure = false; } } catch (Exception) { tablesDto.Failure = true; } return(tablesDto); }
/// <summary> /// Initializes a new instance of the <see cref="FontInstance"/> class. /// </summary> /// <param name="nameTable">The name table.</param> /// <param name="cmap">The cmap.</param> /// <param name="glyphs">The glyphs.</param> /// <param name="os2">The os2.</param> /// <param name="horizontalHeadTable">The horizontal head table.</param> /// <param name="horizontalMetrics">The horizontal metrics.</param> /// <param name="head">The head.</param> /// <param name="kern">The kern.</param> /// <param name="colrTable">The COLR table</param> /// <param name="cpalTable">The CPAL table</param> internal FontInstance( NameTable nameTable, CMapTable cmap, GlyphTable glyphs, OS2Table os2, HorizontalHeadTable horizontalHeadTable, HorizontalMetricsTable horizontalMetrics, HeadTable head, KerningTable kern, ColrTable?colrTable, CpalTable?cpalTable) { this.cmap = cmap; this.os2 = os2; this.glyphs = glyphs; this.horizontalMetrics = horizontalMetrics; this.head = head; this.glyphCache = new GlyphInstance[this.glyphs.GlyphCount]; if (!(colrTable is null)) { this.colorGlyphCache = new GlyphInstance[this.glyphs.GlyphCount][]; } bool useTypoMetrics = os2.FontStyle.HasFlag(OS2Table.FontStyleSelection.USE_TYPO_METRICS); // https://www.microsoft.com/typography/otspec/recom.htm#tad this.Ascender = useTypoMetrics ? os2.TypoAscender : horizontalHeadTable.Ascender; this.Descender = useTypoMetrics ? os2.TypoDescender : horizontalHeadTable.Descender; this.LineGap = useTypoMetrics ? os2.TypoLineGap : horizontalHeadTable.LineGap; this.LineHeight = this.Ascender - this.Descender + this.LineGap; this.EmSize = this.head.UnitsPerEm; this.kerning = kern; this.colrTable = colrTable; this.cpalTable = cpalTable; this.Description = new FontDescription(nameTable, os2, head); }
/// <summary> /// Initializes a new instance of the <see cref="FontDescription" /> class. /// </summary> /// <param name="nameTable">The name table.</param> /// <param name="os2">The os2.</param> /// <param name="head">The head.</param> internal FontDescription(NameTable nameTable, OS2Table os2, HeadTable head) : this(nameTable.FontName, nameTable.FontFamilyName, nameTable.FontSubFamilyName, ConvertStyle(os2, head)) { }
public static Font ReadFromStream(Stream stream) { var font = new Font(); var reader = new BinaryReader(stream); // Offset Table font.OffsetTable = OffsetTable.Read(reader); // Head var headTableRecord = font.OffsetTable.TableRecords.Single(x => x.TableTag == HeadTable.Tag); stream.Seek(headTableRecord.Offset, SeekOrigin.Begin); font.HeadTable = HeadTable.Read(reader); // Horizontal Header var horizontalHeaderTableRecord = font.OffsetTable.TableRecords.Single(x => x.TableTag == HorizontalHeaderTable.Tag); stream.Seek(horizontalHeaderTableRecord.Offset, SeekOrigin.Begin); font.HorizontalHeaderTable = HorizontalHeaderTable.Read(reader); // Maximum Profile var maximumProfileTableRecord = font.OffsetTable.TableRecords.Single(x => x.TableTag == MaximumProfileTableBase.Tag); stream.Seek(maximumProfileTableRecord.Offset, SeekOrigin.Begin); var maximumProfileTableVersion = Math.Round(reader.ReadFixedPointNumber(), 2); if (maximumProfileTableVersion == 0.5m) { font.MaximumProfileTable = MaximumProfileTableV0_5.Read(reader, maximumProfileTableVersion); } else if (maximumProfileTableVersion == 1.0m) { font.MaximumProfileTable = MaximumProfileTableV1.Read(reader, maximumProfileTableVersion); } // Horizontal Metrics var horizontalMetricsTableRecord = font.OffsetTable.TableRecords.Single(x => x.TableTag == HorizontalMetricsTable.Tag); stream.Seek(horizontalMetricsTableRecord.Offset, SeekOrigin.Begin); font.HorizontalMetricsTable = HorizontalMetricsTable.Read(reader, font.HorizontalHeaderTable.NumberOfHMetrics, font.MaximumProfileTable.NumGlyphs); // Glyph var glyphTableRecord = font.OffsetTable.TableRecords.Single(x => x.TableTag == GlyphTable.Tag); font.GlyphTable = new GlyphTable(reader, glyphTableRecord.Offset); // IndexLocation var indexLocationTableRecord = font.OffsetTable.TableRecords.Single(x => x.TableTag == IndexLocationTableBase.Tag); stream.Seek(indexLocationTableRecord.Offset, SeekOrigin.Begin); if (font.HeadTable.IndexToLocFormat == 0) { font.IndexLocationTable = IndexLocationShortFormatTable.Read(reader, font.MaximumProfileTable.NumGlyphs); } else { font.IndexLocationTable = IndexLocationLongFormatTable.Read(reader, font.MaximumProfileTable.NumGlyphs); } // PostScript var postScriptTableRecord = font.OffsetTable.TableRecords.Single(x => x.TableTag == PostScriptTable.Tag); stream.Seek(postScriptTableRecord.Offset, SeekOrigin.Begin); font.PostScriptTable = PostScriptTable.Read(reader); // OS/2 and Windows var os2TableRecord = font.OffsetTable.TableRecords.Single(x => x.TableTag == Os2Table.Tag); stream.Seek(os2TableRecord.Offset, SeekOrigin.Begin); font.Os2Table = Os2Table.Read(reader); // CharacterMap var characterMapTableRecord = font.OffsetTable.TableRecords.Single(x => x.TableTag == CharacterMapTable.Tag); stream.Seek(characterMapTableRecord.Offset, SeekOrigin.Begin); font.CharacterMapTable = CharacterMapTable.Read(reader); return(font); }
public OpenTypeFont Deserialize(BinaryReader reader) { var font = new OpenTypeFont { SfntVersion = DataTypeConverter.ReadFixed(reader) }; if (!_supportedSfntVersions.Contains(font.SfntVersion)) { throw new NotSupportedException("Bad sfnt version."); } // Table directory var numberOfTables = DataTypeConverter.ReadUShort(reader); reader.BaseStream.Position += 3 * DataTypeLength.UShort; // searchRange, entrySelector, rangeShift var entryList = Enumerable.Range(0, numberOfTables).Select(i => { var entry = new TableDirectoryEntry { Tag = DataTypeConverter.ReadTag(reader) }; reader.BaseStream.Position += DataTypeLength.ULong; // checksum entry.Offset = DataTypeConverter.ReadULong(reader); entry.Length = DataTypeConverter.ReadULong(reader); return(entry); }).ToList(); // Tables font.Tables.AddRange( entryList.OrderBy(entry => entry.Priority).Select <TableDirectoryEntry, IOpenTypeFontTable>(entry => { switch (entry.Tag) { case "cmap": return(CmapTable.Deserialize(reader, entry.Offset)); case "head": return(HeadTable.Deserialize(reader, entry.Offset)); case "maxp": return(MaxpTable.Deserialize(reader, entry.Offset)); case "loca": return(LocaTable.Deserialize(reader, entry.Offset, font.Get <MaxpTable>().NumberOfGlyphs, font.Get <HeadTable>().LocaTableVersion)); case "glyf": return(GlyfTable.Deserialize(reader, entry.Offset, entry.Length, font.Get <LocaTable>())); case "hhea": return(HheaTable.Deserialize(reader, entry.Offset)); case "hmtx": return(HmtxTable.Deserialize(reader, entry.Offset, font.Get <HheaTable>().NumberOfHMetrics, font.Get <MaxpTable>().NumberOfGlyphs)); case "post": return(PostTable.Deserialize(reader, entry.Offset)); default: return(BinaryDataTable.Deserialize(reader, entry.Offset, entry.Length, entry.Tag)); } })); return(font); }
public static void WriteHeadTable(this BinaryWriter writer, HeadTable table) { // Type | Name | Description // -------------|--------------------|---------------------------------------------------------------------------------------------------- // uint16 | majorVersion | Major version number of the font header table — set to 1. // uint16 | minorVersion | Minor version number of the font header table — set to 0. // Fixed | fontRevision | Set by font manufacturer. // uint32 | checkSumAdjustment | To compute: set it to 0, sum the entire font as uint32, then store 0xB1B0AFBA - sum.If the font is used as a component in a font collection file, the value of this field will be invalidated by changes to the file structure and font table directory, and must be ignored. // uint32 | magicNumber | Set to 0x5F0F3CF5. // uint16 | flags | Bit 0: Baseline for font at y = 0; // Bit 1: Left sidebearing point at x = 0(relevant only for TrueType rasterizers) — see the note below regarding variable fonts; // Bit 2: Instructions may depend on point size; // Bit 3: Force ppem to integer values for all internal scaler math; may use fractional ppem sizes if this bit is clear; // Bit 4: Instructions may alter advance width(the advance widths might not scale linearly); // Bit 5: This bit is not used in OpenType, and should not be set in order to ensure compatible behavior on all platforms.If set, it may result in different behavior for vertical layout in some platforms. (See Apple's specification for details regarding behavior in Apple platforms.) // Bits 6–10: These bits are not used in Opentype and should always be cleared. (See Apple's specification for details regarding legacy used in Apple platforms.) // Bit 11: Font data is ‘lossless’ as a results of having been subjected to optimizing transformation and/or compression (such as e.g.compression mechanisms defined by ISO/IEC 14496-18, MicroType Express, WOFF 2.0 or similar) where the original font functionality and features are retained but the binary compatibility between input and output font files is not guaranteed.As a result of the applied transform, the ‘DSIG’ Table may also be invalidated. // Bit 12: Font converted (produce compatible metrics) // Bit 13: Font optimized for ClearType™. Note, fonts that rely on embedded bitmaps (EBDT) for rendering should not be considered optimized for ClearType, and therefore should keep this bit cleared. // Bit 14: Last Resort font.If set, indicates that the glyphs encoded in the cmap subtables are simply generic symbolic representations of code point ranges and don’t truly represent support for those code points.If unset, indicates that the glyphs encoded in the cmap subtables represent proper support for those code points. // Bit 15: Reserved, set to 0 // uint16 | unitsPerEm | Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines. // LONGDATETIME | created | Number of seconds since 12:00 midnight that started January 1st 1904 in GMT/UTC time zone. 64-bit integer // LONGDATETIME | modified | Number of seconds since 12:00 midnight that started January 1st 1904 in GMT/UTC time zone. 64-bit integer // int16 | xMin | For all glyph bounding boxes. // int16 | yMin | For all glyph bounding boxes. // int16 | xMax | For all glyph bounding boxes. // int16 | yMax | For all glyph bounding boxes. // uint16 | macStyle | Bit 0: Bold (if set to 1); // Bit 1: Italic(if set to 1) // Bit 2: Underline(if set to 1) // Bit 3: Outline(if set to 1) // Bit 4: Shadow(if set to 1) // Bit 5: Condensed(if set to 1) // Bit 6: Extended(if set to 1) // Bits 7–15: Reserved(set to 0). // uint16 |lowestRecPPEM | Smallest readable size in pixels. // int16 | fontDirectionHint | Deprecated(Set to 2). // 0: Fully mixed directional glyphs; // 1: Only strongly left to right; // 2: Like 1 but also contains neutrals; // -1: Only strongly right to left; // -2: Like -1 but also contains neutrals. 1 // int16 | indexToLocFormat | 0 for short offsets (Offset16), 1 for long (Offset32). // int16 | glyphDataFormat | 0 for current format. writer.WriteUInt16(1); writer.WriteUInt16(0); writer.WriteUInt32(0); writer.WriteUInt32(0); writer.WriteUInt32(0x5F0F3CF5); writer.WriteUInt16((ushort)table.Flags); writer.WriteUInt16(table.UnitsPerEm); DateTime startDate = new DateTime(1904, 01, 01, 0, 0, 0, DateTimeKind.Utc); writer.WriteInt64((long)table.Created.Subtract(startDate).TotalSeconds); writer.WriteInt64((long)table.Modified.Subtract(startDate).TotalSeconds); writer.WriteInt16((short)table.Bounds.Min.X); writer.WriteInt16((short)table.Bounds.Min.Y); writer.WriteInt16((short)table.Bounds.Max.X); writer.WriteInt16((short)table.Bounds.Max.Y); writer.WriteUInt16((ushort)table.MacStyle); writer.WriteUInt16(table.LowestRecPPEM); writer.WriteInt16(2); writer.WriteInt16((short)table.IndexLocationFormat); writer.WriteInt16(0); }
/// <summary> /// Initializes a new instance of the <see cref="StreamFontMetrics"/> class. /// </summary> /// <param name="nameTable">The name table.</param> /// <param name="maximumProfileTable">The maximum profile table.</param> /// <param name="cmap">The cmap table.</param> /// <param name="glyphs">The glyph table.</param> /// <param name="os2">The os2 table.</param> /// <param name="horizontalHeadTable">The horizontal head table.</param> /// <param name="horizontalMetrics">The horizontal metrics table.</param> /// <param name="verticalHeadTable">The vertical head table.</param> /// <param name="verticalMetrics">The vertical metrics table.</param> /// <param name="head">The head table.</param> /// <param name="kern">The kerning table.</param> /// <param name="gSubTable">The glyph substitution table.</param> /// <param name="gPosTable">The glyph positioning table.</param> /// <param name="colrTable">The COLR table</param> /// <param name="cpalTable">The CPAL table</param> /// <param name="fpgm">The font program table.</param> /// <param name="cvt">The control value table.</param> /// <param name="prep">The control value program table.</param> /// <param name="glyphDefinitionTable">The glyph definition table.</param> internal StreamFontMetrics( NameTable nameTable, MaximumProfileTable maximumProfileTable, CMapTable cmap, GlyphTable glyphs, OS2Table os2, HorizontalHeadTable horizontalHeadTable, HorizontalMetricsTable horizontalMetrics, VerticalHeadTable?verticalHeadTable, VerticalMetricsTable?verticalMetrics, HeadTable head, KerningTable kern, GSubTable?gSubTable, GPosTable?gPosTable, ColrTable?colrTable, CpalTable?cpalTable, FpgmTable?fpgm, CvtTable?cvt, PrepTable?prep, GlyphDefinitionTable?glyphDefinitionTable) { this.maximumProfileTable = maximumProfileTable; this.cmap = cmap; this.os2 = os2; this.glyphs = glyphs; this.horizontalMetrics = horizontalMetrics; this.verticalMetricsTable = verticalMetrics; this.head = head; this.glyphCache = new GlyphMetrics[this.glyphs.GlyphCount][]; if (colrTable is not null) { this.colorGlyphCache = new GlyphMetrics[this.glyphs.GlyphCount][]; } // https://www.microsoft.com/typography/otspec/recom.htm#tad // We use the same approach as FreeType for calculating the the global ascender, descender, and // height of OpenType fonts for consistency. // // 1.If the OS/ 2 table exists and the fsSelection bit 7 is set (USE_TYPO_METRICS), trust the font // and use the Typo* metrics. // 2.Otherwise, use the HorizontalHeadTable "hhea" table's metrics. // 3.If they are zero and the OS/ 2 table exists, // - Use the OS/ 2 table's sTypo* metrics if they are non-zero. // - Otherwise, use the OS / 2 table's usWin* metrics. bool useTypoMetrics = os2.FontStyle.HasFlag(OS2Table.FontStyleSelection.USE_TYPO_METRICS); if (useTypoMetrics) { this.Ascender = os2.TypoAscender; this.Descender = os2.TypoDescender; this.LineGap = os2.TypoLineGap; this.LineHeight = (short)(this.Ascender - this.Descender + this.LineGap); } else { this.Ascender = horizontalHeadTable.Ascender; this.Descender = horizontalHeadTable.Descender; this.LineGap = horizontalHeadTable.LineGap; this.LineHeight = (short)(this.Ascender - this.Descender + this.LineGap); } if (this.Ascender == 0 || this.Descender == 0) { if (os2.TypoAscender != 0 || os2.TypoDescender != 0) { this.Ascender = os2.TypoAscender; this.Descender = os2.TypoDescender; this.LineGap = os2.TypoLineGap; this.LineHeight = (short)(this.Ascender - this.Descender + this.LineGap); } else { this.Ascender = (short)os2.WinAscent; this.Descender = (short)-os2.WinDescent; this.LineHeight = (short)(this.Ascender - this.Descender); } } this.UnitsPerEm = this.head.UnitsPerEm; // 72 * UnitsPerEm means 1pt = 1px this.ScaleFactor = this.UnitsPerEm * 72F; this.AdvanceWidthMax = (short)horizontalHeadTable.AdvanceWidthMax; this.AdvanceHeightMax = verticalHeadTable == null ? this.LineHeight : verticalHeadTable.AdvanceHeightMax; this.kerningTable = kern; this.gSubTable = gSubTable; this.gPosTable = gPosTable; this.colrTable = colrTable; this.cpalTable = cpalTable; this.fpgm = fpgm; this.cvt = cvt; this.prep = prep; this.glyphDefinitionTable = glyphDefinitionTable; this.Description = new FontDescription(nameTable, os2, head); }