blob: fc40c73b1df57d4487b2490359d8aa8c5a682be2 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_BIDI_PARAGRAPH_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_BIDI_PARAGRAPH_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include <unicode/ubidi.h>
namespace blink {
class ComputedStyle;
// NGBidiParagraph resolves bidirectional runs in a paragraph using ICU BiDi.
// http://userguide.icu-project.org/transforms/bidi
//
// Given a string of a paragraph, it runs Unicode Bidirectional Algorithm in
// UAX#9 and create logical runs.
// http://unicode.org/reports/tr9/
// It can also create visual runs once lines breaks are determined.
class CORE_EXPORT NGBidiParagraph {
STACK_ALLOCATED();
public:
NGBidiParagraph() = default;
~NGBidiParagraph();
// Splits the given paragraph to bidi runs and resolves the bidi embedding
// level of each run.
// Returns false on failure. Nothing other than the destructor should be
// called.
bool SetParagraph(const String&, const ComputedStyle&);
bool SetParagraph(const String&,
base::Optional<TextDirection> base_direction);
// @return the entire text is unidirectional.
bool IsUnidirectional() const {
return ubidi_getDirection(ubidi_) != UBIDI_MIXED;
}
// The base direction (a.k.a. paragraph direction) of this block.
// This is determined by the 'direction' property of the block, or by the
// heuristic rules defined in UAX#9 if 'unicode-bidi: plaintext'.
TextDirection BaseDirection() const { return base_direction_; }
// Compute the base direction for a given string using the heuristic
// rules defined in UAX#9.
// This is generally determined by the first strong character.
// http://unicode.org/reports/tr9/#The_Paragraph_Level
static TextDirection BaseDirectionForString(const StringView&);
struct Run {
Run(unsigned start, unsigned end, UBiDiLevel level)
: start(start), end(end), level(level) {
DCHECK_GT(end, start);
}
unsigned Length() const { return end - start; }
TextDirection Direction() const { return DirectionFromLevel(level); }
bool operator==(const Run& other) const {
return start == other.start && end == other.end && level == other.level;
}
unsigned start;
unsigned end;
UBiDiLevel level;
};
using Runs = Vector<Run, 32>;
// Get a list of |Run| in the logical order (before bidi reorder.)
// |text| must be the same one as |SetParagraph|.
// This is higher-level API for |GetLogicalRun|.
void GetLogicalRuns(const String& text, Runs* runs) const;
// Returns the end offset of a logical run that starts from the |start|
// offset.
unsigned GetLogicalRun(unsigned start, UBiDiLevel*) const;
// Create a list of indices in the visual order.
// A wrapper for ICU |ubidi_reorderVisual()|.
static void IndicesInVisualOrder(
const Vector<UBiDiLevel, 32>& levels,
Vector<int32_t, 32>* indices_in_visual_order_out);
private:
UBiDi* ubidi_ = nullptr;
TextDirection base_direction_ = TextDirection::kLtr;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_BIDI_PARAGRAPH_H_