• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 "xfa/fgas/layout/cfx_char.h"
8 
9 #include <algorithm>
10 
11 #include "core/fxcrt/fx_extension.h"
12 
13 namespace {
14 
15 #ifndef NDEBUG
16 constexpr int32_t kBidiMaxLevel = 61;
17 #endif  // NDEBUG
18 
19 #undef PACK_NIBBLES
20 #define PACK_NIBBLES(hi, lo) \
21   ((static_cast<uint32_t>(hi) << 4) + static_cast<uint32_t>(lo))
22 
23 enum FX_BIDIWEAKSTATE : uint8_t {
24   FX_BWSxa = 0,
25   FX_BWSxr,
26   FX_BWSxl,
27   FX_BWSao,
28   FX_BWSro,
29   FX_BWSlo,
30   FX_BWSrt,
31   FX_BWSlt,
32   FX_BWScn,
33   FX_BWSra,
34   FX_BWSre,
35   FX_BWSla,
36   FX_BWSle,
37   FX_BWSac,
38   FX_BWSrc,
39   FX_BWSrs,
40   FX_BWSlc,
41   FX_BWSls,
42   FX_BWSret,
43   FX_BWSlet
44 };
45 
46 // NOTE: Range of FX_BIDICLASS prevents encoding all possible values in this
47 // manner, but the ones used manage to fit. Except that I suspect that 0xF
48 // was intended to be used as a sentinel, even though it also means kRLE.
49 // TODO(tsepez): pick a better representation.
50 enum FX_BIDIWEAKACTION : uint16_t {
51   FX_BWAIX = 0x100,
52   FX_BWAXX = 0x0F,
53   FX_BWAxxx = 0xFF,
54   FX_BWAxIx = 0x100 + FX_BWAxxx,
55   FX_BWAxxN = PACK_NIBBLES(0x0F, FX_BIDICLASS::kON),
56   FX_BWAxxE = PACK_NIBBLES(0x0F, FX_BIDICLASS::kEN),
57   FX_BWAxxA = PACK_NIBBLES(0x0F, FX_BIDICLASS::kAN),
58   FX_BWAxxR = PACK_NIBBLES(0x0F, FX_BIDICLASS::kR),
59   FX_BWAxxL = PACK_NIBBLES(0x0F, FX_BIDICLASS::kL),
60   FX_BWANxx = PACK_NIBBLES(FX_BIDICLASS::kON, 0x0F),
61   FX_BWAAxx = PACK_NIBBLES(FX_BIDICLASS::kAN, 0x0F),
62   FX_BWAExE = PACK_NIBBLES(FX_BIDICLASS::kEN, FX_BIDICLASS::kEN),
63   FX_BWANIx = 0x100 + PACK_NIBBLES(FX_BIDICLASS::kON, 0x0F),
64   FX_BWANxN = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kON),
65   FX_BWANxR = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kR),
66   FX_BWANxE = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kEN),
67   FX_BWAAxA = PACK_NIBBLES(FX_BIDICLASS::kAN, FX_BIDICLASS::kAN),
68   FX_BWANxL = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kL),
69   FX_BWALxL = PACK_NIBBLES(FX_BIDICLASS::kL, FX_BIDICLASS::kL),
70   FX_BWAxIL = 0x100 + PACK_NIBBLES(0x0F, FX_BIDICLASS::kL),
71   FX_BWAAxR = PACK_NIBBLES(FX_BIDICLASS::kAN, FX_BIDICLASS::kR),
72   FX_BWALxx = PACK_NIBBLES(FX_BIDICLASS::kL, 0x0F),
73 };
74 
75 enum FX_BIDINEUTRALSTATE : uint8_t {
76   FX_BNSr = 0,
77   FX_BNSl,
78   FX_BNSrn,
79   FX_BNSln,
80   FX_BNSa,
81   FX_BNSna
82 };
83 
84 enum FX_BIDINEUTRALACTION : uint16_t {
85   // For placeholders in table.
86   FX_BNAZero = 0,
87 
88   // Other values.
89   FX_BNAnL = PACK_NIBBLES(0, FX_BIDICLASS::kL),
90   FX_BNAEn = PACK_NIBBLES(FX_BIDICLASS::kAN, 0),
91   FX_BNARn = PACK_NIBBLES(FX_BIDICLASS::kR, 0),
92   FX_BNALn = PACK_NIBBLES(FX_BIDICLASS::kL, 0),
93   FX_BNAIn = FX_BWAIX,
94   FX_BNALnL = PACK_NIBBLES(FX_BIDICLASS::kL, FX_BIDICLASS::kL),
95 };
96 #undef PACK_NIBBLES
97 
98 const FX_BIDICLASS kNTypes[] = {
99     FX_BIDICLASS::kN,   FX_BIDICLASS::kL,   FX_BIDICLASS::kR,
100     FX_BIDICLASS::kAN,  FX_BIDICLASS::kEN,  FX_BIDICLASS::kAL,
101     FX_BIDICLASS::kNSM, FX_BIDICLASS::kCS,  FX_BIDICLASS::kES,
102     FX_BIDICLASS::kET,  FX_BIDICLASS::kBN,  FX_BIDICLASS::kBN,
103     FX_BIDICLASS::kN,   FX_BIDICLASS::kB,   FX_BIDICLASS::kRLO,
104     FX_BIDICLASS::kRLE, FX_BIDICLASS::kLRO, FX_BIDICLASS::kLRE,
105     FX_BIDICLASS::kPDF, FX_BIDICLASS::kON,
106 };
107 
108 const FX_BIDIWEAKSTATE kWeakStates[20][10] = {
109     {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSxa,
110      FX_BWSao, FX_BWSao, FX_BWSao},
111     {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSxr,
112      FX_BWSro, FX_BWSro, FX_BWSrt},
113     {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSxl,
114      FX_BWSlo, FX_BWSlo, FX_BWSlt},
115     {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
116      FX_BWSao, FX_BWSao, FX_BWSao},
117     {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
118      FX_BWSro, FX_BWSro, FX_BWSrt},
119     {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
120      FX_BWSlo, FX_BWSlo, FX_BWSlt},
121     {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSrt,
122      FX_BWSro, FX_BWSro, FX_BWSrt},
123     {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlt,
124      FX_BWSlo, FX_BWSlo, FX_BWSlt},
125     {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWScn,
126      FX_BWSac, FX_BWSao, FX_BWSao},
127     {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSra,
128      FX_BWSrc, FX_BWSro, FX_BWSrt},
129     {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSre,
130      FX_BWSrs, FX_BWSrs, FX_BWSret},
131     {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSla,
132      FX_BWSlc, FX_BWSlo, FX_BWSlt},
133     {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSle,
134      FX_BWSls, FX_BWSls, FX_BWSlet},
135     {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
136      FX_BWSao, FX_BWSao, FX_BWSao},
137     {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
138      FX_BWSro, FX_BWSro, FX_BWSrt},
139     {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
140      FX_BWSro, FX_BWSro, FX_BWSrt},
141     {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
142      FX_BWSlo, FX_BWSlo, FX_BWSlt},
143     {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
144      FX_BWSlo, FX_BWSlo, FX_BWSlt},
145     {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSret,
146      FX_BWSro, FX_BWSro, FX_BWSret},
147     {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlet,
148      FX_BWSlo, FX_BWSlo, FX_BWSlet},
149 };
150 
151 const FX_BIDIWEAKACTION kWeakActions[20][10] = {
152     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
153      FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
154     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
155      FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
156     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
157      FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
158     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
159      FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
160     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
161      FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
162     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
163      FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
164     {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
165      FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
166     {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
167      FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
168     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
169      FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxxN},
170     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
171      FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
172     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
173      FX_BWAxxE, FX_BWAxIx, FX_BWAxIx, FX_BWAxxE},
174     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
175      FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
176     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
177      FX_BWAxxL, FX_BWAxIx, FX_BWAxIx, FX_BWAxxL},
178     {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWAAxA, FX_BWANxR,
179      FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANxN},
180     {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxE, FX_BWANxR,
181      FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
182     {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
183      FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
184     {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxL, FX_BWANxR,
185      FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
186     {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
187      FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
188     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
189      FX_BWAxxE, FX_BWAxxN, FX_BWAxxN, FX_BWAxxE},
190     {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
191      FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxxL},
192 };
193 
194 const FX_BIDINEUTRALSTATE kNeutralStates[6][5] = {
195     {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
196     {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
197     {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
198     {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
199     {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
200     {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
201 };
202 
203 const FX_BIDINEUTRALACTION kNeutralActions[6][5] = {
204     {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAZero},
205     {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAnL},
206     {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNARn},
207     {FX_BNAIn, FX_BNALn, FX_BNAEn, FX_BNAEn, FX_BNALnL},
208     {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAnL},
209     {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNAEn},
210 };
211 
212 const uint8_t kAddLevel[2][4] = {
213     {0, 1, 2, 2},
214     {1, 0, 1, 1},
215 };
216 
Direction(int32_t val)217 FX_BIDICLASS Direction(int32_t val) {
218   return FX_IsOdd(val) ? FX_BIDICLASS::kR : FX_BIDICLASS::kL;
219 }
220 
GetDeferredType(int32_t val)221 FX_BIDICLASS GetDeferredType(int32_t val) {
222   return static_cast<FX_BIDICLASS>((val >> 4) & 0x0F);
223 }
224 
GetResolvedType(int32_t val)225 FX_BIDICLASS GetResolvedType(int32_t val) {
226   return static_cast<FX_BIDICLASS>(val & 0x0F);
227 }
228 
GetDeferredNeutrals(int32_t iAction,int32_t iLevel)229 FX_BIDICLASS GetDeferredNeutrals(int32_t iAction, int32_t iLevel) {
230   FX_BIDICLASS eClass = GetDeferredType(iAction);
231   return eClass == FX_BIDICLASS::kAN ? Direction(iLevel) : eClass;
232 }
233 
GetResolvedNeutrals(int32_t iAction)234 FX_BIDICLASS GetResolvedNeutrals(int32_t iAction) {
235   return GetResolvedType(iAction);
236 }
237 
GetWeakState(FX_BIDIWEAKSTATE eState,FX_BIDICLASS eClass)238 FX_BIDIWEAKSTATE GetWeakState(FX_BIDIWEAKSTATE eState, FX_BIDICLASS eClass) {
239   ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kWeakStates));
240   ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kWeakStates[0]));
241   return kWeakStates[static_cast<size_t>(eState)][static_cast<size_t>(eClass)];
242 }
243 
GetWeakAction(FX_BIDIWEAKSTATE eState,FX_BIDICLASS eClass)244 FX_BIDIWEAKACTION GetWeakAction(FX_BIDIWEAKSTATE eState, FX_BIDICLASS eClass) {
245   ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kWeakActions));
246   ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kWeakActions[0]));
247   return kWeakActions[static_cast<size_t>(eState)][static_cast<size_t>(eClass)];
248 }
249 
GetNeutralState(FX_BIDINEUTRALSTATE eState,FX_BIDICLASS eClass)250 FX_BIDINEUTRALSTATE GetNeutralState(FX_BIDINEUTRALSTATE eState,
251                                     FX_BIDICLASS eClass) {
252   ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kNeutralStates));
253   ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kNeutralStates[0]));
254   return kNeutralStates[static_cast<size_t>(eState)]
255                        [static_cast<size_t>(eClass)];
256 }
257 
GetNeutralAction(FX_BIDINEUTRALSTATE eState,FX_BIDICLASS eClass)258 FX_BIDINEUTRALACTION GetNeutralAction(FX_BIDINEUTRALSTATE eState,
259                                       FX_BIDICLASS eClass) {
260   ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kNeutralActions));
261   ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kNeutralActions[0]));
262   return kNeutralActions[static_cast<size_t>(eState)]
263                         [static_cast<size_t>(eClass)];
264 }
265 
ReverseString(std::vector<CFX_Char> * chars,size_t iStart,size_t iCount)266 void ReverseString(std::vector<CFX_Char>* chars, size_t iStart, size_t iCount) {
267   ASSERT(pdfium::IndexInBounds(*chars, iStart));
268   ASSERT(iStart + iCount <= chars->size());
269 
270   std::reverse(chars->begin() + iStart, chars->begin() + iStart + iCount);
271 }
272 
SetDeferredRunClass(std::vector<CFX_Char> * chars,size_t iStart,size_t iCount,FX_BIDICLASS eValue)273 void SetDeferredRunClass(std::vector<CFX_Char>* chars,
274                          size_t iStart,
275                          size_t iCount,
276                          FX_BIDICLASS eValue) {
277   ASSERT(iStart <= chars->size());
278   ASSERT(iStart >= iCount);
279 
280   size_t iLast = iStart - iCount;
281   for (size_t i = iStart; i > iLast; --i)
282     (*chars)[i - 1].m_iBidiClass = eValue;
283 }
284 
SetDeferredRunLevel(std::vector<CFX_Char> * chars,size_t iStart,size_t iCount,int32_t iValue)285 void SetDeferredRunLevel(std::vector<CFX_Char>* chars,
286                          size_t iStart,
287                          size_t iCount,
288                          int32_t iValue) {
289   ASSERT(iStart <= chars->size());
290   ASSERT(iStart >= iCount);
291 
292   size_t iLast = iStart - iCount;
293   for (size_t i = iStart; i > iLast; --i)
294     (*chars)[i - 1].m_iBidiLevel = static_cast<int16_t>(iValue);
295 }
296 
Classify(std::vector<CFX_Char> * chars,size_t iCount)297 void Classify(std::vector<CFX_Char>* chars, size_t iCount) {
298   for (size_t i = 0; i < iCount; ++i) {
299     CFX_Char& cur = (*chars)[i];
300     cur.m_iBidiClass = FX_GetBidiClass(cur.char_code());
301   }
302 }
303 
ClassifyWithTransform(std::vector<CFX_Char> * chars,size_t iCount)304 void ClassifyWithTransform(std::vector<CFX_Char>* chars, size_t iCount) {
305   for (size_t i = 0; i < iCount; ++i) {
306     CFX_Char& cur = (*chars)[i];
307     cur.m_iBidiClass =
308         kNTypes[static_cast<size_t>(FX_GetBidiClass(cur.char_code()))];
309   }
310 }
311 
ResolveExplicit(std::vector<CFX_Char> * chars,size_t iCount)312 void ResolveExplicit(std::vector<CFX_Char>* chars, size_t iCount) {
313   for (size_t i = 0; i < iCount; ++i)
314     (*chars)[i].m_iBidiLevel = 0;
315 }
316 
ResolveWeak(std::vector<CFX_Char> * chars,size_t iCount)317 void ResolveWeak(std::vector<CFX_Char>* chars, size_t iCount) {
318   if (iCount <= 1)
319     return;
320   --iCount;
321 
322   int32_t iLevelCur = 0;
323   size_t iNum = 0;
324   FX_BIDIWEAKSTATE eState = FX_BWSxl;
325   FX_BIDICLASS eClsCur;
326   FX_BIDICLASS eClsRun;
327   FX_BIDICLASS eClsNew;
328   size_t i = 0;
329   for (; i <= iCount; ++i) {
330     CFX_Char* pTC = &(*chars)[i];
331     eClsCur = pTC->m_iBidiClass;
332     if (eClsCur == FX_BIDICLASS::kBN) {
333       pTC->m_iBidiLevel = (int16_t)iLevelCur;
334       if (i == iCount && iLevelCur != 0) {
335         eClsCur = Direction(iLevelCur);
336         pTC->m_iBidiClass = eClsCur;
337       } else if (i < iCount) {
338         CFX_Char* pTCNext = &(*chars)[i + 1];
339         int32_t iLevelNext, iLevelNew;
340         eClsNew = pTCNext->m_iBidiClass;
341         iLevelNext = pTCNext->m_iBidiLevel;
342         if (eClsNew != FX_BIDICLASS::kBN && iLevelCur != iLevelNext) {
343           iLevelNew = std::max(iLevelNext, iLevelCur);
344           pTC->m_iBidiLevel = static_cast<int16_t>(iLevelNew);
345           eClsCur = Direction(iLevelNew);
346           pTC->m_iBidiClass = eClsCur;
347           iLevelCur = iLevelNext;
348         } else {
349           if (iNum > 0)
350             ++iNum;
351           continue;
352         }
353       } else {
354         if (iNum > 0)
355           ++iNum;
356         continue;
357       }
358     }
359     if (eClsCur > FX_BIDICLASS::kBN)
360       continue;
361 
362     FX_BIDIWEAKACTION eAction = GetWeakAction(eState, eClsCur);
363     eClsRun = GetDeferredType(eAction);
364     if (eClsRun != static_cast<FX_BIDICLASS>(0xF) && iNum > 0) {
365       SetDeferredRunClass(chars, i, iNum, eClsRun);
366       iNum = 0;
367     }
368     eClsNew = GetResolvedType(eAction);
369     if (eClsNew != static_cast<FX_BIDICLASS>(0xF))
370       pTC->m_iBidiClass = eClsNew;
371     if (FX_BWAIX & eAction)
372       ++iNum;
373 
374     eState = GetWeakState(eState, eClsCur);
375   }
376   if (iNum == 0)
377     return;
378 
379   eClsCur = Direction(0);
380   eClsRun = GetDeferredType(GetWeakAction(eState, eClsCur));
381   if (eClsRun != static_cast<FX_BIDICLASS>(0xF))
382     SetDeferredRunClass(chars, i, iNum, eClsRun);
383 }
384 
ResolveNeutrals(std::vector<CFX_Char> * chars,size_t iCount)385 void ResolveNeutrals(std::vector<CFX_Char>* chars, size_t iCount) {
386   if (iCount <= 1)
387     return;
388   --iCount;
389 
390   CFX_Char* pTC;
391   int32_t iLevel = 0;
392   size_t i = 0;
393   size_t iNum = 0;
394   FX_BIDINEUTRALSTATE eState = FX_BNSl;
395   FX_BIDICLASS eClsCur;
396   FX_BIDICLASS eClsRun;
397   FX_BIDICLASS eClsNew;
398   for (; i <= iCount; ++i) {
399     pTC = &(*chars)[i];
400     eClsCur = pTC->m_iBidiClass;
401     if (eClsCur == FX_BIDICLASS::kBN) {
402       if (iNum)
403         ++iNum;
404       continue;
405     }
406     if (eClsCur >= FX_BIDICLASS::kAL)
407       continue;
408 
409     FX_BIDINEUTRALACTION eAction = GetNeutralAction(eState, eClsCur);
410     eClsRun = GetDeferredNeutrals(eAction, iLevel);
411     if (eClsRun != FX_BIDICLASS::kN && iNum > 0) {
412       SetDeferredRunClass(chars, i, iNum, eClsRun);
413       iNum = 0;
414     }
415 
416     eClsNew = GetResolvedNeutrals(eAction);
417     if (eClsNew != FX_BIDICLASS::kN)
418       pTC->m_iBidiClass = eClsNew;
419     if (FX_BNAIn & eAction)
420       ++iNum;
421 
422     eState = GetNeutralState(eState, eClsCur);
423     iLevel = pTC->m_iBidiLevel;
424   }
425   if (iNum == 0)
426     return;
427 
428   eClsCur = Direction(iLevel);
429   eClsRun = GetDeferredNeutrals(GetNeutralAction(eState, eClsCur), iLevel);
430   if (eClsRun != FX_BIDICLASS::kN)
431     SetDeferredRunClass(chars, i, iNum, eClsRun);
432 }
433 
ResolveImplicit(std::vector<CFX_Char> * chars,size_t iCount)434 void ResolveImplicit(std::vector<CFX_Char>* chars, size_t iCount) {
435   for (size_t i = 0; i < iCount; ++i) {
436     FX_BIDICLASS eCls = (*chars)[i].m_iBidiClass;
437     if (eCls == FX_BIDICLASS::kBN || eCls <= FX_BIDICLASS::kON ||
438         eCls >= FX_BIDICLASS::kAL) {
439       continue;
440     }
441     (*chars)[i].m_iBidiLevel += kAddLevel[FX_IsOdd((*chars)[i].m_iBidiLevel)]
442                                          [static_cast<size_t>(eCls) - 1];
443   }
444 }
445 
ResolveWhitespace(std::vector<CFX_Char> * chars,size_t iCount)446 void ResolveWhitespace(std::vector<CFX_Char>* chars, size_t iCount) {
447   if (iCount <= 1)
448     return;
449   iCount--;
450 
451   int32_t iLevel = 0;
452   size_t i = 0;
453   size_t iNum = 0;
454   for (; i <= iCount; ++i) {
455     switch (static_cast<FX_BIDICLASS>((*chars)[i].m_iBidiClass)) {
456       case FX_BIDICLASS::kWS:
457         ++iNum;
458         break;
459       case FX_BIDICLASS::kRLE:
460       case FX_BIDICLASS::kLRE:
461       case FX_BIDICLASS::kLRO:
462       case FX_BIDICLASS::kRLO:
463       case FX_BIDICLASS::kPDF:
464       case FX_BIDICLASS::kBN:
465         (*chars)[i].m_iBidiLevel = static_cast<int16_t>(iLevel);
466         ++iNum;
467         break;
468       case FX_BIDICLASS::kS:
469       case FX_BIDICLASS::kB:
470         if (iNum > 0)
471           SetDeferredRunLevel(chars, i, iNum, 0);
472 
473         (*chars)[i].m_iBidiLevel = 0;
474         iNum = 0;
475         break;
476       default:
477         iNum = 0;
478         break;
479     }
480     iLevel = (*chars)[i].m_iBidiLevel;
481   }
482   if (iNum > 0)
483     SetDeferredRunLevel(chars, i, iNum, 0);
484 }
485 
ReorderLevel(std::vector<CFX_Char> * chars,size_t iCount,int32_t iBaseLevel,size_t iStart,bool bReverse)486 size_t ReorderLevel(std::vector<CFX_Char>* chars,
487                     size_t iCount,
488                     int32_t iBaseLevel,
489                     size_t iStart,
490                     bool bReverse) {
491   ASSERT(iBaseLevel >= 0);
492   ASSERT(iBaseLevel <= kBidiMaxLevel);
493   ASSERT(iStart < iCount);
494 
495   if (iCount < 1)
496     return 0;
497 
498   bReverse = bReverse || FX_IsOdd(iBaseLevel);
499   size_t i = iStart;
500   for (; i < iCount; ++i) {
501     int32_t iLevel = (*chars)[i].m_iBidiLevel;
502     if (iLevel == iBaseLevel)
503       continue;
504     if (iLevel < iBaseLevel)
505       break;
506 
507     i += ReorderLevel(chars, iCount, iBaseLevel + 1, i, bReverse) - 1;
508   }
509 
510   size_t iNum = i - iStart;
511   if (bReverse && iNum > 1)
512     ReverseString(chars, iStart, iNum);
513 
514   return iNum;
515 }
516 
Reorder(std::vector<CFX_Char> * chars,size_t iCount)517 void Reorder(std::vector<CFX_Char>* chars, size_t iCount) {
518   for (size_t i = 0; i < iCount;)
519     i += ReorderLevel(chars, iCount, 0, i, false);
520 }
521 
Position(std::vector<CFX_Char> * chars,size_t iCount)522 void Position(std::vector<CFX_Char>* chars, size_t iCount) {
523   for (size_t i = 0; i < iCount; ++i) {
524     if ((*chars)[i].m_iBidiPos > iCount)
525       continue;
526 
527     (*chars)[(*chars)[i].m_iBidiPos].m_iBidiOrder = i;
528   }
529 }
530 
531 }  // namespace
532 
533 // static
BidiLine(std::vector<CFX_Char> * chars,size_t iCount)534 void CFX_Char::BidiLine(std::vector<CFX_Char>* chars, size_t iCount) {
535   ASSERT(iCount <= chars->size());
536   if (iCount < 2)
537     return;
538 
539   ClassifyWithTransform(chars, iCount);
540   ResolveExplicit(chars, iCount);
541   ResolveWeak(chars, iCount);
542   ResolveNeutrals(chars, iCount);
543   ResolveImplicit(chars, iCount);
544   Classify(chars, iCount);
545   ResolveWhitespace(chars, iCount);
546   Reorder(chars, iCount);
547   Position(chars, iCount);
548 }
549 
CFX_Char(uint16_t wCharCode)550 CFX_Char::CFX_Char(uint16_t wCharCode) : CFX_Char(wCharCode, 100, 100) {}
551 
CFX_Char(uint16_t wCharCode,int32_t iHorizontalScale,int32_t iVerticalScale)552 CFX_Char::CFX_Char(uint16_t wCharCode,
553                    int32_t iHorizontalScale,
554                    int32_t iVerticalScale)
555     : m_wCharCode(wCharCode),
556       m_iHorizontalScale(iHorizontalScale),
557       m_iVerticalScale(iVerticalScale) {}
558 
559 CFX_Char::CFX_Char(const CFX_Char& other) = default;
560 
561 CFX_Char::~CFX_Char() = default;
562 
GetCharType() const563 FX_CHARTYPE CFX_Char::GetCharType() const {
564   return FX_GetCharType(m_wCharCode);
565 }
566