chromium/ui/gfx/render_text.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/gfx/render_text.h"

#include <limits.h>

#include <algorithm>
#include <climits>
#include <utility>

#include "base/check_op.h"
#include "base/command_line.h"
#include "base/i18n/break_iterator.h"
#include "base/i18n/char_iterator.h"
#include "base/i18n/rtl.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/paint/draw_looper.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_shader.h"
#include "third_party/icu/source/common/unicode/rbbi.h"
#include "third_party/icu/source/common/unicode/uchar.h"
#include "third_party/icu/source/common/unicode/utf16.h"
#include "third_party/skia/include/core/SkFontStyle.h"
#include "third_party/skia/include/core/SkTextBlob.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/skia_conversions.h"
#include "ui/gfx/platform_font.h"
#include "ui/gfx/render_text_harfbuzz.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/gfx/text_constants.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/text_utils.h"
#include "ui/gfx/utf16_indexing.h"

namespace gfx {

namespace {

// Replacement codepoint for elided text.
constexpr char16_t kEllipsisCodepoint =;

// Fraction of the text size to raise the center of a strike-through line above
// the baseline.
const SkScalar kStrikeThroughOffset =;
// Fraction of the text size to lower an underline below the baseline.
const SkScalar kUnderlineOffset =;

// Float comparison needs epsilon to consider rounding errors in float
// arithmetic. Epsilon should be dependent on the context and here, we are
// dealing with glyph widths, use a fairly large number.
const float kFloatComparisonEpsilon =;
float Clamp(float f) {}

// Given |font| and |display_width|, returns the width of the fade gradient.
int CalculateFadeGradientWidth(const FontList& font_list, int display_width) {}

// Appends to |positions| and |colors| values corresponding to the fade over
// |fade_rect| from color |c0| to color |c1|.
void AddFadeEffect(const Rect& text_rect,
                   const Rect& fade_rect,
                   SkColor c0,
                   SkColor c1,
                   std::vector<SkScalar>* positions,
                   std::vector<SkColor>* colors) {}

// Creates a SkShader to fade the text, with |left_part| specifying the left
// fade effect, if any, and |right_part| specifying the right fade effect.
sk_sp<cc::PaintShader> CreateFadeShader(const FontList& font_list,
                                        const Rect& text_rect,
                                        const Rect& left_part,
                                        const Rect& right_part,
                                        SkColor color) {}

// Converts a FontRenderParams::Hinting value to the corresponding
// SkFontHinting value.
SkFontHinting FontRenderParamsHintingToSkFontHinting(
    FontRenderParams::Hinting params_hinting) {}

// Make sure ranges don't break text graphemes.  If a range in |break_list|
// does break a grapheme in |render_text|, the range will be slightly
// extended to encompass the grapheme.
template <typename T>
void RestoreBreakList(RenderText* render_text, BreakList<T>* break_list) {}

// Move the iterator |iter| forward until |position| is included in the range.
template <typename T>
typename BreakList<T>::const_iterator IncrementBreakListIteratorToPosition(
    const BreakList<T>& break_list,
    typename BreakList<T>::const_iterator iter,
    size_t position) {}

// Replaces the unicode control characters, control characters and PUA (Private
// Use Areas) codepoints.
UChar32 ReplaceControlCharacter(UChar32 codepoint) {}

// Returns the line segment index for the |line|, |text_x| pair. |text_x| is
// relative to text in the given line. Returns -1 if |text_x| is to the left
// of text in the line and |line|.segments.size() if it's to the right.
// |offset_relative_segment| will contain the offset of |text_x| relative to
// the start of the segment it is contained in.
int GetLineSegmentContainingXCoord(const internal::Line& line,
                                   float line_x,
                                   float* offset_relative_segment) {}

}  // namespace

namespace internal {

SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas)
    :{}

SkiaTextRenderer::~SkiaTextRenderer() {}

void SkiaTextRenderer::SetDrawLooper(sk_sp<cc::DrawLooper> draw_looper) {}

void SkiaTextRenderer::SetFontRenderParams(const FontRenderParams& params,
                                           bool subpixel_rendering_suppressed) {}

void SkiaTextRenderer::SetTypeface(sk_sp<SkTypeface> typeface) {}

void SkiaTextRenderer::SetTextSize(SkScalar size) {}

void SkiaTextRenderer::SetForegroundColor(SkColor foreground) {}

void SkiaTextRenderer::SetShader(sk_sp<cc::PaintShader> shader) {}

void SkiaTextRenderer::SetFillStyle(cc::PaintFlags::Style fill_style) {}

void SkiaTextRenderer::SetStrokeWidth(SkScalar stroke_width) {}

void SkiaTextRenderer::DrawPosText(const SkPoint* pos,
                                   const uint16_t* glyphs,
                                   size_t glyph_count) {}

void SkiaTextRenderer::DrawUnderline(int x,
                                     int y,
                                     int width,
                                     SkScalar thickness_factor) {}

void SkiaTextRenderer::DrawStrike(int x,
                                  int y,
                                  int width,
                                  SkScalar thickness_factor) {}

StyleIterator::StyleIterator(
    const BreakList<SkColor>* colors,
    const BreakList<BaselineStyle>* baselines,
    const BreakList<int>* font_size_overrides,
    const BreakList<Font::Weight>* weights,
    const BreakList<SkTypefaceID>* resolved_typefaces,
    const BreakList<cc::PaintFlags::Style>* fill_styles,
    const BreakList<SkScalar>* stroke_widths,
    const StyleArray* styles)
    :{}

StyleIterator::StyleIterator(const StyleIterator& style) = default;
StyleIterator::~StyleIterator() = default;
StyleIterator& StyleIterator::operator=(const StyleIterator& style) = default;

Range StyleIterator::GetRange() const {}

Range StyleIterator::GetTextBreakingRange() const {}

void StyleIterator::IncrementToPosition(size_t position) {}

LineSegment::LineSegment() :{}

LineSegment::~LineSegment() {}

Line::Line() :{}

Line::Line(const Line& other) = default;

Line::~Line() {}

ShapedText::ShapedText(std::vector<Line> lines) :{}
ShapedText::~ShapedText() = default;

void ApplyRenderParams(const FontRenderParams& params,
                       bool subpixel_rendering_suppressed,
                       SkFont* font) {}

}  // namespace internal

// static
constexpr char16_t RenderText::kPasswordReplacementChar;
constexpr bool RenderText::kDragToEndIfOutsideVerticalBounds;
constexpr int RenderText::kInvalidBaseline;
constexpr SkScalar RenderText::kLineThicknessFactor;

RenderText::~RenderText() = default;

// static
std::unique_ptr<RenderText> RenderText::CreateRenderText() {}

std::unique_ptr<RenderText> RenderText::CreateInstanceOfSameStyle(
    const std::u16string& text) const {}

void RenderText::SetText(std::u16string text) {}

void RenderText::AppendText(const std::u16string& text) {}

void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) {}

void RenderText::SetVerticalAlignment(VerticalAlignment alignment) {}

void RenderText::SetFontList(const FontList& font_list) {}

void RenderText::SetCursorEnabled(bool cursor_enabled) {}

void RenderText::SetObscured(bool obscured) {}

void RenderText::SetObscuredRevealIndex(std::optional<size_t> index) {}

void RenderText::SetObscuredGlyphSpacing(int spacing) {}

void RenderText::SetMultiline(bool multiline) {}

void RenderText::SetMaxLines(size_t max_lines) {}

size_t RenderText::GetNumLines() {}

size_t RenderText::GetTextIndexOfLine(size_t line) {}

void RenderText::SetWordWrapBehavior(WordWrapBehavior behavior) {}

void RenderText::SetMinLineHeight(int line_height) {}

void RenderText::SetElideBehavior(ElideBehavior elide_behavior) {}

void RenderText::SetWhitespaceElision(std::optional<bool> whitespace_elision) {}

void RenderText::SetDisplayRect(const Rect& r) {}

const std::vector<Range> RenderText::GetAllSelections() const {}

void RenderText::SetCursorPosition(size_t position) {}

void RenderText::MoveCursor(BreakType break_type,
                            VisualCursorDirection direction,
                            SelectionBehavior selection_behavior) {}

bool RenderText::SetSelection(const SelectionModel& model) {}

bool RenderText::MoveCursorToPoint(const Point& point,
                                   bool select,
                                   const Point& drag_origin) {}

bool RenderText::SelectRange(const Range& range, bool primary) {}

bool RenderText::IsPointInSelection(const Point& point) {}

void RenderText::ClearSelection() {}

void RenderText::SelectAll(bool reversed) {}

void RenderText::SelectWord() {}

void RenderText::SetCompositionRange(const Range& composition_range) {}

void RenderText::SetColor(SkColor value) {}

void RenderText::ApplyColor(SkColor value, const Range& range) {}

void RenderText::SetBaselineStyle(BaselineStyle value) {}

void RenderText::ApplyBaselineStyle(BaselineStyle value, const Range& range) {}

void RenderText::ApplyFontSizeOverride(int font_size_override,
                                       const Range& range) {}

void RenderText::SetStyle(TextStyle style, bool value) {}

void RenderText::ApplyStyle(TextStyle style, bool value, const Range& range) {}

void RenderText::SetWeight(Font::Weight weight) {}

void RenderText::ApplyWeight(Font::Weight weight, const Range& range) {}

void RenderText::SetFillStyle(cc::PaintFlags::Style style) {}

void RenderText::ApplyFillStyle(cc::PaintFlags::Style style,
                                const Range& range) {}

void RenderText::SetStrokeWidth(SkScalar stroke_width) {}

void RenderText::ApplyStrokeWidth(SkScalar stroke_width, const Range& range) {}

void RenderText::SetEliding(bool value) {}

void RenderText::ApplyEliding(bool value, const Range& range) {}

bool RenderText::GetStyle(TextStyle style) const {}

void RenderText::SetDirectionalityMode(DirectionalityMode mode) {}

base::i18n::TextDirection RenderText::GetTextDirection() const {}

base::i18n::TextDirection RenderText::GetDisplayTextDirection() {}

VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() {}

VisualCursorDirection RenderText::GetVisualDirectionOfLogicalBeginning() {}

Size RenderText::GetStringSize() {}

float RenderText::TotalLineWidth() {}

float RenderText::GetContentWidthF() {}

int RenderText::GetContentWidth() {}

int RenderText::GetBaseline() {}

void RenderText::Draw(Canvas* canvas, bool select_all) {}

SelectionModel RenderText::FindCursorPosition(const Point& view_point,
                                              const Point& drag_origin) {}

bool RenderText::IsValidLogicalIndex(size_t index) const {}

bool RenderText::IsValidCursorIndex(size_t index) const {}

Rect RenderText::GetCursorBounds(const SelectionModel& caret,
                                 bool insert_mode) {}

const Rect& RenderText::GetUpdatedCursorBounds() {}

internal::GraphemeIterator RenderText::GetGraphemeIteratorAtTextIndex(
    size_t index) const {}

internal::GraphemeIterator RenderText::GetGraphemeIteratorAtDisplayTextIndex(
    size_t index) const {}

size_t RenderText::GetTextIndex(internal::GraphemeIterator iter) const {}

size_t RenderText::GetDisplayTextIndex(internal::GraphemeIterator iter) const {}

bool RenderText::IsGraphemeBoundary(size_t index) const {}

size_t RenderText::IndexOfAdjacentGrapheme(
    size_t index,
    LogicalCursorDirection direction) const {}

SelectionModel RenderText::GetSelectionModelForSelectionStart() const {}

const Vector2d& RenderText::GetUpdatedDisplayOffset() {}

void RenderText::SetDisplayOffset(int horizontal_offset) {}

void RenderText::SetDisplayOffset(Vector2d offset) {}

Vector2d RenderText::GetLineOffset(size_t line_number) {}

bool RenderText::GetWordLookupDataAtPoint(const Point& point,
                                          DecoratedText* decorated_word,
                                          Rect* rect) {}

bool RenderText::GetLookupDataForRange(const Range& range,
                                       DecoratedText* decorated_text,
                                       Rect* rect) {}

std::u16string RenderText::GetTextFromRange(const Range& range) const {}

Range RenderText::ExpandRangeToGraphemeBoundary(const Range& range) const {}

Range RenderText::ExpandRangeToWordBoundary(const Range& range) const {}

bool RenderText::IsNewlineSegment(const internal::LineSegment& segment) const {}

bool RenderText::IsNewlineSegment(const std::u16string& text,
                                  const internal::LineSegment& segment) const {}

Range RenderText::GetLineRange(const std::u16string& text,
                               const internal::Line& line) const {}

RenderText::RenderText() = default;

internal::StyleIterator RenderText::GetTextStyleIterator() const {}

internal::StyleIterator RenderText::GetLayoutTextStyleIterator() const {}

bool RenderText::IsHomogeneous() const {}

internal::ShapedText* RenderText::GetShapedText() {}

int RenderText::GetDisplayTextBaseline() {}

SelectionModel RenderText::GetAdjacentSelectionModel(
    const SelectionModel& current,
    BreakType break_type,
    VisualCursorDirection direction) {}

SelectionModel RenderText::EdgeSelectionModel(
    VisualCursorDirection direction) {}

SelectionModel RenderText::LineSelectionModel(size_t line_index,
                                              VisualCursorDirection direction) {}

void RenderText::SetSelectionModel(const SelectionModel& model) {}

void RenderText::AddSecondarySelection(const Range selection) {}

size_t RenderText::TextIndexToDisplayIndex(size_t index) const {}

size_t RenderText::DisplayIndexToTextIndex(size_t index) const {}

void RenderText::OnLayoutTextAttributeChanged() {}

void RenderText::EnsureLayoutTextUpdated() const {}

const std::u16string& RenderText::GetLayoutText() const {}

void RenderText::UpdateDisplayText(float text_width) {}

Point RenderText::ToViewPoint(const PointF& point, size_t line) {}

HorizontalAlignment RenderText::GetCurrentHorizontalAlignment() {}

Vector2d RenderText::GetAlignmentOffset(size_t line_number) {}

void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) {}

void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) {}

base::i18n::TextDirection RenderText::GetTextDirectionForGivenText(
    const std::u16string& text) const {}

void RenderText::UpdateStyleLengths() {}

void RenderText::UpdateLayoutStyleLengths(size_t max_length) const {}

int RenderText::GetLineContainingYCoord(float text_y) {}

// static
bool RenderText::RangeContainsCaret(const Range& range,
                                    size_t caret_pos,
                                    LogicalCursorDirection caret_affinity) {}

// static
int RenderText::DetermineBaselineCenteringText(const int display_height,
                                               const FontList& font_list) {}

// static
Rect RenderText::ExpandToBeVerticallySymmetric(const Rect& rect,
                                               const Rect& display_rect) {}

// static
void RenderText::MergeIntersectingRects(std::vector<Rect>& rects) {}

void RenderText::OnTextAttributeChanged() {}

std::u16string RenderText::Elide(const std::u16string& text,
                                 float text_width,
                                 float available_width,
                                 ElideBehavior behavior) {}

std::u16string RenderText::ElideEmail(const std::u16string& email,
                                      float available_width) {}

void RenderText::UpdateCachedBoundsAndOffset() {}

internal::GraphemeIterator RenderText::GetGraphemeIteratorAtIndex(
    const std::u16string& text,
    const size_t internal::TextToDisplayIndex::*field,
    size_t index) const {}

void RenderText::DrawSelections(Canvas* canvas,
                                const std::vector<Range>& selections) {}

size_t RenderText::GetNearestWordStartBoundary(size_t index) const {}

}  // namespace gfx