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); }
public override void OnProcessMatchResult(UIElements.VisualElement element, ref StyleSheets.RuleMatcher matcher, ref 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) { }