1 // Copyright 2014 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 #include "third_party/blink/renderer/core/style/computed_style.h"
6
7 #include "build/build_config.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/blink/renderer/core/css/css_font_selector.h"
10 #include "third_party/blink/renderer/core/css/css_gradient_value.h"
11 #include "third_party/blink/renderer/core/css/css_identifier_value.h"
12 #include "third_party/blink/renderer/core/css/css_math_expression_node.h"
13 #include "third_party/blink/renderer/core/css/css_math_function_value.h"
14 #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
15 #include "third_party/blink/renderer/core/css/css_test_helpers.h"
16 #include "third_party/blink/renderer/core/css/css_value_list.h"
17 #include "third_party/blink/renderer/core/css/parser/css_parser.h"
18 #include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
19 #include "third_party/blink/renderer/core/css/property_registry.h"
20 #include "third_party/blink/renderer/core/css/resolver/style_adjuster.h"
21 #include "third_party/blink/renderer/core/css/resolver/style_cascade.h"
22 #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
23 #include "third_party/blink/renderer/core/css/style_engine.h"
24 #include "third_party/blink/renderer/core/dom/document.h"
25 #include "third_party/blink/renderer/core/frame/settings.h"
26 #include "third_party/blink/renderer/core/style/clip_path_operation.h"
27 #include "third_party/blink/renderer/core/style/shape_clip_path_operation.h"
28 #include "third_party/blink/renderer/core/style/shape_value.h"
29 #include "third_party/blink/renderer/core/style/style_difference.h"
30 #include "third_party/blink/renderer/core/style/style_generated_image.h"
31 #include "third_party/blink/renderer/core/style/style_initial_data.h"
32 #include "third_party/blink/renderer/core/testing/color_scheme_helper.h"
33 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
34 #include "third_party/blink/renderer/platform/heap/heap.h"
35 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
36 #include "third_party/blink/renderer/platform/transforms/scale_transform_operation.h"
37 #include "ui/base/ui_base_features.h"
38
39 namespace blink {
40
TEST(ComputedStyleTest,ShapeOutsideBoxEqual)41 TEST(ComputedStyleTest, ShapeOutsideBoxEqual) {
42 auto* shape1 = MakeGarbageCollected<ShapeValue>(CSSBoxType::kContent);
43 auto* shape2 = MakeGarbageCollected<ShapeValue>(CSSBoxType::kContent);
44 scoped_refptr<ComputedStyle> style1 = ComputedStyle::Create();
45 scoped_refptr<ComputedStyle> style2 = ComputedStyle::Create();
46 style1->SetShapeOutside(shape1);
47 style2->SetShapeOutside(shape2);
48 EXPECT_EQ(*style1, *style2);
49 }
50
TEST(ComputedStyleTest,ShapeOutsideCircleEqual)51 TEST(ComputedStyleTest, ShapeOutsideCircleEqual) {
52 scoped_refptr<BasicShapeCircle> circle1 = BasicShapeCircle::Create();
53 scoped_refptr<BasicShapeCircle> circle2 = BasicShapeCircle::Create();
54 auto* shape1 = MakeGarbageCollected<ShapeValue>(std::move(circle1),
55 CSSBoxType::kContent);
56 auto* shape2 = MakeGarbageCollected<ShapeValue>(std::move(circle2),
57 CSSBoxType::kContent);
58 scoped_refptr<ComputedStyle> style1 = ComputedStyle::Create();
59 scoped_refptr<ComputedStyle> style2 = ComputedStyle::Create();
60 style1->SetShapeOutside(shape1);
61 style2->SetShapeOutside(shape2);
62 EXPECT_EQ(*style1, *style2);
63 }
64
TEST(ComputedStyleTest,ClipPathEqual)65 TEST(ComputedStyleTest, ClipPathEqual) {
66 scoped_refptr<BasicShapeCircle> shape = BasicShapeCircle::Create();
67 scoped_refptr<ShapeClipPathOperation> path1 =
68 ShapeClipPathOperation::Create(shape);
69 scoped_refptr<ShapeClipPathOperation> path2 =
70 ShapeClipPathOperation::Create(shape);
71 scoped_refptr<ComputedStyle> style1 = ComputedStyle::Create();
72 scoped_refptr<ComputedStyle> style2 = ComputedStyle::Create();
73 style1->SetClipPath(path1);
74 style2->SetClipPath(path2);
75 EXPECT_EQ(*style1, *style2);
76 }
77
TEST(ComputedStyleTest,FocusRingWidth)78 TEST(ComputedStyleTest, FocusRingWidth) {
79 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
80 if (::features::IsFormControlsRefreshEnabled()) {
81 style->SetOutlineStyleIsAuto(static_cast<bool>(OutlineIsAuto::kOn));
82 EXPECT_EQ(3, style->GetOutlineStrokeWidthForFocusRing());
83 style->SetEffectiveZoom(3.5);
84 style->SetOutlineWidth(4);
85 EXPECT_EQ(3.5, style->GetOutlineStrokeWidthForFocusRing());
86 } else {
87 style->SetEffectiveZoom(3.5);
88 style->SetOutlineStyle(EBorderStyle::kSolid);
89 #if defined(OS_MAC)
90 EXPECT_EQ(3, style->GetOutlineStrokeWidthForFocusRing());
91 #else
92 style->SetOutlineStyleIsAuto(static_cast<bool>(OutlineIsAuto::kOn));
93 static uint16_t outline_width = 4;
94 style->SetOutlineWidth(outline_width);
95
96 double expected_width = 3.5;
97 EXPECT_EQ(expected_width, style->GetOutlineStrokeWidthForFocusRing());
98
99 expected_width = 1.0;
100 style->SetEffectiveZoom(0.5);
101 EXPECT_EQ(expected_width, style->GetOutlineStrokeWidthForFocusRing());
102 #endif
103 }
104 }
105
TEST(ComputedStyleTest,FocusRingOutset)106 TEST(ComputedStyleTest, FocusRingOutset) {
107 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
108 style->SetOutlineStyle(EBorderStyle::kSolid);
109 style->SetOutlineStyleIsAuto(static_cast<bool>(OutlineIsAuto::kOn));
110 style->SetEffectiveZoom(4.75);
111 if (::features::IsFormControlsRefreshEnabled()) {
112 EXPECT_EQ(4, style->OutlineOutsetExtent());
113 } else {
114 #if defined(OS_MAC)
115 EXPECT_EQ(4, style->OutlineOutsetExtent());
116 #else
117 EXPECT_EQ(3, style->OutlineOutsetExtent());
118 #endif
119 }
120 }
121
TEST(ComputedStyleTest,SVGStackingContext)122 TEST(ComputedStyleTest, SVGStackingContext) {
123 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
124 style->UpdateIsStackingContextWithoutContainment(false, false, true);
125 EXPECT_TRUE(style->IsStackingContextWithoutContainment());
126 }
127
TEST(ComputedStyleTest,Preserve3dForceStackingContext)128 TEST(ComputedStyleTest, Preserve3dForceStackingContext) {
129 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
130 style->SetTransformStyle3D(ETransformStyle3D::kPreserve3d);
131 style->SetOverflowX(EOverflow::kHidden);
132 style->SetOverflowY(EOverflow::kHidden);
133 style->UpdateIsStackingContextWithoutContainment(false, false, false);
134 EXPECT_EQ(ETransformStyle3D::kFlat, style->UsedTransformStyle3D());
135 EXPECT_TRUE(style->IsStackingContextWithoutContainment());
136 }
137
TEST(ComputedStyleTest,LayoutContainmentStackingContext)138 TEST(ComputedStyleTest, LayoutContainmentStackingContext) {
139 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
140 EXPECT_FALSE(style->IsStackingContextWithoutContainment());
141 style->SetContain(kContainsLayout);
142 style->UpdateIsStackingContextWithoutContainment(false, false, false);
143 // Containment doesn't change IsStackingContextWithoutContainment
144 EXPECT_FALSE(style->IsStackingContextWithoutContainment());
145 }
146
TEST(ComputedStyleTest,FirstPublicPseudoStyle)147 TEST(ComputedStyleTest, FirstPublicPseudoStyle) {
148 static_assert(kFirstPublicPseudoId == kPseudoIdFirstLine,
149 "Make sure we are testing the first public pseudo id");
150
151 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
152 style->SetHasPseudoElementStyle(kPseudoIdFirstLine);
153 EXPECT_TRUE(style->HasPseudoElementStyle(kPseudoIdFirstLine));
154 EXPECT_TRUE(style->HasAnyPseudoElementStyles());
155 }
156
TEST(ComputedStyleTest,LastPublicPseudoElementStyle)157 TEST(ComputedStyleTest, LastPublicPseudoElementStyle) {
158 static_assert(kFirstInternalPseudoId - 1 == kPseudoIdTargetText,
159 "Make sure we are testing the last public pseudo id");
160
161 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
162 style->SetHasPseudoElementStyle(kPseudoIdTargetText);
163 EXPECT_TRUE(style->HasPseudoElementStyle(kPseudoIdTargetText));
164 EXPECT_TRUE(style->HasAnyPseudoElementStyles());
165 }
166
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesRespectsTransformAnimation)167 TEST(ComputedStyleTest,
168 UpdatePropertySpecificDifferencesRespectsTransformAnimation) {
169 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
170 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
171 other->SetHasCurrentTransformAnimation(true);
172 StyleDifference diff;
173 style->UpdatePropertySpecificDifferences(*other, diff);
174 EXPECT_TRUE(diff.TransformChanged());
175 }
176
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesCompositingReasonsTransforom)177 TEST(ComputedStyleTest,
178 UpdatePropertySpecificDifferencesCompositingReasonsTransforom) {
179 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
180 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
181
182 TransformOperations operations;
183 // An operation is necessary since having either a non-empty transform list
184 // or a transform animation will set HasTransform();
185 operations.Operations().push_back(
186 ScaleTransformOperation::Create(1, 1, TransformOperation::kScale));
187
188 style->SetTransform(operations);
189 other->SetTransform(operations);
190
191 other->SetHasCurrentTransformAnimation(true);
192 StyleDifference diff;
193 style->UpdatePropertySpecificDifferences(*other, diff);
194 EXPECT_FALSE(diff.TransformChanged());
195 EXPECT_TRUE(diff.CompositingReasonsChanged());
196 }
197
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesCompositingReasonsOpacity)198 TEST(ComputedStyleTest,
199 UpdatePropertySpecificDifferencesCompositingReasonsOpacity) {
200 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
201 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
202
203 other->SetHasCurrentOpacityAnimation(true);
204 StyleDifference diff;
205 style->UpdatePropertySpecificDifferences(*other, diff);
206 EXPECT_TRUE(diff.CompositingReasonsChanged());
207 }
208
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesCompositingReasonsFilter)209 TEST(ComputedStyleTest,
210 UpdatePropertySpecificDifferencesCompositingReasonsFilter) {
211 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
212 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
213
214 other->SetHasCurrentFilterAnimation(true);
215 StyleDifference diff;
216 style->UpdatePropertySpecificDifferences(*other, diff);
217 EXPECT_TRUE(diff.CompositingReasonsChanged());
218 }
219
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesCompositingReasonsBackdropFilter)220 TEST(ComputedStyleTest,
221 UpdatePropertySpecificDifferencesCompositingReasonsBackdropFilter) {
222 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
223 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
224
225 other->SetHasCurrentBackdropFilterAnimation(true);
226 StyleDifference diff;
227 style->UpdatePropertySpecificDifferences(*other, diff);
228 EXPECT_TRUE(diff.CompositingReasonsChanged());
229 }
230
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesCompositingReasonsBackfaceVisibility)231 TEST(ComputedStyleTest,
232 UpdatePropertySpecificDifferencesCompositingReasonsBackfaceVisibility) {
233 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
234 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
235
236 other->SetBackfaceVisibility(EBackfaceVisibility::kHidden);
237 StyleDifference diff;
238 style->UpdatePropertySpecificDifferences(*other, diff);
239 EXPECT_TRUE(diff.CompositingReasonsChanged());
240 }
241
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesCompositingReasonsWillChange)242 TEST(ComputedStyleTest,
243 UpdatePropertySpecificDifferencesCompositingReasonsWillChange) {
244 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
245 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
246
247 other->SetBackfaceVisibility(EBackfaceVisibility::kHidden);
248 StyleDifference diff;
249 style->UpdatePropertySpecificDifferences(*other, diff);
250 EXPECT_TRUE(diff.CompositingReasonsChanged());
251 }
252
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesCompositingReasonsUsedStylePreserve3D)253 TEST(ComputedStyleTest,
254 UpdatePropertySpecificDifferencesCompositingReasonsUsedStylePreserve3D) {
255 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
256 style->SetTransformStyle3D(ETransformStyle3D::kPreserve3d);
257 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
258
259 // This induces a flat used transform style.
260 other->SetOpacity(0.5);
261 StyleDifference diff;
262 style->UpdatePropertySpecificDifferences(*other, diff);
263 EXPECT_TRUE(diff.CompositingReasonsChanged());
264 }
265
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesCompositingReasonsOverflow)266 TEST(ComputedStyleTest,
267 UpdatePropertySpecificDifferencesCompositingReasonsOverflow) {
268 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
269 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
270
271 other->SetOverflowX(EOverflow::kHidden);
272 StyleDifference diff;
273 style->UpdatePropertySpecificDifferences(*other, diff);
274 EXPECT_TRUE(diff.CompositingReasonsChanged());
275 }
276
TEST(ComputedStyleTest,UpdatePropertySpecificDifferencesCompositingReasonsContainsPaint)277 TEST(ComputedStyleTest,
278 UpdatePropertySpecificDifferencesCompositingReasonsContainsPaint) {
279 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
280 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
281
282 // This induces a flat used transform style.
283 other->SetContain(kContainsPaint);
284 StyleDifference diff;
285 style->UpdatePropertySpecificDifferences(*other, diff);
286 EXPECT_TRUE(diff.CompositingReasonsChanged());
287 }
288
TEST(ComputedStyleTest,UpdateBackgroundColorDifferencesHasAlpha)289 TEST(ComputedStyleTest, UpdateBackgroundColorDifferencesHasAlpha) {
290 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
291 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
292
293 StyleDifference diff;
294 style->AdjustDiffForBackgroundVisuallyEqual(*other, diff);
295 EXPECT_FALSE(diff.HasAlphaChanged());
296
297 style->SetBackgroundColor(StyleColor(Color(255, 255, 255, 255)));
298 other->SetBackgroundColor(StyleColor(Color(255, 255, 255, 128)));
299
300 EXPECT_FALSE(
301 style->VisitedDependentColor(GetCSSPropertyBackgroundColor()).HasAlpha());
302 EXPECT_TRUE(
303 other->VisitedDependentColor(GetCSSPropertyBackgroundColor()).HasAlpha());
304
305 style->AdjustDiffForBackgroundVisuallyEqual(*other, diff);
306 EXPECT_TRUE(diff.HasAlphaChanged());
307 }
308
TEST(ComputedStyleTest,UpdateBackgroundLayerDifferencesHasAlpha)309 TEST(ComputedStyleTest, UpdateBackgroundLayerDifferencesHasAlpha) {
310 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
311 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
312
313 StyleDifference diff;
314 style->AdjustDiffForBackgroundVisuallyEqual(*other, diff);
315 EXPECT_FALSE(diff.HasAlphaChanged());
316
317 other->AccessBackgroundLayers().EnsureNext();
318 style->AdjustDiffForBackgroundVisuallyEqual(*other, diff);
319 EXPECT_TRUE(diff.HasAlphaChanged());
320 }
321
TEST(ComputedStyleTest,HasOutlineWithCurrentColor)322 TEST(ComputedStyleTest, HasOutlineWithCurrentColor) {
323 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
324 EXPECT_FALSE(style->HasOutline());
325 EXPECT_FALSE(style->HasOutlineWithCurrentColor());
326 style->SetOutlineColor(StyleColor::CurrentColor());
327 EXPECT_FALSE(style->HasOutlineWithCurrentColor());
328 style->SetOutlineWidth(5);
329 EXPECT_FALSE(style->HasOutlineWithCurrentColor());
330 style->SetOutlineStyle(EBorderStyle::kSolid);
331 EXPECT_TRUE(style->HasOutlineWithCurrentColor());
332 }
333
TEST(ComputedStyleTest,HasBorderColorReferencingCurrentColor)334 TEST(ComputedStyleTest, HasBorderColorReferencingCurrentColor) {
335 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
336 EXPECT_FALSE(style->HasBorderColorReferencingCurrentColor());
337 style->SetBorderBottomColor(StyleColor::CurrentColor());
338 EXPECT_FALSE(style->HasBorderColorReferencingCurrentColor());
339 style->SetBorderBottomWidth(5);
340 EXPECT_FALSE(style->HasBorderColorReferencingCurrentColor());
341 style->SetBorderBottomStyle(EBorderStyle::kSolid);
342 EXPECT_TRUE(style->HasBorderColorReferencingCurrentColor());
343 }
344
TEST(ComputedStyleTest,BorderWidth)345 TEST(ComputedStyleTest, BorderWidth) {
346 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
347 style->SetBorderBottomWidth(5);
348 EXPECT_EQ(style->BorderBottomWidth(), 0);
349 EXPECT_EQ(style->BorderBottom().Width(), 5);
350 style->SetBorderBottomStyle(EBorderStyle::kSolid);
351 EXPECT_EQ(style->BorderBottomWidth(), 5);
352 EXPECT_EQ(style->BorderBottom().Width(), 5);
353 }
354
TEST(ComputedStyleTest,CursorList)355 TEST(ComputedStyleTest, CursorList) {
356 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
357 scoped_refptr<ComputedStyle> other = ComputedStyle::Create();
358
359 auto* gradient = MakeGarbageCollected<cssvalue::CSSLinearGradientValue>(
360 nullptr, nullptr, nullptr, nullptr, nullptr, cssvalue::kRepeating);
361
362 auto* image_value = MakeGarbageCollected<StyleGeneratedImage>(*gradient);
363 auto* other_image_value =
364 MakeGarbageCollected<StyleGeneratedImage>(*gradient);
365
366 EXPECT_TRUE(DataEquivalent(image_value, other_image_value));
367
368 style->AddCursor(image_value, false);
369 other->AddCursor(other_image_value, false);
370 EXPECT_EQ(*style, *other);
371 }
372
TEST(ComputedStyleTest,BorderStyle)373 TEST(ComputedStyleTest, BorderStyle) {
374 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
375 scoped_refptr<ComputedStyle> other = ComputedStyle::Create();
376 style->SetBorderLeftStyle(EBorderStyle::kSolid);
377 style->SetBorderTopStyle(EBorderStyle::kSolid);
378 style->SetBorderRightStyle(EBorderStyle::kSolid);
379 style->SetBorderBottomStyle(EBorderStyle::kSolid);
380 other->SetBorderLeftStyle(EBorderStyle::kSolid);
381 other->SetBorderTopStyle(EBorderStyle::kSolid);
382 other->SetBorderRightStyle(EBorderStyle::kSolid);
383 other->SetBorderBottomStyle(EBorderStyle::kSolid);
384
385 EXPECT_TRUE(style->BorderSizeEquals(*other));
386 style->SetBorderLeftWidth(1.0);
387 EXPECT_FALSE(style->BorderSizeEquals(*other));
388 other->SetBorderLeftWidth(1.0);
389 EXPECT_TRUE(style->BorderSizeEquals(*other));
390
391 EXPECT_TRUE(style->BorderSizeEquals(*other));
392 style->SetBorderTopWidth(1.0);
393 EXPECT_FALSE(style->BorderSizeEquals(*other));
394 other->SetBorderTopWidth(1.0);
395 EXPECT_TRUE(style->BorderSizeEquals(*other));
396
397 EXPECT_TRUE(style->BorderSizeEquals(*other));
398 style->SetBorderRightWidth(1.0);
399 EXPECT_FALSE(style->BorderSizeEquals(*other));
400 other->SetBorderRightWidth(1.0);
401 EXPECT_TRUE(style->BorderSizeEquals(*other));
402
403 EXPECT_TRUE(style->BorderSizeEquals(*other));
404 style->SetBorderBottomWidth(1.0);
405 EXPECT_FALSE(style->BorderSizeEquals(*other));
406 other->SetBorderBottomWidth(1.0);
407 EXPECT_TRUE(style->BorderSizeEquals(*other));
408
409 style->SetBorderLeftStyle(EBorderStyle::kHidden);
410 EXPECT_FALSE(style->BorderSizeEquals(*other));
411 style->SetBorderLeftStyle(EBorderStyle::kNone);
412 EXPECT_FALSE(style->BorderSizeEquals(*other));
413 style->SetBorderLeftStyle(EBorderStyle::kSolid);
414 EXPECT_TRUE(style->BorderSizeEquals(*other));
415
416 style->SetBorderTopStyle(EBorderStyle::kHidden);
417 EXPECT_FALSE(style->BorderSizeEquals(*other));
418 style->SetBorderTopStyle(EBorderStyle::kNone);
419 EXPECT_FALSE(style->BorderSizeEquals(*other));
420 style->SetBorderTopStyle(EBorderStyle::kSolid);
421 EXPECT_TRUE(style->BorderSizeEquals(*other));
422
423 style->SetBorderRightStyle(EBorderStyle::kHidden);
424 EXPECT_FALSE(style->BorderSizeEquals(*other));
425 style->SetBorderRightStyle(EBorderStyle::kNone);
426 EXPECT_FALSE(style->BorderSizeEquals(*other));
427 style->SetBorderRightStyle(EBorderStyle::kSolid);
428 EXPECT_TRUE(style->BorderSizeEquals(*other));
429
430 style->SetBorderBottomStyle(EBorderStyle::kHidden);
431 EXPECT_FALSE(style->BorderSizeEquals(*other));
432 style->SetBorderBottomStyle(EBorderStyle::kNone);
433 EXPECT_FALSE(style->BorderSizeEquals(*other));
434 style->SetBorderBottomStyle(EBorderStyle::kSolid);
435 EXPECT_TRUE(style->BorderSizeEquals(*other));
436 }
437
438 #define TEST_ANIMATION_FLAG(flag, inherited) \
439 do { \
440 auto style = ComputedStyle::Create(); \
441 auto other = ComputedStyle::Create(); \
442 EXPECT_FALSE(style->flag()); \
443 EXPECT_FALSE(other->flag()); \
444 style->Set##flag(true); \
445 EXPECT_TRUE(style->flag()); \
446 EXPECT_EQ(ComputedStyle::Difference::inherited, \
447 ComputedStyle::ComputeDifference(style.get(), other.get())); \
448 auto diff = style->VisualInvalidationDiff(*document, *other); \
449 EXPECT_TRUE(diff.HasDifference()); \
450 EXPECT_TRUE(diff.CompositingReasonsChanged()); \
451 } while (false)
452
453 #define TEST_ANIMATION_FLAG_NO_DIFF(flag) \
454 do { \
455 auto style = ComputedStyle::Create(); \
456 auto other = ComputedStyle::Create(); \
457 EXPECT_FALSE(style->flag()); \
458 EXPECT_FALSE(other->flag()); \
459 style->Set##flag(true); \
460 EXPECT_TRUE(style->flag()); \
461 EXPECT_EQ(ComputedStyle::Difference::kEqual, \
462 ComputedStyle::ComputeDifference(style.get(), other.get())); \
463 auto diff = style->VisualInvalidationDiff(*document, *other); \
464 EXPECT_FALSE(diff.HasDifference()); \
465 EXPECT_FALSE(diff.CompositingReasonsChanged()); \
466 } while (false)
467
TEST(ComputedStyleTest,AnimationFlags)468 TEST(ComputedStyleTest, AnimationFlags) {
469 Persistent<Document> document = Document::CreateForTest();
470 TEST_ANIMATION_FLAG(HasCurrentTransformAnimation, kNonInherited);
471 TEST_ANIMATION_FLAG(HasCurrentOpacityAnimation, kNonInherited);
472 TEST_ANIMATION_FLAG(HasCurrentFilterAnimation, kNonInherited);
473 TEST_ANIMATION_FLAG(HasCurrentBackdropFilterAnimation, kNonInherited);
474 TEST_ANIMATION_FLAG(SubtreeWillChangeContents, kInherited);
475 TEST_ANIMATION_FLAG_NO_DIFF(IsRunningTransformAnimationOnCompositor);
476 TEST_ANIMATION_FLAG_NO_DIFF(IsRunningOpacityAnimationOnCompositor);
477 TEST_ANIMATION_FLAG_NO_DIFF(IsRunningFilterAnimationOnCompositor);
478 TEST_ANIMATION_FLAG_NO_DIFF(IsRunningBackdropFilterAnimationOnCompositor);
479 }
480
TEST(ComputedStyleTest,CustomPropertiesEqual_Values)481 TEST(ComputedStyleTest, CustomPropertiesEqual_Values) {
482 auto dummy = std::make_unique<DummyPageHolder>(IntSize(0, 0));
483 css_test_helpers::RegisterProperty(dummy->GetDocument(), "--x", "<length>",
484 "0px", false);
485
486 scoped_refptr<ComputedStyle> style1 = ComputedStyle::Create();
487 scoped_refptr<ComputedStyle> style2 = ComputedStyle::Create();
488
489 using UnitType = CSSPrimitiveValue::UnitType;
490
491 const auto* value1 = CSSNumericLiteralValue::Create(1.0, UnitType::kPixels);
492 const auto* value2 = CSSNumericLiteralValue::Create(2.0, UnitType::kPixels);
493 const auto* value3 = CSSNumericLiteralValue::Create(1.0, UnitType::kPixels);
494
495 Vector<AtomicString> properties;
496 properties.push_back("--x");
497
498 style1->SetVariableValue("--x", value1, false);
499 style2->SetVariableValue("--x", value1, false);
500 EXPECT_TRUE(style1->CustomPropertiesEqual(properties, *style2));
501
502 style1->SetVariableValue("--x", value1, false);
503 style2->SetVariableValue("--x", value3, false);
504 EXPECT_TRUE(style1->CustomPropertiesEqual(properties, *style2));
505
506 style1->SetVariableValue("--x", value1, false);
507 style2->SetVariableValue("--x", value2, false);
508 EXPECT_FALSE(style1->CustomPropertiesEqual(properties, *style2));
509 }
510
TEST(ComputedStyleTest,CustomPropertiesEqual_Data)511 TEST(ComputedStyleTest, CustomPropertiesEqual_Data) {
512 auto dummy = std::make_unique<DummyPageHolder>(IntSize(0, 0));
513 css_test_helpers::RegisterProperty(dummy->GetDocument(), "--x", "<length>",
514 "0px", false);
515
516 scoped_refptr<ComputedStyle> style1 = ComputedStyle::Create();
517 scoped_refptr<ComputedStyle> style2 = ComputedStyle::Create();
518
519 auto value1 = css_test_helpers::CreateVariableData("foo");
520 auto value2 = css_test_helpers::CreateVariableData("bar");
521 auto value3 = css_test_helpers::CreateVariableData("foo");
522
523 Vector<AtomicString> properties;
524 properties.push_back("--x");
525
526 style1->SetVariableData("--x", value1, false);
527 style2->SetVariableData("--x", value1, false);
528 EXPECT_TRUE(style1->CustomPropertiesEqual(properties, *style2));
529
530 style1->SetVariableData("--x", value1, false);
531 style2->SetVariableData("--x", value3, false);
532 EXPECT_TRUE(style1->CustomPropertiesEqual(properties, *style2));
533
534 style1->SetVariableData("--x", value1, false);
535 style2->SetVariableData("--x", value2, false);
536 EXPECT_FALSE(style1->CustomPropertiesEqual(properties, *style2));
537 }
538
TEST(ComputedStyleTest,CustomPropertiesInheritance_FastPath)539 TEST(ComputedStyleTest, CustomPropertiesInheritance_FastPath) {
540 auto dummy = std::make_unique<DummyPageHolder>(IntSize(0, 0));
541 css_test_helpers::RegisterProperty(dummy->GetDocument(), "--x", "<length>",
542 "0px", true);
543
544 scoped_refptr<ComputedStyle> old_style = ComputedStyle::Create();
545 scoped_refptr<ComputedStyle> new_style = ComputedStyle::Create();
546
547 using UnitType = CSSPrimitiveValue::UnitType;
548
549 const auto* value1 = CSSNumericLiteralValue::Create(1.0, UnitType::kPixels);
550 const auto* value2 = CSSNumericLiteralValue::Create(2.0, UnitType::kPixels);
551
552 EXPECT_FALSE(old_style->HasVariableDeclaration());
553 EXPECT_FALSE(old_style->HasVariableReference());
554 EXPECT_FALSE(new_style->HasVariableReference());
555 EXPECT_FALSE(new_style->HasVariableDeclaration());
556
557 // Removed variable
558 old_style->SetVariableValue("--x", value1, true);
559 EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
560 ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
561
562 old_style = ComputedStyle::Create();
563 new_style = ComputedStyle::Create();
564
565 // Added a new variable
566 new_style->SetVariableValue("--x", value2, true);
567 EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
568 ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
569
570 // Change value of variable
571 old_style->SetVariableValue("--x", value1, true);
572 new_style->SetVariableValue("--x", value2, true);
573 new_style->SetHasVariableReference();
574 EXPECT_FALSE(new_style->HasVariableDeclaration());
575 EXPECT_TRUE(new_style->HasVariableReference());
576 EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
577 ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
578
579 old_style = ComputedStyle::Create();
580 new_style = ComputedStyle::Create();
581
582 // New styles with variable declaration don't force style recalc
583 old_style->SetVariableValue("--x", value1, true);
584 new_style->SetVariableValue("--x", value2, true);
585 new_style->SetHasVariableDeclaration();
586 EXPECT_TRUE(new_style->HasVariableDeclaration());
587 EXPECT_FALSE(new_style->HasVariableReference());
588 EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
589 ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
590
591 old_style = ComputedStyle::Create();
592 new_style = ComputedStyle::Create();
593
594 // New styles with variable reference don't force style recalc
595 old_style->SetVariableValue("--x", value1, true);
596 new_style->SetVariableValue("--x", value2, true);
597 new_style->SetHasVariableDeclaration();
598 new_style->SetHasVariableReference();
599 EXPECT_TRUE(new_style->HasVariableDeclaration());
600 EXPECT_TRUE(new_style->HasVariableReference());
601 EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
602 ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
603 }
604
TEST(ComputedStyleTest,CustomPropertiesInheritance_StyleRecalc)605 TEST(ComputedStyleTest, CustomPropertiesInheritance_StyleRecalc) {
606 auto dummy = std::make_unique<DummyPageHolder>(IntSize(0, 0));
607 css_test_helpers::RegisterProperty(dummy->GetDocument(), "--x", "<length>",
608 "0px", true);
609
610 scoped_refptr<ComputedStyle> old_style = ComputedStyle::Create();
611 scoped_refptr<ComputedStyle> new_style = ComputedStyle::Create();
612
613 using UnitType = CSSPrimitiveValue::UnitType;
614
615 const auto* value1 = CSSNumericLiteralValue::Create(1.0, UnitType::kPixels);
616 const auto* value2 = CSSNumericLiteralValue::Create(2.0, UnitType::kPixels);
617
618 EXPECT_FALSE(old_style->HasVariableDeclaration());
619 EXPECT_FALSE(old_style->HasVariableReference());
620 EXPECT_FALSE(new_style->HasVariableReference());
621 EXPECT_FALSE(new_style->HasVariableDeclaration());
622
623 // Removed variable value
624 // Old styles with variable reference force style recalc
625 old_style->SetHasVariableReference();
626 old_style->SetVariableValue("--x", value2, true);
627 EXPECT_TRUE(old_style->HasVariableReference());
628 EXPECT_EQ(ComputedStyle::Difference::kInherited,
629 ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
630
631 old_style = ComputedStyle::Create();
632 new_style = ComputedStyle::Create();
633
634 // New variable value
635 // Old styles with variable declaration force style recalc
636 old_style->SetHasVariableDeclaration();
637 new_style->SetVariableValue("--x", value2, true);
638 EXPECT_TRUE(old_style->HasVariableDeclaration());
639 EXPECT_EQ(ComputedStyle::Difference::kInherited,
640 ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
641
642 old_style = ComputedStyle::Create();
643 new_style = ComputedStyle::Create();
644
645 // Change variable value
646 // Old styles with variable declaration force style recalc
647 old_style->SetVariableValue("--x", value1, true);
648 new_style->SetVariableValue("--x", value2, true);
649 old_style->SetHasVariableDeclaration();
650 EXPECT_TRUE(old_style->HasVariableDeclaration());
651 EXPECT_EQ(ComputedStyle::Difference::kInherited,
652 ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
653
654 old_style = ComputedStyle::Create();
655 new_style = ComputedStyle::Create();
656
657 // Change variable value
658 // Old styles with variable reference force style recalc
659 old_style->SetVariableValue("--x", value1, true);
660 new_style->SetVariableValue("--x", value2, true);
661 old_style->SetHasVariableReference();
662 EXPECT_TRUE(old_style->HasVariableReference());
663 EXPECT_EQ(ComputedStyle::Difference::kInherited,
664 ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
665 }
666
TEST(ComputedStyleTest,ApplyColorSchemeLightOnDark)667 TEST(ComputedStyleTest, ApplyColorSchemeLightOnDark) {
668 ScopedCSSColorSchemeUARenderingForTest scoped_ua_enabled(true);
669
670 std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
671 std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
672 const ComputedStyle* initial = &ComputedStyle::InitialStyle();
673
674 ColorSchemeHelper color_scheme_helper(dummy_page_holder_->GetDocument());
675 color_scheme_helper.SetPreferredColorScheme(
676 mojom::blink::PreferredColorScheme::kDark);
677 StyleResolverState state(dummy_page_holder_->GetDocument(),
678 *dummy_page_holder_->GetDocument().documentElement(),
679 initial, initial);
680
681 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
682 state.SetStyle(style);
683
684 CSSPropertyRef ref("color-scheme", state.GetDocument());
685
686 CSSValueList* dark_value = CSSValueList::CreateSpaceSeparated();
687 dark_value->Append(*CSSIdentifierValue::Create(CSSValueID::kDark));
688
689 CSSValueList* light_value = CSSValueList::CreateSpaceSeparated();
690 light_value->Append(*CSSIdentifierValue::Create(CSSValueID::kLight));
691
692 To<Longhand>(ref.GetProperty()).ApplyValue(state, *dark_value);
693 EXPECT_EQ(mojom::blink::ColorScheme::kDark, style->UsedColorScheme());
694
695 To<Longhand>(ref.GetProperty()).ApplyValue(state, *light_value);
696 EXPECT_EQ(mojom::blink::ColorScheme::kLight, style->UsedColorScheme());
697 }
698
TEST(ComputedStyleTest,ApplyInternalLightDarkColor)699 TEST(ComputedStyleTest, ApplyInternalLightDarkColor) {
700 using css_test_helpers::ParseDeclarationBlock;
701
702 ScopedCSSColorSchemeUARenderingForTest scoped_ua_enabled(true);
703
704 std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
705 std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
706 const ComputedStyle* initial = &ComputedStyle::InitialStyle();
707
708 ColorSchemeHelper color_scheme_helper(dummy_page_holder_->GetDocument());
709 color_scheme_helper.SetPreferredColorScheme(
710 mojom::blink::PreferredColorScheme::kDark);
711 StyleResolverState state(dummy_page_holder_->GetDocument(),
712 *dummy_page_holder_->GetDocument().documentElement(),
713 initial, initial);
714
715 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
716 state.SetStyle(style);
717
718 CSSValueList* dark_value = CSSValueList::CreateSpaceSeparated();
719 dark_value->Append(*CSSIdentifierValue::Create(CSSValueID::kDark));
720
721 CSSValueList* light_value = CSSValueList::CreateSpaceSeparated();
722 light_value->Append(*CSSIdentifierValue::Create(CSSValueID::kLight));
723
724 auto* color_declaration = ParseDeclarationBlock(
725 "color:-internal-light-dark(black, white)", CSSParserMode::kUASheetMode);
726 auto* dark_declaration = ParseDeclarationBlock("color-scheme:dark");
727 auto* light_declaration = ParseDeclarationBlock("color-scheme:light");
728
729 StyleCascade cascade1(state);
730 cascade1.MutableMatchResult().AddMatchedProperties(color_declaration);
731 cascade1.MutableMatchResult().AddMatchedProperties(dark_declaration);
732 cascade1.Apply();
733 EXPECT_EQ(Color::kWhite, style->VisitedDependentColor(GetCSSPropertyColor()));
734
735 StyleCascade cascade2(state);
736 cascade2.MutableMatchResult().AddMatchedProperties(color_declaration);
737 cascade2.MutableMatchResult().AddMatchedProperties(light_declaration);
738 cascade2.Apply();
739 EXPECT_EQ(Color::kBlack, style->VisitedDependentColor(GetCSSPropertyColor()));
740 }
741
TEST(ComputedStyleTest,ApplyInternalLightDarkBackgroundImage)742 TEST(ComputedStyleTest, ApplyInternalLightDarkBackgroundImage) {
743 using css_test_helpers::ParseDeclarationBlock;
744
745 ScopedCSSColorSchemeUARenderingForTest scoped_ua_enabled(true);
746
747 std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
748 std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
749 const ComputedStyle* initial = &ComputedStyle::InitialStyle();
750
751 ColorSchemeHelper color_scheme_helper(dummy_page_holder_->GetDocument());
752 color_scheme_helper.SetPreferredColorScheme(
753 mojom::blink::PreferredColorScheme::kDark);
754 StyleResolverState state(dummy_page_holder_->GetDocument(),
755 *dummy_page_holder_->GetDocument().documentElement(),
756 initial, initial);
757
758 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
759 state.SetStyle(style);
760
761 auto* bgimage_declaration = ParseDeclarationBlock(
762 "background-image:-internal-light-dark(none, url(dummy.png))",
763 kUASheetMode);
764 auto* dark_declaration = ParseDeclarationBlock("color-scheme:dark");
765 auto* light_declaration = ParseDeclarationBlock("color-scheme:light");
766
767 EXPECT_FALSE(style->HasNonInheritedLightDarkValue());
768
769 StyleCascade cascade1(state);
770 cascade1.MutableMatchResult().AddMatchedProperties(bgimage_declaration);
771 cascade1.MutableMatchResult().AddMatchedProperties(dark_declaration);
772 cascade1.Apply();
773 EXPECT_TRUE(style->HasBackgroundImage());
774 EXPECT_TRUE(style->HasNonInheritedLightDarkValue());
775
776 style = ComputedStyle::Create();
777 state.SetStyle(style);
778
779 StyleCascade cascade2(state);
780 cascade2.MutableMatchResult().AddMatchedProperties(bgimage_declaration);
781 cascade2.MutableMatchResult().AddMatchedProperties(light_declaration);
782 cascade2.Apply();
783 EXPECT_FALSE(style->HasBackgroundImage());
784 EXPECT_TRUE(style->HasNonInheritedLightDarkValue());
785 }
786
TEST(ComputedStyleTest,StrokeWidthZoomAndCalc)787 TEST(ComputedStyleTest, StrokeWidthZoomAndCalc) {
788 std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
789 std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
790
791 const ComputedStyle* initial = &ComputedStyle::InitialStyle();
792
793 StyleResolverState state(dummy_page_holder_->GetDocument(),
794 *dummy_page_holder_->GetDocument().documentElement(),
795 initial, initial);
796
797 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
798 style->SetEffectiveZoom(1.5);
799 state.SetStyle(style);
800
801 auto* calc_value =
802 CSSMathFunctionValue::Create(CSSMathExpressionNumericLiteral::Create(
803 CSSNumericLiteralValue::Create(10,
804 CSSPrimitiveValue::UnitType::kNumber),
805 true));
806
807 To<Longhand>(GetCSSPropertyStrokeWidth()).ApplyValue(state, *calc_value);
808 auto* computed_value =
809 To<Longhand>(GetCSSPropertyStrokeWidth())
810 .CSSValueFromComputedStyleInternal(*style, style->SvgStyle(),
811 nullptr /* layout_object */,
812 false /* allow_visited_style */);
813 ASSERT_TRUE(computed_value);
814 auto* numeric_value = DynamicTo<CSSNumericLiteralValue>(computed_value);
815 ASSERT_TRUE(numeric_value);
816 EXPECT_TRUE(numeric_value->IsPx());
817 EXPECT_EQ(10, numeric_value->DoubleValue());
818 }
819
TEST(ComputedStyleTest,InitialVariableNamesEmpty)820 TEST(ComputedStyleTest, InitialVariableNamesEmpty) {
821 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
822 EXPECT_TRUE(style->GetVariableNames().IsEmpty());
823 }
824
TEST(ComputedStyleTest,InitialVariableNames)825 TEST(ComputedStyleTest, InitialVariableNames) {
826 using css_test_helpers::CreateLengthRegistration;
827
828 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
829
830 PropertyRegistry* registry = MakeGarbageCollected<PropertyRegistry>();
831 registry->RegisterProperty("--x", *CreateLengthRegistration("--x", 1));
832 registry->RegisterProperty("--y", *CreateLengthRegistration("--y", 2));
833 style->SetInitialData(StyleInitialData::Create(*registry));
834
835 EXPECT_EQ(2u, style->GetVariableNames().size());
836 EXPECT_TRUE(style->GetVariableNames().Contains("--x"));
837 EXPECT_TRUE(style->GetVariableNames().Contains("--y"));
838 }
839
TEST(ComputedStyleTest,InheritedVariableNames)840 TEST(ComputedStyleTest, InheritedVariableNames) {
841 using css_test_helpers::CreateVariableData;
842
843 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
844
845 const bool inherited = true;
846 style->SetVariableData("--a", CreateVariableData("foo"), inherited);
847 style->SetVariableData("--b", CreateVariableData("bar"), inherited);
848
849 EXPECT_EQ(2u, style->GetVariableNames().size());
850 EXPECT_TRUE(style->GetVariableNames().Contains("--a"));
851 EXPECT_TRUE(style->GetVariableNames().Contains("--b"));
852 }
853
TEST(ComputedStyleTest,NonInheritedVariableNames)854 TEST(ComputedStyleTest, NonInheritedVariableNames) {
855 using css_test_helpers::CreateVariableData;
856
857 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
858
859 const bool inherited = true;
860 style->SetVariableData("--a", CreateVariableData("foo"), !inherited);
861 style->SetVariableData("--b", CreateVariableData("bar"), !inherited);
862
863 EXPECT_EQ(2u, style->GetVariableNames().size());
864 EXPECT_TRUE(style->GetVariableNames().Contains("--a"));
865 EXPECT_TRUE(style->GetVariableNames().Contains("--b"));
866 }
867
TEST(ComputedStyleTest,InheritedAndNonInheritedVariableNames)868 TEST(ComputedStyleTest, InheritedAndNonInheritedVariableNames) {
869 using css_test_helpers::CreateVariableData;
870
871 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
872
873 const bool inherited = true;
874 style->SetVariableData("--a", CreateVariableData("foo"), inherited);
875 style->SetVariableData("--b", CreateVariableData("bar"), inherited);
876 style->SetVariableData("--d", CreateVariableData("foz"), !inherited);
877 style->SetVariableData("--c", CreateVariableData("baz"), !inherited);
878
879 EXPECT_EQ(4u, style->GetVariableNames().size());
880 EXPECT_TRUE(style->GetVariableNames().Contains("--a"));
881 EXPECT_TRUE(style->GetVariableNames().Contains("--b"));
882 EXPECT_TRUE(style->GetVariableNames().Contains("--c"));
883 EXPECT_TRUE(style->GetVariableNames().Contains("--d"));
884 }
885
TEST(ComputedStyleTest,InitialAndInheritedAndNonInheritedVariableNames)886 TEST(ComputedStyleTest, InitialAndInheritedAndNonInheritedVariableNames) {
887 using css_test_helpers::CreateLengthRegistration;
888 using css_test_helpers::CreateVariableData;
889
890 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
891
892 PropertyRegistry* registry = MakeGarbageCollected<PropertyRegistry>();
893 registry->RegisterProperty("--b", *CreateLengthRegistration("--b", 1));
894 registry->RegisterProperty("--e", *CreateLengthRegistration("--e", 2));
895 style->SetInitialData(StyleInitialData::Create(*registry));
896
897 const bool inherited = true;
898 style->SetVariableData("--a", CreateVariableData("foo"), inherited);
899 style->SetVariableData("--b", CreateVariableData("bar"), inherited);
900 style->SetVariableData("--d", CreateVariableData("foz"), !inherited);
901 style->SetVariableData("--c", CreateVariableData("baz"), !inherited);
902
903 EXPECT_EQ(5u, style->GetVariableNames().size());
904 EXPECT_TRUE(style->GetVariableNames().Contains("--a"));
905 EXPECT_TRUE(style->GetVariableNames().Contains("--b"));
906 EXPECT_TRUE(style->GetVariableNames().Contains("--c"));
907 EXPECT_TRUE(style->GetVariableNames().Contains("--d"));
908 EXPECT_TRUE(style->GetVariableNames().Contains("--e"));
909 }
910
TEST(ComputedStyleTest,BorderWidthZoom)911 TEST(ComputedStyleTest, BorderWidthZoom) {
912 std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
913 std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
914
915 const ComputedStyle* initial = &ComputedStyle::InitialStyle();
916
917 StyleResolverState state(dummy_page_holder_->GetDocument(),
918 *dummy_page_holder_->GetDocument().documentElement(),
919 initial, initial);
920
921 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
922 style->SetEffectiveZoom(2);
923 style->SetBorderLeftStyle(EBorderStyle::kSolid);
924 style->SetOutlineStyle(EBorderStyle::kSolid);
925 style->SetColumnRuleStyle(EBorderStyle::kSolid);
926 state.SetStyle(style);
927
928 const struct {
929 CSSIdentifierValue* css_value;
930 double expected_px;
931 STACK_ALLOCATED();
932 } tests[] = {
933 {CSSIdentifierValue::Create(CSSValueID::kThin), 1.0},
934 {CSSIdentifierValue::Create(CSSValueID::kMedium), 3.0},
935 {CSSIdentifierValue::Create(CSSValueID::kThick), 5.0},
936 };
937
938 for (const auto& test : tests) {
939 for (const auto* property :
940 {&GetCSSPropertyBorderLeftWidth(), &GetCSSPropertyOutlineWidth(),
941 &GetCSSPropertyColumnRuleWidth()}) {
942 const Longhand& longhand = To<Longhand>(*property);
943 longhand.ApplyValue(state, *test.css_value);
944 auto* computed_value = longhand.CSSValueFromComputedStyleInternal(
945 *style, style->SvgStyle(), nullptr /* layout_object */,
946 false /* allow_visited_style */);
947 AtomicString prop_name = longhand.GetCSSPropertyName().ToAtomicString();
948 ASSERT_TRUE(computed_value) << prop_name;
949 auto* numeric_value = DynamicTo<CSSNumericLiteralValue>(computed_value);
950 ASSERT_TRUE(numeric_value) << prop_name;
951 EXPECT_TRUE(numeric_value->IsPx()) << prop_name;
952 EXPECT_EQ(test.expected_px, numeric_value->DoubleValue()) << prop_name;
953 }
954 }
955 }
956
TEST(ComputedStyleTest,TextDecorationEqualDoesNotRequireRecomputeInkOverflow)957 TEST(ComputedStyleTest, TextDecorationEqualDoesNotRequireRecomputeInkOverflow) {
958 using css_test_helpers::ParseDeclarationBlock;
959
960 std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
961 std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
962 const ComputedStyle* initial = &ComputedStyle::InitialStyle();
963
964 StyleResolverState state(dummy_page_holder_->GetDocument(),
965 *dummy_page_holder_->GetDocument().documentElement(),
966 initial, initial);
967
968 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
969
970 // Set up the initial text decoration properties
971 style->SetTextDecorationStyle(ETextDecorationStyle::kSolid);
972 style->SetTextDecorationColor(StyleColor(CSSValueID::kGreen));
973 style->SetTextDecoration(TextDecoration::kUnderline);
974 style->SetTextDecorationThickness(
975 TextDecorationThickness(Length(5, Length::Type::kFixed)));
976 style->SetTextUnderlineOffset(Length(2, Length::Type::kFixed));
977 style->SetTextUnderlinePosition(kTextUnderlinePositionUnder);
978 state.SetStyle(style);
979 StyleAdjuster::AdjustComputedStyle(state, nullptr /* element */);
980 EXPECT_EQ(TextDecoration::kUnderline, style->TextDecorationsInEffect());
981
982 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
983 StyleDifference diff1;
984 style->UpdatePropertySpecificDifferences(*other, diff1);
985 EXPECT_FALSE(diff1.NeedsRecomputeVisualOverflow());
986
987 // Change the color, and it should not invalidate
988 other->SetTextDecorationColor(StyleColor(CSSValueID::kBlue));
989 state.SetStyle(other);
990 StyleAdjuster::AdjustComputedStyle(state, nullptr /* element */);
991 StyleDifference diff2;
992 style->UpdatePropertySpecificDifferences(*other, diff2);
993 EXPECT_FALSE(diff2.NeedsRecomputeVisualOverflow());
994 }
995
TEST(ComputedStyleTest,TextDecorationNotEqualRequiresRecomputeInkOverflow)996 TEST(ComputedStyleTest, TextDecorationNotEqualRequiresRecomputeInkOverflow) {
997 using css_test_helpers::ParseDeclarationBlock;
998
999 std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
1000 std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
1001 const ComputedStyle* initial = &ComputedStyle::InitialStyle();
1002
1003 StyleResolverState state(dummy_page_holder_->GetDocument(),
1004 *dummy_page_holder_->GetDocument().documentElement(),
1005 initial, initial);
1006
1007 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
1008
1009 // Set up the initial text decoration properties
1010 style->SetTextDecorationStyle(ETextDecorationStyle::kSolid);
1011 style->SetTextDecorationColor(StyleColor(CSSValueID::kGreen));
1012 style->SetTextDecoration(TextDecoration::kUnderline);
1013 style->SetTextDecorationThickness(
1014 TextDecorationThickness(Length(5, Length::Type::kFixed)));
1015 style->SetTextUnderlineOffset(Length(2, Length::Type::kFixed));
1016 style->SetTextUnderlinePosition(kTextUnderlinePositionUnder);
1017 state.SetStyle(style);
1018 StyleAdjuster::AdjustComputedStyle(state, nullptr /* element */);
1019
1020 // Change decoration style
1021 scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
1022 other->SetTextDecorationStyle(ETextDecorationStyle::kWavy);
1023 state.SetStyle(other);
1024 StyleAdjuster::AdjustComputedStyle(state, nullptr /* element */);
1025 StyleDifference diff_decoration_style;
1026 style->UpdatePropertySpecificDifferences(*other, diff_decoration_style);
1027 EXPECT_TRUE(diff_decoration_style.NeedsRecomputeVisualOverflow());
1028
1029 // Change decoration line
1030 other = ComputedStyle::Clone(*style);
1031 other->SetTextDecoration(TextDecoration::kOverline);
1032 state.SetStyle(other);
1033 StyleAdjuster::AdjustComputedStyle(state, nullptr /* element */);
1034 StyleDifference diff_decoration_line;
1035 style->UpdatePropertySpecificDifferences(*other, diff_decoration_line);
1036 EXPECT_TRUE(diff_decoration_line.NeedsRecomputeVisualOverflow());
1037
1038 // Change decoration thickness
1039 other = ComputedStyle::Clone(*style);
1040 other->SetTextDecorationThickness(
1041 TextDecorationThickness(Length(3, Length::Type::kFixed)));
1042 state.SetStyle(other);
1043 StyleAdjuster::AdjustComputedStyle(state, nullptr /* element */);
1044 StyleDifference diff_decoration_thickness;
1045 style->UpdatePropertySpecificDifferences(*other, diff_decoration_thickness);
1046 EXPECT_TRUE(diff_decoration_thickness.NeedsRecomputeVisualOverflow());
1047
1048 // Change underline offset
1049 other = ComputedStyle::Clone(*style);
1050 other->SetTextUnderlineOffset(Length(4, Length::Type::kFixed));
1051 state.SetStyle(other);
1052 StyleAdjuster::AdjustComputedStyle(state, nullptr /* element */);
1053 StyleDifference diff_underline_offset;
1054 style->UpdatePropertySpecificDifferences(*other, diff_underline_offset);
1055 EXPECT_TRUE(diff_underline_offset.NeedsRecomputeVisualOverflow());
1056
1057 // Change underline position
1058 other = ComputedStyle::Clone(*style);
1059 other->SetTextUnderlinePosition(kTextUnderlinePositionLeft);
1060 state.SetStyle(other);
1061 StyleAdjuster::AdjustComputedStyle(state, nullptr /* element */);
1062 StyleDifference diff_underline_position;
1063 style->UpdatePropertySpecificDifferences(*other, diff_underline_position);
1064 EXPECT_TRUE(diff_underline_position.NeedsRecomputeVisualOverflow());
1065 }
1066
1067 // Verify that cloned ComputedStyle is independent from source, i.e.
1068 // copy-on-write works as expected.
TEST(ComputedStyleTest,ClonedStyleAnimationsAreIndependent)1069 TEST(ComputedStyleTest, ClonedStyleAnimationsAreIndependent) {
1070 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
1071
1072 auto& animations = style->AccessAnimations();
1073 animations.DelayList().clear();
1074 animations.DelayList().push_back(CSSAnimationData::InitialDelay());
1075 EXPECT_EQ(1u, style->Animations()->DelayList().size());
1076
1077 scoped_refptr<ComputedStyle> cloned_style = ComputedStyle::Clone(*style);
1078 auto& cloned_style_animations = cloned_style->AccessAnimations();
1079 EXPECT_EQ(1u, cloned_style_animations.DelayList().size());
1080 cloned_style_animations.DelayList().push_back(
1081 CSSAnimationData::InitialDelay());
1082
1083 EXPECT_EQ(2u, cloned_style->Animations()->DelayList().size());
1084 EXPECT_EQ(1u, style->Animations()->DelayList().size());
1085 }
1086
TEST(ComputedStyleTest,ClonedStyleTransitionsAreIndependent)1087 TEST(ComputedStyleTest, ClonedStyleTransitionsAreIndependent) {
1088 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
1089
1090 auto& transitions = style->AccessTransitions();
1091 transitions.PropertyList().clear();
1092 transitions.PropertyList().push_back(CSSTransitionData::InitialProperty());
1093 EXPECT_EQ(1u, style->Transitions()->PropertyList().size());
1094
1095 scoped_refptr<ComputedStyle> cloned_style = ComputedStyle::Clone(*style);
1096 auto& cloned_style_transitions = cloned_style->AccessTransitions();
1097 EXPECT_EQ(1u, cloned_style_transitions.PropertyList().size());
1098 cloned_style_transitions.PropertyList().push_back(
1099 CSSTransitionData::InitialProperty());
1100
1101 EXPECT_EQ(2u, cloned_style->Transitions()->PropertyList().size());
1102 EXPECT_EQ(1u, style->Transitions()->PropertyList().size());
1103 }
1104
TEST(ComputedStyleTest,ApplyInitialAnimationNameAndTransitionProperty)1105 TEST(ComputedStyleTest, ApplyInitialAnimationNameAndTransitionProperty) {
1106 std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
1107 std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
1108
1109 const ComputedStyle* initial = &ComputedStyle::InitialStyle();
1110 StyleResolverState state(dummy_page_holder_->GetDocument(),
1111 *dummy_page_holder_->GetDocument().documentElement(),
1112 initial, initial);
1113
1114 scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
1115 state.SetStyle(style);
1116 EXPECT_FALSE(style->Animations());
1117 EXPECT_FALSE(style->Transitions());
1118
1119 To<Longhand>(GetCSSPropertyAnimationName()).ApplyInitial(state);
1120 To<Longhand>(GetCSSPropertyTransitionProperty()).ApplyInitial(state);
1121 EXPECT_FALSE(style->Animations());
1122 EXPECT_FALSE(style->Transitions());
1123 }
1124
1125 } // namespace blink
1126