#include "ui/gfx/render_text_harfbuzz.h"
#include <limits>
#include <set>
#include <string_view>
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/lru_cache.h"
#include "base/containers/span.h"
#include "base/debug/alias.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/hash/hash.h"
#include "base/i18n/base_i18n_switches.h"
#include "base/i18n/break_iterator.h"
#include "base/i18n/char_iterator.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/current_thread.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "skia/ext/font_utils.h"
#include "third_party/icu/source/common/unicode/ubidi.h"
#include "third_party/icu/source/common/unicode/uscript.h"
#include "third_party/icu/source/common/unicode/utf16.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkFontMetrics.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/bidi_line_iterator.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/decorated_text.h"
#include "ui/gfx/font.h"
#include "ui/gfx/font_fallback.h"
#include "ui/gfx/font_render_params.h"
#include "ui/gfx/harfbuzz_font_skia.h"
#include "ui/gfx/platform_font.h"
#include "ui/gfx/range/range_f.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/switches.h"
#include "ui/gfx/text_utils.h"
#include "ui/gfx/utf16_indexing.h"
#if BUILDFLAG(IS_APPLE)
#include "base/apple/foundation_util.h"
#include "base/mac/mac_util.h"
#include "third_party/skia/include/ports/SkTypeface_mac.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/locale_utils.h"
#endif
#include <hb.h>
namespace gfx {
namespace {
const size_t kMaxTextLength = …;
const size_t kMaxScripts = …;
enum class ShapeRunFallback { … };
void RecordShapeRunsFallback(ShapeRunFallback fallback) { … }
bool IsExtendedPictographicCodepoint(UChar32 codepoint) { … }
bool IsEmojiRelatedCodepoint(UChar32 codepoint) { … }
bool IsBracket(UChar32 codepoint) { … }
std::vector<UScriptCode> GetScriptExtensions(UChar32 codepoint) { … }
void ScriptSetIntersect(UChar32 codepoint, std::vector<UScriptCode>& result) { … }
struct GraphemeProperties { … };
GraphemeProperties RetrieveGraphemeProperties(std::u16string_view text,
bool retrieve_block) { … }
bool AreGraphemePropertiesCompatible(const GraphemeProperties& first,
const GraphemeProperties& second) { … }
size_t FindRunBreakingCharacter(const std::u16string& text,
UScriptCode script,
size_t run_start,
size_t run_break,
size_t run_end) { … }
size_t ScriptInterval(const std::u16string& text,
size_t start,
size_t length,
UScriptCode* script) { … }
inline hb_script_t ICUScriptToHBScript(UScriptCode script) { … }
bool FontWasAlreadyTried(sk_sp<SkTypeface> typeface,
std::set<SkTypefaceID>* fallback_fonts) { … }
void MarkFontAsTried(sk_sp<SkTypeface> typeface,
std::set<SkTypefaceID>* fallback_fonts) { … }
bool IsNewlineSegment(const std::u16string& text,
const internal::LineSegment& segment) { … }
size_t LineIndexForNewline(const size_t line_index,
const std::u16string& text,
const internal::LineSegment& segment,
const SelectionModel& caret) { … }
template <class Iterator>
bool GetClusterAtImpl(size_t pos,
Range range,
Iterator elements_begin,
Iterator elements_end,
bool reversed,
Range* chars,
Range* glyphs) { … }
class HarfBuzzLineBreaker { … };
void ApplyForcedDirection(UBiDiLevel* level) { … }
internal::TextRunHarfBuzz::FontParams CreateFontParams(
const Font& primary_font,
UBiDiLevel bidi_level,
UScriptCode script,
const internal::StyleIterator& style) { … }
BASE_FEATURE(…);
bool IsRemoveFontLinkFallbacks() { … }
BASE_FEATURE(…);
bool IsEnableFallbackFontsCrashReporting() { … }
void AppendFontNameAndShapedTextToCrashDumpReport(
const std::u16string& text,
const std::vector<internal::TextRunHarfBuzz*>& shaped_runs,
const std::string& font_name,
std::u16string& report) { … }
}
namespace internal {
sk_sp<SkTypeface> CreateSkiaTypeface(const Font& font,
bool italic,
Font::Weight weight) { … }
TextRunHarfBuzz::FontParams::FontParams(const Font& template_font)
: … { … }
TextRunHarfBuzz::FontParams::~FontParams() = default;
TextRunHarfBuzz::FontParams::FontParams(
const TextRunHarfBuzz::FontParams& other) = default;
TextRunHarfBuzz::FontParams& TextRunHarfBuzz::FontParams::operator=(
const TextRunHarfBuzz::FontParams& other) = default;
bool TextRunHarfBuzz::FontParams::operator==(const FontParams& other) const { … }
void TextRunHarfBuzz::FontParams::
ComputeRenderParamsFontSizeAndBaselineOffset() { … }
size_t TextRunHarfBuzz::FontParams::Hash::operator()(
const FontParams& key) const { … }
bool TextRunHarfBuzz::FontParams::SetRenderParamsRematchFont(
const Font& new_font,
const FontRenderParams& new_render_params) { … }
bool TextRunHarfBuzz::FontParams::SetRenderParamsOverrideSkiaFaceFromFont(
const Font& fallback_font,
const FontRenderParams& new_render_params) { … }
TextRunHarfBuzz::ShapeOutput::ShapeOutput() = default;
TextRunHarfBuzz::ShapeOutput::~ShapeOutput() = default;
TextRunHarfBuzz::ShapeOutput::ShapeOutput(
const TextRunHarfBuzz::ShapeOutput& other) = default;
TextRunHarfBuzz::ShapeOutput& TextRunHarfBuzz::ShapeOutput::operator=(
const TextRunHarfBuzz::ShapeOutput& other) = default;
TextRunHarfBuzz::ShapeOutput::ShapeOutput(
TextRunHarfBuzz::ShapeOutput&& other) = default;
TextRunHarfBuzz::ShapeOutput& TextRunHarfBuzz::ShapeOutput::operator=(
TextRunHarfBuzz::ShapeOutput&& other) = default;
TextRunHarfBuzz::TextRunHarfBuzz(const Font& template_font)
: … { … }
TextRunHarfBuzz::~TextRunHarfBuzz() { … }
Range TextRunHarfBuzz::CharRangeToGlyphRange(const Range& char_range) const { … }
size_t TextRunHarfBuzz::CountMissingGlyphs() const { … }
void TextRunHarfBuzz::GetClusterAt(size_t pos,
Range* chars,
Range* glyphs) const { … }
RangeF TextRunHarfBuzz::GetGraphemeBounds(RenderTextHarfBuzz* render_text,
size_t text_index) const { … }
RangeF TextRunHarfBuzz::GetGraphemeSpanForCharRange(
RenderTextHarfBuzz* render_text,
const Range& char_range) const { … }
SkScalar TextRunHarfBuzz::GetGlyphWidthForCharRange(
const Range& char_range) const { … }
void TextRunHarfBuzz::UpdateFontParamsAndShape(
const FontParams& new_font_params,
const ShapeOutput& new_shape) { … }
TextRunList::TextRunList() : … { … }
TextRunList::~TextRunList() { … }
void TextRunList::Reset() { … }
void TextRunList::InitIndexMap() { … }
void TextRunList::ComputePrecedingRunWidths() { … }
size_t TextRunList::GetRunIndexAt(size_t position) const { … }
namespace {
struct ShapeRunWithFontInput { … };
constexpr int kShapeRunCacheSize = …;
ShapeRunCacheBase;
class ShapeRunCache : public ShapeRunCacheBase { … };
void ShapeRunWithFont(const ShapeRunWithFontInput& in,
TextRunHarfBuzz::ShapeOutput* out) { … }
std::string GetApplicationLocale() { … }
}
}
RenderTextHarfBuzz::RenderTextHarfBuzz()
: … { … }
RenderTextHarfBuzz::~RenderTextHarfBuzz() { … }
const std::u16string& RenderTextHarfBuzz::GetDisplayText() { … }
SizeF RenderTextHarfBuzz::GetStringSizeF() { … }
SizeF RenderTextHarfBuzz::GetLineSizeF(const SelectionModel& caret) { … }
std::vector<Rect> RenderTextHarfBuzz::GetSubstringBounds(const Range& range) { … }
RangeF RenderTextHarfBuzz::GetCursorSpan(const Range& text_range) { … }
size_t RenderTextHarfBuzz::GetLineContainingCaret(const SelectionModel& caret) { … }
SelectionModel RenderTextHarfBuzz::AdjacentCharSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) { … }
SelectionModel RenderTextHarfBuzz::AdjacentWordSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) { … }
SelectionModel RenderTextHarfBuzz::AdjacentLineSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) { … }
void RenderTextHarfBuzz::OnLayoutTextAttributeChanged() { … }
void RenderTextHarfBuzz::OnDisplayTextAttributeChanged() { … }
void RenderTextHarfBuzz::EnsureLayout() { … }
void RenderTextHarfBuzz::DrawVisualText(internal::SkiaTextRenderer* renderer,
const std::vector<Range>& selections) { … }
size_t RenderTextHarfBuzz::GetRunContainingCaret(
const SelectionModel& caret) { … }
SelectionModel RenderTextHarfBuzz::FirstSelectionModelInsideRun(
const internal::TextRunHarfBuzz* run) { … }
SelectionModel RenderTextHarfBuzz::LastSelectionModelInsideRun(
const internal::TextRunHarfBuzz* run) { … }
void RenderTextHarfBuzz::BuildResolvedTypefaceBreakList(
internal::TextRunList* run_list) { … }
void RenderTextHarfBuzz::ItemizeAndShapeText(const std::u16string& text,
internal::TextRunList* run_list) { … }
bool RenderTextHarfBuzz::ItemizeAndShapeTextImpl(
CommonizedRunsMap* commonized_run_map,
const std::u16string& text,
internal::TextRunList* run_list) { … }
void RenderTextHarfBuzz::ItemizeTextToRuns(
const std::u16string& text,
internal::TextRunList* out_run_list,
CommonizedRunsMap* out_commonized_run_map) { … }
bool RenderTextHarfBuzz::ShapeRuns(
const std::u16string& text,
const internal::TextRunHarfBuzz::FontParams& font_params,
std::vector<internal::TextRunHarfBuzz*> runs) { … }
void RenderTextHarfBuzz::ShapeRunsWithFont(
const std::u16string& text,
const internal::TextRunHarfBuzz::FontParams& font_params,
std::vector<internal::TextRunHarfBuzz*>* in_out_runs,
std::vector<internal::TextRunHarfBuzz*>* successfully_shaped_runs) { … }
void RenderTextHarfBuzz::EnsureLayoutRunList() { … }
internal::TextRunList* RenderTextHarfBuzz::GetRunList() { … }
const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { … }
bool RenderTextHarfBuzz::IsValidDisplayRange(Range display_range) { … }
void RenderTextHarfBuzz::GetDecoratedTextForRange(
const Range& text_range,
DecoratedText* decorated_text) { … }
}