michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * style sheet and style rule processor representing style attributes michael@0: */ michael@0: michael@0: #include "nsHTMLCSSStyleSheet.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "mozilla/css/StyleRule.h" michael@0: #include "nsIStyleRuleProcessor.h" michael@0: #include "nsPresContext.h" michael@0: #include "nsRuleWalker.h" michael@0: #include "nsRuleProcessorData.h" michael@0: #include "mozilla/dom/Element.h" michael@0: #include "nsAttrValue.h" michael@0: #include "nsAttrValueInlines.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::dom; michael@0: michael@0: namespace { michael@0: michael@0: PLDHashOperator michael@0: ClearAttrCache(const nsAString& aKey, MiscContainer*& aValue, void*) michael@0: { michael@0: // Ideally we'd just call MiscContainer::Evict, but we can't do that since michael@0: // we're iterating the hashtable. michael@0: MOZ_ASSERT(aValue->mType == nsAttrValue::eCSSStyleRule); michael@0: michael@0: aValue->mValue.mCSSStyleRule->SetHTMLCSSStyleSheet(nullptr); michael@0: aValue->mValue.mCached = 0; michael@0: michael@0: return PL_DHASH_REMOVE; michael@0: } michael@0: michael@0: } // anonymous namespace michael@0: michael@0: nsHTMLCSSStyleSheet::nsHTMLCSSStyleSheet() michael@0: { michael@0: } michael@0: michael@0: nsHTMLCSSStyleSheet::~nsHTMLCSSStyleSheet() michael@0: { michael@0: // We may go away before all of our cached style attributes do, michael@0: // so clean up any that are left. michael@0: mCachedStyleAttrs.Enumerate(ClearAttrCache, nullptr); michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsHTMLCSSStyleSheet, nsIStyleRuleProcessor) michael@0: michael@0: /* virtual */ void michael@0: nsHTMLCSSStyleSheet::RulesMatching(ElementRuleProcessorData* aData) michael@0: { michael@0: Element* element = aData->mElement; michael@0: michael@0: // just get the one and only style rule from the content's STYLE attribute michael@0: css::StyleRule* rule = element->GetInlineStyleRule(); michael@0: if (rule) { michael@0: rule->RuleMatched(); michael@0: aData->mRuleWalker->Forward(rule); michael@0: } michael@0: michael@0: rule = element->GetSMILOverrideStyleRule(); michael@0: if (rule) { michael@0: if (aData->mPresContext->IsProcessingRestyles() && michael@0: !aData->mPresContext->IsProcessingAnimationStyleChange()) { michael@0: // Non-animation restyle -- don't process SMIL override style, because we michael@0: // don't want SMIL animation to trigger new CSS transitions. Instead, michael@0: // request an Animation restyle, so we still get noticed. michael@0: aData->mPresContext->PresShell()->RestyleForAnimation(element, michael@0: eRestyle_Self); michael@0: } else { michael@0: // Animation restyle (or non-restyle traversal of rules) michael@0: // Now we can walk SMIL overrride style, without triggering transitions. michael@0: rule->RuleMatched(); michael@0: aData->mRuleWalker->Forward(rule); michael@0: } michael@0: } michael@0: } michael@0: michael@0: /* virtual */ void michael@0: nsHTMLCSSStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData) michael@0: { michael@0: if (nsCSSPseudoElements::PseudoElementSupportsStyleAttribute(aData->mPseudoType)) { michael@0: MOZ_ASSERT(aData->mPseudoElement, michael@0: "If pseudo element is supposed to support style attribute, it must " michael@0: "have a pseudo element set"); michael@0: michael@0: // just get the one and only style rule from the content's STYLE attribute michael@0: css::StyleRule* rule = aData->mPseudoElement->GetInlineStyleRule(); michael@0: if (rule) { michael@0: rule->RuleMatched(); michael@0: aData->mRuleWalker->Forward(rule); michael@0: } michael@0: } michael@0: } michael@0: michael@0: /* virtual */ void michael@0: nsHTMLCSSStyleSheet::RulesMatching(AnonBoxRuleProcessorData* aData) michael@0: { michael@0: } michael@0: michael@0: #ifdef MOZ_XUL michael@0: /* virtual */ void michael@0: nsHTMLCSSStyleSheet::RulesMatching(XULTreeRuleProcessorData* aData) michael@0: { michael@0: } michael@0: #endif michael@0: michael@0: // Test if style is dependent on content state michael@0: /* virtual */ nsRestyleHint michael@0: nsHTMLCSSStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData) michael@0: { michael@0: return nsRestyleHint(0); michael@0: } michael@0: michael@0: /* virtual */ nsRestyleHint michael@0: nsHTMLCSSStyleSheet::HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) michael@0: { michael@0: return nsRestyleHint(0); michael@0: } michael@0: michael@0: /* virtual */ bool michael@0: nsHTMLCSSStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aData) michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: // Test if style is dependent on attribute michael@0: /* virtual */ nsRestyleHint michael@0: nsHTMLCSSStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) michael@0: { michael@0: // Perhaps should check that it's XUL, SVG, (or HTML) namespace, but michael@0: // it doesn't really matter. michael@0: if (aData->mAttrHasChanged && aData->mAttribute == nsGkAtoms::style) { michael@0: return eRestyle_Self; michael@0: } michael@0: michael@0: return nsRestyleHint(0); michael@0: } michael@0: michael@0: /* virtual */ bool michael@0: nsHTMLCSSStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext) michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: nsHTMLCSSStyleSheet::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return 0; michael@0: } michael@0: michael@0: /* virtual */ size_t michael@0: nsHTMLCSSStyleSheet::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const michael@0: { michael@0: return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); michael@0: } michael@0: michael@0: void michael@0: nsHTMLCSSStyleSheet::CacheStyleAttr(const nsAString& aSerialized, michael@0: MiscContainer* aValue) michael@0: { michael@0: mCachedStyleAttrs.Put(aSerialized, aValue); michael@0: } michael@0: michael@0: void michael@0: nsHTMLCSSStyleSheet::EvictStyleAttr(const nsAString& aSerialized, michael@0: MiscContainer* aValue) michael@0: { michael@0: #ifdef DEBUG michael@0: { michael@0: NS_ASSERTION(aValue = mCachedStyleAttrs.Get(aSerialized), michael@0: "Cached value does not match?!"); michael@0: } michael@0: #endif michael@0: mCachedStyleAttrs.Remove(aSerialized); michael@0: } michael@0: michael@0: MiscContainer* michael@0: nsHTMLCSSStyleSheet::LookupStyleAttr(const nsAString& aSerialized) michael@0: { michael@0: return mCachedStyleAttrs.Get(aSerialized); michael@0: }