Пример #1
0
        /// <summary> 
        /// ShaperFeateruList.AddFeature - add a feature to the array
        /// </summary> 
        /// <param name="feature">new feature to add</param> 
        /// <remarks>
        ///     This is aimed at allowing shaping engines to add features 
        ///     to the array (generally used for required, all character
        ///     features added at the start of shaping)
        /// </remarks>
        internal void AddFeature (Feature feature) 
        {
            if ( _featuresCount == _features.Length ) 
            { 
                // need more space, so resize the array
               if (!Resize((ushort)(_featuresCount + 1),_featuresCount)) 
               {
                    return; // can't resize array, fail quietly (not going
                            // to apply this feature!)
               } 
            }
 
            _features[_featuresCount] = feature; 
            ++_featuresCount;
        } 
Пример #2
0
        /// <summary>
        /// ShaperFeateruList.AddFeature - add a feature to the array
        /// </summary> 
        /// <remarks>
        ///     An alternative to adding an already created feature. 
        /// </remarks> 
        internal void AddFeature (ushort startIndex, ushort length, uint featureTag, uint parameter)
        { 
            if ( _featuresCount == _features.Length )
            {
                // need more space
               if (!Resize((ushort)(_featuresCount + 1),_featuresCount)) 
               {
                    return; 
               } 
            }
 
            if (_features[_featuresCount] != null)
            {
                _features[_featuresCount].Tag = featureTag;
                _features[_featuresCount].StartIndex = startIndex; 
                _features[_featuresCount].Length = length;
                _features[_featuresCount].Parameter = parameter; 
            } 
            else
            { 
                _features[_featuresCount] = new Feature(startIndex,length,featureTag,parameter);
            }

            ++_featuresCount; 
        }
Пример #3
0
        /// <summary> 
        /// ShaperFeateruList.Initialize - initializer for GetGlyphs.
        /// </summary> 
        /// <remarks>
        ///   Called by pertinent shaper's GetGlyph method (indirectly -
        ///   this function is actually called by the
        ///   ShaperBuffers.InitializeFeatureList method which is 
        ///   called by those shapers that need to create a text dependent
        ///   list of features (e.g. Arabic, Mongolian). 
        /// </remarks> 
        internal bool Initialize (ushort newSize)
        { 
            if (_features == null ||
                newSize > _features.Length ||
                newSize == 0)
            { 
                Feature[] newArray = new Feature[newSize];
                if (newArray != null) 
                { 
                    _features = newArray;
                } 
            }

            _featuresCount = 0;
            _minimumAddCount = 3;       // add space for init,med,final whenever we need to actually resize array 
            return _features != null;
        } 
Пример #4
0
        /// <summary>
        /// ShaperFeateruList.Resize - used to change the size of the features array 
        /// </summary>
        /// <param name="newSize">Requested new array size</param>
        /// <param name="keepCount">number of features to copy into new array</param>
        /// <remarks> 
        ///   Used locally for each AddFeature, and by ShaperBuffers.InitializeFeatureList.
        ///   May be called from a shaping engine. 
        ///   The "keepCount" count takes priority over "newSize" if there's already an 
        ///   array, so if size is less than keep, the resized array has at least keep elements.
        /// </remarks> 
        internal bool Resize (ushort newSize, ushort keepCount)
        {
            _featuresCount = keepCount;     //
 
            if (_features != null &&
                _features.Length != 0 && 
                keepCount > 0 && 
                _features.Length >= keepCount)
            { 
                // make sure keep count is no bigger than current
                // array size
                ushort currentLength = (ushort)_features.Length;
 
                // make sure new size is at least as big as keep count
                if (newSize < keepCount) 
                { 
                    newSize = keepCount;
                } 

                // if new size is bigger than the current array, create
                // a new array
                if (newSize > currentLength) 
                {
                    // always use minimum leap for adding to array 
                    if (newSize < (currentLength + _minimumAddCount)) 
                    {
                       newSize = (ushort)(currentLength + _minimumAddCount); 
                    }

                    Feature[] newArray = new Feature[newSize];
                    if (newArray == null) 
                    {
                        // can't create new array, leave (at least we still 
                        // have our current array) 
                        return false;
                    } 

                    // Our client wants us to keep the first "keepCount" entries.
                    // so copy them now.
                    for (int i = 0; i < keepCount; ++i) 
                    {
                        newArray[i] = _features[i]; 
                    } 

                    _features = newArray; 
                }
            }
            else
            { 
                // nothing to keep, or currently no array so initialize
                return Initialize(newSize); 
            } 

            return true; 

        }
Пример #5
0
        private static void GetNextEnabledGlyphRange(
            Feature[]               FeatureSet,     // In: List of features to apply
            int                     featureCount,   // In: Actual nubmer of features in FeatureSet
            int                     featureSetOffset, // In: offset of input chars inside feature set
            FontTable               Table,          // Layout table (GSUB or GPOS)
            OpenTypeLayoutWorkspace workspace,      // workspace with compiled feature set
            LangSysTable            LangSys,        // Language system
            FeatureList             Features,       // List of Features in layout table
            ushort                  lookupIndex,    // List of lokups definitions in layout table
            int                     CharCount,      // Characters count (i.e. Charmap.Length);
            UshortList              Charmap,        // Character to glyph mapping

            int                     StartChar,
            int                     StartGlyph,
            int                     GlyphRunLength,

            out int                 FirstChar,      // First char in enabled range
            out int                 AfterLastChar,  // next char after enabled range
            out int                 FirstGlyph,     // First char in enabled range
            out int                 AfterLastGlyph, // next char after enabled range
            out uint                Parameter       // applied feature parameter
            )
        {
            FirstChar       = int.MaxValue;
            AfterLastChar   = int.MaxValue;
            FirstGlyph      = StartGlyph;
            AfterLastGlyph  = GlyphRunLength;
            Parameter       = 0;

            if (workspace.IsRequiredFeatureFlagSet(lookupIndex))
            {
                FirstChar       = StartChar;
                AfterLastChar   = CharCount;
                FirstGlyph      = StartGlyph;
                AfterLastGlyph  = GlyphRunLength;

                return;
            }

            for(int feature=0; feature < featureCount; feature++)
            {
                if (!workspace.IsFeatureFlagSet(lookupIndex,feature))
                {
                    continue;
                }

                Feature featureDescription = FeatureSet[feature];

                // Shift values from the feature by specified offset and
                // work with these values from here
                int featureStart = featureDescription.StartIndex - featureSetOffset;
                if (featureStart < 0)
                {
                    featureStart = 0;
                }

                int featureAfterEnd = featureDescription.StartIndex + featureDescription.Length
                                            - featureSetOffset;
                if (featureAfterEnd > CharCount)
                {
                    featureAfterEnd = CharCount;
                }

                //If feature is disabled there should not be any flag set
                Debug.Assert(featureDescription.Parameter != 0);

                if (featureAfterEnd <= StartChar)
                {
                    continue;
                }

                if (featureStart < FirstChar ||
                    (
                      featureStart == FirstChar &&
                      featureAfterEnd >= AfterLastChar
                    )
                   )
                {
                    FirstChar     = featureStart;
                    AfterLastChar = featureAfterEnd;
                    Parameter     = featureDescription.Parameter;
                    continue;
                }
            }

            //No ranges found
            if (FirstChar == int.MaxValue)
            {
                FirstGlyph      = GlyphRunLength;
                AfterLastGlyph  = GlyphRunLength;
            }
            else
            {
                if (StartGlyph > Charmap[FirstChar])
                    FirstGlyph = StartGlyph;
                else
                    FirstGlyph = Charmap[FirstChar];

                if (AfterLastChar < CharCount)
                    AfterLastGlyph = Charmap[AfterLastChar];
                else
                    AfterLastGlyph = GlyphRunLength;
            }

        }
Пример #6
0
        private static void CompileFeatureSet(
            Feature[]               FeatureSet,     // In: List of features to apply
            int                     featureCount,   // In: Actual number of features in FeatureSet
            int                     featureSetOffset, //In: Offset of character input sequence inside feature set
            int                     charCount,      // In: number of characters in the input string
            FontTable               Table,          // In: Layout table (GSUB or GPOS)
            LangSysTable            LangSys,        // In: Language system
            FeatureList             Features,       // In: List of Features in layout table
            int                     lookupCount,    // In: number of lookup in layout table
            OpenTypeLayoutWorkspace workspace       // In: workspace with compiled feature set
            )
        {
            workspace.InitLookupUsageFlags(lookupCount, featureCount);

            //Set lookup uasge flags for required feature
            FeatureTable requiredFeatureTable = LangSys.RequiredFeature(Table, Features);
            if (!requiredFeatureTable.IsNull)
            {
                int featureLookupCount = requiredFeatureTable.LookupCount(Table);
                for(ushort lookup = 0; lookup < featureLookupCount; lookup++)
                {
                    workspace.SetRequiredFeatureFlag(requiredFeatureTable.LookupIndex(Table,lookup));
                }
            }

            //Set lookup usage flags for each feature in the FeatureSet
            for(int feature = 0; feature < featureCount; feature++)
            {
                Feature featureDescription = FeatureSet[feature];

                //Filter out features which:
                // Not enabled or applied completely before or after input characters
                if (featureDescription.Parameter == 0 ||
                    featureDescription.StartIndex >= (featureSetOffset + charCount) ||
                    (featureDescription.StartIndex+featureDescription.Length) <= featureSetOffset
                   )
                {
                    continue;
                }

                FeatureTable featureTable = LangSys.FindFeature( Table,
                                                                 Features,
                                                                 featureDescription.Tag);
                if (featureTable.IsNull)
                {
                    continue;
                }

                int featureLookupCount = featureTable.LookupCount(Table);
                for(ushort lookup = 0; lookup < featureLookupCount; lookup++)
                {
                    workspace.SetFeatureFlag(featureTable.LookupIndex(Table,lookup), feature);
                }
            }
        }
Пример #7
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);
                    }
                }
            }
        }
Пример #8
0
        internal static OpenTypeLayoutResult SubstituteGlyphs(
            IOpenTypeFont           Font,           // In: Font access interface
            OpenTypeLayoutWorkspace workspace,      // In: Workspace for layout engine
            uint                    ScriptTag,      // In: Script tag 
            uint                    LangSysTag,     // In: LangSys tag
            Feature[]               FeatureSet,     // In: List of features to apply 
            int                     featureCount,   // In: Actual number of features in FeatureSet 
            int                     featureSetOffset,
            int                     CharCount,      // In: Characters count (i.e. Charmap.Length); 
            UshortList              Charmap,        // In/out: Char to glyph mapping
            GlyphInfoList           Glyphs          // In/out: List of GlyphInfo structs
            )
        { 
            try
            { 
                FontTable GsubTable = Font.GetFontTable(OpenTypeTags.GSUB); 
                if (!GsubTable.IsPresent) {return OpenTypeLayoutResult.ScriptNotFound;}
 
                GSUBHeader GsubHeader = new GSUBHeader(0);
                ScriptList ScriptList = GsubHeader.GetScriptList(GsubTable);

                ScriptTable Script    = ScriptList.FindScript(GsubTable,ScriptTag); 
                if (Script.IsNull) {return OpenTypeLayoutResult.ScriptNotFound;}
 
                LangSysTable LangSys = Script.FindLangSys(GsubTable,LangSysTag); 
                if (LangSys.IsNull) {return OpenTypeLayoutResult.LangSysNotFound;}
 
                FeatureList FeatureList = GsubHeader.GetFeatureList(GsubTable);
                LookupList LookupList = GsubHeader.GetLookupList(GsubTable);

                LayoutEngine.ApplyFeatures( 
                    Font,
                    workspace, 
                    OpenTypeTags.GSUB, 
                    GsubTable,
                    new LayoutMetrics(), //it is not needed for substitution 
                    LangSys,
                    FeatureList,
                    LookupList,
                    FeatureSet, 
                    featureCount,
                    featureSetOffset, 
                    CharCount, 
                    Charmap,
                    Glyphs, 
                    null,
                    null
                );
            } 
            catch (FileFormatException)
            { 
                return OpenTypeLayoutResult.BadFontTable; 
            }
 
            return OpenTypeLayoutResult.Success;
        }
Пример #9
0
        internal static OpenTypeLayoutResult PositionGlyphs( 
            IOpenTypeFont           Font,
            OpenTypeLayoutWorkspace workspace,
            uint                    ScriptTag,
            uint                    LangSysTag, 
            LayoutMetrics           Metrics,
            Feature[]               FeatureSet, 
            int                     featureCount, 
            int                     featureSetOffset,
            int                     CharCount, 
            UshortList              Charmap,
            GlyphInfoList           Glyphs,
            int*                    Advances,
            LayoutOffset*           Offsets 
        )
        { 
            try 
            {
                FontTable GposTable = Font.GetFontTable(OpenTypeTags.GPOS); 
                if (!GposTable.IsPresent) {return  OpenTypeLayoutResult.ScriptNotFound;}

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

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

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

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

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

            return OpenTypeLayoutResult.Success;
        }