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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
|
// Copyright 2019 The Chromium Authors
// 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_PLATFORM_GEOMETRY_CALCULATION_EXPRESSION_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_CALCULATION_EXPRESSION_NODE_H_
#include "base/check_op.h"
#include "third_party/blink/renderer/platform/geometry/length.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
enum class CalculationOperator {
kAdd,
kSubtract,
kMultiply, // Division is converted to multiplication and use this value too.
kInvert,
kMin,
kMax,
kClamp,
kRoundNearest,
kRoundUp,
kRoundDown,
kRoundToZero,
kMod,
kRem,
kLog,
kExp,
kSqrt,
kHypot,
kAbs,
kSign,
kProgress,
kContainerProgress,
kCalcSize,
kMediaProgress,
kPow,
kSin,
kCos,
kTan,
kAsin,
kAcos,
kAtan,
kAtan2,
kInvalid
};
// Represents an expression composed of numbers, |PixelsAndPercent| and multiple
// types of operators. To be consumed by |Length| values that involve
// non-trivial math functions like min() and max().
class PLATFORM_EXPORT CalculationExpressionNode
: public RefCounted<CalculationExpressionNode> {
public:
virtual float Evaluate(float max_value, const EvaluationInput&) const = 0;
bool operator==(const CalculationExpressionNode& other) const {
return Equals(other);
}
bool operator!=(const CalculationExpressionNode& other) const {
return !operator==(other);
}
bool HasAuto() const { return has_auto_; }
bool HasContentOrIntrinsicSize() const { return has_content_or_intrinsic_; }
bool HasAutoOrContentOrIntrinsicSize() const {
return has_auto_ || has_content_or_intrinsic_;
}
bool HasStretch() const { return has_stretch_; }
// HasPercent returns whether this node's value expression should be
// treated as having a percent. Note that this means that percentages
// inside of the calculation part of a calc-size() do not make the
// calc-size() act as though it has a percent.
bool HasPercent() const { return has_percent_; }
bool HasPercentOrStretch() const { return has_percent_ || has_stretch_; }
bool HasColorChannelKeyword() const { return has_color_channel_keyword_; }
virtual bool HasMinContent() const { return false; }
virtual bool HasMaxContent() const { return false; }
virtual bool HasFitContent() const { return false; }
virtual bool IsNumber() const { return false; }
virtual bool IsIdentifier() const { return false; }
virtual bool IsSizingKeyword() const { return false; }
virtual bool IsColorChannelKeyword() const { return false; }
virtual bool IsPixelsAndPercent() const { return false; }
virtual bool IsOperation() const { return false; }
virtual scoped_refptr<const CalculationExpressionNode> Zoom(
double factor) const = 0;
virtual ~CalculationExpressionNode() = default;
#if DCHECK_IS_ON()
enum class ResultType { kInvalid, kNumber, kPixelsAndPercent, kIdent };
virtual ResultType ResolvedResultType() const = 0;
protected:
ResultType result_type_;
#endif
protected:
virtual bool Equals(const CalculationExpressionNode& other) const = 0;
bool has_content_or_intrinsic_ = false;
bool has_auto_ = false;
bool has_percent_ = false;
bool has_stretch_ = false;
bool has_color_channel_keyword_ = false;
};
class PLATFORM_EXPORT CalculationExpressionNumberNode final
: public CalculationExpressionNode {
public:
CalculationExpressionNumberNode(float value) : value_(value) {
#if DCHECK_IS_ON()
result_type_ = ResultType::kNumber;
#endif
}
float Value() const { return value_; }
// Implement |CalculationExpressionNode|:
float Evaluate(float max_value, const EvaluationInput&) const final;
bool Equals(const CalculationExpressionNode& other) const final;
scoped_refptr<const CalculationExpressionNode> Zoom(
double factor) const final;
bool IsNumber() const final { return true; }
~CalculationExpressionNumberNode() final = default;
#if DCHECK_IS_ON()
ResultType ResolvedResultType() const final;
#endif
private:
float value_;
};
template <>
struct DowncastTraits<CalculationExpressionNumberNode> {
static bool AllowFrom(const CalculationExpressionNode& node) {
return node.IsNumber();
}
};
class PLATFORM_EXPORT CalculationExpressionIdentifierNode final
: public CalculationExpressionNode {
public:
explicit CalculationExpressionIdentifierNode(AtomicString identifier)
: identifier_(std::move(identifier)) {
#if DCHECK_IS_ON()
result_type_ = ResultType::kIdent;
#endif
}
const AtomicString& Value() const { return identifier_; }
// Implement |CalculationExpressionNode|:
float Evaluate(float max_value, const EvaluationInput&) const final {
return 0.0f;
}
bool Equals(const CalculationExpressionNode& other) const final {
auto* other_identifier =
DynamicTo<CalculationExpressionIdentifierNode>(other);
return other_identifier && other_identifier->Value() == Value();
}
scoped_refptr<const CalculationExpressionNode> Zoom(
double factor) const final {
return this;
}
bool IsIdentifier() const final { return true; }
#if DCHECK_IS_ON()
ResultType ResolvedResultType() const final { return ResultType::kIdent; }
#endif
private:
AtomicString identifier_;
};
template <>
struct DowncastTraits<CalculationExpressionIdentifierNode> {
static bool AllowFrom(const CalculationExpressionNode& node) {
return node.IsIdentifier();
}
};
class PLATFORM_EXPORT CalculationExpressionSizingKeywordNode final
: public CalculationExpressionNode {
public:
enum class Keyword : uint8_t {
kSize,
kAny,
kAuto,
kContent,
// The keywords below should match those accepted by
// css_parsing_utils::ValidWidthOrHeightKeyword.
kMinContent,
kWebkitMinContent,
kMaxContent,
kWebkitMaxContent,
kFitContent,
kWebkitFitContent,
kStretch,
kWebkitFillAvailable,
};
explicit CalculationExpressionSizingKeywordNode(Keyword keyword);
Keyword Value() const { return keyword_; }
// Implement |CalculationExpressionNode|:
float Evaluate(float max_value, const EvaluationInput&) const final;
bool Equals(const CalculationExpressionNode& other) const final {
auto* other_sizing_keyword =
DynamicTo<CalculationExpressionSizingKeywordNode>(other);
return other_sizing_keyword && other_sizing_keyword->Value() == Value();
}
scoped_refptr<const CalculationExpressionNode> Zoom(
double factor) const final {
// TODO(https://crbug.com/313072): Is this correct, or do we need to
// adjust for zoom?
return this;
}
bool IsSizingKeyword() const final { return true; }
bool HasMinContent() const final {
return keyword_ == Keyword::kMinContent ||
keyword_ == Keyword::kWebkitMinContent;
}
bool HasMaxContent() const final {
return keyword_ == Keyword::kMaxContent ||
keyword_ == Keyword::kWebkitMaxContent;
}
bool HasFitContent() const final {
return keyword_ == Keyword::kFitContent ||
keyword_ == Keyword::kWebkitFitContent;
}
#if DCHECK_IS_ON()
ResultType ResolvedResultType() const final {
return ResultType::kPixelsAndPercent;
}
#endif
private:
Keyword keyword_;
};
template <>
struct DowncastTraits<CalculationExpressionSizingKeywordNode> {
static bool AllowFrom(const CalculationExpressionNode& node) {
return node.IsSizingKeyword();
}
};
class PLATFORM_EXPORT CalculationExpressionColorChannelKeywordNode final
: public CalculationExpressionNode {
public:
explicit CalculationExpressionColorChannelKeywordNode(
ColorChannelKeyword channel);
ColorChannelKeyword Value() const { return channel_; }
// Implement |CalculationExpressionNode|:
float Evaluate(float max_value, const EvaluationInput&) const final;
bool Equals(const CalculationExpressionNode& other) const final {
auto* other_color_channel_keyword =
DynamicTo<CalculationExpressionColorChannelKeywordNode>(other);
return other_color_channel_keyword &&
other_color_channel_keyword->Value() == Value();
}
scoped_refptr<const CalculationExpressionNode> Zoom(
double factor) const final {
return this;
}
bool IsColorChannelKeyword() const final { return true; }
#if DCHECK_IS_ON()
ResultType ResolvedResultType() const final { return ResultType::kNumber; }
#endif
private:
ColorChannelKeyword channel_;
};
template <>
struct DowncastTraits<CalculationExpressionColorChannelKeywordNode> {
static bool AllowFrom(const CalculationExpressionNode& node) {
return node.IsColorChannelKeyword();
}
};
class PLATFORM_EXPORT CalculationExpressionPixelsAndPercentNode final
: public CalculationExpressionNode {
public:
CalculationExpressionPixelsAndPercentNode(PixelsAndPercent value)
: value_(value) {
#if DCHECK_IS_ON()
result_type_ = ResultType::kPixelsAndPercent;
#endif
if (value.has_explicit_percent) {
has_percent_ = true;
}
}
float Pixels() const { return value_.pixels; }
float Percent() const { return value_.percent; }
PixelsAndPercent GetPixelsAndPercent() const { return value_; }
bool HasExplicitPixels() const { return value_.has_explicit_pixels; }
bool HasExplicitPercent() const { return value_.has_explicit_percent; }
// Implement |CalculationExpressionNode|:
float Evaluate(float max_value, const EvaluationInput&) const final;
bool Equals(const CalculationExpressionNode& other) const final;
scoped_refptr<const CalculationExpressionNode> Zoom(
double factor) const final;
bool IsPixelsAndPercent() const final { return true; }
~CalculationExpressionPixelsAndPercentNode() final = default;
#if DCHECK_IS_ON()
ResultType ResolvedResultType() const final;
#endif
private:
PixelsAndPercent value_;
};
template <>
struct DowncastTraits<CalculationExpressionPixelsAndPercentNode> {
static bool AllowFrom(const CalculationExpressionNode& node) {
return node.IsPixelsAndPercent();
}
};
class PLATFORM_EXPORT CalculationExpressionOperationNode final
: public CalculationExpressionNode {
public:
using Children = Vector<scoped_refptr<const CalculationExpressionNode>>;
static scoped_refptr<const CalculationExpressionNode> CreateSimplified(
Children&& children,
CalculationOperator op);
CalculationExpressionOperationNode(Children&& children,
CalculationOperator op);
const Children& GetChildren() const { return children_; }
CalculationOperator GetOperator() const { return operator_; }
// Implement |CalculationExpressionNode|:
float Evaluate(float max_value, const EvaluationInput&) const final;
bool Equals(const CalculationExpressionNode& other) const final;
scoped_refptr<const CalculationExpressionNode> Zoom(
double factor) const final;
bool IsOperation() const final { return true; }
bool HasMinContent() const final;
bool HasMaxContent() const final;
bool HasFitContent() const final;
~CalculationExpressionOperationNode() final = default;
#if DCHECK_IS_ON()
ResultType ResolvedResultType() const final;
#endif
private:
Children children_;
CalculationOperator operator_;
};
template <>
struct DowncastTraits<CalculationExpressionOperationNode> {
static bool AllowFrom(const CalculationExpressionNode& node) {
return node.IsOperation();
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_CALCULATION_EXPRESSION_NODE_H_
|