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 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 } 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 } 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 241 IFX_ArabicChar* IFX_ArabicChar::Create() { 242 return new CFX_ArabicChar; 243 } 244 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 } 249 FX_BOOL CFX_ArabicChar::IsArabicFormChar(FX_WCHAR wch) const { 250 return (kTextLayoutCodeProperties[(FX_WORD)wch] & FX_CHARTYPEBITSMASK) == 251 FX_CHARTYPE_ArabicForm; 252 } 253 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 } 261 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 } 298 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 } 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 } 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 }; 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 } 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 }; 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 }; 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 } 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 } 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 }; 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 } 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 } 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 } 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 } 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: 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 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 }; 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 } 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