public override bool TryUpdatePosition(
                FontMetrics fontMetrics,
                GPosTable table,
                GlyphPositioningCollection collection,
                Tag feature,
                ushort index,
                int count)
            {
                if (count <= 1)
                {
                    return(false);
                }

                ushort glyphId = collection[index][0];

                if (glyphId == 0)
                {
                    return(false);
                }

                int coverage = this.coverageTable.CoverageIndexOf(glyphId);

                if (coverage > -1)
                {
                    PairSetTable pairSet  = this.pairSets[coverage];
                    ushort       glyphId2 = collection[index + 1][0];
                    if (glyphId2 == 0)
                    {
                        return(false);
                    }

                    if (pairSet.TryGetPairValueRecord(glyphId2, out PairValueRecord pairValueRecord))
                    {
                        ValueRecord record1 = pairValueRecord.ValueRecord1;
                        AdvancedTypographicUtils.ApplyPosition(collection, index, record1);

                        ValueRecord record2 = pairValueRecord.ValueRecord2;
                        AdvancedTypographicUtils.ApplyPosition(collection, (ushort)(index + 1), record2);

                        return(true);
                    }
                }

                return(false);
            }
            public static LookupType2Format1SubTable Load(BigEndianBinaryReader reader, long offset, LookupFlags lookupFlags)
            {
                // Pair Adjustment Positioning Subtable format 1.
                // +-------------+------------------------------+------------------------------------------------+
                // | Type        |  Name                        | Description                                    |
                // +=============+==============================+================================================+
                // | uint16      | posFormat                    | Format identifier: format = 1                  |
                // +-------------+------------------------------+------------------------------------------------+
                // | Offset16    | coverageOffset               | Offset to Coverage table, from beginning of    |
                // |             |                              | PairPos subtable.                              |
                // +-------------+------------------------------+------------------------------------------------+
                // | uint16      | valueFormat1                 | Defines the types of data in valueRecord1 —    |
                // |             |                              | for the first glyph in the pair (may be zero). |
                // +-------------+------------------------------+------------------------------------------------+
                // | uint16      | valueFormat2                 | Defines the types of data in valueRecord2 —    |
                // |             |                              | for the second glyph in the pair (may be zero).|
                // +-------------+------------------------------+------------------------------------------------+
                // | uint16      | pairSetCount                 | Number of PairSet tables                       |
                // +-------------+------------------------------+------------------------------------------------+
                // | Offset16    | pairSetOffsets[pairSetCount] | Array of offsets to PairSet tables.            |
                // |             |                              | Offsets are from beginning of PairPos subtable,|
                // |             |                              | ordered by Coverage Index.                     |
                // +-------------+------------------------------+------------------------------------------------+
                ushort      coverageOffset = reader.ReadOffset16();
                ValueFormat valueFormat1   = reader.ReadUInt16 <ValueFormat>();
                ValueFormat valueFormat2   = reader.ReadUInt16 <ValueFormat>();
                ushort      pairSetCount   = reader.ReadUInt16();

                using Buffer <ushort> pairSetOffsetsBuffer = new(pairSetCount);
                Span <ushort> pairSetOffsets = pairSetOffsetsBuffer.GetSpan();

                reader.ReadUInt16Array(pairSetOffsets);

                var pairSets = new PairSetTable[pairSetCount];

                for (int i = 0; i < pairSetCount; i++)
                {
                    reader.Seek(offset + pairSetOffsets[i], SeekOrigin.Begin);
                    pairSets[i] = PairSetTable.Load(reader, offset + pairSetOffsets[i], valueFormat1, valueFormat2);
                }

                var coverageTable = CoverageTable.Load(reader, offset + coverageOffset);

                return(new LookupType2Format1SubTable(coverageTable, pairSets, lookupFlags));
            }
Ejemplo n.º 3
0
            /// <summary>
            ///  Lookup Type 2: Pair Adjustment Positioning Subtable
            /// </summary>
            /// <param name="reader"></param>
            void ReadLookupType2(BinaryReader reader)
            {
                //-----------------------------------------------
                // USHORT 	PosFormat 	Format identifier-format = 1
                //Offset 	Coverage 	Offset to Coverage table-from beginning of PairPos subtable-only the first glyph in each pair
                //USHORT 	ValueFormat1 	Defines the types of data in ValueRecord1-for the first glyph in the pair -may be zero (0)
                //USHORT 	ValueFormat2 	Defines the types of data in ValueRecord2-for the second glyph in the pair -may be zero (0)
                //USHORT 	PairSetCount 	Number of PairSet tables
                //Offset 	PairSetOffset
                //[PairSetCount] 	Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index
                //                PairSet table
                //Value 	Type 	Description
                //USHORT 	PairValueCount 	Number of PairValueRecords
                //struct 	PairValueRecord
                //[PairValueCount] 	Array of PairValueRecords-ordered by GlyphID of the second glyph

                //A PairValueRecord specifies the second glyph in a pair (SecondGlyph) and defines a ValueRecord for each glyph (Value1 and Value2). If ValueFormat1 is set to zero (0) in the PairPos subtable, ValueRecord1 will be empty; similarly, if ValueFormat2 is 0, Value2 will be empty.

                //Example 4 at the end of this chapter shows a PairPosFormat1 subtable that defines two cases of pair kerning.
                //PairValueRecord
                //Value 	Type 	Description
                //GlyphID 	SecondGlyph 	GlyphID of second glyph in the pair-first glyph is listed in the Coverage table
                //ValueRecord 	Value1 	Positioning data for the first glyph in the pair
                //ValueRecord 	Value2 	Positioning data for the second glyph in the pair
                //-----------------------------------------------

                // PairPosFormat2 subtable: Class pair adjustment
                //Value 	Type 	Description
                //USHORT 	PosFormat 	Format identifier-format = 2
                //Offset 	Coverage 	Offset to Coverage table-from beginning of PairPos subtable-for the first glyph of the pair
                //USHORT 	ValueFormat1 	ValueRecord definition-for the first glyph of the pair-may be zero (0)
                //USHORT 	ValueFormat2 	ValueRecord definition-for the second glyph of the pair-may be zero (0)
                //Offset 	ClassDef1 	Offset to ClassDef table-from beginning of PairPos subtable-for the first glyph of the pair
                //Offset 	ClassDef2 	Offset to ClassDef table-from beginning of PairPos subtable-for the second glyph of the pair
                //USHORT 	Class1Count 	Number of classes in ClassDef1 table-includes Class0
                //USHORT 	Class2Count 	Number of classes in ClassDef2 table-includes Class0
                //struct 	Class1Record
                //[Class1Count] 	Array of Class1 records-ordered by Class1

                //Each Class1Record contains an array of Class2Records (Class2Record), which also are ordered by class value. 
                //One Class2Record must be declared for each class in the ClassDef2 table, including Class 0.
                //Class1Record
                //Value 	Type 	Description
                //struct 	Class2Record[Class2Count] 	Array of Class2 records-ordered by Class2

                //A Class2Record consists of two ValueRecords,
                //one for the first glyph in a class pair (Value1) and one for the second glyph (Value2).
                //If the PairPos subtable has a value of zero (0) for ValueFormat1 or ValueFormat2, 
                //the corresponding record (ValueRecord1 or ValueRecord2) will be empty.

                //Example 5 at the end of this chapter demonstrates pair kerning with glyph classes in a PairPosFormat2 subtable.
                //Class2Record
                //Value 	Type 	Description
                //ValueRecord 	Value1 	Positioning for first glyph-empty if ValueFormat1 = 0
                //ValueRecord 	Value2 	Positioning for second glyph-empty if ValueFormat2 = 0
                long thisLookupTablePos = reader.BaseStream.Position;
                int j = subTableOffsets.Length;

                for (int i = 0; i < j; ++i)
                {
                    //move to read pos
                    long subTableStartAt = lookupTablePos + subTableOffsets[i];
                    reader.BaseStream.Seek(subTableStartAt, SeekOrigin.Begin);

                    //-----------------------

                    ushort format = reader.ReadUInt16();

                    switch (format)
                    {
                        default: throw new NotSupportedException();
                        case 1:
                            {
                                short coverage = reader.ReadInt16();
                                ushort value1Format = reader.ReadUInt16();
                                ushort value2Format = reader.ReadUInt16();
                                ushort pairSetCount = reader.ReadUInt16();
                                short[] pairSetOffsetArray = Utils.ReadInt16Array(reader, pairSetCount);
                                PairSetTable[] pairSetTables = new PairSetTable[pairSetCount];
                                for (int n = 0; n < pairSetCount; ++n)
                                {
                                    //read each pair set table
                                    reader.BaseStream.Seek(thisLookupTablePos + pairSetOffsetArray[i], SeekOrigin.Begin);
                                    var pairSetTable = new PairSetTable();
                                    pairSetTable.ReadFrom(reader, value1Format, value2Format);
                                    pairSetTables[n] = pairSetTable;
                                }
                                var subTable = new LkSubTableType2(pairSetTables);
                                //coverage                                 
                                subTable.CoverageTable = CoverageTable.CreateFrom(reader, subTableStartAt + coverage);

                                subTables.Add(subTable);
                            } break;
                        case 2:
                            {


                                short coverage = reader.ReadInt16();
                                ushort value1Format = reader.ReadUInt16();
                                ushort value2Format = reader.ReadUInt16();
                                short classDef1Offset = reader.ReadInt16();
                                short classDef2Offset = reader.ReadInt16();
                                ushort class1Count = reader.ReadUInt16();
                                ushort class2Count = reader.ReadUInt16();


                                throw new NotImplementedException();

                            }
                            break;
                    }


                }
            }
Ejemplo n.º 4
0
 public LkSubTableType2(PairSetTable[] pairSetTables)
 {
     this.pairSetTables = pairSetTables;
 }