Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(759)

Side by Side Diff: sky/engine/core/dom/Element.cpp

Issue 837883002: Store features in the ScopedStyleResoolver. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Simpler even. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/engine/core/dom/Element.h ('k') | sky/engine/core/dom/SpaceSplitString.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Peter Kelly (pmk@post.com) 4 * (C) 2001 Peter Kelly (pmk@post.com)
5 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * (C) 2007 David Smith (catfish.man@gmail.com) 6 * (C) 2007 David Smith (catfish.man@gmail.com)
7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. 7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
8 * (C) 2007 Eric Seidel (eric@webkit.org) 8 * (C) 2007 Eric Seidel (eric@webkit.org)
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 656
657 if (isStyledElement() && name == HTMLNames::styleAttr) { 657 if (isStyledElement() && name == HTMLNames::styleAttr) {
658 styleAttributeChanged(newValue); 658 styleAttributeChanged(newValue);
659 } 659 }
660 660
661 if (name == HTMLNames::idAttr) { 661 if (name == HTMLNames::idAttr) {
662 AtomicString oldId = elementData()->idForStyleResolution(); 662 AtomicString oldId = elementData()->idForStyleResolution();
663 AtomicString newId = newValue; 663 AtomicString newId = newValue;
664 if (newId != oldId) { 664 if (newId != oldId) {
665 elementData()->setIdForStyleResolution(newId); 665 elementData()->setIdForStyleResolution(newId);
666 if (testShouldInvalidateStyle) 666 if (testShouldInvalidateStyle && (affectedByIdSelector(oldId) || aff ectedByIdSelector(newId)))
667 styleResolver->ensureUpdatedRuleFeatureSet().scheduleStyleInvali dationForIdChange(oldId, newId, *this); 667 setNeedsStyleRecalc(LocalStyleChange);
668 } 668 }
669 } else if (name == HTMLNames::classAttr) { 669 } else if (name == HTMLNames::classAttr) {
670 classAttributeChanged(newValue); 670 classAttributeChanged(newValue);
671 } 671 }
672 672
673 // If there is currently no StyleResolver, we can't be sure that this attrib ute change won't affect style. 673 // If there is currently no StyleResolver, we can't be sure that this attrib ute change won't affect style.
674 if (!styleResolver) 674 if (!styleResolver)
675 setNeedsStyleRecalc(SubtreeStyleChange); 675 setNeedsStyleRecalc(SubtreeStyleChange);
676 } 676 }
677 677
678 inline void Element::attributeChangedFromParserOrByCloning(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason reason) 678 inline void Element::attributeChangedFromParserOrByCloning(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason reason)
679 { 679 {
680 attributeChanged(name, newValue, reason); 680 attributeChanged(name, newValue, reason);
681 } 681 }
682 682
683 template <typename CharacterType>
684 static inline bool classStringHasClassName(const CharacterType* characters, unsi gned length)
685 {
686 ASSERT(length > 0);
687
688 unsigned i = 0;
689 do {
690 if (isNotHTMLSpace<CharacterType>(characters[i]))
691 break;
692 ++i;
693 } while (i < length);
694
695 return i < length;
696 }
697
698 static inline bool classStringHasClassName(const AtomicString& newClassString)
699 {
700 unsigned length = newClassString.length();
701
702 if (!length)
703 return false;
704
705 if (newClassString.is8Bit())
706 return classStringHasClassName(newClassString.characters8(), length);
707 return classStringHasClassName(newClassString.characters16(), length);
708 }
709
710 void Element::classAttributeChanged(const AtomicString& newClassString) 683 void Element::classAttributeChanged(const AtomicString& newClassString)
711 { 684 {
712 StyleResolver* styleResolver = document().styleResolver(); 685 StyleResolver* styleResolver = document().styleResolver();
713 bool testShouldInvalidateStyle = inActiveDocument() && styleResolver && styl eChangeType() < SubtreeStyleChange; 686 bool testShouldInvalidateStyle = inActiveDocument() && styleResolver && styl eChangeType() < SubtreeStyleChange;
714 687
715 ASSERT(elementData()); 688 ASSERT(elementData());
716 if (classStringHasClassName(newClassString)) { 689 const SpaceSplitString oldClasses = elementData()->classNames();
ojan 2015/01/07 04:03:27 Include in the change description what this was fo
717 const SpaceSplitString oldClasses = elementData()->classNames(); 690 elementData()->setClass(newClassString, false);
718 elementData()->setClass(newClassString, false); 691 const SpaceSplitString& newClasses = elementData()->classNames();
719 const SpaceSplitString& newClasses = elementData()->classNames(); 692 if (testShouldInvalidateStyle && classChangeNeedsStyleRecalc(oldClasses, new Classes))
720 if (testShouldInvalidateStyle) 693 setNeedsStyleRecalc(LocalStyleChange);
721 styleResolver->ensureUpdatedRuleFeatureSet().scheduleStyleInvalidati onForClassChange(oldClasses, newClasses, *this); 694 if (!newClasses.size())
722 } else {
723 const SpaceSplitString& oldClasses = elementData()->classNames();
724 if (testShouldInvalidateStyle)
725 styleResolver->ensureUpdatedRuleFeatureSet().scheduleStyleInvalidati onForClassChange(oldClasses, *this);
726 elementData()->clearClass(); 695 elementData()->clearClass();
696 }
697
698 bool Element::classChangeNeedsStyleRecalc(const SpaceSplitString& oldClasses, co nst SpaceSplitString& newClasses)
699 {
700 // Class vectors tend to be very short. This is faster than using a hash tab le.
701 BitVector remainingClassBits;
702 remainingClassBits.ensureSize(oldClasses.size());
703
704 for (unsigned i = 0; i < newClasses.size(); ++i) {
705 bool found = false;
706 for (unsigned j = 0; j < oldClasses.size(); ++j) {
707 if (newClasses[i] == oldClasses[j]) {
708 // Mark each class that is still in the newClasses so we can ski p doing
709 // an n^2 search below when looking for removals. We can't break from
710 // this loop early since a class can appear more than once.
711 remainingClassBits.quickSet(j);
712 found = true;
713 }
714 }
715 // Class was added.
716 if (!found && affectedByClassSelector(newClasses[i]))
717 return true;
727 } 718 }
719
720 for (unsigned i = 0; i < oldClasses.size(); ++i) {
721 if (remainingClassBits.quickGet(i))
722 continue;
723 // Class was removed.
724 if (affectedByClassSelector(oldClasses[i]))
725 return true;
726 }
727 return false;
728 } 728 }
729 729
730 bool Element::shouldInvalidateDistributionWhenAttributeChanged(ElementShadow* el ementShadow, const QualifiedName& name, const AtomicString& newValue) 730 bool Element::shouldInvalidateDistributionWhenAttributeChanged(ElementShadow* el ementShadow, const QualifiedName& name, const AtomicString& newValue)
731 { 731 {
732 ASSERT(elementShadow); 732 ASSERT(elementShadow);
733 const SelectRuleFeatureSet& featureSet = elementShadow->ensureSelectFeatureS et(); 733 const SelectRuleFeatureSet& featureSet = elementShadow->ensureSelectFeatureS et();
734 734
735 if (name == HTMLNames::idAttr) { 735 if (name == HTMLNames::idAttr) {
736 AtomicString oldId = elementData()->idForStyleResolution(); 736 AtomicString oldId = elementData()->idForStyleResolution();
737 AtomicString newId = newValue; 737 AtomicString newId = newValue;
738 if (newId != oldId) { 738 if (newId != oldId) {
739 if (!oldId.isEmpty() && featureSet.hasSelectorForId(oldId)) 739 if (!oldId.isEmpty() && featureSet.hasSelectorForId(oldId))
740 return true; 740 return true;
741 if (!newId.isEmpty() && featureSet.hasSelectorForId(newId)) 741 if (!newId.isEmpty() && featureSet.hasSelectorForId(newId))
742 return true; 742 return true;
743 } 743 }
744 } 744 }
745 745
746 if (name == HTMLNames::classAttr) { 746 if (name == HTMLNames::classAttr) {
747 const AtomicString& newClassString = newValue; 747 const SpaceSplitString& oldClasses = elementData()->classNames();
748 if (classStringHasClassName(newClassString)) { 748 const SpaceSplitString newClasses(newValue, false);
749 const SpaceSplitString& oldClasses = elementData()->classNames(); 749 if (featureSet.checkSelectorsForClassChange(oldClasses, newClasses))
750 const SpaceSplitString newClasses(newClassString, false); 750 return true;
751 if (featureSet.checkSelectorsForClassChange(oldClasses, newClasses))
752 return true;
753 } else {
754 const SpaceSplitString& oldClasses = elementData()->classNames();
755 if (featureSet.checkSelectorsForClassChange(oldClasses))
756 return true;
757 }
758 } 751 }
759 752
760 return featureSet.hasSelectorForAttribute(name.localName()); 753 return featureSet.hasSelectorForAttribute(name.localName());
761 } 754 }
762 755
763 void Element::parserSetAttributes(const Vector<Attribute>& attributeVector) 756 void Element::parserSetAttributes(const Vector<Attribute>& attributeVector)
764 { 757 {
765 ASSERT(!inDocument()); 758 ASSERT(!inDocument());
766 ASSERT(!parentNode()); 759 ASSERT(!parentNode());
767 ASSERT(!m_elementData); 760 ASSERT(!m_elementData);
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after
1554 scope.addElementById(newId, this); 1547 scope.addElementById(newId, this);
1555 } 1548 }
1556 1549
1557 void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue) 1550 void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
1558 { 1551 {
1559 if (name == HTMLNames::idAttr) { 1552 if (name == HTMLNames::idAttr) {
1560 updateId(oldValue, newValue); 1553 updateId(oldValue, newValue);
1561 } 1554 }
1562 1555
1563 if (oldValue != newValue) { 1556 if (oldValue != newValue) {
1564 if (inActiveDocument() && document().styleResolver() && styleChangeType( ) < SubtreeStyleChange) 1557 if (inActiveDocument() && document().styleResolver() && styleChangeType( ) < SubtreeStyleChange && affectedByAttributeSelector(name.localName()))
1565 document().ensureStyleResolver().ensureUpdatedRuleFeatureSet().sched uleStyleInvalidationForAttributeChange(name, *this); 1558 setNeedsStyleRecalc(LocalStyleChange);
1566 1559
1567 if (isUpgradedCustomElement()) 1560 if (isUpgradedCustomElement())
1568 CustomElement::attributeDidChange(this, name.localName(), oldValue, newValue); 1561 CustomElement::attributeDidChange(this, name.localName(), oldValue, newValue);
1569 } 1562 }
1570 1563
1571 if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInter estGroup::createForAttributesMutation(*this, name)) 1564 if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInter estGroup::createForAttributesMutation(*this, name))
1572 recipients->enqueueMutationRecord(MutationRecord::createAttributes(this, name, oldValue)); 1565 recipients->enqueueMutationRecord(MutationRecord::createAttributes(this, name, oldValue));
1573 } 1566 }
1574 1567
1575 static bool needsURLResolutionForInlineStyle(const Element& element, const Docum ent& oldDocument, const Document& newDocument) 1568 static bool needsURLResolutionForInlineStyle(const Element& element, const Docum ent& oldDocument, const Document& newDocument)
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
1803 } 1796 }
1804 1797
1805 bool Element::supportsStyleSharing() const 1798 bool Element::supportsStyleSharing() const
1806 { 1799 {
1807 if (!isStyledElement() || !parentOrShadowHostElement()) 1800 if (!isStyledElement() || !parentOrShadowHostElement())
1808 return false; 1801 return false;
1809 // If the element has inline style it is probably unique. 1802 // If the element has inline style it is probably unique.
1810 if (inlineStyle()) 1803 if (inlineStyle())
1811 return false; 1804 return false;
1812 // Ids stop style sharing if they show up in the stylesheets. 1805 // Ids stop style sharing if they show up in the stylesheets.
1813 if (hasID() && document().ensureStyleResolver().hasRulesForId(idForStyleReso lution())) 1806 if (hasID() && affectedByIdSelector(idForStyleResolution()))
1814 return false; 1807 return false;
1815 // :active and :hover elements always make a chain towards the document node 1808 // :active and :hover elements always make a chain towards the document node
1816 // and no siblings or cousins will have the same state. There's also only on e 1809 // and no siblings or cousins will have the same state. There's also only on e
1817 // :focus element per scope so we don't need to attempt to share. 1810 // :focus element per scope so we don't need to attempt to share.
1818 if (isUserActionElement()) 1811 if (isUserActionElement())
1819 return false; 1812 return false;
1820 if (hasActiveAnimations()) 1813 if (hasActiveAnimations())
1821 return false; 1814 return false;
1822 // Turn off style sharing for elements that can gain layers for reasons outs ide of the style system. 1815 // Turn off style sharing for elements that can gain layers for reasons outs ide of the style system.
1823 // See comments in RenderObject::setStyle(). 1816 // See comments in RenderObject::setStyle().
1824 // FIXME: Why does gaining a layer from outside the style system require dis abling sharing? 1817 // FIXME: Why does gaining a layer from outside the style system require dis abling sharing?
1825 if (isHTMLCanvasElement(*this)) 1818 if (isHTMLCanvasElement(*this))
1826 return false; 1819 return false;
1827 return true; 1820 return true;
1828 } 1821 }
1829 1822
1823 bool Element::affectedByAttributeSelector(const AtomicString& attributeName) con st
1824 {
1825 if (attributeName.isEmpty())
1826 return false;
1827 // TODO(esprehn): This makes sure the style system is updated, eventually
1828 // we'll remove all the global lists and this won't be needed.
1829 document().ensureStyleResolver();
1830 if (treeScope().scopedStyleResolver().features().hasSelectorForAttribute(att ributeName))
1831 return true;
1832 // Host rules could also have effects.
1833 if (ShadowRoot* shadowRoot = this->shadowRoot())
1834 return shadowRoot->scopedStyleResolver().features().hasSelectorForAttrib ute(attributeName);
1835 return false;
1836 }
1837
1838 bool Element::affectedByClassSelector(const AtomicString& classValue) const
1839 {
1840 if (classValue.isEmpty())
1841 return false;
1842 // TODO(esprehn): This makes sure the style system is updated, eventually
1843 // we'll remove all the global lists and this won't be needed.
1844 document().ensureStyleResolver();
1845 if (treeScope().scopedStyleResolver().features().hasSelectorForClass(classVa lue))
1846 return true;
1847 // Host rules could also have effects.
1848 if (ShadowRoot* shadowRoot = this->shadowRoot())
1849 return shadowRoot->scopedStyleResolver().features().hasSelectorForClass( classValue);
1850 return false;
1851 }
1852
1853 bool Element::affectedByIdSelector(const AtomicString& idValue) const
1854 {
1855 if (idValue.isEmpty())
1856 return false;
1857 // TODO(esprehn): This makes sure the style system is updated, eventually
1858 // we'll remove all the global lists and this won't be needed.
1859 document().ensureStyleResolver();
1860 if (treeScope().scopedStyleResolver().features().hasSelectorForId(idValue))
1861 return true;
1862 // Host rules could also have effects.
1863 if (ShadowRoot* shadowRoot = this->shadowRoot())
1864 return shadowRoot->scopedStyleResolver().features().hasSelectorForId(idV alue);
1865 return false;
1866 }
1867
1830 } // namespace blink 1868 } // namespace blink
OLDNEW
« no previous file with comments | « sky/engine/core/dom/Element.h ('k') | sky/engine/core/dom/SpaceSplitString.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698