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 static HorizontalMetricsTable Load(FontReader reader) { // you should load all dependent tables prior to manipulating the reader HorizontalHeadTable headTable = reader.GetTable <HorizontalHeadTable>(); MaximumProfileTable profileTable = reader.GetTable <MaximumProfileTable>(); // Move to start of table using BigEndianBinaryReader binaryReader = reader.GetReaderAtTablePosition(TableName); return(Load(binaryReader, headTable.NumberOfHMetrics, profileTable.GlyphCount)); }
public void ShouldReturnNullWhenTableCouldNotBeFound() { var writer = new BinaryWriter(); writer.WriteTrueTypeFileHeader(); using (var stream = writer.GetStream()) { Assert.Null(HorizontalHeadTable.Load(new FontReader(stream))); } }
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) { }
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 HorizontalHeadTable hhea = reader.GetTable <HorizontalHeadTable>(); // 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 ColrTable?colrTable = reader.TryGetTable <ColrTable>(); // colr CpalTable?cpalTable; if (colrTable != null) { cpalTable = reader.GetTable <CpalTable>(); // CPAL - required if COLR is provided } else { cpalTable = reader.TryGetTable <CpalTable>(); // colr } // post - PostScript information // gasp - Grid-fitting/Scan-conversion (optional table) // PCLT - PCL 5 data // DSIG - Digital signature return(new FontInstance( nameTable, cmap, glyphs, os2, hhea, horizontalMetrics, head, kern, colrTable, cpalTable)); }
public static void WriteHorizontalHeadTable(this BinaryWriter writer, HorizontalHeadTable table) { // Type | Name | Description // ----------|----------------------|---------------------------------------------------------------------------------------------------- // uint16 | majorVersion | Major version number of the horizontal header table — set to 1. // uint16 | minorVersion | Minor version number of the horizontal header table — set to 0. // FWORD | Ascender | Typographic ascent (Distance from baseline of highest ascender). // FWORD | Descender | Typographic descent (Distance from baseline of lowest descender). // FWORD | LineGap | Typographic line gap. - Negative LineGap values are treated as zero in Windows 3.1, and in Mac OS System 6 and System 7. // UFWORD | advanceWidthMax | Maximum advance width value in 'hmtx' table. // FWORD | minLeftSideBearing | Minimum left sidebearing value in 'hmtx' table. // FWORD | minRightSideBearing | Minimum right sidebearing value; calculated as Min(aw - lsb - (xMax - xMin)). // FWORD | xMaxExtent | Max(lsb + (xMax - xMin)). // int16 | caretSlopeRise | Used to calculate the slope of the cursor (rise/run); 1 for vertical. // int16 | caretSlopeRun | 0 for vertical. // int16 | caretOffset | The amount by which a slanted highlight on a glyph needs to be shifted to produce the best appearance. Set to 0 for non-slanted fonts // int16 | (reserved) | set to 0 // int16 | (reserved) | set to 0 // int16 | (reserved) | set to 0 // int16 | (reserved) | set to 0 // int16 | metricDataFormat | 0 for current format. // uint16 | numberOfHMetrics | Number of hMetric entries in 'hmtx' table writer.WriteUInt16(1); writer.WriteUInt16(1); writer.WriteFWORD(table.Ascender); writer.WriteFWORD(table.Descender); writer.WriteFWORD(table.LineGap); writer.WriteUFWORD(table.AdvanceWidthMax); writer.WriteFWORD(table.MinLeftSideBearing); writer.WriteFWORD(table.MinRightSideBearing); writer.WriteFWORD(table.XMaxExtent); writer.WriteInt16(table.CaretSlopeRise); writer.WriteInt16(table.CaretSlopeRun); writer.WriteInt16(table.CaretOffset); writer.WriteInt16(0); // reserved writer.WriteInt16(0); // reserved writer.WriteInt16(0); // reserved writer.WriteInt16(0); // reserved writer.WriteInt16(0); // metricDataFormat should be 0 writer.WriteUInt16(table.NumberOfHMetrics); }
public void LoadHorizontalHeadTable() { var writer = new BinaryWriter(); writer.WriteHorizontalHeadTable(new HorizontalHeadTable(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)); HorizontalHeadTable tbl = HorizontalHeadTable.Load(writer.GetReader()); Assert.Equal(1, tbl.Ascender); Assert.Equal(2, tbl.Descender); Assert.Equal(3, tbl.LineGap); Assert.Equal(4, tbl.AdvanceWidthMax); Assert.Equal(5, tbl.MinLeftSideBearing); Assert.Equal(6, tbl.MinRightSideBearing); Assert.Equal(7, tbl.XMaxExtent); Assert.Equal(8, tbl.CaretSlopeRise); Assert.Equal(9, tbl.CaretSlopeRun); Assert.Equal(10, tbl.CaretOffset); Assert.Equal(11, tbl.NumberOfHMetrics); }
/// <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="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); }