nsTreeStyleCache.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. #include "nsTreeStyleCache.h"
  6. #include "nsStyleSet.h"
  7. #include "mozilla/dom/Element.h"
  8. #include "mozilla/StyleSetHandle.h"
  9. #include "mozilla/StyleSetHandleInlines.h"
  10. nsTreeStyleCache::Transition::Transition(DFAState aState, nsIAtom* aSymbol)
  11. : mState(aState), mInputSymbol(aSymbol)
  12. {
  13. }
  14. bool
  15. nsTreeStyleCache::Transition::operator==(const Transition& aOther) const
  16. {
  17. return aOther.mState == mState && aOther.mInputSymbol == mInputSymbol;
  18. }
  19. uint32_t
  20. nsTreeStyleCache::Transition::Hash() const
  21. {
  22. // Make a 32-bit integer that combines the low-order 16 bits of the state and the input symbol.
  23. uint32_t hb = mState << 16;
  24. uint32_t lb = (NS_PTR_TO_UINT32(mInputSymbol.get()) << 16) >> 16;
  25. return hb+lb;
  26. }
  27. // The style context cache impl
  28. nsStyleContext*
  29. nsTreeStyleCache::GetStyleContext(nsICSSPseudoComparator* aComparator,
  30. nsPresContext* aPresContext,
  31. nsIContent* aContent,
  32. nsStyleContext* aContext,
  33. nsIAtom* aPseudoElement,
  34. const AtomArray & aInputWord)
  35. {
  36. uint32_t count = aInputWord.Length();
  37. // Go ahead and init the transition table.
  38. if (!mTransitionTable) {
  39. // Automatic miss. Build the table
  40. mTransitionTable = new TransitionTable();
  41. }
  42. // The first transition is always made off the supplied pseudo-element.
  43. Transition transition(0, aPseudoElement);
  44. DFAState currState = mTransitionTable->Get(transition);
  45. if (!currState) {
  46. // We had a miss. Make a new state and add it to our hash.
  47. currState = mNextState;
  48. mNextState++;
  49. mTransitionTable->Put(transition, currState);
  50. }
  51. for (uint32_t i = 0; i < count; i++) {
  52. Transition transition(currState, aInputWord[i]);
  53. currState = mTransitionTable->Get(transition);
  54. if (!currState) {
  55. // We had a miss. Make a new state and add it to our hash.
  56. currState = mNextState;
  57. mNextState++;
  58. mTransitionTable->Put(transition, currState);
  59. }
  60. }
  61. // We're in a final state.
  62. // Look up our style context for this state.
  63. nsStyleContext* result = nullptr;
  64. if (mCache) {
  65. result = mCache->GetWeak(currState);
  66. }
  67. if (!result) {
  68. // We missed the cache. Resolve this pseudo-style.
  69. // XXXheycam ServoStyleSets do not support XUL tree styles.
  70. if (aPresContext->StyleSet()->IsServo()) {
  71. MOZ_CRASH("stylo: ServoStyleSets should not support XUL tree styles yet");
  72. }
  73. RefPtr<nsStyleContext> newResult = aPresContext->StyleSet()->AsGecko()->
  74. ResolveXULTreePseudoStyle(aContent->AsElement(), aPseudoElement,
  75. aContext, aComparator);
  76. // Put the style context in our table, transferring the owning reference to the table.
  77. if (!mCache) {
  78. mCache = new StyleContextCache();
  79. }
  80. result = newResult.get();
  81. mCache->Put(currState, newResult.forget());
  82. }
  83. return result;
  84. }