summaryrefslogtreecommitdiff
path: root/layout/style/RuleNodeCacheConditions.h
blob: 4b1a2349a55a75df430dba3c43bbac863d8af444 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */

/*
 * an object that stores the result of determining whether a style struct that
 * was computed can be cached in the rule tree, and if so, what the conditions
 * it relies on are
 */

#ifndef RuleNodeCacheConditions_h_
#define RuleNodeCacheConditions_h_

#include "mozilla/Attributes.h"
#include "nsCoord.h"
#include "nsTArray.h"

class nsStyleContext;

namespace mozilla {

/**
 * nsRuleNodeCacheConditions is used to store information about whether
 * we can store a style struct that we're computing in the rule tree.
 *
 * For inherited structs (i.e., structs with inherited properties), we
 * cache the struct in the rule tree if it does not depend on any data
 * in the style context tree, and otherwise store it in the style
 * context tree.  This means that for inherited structs, setting any
 * conditions is equivalent to making the struct uncacheable.
 *
 * For reset structs (i.e., structs with non-inherited properties), we
 * are also able to cache structs in the rule tree conditionally on
 * certain common conditions.  For these structs, setting conditions
 * (SetFontSizeDependency, SetWritingModeDependency) instead causes the
 * struct to be stored, with the condition, in the rule tree.
 */
class RuleNodeCacheConditions
{
public:
  RuleNodeCacheConditions()
    : mFontSize(0), mBits(0) {}
  RuleNodeCacheConditions(const RuleNodeCacheConditions& aOther)
    : mFontSize(aOther.mFontSize), mBits(aOther.mBits) {}
  RuleNodeCacheConditions& operator=(const RuleNodeCacheConditions& aOther)
  {
    mFontSize = aOther.mFontSize;
    mBits = aOther.mBits;
    return *this;
  }
  bool operator==(const RuleNodeCacheConditions& aOther) const
  {
    return mFontSize == aOther.mFontSize &&
           mBits == aOther.mBits;
  }
  bool operator!=(const RuleNodeCacheConditions& aOther) const
  {
    return !(*this == aOther);
  }

  bool Matches(nsStyleContext* aStyleContext) const;

  /**
   * Record that the data being computed depend on the font-size
   * property of the element for which they are being computed.
   *
   * Note that we sometimes actually call this when there is a
   * dependency on the font-size property of the parent element, but we
   * only do so while computing inherited structs (nsStyleFont), and we
   * only store reset structs conditionally.
   */
  void SetFontSizeDependency(nscoord aCoord)
  {
    MOZ_ASSERT(!(mBits & eHaveFontSize) || mFontSize == aCoord);
    mFontSize = aCoord;
    mBits |= eHaveFontSize;
  }

  /**
   * Record that the data being computed depend on the writing mode of
   * the element for which they are being computed, which in turn
   * depends on its 'writing-mode', 'direction', and 'text-orientation'
   * properties.
   */
  void SetWritingModeDependency(uint8_t aWritingMode)
  {
    MOZ_ASSERT(!(mBits & eHaveWritingMode) || GetWritingMode() == aWritingMode);
    mBits |= (static_cast<uint64_t>(aWritingMode) << eWritingModeShift) |
             eHaveWritingMode;
  }

  void SetUncacheable()
  {
    mBits |= eUncacheable;
  }

  void Clear()
  {
    *this = RuleNodeCacheConditions();
  }

  bool Cacheable() const
  {
    return !(mBits & eUncacheable);
  }

  bool CacheableWithDependencies() const
  {
    return !(mBits & eUncacheable) &&
           (mBits & eHaveBitsMask) != 0;
  }

  bool CacheableWithoutDependencies() const
  {
    // We're not uncacheable and we have don't have a font-size or
    // writing mode value.
    return (mBits & eHaveBitsMask) == 0;
  }

#ifdef DEBUG
  void List() const;
#endif

private:
  enum {
    eUncacheable      = 0x0001,
    eHaveFontSize     = 0x0002,
    eHaveWritingMode  = 0x0004,
    eHaveBitsMask     = 0x00ff,
    eWritingModeMask  = 0xff00,
    eWritingModeShift = 8,
  };

  uint8_t GetWritingMode() const
  {
    return static_cast<uint8_t>(
        (mBits & eWritingModeMask) >> eWritingModeShift);
  }

  // The font size from which em units are derived.
  nscoord mFontSize;

  // Values in mBits:
  //   bit 0:      are we set to "uncacheable"?
  //   bit 1:      do we have a font size value?
  //   bit 2:      do we have a writing mode value?
  //   bits 3-7:   unused
  //   bits 8-15:  writing mode (uint8_t)
  //   bits 16-31: unused
  uint32_t mBits;
};

} // namespace mozilla

#endif // !defined(RuleNodeCacheConditions_h_)