| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "third_party/blink/renderer/core/paint/text_painter.h" |
| |
| #include "third_party/blink/renderer/core/css/css_property_names.h" |
| #include "third_party/blink/renderer/core/frame/settings.h" |
| #include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h" |
| #include "third_party/blink/renderer/core/layout/api/line_layout_item.h" |
| #include "third_party/blink/renderer/core/layout/layout_object.h" |
| #include "third_party/blink/renderer/core/layout/layout_text_combine.h" |
| #include "third_party/blink/renderer/core/paint/applied_decoration_painter.h" |
| #include "third_party/blink/renderer/core/paint/box_painter.h" |
| #include "third_party/blink/renderer/core/paint/highlight_painting_utils.h" |
| #include "third_party/blink/renderer/core/paint/paint_info.h" |
| #include "third_party/blink/renderer/core/style/computed_style.h" |
| #include "third_party/blink/renderer/core/style/shadow_list.h" |
| #include "third_party/blink/renderer/platform/fonts/font.h" |
| #include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h" |
| #include "third_party/blink/renderer/platform/graphics/graphics_context.h" |
| #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h" |
| #include "third_party/blink/renderer/platform/text/text_run.h" |
| #include "third_party/blink/renderer/platform/wtf/assertions.h" |
| #include "third_party/blink/renderer/platform/wtf/text/character_names.h" |
| |
| namespace blink { |
| |
| void TextPainter::Paint(unsigned start_offset, |
| unsigned end_offset, |
| unsigned length, |
| const TextPaintStyle& text_style, |
| DOMNodeId node_id) { |
| GraphicsContextStateSaver state_saver(graphics_context_, false); |
| UpdateGraphicsContext(text_style, state_saver); |
| if (combined_text_) { |
| graphics_context_.Save(); |
| combined_text_->TransformToInlineCoordinates(graphics_context_, |
| text_frame_rect_); |
| PaintInternal<kPaintText>(start_offset, end_offset, length, node_id); |
| graphics_context_.Restore(); |
| } else { |
| PaintInternal<kPaintText>(start_offset, end_offset, length, node_id); |
| } |
| |
| if (!emphasis_mark_.IsEmpty()) { |
| if (text_style.emphasis_mark_color != text_style.fill_color) |
| graphics_context_.SetFillColor(text_style.emphasis_mark_color); |
| |
| if (combined_text_) { |
| PaintEmphasisMarkForCombinedText(); |
| } else { |
| PaintInternal<kPaintEmphasisMark>(start_offset, end_offset, length, |
| node_id); |
| } |
| } |
| } |
| |
| template <TextPainter::PaintInternalStep step> |
| void TextPainter::PaintInternalRun(TextRunPaintInfo& text_run_paint_info, |
| unsigned from, |
| unsigned to, |
| DOMNodeId node_id) { |
| DCHECK(from <= text_run_paint_info.run.length()); |
| DCHECK(to <= text_run_paint_info.run.length()); |
| |
| text_run_paint_info.from = from; |
| text_run_paint_info.to = to; |
| |
| if (step == kPaintEmphasisMark) { |
| graphics_context_.DrawEmphasisMarks( |
| font_, text_run_paint_info, emphasis_mark_, |
| FloatPoint(text_origin_) + IntSize(0, emphasis_mark_offset_)); |
| } else { |
| DCHECK(step == kPaintText); |
| graphics_context_.DrawText(font_, text_run_paint_info, |
| FloatPoint(text_origin_), node_id); |
| } |
| } |
| |
| template <TextPainter::PaintInternalStep Step> |
| void TextPainter::PaintInternal(unsigned start_offset, |
| unsigned end_offset, |
| unsigned truncation_point, |
| DOMNodeId node_id) { |
| TextRunPaintInfo text_run_paint_info(run_); |
| if (start_offset <= end_offset) { |
| PaintInternalRun<Step>(text_run_paint_info, start_offset, end_offset, |
| node_id); |
| } else { |
| if (end_offset > 0) { |
| PaintInternalRun<Step>(text_run_paint_info, ellipsis_offset_, end_offset, |
| node_id); |
| } |
| if (start_offset < truncation_point) { |
| PaintInternalRun<Step>(text_run_paint_info, start_offset, |
| truncation_point, node_id); |
| } |
| } |
| } |
| |
| void TextPainter::ClipDecorationsStripe(float upper, |
| float stripe_width, |
| float dilation) { |
| TextRunPaintInfo text_run_paint_info(run_); |
| if (!run_.length()) |
| return; |
| |
| Vector<Font::TextIntercept> text_intercepts; |
| font_.GetTextIntercepts( |
| text_run_paint_info, graphics_context_.DeviceScaleFactor(), |
| graphics_context_.FillFlags(), |
| std::make_tuple(upper, upper + stripe_width), text_intercepts); |
| |
| DecorationsStripeIntercepts(upper, stripe_width, dilation, text_intercepts); |
| } |
| |
| void TextPainter::PaintEmphasisMarkForCombinedText() { |
| const SimpleFontData* font_data = font_.PrimaryFont(); |
| DCHECK(font_data); |
| if (!font_data) |
| return; |
| |
| DCHECK(combined_text_); |
| TextRun placeholder_text_run(&kIdeographicFullStopCharacter, 1); |
| FloatPoint emphasis_mark_text_origin( |
| text_frame_rect_.X().ToFloat(), text_frame_rect_.Y().ToFloat() + |
| font_data->GetFontMetrics().Ascent() + |
| emphasis_mark_offset_); |
| TextRunPaintInfo text_run_paint_info(placeholder_text_run); |
| graphics_context_.ConcatCTM(Rotation(text_frame_rect_, kClockwise)); |
| graphics_context_.DrawEmphasisMarks(combined_text_->OriginalFont(), |
| text_run_paint_info, emphasis_mark_, |
| emphasis_mark_text_origin); |
| graphics_context_.ConcatCTM(Rotation(text_frame_rect_, kCounterclockwise)); |
| } |
| |
| } // namespace blink |