FontCollectionHeader ReadTTCHeader(ByteOrderSwappingBinaryReader input) { //https://docs.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header //TTC Header Version 1.0: //Type Name Description //TAG ttcTag Font Collection ID string: 'ttcf' (used for fonts with CFF or CFF2 outlines as well as TrueType outlines) //uint16 majorVersion Major version of the TTC Header, = 1. //uint16 minorVersion Minor version of the TTC Header, = 0. //uint32 numFonts Number of fonts in TTC //Offset32 offsetTable[numFonts] Array of offsets to the OffsetTable for each font from the beginning of the file //TTC Header Version 2.0: //Type Name Description //TAG ttcTag Font Collection ID string: 'ttcf' //uint16 majorVersion Major version of the TTC Header, = 2. //uint16 minorVersion Minor version of the TTC Header, = 0. //uint32 numFonts Number of fonts in TTC //Offset32 offsetTable[numFonts] Array of offsets to the OffsetTable for each font from the beginning of the file //uint32 dsigTag Tag indicating that a DSIG table exists, 0x44534947 ('DSIG') (null if no signature) //uint32 dsigLength The length (in bytes) of the DSIG table (null if no signature) //uint32 dsigOffset The offset (in bytes) of the DSIG table from the beginning of the TTC file (null if no signature) var ttcHeader = new FontCollectionHeader(); ttcHeader.majorVersion = input.ReadUInt16(); ttcHeader.minorVersion = input.ReadUInt16(); uint numFonts = input.ReadUInt32(); int[] offsetTables = new int[numFonts]; for (uint i = 0; i < numFonts; ++i) { offsetTables[i] = input.ReadInt32(); } ttcHeader.numFonts = numFonts; ttcHeader.offsetTables = offsetTables; // if (ttcHeader.majorVersion == 2) { ttcHeader.dsigTag = input.ReadUInt32(); ttcHeader.dsigLength = input.ReadUInt32(); ttcHeader.dsigOffset = input.ReadUInt32(); if (ttcHeader.dsigTag == 0x44534947) { //Tag indicating that a DSIG table exists //TODO: goto DSIG add read signature } } return(ttcHeader); }
/// <summary> /// read only name entry /// </summary> /// <param name="stream"></param> /// <returns></returns> public PreviewFontInfo ReadPreview(Stream stream) { //var little = BitConverter.IsLittleEndian; using (var input = new ByteOrderSwappingBinaryReader(stream)) { ushort majorVersion = input.ReadUInt16(); ushort minorVersion = input.ReadUInt16(); if (KnownFontFiles.IsTtcf(majorVersion, minorVersion)) { //this font stream is 'The Font Collection' FontCollectionHeader ttcHeader = ReadTTCHeader(input); PreviewFontInfo[] members = new PreviewFontInfo[ttcHeader.numFonts]; for (uint i = 0; i < ttcHeader.numFonts; ++i) { input.BaseStream.Seek(ttcHeader.offsetTables[i], SeekOrigin.Begin); PreviewFontInfo member = members[i] = ReadActualFontPreview(input, false); member.ActualStreamOffset = ttcHeader.offsetTables[i]; } return(new PreviewFontInfo(BuildTtcfName(members), members)); } else if (KnownFontFiles.IsWoff(majorVersion, minorVersion)) { //check if we enable woff or not WebFont.WoffReader woffReader = new WebFont.WoffReader(); input.BaseStream.Position = 0; return(woffReader.ReadPreview(input)); } else if (KnownFontFiles.IsWoff2(majorVersion, minorVersion)) { //check if we enable woff2 or not WebFont.Woff2Reader woffReader = new WebFont.Woff2Reader(); input.BaseStream.Position = 0; return(woffReader.ReadPreview(input)); } else { return(ReadActualFontPreview(input, true));//skip version data (majorVersion, minorVersion) } } }
/// <summary> /// read only name entry /// </summary> /// <param name="stream"></param> /// <returns></returns> public PreviewFontInfo ReadPreview(Stream stream) { 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))); } NameEntry nameEntry = ReadTableIfExists(tables, input, new NameEntry()); OS2Table os2Table = ReadTableIfExists(tables, input, new OS2Table()); return(new PreviewFontInfo( nameEntry.FontName, nameEntry.FontSubFamily, Extensions.TypefaceExtensions.TranslatedOS2FontStyle(os2Table) )); } }
public Typeface Read(Stream stream, int streamStartOffset = 0, ReadFlags readFlags = ReadFlags.Full) { //bool little = BitConverter.IsLittleEndian; if (streamStartOffset > 0) { //eg. for ttc stream.Seek(streamStartOffset, SeekOrigin.Begin); } using (var input = new ByteOrderSwappingBinaryReader(stream)) { ushort majorVersion = input.ReadUInt16(); ushort minorVersion = input.ReadUInt16(); if (KnownFontFiles.IsTtcf(majorVersion, minorVersion)) { //this font stream is 'The Font Collection' //To read content of ttc=> one must specific the offset //so use read preview first=> you will know that what are inside the ttc. return(null); } else if (KnownFontFiles.IsWoff(majorVersion, minorVersion)) { //check if we enable woff or not WebFont.WoffReader woffReader = new WebFont.WoffReader(); input.BaseStream.Position = 0; return(woffReader.Read(input)); } else if (KnownFontFiles.IsWoff2(majorVersion, minorVersion)) { //check if we enable woff2 or not WebFont.Woff2Reader woffReader = new WebFont.Woff2Reader(); input.BaseStream.Position = 0; return(woffReader.Read(input)); } //----------------------------------------------------------------- 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))); } //------------------------------------------------------------------ return(ReadTableEntryCollection(tables, input)); } }
PreviewFontInfo ReadActualFontPreview(ByteOrderSwappingBinaryReader input, bool skipVersionData) { if (!skipVersionData) { 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))); } return(ReadPreviewFontInfo(tables, input)); }
/// <summary> /// read only name entry /// </summary> /// <param name="stream"></param> /// <returns></returns> public InstalledFont ReadPreview(Stream stream) { 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))); } //translate... NameEntry nameEntry = ReadTableIfExists(tables, input, new NameEntry()); return(new InstalledFont(nameEntry.FontName, nameEntry.FontSubFamily)); } }
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); } }
public Typeface Read(Stream stream, ReadFlags readFlags = ReadFlags.Full) { bool 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)); //--- 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); } }