#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
#include <hb.h>
#include <unicode/uchar.h>
#include <unicode/uscript.h>
#include <algorithm>
#include <hb-cplusplus.hh>
#include <memory>
#include <utility>
#include "base/check_op.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_iterator.h"
#include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h"
#include "third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h"
#include "third_party/blink/renderer/platform/fonts/shaping/font_features.h"
#include "third_party/blink/renderer/platform/fonts/shaping/han_kerning.h"
#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
#include "third_party/blink/renderer/platform/fonts/small_caps_iterator.h"
#include "third_party/blink/renderer/platform/fonts/utf16_text_iterator.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
namespace {
constexpr hb_feature_t CreateFeature(char c1,
char c2,
char c3,
char c4,
uint32_t value = 0) { … }
#if EXPENSIVE_DCHECKS_ARE_ON()
void CheckShapeResultRange(const ShapeResult* result,
unsigned start,
unsigned end,
const String& text,
const Font* font) { … }
#endif
struct TrackEmoji { … };
void IdentifyBrokenEmoji(void* context,
unsigned character_index,
Glyph glyph,
gfx::Vector2dF,
float,
bool,
CanvasRotationInVertical,
const SimpleFontData*) { … }
struct EmojiCorrectness { … };
EmojiCorrectness ComputeBrokenEmojiPercentage(ShapeResult* shape_result,
unsigned start_index,
unsigned end_index) { … }
}
enum ReshapeQueueItemAction { … };
struct ReshapeQueueItem { … };
struct RangeContext { … };
struct BufferSlice { … };
namespace {
static inline hb_script_t ICUScriptToHBScript(UScriptCode script) { … }
inline float HarfBuzzPositionToFloat(hb_position_t value) { … }
void RoundHarfBuzzPosition(hb_position_t* value) { … }
void RoundHarfBuzzBufferPositions(hb_buffer_t* buffer) { … }
inline bool ShapeRange(hb_buffer_t* buffer,
const FontFeatures& font_features,
const SimpleFontData* current_font,
const UnicodeRangeSet* current_font_range_set,
UScriptCode current_run_script,
hb_direction_t direction,
hb_language_t language,
float specified_size) { … }
BufferSlice ComputeSlice(RangeContext* range_data,
const ReshapeQueueItem& current_queue_item,
const hb_glyph_info_t* glyph_info,
unsigned num_glyphs,
unsigned old_glyph_index,
unsigned new_glyph_index) { … }
bool IsLastFontToShape(HarfBuzzShaper::FallbackFontStage fallback_stage) { … }
bool StageNeedsQueueReset(HarfBuzzShaper::FallbackFontStage fallback_stage) { … }
HarfBuzzShaper::FallbackFontStage ChangeStageToLast(
HarfBuzzShaper::FallbackFontStage fallback_stage) { … }
HarfBuzzShaper::FallbackFontStage ChangeStageToVS(
HarfBuzzShaper::FallbackFontStage fallback_stage) { … }
void QueueCharacters(RangeContext* range_data,
const SimpleFontData* current_font,
bool& font_cycle_queued,
const BufferSlice& slice,
HarfBuzzShaper::FallbackFontStage font_stage) { … }
CanvasRotationInVertical CanvasRotationForRun(
FontOrientation font_orientation,
OrientationIterator::RenderOrientation render_orientation,
const FontDescription& font_description) { … }
}
inline void HarfBuzzShaper::CheckTextLen(unsigned start,
unsigned length) const { … }
inline void HarfBuzzShaper::CheckTextEnd(unsigned start, unsigned end) const { … }
void HarfBuzzShaper::CommitGlyphs(RangeContext* range_data,
const SimpleFontData* current_font,
UScriptCode current_run_script,
CanvasRotationInVertical canvas_rotation,
FallbackFontStage fallback_stage,
const BufferSlice& slice,
ShapeResult* shape_result) const { … }
void HarfBuzzShaper::ExtractShapeResults(
RangeContext* range_data,
bool& font_cycle_queued,
const ReshapeQueueItem& current_queue_item,
const SimpleFontData* current_font,
UScriptCode current_run_script,
CanvasRotationInVertical canvas_rotation,
FallbackFontStage& fallback_stage,
ShapeResult* shape_result) const { … }
bool HarfBuzzShaper::CollectFallbackHintChars(
const Deque<ReshapeQueueItem>& reshape_queue,
bool needs_hint_list,
HintCharList& hint) const { … }
namespace {
void SplitUntilNextCaseChange(
const String& text,
Deque<blink::ReshapeQueueItem>* queue,
blink::ReshapeQueueItem& current_queue_item,
SmallCapsIterator::SmallCapsBehavior& small_caps_behavior) { … }
class CapsFeatureSettingsScopedOverlay final { … };
CapsFeatureSettingsScopedOverlay::CapsFeatureSettingsScopedOverlay(
FontFeatures* features,
FontDescription::FontVariantCaps variant_caps)
: … { … }
void CapsFeatureSettingsScopedOverlay::OverlayCapsFeatures(
FontDescription::FontVariantCaps variant_caps) { … }
void CapsFeatureSettingsScopedOverlay::PrependCounting(
const hb_feature_t& feature) { … }
CapsFeatureSettingsScopedOverlay::~CapsFeatureSettingsScopedOverlay() { … }
}
void HarfBuzzShaper::ShapeSegment(
RangeContext* range_data,
const RunSegmenter::RunSegmenterRange& segment,
ShapeResult* result) const { … }
ShapeResult* HarfBuzzShaper::Shape(const Font* font,
TextDirection direction,
unsigned start,
unsigned end) const { … }
ShapeResult* HarfBuzzShaper::Shape(
const Font* font,
TextDirection direction,
unsigned start,
unsigned end,
const Vector<RunSegmenter::RunSegmenterRange>& ranges,
ShapeOptions options) const { … }
ShapeResult* HarfBuzzShaper::Shape(
const Font* font,
TextDirection direction,
unsigned start,
unsigned end,
const RunSegmenter::RunSegmenterRange pre_segmented,
ShapeOptions options) const { … }
ShapeResult* HarfBuzzShaper::Shape(const Font* font,
TextDirection direction) const { … }
void HarfBuzzShaper::GetGlyphData(const SimpleFontData& font_data,
const LayoutLocale& locale,
UScriptCode script,
bool is_horizontal,
GlyphDataList& glyphs) { … }
}