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/paint/text_painter.h"
6 
7 #include <memory>
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
10 #include "third_party/blink/renderer/core/css/css_property_names.h"
11 #include "third_party/blink/renderer/core/css_value_keywords.h"
12 #include "third_party/blink/renderer/core/frame/settings.h"
13 #include "third_party/blink/renderer/core/layout/api/line_layout_text.h"
14 #include "third_party/blink/renderer/core/paint/paint_info.h"
15 #include "third_party/blink/renderer/core/style/shadow_data.h"
16 #include "third_party/blink/renderer/core/style/shadow_list.h"
17 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
18 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
19 
20 namespace blink {
21 namespace {
22 
23 class TextPainterTest : public RenderingTest {
24  public:
TextPainterTest()25   TextPainterTest()
26       : layout_text_(nullptr),
27         paint_controller_(std::make_unique<PaintController>()),
28         context_(*paint_controller_) {}
29 
30  protected:
GetLineLayoutText()31   LineLayoutText GetLineLayoutText() { return LineLayoutText(layout_text_); }
32 
CreatePaintInfo(bool uses_text_as_clip,bool is_printing)33   PaintInfo CreatePaintInfo(bool uses_text_as_clip, bool is_printing) {
34     return PaintInfo(
35         context_, IntRect(),
36         uses_text_as_clip ? PaintPhase::kTextClip
37                           : PaintPhase::kSelfBlockBackgroundOnly,
38         is_printing ? kGlobalPaintPrinting : kGlobalPaintNormalPhase, 0);
39   }
40 
41  protected:
SetUp()42   void SetUp() override {
43     RenderingTest::SetUp();
44     SetBodyInnerHTML("Hello world");
45     UpdateLayoutText();
46   }
UpdateLayoutText()47   void UpdateLayoutText() {
48     layout_text_ =
49         ToLayoutText(GetDocument().body()->firstChild()->GetLayoutObject());
50     ASSERT_TRUE(layout_text_);
51     ASSERT_EQ("Hello world", layout_text_->GetText());
52   }
53 
54   LayoutText* layout_text_;
55   std::unique_ptr<PaintController> paint_controller_;
56   GraphicsContext context_;
57 };
58 
TEST_F(TextPainterTest,TextPaintingStyle_Simple)59 TEST_F(TextPainterTest, TextPaintingStyle_Simple) {
60   GetDocument().body()->SetInlineStyleProperty(CSSPropertyID::kColor,
61                                                CSSValueID::kBlue);
62   UpdateAllLifecyclePhasesForTest();
63 
64   TextPaintStyle text_style = TextPainter::TextPaintingStyle(
65       GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
66       CreatePaintInfo(false /* usesTextAsClip */, false /* isPrinting */));
67   EXPECT_EQ(Color(0, 0, 255), text_style.fill_color);
68   EXPECT_EQ(Color(0, 0, 255), text_style.stroke_color);
69   EXPECT_EQ(Color(0, 0, 255), text_style.emphasis_mark_color);
70   EXPECT_EQ(0, text_style.stroke_width);
71   EXPECT_EQ(nullptr, text_style.shadow);
72 }
73 
TEST_F(TextPainterTest,TextPaintingStyle_AllProperties)74 TEST_F(TextPainterTest, TextPaintingStyle_AllProperties) {
75   GetDocument().body()->SetInlineStyleProperty(
76       CSSPropertyID::kWebkitTextFillColor, CSSValueID::kRed);
77   GetDocument().body()->SetInlineStyleProperty(
78       CSSPropertyID::kWebkitTextStrokeColor, CSSValueID::kLime);
79   GetDocument().body()->SetInlineStyleProperty(
80       CSSPropertyID::kWebkitTextEmphasisColor, CSSValueID::kBlue);
81   GetDocument().body()->SetInlineStyleProperty(
82       CSSPropertyID::kWebkitTextStrokeWidth, 4,
83       CSSPrimitiveValue::UnitType::kPixels);
84   GetDocument().body()->SetInlineStyleProperty(CSSPropertyID::kTextShadow,
85                                                "1px 2px 3px yellow");
86   UpdateAllLifecyclePhasesForTest();
87 
88   TextPaintStyle text_style = TextPainter::TextPaintingStyle(
89       GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
90       CreatePaintInfo(false /* usesTextAsClip */, false /* isPrinting */));
91   EXPECT_EQ(Color(255, 0, 0), text_style.fill_color);
92   EXPECT_EQ(Color(0, 255, 0), text_style.stroke_color);
93   EXPECT_EQ(Color(0, 0, 255), text_style.emphasis_mark_color);
94   EXPECT_EQ(4, text_style.stroke_width);
95   ASSERT_NE(nullptr, text_style.shadow);
96   EXPECT_EQ(1u, text_style.shadow->Shadows().size());
97   EXPECT_EQ(1, text_style.shadow->Shadows()[0].X());
98   EXPECT_EQ(2, text_style.shadow->Shadows()[0].Y());
99   EXPECT_EQ(3, text_style.shadow->Shadows()[0].Blur());
100   EXPECT_EQ(Color(255, 255, 0),
101             text_style.shadow->Shadows()[0].GetColor().GetColor());
102 }
103 
TEST_F(TextPainterTest,TextPaintingStyle_UsesTextAsClip)104 TEST_F(TextPainterTest, TextPaintingStyle_UsesTextAsClip) {
105   GetDocument().body()->SetInlineStyleProperty(
106       CSSPropertyID::kWebkitTextFillColor, CSSValueID::kRed);
107   GetDocument().body()->SetInlineStyleProperty(
108       CSSPropertyID::kWebkitTextStrokeColor, CSSValueID::kLime);
109   GetDocument().body()->SetInlineStyleProperty(
110       CSSPropertyID::kWebkitTextEmphasisColor, CSSValueID::kBlue);
111   GetDocument().body()->SetInlineStyleProperty(
112       CSSPropertyID::kWebkitTextStrokeWidth, 4,
113       CSSPrimitiveValue::UnitType::kPixels);
114   GetDocument().body()->SetInlineStyleProperty(CSSPropertyID::kTextShadow,
115                                                "1px 2px 3px yellow");
116   UpdateAllLifecyclePhasesForTest();
117 
118   TextPaintStyle text_style = TextPainter::TextPaintingStyle(
119       GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
120       CreatePaintInfo(true /* usesTextAsClip */, false /* isPrinting */));
121   EXPECT_EQ(Color::kBlack, text_style.fill_color);
122   EXPECT_EQ(Color::kBlack, text_style.stroke_color);
123   EXPECT_EQ(Color::kBlack, text_style.emphasis_mark_color);
124   EXPECT_EQ(4, text_style.stroke_width);
125   EXPECT_EQ(nullptr, text_style.shadow);
126 }
127 
TEST_F(TextPainterTest,TextPaintingStyle_ForceBackgroundToWhite_NoAdjustmentNeeded)128 TEST_F(TextPainterTest,
129        TextPaintingStyle_ForceBackgroundToWhite_NoAdjustmentNeeded) {
130   GetDocument().body()->SetInlineStyleProperty(
131       CSSPropertyID::kWebkitTextFillColor, CSSValueID::kRed);
132   GetDocument().body()->SetInlineStyleProperty(
133       CSSPropertyID::kWebkitTextStrokeColor, CSSValueID::kLime);
134   GetDocument().body()->SetInlineStyleProperty(
135       CSSPropertyID::kWebkitTextEmphasisColor, CSSValueID::kBlue);
136   GetDocument().body()->SetInlineStyleProperty(
137       CSSPropertyID::kWebkitPrintColorAdjust, CSSValueID::kEconomy);
138   GetDocument().GetSettings()->SetShouldPrintBackgrounds(false);
139   FloatSize page_size(500, 800);
140   GetFrame().StartPrinting(page_size, page_size, 1);
141   UpdateAllLifecyclePhasesForTest();
142   // In LayoutNG, printing currently forces layout tree reattachment,
143   // so we need to re-get layout_text_.
144   UpdateLayoutText();
145 
146   TextPaintStyle text_style = TextPainter::TextPaintingStyle(
147       GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
148       CreatePaintInfo(false /* usesTextAsClip */, true /* isPrinting */));
149   EXPECT_EQ(Color(255, 0, 0), text_style.fill_color);
150   EXPECT_EQ(Color(0, 255, 0), text_style.stroke_color);
151   EXPECT_EQ(Color(0, 0, 255), text_style.emphasis_mark_color);
152 }
153 
TEST_F(TextPainterTest,TextPaintingStyle_ForceBackgroundToWhite_Darkened)154 TEST_F(TextPainterTest, TextPaintingStyle_ForceBackgroundToWhite_Darkened) {
155   GetDocument().body()->SetInlineStyleProperty(
156       CSSPropertyID::kWebkitTextFillColor, "rgb(255, 220, 220)");
157   GetDocument().body()->SetInlineStyleProperty(
158       CSSPropertyID::kWebkitTextStrokeColor, "rgb(220, 255, 220)");
159   GetDocument().body()->SetInlineStyleProperty(
160       CSSPropertyID::kWebkitTextEmphasisColor, "rgb(220, 220, 255)");
161   GetDocument().body()->SetInlineStyleProperty(
162       CSSPropertyID::kWebkitPrintColorAdjust, CSSValueID::kEconomy);
163   GetDocument().GetSettings()->SetShouldPrintBackgrounds(false);
164   FloatSize page_size(500, 800);
165   GetFrame().StartPrinting(page_size, page_size, 1);
166   GetDocument().View()->UpdateLifecyclePhasesForPrinting();
167   // In LayoutNG, printing currently forces layout tree reattachment,
168   // so we need to re-get layout_text_.
169   UpdateLayoutText();
170 
171   TextPaintStyle text_style = TextPainter::TextPaintingStyle(
172       GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
173       CreatePaintInfo(false /* usesTextAsClip */, true /* isPrinting */));
174   EXPECT_EQ(Color(255, 220, 220).Dark(), text_style.fill_color);
175   EXPECT_EQ(Color(220, 255, 220).Dark(), text_style.stroke_color);
176   EXPECT_EQ(Color(220, 220, 255).Dark(), text_style.emphasis_mark_color);
177 }
178 
179 }  // namespace
180 }  // namespace blink
181