Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(773)

Unified Diff: third_party/WebKit/Source/core/paint/NGTextFragmentPainter.cpp

Issue 2842983002: [LayoutNG] Paint inlines from the fragment tree
Patch Set: Rebase w/HEAD Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/paint/NGTextFragmentPainter.cpp
diff --git a/third_party/WebKit/Source/core/paint/NGTextFragmentPainter.cpp b/third_party/WebKit/Source/core/paint/NGTextFragmentPainter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4d9b8e3467caee7e00d067a81ff9357aa89046ce
--- /dev/null
+++ b/third_party/WebKit/Source/core/paint/NGTextFragmentPainter.cpp
@@ -0,0 +1,279 @@
+// Copyright 2017 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 "core/paint/NGTextFragmentPainter.h"
+
+#include "core/frame/LocalFrame.h"
+#include "core/layout/ng/inline/ng_physical_text_fragment.h"
+#include "core/paint/NGTextPainter.h"
+#include "core/paint/PaintInfo.h"
+#include "core/paint/TextPainterBase.h"
+#include "core/style/AppliedTextDecoration.h"
+#include "platform/graphics/GraphicsContextStateSaver.h"
+#include "platform/graphics/paint/DrawingRecorder.h"
+#include "platform/wtf/Optional.h"
+
+namespace blink {
+
+namespace {
+static void PrepareContextForDecoration(
+ GraphicsContext& context,
+ GraphicsContextStateSaver& state_saver,
+ bool is_horizontal,
+ const TextPainterBase::Style& text_style,
+ const LayoutRect& box_rect) {
+ TextPainterBase::UpdateGraphicsContext(context, text_style, is_horizontal,
+ state_saver);
+}
+
+static void RestoreContextFromDecoration(GraphicsContext& context,
+ const LayoutRect& box_rect) {}
+
+static void PaintDecorationsExceptLineThrough(
+ NGTextPainter& text_painter,
+ bool& has_line_through_decoration,
+ const NGPhysicalTextFragment* fragment,
+ const DecorationInfo& decoration_info,
+ const PaintInfo& paint_info,
+ const Vector<AppliedTextDecoration>& decorations) {
+ GraphicsContext& context = paint_info.context;
+ GraphicsContextStateSaver state_saver(context);
+ context.SetStrokeThickness(decoration_info.thickness);
+
+ // text-underline-position may flip underline and overline.
+ ResolvedUnderlinePosition underline_position =
+ decoration_info.underline_position;
+ bool flip_underline_and_overline = false;
+ if (underline_position == ResolvedUnderlinePosition::kOver) {
+ flip_underline_and_overline = true;
+ underline_position = ResolvedUnderlinePosition::kUnder;
+ }
+
+ // for (const AppliedTextDecoration& decoration : decorations) {
+ // TextDecoration lines = decoration.Lines();
+ // if (flip_underline_and_overline) {
+ // lines = static_cast<TextDecoration>(
+ // lines ^ (kTextDecorationUnderline | kTextDecorationOverline));
+ // }
+ // if ((lines & kTextDecorationUnderline) && decoration_info.font_data) {
+ // const int underline_offset = 0;
+ // text_painter.PaintDecorationUnderOrOverLine(context, decoration_info,
+ // decoration,
+ // underline_offset);
+ // }
+ // if (lines & kTextDecorationOverline) {
+ // const int overline_offset = 0;
+ // text_painter.PaintDecorationUnderOrOverLine(context, decoration_info,
+ // decoration,
+ // overline_offset);
+ // }
+ // // We could instead build a vector of the TextDecoration instances needing
+ // // line-through but this is a rare case so better to avoid vector
+ // overhead. has_line_through_decoration |= ((lines &
+ // kTextDecorationLineThrough) != 0);
+ //}
+}
+
+} // anonymous namespace
+
+void NGTextFragmentPainter::Paint(const Document& document,
+ const PaintInfo& paint_info,
+ const LayoutPoint& paint_offset) {
+ // TODO(eae): Move
+ static unsigned short kCNoTruncation = USHRT_MAX;
+ static unsigned short kCFullTruncation = USHRT_MAX - 1;
+
+ const ComputedStyle& style_to_use = text_fragment_->Style();
+
+ NGPhysicalSize size_;
+ NGPhysicalOffset offset_;
+
+ // We round the y-axis to ensure consistent line heights.
+ LayoutPoint adjusted_paint_offset =
+ LayoutPoint(paint_offset.X(), LayoutUnit(paint_offset.Y().Round()));
+
+ NGPhysicalOffset offset = text_fragment_->Offset();
+ LayoutPoint box_origin(offset.left, offset.top);
+ box_origin.Move(adjusted_paint_offset.X(), adjusted_paint_offset.Y());
+
+ LayoutRect box_rect(box_origin, LayoutSize(text_fragment_->Size().width,
+ text_fragment_->Size().height));
+
+ GraphicsContext& context = paint_info.context;
+
+ bool is_printing = paint_info.IsPrinting();
+
+ // Determine whether or not we're selected.
+ // bool have_selection = !is_printing &&
+ // paint_info.phase != kPaintPhaseTextClip &&
+ // inline_text_box_.GetSelectionState() != SelectionNone;
+ bool have_selection = false;
+ if (!have_selection && paint_info.phase == kPaintPhaseSelection) {
+ // When only painting the selection, don't bother to paint if there is none.
+ return;
+ }
+
+ // Determine text colors.
+ TextPainterBase::Style text_style =
+ TextPainterBase::TextPaintingStyle(document, style_to_use, paint_info);
+ // TextPainterBase::Style selection_style =
+ // TextPainter::SelectionPaintingStyle(
+ // text_fragment_.GetLineLayoutItem(), have_selection, paint_info,
+ // text_style);
+ TextPainterBase::Style selection_style = text_style;
+ bool paint_selected_text_only = (paint_info.phase == kPaintPhaseSelection);
+ bool paint_selected_text_separately =
+ !paint_selected_text_only && text_style != selection_style;
+
+ // Set our font.
+ const Font& font = style_to_use.GetFont();
+ const SimpleFontData* font_data = font.PrimaryFont();
+ DCHECK(font_data);
+
+ int ascent = font_data ? font_data->GetFontMetrics().Ascent() : 0;
+ LayoutPoint text_origin(box_origin.X(), box_origin.Y() + ascent);
+
+ // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
+ // include selection and composition highlights.
+ if (paint_info.phase != kPaintPhaseSelection &&
+ paint_info.phase != kPaintPhaseTextClip && !is_printing) {
+ // PaintDocumentMarkers(paint_info, box_origin, style_to_use, font,
+ // DocumentMarkerPaintPhase::kBackground);
+
+ // const LayoutObject& text_box_layout_object = InlineLayoutObject();
+ // if (have_selection && !PaintsCompositionMarkers(text_box_layout_object))
+ // {
+ // if (combined_text)
+ // PaintSelection<InlineTextBoxPainter::PaintOptions::kCombinedText>(
+ // context, box_rect, style_to_use, font, selection_style.fill_color,
+ // combined_text);
+ // else
+ // PaintSelection<InlineTextBoxPainter::PaintOptions::kNormal>(
+ // context, box_rect, style_to_use, font,
+ // selection_style.fill_color);
+ //}
+ }
+
+ // 2. Now paint the foreground, including text and decorations.
+ int selection_start = 0;
+ int selection_end = 0;
+ // if (paint_selected_text_only || paint_selected_text_separately)
+ // text_fragment_.SelectionStartEnd(selection_start, selection_end);
+
+ // bool respect_hyphen =
+ // selection_end == static_cast<int>(text_fragment_.Len()) &&
+ // text_fragment_.HasHyphen();
+ // if (respect_hyphen)
+ // selection_end = text_run.length();
+
+ unsigned length = text_fragment_->Text().length();
+
+ bool ltr = true;
+ bool flow_is_ltr = true;
+ if (text_fragment_->Truncation() != kCNoTruncation) {
+ // In a mixed-direction flow the ellipsis is at the start of the text
+ // rather than at the end of it.
+ selection_start =
+ ltr == flow_is_ltr
+ ? std::min<int>(selection_start, text_fragment_->Truncation())
+ : std::max<int>(selection_start, text_fragment_->Truncation());
+ selection_end =
+ ltr == flow_is_ltr
+ ? std::min<int>(selection_end, text_fragment_->Truncation())
+ : std::max<int>(selection_end, text_fragment_->Truncation());
+ length = ltr == flow_is_ltr ? text_fragment_->Truncation() : length;
+ }
+
+ NGTextPainter text_painter(context, font, text_fragment_, text_origin,
+ box_rect, text_fragment_->IsHorizontal());
+ TextEmphasisPosition emphasis_mark_position;
+ // bool has_text_emphasis = text_fragment_->GetEmphasisMarkPosition(
+ // style_to_use, emphasis_mark_position);
+ emphasis_mark_position = kTextEmphasisPositionOver;
+ bool has_text_emphasis = false;
+ if (has_text_emphasis) {
+ text_painter.SetEmphasisMark(style_to_use.TextEmphasisMarkString(),
+ emphasis_mark_position);
+ }
+ // if (combined_text)
+ // text_painter.SetCombinedText(combined_text);
+ if (text_fragment_->Truncation() != kCNoTruncation && ltr != flow_is_ltr)
+ text_painter.SetEllipsisOffset(text_fragment_->Truncation());
+
+ bool should_rotate = false;
+
+ if (!paint_selected_text_only) {
+ // Paint text decorations except line-through.
+ DecorationInfo decoration_info;
+ bool has_line_through_decoration = false;
+ if (style_to_use.TextDecorationsInEffect() != TextDecoration::kNone &&
+ text_fragment_->Truncation() != kCFullTruncation) {
+ LayoutPoint local_origin = LayoutPoint(box_origin);
+ LayoutUnit width = text_fragment_->Size().width;
+ // const NGPhysicalTextFragment* decorating_box =
+ // EnclosingUnderlineObject(&text_fragment_);
+ const ComputedStyle* decorating_box_style = nullptr;
+ // FontBaseline baseline_type = text_fragment_->Root().BaselineType();
+ FontBaseline baseline_type = kAlphabeticBaseline;
+
+ text_painter.ComputeDecorationInfo(decoration_info, box_origin,
+ local_origin, width, baseline_type,
+ style_to_use, decorating_box_style);
+
+ GraphicsContextStateSaver state_saver(context, false);
+ PrepareContextForDecoration(context, state_saver,
+ text_fragment_->IsHorizontal(), text_style,
+ box_rect);
+ PaintDecorationsExceptLineThrough(
+ text_painter, has_line_through_decoration, text_fragment_,
+ decoration_info, paint_info, style_to_use.AppliedTextDecorations());
+ RestoreContextFromDecoration(context, box_rect);
+ }
+
+ int start_offset = 0;
+ int end_offset = length;
+ // Where the text and its flow have opposite directions then our offset into
+ // the text given by |truncation| is at the start of the part that will be
+ // visible.
+ if (text_fragment_->Truncation() != kCNoTruncation && ltr != flow_is_ltr) {
+ start_offset = text_fragment_->Truncation();
+ end_offset = length;
+ }
+
+ if (paint_selected_text_separately && selection_start < selection_end) {
+ start_offset = selection_end;
+ end_offset = selection_start;
+ }
+
+ text_painter.Paint(start_offset, end_offset, length, text_style);
+
+ // Paint line-through decoration if needed.
+ if (has_line_through_decoration) {
+ GraphicsContextStateSaver state_saver(context, false);
+ PrepareContextForDecoration(context, state_saver,
+ text_fragment_->IsHorizontal(), text_style,
+ box_rect);
+ text_painter.PaintDecorationsOnlyLineThrough(
+ decoration_info, paint_info, style_to_use.AppliedTextDecorations());
+ RestoreContextFromDecoration(context, box_rect);
+ }
+ }
+
+ if ((paint_selected_text_only || paint_selected_text_separately) &&
+ selection_start < selection_end) {
+ // paint only the text that is selected
+ text_painter.Paint(selection_start, selection_end, length, selection_style);
+ }
+
+ // if (paint_info.phase == kPaintPhaseForeground)
+ // PaintDocumentMarkers(paint_info, box_origin, style_to_use, font,
+ // DocumentMarkerPaintPhase::kForeground);
+
+ if (should_rotate) {
+ context.ConcatCTM(TextPainterBase::Rotation(
+ box_rect, TextPainterBase::kCounterclockwise));
+ }
+}
+
+} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/paint/NGTextFragmentPainter.h ('k') | third_party/WebKit/Source/core/paint/NGTextPainter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698