1 // Copyright 2014 PDFium 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/include/fxcrt/fx_ucd.h"
8 #include "fx_arabic.h"
9
10 namespace {
11
12 const FX_ARBFORMTABLE g_FX_ArabicFormTables[] = {
13 {0xFE81, 0xFE82, 0xFE81, 0xFE82},
14 {0xFE83, 0xFE84, 0xFE83, 0xFE84},
15 {0xFE85, 0xFE86, 0xFE85, 0xFE86},
16 {0xFE87, 0xFE88, 0xFE87, 0xFE88},
17 {0xFE89, 0xFE8A, 0xFE8B, 0xFE8C},
18 {0xFE8D, 0xFE8E, 0xFE8D, 0xFE8E},
19 {0xFE8F, 0xFE90, 0xFE91, 0xFE92},
20 {0xFE93, 0xFE94, 0xFE93, 0xFE94},
21 {0xFE95, 0xFE96, 0xFE97, 0xFE98},
22 {0xFE99, 0xFE9A, 0xFE9B, 0xFE9C},
23 {0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0},
24 {0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4},
25 {0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8},
26 {0xFEA9, 0xFEAA, 0xFEA9, 0xFEAA},
27 {0xFEAB, 0xFEAC, 0xFEAB, 0xFEAC},
28 {0xFEAD, 0xFEAE, 0xFEAD, 0xFEAE},
29 {0xFEAF, 0xFEB0, 0xFEAF, 0xFEB0},
30 {0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4},
31 {0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8},
32 {0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC},
33 {0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0},
34 {0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4},
35 {0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8},
36 {0xFEC9, 0xFECA, 0xFECB, 0xFECC},
37 {0xFECD, 0xFECE, 0xFECF, 0xFED0},
38 {0x063B, 0x063B, 0x063B, 0x063B},
39 {0x063C, 0x063C, 0x063C, 0x063C},
40 {0x063D, 0x063D, 0x063D, 0x063D},
41 {0x063E, 0x063E, 0x063E, 0x063E},
42 {0x063F, 0x063F, 0x063F, 0x063F},
43 {0x0640, 0x0640, 0x0640, 0x0640},
44 {0xFED1, 0xFED2, 0xFED3, 0xFED4},
45 {0xFED5, 0xFED6, 0xFED7, 0xFED8},
46 {0xFED9, 0xFEDA, 0xFEDB, 0xFEDC},
47 {0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0},
48 {0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4},
49 {0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8},
50 {0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC},
51 {0xFEED, 0xFEEE, 0xFEED, 0xFEEE},
52 {0xFEEF, 0xFEF0, 0xFBFE, 0xFBFF},
53 {0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4},
54 {0x064B, 0x064B, 0x064B, 0x064B},
55 {0x064C, 0x064C, 0x064C, 0x064C},
56 {0x064D, 0x064D, 0x064D, 0x064D},
57 {0x064E, 0x064E, 0x064E, 0x064E},
58 {0x064F, 0x064F, 0x064F, 0x064F},
59 {0x0650, 0x0650, 0x0650, 0x0650},
60 {0x0651, 0x0651, 0x0651, 0x0651},
61 {0x0652, 0x0652, 0x0652, 0x0652},
62 {0x0653, 0x0653, 0x0653, 0x0653},
63 {0x0654, 0x0654, 0x0654, 0x0654},
64 {0x0655, 0x0655, 0x0655, 0x0655},
65 {0x0656, 0x0656, 0x0656, 0x0656},
66 {0x0657, 0x0657, 0x0657, 0x0657},
67 {0x0658, 0x0658, 0x0658, 0x0658},
68 {0x0659, 0x0659, 0x0659, 0x0659},
69 {0x065A, 0x065A, 0x065A, 0x065A},
70 {0x065B, 0x065B, 0x065B, 0x065B},
71 {0x065C, 0x065C, 0x065C, 0x065C},
72 {0x065D, 0x065D, 0x065D, 0x065D},
73 {0x065E, 0x065E, 0x065E, 0x065E},
74 {0x065F, 0x065F, 0x065F, 0x065F},
75 {0x0660, 0x0660, 0x0660, 0x0660},
76 {0x0661, 0x0661, 0x0661, 0x0661},
77 {0x0662, 0x0662, 0x0662, 0x0662},
78 {0x0663, 0x0663, 0x0663, 0x0663},
79 {0x0664, 0x0664, 0x0664, 0x0664},
80 {0x0665, 0x0665, 0x0665, 0x0665},
81 {0x0666, 0x0666, 0x0666, 0x0666},
82 {0x0667, 0x0667, 0x0667, 0x0667},
83 {0x0668, 0x0668, 0x0668, 0x0668},
84 {0x0669, 0x0669, 0x0669, 0x0669},
85 {0x066A, 0x066A, 0x066A, 0x066A},
86 {0x066B, 0x066B, 0x066B, 0x066B},
87 {0x066C, 0x066C, 0x066C, 0x066C},
88 {0x066D, 0x066D, 0x066D, 0x066D},
89 {0x066E, 0x066E, 0x066E, 0x066E},
90 {0x066F, 0x066F, 0x066F, 0x066F},
91 {0x0670, 0x0670, 0x0670, 0x0670},
92 {0xFB50, 0xFB51, 0xFB50, 0xFB51},
93 {0x0672, 0x0672, 0x0672, 0x0672},
94 {0x0673, 0x0673, 0x0673, 0x0673},
95 {0x0674, 0x0674, 0x0674, 0x0674},
96 {0x0675, 0x0675, 0x0675, 0x0675},
97 {0x0676, 0x0676, 0x0676, 0x0676},
98 {0x0677, 0x0677, 0x0677, 0x0677},
99 {0x0678, 0x0678, 0x0678, 0x0678},
100 {0xFB66, 0xFB67, 0xFB68, 0xFB69},
101 {0xFB5E, 0xFB5F, 0xFB60, 0xFB61},
102 {0xFB52, 0xFB53, 0xFB54, 0xFB55},
103 {0x067C, 0x067C, 0x067C, 0x067C},
104 {0x067D, 0x067D, 0x067D, 0x067D},
105 {0xFB56, 0xFB57, 0xFB58, 0xFB59},
106 {0xFB62, 0xFB63, 0xFB64, 0xFB65},
107 {0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D},
108 {0x0681, 0x0681, 0x0681, 0x0681},
109 {0x0682, 0x0682, 0x0682, 0x0682},
110 {0xFB76, 0xFB77, 0xFB78, 0xFB79},
111 {0xFB72, 0xFB73, 0xFB74, 0xFB75},
112 {0x0685, 0x0685, 0x0685, 0x0685},
113 {0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D},
114 {0xFB7E, 0xFB7F, 0xFB80, 0xFB81},
115 {0xFB88, 0xFB89, 0xFB88, 0xFB89},
116 {0x0689, 0x0689, 0x0689, 0x0689},
117 {0x068A, 0x068A, 0x068A, 0x068A},
118 {0x068B, 0x068B, 0x068B, 0x068B},
119 {0xFB84, 0xFB85, 0xFB84, 0xFB85},
120 {0xFB82, 0xFB83, 0xFB82, 0xFB83},
121 {0xFB86, 0xFB87, 0xFB86, 0xFB87},
122 {0x068F, 0x068F, 0x068F, 0x068F},
123 {0x0690, 0x0690, 0x0690, 0x0690},
124 {0xFB8C, 0xFB8D, 0xFB8C, 0xFB8D},
125 {0x0692, 0x0692, 0x0692, 0x0692},
126 {0x0693, 0x0693, 0x0693, 0x0693},
127 {0x0694, 0x0694, 0x0694, 0x0694},
128 {0x0695, 0x0695, 0x0695, 0x0695},
129 {0x0696, 0x0696, 0x0696, 0x0696},
130 {0x0697, 0x0697, 0x0697, 0x0697},
131 {0xFB8A, 0xFB8B, 0xFB8A, 0xFB8B},
132 {0x0699, 0x0699, 0x0699, 0x0699},
133 {0x069A, 0x069A, 0x069A, 0x069A},
134 {0x069B, 0x069B, 0x069B, 0x069B},
135 {0x069C, 0x069C, 0x069C, 0x069C},
136 {0x069D, 0x069D, 0x069D, 0x069D},
137 {0x069E, 0x069E, 0x069E, 0x069E},
138 {0x069F, 0x069F, 0x069F, 0x069F},
139 {0x06A0, 0x06A0, 0x06A0, 0x06A0},
140 {0x06A1, 0x06A1, 0x06A1, 0x06A1},
141 {0x06A2, 0x06A2, 0x06A2, 0x06A2},
142 {0x06A3, 0x06A3, 0x06A3, 0x06A3},
143 {0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D},
144 {0x06A5, 0x06A5, 0x06A5, 0x06A5},
145 {0xFB6E, 0xFB6F, 0xFB70, 0xFB71},
146 {0x06A7, 0x06A7, 0x06A7, 0x06A7},
147 {0x06A8, 0x06A8, 0x06A8, 0x06A8},
148 {0xFB8E, 0xFB8F, 0xFB90, 0xFB91},
149 {0x06AA, 0x06AA, 0x06AA, 0x06AA},
150 {0x06AB, 0x06AB, 0x06AB, 0x06AB},
151 {0x06AC, 0x06AC, 0x06AC, 0x06AC},
152 {0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6},
153 {0x06AE, 0x06AE, 0x06AE, 0x06AE},
154 {0xFB92, 0xFB93, 0xFB94, 0xFB95},
155 {0x06B0, 0x06B0, 0x06B0, 0x06B0},
156 {0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D},
157 {0x06B2, 0x06B2, 0x06B2, 0x06B2},
158 {0xFB96, 0xFB97, 0xFB98, 0xFB99},
159 {0x06B4, 0x06B4, 0x06B4, 0x06B4},
160 {0x06B5, 0x06B5, 0x06B5, 0x06B5},
161 {0x06B6, 0x06B6, 0x06B6, 0x06B6},
162 {0x06B7, 0x06B7, 0x06B7, 0x06B7},
163 {0x06B8, 0x06B8, 0x06B8, 0x06B8},
164 {0x06B9, 0x06B9, 0x06B9, 0x06B9},
165 {0xFB9E, 0xFB9F, 0xFBE8, 0xFBE9},
166 {0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3},
167 {0x06BC, 0x06BC, 0x06BC, 0x06BC},
168 {0x06BD, 0x06BD, 0x06BD, 0x06BD},
169 {0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD},
170 {0x06BF, 0x06BF, 0x06BF, 0x06BF},
171 {0xFBA4, 0xFBA5, 0xFBA4, 0xFBA5},
172 {0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9},
173 {0x06C2, 0x06C2, 0x06C2, 0x06C2},
174 {0x06C3, 0x06C3, 0x06C3, 0x06C3},
175 {0x06C4, 0x06C4, 0x06C4, 0x06C4},
176 {0xFBE0, 0xFBE1, 0xFBE0, 0xFBE1},
177 {0xFBD9, 0xFBDA, 0xFBD9, 0xFBDA},
178 {0xFBD7, 0xFBD8, 0xFBD7, 0xFBD8},
179 {0xFBDB, 0xFBDC, 0xFBDB, 0xFBDC},
180 {0xFBE2, 0xFBE3, 0xFBE2, 0xFBE3},
181 {0x06CA, 0x06CA, 0x06CA, 0x06CA},
182 {0xFBDE, 0xFBDF, 0xFBDE, 0xFBDF},
183 {0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF},
184 {0x06CD, 0x06CD, 0x06CD, 0x06CD},
185 {0x06CE, 0x06CE, 0x06CE, 0x06CE},
186 {0x06CF, 0x06CF, 0x06CF, 0x06CF},
187 {0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7},
188 {0x06D1, 0x06D1, 0x06D1, 0x06D1},
189 {0xFBAE, 0xFBAF, 0xFBAE, 0xFBAF},
190 {0xFBB0, 0xFBB1, 0xFBB0, 0xFBB1},
191 {0x06D4, 0x06D4, 0x06D4, 0x06D4},
192 {0x06D5, 0x06D5, 0x06D5, 0x06D5},
193 };
194
195 const FX_ARAALEF gs_FX_AlefTable[] = {
196 {0x0622, 0xFEF5},
197 {0x0623, 0xFEF7},
198 {0x0625, 0xFEF9},
199 {0x0627, 0xFEFB},
200 };
201
202 const FX_ARASHADDA gs_FX_ShaddaTable[] = {
203 {0x064C, 0xFC5E},
204 {0x064D, 0xFC5F},
205 {0x064E, 0xFC60},
206 {0x064F, 0xFC61},
207 {0x0650, 0xFC62},
208 };
209
210 } // namespace
211
FX_GetArabicFormTable(FX_WCHAR unicode)212 const FX_ARBFORMTABLE* FX_GetArabicFormTable(FX_WCHAR unicode) {
213 if (unicode < 0x622 || unicode > 0x6d5) {
214 return NULL;
215 }
216 return g_FX_ArabicFormTables + unicode - 0x622;
217 }
FX_GetArabicFromAlefTable(FX_WCHAR alef)218 FX_WCHAR FX_GetArabicFromAlefTable(FX_WCHAR alef) {
219 static const int32_t s_iAlefCount =
220 sizeof(gs_FX_AlefTable) / sizeof(FX_ARAALEF);
221 for (int32_t iStart = 0; iStart < s_iAlefCount; iStart++) {
222 const FX_ARAALEF& v = gs_FX_AlefTable[iStart];
223 if (v.wAlef == alef) {
224 return v.wIsolated;
225 }
226 }
227 return alef;
228 }
FX_GetArabicFromShaddaTable(FX_WCHAR shadda)229 FX_WCHAR FX_GetArabicFromShaddaTable(FX_WCHAR shadda) {
230 static const int32_t s_iShaddaCount =
231 sizeof(gs_FX_ShaddaTable) / sizeof(FX_ARASHADDA);
232 for (int32_t iStart = 0; iStart < s_iShaddaCount; iStart++) {
233 const FX_ARASHADDA& v = gs_FX_ShaddaTable[iStart];
234 if (v.wShadda == shadda) {
235 return v.wIsolated;
236 }
237 }
238 return shadda;
239 }
240
Create()241 IFX_ArabicChar* IFX_ArabicChar::Create() {
242 return new CFX_ArabicChar;
243 }
IsArabicChar(FX_WCHAR wch) const244 FX_BOOL CFX_ArabicChar::IsArabicChar(FX_WCHAR wch) const {
245 FX_DWORD dwRet =
246 kTextLayoutCodeProperties[(FX_WORD)wch] & FX_CHARTYPEBITSMASK;
247 return dwRet >= FX_CHARTYPE_ArabicAlef;
248 }
IsArabicFormChar(FX_WCHAR wch) const249 FX_BOOL CFX_ArabicChar::IsArabicFormChar(FX_WCHAR wch) const {
250 return (kTextLayoutCodeProperties[(FX_WORD)wch] & FX_CHARTYPEBITSMASK) ==
251 FX_CHARTYPE_ArabicForm;
252 }
GetFormChar(FX_WCHAR wch,FX_WCHAR prev,FX_WCHAR next) const253 FX_WCHAR CFX_ArabicChar::GetFormChar(FX_WCHAR wch,
254 FX_WCHAR prev,
255 FX_WCHAR next) const {
256 CFX_Char c(wch, kTextLayoutCodeProperties[(FX_WORD)wch]);
257 CFX_Char p(prev, kTextLayoutCodeProperties[(FX_WORD)prev]);
258 CFX_Char n(next, kTextLayoutCodeProperties[(FX_WORD)next]);
259 return GetFormChar(&c, &p, &n);
260 }
GetFormChar(const CFX_Char * cur,const CFX_Char * prev,const CFX_Char * next) const261 FX_WCHAR CFX_ArabicChar::GetFormChar(const CFX_Char* cur,
262 const CFX_Char* prev,
263 const CFX_Char* next) const {
264 FX_CHARTYPE eCur;
265 FX_WCHAR wCur;
266 const FX_ARBFORMTABLE* ft = ParseChar(cur, wCur, eCur);
267 if (eCur < FX_CHARTYPE_ArabicAlef || eCur >= FX_CHARTYPE_ArabicNormal) {
268 return wCur;
269 }
270 FX_CHARTYPE ePrev;
271 FX_WCHAR wPrev;
272 ParseChar(prev, wPrev, ePrev);
273 if (wPrev == 0x0644 && eCur == FX_CHARTYPE_ArabicAlef) {
274 return 0xFEFF;
275 }
276 FX_CHARTYPE eNext;
277 FX_WCHAR wNext;
278 ParseChar(next, wNext, eNext);
279 FX_BOOL bAlef = (eNext == FX_CHARTYPE_ArabicAlef && wCur == 0x644);
280 if (ePrev < FX_CHARTYPE_ArabicAlef) {
281 if (bAlef) {
282 return FX_GetArabicFromAlefTable(wNext);
283 } else {
284 return (eNext < FX_CHARTYPE_ArabicAlef) ? ft->wIsolated : ft->wInitial;
285 }
286 } else {
287 if (bAlef) {
288 wCur = FX_GetArabicFromAlefTable(wNext);
289 return (ePrev != FX_CHARTYPE_ArabicDistortion) ? wCur : ++wCur;
290 } else if (ePrev == FX_CHARTYPE_ArabicAlef ||
291 ePrev == FX_CHARTYPE_ArabicSpecial) {
292 return (eNext < FX_CHARTYPE_ArabicAlef) ? ft->wIsolated : ft->wInitial;
293 } else {
294 return (eNext < FX_CHARTYPE_ArabicAlef) ? ft->wFinal : ft->wMedial;
295 }
296 }
297 }
ParseChar(const CFX_Char * pTC,FX_WCHAR & wChar,FX_CHARTYPE & eType) const298 const FX_ARBFORMTABLE* CFX_ArabicChar::ParseChar(const CFX_Char* pTC,
299 FX_WCHAR& wChar,
300 FX_CHARTYPE& eType) const {
301 if (pTC == NULL) {
302 eType = FX_CHARTYPE_Unknown;
303 wChar = 0xFEFF;
304 return NULL;
305 }
306 eType = (FX_CHARTYPE)pTC->GetCharType();
307 wChar = (FX_WCHAR)pTC->m_wCharCode;
308 const FX_ARBFORMTABLE* pFT = FX_GetArabicFormTable(wChar);
309 if (pFT == NULL || eType >= FX_CHARTYPE_ArabicNormal) {
310 eType = FX_CHARTYPE_Unknown;
311 }
312 return pFT;
313 }
FX_BidiReverseString(CFX_WideString & wsText,int32_t iStart,int32_t iCount)314 void FX_BidiReverseString(CFX_WideString& wsText,
315 int32_t iStart,
316 int32_t iCount) {
317 FXSYS_assert(iStart > -1 && iStart < wsText.GetLength());
318 FXSYS_assert(iCount >= 0 && iStart + iCount <= wsText.GetLength());
319 FX_WCHAR wch;
320 FX_WCHAR* pStart = (FX_WCHAR*)(const FX_WCHAR*)wsText;
321 pStart += iStart;
322 FX_WCHAR* pEnd = pStart + iCount - 1;
323 while (pStart < pEnd) {
324 wch = *pStart;
325 *pStart++ = *pEnd;
326 *pEnd-- = wch;
327 }
328 }
FX_BidiSetDeferredRun(CFX_Int32Array & values,int32_t iStart,int32_t iCount,int32_t iValue)329 void FX_BidiSetDeferredRun(CFX_Int32Array& values,
330 int32_t iStart,
331 int32_t iCount,
332 int32_t iValue) {
333 FXSYS_assert(iStart > -1 && iStart <= values.GetSize());
334 FXSYS_assert(iStart - iCount > -1);
335 for (int32_t i = iStart - 1; i >= iStart - iCount; i--) {
336 values.SetAt(i, iValue);
337 }
338 }
339 const int32_t gc_FX_BidiNTypes[] = {
340 FX_BIDICLASS_N, FX_BIDICLASS_L, FX_BIDICLASS_R, FX_BIDICLASS_AN,
341 FX_BIDICLASS_EN, FX_BIDICLASS_AL, FX_BIDICLASS_NSM, FX_BIDICLASS_CS,
342 FX_BIDICLASS_ES, FX_BIDICLASS_ET, FX_BIDICLASS_BN, FX_BIDICLASS_BN,
343 FX_BIDICLASS_N, FX_BIDICLASS_B, FX_BIDICLASS_RLO, FX_BIDICLASS_RLE,
344 FX_BIDICLASS_LRO, FX_BIDICLASS_LRE, FX_BIDICLASS_PDF, FX_BIDICLASS_ON,
345 };
FX_BidiClassify(const CFX_WideString & wsText,CFX_Int32Array & classes,FX_BOOL bWS)346 void FX_BidiClassify(const CFX_WideString& wsText,
347 CFX_Int32Array& classes,
348 FX_BOOL bWS) {
349 FXSYS_assert(wsText.GetLength() == classes.GetSize());
350 int32_t iCount = wsText.GetLength();
351 const FX_WCHAR* pwsStart = (const FX_WCHAR*)wsText;
352 FX_WCHAR wch;
353 int32_t iCls;
354 if (bWS) {
355 for (int32_t i = 0; i < iCount; i++) {
356 wch = *pwsStart++;
357 iCls =
358 ((kTextLayoutCodeProperties[(FX_WORD)wch] & FX_BIDICLASSBITSMASK) >>
359 FX_BIDICLASSBITS);
360 classes.SetAt(i, iCls);
361 }
362 } else {
363 for (int32_t i = 0; i < iCount; i++) {
364 wch = *pwsStart++;
365 iCls =
366 ((kTextLayoutCodeProperties[(FX_WORD)wch] & FX_BIDICLASSBITSMASK) >>
367 FX_BIDICLASSBITS);
368 classes.SetAt(i, gc_FX_BidiNTypes[iCls]);
369 }
370 }
371 }
FX_BidiResolveExplicit(int32_t iBaseLevel,int32_t iDirection,CFX_Int32Array & classes,CFX_Int32Array & levels,int32_t iStart,int32_t iCount,int32_t iNest)372 int32_t FX_BidiResolveExplicit(int32_t iBaseLevel,
373 int32_t iDirection,
374 CFX_Int32Array& classes,
375 CFX_Int32Array& levels,
376 int32_t iStart,
377 int32_t iCount,
378 int32_t iNest) {
379 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL && iNest >= 0);
380 FXSYS_assert(classes.GetSize() == levels.GetSize());
381 FXSYS_assert(iStart >= 0 && iStart < classes.GetSize());
382 FXSYS_assert(iCount >= 0 && iStart + iCount <= classes.GetSize());
383 if (iCount < 1) {
384 return 0;
385 }
386 #if 0
387 int32_t iLastNest = iNest;
388 #endif
389 int32_t iSize = classes.GetSize();
390 int32_t i = iStart, iCur, iCls;
391 for (; i < iSize && iCount > 0; i++, iCount--) {
392 iCur = iCls = classes.GetAt(i);
393 #if 0
394 switch (iCls) {
395 case FX_BIDICLASS_LRO:
396 case FX_BIDICLASS_LRE:
397 classes.SetAt(i, FX_BIDICLASS_BN);
398 iCls = FX_BIDICLASS_BN;
399 iNest ++;
400 if (FX_BidiGreaterEven(iBaseLevel) <= MAX_LEVEL) {
401 int32_t iLevel = FX_BidiGreaterEven(iBaseLevel);
402 levels.SetAt(i, iLevel);
403 i += FX_BidiResolveExplicit(iLevel,
404 (iCls == FX_BIDICLASS_LRE ? FX_BIDICLASS_N : FX_BIDICLASS_L),
405 classes,
406 levels,
407 i + 1,
408 iCount - 1,
409 iNest);
410 iNest --;
411 continue;
412 }
413 break;
414 case FX_BIDICLASS_RLO:
415 case FX_BIDICLASS_RLE:
416 classes.SetAt(i, FX_BIDICLASS_BN);
417 iCls = FX_BIDICLASS_BN;
418 iNest ++;
419 if (FX_BidiGreaterOdd(iBaseLevel) <= MAX_LEVEL) {
420 int32_t iLevel = FX_BidiGreaterOdd(iBaseLevel);
421 levels.SetAt(i, iLevel);
422 i += FX_BidiResolveExplicit(iLevel,
423 (iCls == FX_BIDICLASS_RLE ? FX_BIDICLASS_N : FX_BIDICLASS_R),
424 classes,
425 levels,
426 i + 1,
427 iCount - 1,
428 iNest);
429 iNest --;
430 continue;
431 }
432 break;
433 case FX_BIDICLASS_PDF:
434 classes.SetAt(i, FX_BIDICLASS_BN);
435 iCls = FX_BIDICLASS_BN;
436 if (iNest) {
437 if (iLastNest < iNest) {
438 iNest --;
439 } else {
440 iSize = i;
441 }
442 }
443 break;
444 }
445 iCur = iCls;
446 #endif
447 if (iDirection != FX_BIDICLASS_N) {
448 iCls = iDirection;
449 }
450 if (iCur != FX_BIDICLASS_BN) {
451 classes.SetAt(i, iCls);
452 }
453 levels.SetAt(i, iBaseLevel);
454 }
455 return i - iStart;
456 }
457 const int32_t gc_FX_BidiWeakStates[][10] = {
458 {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSxa,
459 FX_BWSao, FX_BWSao, FX_BWSao},
460 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSxr,
461 FX_BWSro, FX_BWSro, FX_BWSrt},
462 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSxl,
463 FX_BWSlo, FX_BWSlo, FX_BWSlt},
464 {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
465 FX_BWSao, FX_BWSao, FX_BWSao},
466 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
467 FX_BWSro, FX_BWSro, FX_BWSrt},
468 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
469 FX_BWSlo, FX_BWSlo, FX_BWSlt},
470 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSrt,
471 FX_BWSro, FX_BWSro, FX_BWSrt},
472 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlt,
473 FX_BWSlo, FX_BWSlo, FX_BWSlt},
474 {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWScn,
475 FX_BWSac, FX_BWSao, FX_BWSao},
476 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSra,
477 FX_BWSrc, FX_BWSro, FX_BWSrt},
478 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSre,
479 FX_BWSrs, FX_BWSrs, FX_BWSret},
480 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSla,
481 FX_BWSlc, FX_BWSlo, FX_BWSlt},
482 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSle,
483 FX_BWSls, FX_BWSls, FX_BWSlet},
484 {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
485 FX_BWSao, FX_BWSao, FX_BWSao},
486 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
487 FX_BWSro, FX_BWSro, FX_BWSrt},
488 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
489 FX_BWSro, FX_BWSro, FX_BWSrt},
490 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
491 FX_BWSlo, FX_BWSlo, FX_BWSlt},
492 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
493 FX_BWSlo, FX_BWSlo, FX_BWSlt},
494 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSret,
495 FX_BWSro, FX_BWSro, FX_BWSret},
496 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlet,
497 FX_BWSlo, FX_BWSlo, FX_BWSlet},
498 };
499 const int32_t gc_FX_BidiWeakActions[][10] = {
500 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
501 FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
502 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
503 FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
504 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
505 FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
506 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
507 FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
508 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
509 FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
510 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
511 FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
512 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
513 FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
514 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
515 FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
516 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
517 FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxxN},
518 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
519 FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
520 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
521 FX_BWAxxE, FX_BWAxIx, FX_BWAxIx, FX_BWAxxE},
522 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
523 FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
524 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
525 FX_BWAxxL, FX_BWAxIx, FX_BWAxIx, FX_BWAxxL},
526 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWAAxA, FX_BWANxR,
527 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANxN},
528 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxE, FX_BWANxR,
529 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
530 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
531 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
532 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxL, FX_BWANxR,
533 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
534 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
535 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
536 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
537 FX_BWAxxE, FX_BWAxxN, FX_BWAxxN, FX_BWAxxE},
538 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
539 FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxxL},
540 };
FX_BidiResolveWeak(int32_t iBaseLevel,CFX_Int32Array & classes,CFX_Int32Array & levels)541 void FX_BidiResolveWeak(int32_t iBaseLevel,
542 CFX_Int32Array& classes,
543 CFX_Int32Array& levels) {
544 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
545 FXSYS_assert(classes.GetSize() == levels.GetSize());
546 int32_t iSize = classes.GetSize();
547 if (iSize < 1) {
548 return;
549 }
550 iSize--;
551 int32_t iLevelCur = iBaseLevel;
552 int32_t iState = FX_IsOdd(iBaseLevel) ? FX_BWSxr : FX_BWSxl;
553 int32_t i = 0, iCount = 0, iClsCur, iClsRun, iClsNew, iAction;
554 for (; i <= iSize; i++) {
555 iClsCur = classes.GetAt(i);
556 #if 0
557 if (iClsCur == FX_BIDICLASS_BN) {
558 levels.SetAt(i, iLevelCur);
559 if (i == iSize && iLevelCur != iBaseLevel) {
560 iClsCur = FX_BidiDirection(iLevelCur);
561 classes.SetAt(i, iClsCur);
562 } else if (i < iSize) {
563 int32_t iLevelNext, iLevelNew;
564 iClsNew = classes.GetAt(i + 1);
565 iLevelNext = levels.GetAt(i + 1);
566 if (iClsNew != FX_BIDICLASS_BN && iLevelCur != iLevelNext) {
567 iLevelNew = iLevelNext;
568 if (iLevelCur > iLevelNew) {
569 iLevelNew = iLevelCur;
570 }
571 levels.SetAt(i, iLevelNew);
572 iClsCur = FX_BidiDirection(iLevelNew);
573 classes.SetAt(i, iClsCur);
574 iLevelCur = iLevelNext;
575 } else {
576 if (iCount) {
577 iCount ++;
578 }
579 continue;
580 }
581 } else {
582 if (iCount) {
583 iCount ++;
584 }
585 continue;
586 }
587 }
588 #endif
589 FXSYS_assert(iClsCur <= FX_BIDICLASS_BN);
590 iAction = gc_FX_BidiWeakActions[iState][iClsCur];
591 iClsRun = FX_BidiGetDeferredType(iAction);
592 if (iClsRun != FX_BIDIWEAKACTION_XX && iCount > 0) {
593 FX_BidiSetDeferredRun(classes, i, iCount, iClsRun);
594 iCount = 0;
595 }
596 iClsNew = FX_BidiGetResolvedType(iAction);
597 if (iClsNew != FX_BIDIWEAKACTION_XX) {
598 classes.SetAt(i, iClsNew);
599 }
600 if (FX_BIDIWEAKACTION_IX & iAction) {
601 iCount++;
602 }
603 iState = gc_FX_BidiWeakStates[iState][iClsCur];
604 }
605 iClsCur = FX_BidiDirection(iLevelCur);
606 iClsRun = FX_BidiGetDeferredType(gc_FX_BidiWeakActions[iState][iClsCur]);
607 if (iClsRun != FX_BIDIWEAKACTION_XX && iCount > 0) {
608 FX_BidiSetDeferredRun(classes, i, iCount, iClsRun);
609 }
610 }
611 const int32_t gc_FX_BidiNeutralStates[][5] = {
612 {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
613 {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
614 {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
615 {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
616 {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
617 {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
618 };
619 const int32_t gc_FX_BidiNeutralActions[][5] = {
620 {FX_BNAIn, 0, 0, 0, 0},
621 {FX_BNAIn, 0, 0, 0, FX_BCL},
622 {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNARn},
623 {FX_BNAIn, FX_BNALn, FX_BNAEn, FX_BNAEn, FX_BNALnL},
624 {FX_BNAIn, 0, 0, 0, FX_BCL},
625 {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNAEn},
626 };
FX_BidiGetDeferredNeutrals(int32_t iAction,int32_t iLevel)627 int32_t FX_BidiGetDeferredNeutrals(int32_t iAction, int32_t iLevel) {
628 iAction = (iAction >> 4) & 0xF;
629 if (iAction == (FX_BIDINEUTRALACTION_En >> 4)) {
630 return FX_BidiDirection(iLevel);
631 } else {
632 return iAction;
633 }
634 }
FX_BidiGetResolvedNeutrals(int32_t iAction)635 int32_t FX_BidiGetResolvedNeutrals(int32_t iAction) {
636 iAction = (iAction & 0xF);
637 if (iAction == FX_BIDINEUTRALACTION_In) {
638 return 0;
639 } else {
640 return iAction;
641 }
642 }
FX_BidiResolveNeutrals(int32_t iBaseLevel,CFX_Int32Array & classes,const CFX_Int32Array & levels)643 void FX_BidiResolveNeutrals(int32_t iBaseLevel,
644 CFX_Int32Array& classes,
645 const CFX_Int32Array& levels) {
646 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
647 FXSYS_assert(classes.GetSize() == levels.GetSize());
648 int32_t iSize = classes.GetSize();
649 if (iSize < 1) {
650 return;
651 }
652 iSize--;
653 int32_t iLevel = iBaseLevel;
654 int32_t iState = FX_IsOdd(iBaseLevel) ? FX_BNSr : FX_BNSl;
655 int32_t i = 0, iCount = 0, iClsCur, iClsRun, iClsNew, iAction;
656 for (; i <= iSize; i++) {
657 iClsCur = classes.GetAt(i);
658 if (iClsCur == FX_BIDICLASS_BN) {
659 if (iCount) {
660 iCount++;
661 }
662 continue;
663 }
664 FXSYS_assert(iClsCur < FX_BIDICLASS_AL);
665 iAction = gc_FX_BidiNeutralActions[iState][iClsCur];
666 iClsRun = FX_BidiGetDeferredNeutrals(iAction, iLevel);
667 if (iClsRun != FX_BIDICLASS_N && iCount > 0) {
668 FX_BidiSetDeferredRun(classes, i, iCount, iClsRun);
669 iCount = 0;
670 }
671 iClsNew = FX_BidiGetResolvedNeutrals(iAction);
672 if (iClsNew != FX_BIDICLASS_N) {
673 classes.SetAt(i, iClsNew);
674 }
675 if (FX_BIDINEUTRALACTION_In & iAction) {
676 iCount++;
677 }
678 iState = gc_FX_BidiNeutralStates[iState][iClsCur];
679 iLevel = levels.GetAt(i);
680 }
681 iClsCur = FX_BidiDirection(iLevel);
682 iClsRun = FX_BidiGetDeferredNeutrals(
683 gc_FX_BidiNeutralActions[iState][iClsCur], iLevel);
684 if (iClsRun != FX_BIDICLASS_N && iCount > 0) {
685 FX_BidiSetDeferredRun(classes, i, iCount, iClsRun);
686 }
687 }
688 const int32_t gc_FX_BidiAddLevel[][4] = {
689 {0, 1, 2, 2},
690 {1, 0, 1, 1},
691 };
FX_BidiResolveImplicit(const CFX_Int32Array & classes,CFX_Int32Array & levels)692 void FX_BidiResolveImplicit(const CFX_Int32Array& classes,
693 CFX_Int32Array& levels) {
694 FXSYS_assert(classes.GetSize() == levels.GetSize());
695 int32_t iSize = classes.GetSize();
696 if (iSize < 1) {
697 return;
698 }
699 iSize--;
700 int32_t iCls, iLevel;
701 for (int32_t i = 0; i <= iSize; i++) {
702 iCls = classes.GetAt(i);
703 if (iCls == FX_BIDICLASS_BN) {
704 continue;
705 }
706 FXSYS_assert(iCls > FX_BIDICLASS_ON && iCls < FX_BIDICLASS_AL);
707 iLevel = levels.GetAt(i);
708 iLevel += gc_FX_BidiAddLevel[FX_IsOdd(iLevel)][iCls - 1];
709 levels.SetAt(i, iLevel);
710 }
711 }
FX_BidiResolveWhitespace(int32_t iBaseLevel,const CFX_Int32Array & classes,CFX_Int32Array & levels)712 void FX_BidiResolveWhitespace(int32_t iBaseLevel,
713 const CFX_Int32Array& classes,
714 CFX_Int32Array& levels) {
715 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
716 FXSYS_assert(classes.GetSize() == levels.GetSize());
717 int32_t iSize = classes.GetSize();
718 if (iSize < 1) {
719 return;
720 }
721 iSize--;
722 int32_t iLevel = iBaseLevel;
723 int32_t i = 0, iCount = 0;
724 for (; i <= iSize; i++) {
725 switch (classes.GetAt(i)) {
726 case FX_BIDICLASS_WS:
727 iCount++;
728 break;
729 case FX_BIDICLASS_RLE:
730 case FX_BIDICLASS_LRE:
731 case FX_BIDICLASS_LRO:
732 case FX_BIDICLASS_RLO:
733 case FX_BIDICLASS_PDF:
734 case FX_BIDICLASS_BN:
735 levels.SetAt(i, iLevel);
736 iCount++;
737 break;
738 case FX_BIDICLASS_S:
739 case FX_BIDICLASS_B:
740 if (iCount > 0) {
741 FX_BidiSetDeferredRun(levels, i, iCount, iBaseLevel);
742 }
743 levels.SetAt(i, iBaseLevel);
744 iCount = 0;
745 break;
746 default:
747 iCount = 0;
748 break;
749 }
750 iLevel = levels.GetAt(i);
751 }
752 if (iCount > 0) {
753 FX_BidiSetDeferredRun(levels, i, iCount, iBaseLevel);
754 }
755 }
FX_BidiReorderLevel(int32_t iBaseLevel,CFX_WideString & wsText,const CFX_Int32Array & levels,int32_t iStart,FX_BOOL bReverse)756 int32_t FX_BidiReorderLevel(int32_t iBaseLevel,
757 CFX_WideString& wsText,
758 const CFX_Int32Array& levels,
759 int32_t iStart,
760 FX_BOOL bReverse) {
761 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
762 FXSYS_assert(wsText.GetLength() == levels.GetSize());
763 FXSYS_assert(iStart >= 0 && iStart < wsText.GetLength());
764 int32_t iSize = wsText.GetLength();
765 if (iSize < 1) {
766 return 0;
767 }
768 bReverse = bReverse || FX_IsOdd(iBaseLevel);
769 int32_t i = iStart, iLevel;
770 for (; i < iSize; i++) {
771 if ((iLevel = levels.GetAt(i)) == iBaseLevel) {
772 continue;
773 }
774 if (iLevel < iBaseLevel) {
775 break;
776 }
777 i += FX_BidiReorderLevel(iBaseLevel + 1, wsText, levels, i, bReverse) - 1;
778 }
779 int32_t iCount = i - iStart;
780 if (bReverse && iCount > 1) {
781 FX_BidiReverseString(wsText, iStart, iCount);
782 }
783 return iCount;
784 }
FX_BidiReorder(int32_t iBaseLevel,CFX_WideString & wsText,const CFX_Int32Array & levels)785 void FX_BidiReorder(int32_t iBaseLevel,
786 CFX_WideString& wsText,
787 const CFX_Int32Array& levels) {
788 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
789 FXSYS_assert(wsText.GetLength() == levels.GetSize());
790 int32_t iSize = wsText.GetLength();
791 if (iSize < 1) {
792 return;
793 }
794 int32_t i = 0;
795 while (i < iSize) {
796 i += FX_BidiReorderLevel(iBaseLevel, wsText, levels, i, FALSE);
797 }
798 }
FX_BidiLine(CFX_WideString & wsText,int32_t iBaseLevel)799 void FX_BidiLine(CFX_WideString& wsText, int32_t iBaseLevel) {
800 int32_t iLength = wsText.GetLength();
801 if (iLength < 2) {
802 return;
803 }
804 CFX_Int32Array classes, levels;
805 classes.SetAtGrow(iLength - 1, 0);
806 levels.SetAtGrow(iLength - 1, 0);
807 FX_BidiClassify(wsText, classes, FALSE);
808 FX_BidiResolveExplicit(iBaseLevel, FX_BIDICLASS_N, classes, levels, 0,
809 iLength, 0);
810 FX_BidiResolveWeak(iBaseLevel, classes, levels);
811 FX_BidiResolveNeutrals(iBaseLevel, classes, levels);
812 FX_BidiResolveImplicit(classes, levels);
813 FX_BidiClassify(wsText, classes, TRUE);
814 FX_BidiResolveWhitespace(iBaseLevel, classes, levels);
815 FX_BidiReorder(iBaseLevel, wsText, levels);
816 classes.RemoveAll();
817 levels.RemoveAll();
818 }
819 template <class baseType>
820 class CFX_BidiLineTemplate {
821 public:
FX_BidiReverseString(CFX_ArrayTemplate<baseType> & chars,int32_t iStart,int32_t iCount)822 void FX_BidiReverseString(CFX_ArrayTemplate<baseType>& chars,
823 int32_t iStart,
824 int32_t iCount) {
825 FXSYS_assert(iStart > -1 && iStart < chars.GetSize());
826 FXSYS_assert(iCount >= 0 && iStart + iCount <= chars.GetSize());
827 baseType *pStart, *pEnd;
828 int32_t iEnd = iStart + iCount - 1, iTemp;
829 while (iStart < iEnd) {
830 pStart = chars.GetDataPtr(iStart++);
831 pEnd = chars.GetDataPtr(iEnd--);
832 iTemp = pStart->m_iBidiPos;
833 pStart->m_iBidiPos = pEnd->m_iBidiPos;
834 pEnd->m_iBidiPos = iTemp;
835 }
836 }
FX_BidiSetDeferredRun(CFX_ArrayTemplate<baseType> & chars,FX_BOOL bClass,int32_t iStart,int32_t iCount,int32_t iValue)837 void FX_BidiSetDeferredRun(CFX_ArrayTemplate<baseType>& chars,
838 FX_BOOL bClass,
839 int32_t iStart,
840 int32_t iCount,
841 int32_t iValue) {
842 FXSYS_assert(iStart > -1 && iStart <= chars.GetSize());
843 FXSYS_assert(iStart - iCount > -1);
844 baseType* pTC;
845 int32_t iLast = iStart - iCount;
846 if (bClass) {
847 for (int32_t i = iStart - 1; i >= iLast; i--) {
848 pTC = chars.GetDataPtr(i);
849 pTC->m_iBidiClass = (int16_t)iValue;
850 }
851 } else {
852 for (int32_t i = iStart - 1; i >= iLast; i--) {
853 pTC = chars.GetDataPtr(i);
854 pTC->m_iBidiLevel = (int16_t)iValue;
855 }
856 }
857 }
FX_BidiClassify(CFX_ArrayTemplate<baseType> & chars,int32_t iCount,FX_BOOL bWS)858 void FX_BidiClassify(CFX_ArrayTemplate<baseType>& chars,
859 int32_t iCount,
860 FX_BOOL bWS) {
861 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
862 baseType* pTC;
863 if (bWS) {
864 for (int32_t i = 0; i < iCount; i++) {
865 pTC = chars.GetDataPtr(i);
866 pTC->m_iBidiClass =
867 (int16_t)(pTC->m_dwCharProps & FX_BIDICLASSBITSMASK) >>
868 FX_BIDICLASSBITS;
869 }
870 } else {
871 for (int32_t i = 0; i < iCount; i++) {
872 pTC = chars.GetDataPtr(i);
873 pTC->m_iBidiClass = (int16_t)
874 gc_FX_BidiNTypes[(pTC->m_dwCharProps & FX_BIDICLASSBITSMASK) >>
875 FX_BIDICLASSBITS];
876 }
877 }
878 }
FX_BidiResolveExplicit(CFX_ArrayTemplate<baseType> & chars,int32_t iCount,int32_t iBaseLevel)879 void FX_BidiResolveExplicit(CFX_ArrayTemplate<baseType>& chars,
880 int32_t iCount,
881 int32_t iBaseLevel) {
882 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
883 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
884 if (iCount < 1) {
885 return;
886 }
887 baseType* pTC;
888 for (int32_t i = 0; i < iCount; i++) {
889 pTC = chars.GetDataPtr(i);
890 pTC->m_iBidiLevel = (int16_t)iBaseLevel;
891 }
892 }
FX_BidiResolveWeak(CFX_ArrayTemplate<baseType> & chars,int32_t iCount,int32_t iBaseLevel)893 void FX_BidiResolveWeak(CFX_ArrayTemplate<baseType>& chars,
894 int32_t iCount,
895 int32_t iBaseLevel) {
896 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
897 iCount--;
898 if (iCount < 1) {
899 return;
900 }
901 baseType *pTC, *pTCNext;
902 int32_t iLevelCur = iBaseLevel;
903 int32_t iState = FX_IsOdd(iBaseLevel) ? FX_BWSxr : FX_BWSxl;
904 int32_t i = 0, iNum = 0, iClsCur, iClsRun, iClsNew, iAction;
905 for (; i <= iCount; i++) {
906 pTC = chars.GetDataPtr(i);
907 iClsCur = pTC->m_iBidiClass;
908 if (iClsCur == FX_BIDICLASS_BN) {
909 pTC->m_iBidiLevel = (int16_t)iLevelCur;
910 if (i == iCount && iLevelCur != iBaseLevel) {
911 iClsCur = FX_BidiDirection(iLevelCur);
912 pTC->m_iBidiClass = (int16_t)iClsCur;
913 } else if (i < iCount) {
914 pTCNext = chars.GetDataPtr(i + 1);
915 int32_t iLevelNext, iLevelNew;
916 iClsNew = pTCNext->m_iBidiClass;
917 iLevelNext = pTCNext->m_iBidiLevel;
918 if (iClsNew != FX_BIDICLASS_BN && iLevelCur != iLevelNext) {
919 iLevelNew = iLevelNext;
920 if (iLevelCur > iLevelNew) {
921 iLevelNew = iLevelCur;
922 }
923 pTC->m_iBidiLevel = (int16_t)iLevelNew;
924 iClsCur = FX_BidiDirection(iLevelNew);
925 pTC->m_iBidiClass = (int16_t)iClsCur;
926 iLevelCur = iLevelNext;
927 } else {
928 if (iNum > 0) {
929 iNum++;
930 }
931 continue;
932 }
933 } else {
934 if (iNum > 0) {
935 iNum++;
936 }
937 continue;
938 }
939 }
940 FXSYS_assert(iClsCur <= FX_BIDICLASS_BN);
941 iAction = gc_FX_BidiWeakActions[iState][iClsCur];
942 iClsRun = FX_BidiGetDeferredType(iAction);
943 if (iClsRun != FX_BIDIWEAKACTION_XX && iNum > 0) {
944 FX_BidiSetDeferredRun(chars, TRUE, i, iNum, iClsRun);
945 iNum = 0;
946 }
947 iClsNew = FX_BidiGetResolvedType(iAction);
948 if (iClsNew != FX_BIDIWEAKACTION_XX) {
949 pTC->m_iBidiClass = (int16_t)iClsNew;
950 }
951 if (FX_BIDIWEAKACTION_IX & iAction) {
952 iNum++;
953 }
954 iState = gc_FX_BidiWeakStates[iState][iClsCur];
955 }
956 if (iNum > 0) {
957 iClsCur = FX_BidiDirection(iBaseLevel);
958 iClsRun = FX_BidiGetDeferredType(gc_FX_BidiWeakActions[iState][iClsCur]);
959 if (iClsRun != FX_BIDIWEAKACTION_XX) {
960 FX_BidiSetDeferredRun(chars, TRUE, i, iNum, iClsRun);
961 }
962 }
963 }
FX_BidiResolveNeutrals(CFX_ArrayTemplate<baseType> & chars,int32_t iCount,int32_t iBaseLevel)964 void FX_BidiResolveNeutrals(CFX_ArrayTemplate<baseType>& chars,
965 int32_t iCount,
966 int32_t iBaseLevel) {
967 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
968 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
969 iCount--;
970 if (iCount < 1) {
971 return;
972 }
973 baseType* pTC;
974 int32_t iLevel = iBaseLevel;
975 int32_t iState = FX_IsOdd(iBaseLevel) ? FX_BNSr : FX_BNSl;
976 int32_t i = 0, iNum = 0, iClsCur, iClsRun, iClsNew, iAction;
977 for (; i <= iCount; i++) {
978 pTC = chars.GetDataPtr(i);
979 iClsCur = pTC->m_iBidiClass;
980 if (iClsCur == FX_BIDICLASS_BN) {
981 if (iNum) {
982 iNum++;
983 }
984 continue;
985 }
986 FXSYS_assert(iClsCur < FX_BIDICLASS_AL);
987 iAction = gc_FX_BidiNeutralActions[iState][iClsCur];
988 iClsRun = FX_BidiGetDeferredNeutrals(iAction, iLevel);
989 if (iClsRun != FX_BIDICLASS_N && iNum > 0) {
990 FX_BidiSetDeferredRun(chars, TRUE, i, iNum, iClsRun);
991 iNum = 0;
992 }
993 iClsNew = FX_BidiGetResolvedNeutrals(iAction);
994 if (iClsNew != FX_BIDICLASS_N) {
995 pTC->m_iBidiClass = (int16_t)iClsNew;
996 }
997 if (FX_BIDINEUTRALACTION_In & iAction) {
998 iNum++;
999 }
1000 iState = gc_FX_BidiNeutralStates[iState][iClsCur];
1001 iLevel = pTC->m_iBidiLevel;
1002 }
1003 if (iNum > 0) {
1004 iClsCur = FX_BidiDirection(iLevel);
1005 iClsRun = FX_BidiGetDeferredNeutrals(
1006 gc_FX_BidiNeutralActions[iState][iClsCur], iLevel);
1007 if (iClsRun != FX_BIDICLASS_N) {
1008 FX_BidiSetDeferredRun(chars, TRUE, i, iNum, iClsRun);
1009 }
1010 }
1011 }
FX_BidiResolveImplicit(CFX_ArrayTemplate<baseType> & chars,int32_t iCount)1012 void FX_BidiResolveImplicit(CFX_ArrayTemplate<baseType>& chars,
1013 int32_t iCount) {
1014 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
1015 baseType* pTC;
1016 int32_t iCls, iLevel;
1017 for (int32_t i = 0; i < iCount; i++) {
1018 pTC = chars.GetDataPtr(i);
1019 iCls = pTC->m_iBidiClass;
1020 if (iCls == FX_BIDICLASS_BN) {
1021 continue;
1022 }
1023 FXSYS_assert(iCls > FX_BIDICLASS_ON && iCls < FX_BIDICLASS_AL);
1024 iLevel = pTC->m_iBidiLevel;
1025 iLevel += gc_FX_BidiAddLevel[FX_IsOdd(iLevel)][iCls - 1];
1026 pTC->m_iBidiLevel = (int16_t)iLevel;
1027 }
1028 }
FX_BidiResolveWhitespace(CFX_ArrayTemplate<baseType> & chars,int32_t iCount,int32_t iBaseLevel)1029 void FX_BidiResolveWhitespace(CFX_ArrayTemplate<baseType>& chars,
1030 int32_t iCount,
1031 int32_t iBaseLevel) {
1032 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
1033 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
1034 if (iCount < 1) {
1035 return;
1036 }
1037 iCount--;
1038 int32_t iLevel = iBaseLevel;
1039 int32_t i = 0, iNum = 0;
1040 baseType* pTC;
1041 for (; i <= iCount; i++) {
1042 pTC = chars.GetDataPtr(i);
1043 switch (pTC->m_iBidiClass) {
1044 case FX_BIDICLASS_WS:
1045 iNum++;
1046 break;
1047 case FX_BIDICLASS_RLE:
1048 case FX_BIDICLASS_LRE:
1049 case FX_BIDICLASS_LRO:
1050 case FX_BIDICLASS_RLO:
1051 case FX_BIDICLASS_PDF:
1052 case FX_BIDICLASS_BN:
1053 pTC->m_iBidiLevel = (int16_t)iLevel;
1054 iNum++;
1055 break;
1056 case FX_BIDICLASS_S:
1057 case FX_BIDICLASS_B:
1058 if (iNum > 0) {
1059 FX_BidiSetDeferredRun(chars, FALSE, i, iNum, iBaseLevel);
1060 }
1061 pTC->m_iBidiLevel = (int16_t)iBaseLevel;
1062 iNum = 0;
1063 break;
1064 default:
1065 iNum = 0;
1066 break;
1067 }
1068 iLevel = pTC->m_iBidiLevel;
1069 }
1070 if (iNum > 0) {
1071 FX_BidiSetDeferredRun(chars, FALSE, i, iNum, iBaseLevel);
1072 }
1073 }
FX_BidiReorderLevel(CFX_ArrayTemplate<baseType> & chars,int32_t iCount,int32_t iBaseLevel,int32_t iStart,FX_BOOL bReverse)1074 int32_t FX_BidiReorderLevel(CFX_ArrayTemplate<baseType>& chars,
1075 int32_t iCount,
1076 int32_t iBaseLevel,
1077 int32_t iStart,
1078 FX_BOOL bReverse) {
1079 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
1080 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
1081 FXSYS_assert(iStart >= 0 && iStart < iCount);
1082 if (iCount < 1) {
1083 return 0;
1084 }
1085 baseType* pTC;
1086 bReverse = bReverse || FX_IsOdd(iBaseLevel);
1087 int32_t i = iStart, iLevel;
1088 for (; i < iCount; i++) {
1089 pTC = chars.GetDataPtr(i);
1090 if ((iLevel = pTC->m_iBidiLevel) == iBaseLevel) {
1091 continue;
1092 }
1093 if (iLevel < iBaseLevel) {
1094 break;
1095 }
1096 i += FX_BidiReorderLevel(chars, iCount, iBaseLevel + 1, i, bReverse) - 1;
1097 }
1098 int32_t iNum = i - iStart;
1099 if (bReverse && iNum > 1) {
1100 FX_BidiReverseString(chars, iStart, iNum);
1101 }
1102 return iNum;
1103 }
FX_BidiReorder(CFX_ArrayTemplate<baseType> & chars,int32_t iCount,int32_t iBaseLevel)1104 void FX_BidiReorder(CFX_ArrayTemplate<baseType>& chars,
1105 int32_t iCount,
1106 int32_t iBaseLevel) {
1107 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
1108 FXSYS_assert(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL);
1109 int32_t i = 0;
1110 while (i < iCount) {
1111 i += FX_BidiReorderLevel(chars, iCount, iBaseLevel, i, FALSE);
1112 }
1113 }
FX_BidiPosition(CFX_ArrayTemplate<baseType> & chars,int32_t iCount)1114 void FX_BidiPosition(CFX_ArrayTemplate<baseType>& chars, int32_t iCount) {
1115 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
1116 baseType* pTC;
1117 int32_t i = 0;
1118 while (i < iCount) {
1119 pTC = chars.GetDataPtr(i);
1120 pTC = chars.GetDataPtr(pTC->m_iBidiPos);
1121 pTC->m_iBidiOrder = i++;
1122 }
1123 }
1124
FX_BidiLine(CFX_ArrayTemplate<baseType> & chars,int32_t iCount,int32_t iBaseLevel)1125 void FX_BidiLine(CFX_ArrayTemplate<baseType>& chars,
1126 int32_t iCount,
1127 int32_t iBaseLevel) {
1128 FXSYS_assert(iCount > -1 && iCount <= chars.GetSize());
1129 if (iCount < 2) {
1130 return;
1131 }
1132 FX_BidiClassify(chars, iCount, FALSE);
1133 FX_BidiResolveExplicit(chars, iCount, iBaseLevel);
1134 FX_BidiResolveWeak(chars, iCount, iBaseLevel);
1135 FX_BidiResolveNeutrals(chars, iCount, iBaseLevel);
1136 FX_BidiResolveImplicit(chars, iCount);
1137 FX_BidiClassify(chars, iCount, TRUE);
1138 FX_BidiResolveWhitespace(chars, iCount, iBaseLevel);
1139 FX_BidiReorder(chars, iCount, iBaseLevel);
1140 FX_BidiPosition(chars, iCount);
1141 }
1142 };
FX_BidiLine(CFX_TxtCharArray & chars,int32_t iCount,int32_t iBaseLevel)1143 void FX_BidiLine(CFX_TxtCharArray& chars, int32_t iCount, int32_t iBaseLevel) {
1144 CFX_BidiLineTemplate<CFX_TxtChar> blt;
1145 blt.FX_BidiLine(chars, iCount, iBaseLevel);
1146 }
FX_BidiLine(CFX_RTFCharArray & chars,int32_t iCount,int32_t iBaseLevel)1147 void FX_BidiLine(CFX_RTFCharArray& chars, int32_t iCount, int32_t iBaseLevel) {
1148 CFX_BidiLineTemplate<CFX_RTFChar> blt;
1149 blt.FX_BidiLine(chars, iCount, iBaseLevel);
1150 }
1151