chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc

/*
 * Copyright (c) 2012 Google Inc. All rights reserved.
 * Copyright (C) 2013 BlackBerry Limited. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#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()
// Check if the ShapeResult has the specified range.
// |text| and |font| are only for logging.
void CheckShapeResultRange(const ShapeResult* result,
                           unsigned start,
                           unsigned end,
                           const String& text,
                           const Font* font) {}
#endif

struct TrackEmoji {};

// The algorithm is relying on the following assumption: If an emoji is shaped
// correctly it will present as only one glyph. This definitely holds for
// NotoColorEmoji. So if one sequence (which HarfBuzz groups as a cluster)
// presents as multiple glyphs, it means an emoji is rendered as sequence that
// the font did not understand and did not shape into only one glyph. If it
// renders as only one glyph but that glyph is .notdef/Tofu, it also means it's
// broken.  Due to the way flags work (pairs of regional indicators), broken
// flags cannot be correctly identified with this method - as each regional
// indicator will display as one emoji with Noto Color Emoji.
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) {}

}  // namespace

enum ReshapeQueueItemAction {};

struct ReshapeQueueItem {};

//
// Represents a context while shaping a range.
//
// Input-only data and objects whose pointers don't change are marked as
// `const`.
//
struct RangeContext {};

struct BufferSlice {};

namespace {

// A port of hb_icu_script_to_script because harfbuzz on CrOS is built
// without hb-icu. See http://crbug.com/356929
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) {}

}  // namespace

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() {}

}  // namespace

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) {}

}  // namespace blink