Beispiel #1
0
        public static uint[] Load(FontParser parser, int offset, int numGlyphs, bool shortVersion)
        {
            // Seek there now:
            parser.Position = offset;

            // Extra entry is used for computing the length of the last glyph, thus +1.
            int length = numGlyphs + 1;

            // Create the output set:
            uint[] locations = new uint[length];

            // For each one..
            for (int i = 0; i < length; i++)
            {
                if (shortVersion)
                {
                    locations[i] = (uint)(parser.ReadUInt16() * 2);
                }
                else
                {
                    locations[i] = parser.ReadUInt32();
                }
            }

            return(locations);
        }
		public static uint[] Load(FontParser parser,int offset,int numGlyphs,bool shortVersion){
			
			// Seek there now:
			parser.Position=offset;
			
			// Extra entry is used for computing the length of the last glyph, thus +1.
			int length=numGlyphs+1;
			
			// Create the output set:
			uint[] locations=new uint[length];
			
			// For each one..
			for(int i=0;i<length;i++){
				
				if(shortVersion){
					locations[i]=(uint)(parser.ReadUInt16()*2);
				}else{
					locations[i]=parser.ReadUInt32();
				}
				
			}
			
			return locations;
			
		}
Beispiel #3
0
        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();
            }
        }
Beispiel #4
0
        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 bool Load(FontParser parser,int start,FontFace font,Glyph[] glyphs){
			
			// Seek there:
			parser.Position=start;
			
			// Read the version (and check if it's zero):
			if(parser.ReadUInt16()!=0){
				return false;
			}
			
			// Strangely the cmap table can have lots of tables inside it. For now we're looking for the common type 3 table.
			
			// Number of tables:
			int tableCount=parser.ReadUInt16();
			
			// Total characters in font:
			int characterCount=0;
			
			int offset=-1;
			int favour=0;
			
			for(int i = 0; i < tableCount; i += 1) {
				
				// Grab the platform ID:
				int platformId=parser.ReadUInt16();
				
				// And the encoding ID:
				int encodingId=parser.ReadUInt16();
				
				if(platformId==3 || platformId==0){
					
					if(encodingId==10){
						
						// Top favourite - most broad Unicode encoding.
						
						// Read offset:
						offset=(int)parser.ReadUInt32();
						
						break;
						
					}else if(encodingId==1 || encodingId==0){
						
						// Read offset:
						offset=(int)parser.ReadUInt32();
						
						// Mid-range favourite:
						favour=1;
						
						continue;
						
					}else if(favour==0){
						
						// Anything else we'll give a try:
						
						// Read offset (but don't break):
						offset=(int)parser.ReadUInt32();
						
						continue;
						
					}
					
				}
				
				// Skip offset:
				parser.Position+=4;
				
			}
			
			if(offset==-1){
				// We don't support this font :(
				return false;
			}
			
			// Seek to the cmap now:
			parser.Position=start+offset;
			
			// Check it's format 4:
			int format=parser.ReadUInt16();
		
			if(format>6){
				// We now have e.g. 12.0 - another short here:
				parser.Position+=2;
				
				// Size/ structure are both 4 byte ints now:
				parser.Position+=8;
				
			}else{
			
				// Size of the sub-table (map length, u16):
				parser.Position+=2;
				
				// Structure of the sub-table (map language, u16):
				parser.Position+=2;
				
			}
			
			switch(format){
				
				case 0:
				
				// Byte encoding table:
				
				for(int i=0;i<256;i++){
					
					int rByte=parser.ReadByte();
					
					Glyph glyph=glyphs[rByte];
					
					if(glyph!=null){
						characterCount++;
					
						glyph.AddCharcode(i);
					}
					
				}
				
				break;
				case 2:
				
				// The offset to the headers:
				int subOffset=parser.Position + (256 * 2);
				
				// For each high byte:
				for(int i=0;i<256;i++){
					
					// Read the index to the header and zero out the bottom 3 bits:
					int headerPosition=subOffset + (parser.ReadUInt16() & (~7));
					
					// Read the header:
					int firstCode=parser.ReadUInt16(ref headerPosition);
					int entryCount=parser.ReadUInt16(ref headerPosition);
					short idDelta=parser.ReadInt16(ref headerPosition);
					
					// Grab the current position:
					int pos=headerPosition;
					
					// Read the idRangeOffset - the last part of the header:
					pos+=parser.ReadUInt16(ref headerPosition);
					
					int maxCode=firstCode+entryCount;
					
					// Get the high byte value:
					int highByte=(i<<8);
					
					// For each low byte:
					for (int j=firstCode;j<maxCode;j++){
						
						// Get the full charcode (which might not actually exist yet):
						int charCode=highByte+j;
						
						// Read the base of the glyphIndex:
						int p=parser.ReadUInt16(ref pos);
						
						if(p==0){
							continue;
						}
						
						p=(p+idDelta) & 0xFFFF;
						
						if(p==0){
							continue;
						}
						
						Glyph glyph=glyphs[p];
						
						if(glyph!=null){
							
							characterCount++;
							
							glyph.AddCharcode(charCode);
							
						}
						
					}
				}
				
				break;
				case 4:
				
				// Segment count. It's doubled.
				int segCount=(parser.ReadUInt16() >> 1);
				
				// Search range, entry selector and range shift (don't need any):
				parser.Position+=6;
				
				int baseIndex=parser.Position;
				
				int endCountIndex=baseIndex;
				
				baseIndex+=2;
				
				int startCountIndex = baseIndex + segCount * 2;
				int idDeltaIndex = baseIndex + segCount * 4;
				int idRangeOffsetIndex = baseIndex + segCount * 6;
				
				for(int i = 0; i < segCount - 1; i ++){
					
					int endCount = parser.ReadUInt16(ref endCountIndex);
					int startCount = parser.ReadUInt16(ref startCountIndex);
					int idDelta = parser.ReadInt16(ref idDeltaIndex);
					int idRangeOffset = parser.ReadUInt16(ref idRangeOffsetIndex);
					
					for(int c = startCount; c <= endCount;c++){
						
						int glyphIndex;
						
						if(idRangeOffset != 0){
							
							// The idRangeOffset is relative to the current position in the idRangeOffset array.
							// Take the current offset in the idRangeOffset array.
							int glyphIndexOffset = (idRangeOffsetIndex - 2);
							
							// Add the value of the idRangeOffset, which will move us into the glyphIndex array.
							glyphIndexOffset += idRangeOffset;
							
							// Then add the character index of the current segment, multiplied by 2 for USHORTs.
							glyphIndexOffset += (c - startCount) * 2;
							
							glyphIndex=parser.ReadUInt16(ref glyphIndexOffset);
							
							if(glyphIndex!=0){
								glyphIndex = (glyphIndex + idDelta) & 0xFFFF;
							}
							
						}else{
							glyphIndex = (c + idDelta) & 0xFFFF;
						}
						
						// Add a charcode to the glyph now:
						Glyph glyph=glyphs[glyphIndex];
						
						if(glyph!=null){
							characterCount++;
						
							glyph.AddCharcode(c);
						}
					}
					
				}
				
				break;
				
				case 6:
				
				int firstCCode=parser.ReadUInt16();
				int entryCCount=parser.ReadUInt16();
				
				for(int i=0;i<entryCCount;i++){
					
					Glyph glyphC=glyphs[parser.ReadUInt16()];
					
					if(glyphC!=null){
					
						characterCount++;
						
						glyphC.AddCharcode(firstCCode+i);
					
					}
					
				}
				
				break;
				
				case 12:
				
				int groups=(int)parser.ReadUInt32();
				
				for(int i=0;i<groups;i++){
					int startCode=(int)parser.ReadUInt32();
					int endCode=(int)parser.ReadUInt32();
					int startGlyph=(int)parser.ReadUInt32();
					
					int count=(endCode - startCode);
					
					for(int j=0;j<=count;j++){
						
						int glyphIndex=(startGlyph+j);
						
						Glyph glyph=glyphs[glyphIndex];
						
						if(glyph!=null){
							
							characterCount++;
							
							glyph.AddCharcode(startCode+j);
							
						}
						
					}
				}
				
				break;
				
				default:
					Fonts.OnLogMessage("InfiniText does not currently support this font. If you need it, please contact us with this: Format: "+format);
				break;
			}
			
			font.CharacterCount=characterCount;
			
			return true;
			
		}
//--------------------------------------
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        private static int LoadSubTable(FontParser parser, int start, FontFace font, Glyph[] glyphs)
        {
            // Total characters in subtable:
            int characterCount = 0;

            // Seek to the cmap now:
            parser.Position = start;

            // Check it's format 4:
            int format = parser.ReadUInt16();

                        #if INFINITEXT_DEBUG
            Fonts.OnLogMessage("Cmap subtable format: " + format);
                        #endif

            if (format > 13)
            {
                // We now have e.g. 14.0 - ulong here ("Length"):
                parser.Position += 4;
            }
            else if (format > 6)
            {
                // We now have e.g. 12.0 - another short here (reserved):
                parser.Position += 2;

                // Length and language are both 4 byte ints now:
                parser.Position += 8;
            }
            else
            {
                // Size of the sub-table (map length, u16):
                parser.Position += 2;

                // Structure of the sub-table (map language, u16):
                parser.Position += 2;
            }

            switch (format)
            {
            case 0:

                // Byte encoding table:

                for (int i = 0; i < 256; i++)
                {
                    int rByte = parser.ReadByte();

                    Glyph glyph = glyphs[rByte];

                    if (glyph != null)
                    {
                        characterCount++;

                        glyph.AddCharcode(i);
                    }
                }

                break;

            case 2:

                // The offset to the headers:
                int subOffset = parser.Position + (256 * 2);

                // For each high byte:
                for (int i = 0; i < 256; i++)
                {
                    // Read the index to the header and zero out the bottom 3 bits:
                    int headerPosition = subOffset + (parser.ReadUInt16() & (~7));

                    // Read the header:
                    int   firstCode  = parser.ReadUInt16(ref headerPosition);
                    int   entryCount = parser.ReadUInt16(ref headerPosition);
                    short idDelta    = parser.ReadInt16(ref headerPosition);

                    // Grab the current position:
                    int pos = headerPosition;

                    // Read the idRangeOffset - the last part of the header:
                    pos += parser.ReadUInt16(ref headerPosition);

                    int maxCode = firstCode + entryCount;

                    // Get the high byte value:
                    int highByte = (i << 8);

                    // For each low byte:
                    for (int j = firstCode; j < maxCode; j++)
                    {
                        // Get the full charcode (which might not actually exist yet):
                        int charCode = highByte + j;

                        // Read the base of the glyphIndex:
                        int p = parser.ReadUInt16(ref pos);

                        if (p == 0)
                        {
                            continue;
                        }

                        p = (p + idDelta) & 0xFFFF;

                        if (p == 0)
                        {
                            continue;
                        }

                        Glyph glyph = glyphs[p];

                        if (glyph != null)
                        {
                            characterCount++;

                            glyph.AddCharcode(charCode);
                        }
                    }
                }

                break;

            case 4:

                // Segment count. It's doubled.
                int segCount = (parser.ReadUInt16() >> 1);

                // Search range, entry selector and range shift (don't need any):
                parser.Position += 6;

                int baseIndex = parser.Position;

                int endCountIndex = baseIndex;

                baseIndex += 2;

                int startCountIndex    = baseIndex + segCount * 2;
                int idDeltaIndex       = baseIndex + segCount * 4;
                int idRangeOffsetIndex = baseIndex + segCount * 6;

                for (int i = 0; i < segCount - 1; i++)
                {
                    int endCount      = parser.ReadUInt16(ref endCountIndex);
                    int startCount    = parser.ReadUInt16(ref startCountIndex);
                    int idDelta       = parser.ReadInt16(ref idDeltaIndex);
                    int idRangeOffset = parser.ReadUInt16(ref idRangeOffsetIndex);

                    for (int c = startCount; c <= endCount; c++)
                    {
                        int glyphIndex;

                        if (idRangeOffset != 0)
                        {
                            // The idRangeOffset is relative to the current position in the idRangeOffset array.
                            // Take the current offset in the idRangeOffset array.
                            int glyphIndexOffset = (idRangeOffsetIndex - 2);

                            // Add the value of the idRangeOffset, which will move us into the glyphIndex array.
                            glyphIndexOffset += idRangeOffset;

                            // Then add the character index of the current segment, multiplied by 2 for USHORTs.
                            glyphIndexOffset += (c - startCount) * 2;

                            glyphIndex = parser.ReadUInt16(ref glyphIndexOffset);

                            if (glyphIndex != 0)
                            {
                                glyphIndex = (glyphIndex + idDelta) & 0xFFFF;
                            }
                        }
                        else
                        {
                            glyphIndex = (c + idDelta) & 0xFFFF;
                        }

                        // Add a charcode to the glyph now:
                        Glyph glyph = glyphs[glyphIndex];

                        if (glyph != null)
                        {
                            characterCount++;

                            glyph.AddCharcode(c);
                        }
                    }
                }

                break;

            case 6:

                int firstCCode  = parser.ReadUInt16();
                int entryCCount = parser.ReadUInt16();

                for (int i = 0; i < entryCCount; i++)
                {
                    Glyph glyphC = glyphs[parser.ReadUInt16()];

                    if (glyphC != null)
                    {
                        characterCount++;

                        glyphC.AddCharcode(firstCCode + i);
                    }
                }

                break;

            case 10:

                // Trimmed array. Similar to format 6.

                int startCharCode = parser.ReadUInt16();
                int numChars      = parser.ReadUInt16();

                for (int i = 0; i < numChars; i++)
                {
                    Glyph glyphC = glyphs[parser.ReadUInt16()];

                    if (glyphC != null)
                    {
                        characterCount++;

                        glyphC.AddCharcode(startCharCode + i);
                    }
                }

                break;

            case 12:

                // Segmented coverage.
                // Mapping of 1 charcode to 1 glyph. "Segmented" because it can come in blocks called groups.

                int groups = (int)parser.ReadUInt32();

                // For each group of glyphs..
                for (int i = 0; i < groups; i++)
                {
                    // Start/end charcode:
                    int startCode = (int)parser.ReadUInt32();
                    int endCode   = (int)parser.ReadUInt32();

                    // Start glyph ID:
                    int startGlyph = (int)parser.ReadUInt32();

                    int count = (endCode - startCode);

                    // For each glyph/charcode pair..
                    for (int j = 0; j <= count; j++)
                    {
                        // Get the glyph:
                        int glyphIndex = (startGlyph + j);

                        Glyph glyph = glyphs[glyphIndex];

                        if (glyph != null)
                        {
                            characterCount++;

                            // Charcode is..
                            glyph.AddCharcode(startCode + j);
                        }
                    }
                }

                break;

            case 13:

                // Many to one. Same format as #12 but the meaning is a bit different.

                // How many groups?
                int glyphCount = (int)parser.ReadUInt32();

                for (int i = 0; i < glyphCount; i++)
                {
                    int startCode = (int)parser.ReadUInt32();
                    int endCode   = (int)parser.ReadUInt32();
                    int glyphID   = (int)parser.ReadUInt32();

                    // Get the glyph:
                    Glyph glyph = glyphs[glyphID];

                    if (glyph != null)
                    {
                        int count = (endCode - startCode);

                        // For each charcode..
                        for (int j = 0; j <= count; j++)
                        {
                            characterCount++;

                            // Hook up glyph to this charcode:
                            glyph.AddCharcode(startCode + j);
                        }
                    }
                }

                break;

            case 14:

                Fonts.OnLogMessage("InfiniText partially supports part of the font '" + font.Family.Name + "' - this is harmless. Search for this message for more.");

                // This font contains a format 14 CMAP Table.
                // Format 14 is "Unicode variation selectors" - essentially different versions of the same character.
                // E.g. a text Emoji character and a graphical one.
                // In a text system like InfiniText, that just means we must map a bunch of different charcodes
                // to the same glyph.

                // .. I Think! As usual, the OpenType spec doesn't make too much sense.
                // However, it appears to be entirely optional.

                // So, approx implementation is below, however getting the utf32 code point from the variation + base character
                // is completely undocumented - my best guess unfortunately threw errors.

                // See the commented out block below!

                break;

            /*
             *
             * case 14:
             *
             * // How many var selector records?
             * int records=(int)parser.ReadUInt32();
             *
             * for(int i=0;i<records;i++){
             *
             *      // variation selector:
             *      int varSelector=(int)parser.ReadUInt24();
             *
             *      // Offsets:
             *      int defaultUVSOffset=(int)parser.ReadUInt32();
             *      int nonDefaultUVSOffset=(int)parser.ReadUInt32();
             *
             *      // Grab parser position:
             *      int position=parser.Position;
             *
             *      // Got a ref to a default style table?
             *      if(defaultUVSOffset!=0){
             *
             *              // Yep! The UVS is simply a list of "base" characters, each with ranges of available charcodes.
             *              // [BaseCharCode][The extended part. Each of these comes from the range.]
             *              // The actual glyph is the one that we get by directly looking up each of the base characters.
             *
             *              // Seek to the table:
             *              parser.Position=start+defaultUVSOffset;
             *
             *              // Read the unicode value ranges count:
             *              int numUniRangesCount=(int)parser.ReadUInt32();
             *
             *              // For each one..
             *              for(int m=0;m<numUniRangesCount;m++){
             *
             *                      // Read the base charcode:
             *                      int baseCharcode=(int)parser.ReadUInt24();
             *
             *                      // Read the size of the range:
             *                      byte rangeSize=parser.ReadByte();
             *
             *                      for(int c=0;c<=rangeSize;c++){
             *
             *                              // Fetch the base glyph:
             *                              Glyph glyph=font.GetGlyphDirect(baseCharcode);
             *
             *                              if(glyph!=null){
             *
             *                                      // Combine baseCharcode with varSelector next to form the variation (of "glyph").
             *
             *                                      // Get the full charcode (this is incorrect!):
             *                                      // int charcode=char.ConvertToUtf32((char)baseCharcode,(char)varSelector);
             *
             *                                      // Add:
             *                                      //glyph.AddCharcode(charcode);
             *
             *                              }
             *
             *                              // Move baseCharcode along:
             *                              baseCharcode++;
             *
             *                      }
             *
             *              }
             *
             *              // Restore parser:
             *              parser.Position=position;
             *
             *      }
             *
             *      // Got a ref to a non-default style table?
             *      if(nonDefaultUVSOffset!=0){
             *
             *              // Yep! The UVS is simply a list of "base" characters, each with ranges of available charcodes.
             *              // [BaseCharCode][The extended part. Each of these comes from the range.]
             *              // This time though, the glyph to use is directly specified
             *              // (that's what gives it the "non-default" property).
             *
             *              // Seek to the table:
             *              parser.Position=start+nonDefaultUVSOffset;
             *
             *              // Read the number of mappings:
             *              int numMappings=(int)parser.ReadUInt32();
             *
             *              // For each one..
             *              for(int m=0;m<numMappings;m++){
             *
             *                      // Read the base charcode:
             *                      int baseCharcode=(int)parser.ReadUInt24();
             *
             *                      // Read glyph ID:
             *                      int glyphID=(int)parser.ReadUInt16();
             *
             *                      // Get the glyph:
             *                      Glyph glyph=glyphs[glyphID];
             *
             *                      if(glyph!=null){
             *
             *                              // Combine baseCharcode with varSelector next to form the variation (of "glyph").
             *
             *                              // Get the full charcode (this is incorrect!):
             *                              // int charcode=char.ConvertToUtf32((char)baseCharcode,(char)varSelector);
             *
             *                              // Add:
             *                              //glyph.AddCharcode(charcode);
             *
             *                      }
             *
             *              }
             *
             *              // Restore parser:
             *              parser.Position=position;
             *
             *      }
             *
             * }
             *
             * break;
             *
             */

            default:
                Fonts.OnLogMessage("InfiniText does not currently support part of this font. If you need it, please contact us with this: Format: " + format);
                break;
            }

            return(characterCount);
        }
Beispiel #10
0
        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(FontParser parser, int offset, FontFace font, out int locFormatIndex)
        {
            // Seek there now:
            parser.Position = offset;

            // Version:
            parser.ReadVersion();

            // Revision:
            parser.ReadRevision();

            // Checksum adjustment:
            parser.ReadUInt32();

            // Magic number:
            if (parser.ReadUInt32() != 0x5F0F3CF5)
            {
                locFormatIndex = 0;

                return(false);
            }

            // Flags:
            parser.ReadUInt16();

            // Units per em:
            font.UnitsPerEm  = parser.ReadUInt16();
            font.UnitsPerEmF = (float)font.UnitsPerEm;

            // Skip created and modified:
            parser.ReadTime();
            parser.ReadTime();

            // X min:
            parser.ReadInt16();

            // Y min:
            parser.ReadInt16();

            // X max:
            parser.ReadInt16();

            // Y max:
            parser.ReadInt16();

            // Mac style:
            parser.ReadUInt16();

            // Lowest Rec PPEM:
            parser.ReadUInt16();

            // Font direction hint:
            parser.ReadInt16();

            // Index for the loc format:
            locFormatIndex = parser.ReadInt16();             // 50

            // Glyph data format:
            parser.ReadInt16();

            return(true);
        }
Beispiel #12
0
        public static void Load(FontParser parser, int offset, FontFace font, out int numberOfGlyphs)
        {
            // Seek:
            parser.Position = offset;

            // version
            float version = parser.ReadVersion();

            // Italic angle. For some reason it's inverted in the spec - negative means a slope to the right.
            int frac;
            int dec = parser.ReadFixed(out frac);

            if (frac != 0)
            {
                // Figure it out:
                float angle = (float)dec / (float)frac;

                // Apply it (un-inverted):
                font.SetItalicAngle(-angle);
            }

            // underlinePosition
            parser.ReadInt16();

            // underlineThickness
            parser.ReadInt16();

            // isFixedPitch
            parser.ReadUInt32();

            // minMemType42
            parser.ReadUInt32();

            // maxMemType42
            parser.ReadUInt32();

            // minMemType1
            parser.ReadUInt32();

            // maxMemType1
            parser.ReadUInt32();

            if (version == 2f)
            {
                numberOfGlyphs = parser.ReadUInt16();

                /*
                 * string[] glyphNames=new string[numberOfGlyphs];
                 *
                 * for (int i = 0; i < numberOfGlyphs; i++) {
                 *
                 *      // Read the index:
                 *      int index = parser.ReadUInt16();
                 *
                 *      if(index >= StandardNames.Length){
                 *
                 *              // Read the name:
                 *              glyphNames[i]=parser.ReadString(parser.ReadByte());
                 *
                 *      }else{
                 *
                 *              // Grab the std name:
                 *              glyphNames[i]=StandardNames[index];
                 *
                 *      }
                 *
                 * }
                 */
            }
            else if (version == 2.5f)
            {
                numberOfGlyphs = parser.ReadUInt16();

                /*
                 * byte[] offsets = new byte[numberOfGlyphs];
                 *
                 * for (int i = 0; i < post.numberOfGlyphs; i++){
                 *
                 *      offsets[i] = parser.ReadByte();
                 *
                 * }
                 */
            }
            else
            {
                numberOfGlyphs = -1;
            }
        }
Beispiel #13
0
        public static bool Load(FontParser parser, int start, FontFace font, Glyph[] glyphs)
        {
            // Seek there:
            parser.Position = start;

            // Read the version (and check if it's zero):
            if (parser.ReadUInt16() != 0)
            {
                return(false);
            }

            // Strangely the cmap table can have lots of tables inside it. For now we're looking for the common type 3 table.

            // Number of tables:
            int tableCount = parser.ReadUInt16();

            // Total characters in font:
            int characterCount = 0;

            int offset = -1;
            int favour = 0;

            for (int i = 0; i < tableCount; i += 1)
            {
                // Grab the platform ID:
                int platformId = parser.ReadUInt16();

                // And the encoding ID:
                int encodingId = parser.ReadUInt16();

                if (platformId == 3 || platformId == 0)
                {
                    if (encodingId == 10)
                    {
                        // Top favourite - most broad Unicode encoding.

                        // Read offset:
                        offset = (int)parser.ReadUInt32();

                        break;
                    }
                    else if (encodingId == 1 || encodingId == 0)
                    {
                        // Read offset:
                        offset = (int)parser.ReadUInt32();

                        // Mid-range favourite:
                        favour = 1;

                        continue;
                    }
                    else if (favour == 0)
                    {
                        // Anything else we'll give a try:

                        // Read offset (but don't break):
                        offset = (int)parser.ReadUInt32();

                        continue;
                    }
                }

                // Skip offset:
                parser.Position += 4;
            }

            if (offset == -1)
            {
                // We don't support this font :(
                return(false);
            }

            // Seek to the cmap now:
            parser.Position = start + offset;

            // Check it's format 4:
            int format = parser.ReadUInt16();

            if (format > 6)
            {
                // We now have e.g. 12.0 - another short here:
                parser.Position += 2;

                // Size/ structure are both 4 byte ints now:
                parser.Position += 8;
            }
            else
            {
                // Size of the sub-table (map length, u16):
                parser.Position += 2;

                // Structure of the sub-table (map language, u16):
                parser.Position += 2;
            }

            switch (format)
            {
            case 0:

                // Byte encoding table:

                for (int i = 0; i < 256; i++)
                {
                    int rByte = parser.ReadByte();

                    Glyph glyph = glyphs[rByte];

                    if (glyph != null)
                    {
                        characterCount++;

                        glyph.AddCharcode(i);
                    }
                }

                break;

            case 2:

                // The offset to the headers:
                int subOffset = parser.Position + (256 * 2);

                // For each high byte:
                for (int i = 0; i < 256; i++)
                {
                    // Read the index to the header and zero out the bottom 3 bits:
                    int headerPosition = subOffset + (parser.ReadUInt16() & (~7));

                    // Read the header:
                    int   firstCode  = parser.ReadUInt16(ref headerPosition);
                    int   entryCount = parser.ReadUInt16(ref headerPosition);
                    short idDelta    = parser.ReadInt16(ref headerPosition);

                    // Grab the current position:
                    int pos = headerPosition;

                    // Read the idRangeOffset - the last part of the header:
                    pos += parser.ReadUInt16(ref headerPosition);

                    int maxCode = firstCode + entryCount;

                    // Get the high byte value:
                    int highByte = (i << 8);

                    // For each low byte:
                    for (int j = firstCode; j < maxCode; j++)
                    {
                        // Get the full charcode (which might not actually exist yet):
                        int charCode = highByte + j;

                        // Read the base of the glyphIndex:
                        int p = parser.ReadUInt16(ref pos);

                        if (p == 0)
                        {
                            continue;
                        }

                        p = (p + idDelta) & 0xFFFF;

                        if (p == 0)
                        {
                            continue;
                        }

                        Glyph glyph = glyphs[p];

                        if (glyph != null)
                        {
                            characterCount++;

                            glyph.AddCharcode(charCode);
                        }
                    }
                }

                break;

            case 4:

                // Segment count. It's doubled.
                int segCount = (parser.ReadUInt16() >> 1);

                // Search range, entry selector and range shift (don't need any):
                parser.Position += 6;

                int baseIndex = parser.Position;

                int endCountIndex = baseIndex;

                baseIndex += 2;

                int startCountIndex    = baseIndex + segCount * 2;
                int idDeltaIndex       = baseIndex + segCount * 4;
                int idRangeOffsetIndex = baseIndex + segCount * 6;

                for (int i = 0; i < segCount - 1; i++)
                {
                    int endCount      = parser.ReadUInt16(ref endCountIndex);
                    int startCount    = parser.ReadUInt16(ref startCountIndex);
                    int idDelta       = parser.ReadInt16(ref idDeltaIndex);
                    int idRangeOffset = parser.ReadUInt16(ref idRangeOffsetIndex);

                    for (int c = startCount; c <= endCount; c++)
                    {
                        int glyphIndex;

                        if (idRangeOffset != 0)
                        {
                            // The idRangeOffset is relative to the current position in the idRangeOffset array.
                            // Take the current offset in the idRangeOffset array.
                            int glyphIndexOffset = (idRangeOffsetIndex - 2);

                            // Add the value of the idRangeOffset, which will move us into the glyphIndex array.
                            glyphIndexOffset += idRangeOffset;

                            // Then add the character index of the current segment, multiplied by 2 for USHORTs.
                            glyphIndexOffset += (c - startCount) * 2;

                            glyphIndex = parser.ReadUInt16(ref glyphIndexOffset);

                            if (glyphIndex != 0)
                            {
                                glyphIndex = (glyphIndex + idDelta) & 0xFFFF;
                            }
                        }
                        else
                        {
                            glyphIndex = (c + idDelta) & 0xFFFF;
                        }

                        // Add a charcode to the glyph now:
                        Glyph glyph = glyphs[glyphIndex];

                        if (glyph != null)
                        {
                            characterCount++;

                            glyph.AddCharcode(c);
                        }
                    }
                }

                break;

            case 6:

                int firstCCode  = parser.ReadUInt16();
                int entryCCount = parser.ReadUInt16();

                for (int i = 0; i < entryCCount; i++)
                {
                    Glyph glyphC = glyphs[parser.ReadUInt16()];

                    if (glyphC != null)
                    {
                        characterCount++;

                        glyphC.AddCharcode(firstCCode + i);
                    }
                }

                break;

            case 12:

                int groups = (int)parser.ReadUInt32();

                for (int i = 0; i < groups; i++)
                {
                    int startCode  = (int)parser.ReadUInt32();
                    int endCode    = (int)parser.ReadUInt32();
                    int startGlyph = (int)parser.ReadUInt32();

                    int count = (endCode - startCode);

                    for (int j = 0; j <= count; j++)
                    {
                        int glyphIndex = (startGlyph + j);

                        Glyph glyph = glyphs[glyphIndex];

                        if (glyph != null)
                        {
                            characterCount++;

                            glyph.AddCharcode(startCode + j);
                        }
                    }
                }

                break;

            default:
                Fonts.OnLogMessage("InfiniText does not currently support this font. If you need it, please contact us with this: Format: " + format);
                break;
            }

            font.CharacterCount = characterCount;

            return(true);
        }
		public static bool Load(FontParser parser,int offset,FontFace font,out int locFormatIndex){
			
			// Seek there now:
			parser.Position=offset;
			
			// Version:
			parser.ReadVersion();
			
			// Revision:
			parser.ReadRevision();
			
			// Checksum adjustment:
			parser.ReadUInt32();
			
			// Magic number:
			if(parser.ReadUInt32()!=0x5F0F3CF5){
				
				locFormatIndex=0;
				
				return false;
				
			}
			
			// Flags:
			parser.ReadUInt16();
			
			// Units per em:
			font.UnitsPerEm = parser.ReadUInt16();
			font.UnitsPerEmF = (float)font.UnitsPerEm;
			
			// Skip created and modified:
			parser.ReadTime();
			parser.ReadTime();
			
			// X min:
			parser.ReadInt16();
			
			// Y min:
			parser.ReadInt16();
			
			// X max:
			parser.ReadInt16();
			
			// Y max:
			parser.ReadInt16();
			
			// Mac style:
			parser.ReadUInt16();
			
			// Lowest Rec PPEM:
			parser.ReadUInt16();
			
			// Font direction hint:
			parser.ReadInt16();
			
			// Index for the loc format:
			locFormatIndex = parser.ReadInt16(); // 50
			
			// Glyph data format:
			parser.ReadInt16();
			
			return true;
			
		}
Beispiel #15
0
        public static bool Load(FontParser parser, int start, FontFace font, Glyph[] glyphs)
        {
            // Seek there:
            parser.Position = start;

            // Read the version (and check if it's zero):
            if (parser.ReadUInt16() != 0)
            {
                return(false);
            }

            // Strangely the cmap table can have lots of tables inside it. For now we're looking for the common type 3 table.

            // -> Got to grab all tables for a particular "platform".
            // -> Prefer platform 3 (Microsoft, most common and best documented), then 0, then anything else.

            // So, first let's figure out which platform we'll be using.

            // Favourite platform so far:
            int selectedPlatform = -1;

            // Number of tables:
            int tableCount = parser.ReadUInt16();

            for (int i = 0; i < tableCount; i += 1)
            {
                // Grab the platform ID:
                int platformId = parser.ReadUInt16();

                if (platformId == 0)
                {
                    // Great, got platform 0.
                    // Just halt there because we know this fonts got 0 so we'll use that.
                    selectedPlatform = 0;
                    break;
                }
                else if (platformId == 3)
                {
                    // Prefer 3 over others:
                    selectedPlatform = 3;
                }
                else if (selectedPlatform == -1)
                {
                    // Anything else (last resort):
                    selectedPlatform = platformId;
                }

                // Skip encoding ID and offset:
                parser.Position += 6;
            }

            if (selectedPlatform == -1)
            {
                // Empty table! Return.
                return(false);
            }

            // Round 2. This time, select all subtables of the favourite platform.
            // Then collect the offset and load it up.

            // Reset parser, skipping count and version:
            parser.Position = start + 4;

            // For each table..
            for (int i = 0; i < tableCount; i += 1)
            {
                // Grab the platform ID:
                int platformId = parser.ReadUInt16();

                                #if INFINITEXT_DEBUG
                // And the encoding ID:
                int encodingId = parser.ReadUInt16();

                Fonts.OnLogMessage("Font " + font.FamilyName + " cmap subtable. Platform ID: " + platformId + ", encoding ID: " + encodingId);
                                #else
                // And the encoding ID:
                parser.ReadUInt16();
                                #endif

                if (platformId == selectedPlatform)
                {
                    // Read offset:
                    int offset = (int)parser.ReadUInt32();

                    // Get position:
                    int position = parser.Position;

                    // Load the subtable now:
                    font.CharacterCount += LoadSubTable(parser, start + offset, font, glyphs);

                    // Reset parser:
                    parser.Position = position;
                }
                else
                {
                    // Skip offset:
                    parser.Position += 4;
                }
            }

            return(true);
        }
		public static void Load(FontParser parser,int offset,FontFace font,out int numberOfGlyphs){
			
			// Seek:
			parser.Position=offset;
			
			// version
			float version=parser.ReadVersion();
			
			// Italic angle. For some reason it's inverted in the spec - negative means a slope to the right.
			int frac;
			int dec=parser.ReadFixed(out frac);
			
			if(frac!=0){
				
				// Figure it out:
				float angle=(float)dec/(float)frac;
				
				// Apply it (un-inverted):
				font.SetItalicAngle(-angle);
				
			}
			
			// underlinePosition
			parser.ReadInt16();
			
			// underlineThickness
			parser.ReadInt16();
			
			// isFixedPitch
			parser.ReadUInt32();
			
			// minMemType42
			parser.ReadUInt32();
			
			// maxMemType42
			parser.ReadUInt32();
			
			// minMemType1
			parser.ReadUInt32();
			
			// maxMemType1
			parser.ReadUInt32();
			
			if(version==2f){
				
				numberOfGlyphs = parser.ReadUInt16();
				
				/*
				string[] glyphNames=new string[numberOfGlyphs];
				
				for (int i = 0; i < numberOfGlyphs; i++) {
					
					// Read the index:
					int index = parser.ReadUInt16();
					
					if(index >= StandardNames.Length){
						
						// Read the name:
						glyphNames[i]=parser.ReadString(parser.ReadByte());
						
					}else{
						
						// Grab the std name:
						glyphNames[i]=StandardNames[index];
						
					}
					
				}
				*/
				
			}else if(version==2.5f){
				numberOfGlyphs = parser.ReadUInt16();
				
				/*
				byte[] offsets = new byte[numberOfGlyphs];
				
				for (int i = 0; i < post.numberOfGlyphs; i++){
					
					offsets[i] = parser.ReadByte();
					
				}
				*/
			}else{
				numberOfGlyphs=-1;
			}
			
		}
		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();
			}
			
			
		}