Esempio n. 1
0
        public static void InitCache(
            IOpenTypeFont font,
            OpenTypeTags tableTag,
            GlyphInfoList glyphInfo,
            OpenTypeLayoutWorkspace workspace
            )
        {
            Debug.Assert(tableTag == OpenTypeTags.GSUB || tableTag == OpenTypeTags.GPOS);

            byte[] cacheArray = font.GetTableCache(tableTag);

            unsafe
            {
                if (cacheArray == null)
                {
                    workspace.TableCacheData = null;
                }
                else
                {
                    workspace.TableCacheData = cacheArray;

                    workspace.AllocateCachePointers(glyphInfo.Length);
                    RenewPointers(glyphInfo, workspace, 0, glyphInfo.Length);
                }
            }
        }
Esempio n. 2
0
 /// <summary>
 /// Reset all structures to the new font/OTTable/script/langsys.
 ///
 /// Client need to call it only once per shaping engine call.
 /// This is client's responsibility to ensure that workspace is
 /// used for single font/OTTable/script/langsys between Init() calls
 /// </summary>
 ///<param name="font">In: Font access interface</param>
 ///<param name="tableTag">In: Font table tag</param>
 ///<param name="scriptTag">In: Script tag</param>
 ///<param name="langSysTag">In: Language System tag</param>
 ///<returns>Success if workspace is initialized succesfully, specific error if failed</returns>
 internal OpenTypeLayoutResult Init(
     IOpenTypeFont font,
     OpenTypeTags tableTag,
     uint scriptTag,
     uint langSysTag
     )
 {
     // Currently all buffers are per call,
     // no need to do anything.
     return(OpenTypeLayoutResult.Success);
 }
Esempio n. 3
0
        private static void CreateTableCache(IOpenTypeFont font, OpenTypeTags tableTag, int maxCacheSize, out int tableCacheSize)
        {
            // Initialize all computed values
            tableCacheSize = 0;
            int cacheSize       = 0;
            int recordCount     = 0;
            int glyphCount      = 0;
            int lastLookupAdded = -1;

            GlyphLookupRecord[] records = null;

            try
            {
                ComputeTableCache(
                    font,
                    tableTag,
                    maxCacheSize,
                    ref cacheSize,
                    ref records,
                    ref recordCount,
                    ref glyphCount,
                    ref lastLookupAdded
                    );
            }
            catch (FileFormatException)
            {
                cacheSize = 0;
            }

            if (cacheSize > 0)
            {
                tableCacheSize = FillTableCache(
                    font,
                    tableTag,
                    cacheSize,
                    records,
                    recordCount,
                    glyphCount,
                    lastLookupAdded
                    );
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Returns font table data
        /// </summary>
        public FontTable GetFontTable(OpenTypeTags TableTag)
        {
            switch (TableTag)
            {
            case OpenTypeTags.GSUB:
            {
                return(_gsubTable);
            }

            case OpenTypeTags.GPOS:
            {
                return(_gposTable);
            }

            default:
            {
                throw new NotSupportedException();
            }
            }
        }
Esempio n. 5
0
        internal byte[] AllocateTableCache(OpenTypeTags tableTag, int size)
        {
            switch (tableTag)
            {
            case OpenTypeTags.GSUB:
            {
                _gsubCache = new byte[size];
                return(_gsubCache);
            }

            case OpenTypeTags.GPOS:
            {
                _gposCache = new byte[size];
                return(_gposCache);
            }

            default:
            {
                throw new NotSupportedException();
            }
            }
        }
Esempio n. 6
0
        internal byte[] GetTableCache(OpenTypeTags tableTag)
        {
            switch (tableTag)
            {
            case OpenTypeTags.GSUB:
                if (Gsub() != null)
                {
                    return(_gsubCache);
                }
                break;

            case OpenTypeTags.GPOS:
                if (Gpos() != null)
                {
                    return(_gposCache);
                }
                break;

            default:
                throw new NotSupportedException();
            }

            return(null);
        }
Esempio n. 7
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;
        } 
Esempio n. 8
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; 
        }
Esempio n. 9
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; 
            }
Esempio n. 10
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; 
 
        }
Esempio n. 11
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; 
        }
Esempio n. 12
0
 private static bool IsLookupReversal(OpenTypeTags TableTag, ushort LookupType)
 {
     return (TableTag == OpenTypeTags.GSUB && LookupType == 8);
 }
Esempio n. 13
0
        private static int FillTableCache(
            IOpenTypeFont font,
            OpenTypeTags tableTag,
            int cacheSize,
            GlyphLookupRecord[] records,
            int recordCount,
            int glyphCount,
            int lastLookupAdded
            )
        {
            // Fill the cache.

            // We are using basically the same code to fill the cache
            // that had been used to calculate the size. So pList pointer
            // moving through cache memory should not overrun allocated space.
            // Asserts are set to chek that at every place where we write to cache
            // and at the end where we check that we filled exactly the same amount.

            unsafe
            {
                byte[] cache = font.AllocateTableCache(tableTag, cacheSize);
                if (cache == null)
                {
                    // We failed to allocate cache of requested size,
                    // exit without created cache.
                    return(0);
                }

                fixed(byte *pCacheByte = &cache[0])
                {
                    ushort *pCache = (ushort *)pCacheByte;

                    pCache[0] = (ushort)cacheSize;              // Cache size
                    pCache[1] = 0xFFFF;                         // 0xFFFF constants
                    pCache[2] = (ushort)(lastLookupAdded + 1);  // Number of lookups that fit into the cache
                    pCache[3] = (ushort)glyphCount;             // Glyph count

                    ushort *pGlyphs   = pCache + 4;
                    ushort *pList     = pGlyphs + glyphCount * 2;
                    ushort *pPrevList = null;

                    int    prevListIndex = -1, prevListLength = 0;
                    int    curListIndex = 0, curListLength = 1;
                    ushort curGlyph = records[0].Glyph;

                    for (int i = 1; i < recordCount; i++)
                    {
                        if (records[i].Glyph != curGlyph)
                        {
                            // We've found another list. Compare it with previous
                            if (prevListLength != curListLength || // Fast check to avoid full comparison
                                !CompareGlyphRecordLists(records,
                                                         recordCount,
                                                         prevListIndex,
                                                         curListIndex)
                                )
                            {
                                // New list. Remember position in pPrevList and write list down
                                pPrevList = pList;

                                for (int j = curListIndex; j < i; j++)
                                {
                                    Debug.Assert((pList - pCache) * sizeof(ushort) < cacheSize);
                                    *pList = records[j].Lookup;
                                    pList++;
                                }

                                Debug.Assert((pList - pCache) * sizeof(ushort) < cacheSize);
                                *pList = 0xFFFF;
                                pList++;
                            }
                            // Now pPrevList points at the first element of the correct list.

                            *pGlyphs = curGlyph;                                        // Write down glyph id
                            pGlyphs++;
                            *pGlyphs = (ushort)((pPrevList - pCache) * sizeof(ushort)); // Write down list offset
                            pGlyphs++;

                            prevListIndex  = curListIndex;
                            prevListLength = curListLength;

                            curGlyph      = records[i].Glyph;
                            curListIndex  = i;
                            curListLength = 1;
                        }
                    }

                    // And we need to check the last list we missed in the loop
                    if (prevListLength != curListLength || // Fast check to avoid full comparison
                        !CompareGlyphRecordLists(records,
                                                 recordCount,
                                                 prevListIndex,
                                                 curListIndex)
                        )
                    {
                        // New list. Remember position in pPrevList and write list down
                        pPrevList = pList;

                        for (int j = curListIndex; j < recordCount; j++)
                        {
                            Debug.Assert((pList - pCache) * sizeof(ushort) < cacheSize);
                            *pList = records[j].Lookup;
                            pList++;
                        }

                        Debug.Assert((pList - pCache) * sizeof(ushort) < cacheSize);
                        *pList = 0xFFFF;
                        pList++;
                    }
                    // Now pPrevList points at the first element of the correct list.

                    *pGlyphs = curGlyph;                                        // Write down glyph id
                    pGlyphs++;
                    *pGlyphs = (ushort)((pPrevList - pCache) * sizeof(ushort)); // Write down list offset
                    pGlyphs++;

                    // We are done with the cache
                    Debug.Assert((pList - pCache) * sizeof(ushort) == cacheSize);                               // We exactly filled up the cache
                    Debug.Assert((pGlyphs - pCache) * sizeof(ushort) == (4 + glyphCount * 2) * sizeof(ushort)); // Glyphs ended where lists start.
                }
            }

            return(cacheSize);
        }
Esempio n. 14
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; 
            }
Esempio n. 15
0
 public byte[] AllocateTableCache(OpenTypeTags tableTag, int size)
 {
     return(_layout.AllocateTableCache(tableTag, size));
 }
Esempio n. 16
0
 public byte[] GetTableCache(OpenTypeTags tableTag)
 {
     return(_layout.GetTableCache(tableTag));
 }
Esempio n. 17
0
        internal static void GetComplexLanguageList(
                                                OpenTypeTags            tableTag,
                                                FontTable               table,
                                                uint[]                  featureTagsList,
                                                uint[]                  glyphBits,
                                                ushort                  minGlyphId,
                                                ushort                  maxGlyphId,
                                                out WritingSystem[]     complexLanguages,
                                                out int                 complexLanguageCount
                                             )
        {
            ScriptList  scriptList  = new ScriptList(0);
            FeatureList featureList = new FeatureList(0);
            LookupList  lookupList  = new LookupList(0);

            Debug.Assert(tableTag == OpenTypeTags.GSUB || tableTag == OpenTypeTags.GPOS);

            switch (tableTag)
            {
                case OpenTypeTags.GSUB:
                    GSUBHeader gsubHeader = new GSUBHeader(0);
                    scriptList  = gsubHeader.GetScriptList(table);
                    featureList = gsubHeader.GetFeatureList(table);
                    lookupList  = gsubHeader.GetLookupList(table);
                    break;

                case OpenTypeTags.GPOS:
                    GPOSHeader gposHeader = new GPOSHeader(0);
                    scriptList  = gposHeader.GetScriptList(table);
                    featureList = gposHeader.GetFeatureList(table);
                    lookupList  = gposHeader.GetLookupList(table);
                    break;
            }

            int scriptCount  = scriptList.GetScriptCount(table);
            int featureCount = featureList.FeatureCount(table);
            int lookupCount  = lookupList.LookupCount(table);

            // We will mark lookups that should be tested.
            // At the end, we will have only complex ones marked
            uint[] lookupBits = new uint[(lookupCount+31)>>5];

            for(int i = 0; i < (lookupCount+31)>>5; i++)
            {
                lookupBits[i] = 0;
            }

            // Iterate through list of featuers in the table
            for(ushort featureIndex = 0; featureIndex < featureCount; featureIndex++)
            {
                uint featureTag = (uint)featureList.FeatureTag(table, featureIndex);
                bool tagFound   = false;

                //Search for tag in the list of features in question
                for(int j = 0; j < featureTagsList.Length; j++)
                {
                    if (featureTagsList[j] == featureTag)
                    {
                        tagFound = true;
                        break;
                    }
                }

                if (tagFound)
                {
                    // We should mark all lookup mapped to this feature
                    FeatureTable featureTable = featureList.FeatureTable(table, featureIndex);
                    ushort featureLookupCount = featureTable.LookupCount(table);

                    for(ushort j = 0; j < featureLookupCount; j++)
                    {
                        ushort lookupIndex = featureTable.LookupIndex(table, j);
                        
                        if (lookupIndex >= lookupCount)
                        {
                            //This should be invalid font. Lookup associated with the feature is not in lookup array.
                            throw new FileFormatException();
                        }

                        lookupBits[lookupIndex>>5] |= (uint)(1 << (lookupIndex%32));
                    }
                }
            }

            //
            //




            //Now test all marked lookups
            for(ushort lookupIndex = 0; lookupIndex < lookupCount; lookupIndex++)
            {
                if ((lookupBits[lookupIndex>>5] & (1 << (lookupIndex%32))) == 0)
                {
                    continue;
                }

                LookupTable lookup = lookupList.Lookup(table,lookupIndex);

                ushort lookupType    = lookup.LookupType();
                ushort subtableCount = lookup.SubTableCount();

                bool lookupIsCovered = false;

                ushort originalLookupType = lookupType; // We need it to recover,
                                                        // if extension lookup updated lookupFormat
                for(ushort subtableIndex = 0;
                    !lookupIsCovered && 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);
                                    lookupIsCovered = singleSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 2: //MultipleSubst
                                    MultipleSubstitutionSubtable multipleSub =
                                        new MultipleSubstitutionSubtable(subtableOffset);
                                    lookupIsCovered = multipleSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 3: //AlternateSubst
                                    AlternateSubstitutionSubtable alternateSub =
                                        new AlternateSubstitutionSubtable(subtableOffset);
                                    lookupIsCovered = alternateSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 4: //Ligature subst
                                    LigatureSubstitutionSubtable ligaSub =
                                        new LigatureSubstitutionSubtable(subtableOffset);
                                    lookupIsCovered = ligaSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 5: //ContextualSubst
                                    ContextSubtable contextSub =
                                        new ContextSubtable(subtableOffset);
                                    lookupIsCovered = contextSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 6: //ChainingSubst
                                    ChainingSubtable chainingSub =
                                                        new ChainingSubtable(subtableOffset);
                                    lookupIsCovered = chainingSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 7: //Extension lookup
                                    Debug.Assert(false,"Ext.Lookup processed earlier!");
                                    break;

                                case 8: //ReverseCahiningSubst
                                    ReverseChainingSubtable reverseChainingSub =
                                        new ReverseChainingSubtable(subtableOffset);
                                    lookupIsCovered = reverseChainingSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                default:
                                    // Unknown format
                                    lookupIsCovered = true;
                                    break;
                            }

                            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);
                                    lookupIsCovered = singlePos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 2: //PairPos
                                    PairPositioningSubtable pairPos =
                                        new PairPositioningSubtable(subtableOffset);
                                    lookupIsCovered = pairPos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

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

                                    lookupIsCovered = cursivePositioningSubtable.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);

                                    break;

                                case 4: //MarkToBasePos
                                    MarkToBasePositioningSubtable markToBasePos =
                                        new MarkToBasePositioningSubtable(subtableOffset);
                                    lookupIsCovered = markToBasePos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;


                                case 5: //MarkToLigaturePos
                                    // Under construction
                                    MarkToLigaturePositioningSubtable markToLigaPos =
                                       new MarkToLigaturePositioningSubtable(subtableOffset);
                                    lookupIsCovered = markToLigaPos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 6: //MarkToMarkPos
                                    MarkToMarkPositioningSubtable markToMarkPos =
                                        new MarkToMarkPositioningSubtable(subtableOffset);
                                    lookupIsCovered = markToMarkPos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 7: // Contextual
                                    ContextSubtable contextSub =
                                        new ContextSubtable(subtableOffset);
                                    lookupIsCovered = contextSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 8: // Chaining
                                    ChainingSubtable chainingSub =
                                        new ChainingSubtable(subtableOffset);
                                    lookupIsCovered = chainingSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 9: //Extension lookup
                                    Debug.Assert(false,"Ext.Lookup processed earlier!");
                                    break;

                                default:
                                    // Unknown format
                                    lookupIsCovered = true;
                                    break;
                            }

                            break;
                        }

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

                if (!lookupIsCovered)
                {
                    // Clean the flag
                    lookupBits[lookupIndex>>5] &= ~(uint)(1 << (lookupIndex%32));
                }
            }


            // Check if we have any lookup left
            bool complexLookupFound = false;

            for(int i = 0; i < (lookupCount+31)>>5; i++)
            {
                if (lookupBits[i] != 0)
                {
                    complexLookupFound = true;
                    break;
                }
            }

            if (!complexLookupFound)
            {
                // There are no complex lookups
                complexLanguages = null;
                complexLanguageCount = 0;
                return;
            }

            // Now go through all langauages and fill the list
            complexLanguages = new WritingSystem[10];
            complexLanguageCount = 0;

            for(ushort scriptIndex = 0; scriptIndex < scriptCount; scriptIndex++)
            {
                ScriptTable  scriptTable = scriptList.GetScriptTable(table, scriptIndex);
                uint scriptTag = scriptList.GetScriptTag(table, scriptIndex);

                ushort langSysCount = scriptTable.GetLangSysCount(table);

                if (scriptTable.IsDefaultLangSysExists(table))
                {
                    AppendLangSys(scriptTag, (uint)OpenTypeTags.dflt,
                                  scriptTable.GetDefaultLangSysTable(table),
                                  featureList,
                                  table,
                                  featureTagsList,
                                  lookupBits,
                                  ref complexLanguages,
                                  ref complexLanguageCount
                                 );
                }

                for(ushort langSysIndex = 0; langSysIndex < langSysCount; langSysIndex++)
                {
                    uint langSysTag = scriptTable.GetLangSysTag(table, langSysIndex);

                    AppendLangSys(scriptTag, langSysTag,
                                  scriptTable.GetLangSysTable(table, langSysIndex),
                                  featureList,
                                  table,
                                  featureTagsList,
                                  lookupBits,
                                  ref complexLanguages,
                                  ref complexLanguageCount
                                 );
                }
            }
        }
Esempio n. 18
0
        private static CoverageTable GetSubtablePrincipalCoverage(
            FontTable table,
            OpenTypeTags tableTag,
            ushort lookupType,
            int subtableOffset
            )
        {
            Debug.Assert(tableTag == OpenTypeTags.GSUB || tableTag == OpenTypeTags.GPOS);

            CoverageTable coverage = CoverageTable.InvalidCoverage;

            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 singleSubst =
                        new SingleSubstitutionSubtable(subtableOffset);

                    return(singleSubst.GetPrimaryCoverage(table));

                case 2:         //MultipleSubst
                    MultipleSubstitutionSubtable multipleSub =
                        new MultipleSubstitutionSubtable(subtableOffset);
                    return(multipleSub.GetPrimaryCoverage(table));

                case 3:         //AlternateSubst
                    AlternateSubstitutionSubtable alternateSub =
                        new AlternateSubstitutionSubtable(subtableOffset);
                    return(alternateSub.GetPrimaryCoverage(table));

                case 4:         //Ligature subst
                    LigatureSubstitutionSubtable ligaSub =
                        new LigatureSubstitutionSubtable(subtableOffset);
                    return(ligaSub.GetPrimaryCoverage(table));

                case 5:         //ContextualSubst
                    ContextSubtable contextSub =
                        new ContextSubtable(subtableOffset);
                    return(contextSub.GetPrimaryCoverage(table));

                case 6:         //ChainingSubst
                    ChainingSubtable chainingSub =
                        new ChainingSubtable(subtableOffset);
                    return(chainingSub.GetPrimaryCoverage(table));

                case 7:         //Extension lookup
                    // Ext.Lookup processed earlier. It can't contain another ext.lookups in it
                    break;

                case 8:         //ReverseCahiningSubst
                    ReverseChainingSubtable reverseChainingSub =
                        new ReverseChainingSubtable(subtableOffset);
                    return(reverseChainingSub.GetPrimaryCoverage(table));
                }

                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);
                    return(singlePos.GetPrimaryCoverage(table));

                case 2:         //PairPos
                    PairPositioningSubtable pairPos =
                        new PairPositioningSubtable(subtableOffset);
                    return(pairPos.GetPrimaryCoverage(table));

                case 3:         // CursivePos
                    CursivePositioningSubtable cursivePos =
                        new CursivePositioningSubtable(subtableOffset);
                    return(cursivePos.GetPrimaryCoverage(table));

                case 4:         //MarkToBasePos
                    MarkToBasePositioningSubtable markToBasePos =
                        new MarkToBasePositioningSubtable(subtableOffset);
                    return(markToBasePos.GetPrimaryCoverage(table));

                case 5:         //MarkToLigaturePos
                    // Under construction
                    MarkToLigaturePositioningSubtable markToLigaPos =
                        new MarkToLigaturePositioningSubtable(subtableOffset);
                    return(markToLigaPos.GetPrimaryCoverage(table));

                case 6:         //MarkToMarkPos
                    MarkToMarkPositioningSubtable markToMarkPos =
                        new MarkToMarkPositioningSubtable(subtableOffset);
                    return(markToMarkPos.GetPrimaryCoverage(table));

                case 7:         // Contextual
                    ContextSubtable contextPos =
                        new ContextSubtable(subtableOffset);
                    return(contextPos.GetPrimaryCoverage(table));

                case 8:         // Chaining
                    ChainingSubtable chainingPos =
                        new ChainingSubtable(subtableOffset);
                    return(chainingPos.GetPrimaryCoverage(table));

                case 9:         //Extension lookup
                    // Ext.Lookup processed earlier. It can't contain another ext.lookups in it
                    break;
                }

                break;
            }

            return(CoverageTable.InvalidCoverage);
        }
Esempio n. 19
0
        private static void ComputeTableCache(
            IOpenTypeFont font,
            OpenTypeTags tableTag,
            int maxCacheSize,
            ref int cacheSize,
            ref GlyphLookupRecord[] records,
            ref int recordCount,
            ref int glyphCount,
            ref int lastLookupAdded
            )
        {
            FontTable table = font.GetFontTable(tableTag);

            if (!table.IsPresent)
            {
                return;
            }

            FeatureList featureList;
            LookupList  lookupList;

            Debug.Assert(tableTag == OpenTypeTags.GSUB || tableTag == OpenTypeTags.GPOS);

            switch (tableTag)
            {
            case OpenTypeTags.GSUB:
            {
                GSUBHeader header = new GSUBHeader();
                featureList = header.GetFeatureList(table);
                lookupList  = header.GetLookupList(table);
                break;
            }

            case OpenTypeTags.GPOS:
            {
                GPOSHeader header = new GPOSHeader();
                featureList = header.GetFeatureList(table);
                lookupList  = header.GetLookupList(table);
                break;
            }

            default:
            {
                Debug.Assert(false);
                featureList = new FeatureList(0);
                lookupList  = new LookupList(0);
                break;
            }
            }

            // Estimate number of records that can fit into cache using ratio of approximately
            // 4 bytes of cache per actual record. Most of fonts will fit into this value, except
            // some tiny caches and big EA font that can have ratio of around 5 (theoretical maximum is 8).
            //
            // If actual ratio for particluar font will be larger than 4, we will remove records
            // from the end to fit into cache.
            //
            // If ratio is less than 4 we actually can fit more lookups, but for the speed and because most fonts
            // will fit into cache completely anyway we do not do anything about this here.
            int maxRecordCount = maxCacheSize / 4;

            // For now, we will just allocate array of maximum size.
            // Given heuristics above, it wont be greater than max cache size.
            //
            records = new GlyphLookupRecord[maxRecordCount];

            //
            // Now iterate through lookups and subtables, filling in lookup-glyph pairs list
            //
            int lookupCount = lookupList.LookupCount(table);
            int recordCountAfterLastLookup = 0;

            //
            // Not all lookups can be invoked from feature directly,
            // they are actions from contextual lookups.
            // We are not interested in those, because they will
            // never work from high level, so do not bother adding them to the cache.
            //
            // Filling array of lookup usage bits, to skip those not mapped to any lookup
            //
            BitArray lookupUsage = new BitArray(lookupCount);

            for (ushort feature = 0; feature < featureList.FeatureCount(table); feature++)
            {
                FeatureTable featureTable = featureList.FeatureTable(table, feature);

                for (ushort lookup = 0; lookup < featureTable.LookupCount(table); lookup++)
                {
                    ushort lookupIndex = featureTable.LookupIndex(table, lookup);

                    if (lookupIndex >= lookupCount)
                    {
                        // This must be an invalid font. Just igonoring this lookup here.
                        continue;
                    }

                    lookupUsage[lookupIndex] = true;
                }
            }
            // Done with lookup usage bits

            for (ushort lookupIndex = 0; lookupIndex < lookupCount; lookupIndex++)
            {
                if (!lookupUsage[lookupIndex])
                {
                    continue;
                }

                int  firstLookupRecord = recordCount;
                int  maxLookupGlyph    = -1;
                bool cacheIsFull       = false;

                LookupTable lookup        = lookupList.Lookup(table, lookupIndex);
                ushort      lookupType    = lookup.LookupType();
                ushort      subtableCount = lookup.SubTableCount();

                for (ushort subtableIndex = 0; subtableIndex < subtableCount; subtableIndex++)
                {
                    int subtableOffset = lookup.SubtableOffset(table, subtableIndex);

                    CoverageTable coverage = GetSubtablePrincipalCoverage(table, tableTag, lookupType, subtableOffset);

                    if (coverage.IsInvalid)
                    {
                        continue;
                    }

                    cacheIsFull = !AppendCoverageGlyphRecords(table, lookupIndex, coverage, records, ref recordCount, ref maxLookupGlyph);

                    if (cacheIsFull)
                    {
                        break;
                    }
                }

                if (cacheIsFull)
                {
                    break;
                }

                lastLookupAdded            = lookupIndex;
                recordCountAfterLastLookup = recordCount;
            }

            // We may hit storage overflow in the middle of lookup. Throw this partial lookup away
            recordCount = recordCountAfterLastLookup;

            if (lastLookupAdded == -1)
            {
                // We did not succeed adding even single lookup.
                return;
            }

            // We now have glyph records for (may be not all) lookups in the table.
            // Cache structures should be sorted by glyph, then by lookup index.
            Array.Sort(records, 0, recordCount);

            cacheSize  = -1;
            glyphCount = -1;

            // It may happen, that records do not fit into cache, even using our heuristics.
            // We will remove lookups one by one from the end until it fits.
            while (recordCount > 0)
            {
                CalculateCacheSize(records, recordCount, out cacheSize, out glyphCount);

                if (cacheSize <= maxCacheSize)
                {
                    // Fine, we now fit into max cache size
                    break;
                }
                else
                {
                    // Find last lookup index
                    int lastLookup = -1;
                    for (int i = 0; i < recordCount; i++)
                    {
                        int lookup = records[i].Lookup;

                        if (lastLookup < lookup)
                        {
                            lastLookup = lookup;
                        }
                    }

                    Debug.Assert(lastLookup >= 0); // There are lookups, so there was an index

                    // Remove it
                    int currentRecord = 0;
                    for (int i = 0; i < recordCount; i++)
                    {
                        if (records[i].Lookup == lastLookup)
                        {
                            continue;
                        }

                        if (currentRecord == i)
                        {
                            continue;
                        }

                        records[currentRecord] = records[i];
                        currentRecord++;
                    }

                    recordCount = currentRecord;

                    // Do not forget update lastLookupAdded variable
                    lastLookupAdded = lastLookup - 1;
                }
            }

            if (recordCount == 0)
            {
                // We can't fit even single lookup into the cache
                return;
            }

            Debug.Assert(cacheSize > 0);  // We've calcucalted them at least ones, and
            Debug.Assert(glyphCount > 0); // if there is no records, we already should've exited
        }
Esempio n. 20
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;
        }
Esempio n. 21
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;
     }
 }
Esempio n. 22
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);
                    }
                }
            }
        }
Esempio n. 23
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; 
        }
Esempio n. 24
0
 /// <summary> 
 /// Reset all structures to the new font/OTTable/script/langsys. 
 ///
 /// Client need to call it only once per shaping engine call. 
 /// This is client's responsibility to ensure that workspace is
 /// used for single font/OTTable/script/langsys between Init() calls
 /// </summary>
 ///<param name="font">In: Font access interface</param> 
 ///<param name="tableTag">In: Font table tag</param>
 ///<param name="scriptTag">In: Script tag</param> 
 ///<param name="langSysTag">In: Language System tag</param> 
 ///<returns>Success if workspace is initialized succesfully, specific error if failed</returns>
 internal OpenTypeLayoutResult Init( 
     IOpenTypeFont           font,
     OpenTypeTags            tableTag,
     uint                    scriptTag,
     uint                    langSysTag 
     )
 { 
     // Currently all buffers are per call, 
     // no need to do anything.
     return OpenTypeLayoutResult.Success; 
 }