Esempio n. 1
0
        public static TupleVariationHeader Read(BinaryReader reader, int axisCount)
        {
            TupleVariationHeader header = new TupleVariationHeader();

            header.variableDataSize = reader.ReadUInt16();
            ushort tupleIndex = reader.ReadUInt16();
            int    flags      = (tupleIndex >> 12) & 0xF;                      //The high 4 bits are flags(see below).

            header.flags = flags;                                              //The high 4 bits are flags(see below).
            header.indexToSharedTupleRecArray = (ushort)(tupleIndex & 0x0FFF); // The low 12 bits are an index into a shared tuple records array.


            if ((flags & ((int)TupleIndexFormat.EMBEDDED_PEAK_TUPLE >> 12)) == ((int)TupleIndexFormat.EMBEDDED_PEAK_TUPLE >> 12))
            {
                //TODO:...
                header.peakTuple = TupleRecord.ReadTupleRecord(reader, axisCount);
            }
            if ((flags & ((int)TupleIndexFormat.INTERMEDIATE_REGION >> 12)) == ((int)TupleIndexFormat.INTERMEDIATE_REGION >> 12))
            {
                //TODO:...
                header.intermediateStartTuple = TupleRecord.ReadTupleRecord(reader, axisCount);
                header.intermediateEndTuple   = TupleRecord.ReadTupleRecord(reader, axisCount);
            }

            return(header);
        }
Esempio n. 2
0
        void ReadGlyphVariationData(BinaryReader reader, uint[] glyphVariationDataOffsets)
        {
            //------------
            //The glyphVariationData table array
            //The glyphVariationData table array follows the 'gvar' header and shared tuples array.
            //Each glyphVariationData table describes the variation data for a single glyph in the font.

            //GlyphVariationData header:
            //Type                  Name                    Description
            //uint16                tupleVariationCount     A packed field.
            //                                              The high 4 bits are flags,
            //                                              and the low 12 bits are the number of tuple variation tables for this glyph.
            //                                              The number of tuple variation tables can be any number between 1 and 4095.
            //Offset16              dataOffset              Offset from the start of the GlyphVariationData table to the serialized data
            //TupleVariationHeader  tupleVariationHeaders[tupleCount]   Array of tuple variation headers.


            long   beginAt             = reader.BaseStream.Position;
            ushort tupleVariationCount = reader.ReadUInt16();
            ushort dataOffset          = reader.ReadUInt16();
            int    flags      = tupleVariationCount >> 12;   //uppper 4 bits
            int    tupleCount = tupleVariationCount & 0xFFF; //low 12 bits are the number of tuple variation tables for this glyph

            TupleVariationHeader[] headers = new TupleVariationHeader[tupleCount];
            for (int i = 0; i < tupleCount; ++i)
            {
                TupleVariationHeader header = new TupleVariationHeader();
                header.variableDataSize = (short)reader.ReadUInt16();
                header.tupleIndex       = reader.ReadUInt16();

                TupleIndexFormat format        = (TupleIndexFormat)(header.tupleIndex >> 8); //The high 4 bits are flags(see below).
                int indexToSharedTubleRecArrat = header.tupleIndex & 0x0FFF;                 // The low 12 bits are an index into a shared tuple records array.
                if ((format & TupleIndexFormat.EMBEDDED_PEAK_TUPLE) != 0)
                {
                    //read peakTuple
                }
                if ((format & TupleIndexFormat.INTERMEDIATE_REGION) != 0)
                {
                    //read start and end tuple
                }
                headers[i] = header;
            }
        }
Esempio n. 3
0
        GlyphVariableData ReadGlyphVariationData(BinaryReader reader)
        {
            //https://docs.microsoft.com/en-gb/typography/opentype/spec/otvarcommonformats#tuple-records
            //------------
            //The glyphVariationData table array
            //The glyphVariationData table array follows the 'gvar' header and shared tuples array.
            //Each glyphVariationData table describes the variation data for a single glyph in the font.

            //GlyphVariationData header:
            //Type                  Name                    Description
            //uint16                tupleVariationCount     A packed field.
            //                                              The high 4 bits are flags,
            //                                              and the low 12 bits are the number of tuple variation tables for this glyph.
            //                                              The number of tuple variation tables can be any number between 1 and 4095.
            //Offset16              dataOffset              Offset from the start of the GlyphVariationData table to the serialized data
            //TupleVariationHeader  tupleVariationHeaders[tupleCount]   Array of tuple variation headers.

            GlyphVariableData glyphVarData = new GlyphVariableData();

            long   beginAt             = reader.BaseStream.Position;
            ushort tupleVariationCount = reader.ReadUInt16();
            ushort dataOffset          = reader.ReadUInt16();


            //The tupleVariationCount field contains a packed value that includes flags and the number of
            //logical tuple variation tables — which is also the number of physical tuple variation headers.
            //The format of the tupleVariationCount value is as follows:
            //Table 4
            //Mask      Name                Description
            //0x8000    SHARED_POINT_NUMBERS    Flag indicating that some or all tuple variation tables reference a shared set of “point” numbers.
            //                                  These shared numbers are represented as packed point number data at the start of the serialized data.***
            //0x7000    Reserved            Reserved for future use — set to 0.
            //0x0FFF    COUNT_MASK          Mask for the low bits to give the number of tuple variation tables.


            int tupleCount = tupleVariationCount & 0xFFF;//low 12 bits are the number of tuple variation tables for this glyph

            TupleVariationHeader[] tupleHaders = new TupleVariationHeader[tupleCount];
            glyphVarData.tupleHeaders = tupleHaders;

            for (int i = 0; i < tupleCount; ++i)
            {
                tupleHaders[i] = TupleVariationHeader.Read(reader, axisCount);
            }

            //read glyph serialized data (https://docs.microsoft.com/en-gb/typography/opentype/spec/otvarcommonformats#serialized-data)

            reader.BaseStream.Position = beginAt + dataOffset;
            //
            //If the sharedPointNumbers flag is set,
            //then the serialized data following the header begins with packed “point” number data.

            //In the context of a GlyphVariationData table within the 'gvar' table,
            //these identify outline point numbers for which deltas are explicitly provided.
            //In the context of the 'cvar' table, these are interpreted as CVT indices rather than point indices.
            //The format of packed point number data is described below.
            //....

            int flags = tupleVariationCount >> 12; //The high 4 bits are flags,

            if ((flags & 0x8) == 0x8)              //check the flags has SHARED_POINT_NUMBERS or not
            {
                //The serialized data block begins with shared “point” number data,
                //followed by the variation data for the tuple variation tables.
                //The shared point number data is optional:
                //it is present if the corresponding flag is set in the tupleVariationCount field of the header.
                //If present, the shared number data is represented as packed point numbers, described below.

                //https://docs.microsoft.com/en-gb/typography/opentype/spec/otvarcommonformats#packed-point-numbers

                //...
                //Packed point numbers are stored as a count followed by one or more runs of point number data.

                //The count may be stored in one or two bytes.
                //After reading the first byte, the need for a second byte can be determined.
                //The count bytes are processed as follows:

                glyphVarData._sharedPoints = new List <ushort>();
                ReadPackedPoints(reader, glyphVarData._sharedPoints);
            }

            for (int i = 0; i < tupleCount; ++i)
            {
                TupleVariationHeader header = tupleHaders[i];

                ushort dataSize     = header.variableDataSize;
                long   expect_endAt = reader.BaseStream.Position + dataSize;

#if DEBUG
                if (expect_endAt > reader.BaseStream.Length)
                {
                }
#endif
                //The variationDataSize value indicates the size of serialized data for the given tuple variation table that is contained in the serialized data.
                //It does not include the size of the TupleVariationHeader.

                if ((header.flags & ((int)TupleIndexFormat.PRIVATE_POINT_NUMBERS >> 12)) == ((int)TupleIndexFormat.PRIVATE_POINT_NUMBERS) >> 12)
                {
                    List <ushort> privatePoints = new List <ushort>();
                    ReadPackedPoints(reader, privatePoints);
                    header.PrivatePoints = privatePoints.ToArray();
                }
                else if (header.flags != 0)
                {
                }

                //Packed Deltas
                //Packed deltas are stored as a series of runs. Each delta run consists of a control byte followed by the actual delta values of that run.
                //The control byte is a packed value with flags in the high two bits and a count in the low six bits.
                //The flags specify the data size of the delta values in the run. The format of the control byte is as follows:
                //Packed Deltas
                //Mask  Name                Description
                //0x80  DELTAS_ARE_ZERO     Flag indicating that this run contains no data (no explicit delta values are stored), and that all of the deltas for this run are zero.
                //0x40  DELTAS_ARE_WORDS    Flag indicating the data type for delta values in the run. If set, the run contains 16-bit signed deltas (int16); if clear, the run contains 8-bit signed deltas (int8).
                //0x3F  DELTA_RUN_COUNT_MASK    Mask for the low 6 bits to provide the number of delta values in the run, minus one.

                List <short> packedDeltasXY = new List <short>();
                while (reader.BaseStream.Position < expect_endAt)
                {
                    byte controlByte   = reader.ReadByte();
                    int  number_in_run = (controlByte & 0x3F) + 1;

                    int flags01 = (controlByte >> 6) << 6;

                    if (flags01 == 0x80)
                    {
                        for (int nn = 0; nn < number_in_run; ++nn)
                        {
                            packedDeltasXY.Add(0);
                        }
                    }
                    else if (flags01 == 0x40)
                    {
                        //DELTAS_ARE_WORDS Flag indicating the data type for delta values in the run.If set,
                        //the run contains 16 - bit signed deltas(int16);
                        //if clear, the run contains 8 - bit signed deltas(int8).

                        for (int nn = 0; nn < number_in_run; ++nn)
                        {
                            packedDeltasXY.Add(reader.ReadInt16());
                        }
                    }
                    else if (flags01 == 0)
                    {
                        for (int nn = 0; nn < number_in_run; ++nn)
                        {
                            packedDeltasXY.Add(reader.ReadByte());
                        }
                    }
                    else
                    {
                    }
                }
                //---
                header.PackedDeltasXY = packedDeltasXY.ToArray();

#if DEBUG
                //ensure!
                if ((packedDeltasXY.Count % 2) != 0)
                {
                    System.Diagnostics.Debugger.Break();
                }
                //ensure!
                if (reader.BaseStream.Position != expect_endAt)
                {
                    System.Diagnostics.Debugger.Break();
                }
#endif
            }

            return(glyphVarData);
        }