blob: f1f6bfc3bd3d60cf2aecfa17cdcc3d3b4a27171b [file] [log] [blame]
kumarashishg826308d2023-06-23 13:21:22 +00001// 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
16namespace {
17
18#if DCHECK_IS_ON()
19constexpr 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
26enum 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.
53enum 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
78enum 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
87enum 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
101const 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
111const 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
154const 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
197const 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
206const 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
215const uint8_t kAddLevel[2][4] = {
216 {0, 1, 2, 2},
217 {1, 0, 1, 1},
218};
219
220FX_BIDICLASS Direction(int32_t val) {
221 return FX_IsOdd(val) ? FX_BIDICLASS::kR : FX_BIDICLASS::kL;
222}
223
224FX_BIDICLASS GetDeferredType(int32_t val) {
225 return static_cast<FX_BIDICLASS>((val >> 4) & 0x0F);
226}
227
228FX_BIDICLASS GetResolvedType(int32_t val) {
229 return static_cast<FX_BIDICLASS>(val & 0x0F);
230}
231
232FX_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
237FX_BIDICLASS GetResolvedNeutrals(int32_t iAction) {
238 return GetResolvedType(iAction);
239}
240
241FX_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
247FX_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
253FX_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
261FX_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
269void 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
278void 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
290void 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
302void 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
309void 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
317void 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
322void 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
389void 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
438void 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
450void 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
490size_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
521void 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
526void 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
538void 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
554CFGAS_Char::CFGAS_Char(uint16_t wCharCode) : CFGAS_Char(wCharCode, 100, 100) {}
555
556CFGAS_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
563CFGAS_Char::CFGAS_Char(const CFGAS_Char& other) = default;
564
565CFGAS_Char::~CFGAS_Char() = default;
566
567FX_CHARTYPE CFGAS_Char::GetCharType() const {
568 return pdfium::unicode::GetCharType(m_wCharCode);
569}