protected override void ReadContentFrom(BinaryReader reader) { // load each strike table int beginPos = (int)reader.BaseStream.Position; var count = reader.ReadInt32(); if (count > MaxBitmapStrikes) { throw new Exception("Too many bitmap strikes in font."); } var sizeTableHeaders = new BitmapSizeTable[count]; int skipLen = sizeof(uint) + sizeof(ushort) * 2 + 12 * 2; for (int i = 0; i < count; i++) { sizeTableHeaders[i].SubTableOffset = reader.ReadUInt32(); sizeTableHeaders[i].SubTableSize = reader.ReadUInt32(); sizeTableHeaders[i].SubTableCount = reader.ReadUInt32(); // skip colorRef, metrics entries, start and end glyph indices reader.BaseStream.Position += skipLen; sizeTableHeaders[i].PpemX = reader.ReadByte(); sizeTableHeaders[i].PpemY = reader.ReadByte(); sizeTableHeaders[i].BitDepth = reader.ReadByte(); sizeTableHeaders[i].Flags = (BitmapSizeFlags)reader.ReadByte(); } // read index subtables var indexSubTables = new IndexSubTable[count]; for (int i = 0; i < count; i++) { reader.BaseStream.Seek(beginPos + sizeTableHeaders[i].SubTableOffset, SeekOrigin.Begin); indexSubTables[i] = new IndexSubTable { FirstGlyph = reader.ReadUInt16(), LastGlyph = reader.ReadUInt16(), Offset = reader.ReadUInt32() }; } // read the actual data for each strike table for (int i = 0; i < count; i++) { // read the subtable header reader.BaseStream.Seek(beginPos + sizeTableHeaders[i].SubTableOffset + indexSubTables[i].Offset, SeekOrigin.Begin); var indexFormat = reader.ReadUInt16(); var imageFormat = reader.ReadUInt16(); var imageDataOffset = reader.ReadUInt32(); } }
public Glyph[] BuildGlyphList() { List <Glyph> glyphs = new List <Glyph>(); int numSizes = _bmpSizeTables.Length; for (int n = 0; n < numSizes; ++n) { BitmapSizeTable bmpSizeTable = _bmpSizeTables[n]; uint numberofIndexSubTables = bmpSizeTable.numberOfIndexSubTables; for (uint i = 0; i < numberofIndexSubTables; ++i) { bmpSizeTable.indexSubTables[i].BuildGlyphList(glyphs); } } return(glyphs.ToArray()); }
public static SbitTable Read(BinaryReader reader, TableRecord[] tables) { if (!SfntTables.SeekToTable(reader, tables, FourCC.Eblc)) { return(null); } // skip version var baseOffset = reader.Position(); reader.Skip(sizeof(int)); // load each strike table var count = reader.ReadInt32BE(); if (count > MaxBitmapStrikes) { throw new InvalidFontException("Too many bitmap strikes in font."); } var sizeTableHeaders = new BitmapSizeTable[count]; for (int i = 0; i < count; i++) { sizeTableHeaders[i].SubTableOffset = reader.ReadUInt32BE(); sizeTableHeaders[i].SubTableSize = reader.ReadUInt32BE(); sizeTableHeaders[i].SubTableCount = reader.ReadUInt32BE(); // skip colorRef, metrics entries, start and end glyph indices reader.Skip(sizeof(uint) + sizeof(ushort) * 2 + 12 * 2); sizeTableHeaders[i].PpemX = reader.ReadByte(); sizeTableHeaders[i].PpemY = reader.ReadByte(); sizeTableHeaders[i].BitDepth = reader.ReadByte(); sizeTableHeaders[i].Flags = (BitmapSizeFlags)reader.ReadByte(); } // read index subtables var indexSubTables = new IndexSubTable[count]; for (int i = 0; i < count; i++) { reader.Seek(baseOffset + sizeTableHeaders[i].SubTableOffset); indexSubTables[i] = new IndexSubTable { FirstGlyph = reader.ReadUInt16BE(), LastGlyph = reader.ReadUInt16BE(), Offset = reader.ReadUInt32BE() }; } // read the actual data for each strike table for (int i = 0; i < count; i++) { // read the subtable header reader.Seek(baseOffset + sizeTableHeaders[i].SubTableOffset + indexSubTables[i].Offset); var indexFormat = reader.ReadUInt16BE(); var imageFormat = reader.ReadUInt16BE(); var imageDataOffset = reader.ReadUInt32BE(); } return(null); }
protected override void ReadContentFrom(BinaryReader reader) { // load each strike table int beginPos = (int)reader.BaseStream.Position; // ushort versionMajor = reader.ReadUInt16(); ushort versionMinor = reader.ReadUInt16(); uint numSizes = reader.ReadUInt32(); if (numSizes > MaxBitmapStrikes) { throw new Exception("Too many bitmap strikes in font."); } //---------------- var sizeTableHeaders = new BitmapSizeTable[numSizes]; //int skipLen = sizeof(uint) + sizeof(ushort) * 2 + 12 * 2; for (int i = 0; i < numSizes; i++) { //bitmapSizeTable //Type Name Description //Offset32 indexSubTableArrayOffset offset to index subtable from beginning of EBLC. //uint32 indexTablesSize number of bytes in corresponding index subtables and array //uint32 numberOfIndexSubTables an index subtable for each range or format change //uint32 colorRef not used; set to 0. //sbitLineMetrics hori line metrics for text rendered horizontally //sbitLineMetrics vert line metrics for text rendered vertically //uint16 startGlyphIndex lowest glyph index for this size //uint16 endGlyphIndex highest glyph index for this size //uint8 ppemX horizontal pixels per Em //uint8 ppemY vertical pixels per Em //uint8 bitDepth the Microsoft rasterizer v.1.7 or greater supports the following bitDepth values, as described below: 1, 2, 4, and 8. //int8 flags vertical or horizontal(see bitmapFlags) // //sbitLineMetrics (12 bytes) //Type Name //int8 ascender //int8 descender //uint8 widthMax //int8 caretSlopeNumerator //int8 caretSlopeDenominator //int8 caretOffset //int8 minOriginSB //int8 minAdvanceSB //int8 maxBeforeBL //int8 minAfterBL //int8 pad1 //int8 pad2 // BitmapSizeTable bmpsizeTable = new BitmapSizeTable(); bmpsizeTable.SubTableOffset = reader.ReadUInt32(); bmpsizeTable.SubTableSize = reader.ReadUInt32(); bmpsizeTable.SubTableCount = reader.ReadUInt32(); reader.ReadUInt32();//not use, colorRef The colorRef and bitDepth fields are reserved for future enhancements // //metrics entries reader.BaseStream.Position += (12 * 2); //skip line matric // bmpsizeTable.startGlyph = reader.ReadUInt16(); bmpsizeTable.endGlyph = reader.ReadUInt16(); bmpsizeTable.PpemX = reader.ReadByte(); bmpsizeTable.PpemY = reader.ReadByte(); bmpsizeTable.BitDepth = reader.ReadByte(); //The colorRef and bitDepth fields are reserved for future enhancements. For monochrome bitmaps they should have the values colorRef=0 and bitDepth=1. // //The 'flags' byte contains two bits to indicate the direction of small glyph metrics: horizontal or vertical.The remaining bits are reserved. bmpsizeTable.Flags = (BitmapSizeFlags)reader.ReadByte(); sizeTableHeaders[i] = bmpsizeTable; //save } // read index subtables var indexSubTables = new IndexSubTable[numSizes]; for (int i = 0; i < numSizes; i++) { reader.BaseStream.Seek(beginPos + sizeTableHeaders[i].SubTableOffset, SeekOrigin.Begin); //-------------------------------------------- //indexSubTableArray //Type Name Description //uint16 firstGlyphIndex first glyph code of this range //uint16 lastGlyphIndex last glyph code of this range(inclusive) //Offset32 additionalOffsetToIndexSubtable add to indexSubTableArrayOffset to get offset from beginning of 'EBLC' //-------------------------------------------- indexSubTables[i] = new IndexSubTable { FirstGlyph = reader.ReadUInt16(), LastGlyph = reader.ReadUInt16(), Offset = reader.ReadUInt32() }; } // read the actual data for each strike table for (int i = 0; i < numSizes; i++) { // read the subtable header reader.BaseStream.Seek(beginPos + sizeTableHeaders[i].SubTableOffset + indexSubTables[i].Offset, SeekOrigin.Begin); //-------------------------------------------- //indexSubHeader //-------------------------------------------- //Type Name Description //uint16 indexFormat format of this indexSubTable //uint16 imageFormat format of 'EBDT' image data //Offset32 imageDataOffset offset to image data in 'EBDT' table ushort indexFormat = reader.ReadUInt16(); ushort imageFormat = reader.ReadUInt16(); uint imageDataOffset = reader.ReadUInt32(); //There are currently five different formats used for the indexSubTable, //depending upon the size and type of bitmap data in the glyph code range. //Apple 'bloc' tables support only formats 1 through 3. //The choice of which indexSubTable format to use is up to the font manufacturer, //but should be made with the aim of minimizing the size of the font file. //Ranges of glyphs with variable metrics -that is, where glyphs may differ from each other in bounding box height, //width, side bearings or advance - must use format 1, 3 or 4.Ranges of glyphs with constant metrics can save space by using format 2 or 5, which keep a single copy of the metrics information in the indexSubTable rather than a copy per glyph in the 'EBDT' table.In some monospaced fonts it makes sense to store extra white space around some of the glyphs to keep all metrics identical, thus permitting the use of format 2 or 5. //Structures for each indexSubTable format are listed below. //TODO: impl this } }
protected override void ReadContentFrom(BinaryReader reader) { long cblcBeginPos = reader.BaseStream.Position; ushort majorVersion = reader.ReadUInt16(); //3 ushort minorVersion = reader.ReadUInt16(); //0 uint numSizes = reader.ReadUInt32(); //The CblcHeader is followed immediately by the BitmapSize table array(s). //The numSizes in the CblcHeader indicates the number of BitmapSize tables in the array. //Each strike is defined by one BitmapSize table. BitmapSizeTable[] bmpSizeTables = new BitmapSizeTable[numSizes]; for (int i = 0; i < numSizes; ++i) { bmpSizeTables[i] = BitmapSizeTable.ReadBitmapSizeTable(reader); } _bmpSizeTables = bmpSizeTables; // //------- //IndexSubTableArray //Type Name Description //uint16 firstGlyphIndex First glyph ID of this range. //uint16 lastGlyphIndex Last glyph ID of this range(inclusive). //Offset32 additionalOffsetToIndexSubtable Add to indexSubTableArrayOffset to get offset from beginning of EBLC. //After determining the strike, //the rasterizer searches this array for the range containing the given glyph ID. //When the range is found, the additionalOffsetToIndexSubtable is added to the indexSubTableArrayOffset //to get the offset of the IndexSubTable in the EBLC. //The first indexSubTableArray is located after the last bitmapSizeSubTable entry. //Then the IndexSubTables for the strike follow. //Another IndexSubTableArray(if more than one strike) and //its IndexSubTableArray are next. //The EBLC continues with an array and IndexSubTables for each strike. //We now have the offset to the IndexSubTable. //All IndexSubTable formats begin with an IndexSubHeader which identifies the IndexSubTable format, //the format of the EBDT image data, //and the offset from the beginning of the EBDT table to the beginning of the image data for this range. for (int n = 0; n < numSizes; ++n) { BitmapSizeTable bmpSizeTable = bmpSizeTables[n]; uint numberofIndexSubTables = bmpSizeTable.numberOfIndexSubTables; // IndexSubTableArray[] indexSubTableArrs = new IndexSubTableArray[numberofIndexSubTables]; for (uint i = 0; i < numberofIndexSubTables; ++i) { indexSubTableArrs[i] = new IndexSubTableArray( reader.ReadUInt16(), //First glyph ID of this range. reader.ReadUInt16(), //Last glyph ID of this range (inclusive). reader.ReadUInt32()); //Add to indexSubTableArrayOffset to get offset from beginning of EBLC. } //--- IndexSubTableBase[] subTables = new IndexSubTableBase[numberofIndexSubTables]; bmpSizeTable.indexSubTables = subTables; for (uint i = 0; i < numberofIndexSubTables; ++i) { IndexSubTableArray indexSubTableArr = indexSubTableArrs[i]; reader.BaseStream.Position = cblcBeginPos + bmpSizeTable.indexSubTableArrayOffset + indexSubTableArr.additionalOffsetToIndexSubtable; IndexSubTableBase result = subTables[i] = IndexSubTableBase.CreateFrom(bmpSizeTable, reader); result.firstGlyphIndex = indexSubTableArr.firstGlyphIndex; result.lastGlyphIndex = indexSubTableArr.lastGlyphIndex; } } }
protected override void ReadContentFrom(BinaryReader reader) { // load each strike table long eblcBeginPos = reader.BaseStream.Position; // ushort versionMajor = reader.ReadUInt16(); ushort versionMinor = reader.ReadUInt16(); uint numSizes = reader.ReadUInt32(); if (numSizes > MAX_BITMAP_STRIKES) { throw new Exception("Too many bitmap strikes in font."); } //---------------- var bmpSizeTables = new BitmapSizeTable[numSizes]; for (int i = 0; i < numSizes; i++) { bmpSizeTables[i] = BitmapSizeTable.ReadBitmapSizeTable(reader); } _bmpSizeTables = bmpSizeTables; // //------- //IndexSubTableArray //Type Name Description //uint16 firstGlyphIndex First glyph ID of this range. //uint16 lastGlyphIndex Last glyph ID of this range(inclusive). //Offset32 additionalOffsetToIndexSubtable Add to indexSubTableArrayOffset to get offset from beginning of EBLC. //After determining the strike, //the rasterizer searches this array for the range containing the given glyph ID. //When the range is found, the additionalOffsetToIndexSubtable is added to the indexSubTableArrayOffset //to get the offset of the IndexSubTable in the EBLC. //The first indexSubTableArray is located after the last bitmapSizeSubTable entry. //Then the IndexSubTables for the strike follow. //Another IndexSubTableArray(if more than one strike) and //its IndexSubTableArray are next. //The EBLC continues with an array and IndexSubTables for each strike. //We now have the offset to the IndexSubTable. //All IndexSubTable formats begin with an IndexSubHeader which identifies the IndexSubTable format, //the format of the EBDT image data, //and the offset from the beginning of the EBDT table to the beginning of the image data for this range. for (int n = 0; n < numSizes; ++n) { BitmapSizeTable bmpSizeTable = bmpSizeTables[n]; uint numberofIndexSubTables = bmpSizeTable.numberOfIndexSubTables; // IndexSubTableArray[] indexSubTableArrs = new IndexSubTableArray[numberofIndexSubTables]; for (uint i = 0; i < numberofIndexSubTables; ++i) { indexSubTableArrs[i] = new IndexSubTableArray( reader.ReadUInt16(), //First glyph ID of this range. reader.ReadUInt16(), //Last glyph ID of this range (inclusive). reader.ReadUInt32()); //Add to indexSubTableArrayOffset to get offset from beginning of EBLC. } //--- IndexSubTableBase[] subTables = new IndexSubTableBase[numberofIndexSubTables]; bmpSizeTable.indexSubTables = subTables; for (uint i = 0; i < numberofIndexSubTables; ++i) { IndexSubTableArray indexSubTableArr = indexSubTableArrs[i]; reader.BaseStream.Position = eblcBeginPos + bmpSizeTable.indexSubTableArrayOffset + indexSubTableArr.additionalOffsetToIndexSubtable; subTables[i] = IndexSubTableBase.CreateFrom(bmpSizeTable, reader); } } }