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 /* atom list for CSS pseudo-elements */
7 
8 #include "mozilla/ArrayUtils.h"
9 
10 #include "nsCSSPseudoElements.h"
11 #include "nsAtomListUtils.h"
12 #include "nsStaticAtom.h"
13 #include "nsCSSAnonBoxes.h"
14 
15 using namespace mozilla;
16 
17 // define storage for all atoms
18 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
19   nsICSSPseudoElement* nsCSSPseudoElements::name_;
20 #include "nsCSSPseudoElementList.h"
21 #undef CSS_PSEUDO_ELEMENT
22 
23 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
24   NS_STATIC_ATOM_BUFFER(name_##_pseudo_element_buffer, value_)
25 #include "nsCSSPseudoElementList.h"
26 #undef CSS_PSEUDO_ELEMENT
27 
28 // Array of nsStaticAtom for each of the pseudo-elements.
29 static const nsStaticAtom CSSPseudoElements_info[] = {
30 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
31   NS_STATIC_ATOM(name_##_pseudo_element_buffer, (nsIAtom**)&nsCSSPseudoElements::name_),
32 #include "nsCSSPseudoElementList.h"
33 #undef CSS_PSEUDO_ELEMENT
34 };
35 
36 // Flags data for each of the pseudo-elements, which must be separate
37 // from the previous array since there's no place for it in
38 // nsStaticAtom.
39 /* static */ const uint32_t
40 nsCSSPseudoElements::kPseudoElementFlags[] = {
41 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
42   flags_,
43 #include "nsCSSPseudoElementList.h"
44 #undef CSS_PSEUDO_ELEMENT
45 };
46 
AddRefAtoms()47 void nsCSSPseudoElements::AddRefAtoms()
48 {
49   NS_RegisterStaticAtoms(CSSPseudoElements_info);
50 }
51 
IsPseudoElement(nsIAtom * aAtom)52 bool nsCSSPseudoElements::IsPseudoElement(nsIAtom *aAtom)
53 {
54   return nsAtomListUtils::IsMember(aAtom, CSSPseudoElements_info,
55                                    ArrayLength(CSSPseudoElements_info));
56 }
57 
58 /* static */ bool
IsCSS2PseudoElement(nsIAtom * aAtom)59 nsCSSPseudoElements::IsCSS2PseudoElement(nsIAtom *aAtom)
60 {
61   // We don't implement this using PseudoElementHasFlags because callers
62   // want to pass things that could be anon boxes.
63   NS_ASSERTION(nsCSSPseudoElements::IsPseudoElement(aAtom) ||
64                nsCSSAnonBoxes::IsAnonBox(aAtom),
65                "must be pseudo element or anon box");
66   bool result = aAtom == nsCSSPseudoElements::after ||
67                   aAtom == nsCSSPseudoElements::before ||
68                   aAtom == nsCSSPseudoElements::firstLetter ||
69                   aAtom == nsCSSPseudoElements::firstLine;
70   NS_ASSERTION(nsCSSAnonBoxes::IsAnonBox(aAtom) ||
71                result == PseudoElementHasFlags(
72                    GetPseudoType(aAtom, EnabledState::eIgnoreEnabledState),
73                    CSS_PSEUDO_ELEMENT_IS_CSS2),
74                "result doesn't match flags");
75   return result;
76 }
77 
78 /* static */ CSSPseudoElementType
GetPseudoType(nsIAtom * aAtom,EnabledState aEnabledState)79 nsCSSPseudoElements::GetPseudoType(nsIAtom *aAtom, EnabledState aEnabledState)
80 {
81   for (CSSPseudoElementTypeBase i = 0;
82        i < ArrayLength(CSSPseudoElements_info);
83        ++i) {
84     if (*CSSPseudoElements_info[i].mAtom == aAtom) {
85       auto type = static_cast<Type>(i);
86       // ::moz-placeholder is an alias for ::placeholder
87       if (type == CSSPseudoElementType::mozPlaceholder) {
88         type = CSSPseudoElementType::placeholder;
89       }
90       return IsEnabled(type, aEnabledState) ? type : Type::NotPseudo;
91     }
92   }
93 
94   if (nsCSSAnonBoxes::IsAnonBox(aAtom)) {
95 #ifdef MOZ_XUL
96     if (nsCSSAnonBoxes::IsTreePseudoElement(aAtom)) {
97       return Type::XULTree;
98     }
99 #endif
100 
101     return Type::AnonBox;
102   }
103 
104   return Type::NotPseudo;
105 }
106 
107 /* static */ nsIAtom*
GetPseudoAtom(Type aType)108 nsCSSPseudoElements::GetPseudoAtom(Type aType)
109 {
110   NS_ASSERTION(aType < Type::Count, "Unexpected type");
111   return *CSSPseudoElements_info[
112     static_cast<CSSPseudoElementTypeBase>(aType)].mAtom;
113 }
114 
115 /* static */ bool
PseudoElementSupportsUserActionState(const Type aType)116 nsCSSPseudoElements::PseudoElementSupportsUserActionState(const Type aType)
117 {
118   return PseudoElementHasFlags(aType,
119                                CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE);
120 }
121