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