summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/css/resolver/cascade_expansion.h
blob: 34c6145e135f233d6f243df05c71e9963daac88e (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
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_EXPANSION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_EXPANSION_H_

#include <limits>
#include "third_party/blink/renderer/core/css/properties/longhands/custom_property.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_filter.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_origin.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_priority.h"
#include "third_party/blink/renderer/core/style/computed_style_base_constants.h"

namespace blink {

struct MatchedProperties;

inline uint32_t EncodeMatchResultPosition(uint16_t block,
                                          uint16_t declaration) {
  return (static_cast<uint32_t>(block) << 16) | declaration;
}

inline size_t DecodeMatchedPropertiesIndex(uint32_t position) {
  return (position >> 16) & 0xFFFF;
}

inline size_t DecodeDeclarationIndex(uint32_t position) {
  return position & 0xFFFF;
}

// CascadeExpansion takes a declaration block (MatchedProperties) and
// expands the declarations found into the final list of declarations observed
// by StyleCascade. It exists to prevent callers to deal with the complexity
// of the 'all' property, '-internal-visited-' properties, '-internal-ua-'
// properties, and filtering of both regular declarations and "generated"
// declarations.
//
// For example, for the declaration block:
//
//   top:1px;
//   all:unset;
//   top:2px;
//
// CascadeExpansion would emit:
//
//   top:1px;
//   animation-delay:unset;
//   animation-direction:unset;
//   /* ... <all longhands affected by 'all'> ... */
//   -webkit-text-emphasis:unset;
//   -webkit-text-stroke:unset;
//   top:2px;
//
// In other words, 'all' is expanded into the actual longhands it represents.
// A similar expansion happens for properties which have companion
// -internal-visited-* properties (depending on inside-link status).
//
// Usage:
//
//   CascadeExpansion e = ...;
//   for (; !e.AtEnd(); a.Next())
//     DoStuff(e);
//
class CORE_EXPORT CascadeExpansion {
  STACK_ALLOCATED();

  enum class State { kInit, kNormal, kVisited, kAll };

 public:
  // CascadeExpansion objects which exceed these limits will emit nothing.
  static constexpr size_t kMaxDeclarationIndex =
      std::numeric_limits<uint16_t>::max();
  static constexpr size_t kMaxMatchedPropertiesIndex =
      std::numeric_limits<uint16_t>::max();

  CascadeExpansion(const MatchedProperties&,
                   const Document&,
                   CascadeFilter,
                   size_t matched_properties_index);
  // We need an explicit copy constructor, since CascadeExpansion has self-
  // pointers.
  CascadeExpansion(const CascadeExpansion& o);
  void Next();
  inline bool AtEnd() const { return index_ >= size_; }
  inline CSSPropertyID Id() const { return id_; }
  inline CSSPropertyName Name() const {
    if (id_ != CSSPropertyID::kVariable)
      return CSSPropertyName(id_);
    return Property().GetCSSPropertyName();
  }
  inline const CSSProperty& Property() const {
    DCHECK(!AtEnd());
    return *property_;
  }
  inline const CSSValue& Value() const {
    DCHECK(!AtEnd());
    return PropertyAt(index_).Value();
  }
  inline CascadePriority Priority() const { return priority_; }
  uint16_t TreeOrder() const;

 private:
  friend class CascadeExpansionTest;

  static bool IsInAllExpansion(CSSPropertyID);

  bool ShouldEmitVisited() const;

  void AdvanceNormal();
  bool AdvanceVisited();
  void AdvanceAll();

  CSSPropertyValueSet::PropertyReference PropertyAt(size_t) const;

  const Document& document_;
  State state_ = State::kInit;
  const MatchedProperties& matched_properties_;

  // The priority of the current declaration pointed to by index_. This does
  // not change for generated declarations.
  CascadePriority priority_;

  // Index and size of the regular declarations. In other words, index_ will
  // only move during State::kNormal, and not while expanding 'all', etc. It
  // will always point to a valid index in matched_properties_ (unless we're
  // AtEnd()).
  //
  // Note that this is initialized to ~0 such that the first call to Next()
  // (done by the constructor) will produce ~0+1 = 0.
  size_t index_ = std::numeric_limits<size_t>::max();
  size_t size_;

  CascadeFilter filter_;
  const size_t matched_properties_index_;

  // The id/property of the current "virtual" declaration. In other words,
  // the id/property will be updated when expanding 'all', etc.
  CSSPropertyID id_ = CSSPropertyID::kInvalid;
  const CSSProperty* property_ = nullptr;
  CustomProperty custom_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_EXPANSION_H_