1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "core/dom/shadow/SelectRuleFeatureSet.h" 33 34 #include "core/css/CSSSelector.h" 35 36 #include "wtf/BitVector.h" 37 38 namespace WebCore { 39 40 SelectRuleFeatureSet::SelectRuleFeatureSet() 41 : m_featureFlags(0) 42 { 43 } 44 45 void SelectRuleFeatureSet::add(const SelectRuleFeatureSet& featureSet) 46 { 47 m_cssRuleFeatureSet.add(featureSet.m_cssRuleFeatureSet); 48 m_featureFlags |= featureSet.m_featureFlags; 49 } 50 51 void SelectRuleFeatureSet::clear() 52 { 53 m_cssRuleFeatureSet.clear(); 54 m_featureFlags = 0; 55 } 56 57 void SelectRuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector) 58 { 59 m_cssRuleFeatureSet.collectFeaturesFromSelector(selector); 60 61 switch (selector.pseudoType()) { 62 case CSSSelector::PseudoChecked: 63 setSelectRuleFeature(AffectedSelectorChecked); 64 break; 65 case CSSSelector::PseudoEnabled: 66 setSelectRuleFeature(AffectedSelectorEnabled); 67 break; 68 case CSSSelector::PseudoDisabled: 69 setSelectRuleFeature(AffectedSelectorDisabled); 70 break; 71 case CSSSelector::PseudoIndeterminate: 72 setSelectRuleFeature(AffectedSelectorIndeterminate); 73 break; 74 case CSSSelector::PseudoLink: 75 setSelectRuleFeature(AffectedSelectorLink); 76 break; 77 case CSSSelector::PseudoTarget: 78 setSelectRuleFeature(AffectedSelectorTarget); 79 break; 80 case CSSSelector::PseudoVisited: 81 setSelectRuleFeature(AffectedSelectorVisited); 82 break; 83 default: 84 break; 85 } 86 } 87 88 bool SelectRuleFeatureSet::checkSelectorsForClassChange(const SpaceSplitString& changedClasses) const 89 { 90 unsigned changedSize = changedClasses.size(); 91 for (unsigned i = 0; i < changedSize; ++i) { 92 if (hasSelectorForClass(changedClasses[i])) 93 return true; 94 } 95 return false; 96 } 97 98 bool SelectRuleFeatureSet::checkSelectorsForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses) const 99 { 100 if (!oldClasses.size()) 101 return checkSelectorsForClassChange(newClasses); 102 103 // Class vectors tend to be very short. This is faster than using a hash table. 104 BitVector remainingClassBits; 105 remainingClassBits.ensureSize(oldClasses.size()); 106 107 for (unsigned i = 0; i < newClasses.size(); ++i) { 108 bool found = false; 109 for (unsigned j = 0; j < oldClasses.size(); ++j) { 110 if (newClasses[i] == oldClasses[j]) { 111 // Mark each class that is still in the newClasses so we can skip doing 112 // an n^2 search below when looking for removals. We can't break from 113 // this loop early since a class can appear more than once. 114 remainingClassBits.quickSet(j); 115 found = true; 116 } 117 } 118 // Class was added. 119 if (!found) { 120 if (hasSelectorForClass(newClasses[i])) 121 return true; 122 } 123 } 124 125 for (unsigned i = 0; i < oldClasses.size(); ++i) { 126 if (remainingClassBits.quickGet(i)) 127 continue; 128 129 // Class was removed. 130 if (hasSelectorForClass(oldClasses[i])) 131 return true; 132 } 133 return false; 134 } 135 136 } 137 138