1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_EXPANSION_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_EXPANSION_H_
7
8 #include <limits>
9 #include "third_party/blink/renderer/core/css/properties/longhands/custom_property.h"
10 #include "third_party/blink/renderer/core/css/resolver/cascade_filter.h"
11 #include "third_party/blink/renderer/core/css/resolver/cascade_origin.h"
12 #include "third_party/blink/renderer/core/css/resolver/cascade_priority.h"
13 #include "third_party/blink/renderer/core/style/computed_style_base_constants.h"
14
15 namespace blink {
16
17 struct MatchedProperties;
18
EncodeMatchResultPosition(uint16_t block,uint16_t declaration)19 inline uint32_t EncodeMatchResultPosition(uint16_t block,
20 uint16_t declaration) {
21 return (static_cast<uint32_t>(block) << 16) | declaration;
22 }
23
DecodeMatchedPropertiesIndex(uint32_t position)24 inline size_t DecodeMatchedPropertiesIndex(uint32_t position) {
25 return (position >> 16) & 0xFFFF;
26 }
27
DecodeDeclarationIndex(uint32_t position)28 inline size_t DecodeDeclarationIndex(uint32_t position) {
29 return position & 0xFFFF;
30 }
31
32 // CascadeExpansion takes a declaration block (MatchedProperties) and
33 // expands the declarations found into the final list of declarations observed
34 // by StyleCascade. It exists to prevent callers to deal with the complexity
35 // of the 'all' property, '-internal-visited-' properties, '-internal-ua-'
36 // properties, and filtering of both regular declarations and "generated"
37 // declarations.
38 //
39 // For example, for the declaration block:
40 //
41 // top:1px;
42 // all:unset;
43 // top:2px;
44 //
45 // CascadeExpansion would emit:
46 //
47 // top:1px;
48 // animation-delay:unset;
49 // animation-direction:unset;
50 // /* ... <all longhands affected by 'all'> ... */
51 // -webkit-text-emphasis:unset;
52 // -webkit-text-stroke:unset;
53 // top:2px;
54 //
55 // In other words, 'all' is expanded into the actual longhands it represents.
56 // A similar expansion happens for properties which have companion
57 // -internal-visited-* properties (depending on inside-link status).
58 //
59 // Usage:
60 //
61 // CascadeExpansion e = ...;
62 // for (; !e.AtEnd(); a.Next())
63 // DoStuff(e);
64 //
65 class CORE_EXPORT CascadeExpansion {
66 STACK_ALLOCATED();
67
68 enum class State { kInit, kNormal, kVisited, kAll };
69
70 public:
71 // CascadeExpansion objects which exceed these limits will emit nothing.
72 static constexpr size_t kMaxDeclarationIndex =
73 std::numeric_limits<uint16_t>::max();
74 static constexpr size_t kMaxMatchedPropertiesIndex =
75 std::numeric_limits<uint16_t>::max();
76
77 CascadeExpansion(const MatchedProperties&,
78 const Document&,
79 CascadeFilter,
80 size_t matched_properties_index);
81 // We need an explicit copy constructor, since CascadeExpansion has self-
82 // pointers.
83 CascadeExpansion(const CascadeExpansion& o);
84 void Next();
AtEnd()85 inline bool AtEnd() const { return index_ >= size_; }
Id()86 inline CSSPropertyID Id() const { return id_; }
Name()87 inline CSSPropertyName Name() const {
88 if (id_ != CSSPropertyID::kVariable)
89 return CSSPropertyName(id_);
90 return Property().GetCSSPropertyName();
91 }
Property()92 inline const CSSProperty& Property() const {
93 DCHECK(!AtEnd());
94 return *property_;
95 }
Value()96 inline const CSSValue& Value() const {
97 DCHECK(!AtEnd());
98 return PropertyAt(index_).Value();
99 }
Priority()100 inline CascadePriority Priority() const { return priority_; }
101 uint16_t TreeOrder() const;
102
103 private:
104 static bool IsAffectedByAll(CSSPropertyID);
105
106 bool ShouldEmitVisited() const;
107
108 void AdvanceNormal();
109 bool AdvanceVisited();
110 void AdvanceAll();
111
112 CSSPropertyValueSet::PropertyReference PropertyAt(size_t) const;
113
114 const Document& document_;
115 State state_ = State::kInit;
116 const MatchedProperties& matched_properties_;
117
118 // The priority of the current declaration pointed to by index_. This does
119 // not change for generated declarations.
120 CascadePriority priority_;
121
122 // Index and size of the regular declarations. In other words, index_ will
123 // only move during State::kNormal, and not while expanding 'all', etc. It
124 // will always point to a valid index in matched_properties_ (unless we're
125 // AtEnd()).
126 //
127 // Note that this is initialized to ~0 such that the first call to Next()
128 // (done by the constructor) will produce ~0+1 = 0.
129 size_t index_ = std::numeric_limits<size_t>::max();
130 size_t size_;
131
132 CascadeFilter filter_;
133 const size_t matched_properties_index_;
134
135 // The id/property of the current "virtual" declaration. In other words,
136 // the id/property will be updated when expanding 'all', etc.
137 CSSPropertyID id_ = CSSPropertyID::kInvalid;
138 const CSSProperty* property_ = nullptr;
139 CustomProperty custom_;
140 };
141
142 } // namespace blink
143
144 #endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_EXPANSION_H_
145