Beispiel #1
0
        private static bool Match <T>(
            int increment,
            T[] sequence,
            SkippingGlyphIterator iterator,
            Func <T, GlyphShapingData, bool> condition,
            Span <int> matches)
        {
            ushort position = iterator.Index;
            ushort offset   = iterator.Increment(increment);
            IGlyphShapingCollection collection = iterator.Collection;

            int i = 0;

            while (i < sequence.Length && i < MaxContextLength && offset < collection.Count)
            {
                if (!condition(sequence[i], collection.GetGlyphShapingData(offset)))
                {
                    break;
                }

                if (matches.Length == MaxContextLength)
                {
                    matches[i] = iterator.Index;
                }

                i++;
                offset = iterator.Next();
            }

            iterator.Index = position;
            return(i == sequence.Length);
        }
 public SkippingGlyphIterator(FontMetrics fontMetrics, IGlyphShapingCollection collection, ushort index, LookupFlags lookupFlags)
 {
     this.fontMetrics        = fontMetrics;
     this.Collection         = collection;
     this.Index              = index;
     this.ignoreMarks        = (lookupFlags & LookupFlags.IgnoreMarks) != 0;
     this.ignoreBaseGlypghs  = (lookupFlags & LookupFlags.IgnoreBaseGlypghs) != 0;
     this.ignoreLigatures    = (lookupFlags & LookupFlags.IgnoreLigatures) != 0;
     this.markAttachmentType = 0; // TODO: Lookup HarfBuzz to see how this is assigned.
 }
Beispiel #3
0
        public static bool CheckAllCoverages(
            FontMetrics fontMetrics,
            LookupFlags lookupFlags,
            IGlyphShapingCollection collection,
            ushort index,
            int count,
            CoverageTable[] input,
            CoverageTable[] backtrack,
            CoverageTable[] lookahead)
        {
            // Check that there are enough context glyphs.
            if (index - backtrack.Length < 0 || input.Length + lookahead.Length > count)
            {
                return(false);
            }

            // Check all coverages: if any of them does not match, abort update.
            SkippingGlyphIterator iterator = new(fontMetrics, collection, index, lookupFlags);

            if (!MatchCoverageSequence(iterator, backtrack, -backtrack.Length))
            {
                return(false);
            }

            if (!MatchCoverageSequence(iterator, input, 0))
            {
                return(false);
            }

            if (!MatchCoverageSequence(iterator, lookahead, input.Length))
            {
                return(false);
            }

            return(true);
        }
        /// <inheritdoc/>
        public override void AssignFeatures(IGlyphShapingCollection collection, int index, int count)
        {
            this.AddFeature(collection, index, count, CcmpTag);
            this.AddFeature(collection, index, count, LoclTag);
            this.AddFeature(collection, index, count, IsolTag, false);
            this.AddFeature(collection, index, count, FinaTag, false);
            this.AddFeature(collection, index, count, Fin2Tag, false);
            this.AddFeature(collection, index, count, Fin3Tag, false);
            this.AddFeature(collection, index, count, MediTag, false);
            this.AddFeature(collection, index, count, Med2Tag, false);
            this.AddFeature(collection, index, count, InitTag, false);
            this.AddFeature(collection, index, count, MsetTag);

            base.AssignFeatures(collection, index, count);

            int prev  = -1;
            int state = 0;

            byte[] actions = new byte[count];

            // Apply the state machine to map glyphs to features.
            for (int i = 0; i < count; i++)
            {
                GlyphShapingData data         = collection.GetGlyphShapingData(i + index);
                JoiningClass     joiningClass = CodePoint.GetJoiningClass(data.CodePoint);
                JoiningType      joiningType  = joiningClass.JoiningType;
                if (joiningType == JoiningType.Transparent)
                {
                    actions[i] = None;
                    continue;
                }

                int    shapingClassIndex = GetShapingClassIndex(joiningType);
                byte[] actionsWithState  = StateTable[state, shapingClassIndex];
                byte   prevAction        = actionsWithState[0];
                byte   curAction         = actionsWithState[1];
                state = actionsWithState[2];

                if (prevAction != None && prev != -1)
                {
                    actions[prev] = prevAction;
                }

                actions[i] = curAction;
                prev       = i;
            }

            // Apply the chosen features to their respective glyphs.
            for (int i = 0; i < actions.Length; i++)
            {
                switch (actions[i])
                {
                case Fina:
                    collection.EnableShapingFeature(i + index, FinaTag);
                    break;

                case Fin2:
                    collection.EnableShapingFeature(i + index, Fin2Tag);
                    break;

                case Fin3:
                    collection.EnableShapingFeature(i + index, Fin3Tag);
                    break;

                case Isol:
                    collection.EnableShapingFeature(i + index, IsolTag);
                    break;

                case Init:
                    collection.EnableShapingFeature(i + index, InitTag);
                    break;

                case Medi:
                    collection.EnableShapingFeature(i + index, MediTag);
                    break;

                case Med2:
                    collection.EnableShapingFeature(i + index, Med2Tag);
                    break;
                }
            }
        }
 /// <summary>
 /// Assigns the substitution features to each glyph within the collection.
 /// </summary>
 /// <param name="collection">The glyph shaping collection.</param>
 /// <param name="index">The zero-based index of the elements to assign.</param>
 /// <param name="count">The number of elements to assign.</param>
 public abstract void AssignFeatures(IGlyphShapingCollection collection, int index, int count);