1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/i18n/bidi_line_iterator.h"
7 #include "base/logging.h"
14 UBiDiLevel GetParagraphLevelForDirection(TextDirection direction) {
16 case UNKNOWN_DIRECTION:
17 return UBIDI_DEFAULT_LTR;
20 return 1; // Highest RTL level.
23 return 0; // Highest LTR level.
31 // Overrides the default bidi class for a given character, for the custom
32 // "AS_URL" behavior. Returns U_BIDI_CLASS_DEFAULT to defer to the default ICU
35 // Matches the C callback interface of ICU's UBiDiClassCallback type (which is
36 // why there is an unused argument).
37 UCharDirection GetURLBiDiClassCallback(const void* /*unused*/, UChar32 c) {
38 // Note: Use a switch statement instead of strchr() to avoid iterating over a
39 // string for each character (the switch allows for much better compiler
42 // The set of characters that delimit URL components (separating the scheme,
43 // username, password, domain labels, host, path segments, query
44 // names/values and fragment).
53 // Treat all of these characters as strong LTR, which effectively
54 // surrounds all of the text components of a URL (e.g., the domain labels
55 // and path segments) in a left-to-right embedding. This ensures that the
56 // URL components read from left to right, regardless of any RTL
57 // characters. (Within each component, RTL sequences are rendered from
58 // right to left as expected.)
59 return U_LEFT_TO_RIGHT;
61 return U_BIDI_CLASS_DEFAULT;
67 BiDiLineIterator::BiDiLineIterator() : bidi_(nullptr) {}
69 BiDiLineIterator::~BiDiLineIterator() {
76 bool BiDiLineIterator::Open(const string16& text,
77 TextDirection direction,
78 CustomBehavior behavior) {
80 UErrorCode error = U_ZERO_ERROR;
81 bidi_ = ubidi_openSized(static_cast<int>(text.length()), 0, &error);
85 if (behavior == CustomBehavior::AS_URL) {
86 ubidi_setClassCallback(bidi_, GetURLBiDiClassCallback, nullptr, nullptr,
92 ubidi_setPara(bidi_, text.data(), static_cast<int>(text.length()),
93 GetParagraphLevelForDirection(direction), nullptr, &error);
94 return (U_SUCCESS(error));
97 int BiDiLineIterator::CountRuns() const {
98 DCHECK(bidi_ != nullptr);
99 UErrorCode error = U_ZERO_ERROR;
100 const int runs = ubidi_countRuns(bidi_, &error);
101 return U_SUCCESS(error) ? runs : 0;
104 UBiDiDirection BiDiLineIterator::GetVisualRun(int index,
107 DCHECK(bidi_ != nullptr);
108 return ubidi_getVisualRun(bidi_, index, start, length);
111 void BiDiLineIterator::GetLogicalRun(int start,
113 UBiDiLevel* level) const {
114 DCHECK(bidi_ != nullptr);
115 ubidi_getLogicalRun(bidi_, start, end, level);