blob: 90619d184988283fd987d31622c6d2be2f7fcf8c [file] [log] [blame]
// 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