diff options
Diffstat (limited to 'layout/style/StyleSetHandle.h')
-rw-r--r-- | layout/style/StyleSetHandle.h | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/layout/style/StyleSetHandle.h b/layout/style/StyleSetHandle.h new file mode 100644 index 000000000..ad75f75ae --- /dev/null +++ b/layout/style/StyleSetHandle.h @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_StyleSetHandle_h +#define mozilla_StyleSetHandle_h + +#include "mozilla/EventStates.h" +#include "mozilla/RefPtr.h" +#include "mozilla/SheetType.h" +#include "mozilla/StyleBackendType.h" +#include "mozilla/StyleSheet.h" +#include "nsChangeHint.h" +#include "nsCSSPseudoElements.h" +#include "nsTArray.h" + +namespace mozilla { +class CSSStyleSheet; +class ServoStyleSet; +namespace dom { +class Element; +} // namespace dom +} // namespace mozilla +class nsIAtom; +class nsIContent; +class nsIDocument; +class nsStyleContext; +class nsStyleSet; +class nsPresContext; +struct TreeMatchContext; + +namespace mozilla { + +#define SERVO_BIT 0x1 + +/** + * Smart pointer class that can hold a pointer to either an nsStyleSet + * or a ServoStyleSet. + */ +class StyleSetHandle +{ +public: + // We define this Ptr class with a StyleSet API that forwards on to the + // wrapped pointer, rather than putting these methods on StyleSetHandle + // itself, so that we can have StyleSetHandle behave like a smart pointer and + // be dereferenced with operator->. + class Ptr + { + public: + friend class ::mozilla::StyleSetHandle; + + bool IsGecko() const { return !IsServo(); } + bool IsServo() const + { + MOZ_ASSERT(mValue, "StyleSetHandle null pointer dereference"); +#ifdef MOZ_STYLO + return mValue & SERVO_BIT; +#else + return false; +#endif + } + + StyleBackendType BackendType() const + { + return IsGecko() ? StyleBackendType::Gecko : + StyleBackendType::Servo; + } + + nsStyleSet* AsGecko() + { + MOZ_ASSERT(IsGecko()); + return reinterpret_cast<nsStyleSet*>(mValue); + } + + ServoStyleSet* AsServo() + { + MOZ_ASSERT(IsServo()); + return reinterpret_cast<ServoStyleSet*>(mValue & ~SERVO_BIT); + } + + nsStyleSet* GetAsGecko() { return IsGecko() ? AsGecko() : nullptr; } + ServoStyleSet* GetAsServo() { return IsServo() ? AsServo() : nullptr; } + + const nsStyleSet* AsGecko() const + { + return const_cast<Ptr*>(this)->AsGecko(); + } + + const ServoStyleSet* AsServo() const + { + MOZ_ASSERT(IsServo()); + return const_cast<Ptr*>(this)->AsServo(); + } + + const nsStyleSet* GetAsGecko() const { return IsGecko() ? AsGecko() : nullptr; } + const ServoStyleSet* GetAsServo() const { return IsServo() ? AsServo() : nullptr; } + + // These inline methods are defined in StyleSetHandleInlines.h. + inline void Delete(); + + // Style set interface. These inline methods are defined in + // StyleSetHandleInlines.h and just forward to the underlying + // nsStyleSet or ServoStyleSet. See corresponding comments in + // nsStyleSet.h for descriptions of these methods. + + inline void Init(nsPresContext* aPresContext); + inline void BeginShutdown(); + inline void Shutdown(); + inline bool GetAuthorStyleDisabled() const; + inline nsresult SetAuthorStyleDisabled(bool aStyleDisabled); + inline void BeginUpdate(); + inline nsresult EndUpdate(); + inline already_AddRefed<nsStyleContext> + ResolveStyleFor(dom::Element* aElement, + nsStyleContext* aParentContext); + inline already_AddRefed<nsStyleContext> + ResolveStyleFor(dom::Element* aElement, + nsStyleContext* aParentContext, + TreeMatchContext& aTreeMatchContext); + inline already_AddRefed<nsStyleContext> + ResolveStyleForText(nsIContent* aTextNode, + nsStyleContext* aParentContext); + inline already_AddRefed<nsStyleContext> + ResolveStyleForOtherNonElement(nsStyleContext* aParentContext); + inline already_AddRefed<nsStyleContext> + ResolvePseudoElementStyle(dom::Element* aParentElement, + mozilla::CSSPseudoElementType aType, + nsStyleContext* aParentContext, + dom::Element* aPseudoElement); + inline already_AddRefed<nsStyleContext> + ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext, + uint32_t aFlags = 0); + inline nsresult AppendStyleSheet(SheetType aType, StyleSheet* aSheet); + inline nsresult PrependStyleSheet(SheetType aType, StyleSheet* aSheet); + inline nsresult RemoveStyleSheet(SheetType aType, StyleSheet* aSheet); + inline nsresult ReplaceSheets(SheetType aType, + const nsTArray<RefPtr<StyleSheet>>& aNewSheets); + inline nsresult InsertStyleSheetBefore(SheetType aType, + StyleSheet* aNewSheet, + StyleSheet* aReferenceSheet); + inline int32_t SheetCount(SheetType aType) const; + inline StyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const; + inline nsresult RemoveDocStyleSheet(StyleSheet* aSheet); + inline nsresult AddDocStyleSheet(StyleSheet* aSheet, nsIDocument* aDocument); + inline already_AddRefed<nsStyleContext> + ProbePseudoElementStyle(dom::Element* aParentElement, + mozilla::CSSPseudoElementType aType, + nsStyleContext* aParentContext); + inline already_AddRefed<nsStyleContext> + ProbePseudoElementStyle(dom::Element* aParentElement, + mozilla::CSSPseudoElementType aType, + nsStyleContext* aParentContext, + TreeMatchContext& aTreeMatchContext, + dom::Element* aPseudoElement = nullptr); + inline nsRestyleHint HasStateDependentStyle(dom::Element* aElement, + EventStates aStateMask); + inline nsRestyleHint HasStateDependentStyle( + dom::Element* aElement, + mozilla::CSSPseudoElementType aPseudoType, + dom::Element* aPseudoElement, + EventStates aStateMask); + + inline void RootStyleContextAdded(); + inline void RootStyleContextRemoved(); + + private: + // Stores a pointer to an nsStyleSet or a ServoStyleSet. The least + // significant bit is 0 for the former, 1 for the latter. This is + // valid as the least significant bit will never be used for a pointer + // value on platforms we care about. + uintptr_t mValue; + }; + + StyleSetHandle() { mPtr.mValue = 0; } + StyleSetHandle(const StyleSetHandle& aOth) { mPtr.mValue = aOth.mPtr.mValue; } + MOZ_IMPLICIT StyleSetHandle(nsStyleSet* aSet) { *this = aSet; } + MOZ_IMPLICIT StyleSetHandle(ServoStyleSet* aSet) { *this = aSet; } + + StyleSetHandle& operator=(nsStyleSet* aStyleSet) + { + MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aStyleSet) & SERVO_BIT), + "least significant bit shouldn't be set; we use it for state"); + mPtr.mValue = reinterpret_cast<uintptr_t>(aStyleSet); + return *this; + } + + StyleSetHandle& operator=(ServoStyleSet* aStyleSet) + { +#ifdef MOZ_STYLO + MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aStyleSet) & SERVO_BIT), + "least significant bit shouldn't be set; we use it for state"); + mPtr.mValue = + aStyleSet ? (reinterpret_cast<uintptr_t>(aStyleSet) | SERVO_BIT) : 0; + return *this; +#else + MOZ_CRASH("should not have a ServoStyleSet object when MOZ_STYLO is " + "disabled"); +#endif + } + + // Make StyleSetHandle usable in boolean contexts. + explicit operator bool() const { return !!mPtr.mValue; } + bool operator!() const { return !mPtr.mValue; } + + // Make StyleSetHandle behave like a smart pointer. + Ptr* operator->() { return &mPtr; } + const Ptr* operator->() const { return &mPtr; } + +private: + Ptr mPtr; +}; + +#undef SERVO_BIT + +} // namespace mozilla + +#endif // mozilla_StyleSetHandle_h |