public static bool Load(FontParser parser, FontFace font, bool full) { font.RequiresLoad = !full; font.Parser = parser; // Read the version: int dec; int version = parser.ReadFixed(out dec); if (version == 1 && dec == 0) { // TTF outline format. } else { // Reset to start: parser.Position = 0; // OpenType. Read the tag (right at the start): string openTypeVersion = parser.ReadTag(); if (openTypeVersion == "OTTO") { // CFF outline format. } else { // Unsupported format. return(false); } } // Table count: int numTables = parser.ReadUInt16(); // Move to p12: parser.Position = 12; for (int i = 0; i < numTables; i++) { // Read the tables tag: string tag = parser.ReadTag(); // Move parser along: parser.Position += 4; // Read the offset: int offset = (int)parser.ReadUInt32(); // Grab the position - this allows the tables to mess it up: int basePosition = parser.Position; switch (tag) { case "cmap": parser.CmapOffset = offset; break; case "head": // Load the header: if (!HeaderTables.Load(parser, offset, font, out parser.IndexToLocFormat)) { return(false); } break; case "hhea": parser.HheaOffset = offset; break; case "hmtx": parser.HmtxOffset = offset; break; case "maxp": // Maxp table: MaxpTables.Load(parser, offset, font, out parser.GlyphCount); break; case "name": // General meta: NameTables.Load(parser, offset, font); break; case "OS/2": // OS2 table: OS2Tables.Load(parser, offset, font); break; case "post": // Postscript info table: parser.PostOffset = offset; break; case "glyf": parser.GlyfOffset = offset; break; case "loca": parser.LocaOffset = offset; break; case "GSUB": // Gsub(stitute) table. Ligatures fall through here. GsubTables.Load(parser, offset, font); break; case "CFF ": parser.CffOffset = offset; break; case "kern": parser.KernOffset = offset; break; case "GPOS": parser.GposOffset = offset; break; } // Skip meta: parser.Position = basePosition + 4; } if (full) { return(ReadTables(parser, font)); } return(true); }
public static void Load(FontParser parser, int offset, FontFace font) { // Got OS2: parser.ReadOS2 = true; // Seek: parser.Position = offset; // version int version = parser.ReadUInt16(); // xAvgCharWidth parser.ReadInt16(); // usWeightClass int weight = parser.ReadUInt16(); // usWidthClass parser.ReadUInt16(); // fsType parser.ReadUInt16(); // ySubscriptXSize parser.ReadInt16(); // ySubscriptYSize parser.ReadInt16(); // ySubscriptXOffset parser.ReadInt16(); // ySubscriptYOffset parser.ReadInt16(); // ySuperscriptXSize parser.ReadInt16(); // ySuperscriptYSize parser.ReadInt16(); // ySuperscriptXOffset parser.ReadInt16(); // ySuperscriptYOffset parser.ReadInt16(); // yStrikeoutSize font.StrikeSize = (float)parser.ReadInt16() / font.UnitsPerEmF; // yStrikeoutPosition font.StrikeOffset = (float)parser.ReadInt16() / font.UnitsPerEmF; // sFamilyClass parser.ReadInt16(); // panose: /* * byte panose=new byte[10]; * * for(int i=0;i<10;i++){ * panose[i]=parser.ReadByte(); * } */ parser.Position += 10; // ulUnicodeRange1 parser.ReadUInt32(); // ulUnicodeRange2 parser.ReadUInt32(); // ulUnicodeRange3 parser.ReadUInt32(); // ulUnicodeRange4 parser.ReadUInt32(); // achVendID parser.ReadTag(); // fsSelection int type = parser.ReadUInt16(); bool italic = ((type & 1) == 1); // bool strikeout=((type&16)==16); // bool underscore=((type&2)==2); bool oblique = ((type & 512) == 512); bool bold = ((type & 32) == 32); bool regular = ((type & 64) == 64); bool useTypo = ((type & 128) == 128); if (!bold || regular) { // Must be regular: weight = 400; } else if (weight == 0) { weight = 700; } font.SetFlags(italic || oblique, weight); // usFirstCharIndex parser.ReadUInt16(); // usLastCharIndex parser.ReadUInt16(); // sTypoAscender float ascender = (float)parser.ReadInt16() / font.UnitsPerEmF; // sTypoDescender float descender = (float)parser.ReadInt16() / font.UnitsPerEmF; // sTypoLineGap float lineGap = ((float)parser.ReadInt16() / font.UnitsPerEmF); // usWinAscent float wAscender = (float)parser.ReadUInt16() / font.UnitsPerEmF; // usWinDescent float wDescender = (float)parser.ReadUInt16() / font.UnitsPerEmF; // This is an awkward spec hack due to most windows programs // providing the wrong typo descender values. if (Fonts.UseOS2Metrics) { if (useTypo) { float halfGap = lineGap / 2f; font.Ascender = ascender + halfGap; font.Descender = halfGap - descender; font.LineGap = font.Ascender + font.Descender; } else { font.Ascender = wAscender; font.Descender = wDescender; font.LineGap = font.Ascender + font.Descender; } } if (version >= 1) { // ulCodePageRange1 parser.ReadUInt32(); // ulCodePageRange2 parser.ReadUInt32(); } if (version >= 2) { // sxHeight parser.ReadInt16(); // sCapHeight parser.ReadInt16(); // usDefaultChar parser.ReadUInt16(); // usBreakChar parser.ReadUInt16(); // usMaxContent parser.ReadUInt16(); } }
//--------------------------------------
public static bool Load(FontParser parser, FontFace font, bool full) { font.RequiresLoad = !full; font.Parser = parser; // Read the magic number: uint magic = parser.ReadUInt32(); if (magic == 0x00010000) { // TTF outline format. } else if (magic == 0x774F4646) { // WOFF 1 return(WoffLoader.Load(1, parser, font)); } else if (magic == 0x774F4632) { // WOFF 2 return(WoffLoader.Load(2, parser, font)); } else { // OpenType (probably) 0x4F54544F // Reset to start: parser.Position = 0; // OpenType. Read the tag (right at the start): string openTypeVersion = parser.ReadTag(); if (openTypeVersion == "OTTO") { // CFF outline format. } else { // Unsupported format. return(false); } } // Table count: int numTables = parser.ReadUInt16(); // Move to p12: parser.Position = 12; for (int i = 0; i < numTables; i++) { // Read the tables tag (e.g. GPOS): string tag = parser.ReadTag(); // Move parser along: parser.Position += 4; // Read the offset: int offset = (int)parser.ReadUInt32(); // Grab the position - this allows the tables to mess it up: int basePosition = parser.Position; // Handle the table now: if (!parser.HandleTable(tag, offset, font)) { return(false); } // Skip meta: parser.Position = basePosition + 4; } if (full) { return(ReadTables(parser, font)); } return(true); }
public static void Load(FontParser parser, int offset, FontFace font) { // Seek: parser.Position = offset; // version int version = parser.ReadUInt16(); // xAvgCharWidth parser.ReadInt16(); // usWeightClass int weight = parser.ReadUInt16(); // usWidthClass int stretch = parser.ReadUInt16(); // fsType parser.ReadUInt16(); // ySubscriptXSize parser.ReadInt16(); // ySubscriptYSize parser.ReadInt16(); // ySubscriptXOffset parser.ReadInt16(); // ySubscriptYOffset parser.ReadInt16(); // ySuperscriptXSize parser.ReadInt16(); // ySuperscriptYSize parser.ReadInt16(); // ySuperscriptXOffset parser.ReadInt16(); // ySuperscriptYOffset parser.ReadInt16(); // yStrikeoutSize font.StrikeSize = (float)parser.ReadInt16() / font.UnitsPerEmF; // yStrikeoutPosition font.StrikeOffset = (float)parser.ReadInt16() / font.UnitsPerEmF; // sFamilyClass parser.ReadInt16(); // panose: /* * byte panose=new byte[10]; * * for(int i=0;i<10;i++){ * panose[i]=parser.ReadByte(); * } */ parser.Position += 10; // ulUnicodeRange1 parser.ReadUInt32(); // ulUnicodeRange2 parser.ReadUInt32(); // ulUnicodeRange3 parser.ReadUInt32(); // ulUnicodeRange4 parser.ReadUInt32(); // achVendID parser.ReadTag(); // fsSelection int type = parser.ReadUInt16(); bool italic = ((type & 1) == 1); // bool strikeout=((type&16)==16); // bool underscore=((type&2)==2); bool oblique = ((type & 512) == 512); bool bold = ((type & 32) == 32); bool regular = ((type & 64) == 64); bool useTypo = ((type & 128) == 128); if (!bold || regular) { // Must be regular: weight = 400; } else if (weight == 0) { weight = 700; } int styleCode = 0; if (italic) { styleCode = FontFaceFlags.Italic; } else if (oblique) { styleCode = FontFaceFlags.Oblique; } font.SetFlags(styleCode, weight, stretch); // usFirstCharIndex parser.ReadUInt16(); // usLastCharIndex parser.ReadUInt16(); // sTypoAscender float ascender = (float)parser.ReadInt16() / font.UnitsPerEmF; // sTypoDescender float descender = (float)parser.ReadInt16() / font.UnitsPerEmF; // sTypoLineGap float lineGap = ((float)parser.ReadInt16() / font.UnitsPerEmF); // We'll now always use OS/2 unless this table isn't present, in which case HHEA takes over. // (The W3C suggested approach). if (Fonts.AlwaysUseTypo || useTypo) { // Apply as-is: font.Ascender = ascender; font.Descender = -descender; font.LineGap = lineGap; // Remove internal leading if there is one: float internalLeading = (ascender - descender) - 1f; if (internalLeading != 0f) { // Add to lineGap: font.Ascender -= internalLeading; font.LineGap += internalLeading; } // Skip windows ascent/descent parser.Position += 4; } else { // usWinAscent parser.usWinAscent = (float)parser.ReadUInt16() / font.UnitsPerEmF; // usWinDescent parser.usWinDescent = (float)parser.ReadUInt16() / font.UnitsPerEmF; } if (version >= 1) { // ulCodePageRange1 parser.ReadUInt32(); // ulCodePageRange2 parser.ReadUInt32(); } if (version >= 2) { // sxHeight parser.ReadInt16(); // sCapHeight parser.ReadInt16(); // usDefaultChar parser.ReadUInt16(); // usBreakChar parser.ReadUInt16(); // usMaxContent parser.ReadUInt16(); } }
public static bool Load(int version, FontParser parser, FontFace font) { // Load the V1/V2 header: ushort numTables; LoadHeader(version, parser, out numTables); if (version == 1) { MemoryStream ms = new MemoryStream(parser.Data); // Get the ZLIB compression helper: Compressor zLib = Compression.Get("zlib"); // Read each table next. for (int i = 0; i < numTables; i++) { string tag = parser.ReadTag(); uint offset = parser.ReadUInt32(); uint compLength = parser.ReadUInt32(); uint origLength = parser.ReadUInt32(); parser.ReadUInt32(); // origChecksum // Cache position: int pos = parser.Position; if (compLength != origLength) { // Decompress the table now (zlib) // Seek to table: ms.Position = (int)offset; // Decompressed data: byte[] decompressedTable = new byte[(int)origLength]; // Decompress now into our target bytes: zLib.Decompress(ms, decompressedTable); } else { // Ordinary table. parser.HandleTable(tag, (int)offset, font); } // Restore position: parser.Position = pos; } } else if (version == 2) { // Read each table entry next. The data here is compressed as one single block after the table meta. Woff2Table[] tableHeaders = new Woff2Table[numTables]; int offset = 0; for (int i = 0; i < numTables; i++) { // Read the table entry: byte flags = parser.ReadByte(); string tag; int tagFlag = (flags & 63); if (tagFlag == 63) { tag = parser.ReadTag(); } else { tag = TagLookup[tagFlag]; } ulong origLength = parser.ReadBase128(); ulong transformLength = 0; int transformVersion = (flags >> 6); //0-3 if (tag == "glyf" || tag == "loca") { // transform length: transformLength = parser.ReadBase128(); } offset += (int)origLength; tableHeaders[i] = new Woff2Table(tag, offset, (int)transformLength, transformVersion); } } // All ok: return(true); }
public static void Load(FontParser parser,int offset,FontFace font){ // Got OS2: parser.ReadOS2=true; // Seek: parser.Position=offset; // version int version=parser.ReadUInt16(); // xAvgCharWidth parser.ReadInt16(); // usWeightClass int weight=parser.ReadUInt16(); // usWidthClass parser.ReadUInt16(); // fsType parser.ReadUInt16(); // ySubscriptXSize parser.ReadInt16(); // ySubscriptYSize parser.ReadInt16(); // ySubscriptXOffset parser.ReadInt16(); // ySubscriptYOffset parser.ReadInt16(); // ySuperscriptXSize parser.ReadInt16(); // ySuperscriptYSize parser.ReadInt16(); // ySuperscriptXOffset parser.ReadInt16(); // ySuperscriptYOffset parser.ReadInt16(); // yStrikeoutSize font.StrikeSize=(float)parser.ReadInt16()/font.UnitsPerEmF; // yStrikeoutPosition font.StrikeOffset=(float)parser.ReadInt16()/font.UnitsPerEmF; // sFamilyClass parser.ReadInt16(); // panose: /* byte panose=new byte[10]; for(int i=0;i<10;i++){ panose[i]=parser.ReadByte(); } */ parser.Position+=10; // ulUnicodeRange1 parser.ReadUInt32(); // ulUnicodeRange2 parser.ReadUInt32(); // ulUnicodeRange3 parser.ReadUInt32(); // ulUnicodeRange4 parser.ReadUInt32(); // achVendID parser.ReadTag(); // fsSelection int type=parser.ReadUInt16(); bool italic=((type&1)==1); // bool strikeout=((type&16)==16); // bool underscore=((type&2)==2); bool oblique=((type&512)==512); bool bold=((type&32)==32); bool regular=((type&64)==64); bool useTypo=((type&128)==128); if(!bold || regular){ // Must be regular: weight=400; }else if(weight==0){ weight=700; } font.SetFlags(italic || oblique,weight); // usFirstCharIndex parser.ReadUInt16(); // usLastCharIndex parser.ReadUInt16(); // sTypoAscender float ascender=(float)parser.ReadInt16()/font.UnitsPerEmF; // sTypoDescender float descender=(float)parser.ReadInt16()/font.UnitsPerEmF; // sTypoLineGap float lineGap=((float)parser.ReadInt16()/font.UnitsPerEmF); // usWinAscent float wAscender=(float)parser.ReadUInt16()/font.UnitsPerEmF; // usWinDescent float wDescender=(float)parser.ReadUInt16()/font.UnitsPerEmF; // This is an awkward spec hack due to most windows programs // providing the wrong typo descender values. if(Fonts.UseOS2Metrics){ if(useTypo){ float halfGap=lineGap/2f; font.Ascender=ascender + halfGap; font.Descender=halfGap-descender; font.LineGap=font.Ascender + font.Descender; }else{ font.Ascender=wAscender; font.Descender=wDescender; font.LineGap=font.Ascender + font.Descender; } } if (version >= 1){ // ulCodePageRange1 parser.ReadUInt32(); // ulCodePageRange2 parser.ReadUInt32(); } if (version >= 2){ // sxHeight parser.ReadInt16(); // sCapHeight parser.ReadInt16(); // usDefaultChar parser.ReadUInt16(); // usBreakChar parser.ReadUInt16(); // usMaxContent parser.ReadUInt16(); } }