Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsTreeStyleCache.h"
7 #include "nsStyleSet.h"
8 #include "mozilla/dom/Element.h"
10 // The style context cache impl
11 nsStyleContext*
12 nsTreeStyleCache::GetStyleContext(nsICSSPseudoComparator* aComparator,
13 nsPresContext* aPresContext,
14 nsIContent* aContent,
15 nsStyleContext* aContext,
16 nsIAtom* aPseudoElement,
17 const AtomArray & aInputWord)
18 {
19 uint32_t count = aInputWord.Length();
20 nsDFAState startState(0);
21 nsDFAState* currState = &startState;
23 // Go ahead and init the transition table.
24 if (!mTransitionTable) {
25 // Automatic miss. Build the table
26 mTransitionTable =
27 new nsObjectHashtable(nullptr, nullptr, DeleteDFAState, nullptr);
28 }
30 // The first transition is always made off the supplied pseudo-element.
31 nsTransitionKey key(currState->GetStateID(), aPseudoElement);
32 currState = static_cast<nsDFAState*>(mTransitionTable->Get(&key));
34 if (!currState) {
35 // We had a miss. Make a new state and add it to our hash.
36 currState = new nsDFAState(mNextState);
37 mNextState++;
38 mTransitionTable->Put(&key, currState);
39 }
41 for (uint32_t i = 0; i < count; i++) {
42 nsTransitionKey key(currState->GetStateID(), aInputWord[i]);
43 currState = static_cast<nsDFAState*>(mTransitionTable->Get(&key));
45 if (!currState) {
46 // We had a miss. Make a new state and add it to our hash.
47 currState = new nsDFAState(mNextState);
48 mNextState++;
49 mTransitionTable->Put(&key, currState);
50 }
51 }
53 // We're in a final state.
54 // Look up our style context for this state.
55 nsStyleContext* result = nullptr;
56 if (mCache)
57 result = static_cast<nsStyleContext*>(mCache->Get(currState));
58 if (!result) {
59 // We missed the cache. Resolve this pseudo-style.
60 result = aPresContext->StyleSet()->
61 ResolveXULTreePseudoStyle(aContent->AsElement(), aPseudoElement,
62 aContext, aComparator).take();
64 // Put the style context in our table, transferring the owning reference to the table.
65 if (!mCache) {
66 mCache = new nsObjectHashtable(nullptr, nullptr, ReleaseStyleContext, nullptr);
67 }
68 mCache->Put(currState, result);
69 }
71 return result;
72 }
74 bool
75 nsTreeStyleCache::DeleteDFAState(nsHashKey *aKey,
76 void *aData,
77 void *closure)
78 {
79 nsDFAState* entry = static_cast<nsDFAState*>(aData);
80 delete entry;
81 return true;
82 }
84 bool
85 nsTreeStyleCache::ReleaseStyleContext(nsHashKey *aKey,
86 void *aData,
87 void *closure)
88 {
89 nsStyleContext* context = static_cast<nsStyleContext*>(aData);
90 context->Release();
91 return true;
92 }