summaryrefslogtreecommitdiffstats
path: root/layout/style/DeclarationBlock.h
blob: c3ed663b440c055c1bc79b5049929e8aa75bb9f8 (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
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

/*
 * representation of a declaration block in a CSS stylesheet, or of
 * a style attribute
 */

#ifndef mozilla_DeclarationBlock_h
#define mozilla_DeclarationBlock_h

#include "mozilla/ServoUtils.h"
#include "mozilla/StyleBackendType.h"

#include "nsCSSPropertyID.h"

class nsHTMLCSSStyleSheet;

namespace mozilla {

class ServoDeclarationBlock;

namespace css {
class Declaration;
class Rule;
} // namespace css

class DeclarationBlock
{
protected:
  explicit DeclarationBlock(StyleBackendType aType)
    : mImmutable(false), mType(aType) { mContainer.mRaw = 0; }

  DeclarationBlock(const DeclarationBlock& aCopy)
    : DeclarationBlock(aCopy.mType) {}

public:
  MOZ_DECL_STYLO_METHODS(css::Declaration, ServoDeclarationBlock)

  inline MozExternalRefCountType AddRef();
  inline MozExternalRefCountType Release();

  inline already_AddRefed<DeclarationBlock> Clone() const;

  /**
   * Return whether |this| may be modified.
   */
  bool IsMutable() const {
    return !mImmutable;
  }

  /**
   * Crash if |this| cannot be modified.
   */
  void AssertMutable() const {
    MOZ_ASSERT(IsMutable(), "someone forgot to call EnsureMutable");
  }

  /**
   * Mark this declaration as unmodifiable.  It's 'const' so it can
   * be called from ToString.
   */
  void SetImmutable() const { mImmutable = true; }

  /**
   * Copy |this|, if necessary to ensure that it can be modified.
   */
  inline already_AddRefed<DeclarationBlock> EnsureMutable();

  void SetOwningRule(css::Rule* aRule) {
    MOZ_ASSERT(!mContainer.mOwningRule || !aRule,
               "should never overwrite one rule with another");
    mContainer.mOwningRule = aRule;
  }

  css::Rule* GetOwningRule() const {
    if (mContainer.mRaw & 0x1) {
      return nullptr;
    }
    return mContainer.mOwningRule;
  }

  void SetHTMLCSSStyleSheet(nsHTMLCSSStyleSheet* aHTMLCSSStyleSheet) {
    MOZ_ASSERT(!mContainer.mHTMLCSSStyleSheet || !aHTMLCSSStyleSheet,
               "should never overwrite one sheet with another");
    mContainer.mHTMLCSSStyleSheet = aHTMLCSSStyleSheet;
    if (aHTMLCSSStyleSheet) {
      mContainer.mRaw |= uintptr_t(1);
    }
  }

  nsHTMLCSSStyleSheet* GetHTMLCSSStyleSheet() const {
    if (!(mContainer.mRaw & 0x1)) {
      return nullptr;
    }
    auto c = mContainer;
    c.mRaw &= ~uintptr_t(1);
    return c.mHTMLCSSStyleSheet;
  }

  inline void ToString(nsAString& aString) const;

  inline uint32_t Count() const;
  inline bool GetNthProperty(uint32_t aIndex, nsAString& aReturn) const;

  inline void GetPropertyValue(const nsAString& aProperty,
                               nsAString& aValue) const;
  inline void GetPropertyValueByID(nsCSSPropertyID aPropID,
                                   nsAString& aValue) const;
  inline void GetAuthoredPropertyValue(const nsAString& aProperty,
                                       nsAString& aValue) const;
  inline bool GetPropertyIsImportant(const nsAString& aProperty) const;
  inline void RemoveProperty(const nsAString& aProperty);
  inline void RemovePropertyByID(nsCSSPropertyID aProperty);

private:
  union {
    // We only ever have one of these since we have an
    // nsHTMLCSSStyleSheet only for style attributes, and style
    // attributes never have an owning rule.

    // It's an nsHTMLCSSStyleSheet if the low bit is set.

    uintptr_t mRaw;

    // The style rule that owns this declaration.  May be null.
    css::Rule* mOwningRule;

    // The nsHTMLCSSStyleSheet that is responsible for this declaration.
    // Only non-null for style attributes.
    nsHTMLCSSStyleSheet* mHTMLCSSStyleSheet;
  } mContainer;

  // set when declaration put in the rule tree;
  // also by ToString (hence the 'mutable').
  mutable bool mImmutable;

  const StyleBackendType mType;
};

} // namespace mozilla

#endif // mozilla_DeclarationBlock_h