#ifndef UI_GFX_RENDER_TEXT_HARFBUZZ_H_
#define UI_GFX_RENDER_TEXT_HARFBUZZ_H_
#include <hb.h>
#include <stddef.h>
#include <stdint.h>
#include <limits>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "third_party/icu/source/common/unicode/ubidi.h"
#include "third_party/icu/source/common/unicode/uscript.h"
#include "ui/gfx/render_text.h"
namespace gfx {
class Range;
class RangeF;
class RenderTextHarfBuzz;
namespace internal {
struct GFX_EXPORT TextRunHarfBuzz {
explicit TextRunHarfBuzz(const Font& template_font);
TextRunHarfBuzz(const TextRunHarfBuzz&) = delete;
TextRunHarfBuzz& operator=(const TextRunHarfBuzz&) = delete;
~TextRunHarfBuzz();
Range CharRangeToGlyphRange(const Range& range) const;
size_t CountMissingGlyphs() const;
void GetClusterAt(size_t pos, Range* chars, Range* glyphs) const;
RangeF GetGraphemeBounds(RenderTextHarfBuzz* render_text,
size_t text_index) const;
RangeF GetGraphemeSpanForCharRange(RenderTextHarfBuzz* render_text,
const Range& char_range) const;
SkScalar GetGlyphWidthForCharRange(const Range& char_range) const;
struct GFX_EXPORT FontParams {
explicit FontParams(const Font& template_font);
~FontParams();
FontParams(const FontParams& other);
FontParams& operator=(const FontParams& other);
bool operator==(const FontParams& other) const;
void ComputeRenderParamsFontSizeAndBaselineOffset();
bool SetRenderParamsRematchFont(const Font& font,
const FontRenderParams& render_params);
bool SetRenderParamsOverrideSkiaFaceFromFont(
const Font& font,
const FontRenderParams& render_params);
struct Hash {
size_t operator()(const FontParams& key) const;
};
Font font;
sk_sp<SkTypeface> skia_face;
FontRenderParams render_params;
Font::Weight weight = Font::Weight::NORMAL;
int font_size = 0;
int baseline_offset = 0;
int baseline_type = 0;
bool italic = false;
bool strike = false;
bool underline = false;
bool heavy_underline = false;
bool is_rtl = false;
UBiDiLevel level = 0;
UScriptCode script = USCRIPT_INVALID_CODE;
};
struct GFX_EXPORT ShapeOutput {
ShapeOutput();
~ShapeOutput();
ShapeOutput(const ShapeOutput& other);
ShapeOutput& operator=(const ShapeOutput& other);
ShapeOutput(ShapeOutput&& other);
ShapeOutput& operator=(ShapeOutput&& other);
float width = 0.0;
std::vector<uint16_t> glyphs;
std::vector<SkPoint> positions;
std::vector<uint32_t> glyph_to_char;
size_t glyph_count = 0;
size_t missing_glyph_count = std::numeric_limits<size_t>::max();
};
void UpdateFontParamsAndShape(const FontParams& new_font_params,
const ShapeOutput& new_shape);
Range range;
FontParams font_params;
ShapeOutput shape;
float preceding_run_widths = 0.0;
};
class TextRunList {
public:
TextRunList();
TextRunList(const TextRunList&) = delete;
TextRunList& operator=(const TextRunList&) = delete;
~TextRunList();
size_t size() const { return runs_.size(); }
size_t visual_to_logical(size_t index) const {
return visual_to_logical_[index];
}
size_t logical_to_visual(size_t index) const {
return logical_to_visual_[index];
}
const std::vector<std::unique_ptr<TextRunHarfBuzz>>& runs() const {
return runs_;
}
void Add(std::unique_ptr<TextRunHarfBuzz> run) {
runs_.push_back(std::move(run));
}
void Reset();
void InitIndexMap();
void ComputePrecedingRunWidths();
float width() const { return width_; }
size_t GetRunIndexAt(size_t position) const;
private:
std::vector<std::unique_ptr<TextRunHarfBuzz>> runs_;
std::vector<int32_t> visual_to_logical_;
std::vector<int32_t> logical_to_visual_;
float width_;
};
}
class GFX_EXPORT RenderTextHarfBuzz : public RenderText {
public:
RenderTextHarfBuzz();
RenderTextHarfBuzz(const RenderTextHarfBuzz&) = delete;
RenderTextHarfBuzz& operator=(const RenderTextHarfBuzz&) = delete;
~RenderTextHarfBuzz() override;
const std::u16string& GetDisplayText() override;
SizeF GetStringSizeF() override;
SizeF GetLineSizeF(const SelectionModel& caret) override;
std::vector<Rect> GetSubstringBounds(const Range& range) override;
RangeF GetCursorSpan(const Range& text_range) override;
size_t GetLineContainingCaret(const SelectionModel& caret) override;
protected:
SelectionModel AdjacentCharSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) override;
SelectionModel AdjacentWordSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) override;
SelectionModel AdjacentLineSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) override;
void OnLayoutTextAttributeChanged(bool text_changed) override;
void OnDisplayTextAttributeChanged() override;
void EnsureLayout() override;
void DrawVisualText(internal::SkiaTextRenderer* renderer,
const std::vector<Range>& selections) override;
private:
friend class test::RenderTextTestApi;
friend class RenderTextTest;
size_t GetRunContainingCaret(const SelectionModel& caret);
SelectionModel FirstSelectionModelInsideRun(
const internal::TextRunHarfBuzz* run);
SelectionModel LastSelectionModelInsideRun(
const internal::TextRunHarfBuzz* run);
using CommonizedRunsMap =
std::unordered_map<internal::TextRunHarfBuzz::FontParams,
std::vector<internal::TextRunHarfBuzz*>,
internal::TextRunHarfBuzz::FontParams::Hash>;
void ItemizeTextToRuns(const std::u16string& string,
internal::TextRunList* out_run_list,
CommonizedRunsMap* out_commonized_run_map);
void ShapeRuns(const std::u16string& text,
const internal::TextRunHarfBuzz::FontParams& base_font_params,
std::vector<internal::TextRunHarfBuzz*> runs);
void ShapeRunsWithFont(
const std::u16string& text,
const internal::TextRunHarfBuzz::FontParams& font_params,
std::vector<internal::TextRunHarfBuzz*>* in_out_runs,
std::vector<internal::TextRunHarfBuzz*>* sucessfully_shaped_runs =
nullptr);
void ItemizeAndShapeText(const std::u16string& text,
internal::TextRunList* out_run_list);
void EnsureLayoutRunList();
bool IsValidDisplayRange(Range display_range);
internal::TextRunList* GetRunList() override;
const internal::TextRunList* GetRunList() const override;
bool GetDecoratedTextForRange(const Range& range,
DecoratedText* decorated_text) override;
internal::TextRunList layout_run_list_;
std::unique_ptr<internal::TextRunList> display_run_list_;
bool update_layout_run_list_ : 1;
bool update_display_run_list_ : 1;
bool update_display_text_ : 1;
float device_scale_factor_ = 1.0f;
SizeF total_size_;
std::string locale_;
};
}
#endif