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 "third_party/blink/renderer/core/css/css_property_names.h"
8 #include "third_party/blink/renderer/core/frame/settings.h"
9 #include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h"
10 #include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
11 #include "third_party/blink/renderer/core/layout/layout_object.h"
12 #include "third_party/blink/renderer/core/layout/layout_text_combine.h"
13 #include "third_party/blink/renderer/core/paint/applied_decoration_painter.h"
14 #include "third_party/blink/renderer/core/paint/box_painter.h"
15 #include "third_party/blink/renderer/core/paint/highlight_painting_utils.h"
16 #include "third_party/blink/renderer/core/paint/paint_info.h"
17 #include "third_party/blink/renderer/core/style/computed_style.h"
18 #include "third_party/blink/renderer/core/style/shadow_list.h"
19 #include "third_party/blink/renderer/platform/fonts/font.h"
20 #include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
21 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
22 #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
23 #include "third_party/blink/renderer/platform/text/text_run.h"
24 #include "third_party/blink/renderer/platform/wtf/assertions.h"
25 #include "third_party/blink/renderer/platform/wtf/text/character_names.h"
26 
27 namespace blink {
28 
Paint(unsigned start_offset,unsigned end_offset,unsigned length,const TextPaintStyle & text_style,DOMNodeId node_id)29 void TextPainter::Paint(unsigned start_offset,
30                         unsigned end_offset,
31                         unsigned length,
32                         const TextPaintStyle& text_style,
33                         DOMNodeId node_id) {
34   GraphicsContextStateSaver state_saver(graphics_context_, false);
35   UpdateGraphicsContext(text_style, state_saver);
36   if (combined_text_) {
37     graphics_context_.Save();
38     combined_text_->TransformToInlineCoordinates(graphics_context_,
39                                                  text_frame_rect_);
40     PaintInternal<kPaintText>(start_offset, end_offset, length, node_id);
41     graphics_context_.Restore();
42   } else {
43     PaintInternal<kPaintText>(start_offset, end_offset, length, node_id);
44   }
45 
46   if (!emphasis_mark_.IsEmpty()) {
47     if (text_style.emphasis_mark_color != text_style.fill_color)
48       graphics_context_.SetFillColor(text_style.emphasis_mark_color);
49 
50     if (combined_text_) {
51       PaintEmphasisMarkForCombinedText();
52     } else {
53       PaintInternal<kPaintEmphasisMark>(start_offset, end_offset, length,
54                                         node_id);
55     }
56   }
57 }
58 
59 template <TextPainter::PaintInternalStep step>
PaintInternalRun(TextRunPaintInfo & text_run_paint_info,unsigned from,unsigned to,DOMNodeId node_id)60 void TextPainter::PaintInternalRun(TextRunPaintInfo& text_run_paint_info,
61                                    unsigned from,
62                                    unsigned to,
63                                    DOMNodeId node_id) {
64   DCHECK(from <= text_run_paint_info.run.length());
65   DCHECK(to <= text_run_paint_info.run.length());
66 
67   text_run_paint_info.from = from;
68   text_run_paint_info.to = to;
69 
70   if (step == kPaintEmphasisMark) {
71     graphics_context_.DrawEmphasisMarks(
72         font_, text_run_paint_info, emphasis_mark_,
73         FloatPoint(text_origin_) + IntSize(0, emphasis_mark_offset_));
74   } else {
75     DCHECK(step == kPaintText);
76     graphics_context_.DrawText(font_, text_run_paint_info,
77                                FloatPoint(text_origin_), node_id);
78   }
79 }
80 
81 template <TextPainter::PaintInternalStep Step>
PaintInternal(unsigned start_offset,unsigned end_offset,unsigned truncation_point,DOMNodeId node_id)82 void TextPainter::PaintInternal(unsigned start_offset,
83                                 unsigned end_offset,
84                                 unsigned truncation_point,
85                                 DOMNodeId node_id) {
86   TextRunPaintInfo text_run_paint_info(run_);
87   if (start_offset <= end_offset) {
88     PaintInternalRun<Step>(text_run_paint_info, start_offset, end_offset,
89                            node_id);
90   } else {
91     if (end_offset > 0) {
92       PaintInternalRun<Step>(text_run_paint_info, ellipsis_offset_, end_offset,
93                              node_id);
94     }
95     if (start_offset < truncation_point) {
96       PaintInternalRun<Step>(text_run_paint_info, start_offset,
97                              truncation_point, node_id);
98     }
99   }
100 }
101 
ClipDecorationsStripe(float upper,float stripe_width,float dilation)102 void TextPainter::ClipDecorationsStripe(float upper,
103                                         float stripe_width,
104                                         float dilation) {
105   TextRunPaintInfo text_run_paint_info(run_);
106   if (!run_.length())
107     return;
108 
109   Vector<Font::TextIntercept> text_intercepts;
110   font_.GetTextIntercepts(
111       text_run_paint_info, graphics_context_.DeviceScaleFactor(),
112       graphics_context_.FillFlags(),
113       std::make_tuple(upper, upper + stripe_width), text_intercepts);
114 
115   DecorationsStripeIntercepts(upper, stripe_width, dilation, text_intercepts);
116 }
117 
PaintEmphasisMarkForCombinedText()118 void TextPainter::PaintEmphasisMarkForCombinedText() {
119   const SimpleFontData* font_data = font_.PrimaryFont();
120   DCHECK(font_data);
121   if (!font_data)
122     return;
123 
124   DCHECK(combined_text_);
125   TextRun placeholder_text_run(&kIdeographicFullStopCharacter, 1);
126   FloatPoint emphasis_mark_text_origin(
127       text_frame_rect_.X().ToFloat(), text_frame_rect_.Y().ToFloat() +
128                                           font_data->GetFontMetrics().Ascent() +
129                                           emphasis_mark_offset_);
130   TextRunPaintInfo text_run_paint_info(placeholder_text_run);
131   graphics_context_.ConcatCTM(Rotation(text_frame_rect_, kClockwise));
132   graphics_context_.DrawEmphasisMarks(combined_text_->OriginalFont(),
133                                       text_run_paint_info, emphasis_mark_,
134                                       emphasis_mark_text_origin);
135   graphics_context_.ConcatCTM(Rotation(text_frame_rect_, kCounterclockwise));
136 }
137 
138 }  // namespace blink
139