Пример #1
0
        public unsafe void ApplyContextualLookups( 
            IOpenTypeFont           Font,           // Font access interface
            OpenTypeTags            TableTag,       // Layout table tag (GSUB or GPOS) 
            FontTable               Table,          // Layout table (GSUB or GPOS)
            LayoutMetrics           Metrics,        // LayoutMetrics
            int                     CharCount,      // Characters count (i.e. Charmap.Length);
            UshortList              Charmap,        // Char to glyph mapping 
            GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs
            int*                    Advances,       // Glyph adv.widths 
            LayoutOffset*           Offsets,        // Glyph offsets 
            ushort                  LookupFlags,    // Lookup table flags
            int                     FirstGlyph,     // where to apply it 
            int                     AfterLastGlyph, // how long is a context we can use
            uint                    Parameter,      // lookup parameter
            int                     nestingLevel,   // Contextual lookup nesting level
            out int                 nextGlyph       // out: next glyph index 
            )
        { 
            // Limit nesting level for contextual lookups to 
            // prevent infinite loops from corrupt fonts
            if (nestingLevel >=  MaximumContextualLookupNestingLevel) 
            {
                nextGlyph = AfterLastGlyph;
                return;
            } 

            LookupList lookupList; 
            if (TableTag == OpenTypeTags.GSUB) 
            {
                lookupList = (new GSUBHeader(0)).GetLookupList(Table); 
            }
            else
            {
                lookupList = (new GPOSHeader(0)).GetLookupList(Table); 
            }
 
            int prevLookupIndex   = -1; 
            int prevSequenceIndex = -1;
 
            while (true)
            {
                ushort lookupIndex = ushort.MaxValue;
                ushort sequenceIndex = ushort.MaxValue; 

                for(ushort i = 0; i < recordCount; i++) 
                { 
                    ushort recordLookupIndex   = LookupIndex(Table,i);
                    ushort recordSequenceIndex = SequenceIndex(Table,i); 

                    if (recordLookupIndex < prevLookupIndex ||
                        (recordLookupIndex == prevLookupIndex &&
                         recordSequenceIndex <= prevSequenceIndex 
                        )
                       ) 
                    { 
                        // This record we already should have been processed
                        continue; 
                    }

                    // Among not proccessed record, find next one
                    if ( recordLookupIndex < lookupIndex || 
                         (recordLookupIndex == lookupIndex &&
                          recordSequenceIndex < sequenceIndex 
                         ) 
                       )
                    { 
                        lookupIndex = recordLookupIndex;
                        sequenceIndex = recordSequenceIndex;
                    }
                } 

                if (lookupIndex == ushort.MaxValue) 
                { 
                    // All records processed (or we had duplicate records, which we skipped automatically)
                    break; 
                }

                //remember for the next iteration
                prevLookupIndex   = lookupIndex; 
                prevSequenceIndex = sequenceIndex;
 
                // Now find actual glyph where to apply lookup (may depend on lookup flags) 

                int recordFirstGlyph = FirstGlyph; 
                for (int i = 0; i < sequenceIndex && recordFirstGlyph < AfterLastGlyph; i++)
                {
                    recordFirstGlyph = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo,
                                                                         recordFirstGlyph + 1, 
                                                                         LookupFlags,
                                                                         LayoutEngine.LookForward 
                                                                        ); 
                }
 
                if (recordFirstGlyph >= AfterLastGlyph)
                {
                    // Requested position is outside of input sequence, do nothing.
                    continue; 
                }
 
                // And finally apply lookup 

                int prevLength = GlyphInfo.Length; 
                int dummyNextGlyph;
                LayoutEngine.ApplyLookup(
                                            Font,
                                            TableTag, 
                                            Table,
                                            Metrics, 
                                            lookupList.Lookup(Table, lookupIndex), 
                                            CharCount,
                                            Charmap, 
                                            GlyphInfo,
                                            Advances,
                                            Offsets,
 
                                            recordFirstGlyph,
                                            AfterLastGlyph, 
                                            Parameter, 
                                            nestingLevel + 1,
                                            out dummyNextGlyph // we don't need it here 
                                          );
                //We need to adjust afterLastGlyph, in case non-single substitution happened
                AfterLastGlyph += GlyphInfo.Length - prevLength;
            } 

            nextGlyph = AfterLastGlyph; 
 
        }
Пример #2
0
        public unsafe bool Apply(
            IOpenTypeFont           Font,           // Font access interface 
            OpenTypeTags            TableTag,       // Layout table tag (GSUB or GPOS) 
            FontTable               Table,          // Layout table (GSUB or GPOS)
            LayoutMetrics           Metrics,        // LayoutMetrics 
            int                     CharCount,      // Characters count (i.e. Charmap.Length);
            UshortList              Charmap,        // Char to glyph mapping
            GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs
            int*                    Advances,       // Glyph adv.widths 
            LayoutOffset*           Offsets,        // Glyph offsets
            ushort                  LookupFlags,    // Lookup table flags 
            int                     FirstGlyph,     // where to apply it 
            int                     AfterLastGlyph, // how long is a context we can use
            uint                    Parameter,      // lookup parameter 
            out int                 NextGlyph       // out: next glyph index
            )
        {
            //This will be the next glyph, does not matter sequence matched or not 
            NextGlyph = AfterLastGlyph-1;
 
            if (Format(Table)!=1) return false; //Unknown 

            bool match = true; 
            int inputGlyphIndex = AfterLastGlyph - 1;
            int glyphIndex;

            //Check input glyph 
            int coverageIndex = InputCoverage(Table).GetGlyphIndex(Table,GlyphInfo.Glyphs[inputGlyphIndex]);
 
            if (coverageIndex<0) return false; 

            //we reading data sequenctially from table, moving pointer through it 
            int curOffset = offset + offsetBacktrackGlyphCount;

            //
            // Check backtrack sequence 
            //
            ushort backtrackGlyphCount = GlyphCount(Table,curOffset); 
            curOffset += sizeCount; 

            glyphIndex = inputGlyphIndex; 
            for(ushort backtrackIndex = 0;
                backtrackIndex < backtrackGlyphCount && match;
                backtrackIndex++)
            { 
                glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo,
                    glyphIndex-1, 
                    LookupFlags, 
                    LayoutEngine.LookBackward
                    ); 

                if (glyphIndex<0)
                {
                    match = false; 
                }
                else 
                { 
                    match = (Coverage(Table,curOffset).GetGlyphIndex(Table,GlyphInfo.Glyphs[glyphIndex]) >= 0);
                    curOffset += sizeOffset; 
                }
            }

            ushort lookaheadGlyphCount = GlyphCount(Table,curOffset); 
            curOffset += sizeCount;
 
            glyphIndex = inputGlyphIndex; 
            for(ushort lookaheadIndex = 0;
                lookaheadIndex < lookaheadGlyphCount && match; 
                lookaheadIndex++)
            {
                glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo,
                    glyphIndex+1, 
                    LookupFlags,
                    LayoutEngine.LookForward 
                    ); 

                if (glyphIndex>=GlyphInfo.Length) 
                {
                    match = false;
                }
                else 
                {
                    match = (Coverage(Table,curOffset).GetGlyphIndex(Table,GlyphInfo.Glyphs[glyphIndex]) >= 0); 
                    curOffset += sizeOffset; 
                }
            } 

            if (match)
            {
                curOffset += sizeCount + sizeGlyphId*coverageIndex; 
                GlyphInfo.Glyphs[inputGlyphIndex] = Glyph(Table,curOffset);
                GlyphInfo.GlyphFlags[inputGlyphIndex] = (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted); 
            } 

            return match; 
        }
Пример #3
0
        public unsafe bool Apply( 
            IOpenTypeFont           Font,           // Font access interface
            OpenTypeTags            TableTag,       // Layout table tag (GSUB or GPOS) 
            FontTable               Table,          // Layout table (GSUB or GPOS)
            LayoutMetrics           Metrics,        // LayoutMetrics
            int                     CharCount,      // Characters count (i.e. Charmap.Length);
            UshortList              Charmap,        // Char to glyph mapping 
            GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs
            int*                    Advances,       // Glyph adv.widths 
            LayoutOffset*           Offsets,        // Glyph offsets 
            ushort                  LookupFlags,    // Lookup table flags
            int                     FirstGlyph,     // where to apply it 
            int                     AfterLastGlyph, // how long is a context we can use
            uint                    Parameter,      // lookup parameter
            int                     nestingLevel,   // Contextual lookup nesting level
            out int                 NextGlyph       // out: next glyph index 
            )
        { 
            Invariant.Assert(Format(Table)==1); 

            NextGlyph = FirstGlyph + 1; //in case we don't match 

            int glyphCount = GlyphInfo.Length;

            int     glyphIndex = FirstGlyph; 
            ushort  glyphId = GlyphInfo.Glyphs[glyphIndex];
 
            int coverageIndex = Coverage(Table).GetGlyphIndex(Table,glyphId); 
            if (coverageIndex < 0) return false;
 
            SubRuleSet subRuleSet= RuleSet(Table, coverageIndex);

            ushort ruleCount = subRuleSet.RuleCount(Table);
 
            bool match = false;
            for(ushort i=0; !match && i<ruleCount; i++) 
            { 
                match = subRuleSet.Rule(Table,i).Apply(Font, TableTag, Table, Metrics,
                                                        CharCount, Charmap, 
                                                        GlyphInfo, Advances, Offsets,
                                                        LookupFlags, FirstGlyph, AfterLastGlyph,
                                                        Parameter,
                                                        nestingLevel, 
                                                        out NextGlyph
                                                        ); 
            } 

            return match; 
        }
Пример #4
0
            public unsafe bool Apply(
                IOpenTypeFont           Font,           // Font access interface 
                OpenTypeTags            TableTag,       // Layout table tag (GSUB or GPOS) 
                FontTable               Table,          // Layout table (GSUB or GPOS)
                LayoutMetrics           Metrics,        // LayoutMetrics 
                ClassDefTable           ClassDef,
                int                     CharCount,      // Characters count (i.e. Charmap.Length);
                UshortList              Charmap,        // Char to glyph mapping
                GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs 
                int*                    Advances,       // Glyph adv.widths
                LayoutOffset*           Offsets,        // Glyph offsets 
                ushort                  LookupFlags,    // Lookup table flags 
                int                     FirstGlyph,     // where to apply it
                int                     AfterLastGlyph, // how long is a context we can use 
                uint                    Parameter,      // lookup parameter
                int                     nestingLevel,   // Contextual lookup nesting level
                out int                 NextGlyph       // out: next glyph index
                ) 
            {
                NextGlyph = FirstGlyph + 1; //In case we don't match 
 
                //
                // Check input sequence 
                //
                bool match = true;
                int glyphIndex = FirstGlyph;
 
                int inputGlyphCount = GlyphCount(Table);
                for(ushort inputIndex = 1; // go from second glyph in the input 
                    inputIndex < inputGlyphCount && match; 
                    inputIndex++)
                { 
                    glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo,
                        glyphIndex+1,
                        LookupFlags,
                        LayoutEngine.LookForward 
                        );
 
                    if (glyphIndex>=AfterLastGlyph) 
                    {
                        match = false; 
                    }
                    else
                    {
                        ushort classId = ClassId(Table,inputIndex); 

                        ushort glyphClass = 
                                  ClassDef.GetClass(Table,GlyphInfo.Glyphs[glyphIndex]); 

                        match = (glyphClass == classId); 
                    }
                }

                if (match) 
                {
                    ContextualLookups(Table).ApplyContextualLookups( 
                        Font, 
                        TableTag,
                        Table, 
                        Metrics,
                        CharCount,
                        Charmap,
                        GlyphInfo, 
                        Advances,
                        Offsets, 
                        LookupFlags, 
                        FirstGlyph,
                        glyphIndex + 1, //As AfterLastGlyph 
                        Parameter,
                        nestingLevel,
                        out NextGlyph
                    ); 
                }
 
                return match; 
            }
Пример #5
0
 public unsafe bool Apply(
     IOpenTypeFont           Font,           // Font access interface 
     OpenTypeTags            TableTag,       // Layout table tag (GSUB or GPOS) 
     FontTable               Table,          // Layout table (GSUB or GPOS)
     LayoutMetrics           Metrics,        // LayoutMetrics 
     int                     CharCount,      // Characters count (i.e. Charmap.Length);
     UshortList              Charmap,        // Char to glyph mapping
     GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs
     int*                    Advances,       // Glyph adv.widths 
     LayoutOffset*           Offsets,        // Glyph offsets
     ushort                  LookupFlags,    // Lookup table flags 
     int                     FirstGlyph,     // where to apply it 
     int                     AfterLastGlyph, // how long is a context we can use
     uint                    Parameter,      // lookup parameter 
     int                     nestingLevel,   // Contextual lookup nesting level
     out int                 NextGlyph       // out: next glyph index
     )
 { 
     switch (Format(Table))
     { 
         case 1: 
             GlyphContextSubtable glyphContextSubtable =
                                         new GlyphContextSubtable(offset); 
             return glyphContextSubtable.Apply(
                 Font, TableTag, Table, Metrics,
                 CharCount, Charmap,
                 GlyphInfo, Advances, Offsets, 
                 LookupFlags, FirstGlyph, AfterLastGlyph,
                 Parameter, 
                 nestingLevel, 
                 out NextGlyph
                 ); 
         case 2:
             ClassContextSubtable classContextSubtable =
                                         new ClassContextSubtable(offset);
             return classContextSubtable.Apply( 
                 Font, TableTag, Table, Metrics,
                 CharCount, Charmap, 
                 GlyphInfo, Advances, Offsets, 
                 LookupFlags, FirstGlyph, AfterLastGlyph,
                 Parameter, 
                 nestingLevel,
                 out NextGlyph
                 );
         case 3: 
             CoverageContextSubtable coverageContextSubtable =
                                         new CoverageContextSubtable(offset); 
             return coverageContextSubtable.Apply( 
                 Font, TableTag, Table, Metrics,
                 CharCount, Charmap, 
                 GlyphInfo, Advances, Offsets,
                 LookupFlags, FirstGlyph, AfterLastGlyph,
                 Parameter,
                 nestingLevel, 
                 out NextGlyph
                 ); 
         default: 
             //Unknown format
             NextGlyph = FirstGlyph+1; //don't match 
             return false;
     }
 }
Пример #6
0
        public unsafe bool Apply( 
            IOpenTypeFont           Font,           // Font access interface 
            OpenTypeTags            TableTag,       // Layout table tag (GSUB or GPOS)
            FontTable               Table,          // Layout table (GSUB or GPOS) 
            LayoutMetrics           Metrics,        // LayoutMetrics
            int                     CharCount,      // Characters count (i.e. Charmap.Length);
            UshortList              Charmap,        // Char to glyph mapping
            GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs 
            int*                    Advances,       // Glyph adv.widths
            LayoutOffset*           Offsets,        // Glyph offsets 
            ushort                  LookupFlags,    // Lookup table flags 
            int                     FirstGlyph,     // where to apply it
            int                     AfterLastGlyph, // how long is a context we can use 
            uint                    Parameter,      // lookup parameter
            int                     nestingLevel,   // Contextual lookup nesting level
            out int                 NextGlyph       // out: next glyph index
            ) 
        {
            Invariant.Assert(Format(Table)==3); 
 
            NextGlyph = FirstGlyph + 1; //in case we don't match
 
            int glyphCount = GlyphInfo.Length;
            int glyphIndex;

            ushort backtrackGlyphCount = BacktrackGlyphCount(Table); 
            ushort inputGlyphCount     = InputGlyphCount(Table);
            ushort lookaheadGlyphCount = LookaheadGlyphCount(Table); 
 
            if (FirstGlyph < backtrackGlyphCount ||
                (FirstGlyph + inputGlyphCount) > AfterLastGlyph) 
            {
                return false;
            }
 
            bool match = true;
 
            //Check backtrack sequence 
            glyphIndex = FirstGlyph;
            for(ushort backtrackIndex = 0; 
                backtrackIndex < backtrackGlyphCount && match;
                backtrackIndex++)
            {
                 glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo, 
                                                                glyphIndex-1,
                                                                LookupFlags, 
                                                                LayoutEngine.LookBackward 
                                                               );
 
                if (glyphIndex<0 ||
                    BacktrackCoverage(Table,backtrackIndex)
                            .GetGlyphIndex(Table,GlyphInfo.Glyphs[glyphIndex])<0)
                { 
                    match=false;
                } 
            } 

            if (!match) return false; 

            glyphIndex = FirstGlyph;
            for(ushort inputIndex = 0;
                inputIndex < inputGlyphCount && match; 
                inputIndex++)
            { 
                if (glyphIndex>=AfterLastGlyph || 
                    InputCoverage(Table,inputIndex)
                    .GetGlyphIndex(Table,GlyphInfo.Glyphs[glyphIndex])<0) 
                {
                    match=false;
                }
                else 
                {
                    glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo, 
                        glyphIndex + 1, 
                        LookupFlags,
                        LayoutEngine.LookForward 
                        );
                }
            }
 
            if (!match) return false;
 
            int afterInputGlyph = glyphIndex; // remember where we were after input seqence 

            for(ushort lookaheadIndex = 0; 
                lookaheadIndex < lookaheadGlyphCount && match;
                lookaheadIndex++)
            {
                if (glyphIndex>=GlyphInfo.Length || 
                    LookaheadCoverage(Table,lookaheadIndex)
                    .GetGlyphIndex(Table,GlyphInfo.Glyphs[glyphIndex])<0) 
                { 
                    match=false;
                } 
                else
                {
                    glyphIndex = LayoutEngine.
                                    GetNextGlyphInLookup(Font, GlyphInfo, 
                                                         glyphIndex + 1,
                                                         LookupFlags, 
                                                         LayoutEngine.LookForward); 
                }
            } 

            if (match)
            {
                ContextualLookups(Table).ApplyContextualLookups( 
                                                Font,
                                                TableTag, 
                                                Table, 
                                                Metrics,
                                                CharCount, 
                                                Charmap,
                                                GlyphInfo,
                                                Advances,
                                                Offsets, 
                                                LookupFlags,
                                                FirstGlyph, 
                                                afterInputGlyph, //As AfterLastGlyph 
                                                Parameter,
                                                nestingLevel, 
                                                out NextGlyph
                                            );
            }
 
            return match;
        } 
Пример #7
0
        internal static bool ApplyLookup(
            IOpenTypeFont           Font,           // Font access interface
            OpenTypeTags            TableTag,       // Layout table tag (GSUB or GPOS)
            FontTable               Table,          // Layout table (GSUB or GPOS)
            LayoutMetrics           Metrics,        // LayoutMetrics
            LookupTable             Lookup,         // List definition structure
            int                     CharCount,      // Characters count (i.e. Charmap.Length);
            UshortList              Charmap,        // Char to glyph mapping
            GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs
            int*                    Advances,       // Glyph adv.widths
            LayoutOffset*           Offsets,        // Glyph offsets
            int                     FirstGlyph,     // where to apply it
            int                     AfterLastGlyph, // how long is a context we can use
            uint                    Parameter,      // lookup parameter
            int                     nestingLevel,   // Contextual lookup nesting level
            out int                 NextGlyph       // out: next glyph index
            )
        {
            Debug.Assert(TableTag==OpenTypeTags.GSUB || TableTag==OpenTypeTags.GPOS);
            Debug.Assert(FirstGlyph<AfterLastGlyph);
            Debug.Assert(AfterLastGlyph<=GlyphInfo.Length);

            ushort lookupType = Lookup.LookupType();
            ushort lookupFlags = Lookup.LookupFlags();
            ushort subtableCount = Lookup.SubTableCount();

            bool match=false;
            NextGlyph=FirstGlyph+1; //Just to avoid compiler error

            // Find first glyph
            if (!IsLookupReversal(TableTag,lookupType))
            {
                FirstGlyph=LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo,FirstGlyph,
                                                                lookupFlags,LayoutEngine.LookForward);
            }
            else
            {
                AfterLastGlyph = LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo,AfterLastGlyph-1,
                                                                      lookupFlags,LayoutEngine.LookBackward) + 1;
            }
            if (FirstGlyph>=AfterLastGlyph) return match;

            ushort originalLookupType = lookupType; // We need it to recover, if extension lookup updated lookupFormat

            for(ushort subtableIndex=0; !match && subtableIndex < subtableCount; subtableIndex++)
            {
                lookupType = originalLookupType;
                int subtableOffset = Lookup.SubtableOffset(Table, subtableIndex);

                switch (TableTag)
                {
                    case OpenTypeTags.GSUB:
                    {
                        if (lookupType == 7)
                        {
                            ExtensionLookupTable extension =
                                    new ExtensionLookupTable(subtableOffset);

                            lookupType = extension.LookupType(Table);
                            subtableOffset = extension.LookupSubtableOffset(Table);
                        }

                        switch (lookupType)
                        {
                            case 1: //SingleSubst
                                SingleSubstitutionSubtable singleSub =
                                    new SingleSubstitutionSubtable(subtableOffset);
                                match = singleSub.Apply( Table,
                                                         GlyphInfo,
                                                         FirstGlyph,
                                                         out NextGlyph
                                                       );
                                break;

                            case 2: //MultipleSubst
                                MultipleSubstitutionSubtable multipleSub =
                                    new MultipleSubstitutionSubtable(subtableOffset);
                                match = multipleSub.Apply(  Font,
                                                            Table,
                                                            CharCount,
                                                            Charmap,
                                                            GlyphInfo,
                                                            lookupFlags,
                                                            FirstGlyph,
                                                            AfterLastGlyph,
                                                            out NextGlyph
                                                         );
                                break;

                            case 3: //AlternateSubst
                                AlternateSubstitutionSubtable alternateSub =
                                    new AlternateSubstitutionSubtable(subtableOffset);
                                match = alternateSub.Apply( Table,
                                                            GlyphInfo,
                                                            Parameter,
                                                            FirstGlyph,
                                                            out NextGlyph
                                                          );
                                break;

                            case 4: //Ligature subst
                                LigatureSubstitutionSubtable ligaSub =
                                    new LigatureSubstitutionSubtable(subtableOffset);
                                match = ligaSub.Apply( Font,
                                                       Table,
                                                       CharCount,
                                                       Charmap,
                                                       GlyphInfo,
                                                       lookupFlags,
                                                       FirstGlyph,
                                                       AfterLastGlyph,
                                                       out NextGlyph
                                                     );
                                break;

                            case 5: //ContextualSubst
                                ContextSubtable contextSub =
                                    new ContextSubtable(subtableOffset);
                                match = contextSub.Apply( Font,
                                                          TableTag,
                                                          Table,
                                                          Metrics,
                                                          CharCount,
                                                          Charmap,
                                                          GlyphInfo,
                                                          Advances,
                                                          Offsets,
                                                          lookupFlags,
                                                          FirstGlyph,
                                                          AfterLastGlyph,
                                                          Parameter,
                                                          nestingLevel,
                                                          out NextGlyph
                                                        );
                                break;

                            case 6: //ChainingSubst
                                ChainingSubtable chainingSub =
                                                    new ChainingSubtable(subtableOffset);
                                match = chainingSub.Apply(  Font,
                                                            TableTag,
                                                            Table,
                                                            Metrics,
                                                            CharCount,
                                                            Charmap,
                                                            GlyphInfo,
                                                            Advances,
                                                            Offsets,
                                                            lookupFlags,
                                                            FirstGlyph,
                                                            AfterLastGlyph,
                                                            Parameter,
                                                            nestingLevel,
                                                            out NextGlyph
                                                          );
                                break;

                            case 7: //Extension lookup
                                // Ext.Lookup processed earlier. It can't contain another ext.lookups in it.
                                // Just skip it (do nothing);

                                NextGlyph = FirstGlyph + 1;
                                break;

                            case 8: //ReverseCahiningSubst
                                ReverseChainingSubtable reverseChainingSub =
                                    new ReverseChainingSubtable(subtableOffset);
                                match = reverseChainingSub.Apply(
                                                                    Font,
                                                                    TableTag,
                                                                    Table,
                                                                    Metrics,
                                                                    CharCount,
                                                                    Charmap,
                                                                    GlyphInfo,
                                                                    Advances,
                                                                    Offsets,
                                                                    lookupFlags,
                                                                    FirstGlyph,
                                                                    AfterLastGlyph,
                                                                    Parameter,
                                                                    out NextGlyph
                                                                 );
                                break;

                            default:
                                // Unknown format
                                NextGlyph = FirstGlyph+1;
                                break;
                        }

                        if (match)
                        {
                            if (!IsLookupReversal(TableTag,lookupType))
                            {
                                UpdateGlyphFlags(Font,GlyphInfo,FirstGlyph,NextGlyph,true,GlyphFlags.Substituted);
                            }
                            else
                            {
                                UpdateGlyphFlags(Font,GlyphInfo,NextGlyph,AfterLastGlyph,true,GlyphFlags.Substituted);
                            }
                        }

                        break;
                    }

                    case OpenTypeTags.GPOS:
                    {
                        if (lookupType == 9)
                        {
                            ExtensionLookupTable extension =
                                    new ExtensionLookupTable(subtableOffset);

                            lookupType = extension.LookupType(Table);
                            subtableOffset = extension.LookupSubtableOffset(Table);

                        }

                        switch (lookupType)
                        {
                            case 1: //SinglePos
                                SinglePositioningSubtable singlePos =
                                    new SinglePositioningSubtable(subtableOffset);
                                match = singlePos.Apply(Table,
                                                        Metrics,
                                                        GlyphInfo,
                                                        Advances,
                                                        Offsets,
                                                        FirstGlyph,
                                                        AfterLastGlyph,
                                                        out NextGlyph
                                                       );
                                break;

                            case 2: //PairPos
                                PairPositioningSubtable pairPos =
                                    new PairPositioningSubtable(subtableOffset);
                                match = pairPos.Apply(  Font,
                                                        Table,
                                                        Metrics,        // LayoutMetrics
                                                        GlyphInfo,      // List of GlyphInfo structs
                                                        lookupFlags,    // Lookup flags for glyph lookups
                                                        Advances,       // Glyph adv.widths
                                                        Offsets,        // Glyph offsets
                                                        FirstGlyph,     // where to apply lookup
                                                        AfterLastGlyph, // how long is a context we can use
                                                        out NextGlyph   // Next glyph to process
                                                     );
                                break;

                            case 3: // CursivePos
                                // Under construction
                                CursivePositioningSubtable cursivePositioningSubtable =
                                    new CursivePositioningSubtable(subtableOffset);

                                cursivePositioningSubtable.Apply(   Font,
                                                                    Table,
                                                                    Metrics,        // LayoutMetrics
                                                                    GlyphInfo,      // List of GlyphInfo structs
                                                                    lookupFlags,    // Lookup flags for glyph lookups
                                                                    Advances,       // Glyph adv.widths
                                                                    Offsets,        // Glyph offsets
                                                                    FirstGlyph,     // where to apply lookup
                                                                    AfterLastGlyph, // how long is a context we can use
                                                                    out NextGlyph   // Next glyph to process
                                                                );

                                break;

                            case 4: //MarkToBasePos
                                MarkToBasePositioningSubtable markToBasePos =
                                    new MarkToBasePositioningSubtable(subtableOffset);
                                match = markToBasePos.Apply(Font,
                                                            Table,
                                                            Metrics,        // LayoutMetrics
                                                            GlyphInfo,      // List of GlyphInfo structs
                                                            lookupFlags,    // Lookup flags for glyph lookups
                                                            Advances,       // Glyph adv.widths
                                                            Offsets,        // Glyph offsets
                                                            FirstGlyph,     // where to apply lookup
                                                            AfterLastGlyph, // how long is a context we can use
                                                            out NextGlyph   // Next glyph to process
                                                           );
                                break;


                            case 5: //MarkToLigaturePos
                                // Under construction
                                MarkToLigaturePositioningSubtable markToLigaPos =
                                   new MarkToLigaturePositioningSubtable(subtableOffset);
                                match = markToLigaPos.Apply(
                                                            Font,
                                                            Table,
                                                            Metrics,        // LayoutMetrics
                                                            GlyphInfo,      // List of GlyphInfo structs
                                                            lookupFlags,    // Lookup flags for glyph lookups
                                                            CharCount,      // Characters count (i.e. Charmap.Length);
                                                            Charmap,        // Char to glyph mapping
                                                            Advances,       // Glyph adv.widths
                                                            Offsets,        // Glyph offsets
                                                            FirstGlyph,     // where to apply lookup
                                                            AfterLastGlyph, // how long is a context we can use
                                                            out NextGlyph   // Next glyph to process
                                                           );
                                break;

                            case 6: //MarkToMarkPos
                                MarkToMarkPositioningSubtable markToMarkPos =
                                    new MarkToMarkPositioningSubtable(subtableOffset);
                                match = markToMarkPos.Apply(
                                                            Font,
                                                            Table,
                                                            Metrics,        // LayoutMetrics
                                                            GlyphInfo,      // List of GlyphInfo structs
                                                            lookupFlags,    // Lookup flags for glyph lookups
                                                            Advances,       // Glyph adv.widths
                                                            Offsets,        // Glyph offsets
                                                            FirstGlyph,     // where to apply lookup
                                                            AfterLastGlyph, // how long is a context we can use
                                                            out NextGlyph   // Next glyph to process
                                                           );
                                break;

                            case 7: // Contextual
                                ContextSubtable contextSub =
                                    new ContextSubtable(subtableOffset);
                                match = contextSub.Apply( Font,
                                                          TableTag,
                                                          Table,
                                                          Metrics,
                                                          CharCount,
                                                          Charmap,
                                                          GlyphInfo,
                                                          Advances,
                                                          Offsets,
                                                          lookupFlags,
                                                          FirstGlyph,
                                                          AfterLastGlyph,
                                                          Parameter,
                                                          nestingLevel,
                                                          out NextGlyph
                                                        );
                                break;

                            case 8: // Chaining
                                ChainingSubtable chainingSub =
                                    new ChainingSubtable(subtableOffset);
                                match = chainingSub.Apply( Font,
                                                           TableTag,
                                                           Table,
                                                           Metrics,
                                                           CharCount,
                                                           Charmap,
                                                           GlyphInfo,
                                                           Advances,
                                                           Offsets,
                                                           lookupFlags,
                                                           FirstGlyph,
                                                           AfterLastGlyph,
                                                           Parameter,
                                                           nestingLevel,
                                                           out NextGlyph
                                                         );
                                break;

                            case 9: //Extension lookup
                                // Ext.Lookup processed earlier. It can't contain another ext.lookups in it.
                                // Just skip it (do nothing);

                                NextGlyph = FirstGlyph + 1;
                                break;

                            default:
                                // Unknown format
                                NextGlyph = FirstGlyph + 1;
                                break;
                        }

                        if (match)
                        {
                            UpdateGlyphFlags(Font,GlyphInfo,FirstGlyph,NextGlyph,false,GlyphFlags.Positioned);
                        }

                        break;
                    }
                    default:
                        Debug.Assert(false,"Unknown OpenType layout table!");
                        break;
                }
            }

            return match;
        }
Пример #8
0
        public LayoutOffset AnchorCoordinates( 
                                    FontTable       Table,
                                    LayoutMetrics   Metrics, 
                                    LayoutOffset    ContourPoint
                                )
        {
            LayoutOffset Point = new LayoutOffset(); 

            switch (format) 
            { 
                case 1: //Simple coordinates
                        Point.dx = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,XCoordinate(Table)); 
                        Point.dy = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight,YCoordinate(Table));
                        break;

                case 2: //Coordinates + anchor point 
                        if (ContourPoint.dx==int.MinValue)
                        { 
                            Point.dx = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,XCoordinate(Table)); 
                            Point.dy = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight,YCoordinate(Table));
                        } 
                        else
                        {
                            Point.dx = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,ContourPoint.dx);
                            Point.dy = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,ContourPoint.dy); 
                        }
                        break; 
 
                case 3: //Coordinates + Device table
                        Point.dx = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,XCoordinate(Table))+ 
                                        Format3XDeviceTable(Table).Value(Table,Metrics.PixelsEmWidth);
                        Point.dy = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight,YCoordinate(Table))+
                                        Format3YDeviceTable(Table).Value(Table,Metrics.PixelsEmHeight);
                        break; 

                default: //Unknown format 
                    Point.dx = 0; 
                    Point.dx = 0;
                    break; 
            }

            return Point;
        } 
Пример #9
0
        public unsafe bool Apply( 
            FontTable               Table,
            LayoutMetrics           Metrics,        // LayoutMetrics 
            GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs
            int*                    Advances,       // Glyph adv.widths
            LayoutOffset*           Offsets,        // Glyph offsets
            int                     FirstGlyph,     // where to apply lookup 
            int                     AfterLastGlyph, // how long is a context we can use
            out int                 NextGlyph       // Next glyph to process 
        ) 
        {
            Invariant.Assert(FirstGlyph>=0); 
            Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length);

            NextGlyph = FirstGlyph + 1; //In case we don't match;
 
            int glyphCount=GlyphInfo.Length;
            ushort glyphId = GlyphInfo.Glyphs[FirstGlyph]; 
 
            int coverageIndex = Coverage(Table).GetGlyphIndex(Table,glyphId);
            if (coverageIndex == -1) return false; 

            ValueRecordTable valueRecord;

            switch (Format(Table)) 
            {
                case 1: 
                    valueRecord = Format1ValueRecord(Table); 
                    break;
                case 2: 
                    valueRecord = Format2ValueRecord(Table,(ushort)coverageIndex);
                    break;
                default:
                    return false; 
            }
 
            valueRecord.AdjustPos(Table, Metrics, ref Offsets[FirstGlyph], ref Advances[FirstGlyph]); 

            return true; 
        }
Пример #10
0
        public unsafe bool Apply( 
            IOpenTypeFont   Font, 
            FontTable       Table,
            LayoutMetrics   Metrics,        // LayoutMetrics 
            GlyphInfoList   GlyphInfo,      // List of GlyphInfo structs
            ushort          LookupFlags,    // Lookup flags for glyph lookups
            int             CharCount,      // Characters count (i.e. Charmap.Length);
            UshortList      Charmap,        // Char to glyph mapping 
            int*            Advances,       // Glyph adv.widths
            LayoutOffset*   Offsets,        // Glyph offsets 
            int             FirstGlyph,     // where to apply lookup 
            int             AfterLastGlyph, // how long is a context we can use
            out int         NextGlyph       // Next glyph to process 
            )
        {
            Invariant.Assert(FirstGlyph>=0);
            Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length); 

            NextGlyph = FirstGlyph+1; //Always move to the next glyph, whether matched or not 
 
            if (Format(Table) != 1) return false; //unknown format
 
            int glyphCount=GlyphInfo.Length;
            int markGlyph=FirstGlyph;

            //Lookup works with marks only 
            if ((GlyphInfo.GlyphFlags[markGlyph]&(ushort)GlyphFlags.GlyphTypeMask)!=(ushort)GlyphFlags.Mark) return false;
 
            int markCoverageIndex = MarkCoverage(Table).GetGlyphIndex(Table,GlyphInfo.Glyphs[markGlyph]); 
            if (markCoverageIndex==-1) return false;
 
            int baseGlyph;
            ushort component;

            FindBaseLigature(CharCount, Charmap,GlyphInfo,markGlyph, 
                                                out component, out baseGlyph);
            if (baseGlyph<0) return false; 
 
            int baseCoverageIndex = LigatureCoverage(Table).
                                        GetGlyphIndex(Table,GlyphInfo.Glyphs[baseGlyph]); 
            if (baseCoverageIndex == -1) return false;

            ushort classCount = ClassCount(Table);
            MarkArray marks = Marks(Table); 

            ushort markClass = marks.Class(Table,(ushort)markCoverageIndex); 
            if (markClass>=classCount) return false; //Invalid mark class 

            AnchorTable baseAnchor = Ligatures(Table,baseCoverageIndex, classCount). 
                                            LigatureAnchor(Table,component,markClass);
            if (baseAnchor.IsNull())
            {
                return false; 
            }
 
            AnchorTable markAnchor = marks.MarkAnchor(Table,(ushort)markCoverageIndex); 
            if (markAnchor.IsNull())
            { 
                return false;
            }

            Positioning.AlignAnchors(Font,Table,Metrics,GlyphInfo,Advances,Offsets, 
                baseGlyph,markGlyph,baseAnchor,markAnchor,false);
 
            return true; 
        }
Пример #11
0
        public void AdjustPos(  FontTable Table,
                                LayoutMetrics Metrics,
                                ref LayoutOffset GlyphOffset, 
                                ref int    GlyphAdvance
                             ) 
        { 
            int curOffset=offset;
 
            if ((format&XPlacmentFlag)!=0)
            {
                GlyphOffset.dx += Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,
                                                                Table.GetShort(curOffset)); 
                curOffset+=2;
            } 
 
            if ((format&YPlacmentFlag)!=0)
            { 
                GlyphOffset.dy += Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight,
                                                                Table.GetShort(curOffset));

                curOffset+=2; 
            }
 
            if ((format&XAdvanceFlag)!=0) 
            {
                    GlyphAdvance += Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth, 
                                                                    Table.GetShort(curOffset));
                curOffset+=2;
            }
 
            if ((format&YAdvanceFlag)!=0)
            { 
                    GlyphAdvance += Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight, 
                        Table.GetShort(curOffset));
                curOffset+=2; 
            }

            if ((format&XPlacementDeviceFlag)!=0)
            { 
                int deviceTableOffset = Table.GetOffset(curOffset);
                if (deviceTableOffset != FontTable.NullOffset) 
                { 
                    DeviceTable deviceTable  = new DeviceTable(baseTableOffset+deviceTableOffset);
                    GlyphOffset.dx += deviceTable.Value(Table,Metrics.PixelsEmWidth); 
                }

                curOffset+=2;
            } 

            if ((format&YPlacementDeviceFlag)!=0) 
            { 
                int deviceTableOffset = Table.GetOffset(curOffset);
                if (deviceTableOffset != FontTable.NullOffset) 
                {
                    DeviceTable deviceTable  = new DeviceTable(baseTableOffset+deviceTableOffset);
                    GlyphOffset.dy += deviceTable.Value(Table,Metrics.PixelsEmHeight);
                } 

                curOffset+=2; 
            } 

            if ((format&XAdvanceDeviceFlag)!=0) 
            {
                if (Metrics.Direction==TextFlowDirection.LTR || Metrics.Direction==TextFlowDirection.RTL)
                {
                    int deviceTableOffset = Table.GetOffset(curOffset); 
                    if (deviceTableOffset != FontTable.NullOffset)
                    { 
                        DeviceTable deviceTable  = new DeviceTable(baseTableOffset+deviceTableOffset); 
                        GlyphAdvance += deviceTable.Value(Table,Metrics.PixelsEmWidth);
                    } 
                }

                curOffset+=2;
            } 

            if ((format&YAdvanceDeviceFlag)!=0) 
            { 
                if (Metrics.Direction==TextFlowDirection.TTB || Metrics.Direction==TextFlowDirection.BTT)
                { 
                    int deviceTableOffset = Table.GetOffset(curOffset);
                    if (deviceTableOffset != FontTable.NullOffset)
                    {
                        DeviceTable deviceTable  = new DeviceTable(baseTableOffset+deviceTableOffset); 
                        GlyphAdvance += deviceTable.Value(Table,Metrics.PixelsEmHeight);
                    } 
                } 

                curOffset+=2; 
            }
        }
Пример #12
0
        public unsafe bool Apply(
            IOpenTypeFont   Font, 
            FontTable       Table,
            LayoutMetrics   Metrics,        // LayoutMetrics 
            GlyphInfoList   GlyphInfo,      // List of GlyphInfo structs 
            ushort          LookupFlags,    // Lookup flags for glyph lookups
            int*            Advances,       // Glyph adv.widths 
            LayoutOffset*   Offsets,        // Glyph offsets
            int             FirstGlyph,     // where to apply lookup
            int             AfterLastGlyph, // how long is a context we can use
            out int         NextGlyph       // Next glyph to process 
            )
        { 
            Invariant.Assert(FirstGlyph>=0); 
            Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length);
 
            NextGlyph = FirstGlyph+1;

            if (Format(Table) != 1) return false; // Unknown format
 
            bool RTL = (LookupFlags & LayoutEngine.LookupFlagRightToLeft) != 0;
            ushort cursiveBit = (ushort)GlyphFlags.CursiveConnected; 
 
            //
 



            int glyphIndex, prevGlyphIndex, 
                coverageIndex, prevCoverageIndex;
 
            glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo, 
                                                               FirstGlyph,LookupFlags,
                                                               LayoutEngine.LookForward 
                                                           );

            //clear "CursiveConected" bit,
            //we will set it only if there is a connection to previous glyph 
            if (RTL)
            { 
                GlyphInfo.GlyphFlags[glyphIndex] &= (ushort)~cursiveBit; 
            }
 
            if ( glyphIndex >= AfterLastGlyph )
            {
                return false;
            } 

            prevGlyphIndex = LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo, 
                                                               FirstGlyph-1,LookupFlags, 
                                                               LayoutEngine.LookBackward
                                                              ); 
            if ( prevGlyphIndex < 0 )
            {
                return false;
            } 

            CoverageTable coverage = Coverage(Table); 
 
            coverageIndex = coverage.GetGlyphIndex(Table,GlyphInfo.Glyphs[glyphIndex]);
            if (coverageIndex == -1) 
            {
                return false;
            }
 
            prevCoverageIndex = coverage.
                                   GetGlyphIndex(Table,GlyphInfo.Glyphs[prevGlyphIndex]); 
            if (prevCoverageIndex == -1) 
            {
                return false; 
            }

            AnchorTable prevExitAnchor, entryAnchor;
 
            prevExitAnchor = ExitAnchor(Table, prevCoverageIndex);
            if (prevExitAnchor.IsNull()) 
            { 
                return false;
            } 

            entryAnchor = EntryAnchor(Table,coverageIndex);
            if (entryAnchor.IsNull())
            { 
                return false;
            } 
 
            Positioning.AlignAnchors(Font, Table, Metrics,
                                     GlyphInfo, Advances, Offsets, 
                                     prevGlyphIndex, glyphIndex,
                                     prevExitAnchor, entryAnchor, true);

            if (RTL) 
            {
                UshortList glyphFlags = GlyphInfo.GlyphFlags; 
 
                int index;
 
                //set "cursive" bit for everything up to prevGlyphIndex
                for(index = glyphIndex; index>prevGlyphIndex; index--)
                {
                    glyphFlags[index] |= cursiveBit; 
                }
 
                //fix cursive dependencies 
                int yCorrection = Offsets[glyphIndex].dy;
                for(index = glyphIndex; 
                    (glyphFlags[index] & cursiveBit) != 0 ;
                    index--
                   )
                { 
                    Offsets[index].dy -= yCorrection;
                } 
                Invariant.Assert(glyphIndex>=0); //First glyph should not have bit set 
                Offsets[index].dy  -= yCorrection;
            } 

            return true;
        }
Пример #13
0
        public unsafe bool Apply(
            IOpenTypeFont   Font,
            FontTable       Table,
            LayoutMetrics   Metrics,        // LayoutMetrics 
            GlyphInfoList   GlyphInfo,      // List of GlyphInfo structs
            ushort          LookupFlags,    // Lookup flags for glyph lookups 
            int*            Advances,       // Glyph adv.widths 
            LayoutOffset*   Offsets,        // Glyph offsets
            int             FirstGlyph,     // where to apply lookup 
            int             AfterLastGlyph, // how long is a context we can use
            out int         NextGlyph       // Next glyph to process
            )
        { 
            Invariant.Assert(FirstGlyph>=0);
            Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length); 
 
            NextGlyph = FirstGlyph+1; //Always move to the next glyph, whether matched or not
 
            if (Format(Table) != 1) return false; //unknown format

            int glyphCount=GlyphInfo.Length;
 
            int mark1Glyph=FirstGlyph;
 
            //Lookup works with marks only 
            if ((GlyphInfo.GlyphFlags[mark1Glyph]&(ushort)GlyphFlags.GlyphTypeMask)!=(ushort)GlyphFlags.Mark) return false;
 
            int mark1CoverageIndex = Mark1Coverage(Table).GetGlyphIndex(Table,GlyphInfo.Glyphs[mark1Glyph]);
            if (mark1CoverageIndex==-1) return false;

            //Find preceeding mark according mark from specified class 
            int mark2Glyph = LayoutEngine.GetNextGlyphInLookup(Font,
                GlyphInfo, 
                FirstGlyph-1, 
                (ushort)(LookupFlags & 0xFF00), //Clear Ignore... flags
                LayoutEngine.LookBackward); 
            if (mark2Glyph<0) return false;

            int mark2CoverageIndex = Mark2Coverage(Table).GetGlyphIndex(Table,GlyphInfo.Glyphs[mark2Glyph]);
            if (mark2CoverageIndex==-1) return false; 

            ushort classCount = Mark1ClassCount(Table); 
            MarkArray mark1Array = Mark1Array(Table); 

            ushort mark1Class = mark1Array.Class(Table,(ushort)mark1CoverageIndex); 
            if (mark1Class>=classCount) return false; //Invalid mark class

            AnchorTable mark1Anchor = mark1Array.MarkAnchor(Table,(ushort)mark1CoverageIndex);
            if (mark1Anchor.IsNull()) 
            {
                return false; 
            } 

            AnchorTable mark2Anchor = Marks2(Table).Anchor(Table,(ushort)mark2CoverageIndex,classCount,mark1Class); 
            if (mark2Anchor.IsNull())
            {
                return false;
            } 

            Positioning.AlignAnchors(Font,Table,Metrics,GlyphInfo,Advances,Offsets, 
                mark2Glyph,mark1Glyph,mark2Anchor,mark1Anchor,false); 
            return true;
        } 
Пример #14
0
        public static void ApplyFeatures(
            IOpenTypeFont           Font,
            OpenTypeLayoutWorkspace workspace,
            OpenTypeTags            TableTag,
            FontTable               Table,
            LayoutMetrics           Metrics,
            LangSysTable            LangSys,
            FeatureList             Features,
            LookupList              Lookups,
            Feature[]               FeatureSet,
            int                     featureCount,
            int                     featureSetOffset,
            int                     CharCount,
            UshortList              Charmap,
            GlyphInfoList           GlyphInfo,
            int*                    Advances,
            LayoutOffset*           Offsets
            )
        {
            UpdateGlyphFlags(Font, GlyphInfo, 0, GlyphInfo.Length, false, GlyphFlags.NotChanged);

            // if client did not supply us with workspace
            // we will create our own (temporarily)
            if (workspace == null)
            {
                workspace = new OpenTypeLayoutWorkspace();
            }

            ushort lookupCount=Lookups.LookupCount(Table);

            //Compile feature set
            CompileFeatureSet(
                                FeatureSet,
                                featureCount,
                                featureSetOffset,
                                CharCount,
                                Table,
                                LangSys,
                                Features,
                                lookupCount,
                                workspace
                             );

            OpenTypeLayoutCache.InitCache(Font, TableTag, GlyphInfo, workspace);

            for(ushort lookupIndex = 0; lookupIndex < lookupCount; lookupIndex++)
            {
                if (!workspace.IsAggregatedFlagSet(lookupIndex))
                {
                    continue;
                }

                int  firstChar=0,
                     afterLastChar=0,
                     firstGlyph=0,
                     afterLastGlyph=0;

                OpenTypeLayoutCache.FindNextLookup(workspace, 
                                                   GlyphInfo, 
                                                   lookupIndex, 
                                                   out lookupIndex, 
                                                   out firstGlyph);

                // We need to check this again, because FindNextLookup will change lookupIndex
                if (lookupIndex >= lookupCount)
                {
                    break;
                }

                if (!workspace.IsAggregatedFlagSet(lookupIndex))
                {
                    continue;
                }

                LookupTable lookup = Lookups.Lookup(Table, lookupIndex);

                uint parameter=0;
                bool isLookupReversal = IsLookupReversal(TableTag, lookup.LookupType());

                while(firstGlyph < GlyphInfo.Length) // While we have ranges to work on
                {
                    if (!OpenTypeLayoutCache.FindNextGlyphInLookup(workspace, lookupIndex, isLookupReversal, ref firstGlyph, ref afterLastGlyph))
                    {
                        firstGlyph = afterLastGlyph;
                    }

                    if (firstGlyph < afterLastGlyph) // Apply lookup while in one range
                    {
                        int nextGlyph;
                        int oldLength = GlyphInfo.Length;
                        int glyphsAfterLastChar = oldLength - afterLastGlyph;

                        bool match = ApplyLookup(
                                            Font,           // In: Font access interface
                                            TableTag,       // Layout table tag (GSUB or GPOS)
                                            Table,          // Layout table (GSUB or GPOS)
                                            Metrics,        // In: LayoutMetrics
                                            lookup,         // Lookup definition structure
                                            CharCount,
                                            Charmap,        // In: Char to glyph mapping
                                            GlyphInfo,      // In/out: List of GlyphInfo structs
                                            Advances,       // In/out: Glyph adv.widths
                                            Offsets,        // In/out: Glyph offsets

                                            firstGlyph,     // where to apply it
                                            afterLastGlyph, // how long is a context we can use
                                            parameter,      // lookup parameter
                                            0,              // Nesting level for contextual lookups
                                            out nextGlyph   // out: next glyph index
                                                            // !!!: for reversal lookup, should
                                                            //      return new afterLastGlyph
                                            );

                        if (match)
                        {
                            //Adjust range end if length changed,
                            // for reversal changes happens beyond afterLast, no change needed
                            if (!isLookupReversal)
                            {
                                OpenTypeLayoutCache.OnGlyphsChanged(workspace, GlyphInfo, oldLength, firstGlyph, nextGlyph);

                                afterLastGlyph = GlyphInfo.Length - glyphsAfterLastChar;
                                firstGlyph = nextGlyph;
                            }
                            else
                            {
                                OpenTypeLayoutCache.OnGlyphsChanged(workspace, GlyphInfo, oldLength, nextGlyph, afterLastGlyph);

                                afterLastGlyph = nextGlyph;
                            }
                        }
                        else
                        {
                            if (isLookupReversal)
                                afterLastGlyph = nextGlyph;
                            else
                                firstGlyph = nextGlyph;
                        }
                    }
                    else // End of range. Get next
                    {
                        GetNextEnabledGlyphRange(
                            FeatureSet,
                            featureCount,
                            featureSetOffset,
                            Table,
                            workspace,
                            LangSys,
                            Features,
                            lookupIndex,
                            CharCount,
                            Charmap,

                            afterLastChar,
                            afterLastGlyph,
                            GlyphInfo.Length,

                            out firstChar,
                            out afterLastChar,
                            out firstGlyph,
                            out afterLastGlyph,
                            out parameter);
                    }
                }
            }
        }
Пример #15
0
            public unsafe bool Apply(
                IOpenTypeFont           Font,           // Font access interface 
                OpenTypeTags            TableTag,       // Layout table tag (GSUB or GPOS) 
                FontTable               Table,          // Layout table (GSUB or GPOS)
                LayoutMetrics           Metrics,        // LayoutMetrics 
                ClassDefTable           inputClassDef,
                ClassDefTable           backtrackClassDef,
                ClassDefTable           lookaheadClassDef,
                int                     CharCount,      // Characters count (i.e. Charmap.Length); 
                UshortList              Charmap,        // Char to glyph mapping
                GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs 
                int*                    Advances,       // Glyph adv.widths 
                LayoutOffset*           Offsets,        // Glyph offsets
                ushort                  LookupFlags,    // Lookup table flags 
                int                     FirstGlyph,     // where to apply it
                int                     AfterLastGlyph, // how long is a context we can use
                uint                    Parameter,      // lookup parameter
                int                     nestingLevel,   // Contextual lookup nesting level 
                out int                 NextGlyph       // out: next glyph index
                ) 
            { 
                bool match = true;
                NextGlyph = FirstGlyph + 1; //In case we don't match 

                //We are moving through table. We can pick glyph count or glyph class id.
                int curOffset = offset;
                int glyphIndex; 

                // 
                //Check backtrack sequence 
                //
                int backtrackGlyphCount = GlyphCount(Table,curOffset); 
                curOffset += sizeCount;

                glyphIndex = FirstGlyph;
                for(ushort backtrackIndex = 0; 
                    backtrackIndex < backtrackGlyphCount && match;
                    backtrackIndex++) 
                { 
                    glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo,
                        glyphIndex-1, 
                        LookupFlags,
                        LayoutEngine.LookBackward
                        );
 
                    if (glyphIndex<0)
                    { 
                        match = false; 
                    }
                    else 
                    {
                        ushort classId = ClassId(Table,curOffset);
                        curOffset+=sizeClassId;
 
                        ushort glyphClass = backtrackClassDef.
                                        GetClass(Table,GlyphInfo.Glyphs[glyphIndex]); 
 
                        match = (glyphClass == classId);
                    } 
                }

                if (!match) return false;
 
                //
                // Check input sequence 
                // 
                int inputGlyphCount = GlyphCount(Table,curOffset);
                curOffset += sizeCount; 

                glyphIndex = FirstGlyph;
                for(ushort inputIndex = 1; //go from second glyph in the input
                    inputIndex < inputGlyphCount && match; 
                    inputIndex++)
                { 
                    glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo, 
                        glyphIndex+1,
                        LookupFlags, 
                        LayoutEngine.LookForward
                        );

                    if (glyphIndex >= AfterLastGlyph) 
                    {
                        match = false; 
                    } 
                    else
                    { 
                        ushort classId = ClassId(Table,curOffset);
                        curOffset+=sizeClassId;

                        ushort glyphClass = inputClassDef. 
                            GetClass(Table,GlyphInfo.Glyphs[glyphIndex]);
 
                        match = (glyphClass == classId); 
                    }
                } 

                if (!match) return false;

                int afterInputGlyph = glyphIndex + 1; // remember where we were after input seqence 

                // 
                // Check lookahead sequence 
                //
                int lookaheadGlyphCount = GlyphCount(Table,curOffset); 
                curOffset += sizeCount;

                // Lokahead sequence starting right after input,
                // no need to change current glyphIndex 
                for(ushort lookaheadIndex = 0;
                    lookaheadIndex < lookaheadGlyphCount && match; 
                    lookaheadIndex++) 
                {
                    glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo, 
                        glyphIndex+1,
                        LookupFlags,
                        LayoutEngine.LookForward
                        ); 

                    if (glyphIndex >= GlyphInfo.Length) 
                    { 
                        match = false;
                    } 
                    else
                    {
                        ushort classId = ClassId(Table,curOffset);
                        curOffset+=sizeClassId; 

                        ushort glyphClass = lookaheadClassDef. 
                            GetClass(Table,GlyphInfo.Glyphs[glyphIndex]); 

                        match = (glyphClass == classId); 
                    }
                }

                if (match) 
                {
                    ContextualLookups(Table,curOffset).ApplyContextualLookups( 
                        Font, 
                        TableTag,
                        Table, 
                        Metrics,
                        CharCount,
                        Charmap,
                        GlyphInfo, 
                        Advances,
                        Offsets, 
                        LookupFlags, 
                        FirstGlyph,
                        afterInputGlyph, //As AfterLastGlyph 
                        Parameter,
                        nestingLevel,
                        out NextGlyph
                    ); 
                }
 
                return match; 
            }
Пример #16
0
        /// <summary>
        ///  Align to anchors between two glyphs (e.g. mark and base)
        ///  by changing adv.width and offsets for both of them 
        /// </summary>
        /// <param name="Font"></param> 
        /// <param name="Table"></param> 
        /// <param name="Metrics"></param>
        /// <param name="GlyphInfo"></param> 
        /// <param name="Advances"></param>
        /// <param name="Offsets"></param>
        /// <param name="StaticGlyph"></param>
        /// <param name="MobileGlyph"></param> 
        /// <param name="StaticAnchor"></param>
        /// <param name="MobileAnchor"></param> 
        /// <param name="UseAdvances"></param> 
        /// <returns></returns>
        public static unsafe void AlignAnchors( 
                                        IOpenTypeFont   Font,
                                        FontTable          Table,
                                        LayoutMetrics   Metrics,
                                        GlyphInfoList   GlyphInfo, 
                                        int*            Advances,
                                        LayoutOffset*   Offsets, 
                                        int             StaticGlyph, 
                                        int             MobileGlyph,
                                        AnchorTable     StaticAnchor, 
                                        AnchorTable     MobileAnchor,
                                        bool            UseAdvances
                                      )
        { 
            Invariant.Assert(StaticGlyph>=0 && StaticGlyph<GlyphInfo.Length);
            Invariant.Assert(MobileGlyph>=0 && MobileGlyph<GlyphInfo.Length); 
            Invariant.Assert(!StaticAnchor.IsNull()); 
            Invariant.Assert(!MobileAnchor.IsNull());
 
            LayoutOffset ContourPoint = new LayoutOffset();
            if (StaticAnchor.NeedContourPoint(Table))
            {
                ContourPoint = Font.GetGlyphPointCoord(GlyphInfo.Glyphs[MobileGlyph], 
                                                       StaticAnchor.ContourPointIndex(Table));
            } 
            LayoutOffset StaticAnchorPoint = StaticAnchor.AnchorCoordinates(Table,Metrics,ContourPoint); 

            if (MobileAnchor.NeedContourPoint(Table)) 
            {
                ContourPoint = Font.GetGlyphPointCoord(GlyphInfo.Glyphs[MobileGlyph],
                                                                  MobileAnchor.ContourPointIndex(Table));
            } 
            LayoutOffset MobileAnchorPoint = MobileAnchor.AnchorCoordinates(Table,Metrics,ContourPoint);
 
            int AdvanceInBetween=0; 
            if (StaticGlyph<MobileGlyph)
                for(int i=StaticGlyph+1;i<MobileGlyph;i++) AdvanceInBetween+=Advances[i]; 
            else
                for(int i=MobileGlyph+1;i<StaticGlyph;i++) AdvanceInBetween+=Advances[i];

            if (Metrics.Direction==TextFlowDirection.LTR || 
                Metrics.Direction==TextFlowDirection.RTL)
            { 
                Offsets[MobileGlyph].dy = Offsets[StaticGlyph].dy + StaticAnchorPoint.dy 
                                                                  - MobileAnchorPoint.dy;
 
                if ((Metrics.Direction==TextFlowDirection.LTR)==(StaticGlyph<MobileGlyph))
                {
                    // static glyph is on the left(phisically, not logically) to the mobile glyph
                    int dx = Offsets[StaticGlyph].dx - Advances[StaticGlyph] +  StaticAnchorPoint.dx 
                                        - AdvanceInBetween - MobileAnchorPoint.dx;
 
                    if (UseAdvances) 
                    {
                        Advances[StaticGlyph] += dx; 
                    }
                    else
                    {
                        Offsets[MobileGlyph].dx = dx; 
                    }
                } 
                else 
                {
                    // static glyph is on the right(phisically, not logically) to the mobile glyph 
                    int dx = Offsets[StaticGlyph].dx + Advances[MobileGlyph] +  StaticAnchorPoint.dx
                        + AdvanceInBetween - MobileAnchorPoint.dx;

                    if (UseAdvances) 
                    {
                        Advances[MobileGlyph] -= dx; 
                    } 
                    else
                    { 
                        Offsets[MobileGlyph].dx = dx;
                    }
                }
            } 
            else
            { 
                 //TTB, BTT: //Under construction 
            }
 
        }
Пример #17
0
        public unsafe bool Apply( 
            IOpenTypeFont           Font,           // Font access interface 
            OpenTypeTags            TableTag,       // Layout table tag (GSUB or GPOS)
            FontTable               Table,          // Layout table (GSUB or GPOS) 
            LayoutMetrics           Metrics,        // LayoutMetrics
            int                     CharCount,      // Characters count (i.e. Charmap.Length);
            UshortList              Charmap,        // Char to glyph mapping
            GlyphInfoList           GlyphInfo,      // List of GlyphInfo structs 
            int*                    Advances,       // Glyph adv.widths
            LayoutOffset*           Offsets,        // Glyph offsets 
            ushort                  LookupFlags,    // Lookup table flags 
            int                     FirstGlyph,     // where to apply it
            int                     AfterLastGlyph, // how long is a context we can use 
            uint                    Parameter,      // lookup parameter
            int                     nestingLevel,   // Contextual lookup nesting level
            out int                 NextGlyph       // out: next glyph index
            ) 
        {
            Invariant.Assert(Format(Table)==2); 
 
            NextGlyph = FirstGlyph + 1; //in case we don't match
 
            int glyphCount = GlyphInfo.Length;

            int     glyphIndex = FirstGlyph;
            ushort  glyphId = GlyphInfo.Glyphs[glyphIndex]; 

            if (Coverage(Table).GetGlyphIndex(Table,glyphId) < 0) return false; 
 
            ClassDefTable inputClassDef = InputClassDef(Table),
                          backtrackClassDef =  BacktrackClassDef(Table), 
                          lookaheadClassDef = LookaheadClassDef(Table);

            ushort GlyphClass = inputClassDef.GetClass(Table,glyphId);
            if (GlyphClass >= ClassSetCount(Table)) return false; //!!! Bad font table 

            SubClassSet subClassSet = ClassSet(Table,GlyphClass); 
            if (subClassSet.IsNull) return false;   // There are no rules for this class 

            ushort ruleCount = subClassSet.RuleCount(Table); 

            bool match = false;
            for(ushort i=0; !match && i<ruleCount; i++)
            { 
                match = subClassSet.Rule(Table,i).Apply(Font, TableTag, Table, Metrics,
                                                        inputClassDef,backtrackClassDef,lookaheadClassDef, 
                                                        CharCount, Charmap, 
                                                        GlyphInfo, Advances, Offsets,
                                                        LookupFlags, FirstGlyph, AfterLastGlyph, 
                                                        Parameter,
                                                        nestingLevel,
                                                        out NextGlyph
                                                       ); 
            }
 
            return match; 
        }
Пример #18
0
        public unsafe bool Apply(
                            IOpenTypeFont   Font,
                            FontTable       Table, 
                            LayoutMetrics   Metrics,        // LayoutMetrics
                            GlyphInfoList   GlyphInfo,      // List of GlyphInfo structs 
                            ushort          LookupFlags,    // Lookup flags for glyph lookups 
                            int*            Advances,       // Glyph adv.widths
                            LayoutOffset*   Offsets,        // Glyph offsets 
                            int             FirstGlyph,     // where to apply lookup
                            int             AfterLastGlyph, // how long is a context we can use
                            out int         NextGlyph       // Next glyph to process
                         ) 
        {
            Invariant.Assert(FirstGlyph>=0); 
            Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length); 

            NextGlyph = FirstGlyph+1; //Always move to the next glyph, whether matched or not 

            int glyphCount=GlyphInfo.Length;
            ushort firstGlyphId = GlyphInfo.Glyphs[FirstGlyph];
 
            int secondGlyph = LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo,FirstGlyph+1,LookupFlags,LayoutEngine.LookForward);
            if (secondGlyph>=AfterLastGlyph) return false; 
 
            ushort secondGlyphId = GlyphInfo.Glyphs[secondGlyph];
 
            ValueRecordTable firstValueRecord, secondValueRecord;

            switch (Format(Table))
            { 
                case 1:
                { 
                    int coverageIndex = Coverage(Table).GetGlyphIndex(Table,firstGlyphId); 
                    if (coverageIndex==-1) return false;
 
                    PairSetTable pairSet = Format1PairSet(Table,(ushort)coverageIndex);

                    int pairValueIndex = pairSet.FindPairValue(Table, secondGlyphId);
                    if (pairValueIndex == -1) return false; 

                    firstValueRecord  = pairSet.FirstValueRecord(Table,(ushort)pairValueIndex,FirstValueFormat(Table)); 
                    secondValueRecord = pairSet.SecondValueRecord(Table,(ushort)pairValueIndex,SecondValueFormat(Table)); 

                    break; 
                }
                case 2:
                {
                    int coverageIndex = Coverage(Table).GetGlyphIndex(Table,firstGlyphId); 
                    if (coverageIndex == -1) return false;
 
                    ushort firstClassIndex = Format2Class1Table(Table).GetClass(Table,firstGlyphId); 
                    if (firstClassIndex >= Format2Class1Count(Table)) return false; //this is invalid font;
                    ushort secondClassIndex = Format2Class2Table(Table).GetClass(Table,secondGlyphId); 
                    if (secondClassIndex >= Format2Class2Count(Table)) return false; //this is invalid font;

                    ushort class2Count = Format2Class2Count(Table);
                    firstValueRecord = Format2FirstValueRecord(Table, 
                                                               class2Count,
                                                               firstClassIndex, 
                                                               secondClassIndex 
                                                              );
                    secondValueRecord = Format2SecondValueRecord(Table, 
                                                                 class2Count,
                                                                 firstClassIndex,
                                                                 secondClassIndex
                                                                ); 
                    break;
                } 
                default: 
                    return false;
            } 

            //Now adjust positions
            firstValueRecord.AdjustPos (Table, Metrics, ref Offsets[FirstGlyph],  ref Advances[FirstGlyph]);
            secondValueRecord.AdjustPos(Table, Metrics, ref Offsets[secondGlyph], ref Advances[secondGlyph]); 

            return true; 
        } 
Пример #19
0
        /// <summary>
        /// Position glyphs according to features defined in the font.
        /// </summary>
        /// <param name="Font">In: Font access interface</param>
        /// <param name="workspace">In: Workspace for layout engine</param>
        /// <param name="ScriptTag">In: Script tag</param>
        /// <param name="LangSysTag">In: LangSys tag</param>
        /// <param name="Metrics">In: LayoutMetrics</param>
        /// <param name="FeatureSet">In: List of features to apply</param>
        /// <param name="featureCount">In: Actual number of features in <paramref name="FeatureSet"/></param>
        /// <param name="featureSetOffset">In: offset of input characters inside FeatureSet</param>
        /// <param name="CharCount">In: Characters count (i.e. <paramref name="Charmap"/>.Length);</param>
        /// <param name="Charmap">In: Char to glyph mapping</param>
        /// <param name="Glyphs">In/out: List of GlyphInfo structs</param>
        /// <param name="Advances">In/out: Glyphs adv.widths</param>
        /// <param name="Offsets">In/out: Glyph offsets</param>
        /// <returns>Substitution result</returns>
        internal static OpenTypeLayoutResult PositionGlyphs(
            IOpenTypeFont Font,
            OpenTypeLayoutWorkspace workspace,
            uint ScriptTag,
            uint LangSysTag,
            LayoutMetrics Metrics,
            Feature[]               FeatureSet,
            int featureCount,
            int featureSetOffset,
            int CharCount,
            UshortList Charmap,
            GlyphInfoList Glyphs,
            int *Advances,
            LayoutOffset *Offsets
            )
        {
            try
            {
                FontTable GposTable = Font.GetFontTable(OpenTypeTags.GPOS);
                if (!GposTable.IsPresent)
                {
                    return(OpenTypeLayoutResult.ScriptNotFound);
                }

                GPOSHeader GposHeader = new GPOSHeader(0);
                ScriptList ScriptList = GposHeader.GetScriptList(GposTable);

                ScriptTable Script = ScriptList.FindScript(GposTable, ScriptTag);
                if (Script.IsNull)
                {
                    return(OpenTypeLayoutResult.ScriptNotFound);
                }

                LangSysTable LangSys = Script.FindLangSys(GposTable, LangSysTag);
                if (LangSys.IsNull)
                {
                    return(OpenTypeLayoutResult.LangSysNotFound);
                }

                FeatureList FeatureList = GposHeader.GetFeatureList(GposTable);
                LookupList  LookupList  = GposHeader.GetLookupList(GposTable);

                LayoutEngine.ApplyFeatures(
                    Font,
                    workspace,
                    OpenTypeTags.GPOS,
                    GposTable,
                    Metrics,
                    LangSys,
                    FeatureList,
                    LookupList,
                    FeatureSet,
                    featureCount,
                    featureSetOffset,
                    CharCount,
                    Charmap,
                    Glyphs,
                    Advances,
                    Offsets
                    );
            }
            catch (FileFormatException)
            {
                return(OpenTypeLayoutResult.BadFontTable);
            }

            return(OpenTypeLayoutResult.Success);
        }
Пример #20
0
        internal static OpenTypeLayoutResult PositionGlyphs( 
            IOpenTypeFont           Font,
            OpenTypeLayoutWorkspace workspace,
            uint                    ScriptTag,
            uint                    LangSysTag, 
            LayoutMetrics           Metrics,
            Feature[]               FeatureSet, 
            int                     featureCount, 
            int                     featureSetOffset,
            int                     CharCount, 
            UshortList              Charmap,
            GlyphInfoList           Glyphs,
            int*                    Advances,
            LayoutOffset*           Offsets 
        )
        { 
            try 
            {
                FontTable GposTable = Font.GetFontTable(OpenTypeTags.GPOS); 
                if (!GposTable.IsPresent) {return  OpenTypeLayoutResult.ScriptNotFound;}

                GPOSHeader GposHeader = new GPOSHeader(0);
                ScriptList ScriptList = GposHeader.GetScriptList(GposTable); 

                ScriptTable Script    = ScriptList.FindScript(GposTable,ScriptTag); 
                if (Script.IsNull) {return OpenTypeLayoutResult.ScriptNotFound;} 

                LangSysTable LangSys = Script.FindLangSys(GposTable,LangSysTag); 
                if (LangSys.IsNull) {return OpenTypeLayoutResult.LangSysNotFound;}

                FeatureList FeatureList = GposHeader.GetFeatureList(GposTable);
                LookupList LookupList = GposHeader.GetLookupList(GposTable); 

                LayoutEngine.ApplyFeatures( 
                    Font, 
                    workspace,
                    OpenTypeTags.GPOS, 
                    GposTable,
                    Metrics,
                    LangSys,
                    FeatureList, 
                    LookupList,
                    FeatureSet, 
                    featureCount, 
                    featureSetOffset,
                    CharCount, 
                    Charmap,
                    Glyphs,
                    Advances,
                    Offsets 
                );
            } 
            catch (FileFormatException) 
            {
                return OpenTypeLayoutResult.BadFontTable; 
            }

            return OpenTypeLayoutResult.Success;
        }