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); } }
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); }
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); }
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); }
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); }
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); }
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); }
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); } } }
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); } } }
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); } } }
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);
public virtual void OnProcessMatchResult(VisualElement element, ref RuleMatcher matcher, ref HierarchyTraversal.MatchResultInfo matchInfo) { }
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); }