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: #ifndef nsTreeStyleCache_h__ michael@0: #define nsTreeStyleCache_h__ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsHashtable.h" michael@0: #include "nsIAtom.h" michael@0: #include "nsCOMArray.h" michael@0: #include "nsICSSPseudoComparator.h" michael@0: #include "nsStyleContext.h" michael@0: michael@0: typedef nsCOMArray AtomArray; michael@0: michael@0: class nsDFAState : public nsHashKey michael@0: { michael@0: public: michael@0: uint32_t mStateID; michael@0: michael@0: nsDFAState(uint32_t aID) :mStateID(aID) {} michael@0: michael@0: uint32_t GetStateID() { return mStateID; } michael@0: michael@0: uint32_t HashCode(void) const MOZ_OVERRIDE { michael@0: return mStateID; michael@0: } michael@0: michael@0: bool Equals(const nsHashKey *aKey) const MOZ_OVERRIDE { michael@0: nsDFAState* key = (nsDFAState*)aKey; michael@0: return key->mStateID == mStateID; michael@0: } michael@0: michael@0: nsHashKey *Clone(void) const MOZ_OVERRIDE { michael@0: return new nsDFAState(mStateID); michael@0: } michael@0: }; michael@0: michael@0: class nsTransitionKey : public nsHashKey michael@0: { michael@0: public: michael@0: uint32_t mState; michael@0: nsCOMPtr mInputSymbol; michael@0: michael@0: nsTransitionKey(uint32_t aState, nsIAtom* aSymbol) :mState(aState), mInputSymbol(aSymbol) {} michael@0: michael@0: uint32_t HashCode(void) const MOZ_OVERRIDE { michael@0: // Make a 32-bit integer that combines the low-order 16 bits of the state and the input symbol. michael@0: int32_t hb = mState << 16; michael@0: int32_t lb = (NS_PTR_TO_INT32(mInputSymbol.get()) << 16) >> 16; michael@0: return hb+lb; michael@0: } michael@0: michael@0: bool Equals(const nsHashKey *aKey) const MOZ_OVERRIDE { michael@0: nsTransitionKey* key = (nsTransitionKey*)aKey; michael@0: return key->mState == mState && key->mInputSymbol == mInputSymbol; michael@0: } michael@0: michael@0: nsHashKey *Clone(void) const MOZ_OVERRIDE { michael@0: return new nsTransitionKey(mState, mInputSymbol); michael@0: } michael@0: }; michael@0: michael@0: class nsTreeStyleCache michael@0: { michael@0: public: michael@0: nsTreeStyleCache() :mTransitionTable(nullptr), mCache(nullptr), mNextState(0) {} michael@0: ~nsTreeStyleCache() { Clear(); } michael@0: michael@0: void Clear() { delete mTransitionTable; mTransitionTable = nullptr; delete mCache; mCache = nullptr; mNextState = 0; } michael@0: michael@0: nsStyleContext* GetStyleContext(nsICSSPseudoComparator* aComparator, michael@0: nsPresContext* aPresContext, michael@0: nsIContent* aContent, michael@0: nsStyleContext* aContext, michael@0: nsIAtom* aPseudoElement, michael@0: const AtomArray & aInputWord); michael@0: michael@0: static bool DeleteDFAState(nsHashKey *aKey, void *aData, void *closure); michael@0: michael@0: static bool ReleaseStyleContext(nsHashKey *aKey, void *aData, void *closure); michael@0: michael@0: protected: michael@0: // A transition table for a deterministic finite automaton. The DFA michael@0: // takes as its input a single pseudoelement and an ordered set of properties. michael@0: // It transitions on an input word that is the concatenation of the pseudoelement supplied michael@0: // with the properties in the array. michael@0: // michael@0: // It transitions from state to state by looking up entries in the transition table (which is michael@0: // a mapping from (S,i)->S', where S is the current state, i is the next michael@0: // property in the input word, and S' is the state to transition to. michael@0: // michael@0: // If S' is not found, it is constructed and entered into the hashtable michael@0: // under the key (S,i). michael@0: // michael@0: // Once the entire word has been consumed, the final state is used michael@0: // to reference the cache table to locate the style context. michael@0: nsObjectHashtable* mTransitionTable; michael@0: michael@0: // The cache of all active style contexts. This is a hash from michael@0: // a final state in the DFA, Sf, to the resultant style context. michael@0: nsObjectHashtable* mCache; michael@0: michael@0: // An integer counter that is used when we need to make new states in the michael@0: // DFA. michael@0: uint32_t mNextState; michael@0: }; michael@0: michael@0: #endif // nsTreeStyleCache_h__