7#include "xfa/fgas/layout/cfgas_char.h"
12#include "core/fxcrt/fx_extension.h"
13#include "core/fxcrt/stl_util.h"
14#include "third_party/base/check.h"
19constexpr int32_t kBidiMaxLevel = 61;
23#define PACK_NIBBLES(hi, lo)
24 ((static_cast<uint32_t>(hi) << 4
) + static_cast<uint32_t>(lo))
26enum FX_BIDIWEAKSTATE : uint8_t {
53enum FX_BIDIWEAKACTION : uint16_t {
57 FX_BWAxIx = 0x100 + FX_BWAxxx,
78enum FX_BIDINEUTRALSTATE : uint8_t {
87enum FX_BIDINEUTRALACTION : uint16_t {
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},
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},
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},
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},
215const uint8_t kAddLevel[2][4] = {
232FX_BIDICLASS GetDeferredNeutrals(int32_t iAction, int32_t iLevel) {
238 return GetResolvedType(iAction);
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)];
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)];
253FX_BIDINEUTRALSTATE GetNeutralState(FX_BIDINEUTRALSTATE eState,
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)];
261FX_BIDINEUTRALACTION GetNeutralAction(FX_BIDINEUTRALSTATE eState,
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)];
269void ReverseString(std::vector<CFGAS_Char>* chars,
272 DCHECK(fxcrt::IndexInBounds(*chars, iStart));
273 DCHECK(iStart + iCount <= chars->size());
275 std::reverse(chars->begin() + iStart, chars->begin() + iStart + iCount);
278void SetDeferredRunClass(std::vector<CFGAS_Char>* chars,
282 DCHECK(iStart <= chars->size());
283 DCHECK(iStart >= iCount);
285 size_t iLast = iStart - iCount;
286 for (size_t i = iStart; i > iLast; --i)
287 (*chars)[i - 1].m_iBidiClass = eValue;
290void SetDeferredRunLevel(std::vector<CFGAS_Char>* chars,
294 DCHECK(iStart <= chars->size());
295 DCHECK(iStart >= iCount);
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);
302void Classify(std::vector<CFGAS_Char>* chars, size_t iCount) {
303 for (size_t i = 0; i < iCount; ++i) {
309void ClassifyWithTransform(std::vector<CFGAS_Char>* chars, size_t iCount) {
310 for (size_t i = 0; i < iCount; ++i) {
312 cur.m_iBidiClass = kNTypes[
static_cast<size_t>(
313 pdfium::unicode::GetBidiClass(cur.char_code()))];
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;
322void ResolveWeak(std::vector<CFGAS_Char>* chars, size_t iCount) {
327 int32_t iLevelCur = 0;
329 FX_BIDIWEAKSTATE eState = FX_BWSxl;
334 for (; i <= iCount; ++i) {
339 if (i == iCount && iLevelCur != 0) {
340 eClsCur = Direction(iLevelCur);
342 }
else if (i < iCount) {
347 int32_t iLevelNew =
std::max(iLevelNext, iLevelCur);
349 eClsCur = Direction(iLevelNew);
351 iLevelCur = iLevelNext;
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);
372 eClsNew = GetResolvedType(eAction);
375 if (FX_BWAIX & eAction)
378 eState = GetWeakState(eState, eClsCur);
383 eClsCur = Direction(0);
384 eClsRun = GetDeferredType(GetWeakAction(eState, eClsCur));
386 SetDeferredRunClass(chars, i, iNum, eClsRun);
389void ResolveNeutrals(std::vector<CFGAS_Char>* chars, size_t iCount) {
398 FX_BIDINEUTRALSTATE eState = FX_BNSl;
402 for (; i <= iCount; ++i) {
413 FX_BIDINEUTRALACTION eAction = GetNeutralAction(eState, eClsCur);
414 eClsRun = GetDeferredNeutrals(eAction, iLevel);
416 SetDeferredRunClass(chars, i, iNum, eClsRun);
420 eClsNew = GetResolvedNeutrals(eAction);
423 if (FX_BNAIn & eAction)
426 eState = GetNeutralState(eState, eClsCur);
432 eClsCur = Direction(iLevel);
433 eClsRun = GetDeferredNeutrals(GetNeutralAction(eState, eClsCur), iLevel);
435 SetDeferredRunClass(chars, i, iNum, eClsRun);
438void ResolveImplicit(std::vector<CFGAS_Char>* chars, size_t iCount) {
439 for (size_t i = 0; i < iCount; ++i) {
445 (*chars)[i].m_iBidiLevel += kAddLevel[
FX_IsOdd((*chars)[i].m_iBidiLevel)]
446 [
static_cast<size_t>(eCls) - 1];
450void ResolveWhitespace(std::vector<CFGAS_Char>* chars, size_t iCount) {
458 for (; i <= iCount; ++i) {
459 switch (
static_cast<
FX_BIDICLASS>((*chars)[i].m_iBidiClass)) {
469 (*chars)[i].m_iBidiLevel =
static_cast<int16_t>(iLevel);
475 SetDeferredRunLevel(chars, i, iNum, 0);
477 (*chars)[i].m_iBidiLevel = 0;
484 iLevel = (*chars)[i].m_iBidiLevel;
487 SetDeferredRunLevel(chars, i, iNum, 0);
490size_t ReorderLevel(std::vector<CFGAS_Char>* chars,
495 DCHECK(iBaseLevel >= 0);
496 DCHECK(iBaseLevel <= kBidiMaxLevel);
497 DCHECK(iStart < iCount);
502 bReverse = bReverse ||
FX_IsOdd(iBaseLevel);
504 for (; i < iCount; ++i) {
505 int32_t iLevel = (*chars)[i].m_iBidiLevel;
506 if (iLevel == iBaseLevel)
508 if (iLevel < iBaseLevel)
511 i += ReorderLevel(chars, iCount, iBaseLevel + 1, i, bReverse) - 1;
514 size_t iNum = i - iStart;
515 if (bReverse && iNum > 1)
516 ReverseString(chars, iStart, iNum);
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);
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)
531 (*chars)[(*chars)[i].m_iBidiPos].m_iBidiOrder = i;
538void CFGAS_Char::BidiLine(std::vector<CFGAS_Char>* chars, size_t iCount) {
539 DCHECK(iCount <= chars->size());
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);
557 int32_t iHorizontalScale,
558 int32_t iVerticalScale)
559 : m_wCharCode(wCharCode),
560 m_iHorizontalScale(iHorizontalScale),
561 m_iVerticalScale(iVerticalScale) {}
568 return pdfium::unicode::GetCharType(m_wCharCode);
#define PACK_NIBBLES(hi, lo)
CFGAS_Char(const CFGAS_Char &other)
FX_BIDICLASS m_iBidiClass
FX_CHARTYPE GetCharType() const
CFGAS_Char(uint16_t wCharCode)
CFGAS_Char(uint16_t wCharCode, int32_t iHorizontalScale, int32_t iVerticalScale)
uint16_t char_code() const
FX_BIDICLASS GetBidiClass(wchar_t wch)