/src/mozilla-central/layout/base/nsBidi.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef nsBidi_h__ |
8 | | #define nsBidi_h__ |
9 | | |
10 | | #include "unicode/ubidi.h" |
11 | | #include "ICUUtils.h" |
12 | | #include "nsIFrame.h" // for nsBidiLevel/nsBidiDirection declarations |
13 | | |
14 | | // nsBidi implemented as a simple wrapper around the bidi reordering engine |
15 | | // from ICU. |
16 | | // We could eliminate this and let callers use the ICU functions directly |
17 | | // once we no longer care about building without ICU available. |
18 | | |
19 | | class nsBidi |
20 | | { |
21 | | public: |
22 | | /** @brief Default constructor. |
23 | | * |
24 | | * The nsBidi object is initially empty. It is assigned |
25 | | * the Bidi properties of a paragraph by <code>SetPara()</code>. |
26 | | */ |
27 | | nsBidi() |
28 | | { |
29 | | mBiDi = ubidi_open(); |
30 | | } |
31 | | |
32 | | /** @brief Destructor. */ |
33 | | ~nsBidi() |
34 | | { |
35 | | ubidi_close(mBiDi); |
36 | | } |
37 | | |
38 | | /** |
39 | | * Perform the Unicode Bidi algorithm. |
40 | | * |
41 | | * @param aText is a pointer to the single-paragraph text that the |
42 | | * Bidi algorithm will be performed on |
43 | | * (step (P1) of the algorithm is performed externally). |
44 | | * <strong>The text must be (at least) <code>aLength</code> long.</strong> |
45 | | * |
46 | | * @param aLength is the length of the text; if <code>aLength==-1</code> then |
47 | | * the text must be zero-terminated. |
48 | | * |
49 | | * @param aParaLevel specifies the default level for the paragraph; |
50 | | * it is typically 0 (LTR) or 1 (RTL). |
51 | | * If the function shall determine the paragraph level from the text, |
52 | | * then <code>aParaLevel</code> can be set to |
53 | | * either <code>NSBIDI_DEFAULT_LTR</code> |
54 | | * or <code>NSBIDI_DEFAULT_RTL</code>; |
55 | | * if there is no strongly typed character, then |
56 | | * the desired default is used (0 for LTR or 1 for RTL). |
57 | | * Any other value between 0 and <code>NSBIDI_MAX_EXPLICIT_LEVEL</code> |
58 | | * is also valid, with odd levels indicating RTL. |
59 | | */ |
60 | | nsresult SetPara(const char16_t* aText, int32_t aLength, |
61 | | nsBidiLevel aParaLevel) |
62 | 0 | { |
63 | 0 | UErrorCode error = U_ZERO_ERROR; |
64 | 0 | ubidi_setPara(mBiDi, reinterpret_cast<const UChar*>(aText), aLength, |
65 | 0 | aParaLevel, nullptr, &error); |
66 | 0 | return ICUUtils::UErrorToNsResult(error); |
67 | 0 | } |
68 | | |
69 | | /** |
70 | | * Get the directionality of the text. |
71 | | * |
72 | | * @param aDirection receives a <code>NSBIDI_XXX</code> value that indicates |
73 | | * if the entire text represented by this object is unidirectional, |
74 | | * and which direction, or if it is mixed-directional. |
75 | | * |
76 | | * @see nsBidiDirection |
77 | | */ |
78 | | nsBidiDirection GetDirection() |
79 | 0 | { |
80 | 0 | return nsBidiDirection(ubidi_getDirection(mBiDi)); |
81 | 0 | } |
82 | | |
83 | | /** |
84 | | * Get the paragraph level of the text. |
85 | | * |
86 | | * @param aParaLevel receives a <code>NSBIDI_XXX</code> value indicating |
87 | | * the paragraph level |
88 | | * |
89 | | * @see nsBidiLevel |
90 | | */ |
91 | | nsBidiLevel GetParaLevel() |
92 | 0 | { |
93 | 0 | return ubidi_getParaLevel(mBiDi); |
94 | 0 | } |
95 | | |
96 | | /** |
97 | | * Get a logical run. |
98 | | * This function returns information about a run and is used |
99 | | * to retrieve runs in logical order.<p> |
100 | | * This is especially useful for line-breaking on a paragraph. |
101 | | * <code>CountRuns</code> should be called before this. |
102 | | * before the runs are retrieved. |
103 | | * |
104 | | * @param aLogicalStart is the first character of the run. |
105 | | * |
106 | | * @param aLogicalLimit will receive the limit of the run. |
107 | | * The l-value that you point to here may be the |
108 | | * same expression (variable) as the one for |
109 | | * <code>aLogicalStart</code>. |
110 | | * This pointer cannot be <code>nullptr</code>. |
111 | | * |
112 | | * @param aLevel will receive the level of the run. |
113 | | * This pointer cannot be <code>nullptr</code>. |
114 | | */ |
115 | | void GetLogicalRun(int32_t aLogicalStart, |
116 | | int32_t* aLogicalLimit, nsBidiLevel* aLevel); |
117 | | |
118 | | /** |
119 | | * Get the number of runs. |
120 | | * This function may invoke the actual reordering on the |
121 | | * <code>nsBidi</code> object, after <code>SetPara</code> |
122 | | * may have resolved only the levels of the text. Therefore, |
123 | | * <code>CountRuns</code> may have to allocate memory, |
124 | | * and may fail doing so. |
125 | | * |
126 | | * @param aRunCount will receive the number of runs. |
127 | | */ |
128 | | nsresult CountRuns(int32_t* aRunCount); |
129 | | |
130 | | /** |
131 | | * Get one run's logical start, length, and directionality, |
132 | | * which can be 0 for LTR or 1 for RTL. |
133 | | * In an RTL run, the character at the logical start is |
134 | | * visually on the right of the displayed run. |
135 | | * The length is the number of characters in the run.<p> |
136 | | * <code>CountRuns</code> should be called |
137 | | * before the runs are retrieved. |
138 | | * |
139 | | * @param aRunIndex is the number of the run in visual order, in the |
140 | | * range <code>[0..CountRuns-1]</code>. |
141 | | * |
142 | | * @param aLogicalStart is the first logical character index in the text. |
143 | | * The pointer may be <code>nullptr</code> if this index is not needed. |
144 | | * |
145 | | * @param aLength is the number of characters (at least one) in the run. |
146 | | * The pointer may be <code>nullptr</code> if this is not needed. |
147 | | * |
148 | | * @returns the directionality of the run, |
149 | | * <code>NSBIDI_LTR==0</code> or <code>NSBIDI_RTL==1</code>, |
150 | | * never <code>NSBIDI_MIXED</code>. |
151 | | * |
152 | | * @see CountRuns<p> |
153 | | * |
154 | | * Example: |
155 | | * @code |
156 | | * int32_t i, count, logicalStart, visualIndex=0, length; |
157 | | * nsBidiDirection dir; |
158 | | * pBidi->CountRuns(&count); |
159 | | * for(i=0; i<count; ++i) { |
160 | | * dir = pBidi->GetVisualRun(i, &logicalStart, &length); |
161 | | * if(NSBIDI_LTR==dir) { |
162 | | * do { // LTR |
163 | | * show_char(text[logicalStart++], visualIndex++); |
164 | | * } while(--length>0); |
165 | | * } else { |
166 | | * logicalStart+=length; // logicalLimit |
167 | | * do { // RTL |
168 | | * show_char(text[--logicalStart], visualIndex++); |
169 | | * } while(--length>0); |
170 | | * } |
171 | | * } |
172 | | * @endcode |
173 | | * |
174 | | * Note that in right-to-left runs, code like this places |
175 | | * modifier letters before base characters and second surrogates |
176 | | * before first ones. |
177 | | */ |
178 | | nsBidiDirection GetVisualRun(int32_t aRunIndex, |
179 | | int32_t* aLogicalStart, int32_t* aLength) |
180 | 0 | { |
181 | 0 | return nsBidiDirection(ubidi_getVisualRun(mBiDi, aRunIndex, |
182 | 0 | aLogicalStart, aLength)); |
183 | 0 | } |
184 | | |
185 | | /** |
186 | | * This is a convenience function that does not use a nsBidi object. |
187 | | * It is intended to be used for when an application has determined the levels |
188 | | * of objects (character sequences) and just needs to have them reordered (L2). |
189 | | * This is equivalent to using <code>GetVisualMap</code> on a |
190 | | * <code>nsBidi</code> object. |
191 | | * |
192 | | * @param aLevels is an array with <code>aLength</code> levels that have been |
193 | | * determined by the application. |
194 | | * |
195 | | * @param aLength is the number of levels in the array, or, semantically, |
196 | | * the number of objects to be reordered. |
197 | | * It must be <code>aLength>0</code>. |
198 | | * |
199 | | * @param aIndexMap is a pointer to an array of <code>aLength</code> |
200 | | * indexes which will reflect the reordering of the characters. |
201 | | * The array does not need to be initialized.<p> |
202 | | * The index map will result in |
203 | | * <code>aIndexMap[aVisualIndex]==aLogicalIndex</code>. |
204 | | */ |
205 | | static void ReorderVisual(const nsBidiLevel* aLevels, int32_t aLength, |
206 | | int32_t* aIndexMap) |
207 | 0 | { |
208 | 0 | ubidi_reorderVisual(aLevels, aLength, aIndexMap); |
209 | 0 | } |
210 | | |
211 | | private: |
212 | | nsBidi(const nsBidi&) = delete; |
213 | | void operator=(const nsBidi&) = delete; |
214 | | |
215 | | UBiDi* mBiDi; |
216 | | // The two fields below are updated when CountRuns is called. |
217 | | const nsBidiLevel* mLevels = nullptr; |
218 | | int32_t mLength = 0; |
219 | | }; |
220 | | |
221 | | #endif // _nsBidi_h_ |