Upload upstream chromium 71.0.3578.0
[platform/framework/web/chromium-efl.git] / base / i18n / bidi_line_iterator.cc
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.
4
5 #include "base/i18n/bidi_line_iterator.h"
6
7 #include "base/logging.h"
8
9 namespace base {
10 namespace i18n {
11
12 namespace {
13
14 UBiDiLevel GetParagraphLevelForDirection(TextDirection direction) {
15   switch (direction) {
16     case UNKNOWN_DIRECTION:
17       return UBIDI_DEFAULT_LTR;
18       break;
19     case RIGHT_TO_LEFT:
20       return 1;  // Highest RTL level.
21       break;
22     case LEFT_TO_RIGHT:
23       return 0;  // Highest LTR level.
24       break;
25     default:
26       NOTREACHED();
27       return 0;
28   }
29 }
30
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
33 // behavior.
34 //
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
40   // optimization).
41   switch (c) {
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).
45     case '#':
46     case '&':
47     case '.':
48     case '/':
49     case ':':
50     case '=':
51     case '?':
52     case '@':
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;
60     default:
61       return U_BIDI_CLASS_DEFAULT;
62   }
63 }
64
65 }  // namespace
66
67 BiDiLineIterator::BiDiLineIterator() : bidi_(nullptr) {}
68
69 BiDiLineIterator::~BiDiLineIterator() {
70   if (bidi_) {
71     ubidi_close(bidi_);
72     bidi_ = nullptr;
73   }
74 }
75
76 bool BiDiLineIterator::Open(const string16& text,
77                             TextDirection direction,
78                             CustomBehavior behavior) {
79   DCHECK(!bidi_);
80   UErrorCode error = U_ZERO_ERROR;
81   bidi_ = ubidi_openSized(static_cast<int>(text.length()), 0, &error);
82   if (U_FAILURE(error))
83     return false;
84
85   if (behavior == CustomBehavior::AS_URL) {
86     ubidi_setClassCallback(bidi_, GetURLBiDiClassCallback, nullptr, nullptr,
87                            nullptr, &error);
88     if (U_FAILURE(error))
89       return false;
90   }
91
92   ubidi_setPara(bidi_, text.data(), static_cast<int>(text.length()),
93                 GetParagraphLevelForDirection(direction), nullptr, &error);
94   return (U_SUCCESS(error));
95 }
96
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;
102 }
103
104 UBiDiDirection BiDiLineIterator::GetVisualRun(int index,
105                                               int* start,
106                                               int* length) const {
107   DCHECK(bidi_ != nullptr);
108   return ubidi_getVisualRun(bidi_, index, start, length);
109 }
110
111 void BiDiLineIterator::GetLogicalRun(int start,
112                                      int* end,
113                                      UBiDiLevel* level) const {
114   DCHECK(bidi_ != nullptr);
115   ubidi_getLogicalRun(bidi_, start, end, level);
116 }
117
118 }  // namespace i18n
119 }  // namespace base