public virtual void TraverseRecursive(VisualElement element, int depth, List <RuleMatcher> ruleMatchers)
        {
            // if subtree is up to date skip
            if (ShouldSkipElement(element))
            {
                return;
            }

            int originalCount = ruleMatchers.Count;

            BeginElementTest(element, ruleMatchers);

            int count = ruleMatchers.Count; // changes while we iterate so save

            for (int j = 0; j < count; j++)
            {
                RuleMatcher matcher = ruleMatchers[j];

                if (MatchRightToLeft(element, ref matcher))
                {
                    return;
                }
            }

            ProcessMatchedRules(element);

            Recurse(element, depth, ruleMatchers);

            // Remove all matchers that we could possibly have added at this level of recursion
            if (ruleMatchers.Count > originalCount)
            {
                ruleMatchers.RemoveRange(originalCount, ruleMatchers.Count - originalCount);
            }
        }
示例#2
0
        private void GetMatchersFor(List <VisualElement> elements, int idx, int depth, List <RuleMatcher> ruleMatchers)
        {
            VisualElement element = elements[idx];
            int           count   = this.m_Matchers.Count;

            for (int i = 0; i < count; i++)
            {
                RuleMatcher item = this.m_Matchers[i];
                if (item.depth >= depth && StyleContext.Match(element, ref item))
                {
                    StyleSelector[] selectors = item.complexSelector.selectors;
                    int             num       = item.simpleSelectorIndex + 1;
                    int             num2      = selectors.Length;
                    if (num < num2)
                    {
                        RuleMatcher item2 = new RuleMatcher
                        {
                            complexSelector     = item.complexSelector,
                            depth               = ((selectors[num].previousRelationship != StyleSelectorRelationship.Child) ? 2147483647 : (depth + 1)),
                            simpleSelectorIndex = num,
                            sheet               = item.sheet
                        };
                        this.m_Matchers.Add(item2);
                    }
                    else if (idx == 0)
                    {
                        ruleMatchers.Add(item);
                    }
                }
            }
        }
        public virtual MatchResultInfo Match(VisualElement element, ref RuleMatcher matcher, int selectorIndex)
        {
            if (element == null)
            {
                return(default(MatchResultInfo));
            }
            bool          match    = true;
            StyleSelector selector = matcher.complexSelector.selectors[selectorIndex];
            int           count    = selector.parts.Length;

            int  triggerPseudoStateMask   = 0;
            int  dependencyPseudoMask     = 0;
            bool failedOnlyOnPseudoStates = true;

            for (int i = 0; i < count; i++)
            {
                bool isPartMatch = MatchSelectorPart(element, selector, selector.parts[i]);

                if (!isPartMatch)
                {
                    if (selector.parts[i].type == StyleSelectorType.PseudoClass)
                    {
                        // if the element had those flags defined, it would match this selector
                        triggerPseudoStateMask |= selector.pseudoStateMask;
                        // if the element didnt' have those flags, it would match this selector
                        dependencyPseudoMask |= selector.negatedPseudoStateMask;
                    }
                    else
                    {
                        failedOnlyOnPseudoStates = false;
                    }
                }
                else
                {
                    if (selector.parts[i].type == StyleSelectorType.PseudoClass)
                    {
                        // the element matches this selector because it has those flags
                        dependencyPseudoMask |= selector.pseudoStateMask;
                        // the element matches this selector because it does not have those flags
                        triggerPseudoStateMask |= selector.negatedPseudoStateMask;
                    }
                }

                match &= isPartMatch;
            }

            var result = new MatchResultInfo()
            {
                success = match
            };

            if (match || failedOnlyOnPseudoStates)
            {
                result.triggerPseudoMask    = (PseudoStates)triggerPseudoStateMask;
                result.dependencyPseudoMask = (PseudoStates)dependencyPseudoMask;
            }

            return(result);
        }
示例#4
0
        private bool MatchRightToLeft(VisualElement element, ref RuleMatcher matcher)
        {
            VisualElement visualElement  = element;
            int           i              = matcher.complexSelector.selectors.Length - 1;
            VisualElement visualElement2 = null;
            int           num            = -1;
            bool          result;

            while (i >= 0)
            {
                if (visualElement == null)
                {
                    break;
                }
                HierarchyTraversal.MatchResultInfo matchResultInfo = this.Match(visualElement, ref matcher, i);
                this.OnProcessMatchResult(visualElement, ref matcher, ref matchResultInfo);
                if (!matchResultInfo.success)
                {
                    if (i < matcher.complexSelector.selectors.Length - 1 && matcher.complexSelector.selectors[i + 1].previousRelationship == StyleSelectorRelationship.Descendent)
                    {
                        visualElement = visualElement.parent;
                    }
                    else
                    {
                        if (visualElement2 == null)
                        {
                            break;
                        }
                        visualElement = visualElement2;
                        i             = num;
                    }
                }
                else
                {
                    if (i < matcher.complexSelector.selectors.Length - 1 && matcher.complexSelector.selectors[i + 1].previousRelationship == StyleSelectorRelationship.Descendent)
                    {
                        visualElement2 = visualElement.parent;
                        num            = i;
                    }
                    if (--i < 0)
                    {
                        if (this.OnRuleMatchedElement(matcher, element))
                        {
                            result = true;
                            return(result);
                        }
                    }
                    visualElement = visualElement.parent;
                }
            }
            result = false;
            return(result);
        }
示例#5
0
            public override bool OnRuleMatchedElement(RuleMatcher matcher, VisualElement element)
            {
                StyleRule rule        = matcher.complexSelector.rule;
                int       specificity = matcher.complexSelector.specificity;

                m_MatchingRulesHash = (m_MatchingRulesHash * 397) ^ rule.GetHashCode();
                m_MatchingRulesHash = (m_MatchingRulesHash * 397) ^ specificity;
                m_MatchedRules.Add(new RuleRef {
                    selector = matcher.complexSelector, sheet = matcher.sheet
                });
                return(false);
            }
示例#6
0
            public override bool OnRuleMatchedElement(RuleMatcher matcher, VisualElement element)
            {
                StyleRule rule        = matcher.complexSelector.rule;
                int       specificity = matcher.complexSelector.specificity;

                this.m_MatchingRulesHash = (this.m_MatchingRulesHash * 397L ^ (long)rule.GetHashCode());
                this.m_MatchingRulesHash = (this.m_MatchingRulesHash * 397L ^ (long)specificity);
                this.m_MatchedRules.Add(new StyleContext.RuleRef
                {
                    selector = matcher.complexSelector,
                    sheet    = matcher.sheet
                });
                return(false);
            }
示例#7
0
        public virtual bool Match(VisualElement element, ref RuleMatcher matcher)
        {
            bool          flag          = true;
            StyleSelector styleSelector = matcher.complexSelector.selectors[matcher.simpleSelectorIndex];
            int           num           = styleSelector.parts.Length;
            int           num2          = 0;

            while (num2 < num && flag)
            {
                flag = this.MatchSelectorPart(element, styleSelector, styleSelector.parts[num2]);
                num2++;
            }
            return(flag);
        }
示例#8
0
        private static bool Match(VisualElement element, ref RuleMatcher matcher)
        {
            bool          flag          = true;
            StyleSelector styleSelector = matcher.complexSelector.selectors[matcher.simpleSelectorIndex];
            int           num           = styleSelector.parts.Length;
            int           num2          = 0;

            while (num2 < num && flag)
            {
                switch (styleSelector.parts[num2].type)
                {
                case StyleSelectorType.Wildcard:
                    break;

                case StyleSelectorType.Type:
                    flag = (element.typeName == styleSelector.parts[num2].value);
                    break;

                case StyleSelectorType.Class:
                    flag = element.ClassListContains(styleSelector.parts[num2].value);
                    break;

                case StyleSelectorType.PseudoClass:
                {
                    int pseudoStates = (int)element.pseudoStates;
                    flag  = ((styleSelector.pseudoStateMask & pseudoStates) == styleSelector.pseudoStateMask);
                    flag &= ((styleSelector.negatedPseudoStateMask & ~pseudoStates) == styleSelector.negatedPseudoStateMask);
                    break;
                }

                case StyleSelectorType.RecursivePseudoClass:
                    goto IL_FA;

                case StyleSelectorType.ID:
                    flag = (element.name == styleSelector.parts[num2].value);
                    break;

                default:
                    goto IL_FA;
                }
IL_101:
                num2++;
                continue;
IL_FA:
                flag = false;
                goto IL_101;
            }
            return(flag);
        }
示例#9
0
 internal void Traverse(VisualElement element, int depth, List <RuleMatcher> ruleMatchers)
 {
     if (!this.ShouldSkipElement(element))
     {
         int count = ruleMatchers.Count;
         this.BeginElementTest(element, ruleMatchers);
         int count2 = ruleMatchers.Count;
         for (int i = 0; i < count2; i++)
         {
             RuleMatcher matcher = ruleMatchers[i];
             if (matcher.depth >= depth && this.Match(element, ref matcher))
             {
                 StyleSelector[] selectors = matcher.complexSelector.selectors;
                 int             num       = matcher.simpleSelectorIndex + 1;
                 int             num2      = selectors.Length;
                 if (num < num2)
                 {
                     RuleMatcher item = new RuleMatcher
                     {
                         complexSelector     = matcher.complexSelector,
                         depth               = ((selectors[num].previousRelationship != StyleSelectorRelationship.Child) ? int.MaxValue : (depth + 1)),
                         simpleSelectorIndex = num,
                         sheet               = matcher.sheet
                     };
                     ruleMatchers.Add(item);
                 }
                 else if (this.OnRuleMatchedElement(matcher, element))
                 {
                     return;
                 }
             }
         }
         this.ProcessMatchedRules(element);
         this.Recurse(element, depth, ruleMatchers);
         if (ruleMatchers.Count > count)
         {
             ruleMatchers.RemoveRange(count, ruleMatchers.Count - count);
         }
     }
 }
示例#10
0
 public virtual void TraverseRecursive(VisualElement element, int depth, List <RuleMatcher> ruleMatchers)
 {
     if (!this.ShouldSkipElement(element))
     {
         int count = ruleMatchers.Count;
         this.BeginElementTest(element, ruleMatchers);
         int count2 = ruleMatchers.Count;
         for (int i = 0; i < count2; i++)
         {
             RuleMatcher ruleMatcher = ruleMatchers[i];
             if (this.MatchRightToLeft(element, ref ruleMatcher))
             {
                 return;
             }
         }
         this.ProcessMatchedRules(element);
         this.Recurse(element, depth, ruleMatchers);
         if (ruleMatchers.Count > count)
         {
             ruleMatchers.RemoveRange(count, ruleMatchers.Count - count);
         }
     }
 }
示例#11
0
 private void UpdateStyles(VisualElement element, int depth)
 {
     if (element.IsDirty(ChangeType.Styles) || element.IsDirty(ChangeType.StylesPath))
     {
         VisualContainer visualContainer = element as VisualContainer;
         int             count           = this.m_Matchers.Count;
         if (visualContainer != null && visualContainer.styleSheets != null)
         {
             this.AddMatchersFromSheet(visualContainer.styleSheets);
         }
         string fullTypeName = element.fullTypeName;
         long   num          = (long)fullTypeName.GetHashCode();
         num = (num * 397L ^ (long)this.currentPixelsPerPoint.GetHashCode());
         this.m_MatchedRules.Clear();
         int count2 = this.m_Matchers.Count;
         for (int i = 0; i < count2; i++)
         {
             RuleMatcher ruleMatcher = this.m_Matchers[i];
             if (ruleMatcher.depth >= depth && StyleContext.Match(element, ref ruleMatcher))
             {
                 StyleSelector[] selectors = ruleMatcher.complexSelector.selectors;
                 int             num2      = ruleMatcher.simpleSelectorIndex + 1;
                 int             num3      = selectors.Length;
                 if (num2 < num3)
                 {
                     RuleMatcher item = new RuleMatcher
                     {
                         complexSelector     = ruleMatcher.complexSelector,
                         depth               = ((selectors[num2].previousRelationship != StyleSelectorRelationship.Child) ? 2147483647 : (depth + 1)),
                         simpleSelectorIndex = num2,
                         sheet               = ruleMatcher.sheet
                     };
                     this.m_Matchers.Add(item);
                 }
                 else
                 {
                     StyleRule rule        = ruleMatcher.complexSelector.rule;
                     int       specificity = ruleMatcher.complexSelector.specificity;
                     num = (num * 397L ^ (long)rule.GetHashCode());
                     num = (num * 397L ^ (long)specificity);
                     this.m_MatchedRules.Add(new StyleContext.RuleRef
                     {
                         selector = ruleMatcher.complexSelector,
                         sheet    = ruleMatcher.sheet
                     });
                 }
             }
         }
         VisualElementStyles visualElementStyles;
         if (StyleContext.s_StyleCache.TryGetValue(num, out visualElementStyles))
         {
             element.SetSharedStyles(visualElementStyles);
         }
         else
         {
             visualElementStyles = new VisualElementStyles(true);
             int j      = 0;
             int count3 = this.m_MatchedRules.Count;
             while (j < count3)
             {
                 StyleContext.RuleRef ruleRef     = this.m_MatchedRules[j];
                 StylePropertyID[]    propertyIDs = StyleSheetCache.GetPropertyIDs(ruleRef.sheet, ruleRef.selector.ruleIndex);
                 visualElementStyles.ApplyRule(ruleRef.sheet, ruleRef.selector.specificity, ruleRef.selector.rule, propertyIDs, this.m_VisualTree.elementPanel.loadResourceFunc);
                 j++;
             }
             StyleContext.s_StyleCache[num] = visualElementStyles;
             element.SetSharedStyles(visualElementStyles);
         }
         if (visualContainer != null)
         {
             for (int k = 0; k < visualContainer.childrenCount; k++)
             {
                 VisualElement childAt = visualContainer.GetChildAt(k);
                 this.UpdateStyles(childAt, depth + 1);
             }
         }
         if (this.m_Matchers.Count > count)
         {
             this.m_Matchers.RemoveRange(count, this.m_Matchers.Count - count);
         }
     }
 }
示例#12
0
 public override void OnProcessMatchResult(VisualElement element, ref RuleMatcher matcher, ref HierarchyTraversal.MatchResultInfo matchInfo)
 {
     element.triggerPseudoMask    |= matchInfo.triggerPseudoMask;
     element.dependencyPseudoMask |= matchInfo.dependencyPseudoMask;
 }
        private bool MatchRightToLeft(VisualElement element, ref RuleMatcher matcher)
        {
            // see https://speakerdeck.com/constellation/css-jit-just-in-time-compiled-css-selectors-in-webkit for
            // a detailed explaination of the algorithm

            var           current   = element;
            int           nextIndex = matcher.complexSelector.selectors.Length - 1;
            VisualElement saved     = null;
            int           savedIdx  = -1;

            // go backward
            while (nextIndex >= 0)
            {
                if (current == null)
                {
                    break;
                }

                MatchResultInfo matchInfo = Match(current, ref matcher, nextIndex);
                OnProcessMatchResult(current, ref matcher, ref matchInfo);

                if (!matchInfo.success)
                {
                    // if we have a descendent relationship, keep trying on the parent
                    // ie. "div span", div failed on this element, try on the parent
                    // happens earlier than the backtracking saving below
                    if (nextIndex < matcher.complexSelector.selectors.Length - 1 &&
                        matcher.complexSelector.selectors[nextIndex + 1].previousRelationship == StyleSelectorRelationship.Descendent)
                    {
                        current = current.parent;
                        continue;
                    }

                    // otherwise, if there's a previous relationship, it's a 'child' one. backtrack from the saved point and try again
                    // ie.  for "#x > .a .b", #x failed, backtrack to .a on the saved element
                    if (saved != null)
                    {
                        current   = saved;
                        nextIndex = savedIdx;
                        continue;
                    }

                    break;
                }

                // backtracking save
                // for "a > b c": we're considering the b matcher. c's previous relationship is Descendent
                // save the current element parent to try to match b again
                if (nextIndex < matcher.complexSelector.selectors.Length - 1 &&
                    matcher.complexSelector.selectors[nextIndex + 1].previousRelationship == StyleSelectorRelationship.Descendent)
                {
                    saved    = current.parent;
                    savedIdx = nextIndex;
                }

                // from now, the element is a match
                if (--nextIndex < 0)
                {
                    //TODO: abort if return false
                    if (OnRuleMatchedElement(matcher, element))
                    {
                        return(true);
                    }
                }
                current = current.parent;
            }
            return(false);
        }
 public virtual void OnProcessMatchResult(VisualElement element, ref RuleMatcher matcher, ref MatchResultInfo matchInfo)
 {
 }
 public abstract bool OnRuleMatchedElement(RuleMatcher matcher, VisualElement element);
示例#16
0
 public virtual void OnProcessMatchResult(VisualElement element, ref RuleMatcher matcher, ref HierarchyTraversal.MatchResultInfo matchInfo)
 {
 }
示例#17
0
 public virtual HierarchyTraversal.MatchResultInfo Match(VisualElement element, ref RuleMatcher matcher, int selectorIndex)
 {
     HierarchyTraversal.MatchResultInfo result;
     if (element == null)
     {
         result = default(HierarchyTraversal.MatchResultInfo);
     }
     else
     {
         bool          flag          = true;
         StyleSelector styleSelector = matcher.complexSelector.selectors[selectorIndex];
         int           num           = styleSelector.parts.Length;
         int           num2          = 0;
         int           num3          = 0;
         bool          flag2         = true;
         for (int i = 0; i < num; i++)
         {
             bool flag3 = this.MatchSelectorPart(element, styleSelector, styleSelector.parts[i]);
             if (!flag3)
             {
                 if (styleSelector.parts[i].type == StyleSelectorType.PseudoClass)
                 {
                     num2 |= styleSelector.pseudoStateMask;
                     num3 |= styleSelector.negatedPseudoStateMask;
                 }
                 else
                 {
                     flag2 = false;
                 }
             }
             else if (styleSelector.parts[i].type == StyleSelectorType.PseudoClass)
             {
                 num3 |= styleSelector.pseudoStateMask;
                 num2 |= styleSelector.negatedPseudoStateMask;
             }
             flag &= flag3;
         }
         HierarchyTraversal.MatchResultInfo matchResultInfo = new HierarchyTraversal.MatchResultInfo
         {
             success = flag
         };
         if (flag || flag2)
         {
             matchResultInfo.triggerPseudoMask    = (PseudoStates)num2;
             matchResultInfo.dependencyPseudoMask = (PseudoStates)num3;
         }
         result = matchResultInfo;
     }
     return(result);
 }