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