|
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/. */ |
|
5 |
|
6 #include "nsTreeStyleCache.h" |
|
7 #include "nsStyleSet.h" |
|
8 #include "mozilla/dom/Element.h" |
|
9 |
|
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; |
|
22 |
|
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 } |
|
29 |
|
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)); |
|
33 |
|
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 } |
|
40 |
|
41 for (uint32_t i = 0; i < count; i++) { |
|
42 nsTransitionKey key(currState->GetStateID(), aInputWord[i]); |
|
43 currState = static_cast<nsDFAState*>(mTransitionTable->Get(&key)); |
|
44 |
|
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 } |
|
52 |
|
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(); |
|
63 |
|
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 } |
|
70 |
|
71 return result; |
|
72 } |
|
73 |
|
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 } |
|
83 |
|
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 } |