#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 {
constexpr char16_t kEllipsisCodepoint = …;
const SkScalar kStrikeThroughOffset = …;
const SkScalar kUnderlineOffset = …;
const float kFloatComparisonEpsilon = …;
float Clamp(float f) { … }
int CalculateFadeGradientWidth(const FontList& font_list, int display_width) { … }
void AddFadeEffect(const Rect& text_rect,
const Rect& fade_rect,
SkColor c0,
SkColor c1,
std::vector<SkScalar>* positions,
std::vector<SkColor>* colors) { … }
sk_sp<cc::PaintShader> CreateFadeShader(const FontList& font_list,
const Rect& text_rect,
const Rect& left_part,
const Rect& right_part,
SkColor color) { … }
SkFontHinting FontRenderParamsHintingToSkFontHinting(
FontRenderParams::Hinting params_hinting) { … }
template <typename T>
void RestoreBreakList(RenderText* render_text, BreakList<T>* break_list) { … }
template <typename T>
typename BreakList<T>::const_iterator IncrementBreakListIteratorToPosition(
const BreakList<T>& break_list,
typename BreakList<T>::const_iterator iter,
size_t position) { … }
UChar32 ReplaceControlCharacter(UChar32 codepoint) { … }
int GetLineSegmentContainingXCoord(const internal::Line& line,
float line_x,
float* offset_relative_segment) { … }
}
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) { … }
}
constexpr char16_t RenderText::kPasswordReplacementChar;
constexpr bool RenderText::kDragToEndIfOutsideVerticalBounds;
constexpr int RenderText::kInvalidBaseline;
constexpr SkScalar RenderText::kLineThicknessFactor;
RenderText::~RenderText() = default;
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) { … }
bool RenderText::RangeContainsCaret(const Range& range,
size_t caret_pos,
LogicalCursorDirection caret_affinity) { … }
int RenderText::DetermineBaselineCenteringText(const int display_height,
const FontList& font_list) { … }
Rect RenderText::ExpandToBeVerticallySymmetric(const Rect& rect,
const Rect& display_rect) { … }
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 { … }
}