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