Esempio n. 1
0
        public static BitmapSizeTable ReadBitmapSizeTable(BinaryReader reader)
        {
            //EBLC's BitmapSize Table   (https://docs.microsoft.com/en-us/typography/opentype/spec/eblc)
            //Type          Name                        Description
            //Offset32      indexSubTableArrayOffset    Offset to IndexSubtableArray, from beginning of EBLC.
            //uint32        indexTablesSize             Number of bytes in corresponding index subtables and array.
            //uint32        numberOfIndexSubTables      There is an IndexSubtable 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 Bitmap Flags, below).


            //CBLC's BitmapSize Table  (https://docs.microsoft.com/en-us/typography/opentype/spec/cblc)
            //Type                Name                      Description
            //Offset32            indexSubTableArrayOffset  Offset to index subtable from beginning of CBLC.
            //uint32              indexTablesSize           Number of bytes in corresponding index subtables and array.
            //uint32              numberofIndexSubTables    There is 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                  In addtition to already defined bitDepth values 1, 2, 4, and 8
            //                                              supported by existing implementations, the value of 32 is used to
            //                                              identify color bitmaps with 8 bit per pixel RGBA channels.
            //int8                flags                     Vertical or horizontal(see the Bitmap Flags section of the EBLC table chapter).


            //The indexSubTableArrayOffset is the offset from the beginning of
            //the CBLC table to the indexSubTableArray.

            //Each strike has one of these arrays to support various formats and
            //discontiguous ranges of bitmaps.The indexTablesSize is
            //the total number of bytes in the indexSubTableArray and
            //the associated indexSubTables.
            //The numberOfIndexSubTables is a count of the indexSubTables for this strike.


            //The rest of the CBLC table structure is identical to one already defined for EBLC.


            BitmapSizeTable bmpSizeTable = new BitmapSizeTable();

            bmpSizeTable.indexSubTableArrayOffset = reader.ReadUInt32();
            bmpSizeTable.indexTablesSize          = reader.ReadUInt32();
            bmpSizeTable.numberOfIndexSubTables   = reader.ReadUInt32();
            bmpSizeTable.colorRef = reader.ReadUInt32();

            BitmapSizeTable.ReadSbitLineMetrics(reader, ref bmpSizeTable.hori);
            BitmapSizeTable.ReadSbitLineMetrics(reader, ref bmpSizeTable.vert);


            bmpSizeTable.startGlyphIndex = reader.ReadUInt16();
            bmpSizeTable.endGlyphIndex   = reader.ReadUInt16();
            bmpSizeTable.ppemX           = reader.ReadByte();
            bmpSizeTable.ppemY           = reader.ReadByte();
            bmpSizeTable.bitDepth        = reader.ReadByte();
            bmpSizeTable.flags           = (sbyte)reader.ReadByte();

            return(bmpSizeTable);
        }
Esempio n. 2
0
        public static IndexSubTableBase CreateFrom(BitmapSizeTable bmpSizeTable, BinaryReader reader)
        {
            //read IndexSubHeader
            //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.

            //There are currently five different formats used for the IndexSubTable,
            //depending upon the size and type of bitmap data in the glyph ID 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.

            IndexSubHeader header = new IndexSubHeader(
                reader.ReadUInt16(),
                reader.ReadUInt16(),
                reader.ReadUInt32()
                );

            switch (header.indexFormat)
            {
            case 1:

                //IndexSubTable1: variable - metrics glyphs with 4 - byte offsets
                //Type                  Name            Description
                //IndexSubHeader        header          Header info.
                //Offset32              offsetArray[]   offsetArray[glyphIndex] + imageDataOffset = glyphData sizeOfArray = (lastGlyph - firstGlyph + 1) + 1 + 1 pad if needed
            {
                int    nElem       = (bmpSizeTable.endGlyphIndex - bmpSizeTable.startGlyphIndex + 1);
                uint[] offsetArray = Utils.ReadUInt32Array(reader, nElem);
                //check 16 bit align padd
                IndexSubTable1 subTable = new IndexSubTable1();
                subTable.header      = header;
                subTable.offsetArray = offsetArray;
                return(subTable);
            }

            case 2:
                //IndexSubTable2: all glyphs have identical metrics
                //Type                 Name Description
                //IndexSubHeader       header  Header info.
                //uint32               imageSize   All the glyphs are of the same size.
                //BigGlyphMetrics      bigMetrics  All glyphs have the same metrics; glyph data may be compressed, byte-aligned, or bit-aligned.
            {
                IndexSubTable2 subtable = new IndexSubTable2();
                subtable.header    = header;
                subtable.imageSize = reader.ReadUInt32();
                BigGlyphMetrics.ReadBigGlyphMetric(reader, ref subtable.BigGlyphMetrics);
                return(subtable);
            }

            case 3:
                //IndexSubTable3: variable - metrics glyphs with 2 - byte offsets
                //Type                 Name         Description
                //IndexSubHeader       header       Header info.
                //Offset16             offsetArray[]   offsetArray[glyphIndex] + imageDataOffset = glyphData sizeOfArray = (lastGlyph - firstGlyph + 1) + 1 + 1 pad if needed
            {
                int      nElem       = (bmpSizeTable.endGlyphIndex - bmpSizeTable.startGlyphIndex + 1);
                ushort[] offsetArray = Utils.ReadUInt16Array(reader, nElem);
                //check 16 bit align padd
                IndexSubTable3 subTable = new IndexSubTable3();
                subTable.header      = header;
                subTable.offsetArray = offsetArray;
                return(subTable);
            }

            case 4:
                //IndexSubTable4: variable - metrics glyphs with sparse glyph codes
                //Type                Name      Description
                //IndexSubHeader      header    Header info.
                //uint32              numGlyphs Array length.
                //GlyphIdOffsetPair   glyphArray[numGlyphs + 1]   One per glyph.
            {
                IndexSubTable4 subTable = new IndexSubTable4();
                subTable.header = header;

                uint numGlyphs = reader.ReadUInt32();
                GlyphIdOffsetPair[] glyphArray = subTable.glyphArray = new GlyphIdOffsetPair[numGlyphs + 1];
                for (int i = 0; i <= numGlyphs; ++i)         //***
                {
                    glyphArray[i] = new GlyphIdOffsetPair(reader.ReadUInt16(), reader.ReadUInt16());
                }
                return(subTable);
            }

            case 5:
                //IndexSubTable5: constant - metrics glyphs with sparse glyph codes
                //Type                Name     Description
                //IndexSubHeader      header  Header info.
                //uint32              imageSize   All glyphs have the same data size.
                //BigGlyphMetrics     bigMetrics  All glyphs have the same metrics.
                //uint32              numGlyphs   Array length.
                //uint16              glyphIdArray[numGlyphs]     One per glyph, sorted by glyph ID.
            {
                IndexSubTable5 subTable = new IndexSubTable5();
                subTable.header = header;

                subTable.imageSize = reader.ReadUInt32();
                BigGlyphMetrics.ReadBigGlyphMetric(reader, ref subTable.BigGlyphMetrics);
                subTable.glyphIdArray = Utils.ReadUInt16Array(reader, (int)reader.ReadUInt32());
                return(subTable);
            }
            }

            //The size of the EBDT image data can be calculated from the IndexSubTable information.
            //For the constant-metrics formats(2 and 5) the image data size is constant,
            //and is given in the imageSize field.For the variable metrics formats(1, 3, and 4)
            //image data must be stored contiguously and in glyph ID order,
            //so the image data size may be calculated by subtracting the offset for
            //the current glyph from the offset of the next glyph.

            //Because of this, it is necessary to store one extra element in the offsetArray pointing
            //just past the end of the range’s image data.
            //This will allow the correct calculation of the image data size for the last glyph in the range.

            //Contiguous, or nearly contiguous,
            //ranges of glyph IDs are handled best by formats 1, 2, and 3 which
            //store an offset for every glyph ID in the range.
            //Very sparse ranges of glyph IDs should use format 4 or 5 which explicitly
            //call out the glyph IDs represented in the range.
            //A small number of missing glyphs can be efficiently represented in formats 1 or 3 by having
            //the offset for the missing glyph be followed by the same offset for
            //the next glyph, thus indicating a data size of zero.

            //The only difference between formats 1 and 3 is
            //the size of the offsetArray elements: format 1 uses uint32s while format 3 uses uint16s.
            //Therefore format 1 can cover a greater range(> 64k bytes)
            //while format 3 saves more space in the EBLC table.
            //Since the offsetArray elements are added to the imageDataOffset base address in the IndexSubHeader,
            //a very large set of glyph bitmap data could be addressed by splitting it into multiple ranges,
            //each less than 64k bytes in size,
            //allowing the use of the more efficient format 3.

            //The EBLC table specification requires 16 - bit alignment for all subtables.
            //This occurs naturally for IndexSubTable formats 1, 2, and 4,
            //but may not for formats 3 and 5,
            //since they include arrays of type uint16.
            //When there is an odd number of elements in these arrays
            //**it is necessary to add an extra padding element to maintain proper alignment.


            return(null);
        }