/src/mozilla-central/layout/style/nsCSSPseudoElements.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | /* atom list for CSS pseudo-elements */ |
8 | | |
9 | | #include "nsCSSPseudoElements.h" |
10 | | |
11 | | #include "mozilla/ArrayUtils.h" |
12 | | |
13 | | #include "nsCSSAnonBoxes.h" |
14 | | #include "nsDOMString.h" |
15 | | #include "nsGkAtomConsts.h" |
16 | | #include "nsStaticAtomUtils.h" |
17 | | |
18 | | using namespace mozilla; |
19 | | |
20 | | // Flags data for each of the pseudo-elements. |
21 | | /* static */ const uint32_t |
22 | | nsCSSPseudoElements::kPseudoElementFlags[] = { |
23 | | #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \ |
24 | | flags_, |
25 | | #include "nsCSSPseudoElementList.h" |
26 | | #undef CSS_PSEUDO_ELEMENT |
27 | | }; |
28 | | |
29 | | static nsStaticAtom* |
30 | | GetAtomBase() |
31 | 0 | { |
32 | 0 | return const_cast<nsStaticAtom*>( |
33 | 0 | nsGkAtoms::GetAtomByIndex(kAtomIndex_PseudoElements)); |
34 | 0 | } |
35 | | |
36 | | bool |
37 | | nsCSSPseudoElements::IsPseudoElement(nsAtom* aAtom) |
38 | 0 | { |
39 | 0 | return nsStaticAtomUtils::IsMember(aAtom, GetAtomBase(), |
40 | 0 | kAtomCount_PseudoElements); |
41 | 0 | } |
42 | | |
43 | | /* static */ bool |
44 | | nsCSSPseudoElements::IsCSS2PseudoElement(nsAtom *aAtom) |
45 | 0 | { |
46 | 0 | // We don't implement this using PseudoElementHasFlags because callers |
47 | 0 | // want to pass things that could be anon boxes. |
48 | 0 | NS_ASSERTION(nsCSSPseudoElements::IsPseudoElement(aAtom) || |
49 | 0 | nsCSSAnonBoxes::IsAnonBox(aAtom), |
50 | 0 | "must be pseudo element or anon box"); |
51 | 0 | bool result = aAtom == nsCSSPseudoElements::after() || |
52 | 0 | aAtom == nsCSSPseudoElements::before() || |
53 | 0 | aAtom == nsCSSPseudoElements::firstLetter() || |
54 | 0 | aAtom == nsCSSPseudoElements::firstLine(); |
55 | 0 | NS_ASSERTION(nsCSSAnonBoxes::IsAnonBox(aAtom) || |
56 | 0 | result == PseudoElementHasFlags( |
57 | 0 | GetPseudoType(aAtom, EnabledState::eIgnoreEnabledState), |
58 | 0 | CSS_PSEUDO_ELEMENT_IS_CSS2), |
59 | 0 | "result doesn't match flags"); |
60 | 0 | return result; |
61 | 0 | } |
62 | | |
63 | | /* static */ CSSPseudoElementType |
64 | | nsCSSPseudoElements::GetPseudoType(nsAtom* aAtom, EnabledState aEnabledState) |
65 | 0 | { |
66 | 0 | Maybe<uint32_t> index = |
67 | 0 | nsStaticAtomUtils::Lookup(aAtom, GetAtomBase(), kAtomCount_PseudoElements); |
68 | 0 | if (index.isSome()) { |
69 | 0 | auto type = static_cast<Type>(*index); |
70 | 0 | return IsEnabled(type, aEnabledState) ? type : Type::NotPseudo; |
71 | 0 | } |
72 | 0 |
|
73 | 0 | if (nsCSSAnonBoxes::IsAnonBox(aAtom)) { |
74 | 0 | #ifdef MOZ_XUL |
75 | 0 | if (nsCSSAnonBoxes::IsTreePseudoElement(aAtom)) { |
76 | 0 | return Type::XULTree; |
77 | 0 | } |
78 | 0 | #endif |
79 | 0 | |
80 | 0 | if (nsCSSAnonBoxes::IsNonInheritingAnonBox(aAtom)) { |
81 | 0 | return Type::NonInheritingAnonBox; |
82 | 0 | } |
83 | 0 | |
84 | 0 | return Type::InheritingAnonBox; |
85 | 0 | } |
86 | 0 | |
87 | 0 | return Type::NotPseudo; |
88 | 0 | } |
89 | | |
90 | | /* static */ nsAtom* |
91 | | nsCSSPseudoElements::GetPseudoAtom(Type aType) |
92 | 0 | { |
93 | 0 | MOZ_ASSERT(aType < Type::Count, "Unexpected type"); |
94 | 0 | size_t index = kAtomIndex_PseudoElements + static_cast<size_t>(aType); |
95 | 0 | return nsGkAtoms::GetAtomByIndex(index); |
96 | 0 | } |
97 | | |
98 | | /* static */ already_AddRefed<nsAtom> |
99 | | nsCSSPseudoElements::GetPseudoAtom(const nsAString& aPseudoElement) |
100 | 0 | { |
101 | 0 | if (DOMStringIsNull(aPseudoElement) || aPseudoElement.IsEmpty() || |
102 | 0 | aPseudoElement.First() != char16_t(':')) { |
103 | 0 | return nullptr; |
104 | 0 | } |
105 | 0 | |
106 | 0 | // deal with two-colon forms of aPseudoElt |
107 | 0 | nsAString::const_iterator start, end; |
108 | 0 | aPseudoElement.BeginReading(start); |
109 | 0 | aPseudoElement.EndReading(end); |
110 | 0 | NS_ASSERTION(start != end, "aPseudoElement is not empty!"); |
111 | 0 | ++start; |
112 | 0 | bool haveTwoColons = true; |
113 | 0 | if (start == end || *start != char16_t(':')) { |
114 | 0 | --start; |
115 | 0 | haveTwoColons = false; |
116 | 0 | } |
117 | 0 | RefPtr<nsAtom> pseudo = NS_Atomize(Substring(start, end)); |
118 | 0 | MOZ_ASSERT(pseudo); |
119 | 0 |
|
120 | 0 | // There aren't any non-CSS2 pseudo-elements with a single ':' |
121 | 0 | if (!haveTwoColons && |
122 | 0 | (!IsPseudoElement(pseudo) || !IsCSS2PseudoElement(pseudo))) { |
123 | 0 | // XXXbz I'd really rather we threw an exception or something, but |
124 | 0 | // the DOM spec sucks. |
125 | 0 | return nullptr; |
126 | 0 | } |
127 | 0 | |
128 | 0 | return pseudo.forget(); |
129 | 0 | } |
130 | | |
131 | | /* static */ bool |
132 | | nsCSSPseudoElements::PseudoElementSupportsUserActionState(const Type aType) |
133 | 0 | { |
134 | 0 | return PseudoElementHasFlags(aType, |
135 | 0 | CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE); |
136 | 0 | } |
137 | | |
138 | | /* static */ nsString |
139 | | nsCSSPseudoElements::PseudoTypeAsString(Type aPseudoType) |
140 | 0 | { |
141 | 0 | switch (aPseudoType) { |
142 | 0 | case CSSPseudoElementType::before: |
143 | 0 | return NS_LITERAL_STRING("::before"); |
144 | 0 | case CSSPseudoElementType::after: |
145 | 0 | return NS_LITERAL_STRING("::after"); |
146 | 0 | default: |
147 | 0 | MOZ_ASSERT(aPseudoType == CSSPseudoElementType::NotPseudo, |
148 | 0 | "Unexpected pseudo type"); |
149 | 0 | return EmptyString(); |
150 | 0 | } |
151 | 0 | } |
152 | | |
153 | | #ifdef DEBUG |
154 | | /* static */ void |
155 | | nsCSSPseudoElements::AssertAtoms() |
156 | | { |
157 | | nsStaticAtom* base = GetAtomBase(); |
158 | | #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \ |
159 | | { \ |
160 | | RefPtr<nsAtom> atom = NS_Atomize(value_); \ |
161 | | size_t index = static_cast<size_t>(CSSPseudoElementType::name_); \ |
162 | | MOZ_ASSERT(atom == nsGkAtoms::PseudoElement_##name_, \ |
163 | | "Static atom for " #name_ " has incorrect value"); \ |
164 | | MOZ_ASSERT(atom == &base[index], \ |
165 | | "Static atom for " #name_ " not at expected index"); \ |
166 | | } |
167 | | #include "nsCSSPseudoElementList.h" |
168 | | #undef CSS_PSEUDO_ELEMENT |
169 | | } |
170 | | #endif |