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