7#include "xfa/fgas/layout/cfgas_char.h"
13#include "core/fxcrt/check.h"
14#include "core/fxcrt/fx_extension.h"
15#include "core/fxcrt/stl_util.h"
20constexpr int32_t kBidiMaxLevel = 61;
24#define PACK_NIBBLES(hi, lo)
25 ((static_cast<uint32_t>(hi) << 4
) + static_cast<uint32_t>(lo))
27enum FX_BIDIWEAKSTATE : uint8_t {
54enum FX_BIDIWEAKACTION : uint16_t {
58 FX_BWAxIx = 0x100 + FX_BWAxxx,
79enum FX_BIDINEUTRALSTATE : uint8_t {
88enum FX_BIDINEUTRALACTION : uint16_t {
111using WeakStateRow =
std::array<
const FX_BIDIWEAKSTATE, 10>;
112constexpr std::array<
const WeakStateRow, 20> kWeakStateTable = {{
113 {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSxa,
114 FX_BWSao, FX_BWSao, FX_BWSao},
115 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSxr,
116 FX_BWSro, FX_BWSro, FX_BWSrt},
117 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSxl,
118 FX_BWSlo, FX_BWSlo, FX_BWSlt},
119 {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
120 FX_BWSao, FX_BWSao, FX_BWSao},
121 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
122 FX_BWSro, FX_BWSro, FX_BWSrt},
123 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
124 FX_BWSlo, FX_BWSlo, FX_BWSlt},
125 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSrt,
126 FX_BWSro, FX_BWSro, FX_BWSrt},
127 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlt,
128 FX_BWSlo, FX_BWSlo, FX_BWSlt},
129 {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWScn,
130 FX_BWSac, FX_BWSao, FX_BWSao},
131 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSra,
132 FX_BWSrc, FX_BWSro, FX_BWSrt},
133 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSre,
134 FX_BWSrs, FX_BWSrs, FX_BWSret},
135 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSla,
136 FX_BWSlc, FX_BWSlo, FX_BWSlt},
137 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSle,
138 FX_BWSls, FX_BWSls, FX_BWSlet},
139 {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
140 FX_BWSao, FX_BWSao, FX_BWSao},
141 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
142 FX_BWSro, FX_BWSro, FX_BWSrt},
143 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
144 FX_BWSro, FX_BWSro, FX_BWSrt},
145 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
146 FX_BWSlo, FX_BWSlo, FX_BWSlt},
147 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
148 FX_BWSlo, FX_BWSlo, FX_BWSlt},
149 {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSret,
150 FX_BWSro, FX_BWSro, FX_BWSret},
151 {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlet,
152 FX_BWSlo, FX_BWSlo, FX_BWSlet},
155using WeakActionRow =
std::array<
const FX_BIDIWEAKACTION, 10>;
156constexpr std::array<
const WeakActionRow, 20> kWeakActionTable = {{
157 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
158 FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
159 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
160 FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
161 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
162 FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
163 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
164 FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
165 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
166 FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
167 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
168 FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
169 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
170 FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
171 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
172 FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
173 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
174 FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxxN},
175 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
176 FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
177 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
178 FX_BWAxxE, FX_BWAxIx, FX_BWAxIx, FX_BWAxxE},
179 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
180 FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
181 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
182 FX_BWAxxL, FX_BWAxIx, FX_BWAxIx, FX_BWAxxL},
183 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWAAxA, FX_BWANxR,
184 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANxN},
185 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxE, FX_BWANxR,
186 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
187 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
188 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
189 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxL, FX_BWANxR,
190 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
191 {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
192 FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
193 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
194 FX_BWAxxE, FX_BWAxxN, FX_BWAxxN, FX_BWAxxE},
195 {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
196 FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxxL},
199using NeutralStateRow =
std::array<
const FX_BIDINEUTRALSTATE, 5>;
200constexpr std::array<
const NeutralStateRow, 6> kNeutralStateTable = {{
201 {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
202 {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
203 {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
204 {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
205 {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
206 {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
209using NeutralActionRow =
std::array<
const FX_BIDINEUTRALACTION, 5>;
210constexpr std::array<
const NeutralActionRow, 6> kNeutralActionTable = {{
211 {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAZero},
212 {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAnL},
213 {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNARn},
214 {FX_BNAIn, FX_BNALn, FX_BNAEn, FX_BNAEn, FX_BNALnL},
215 {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAnL},
216 {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNAEn},
219using AddLevelRow =
std::array<
const uint8_t, 4>;
220constexpr std::array<
const AddLevelRow, 2> kAddLevelTable = {{
237FX_BIDICLASS GetDeferredNeutrals(int32_t iAction, int32_t iLevel) {
243 return GetResolvedType(iAction);
246FX_BIDIWEAKSTATE GetWeakState(FX_BIDIWEAKSTATE eState,
FX_BIDICLASS eClass) {
247 return kWeakStateTable[
static_cast<size_t>(eState)]
248 [
static_cast<size_t>(eClass)];
251FX_BIDIWEAKACTION GetWeakAction(FX_BIDIWEAKSTATE eState,
FX_BIDICLASS eClass) {
252 return kWeakActionTable[
static_cast<size_t>(eState)]
253 [
static_cast<size_t>(eClass)];
256FX_BIDINEUTRALSTATE GetNeutralState(FX_BIDINEUTRALSTATE eState,
258 return kNeutralStateTable[
static_cast<size_t>(eState)]
259 [
static_cast<size_t>(eClass)];
262FX_BIDINEUTRALACTION GetNeutralAction(FX_BIDINEUTRALSTATE eState,
264 return kNeutralActionTable[
static_cast<size_t>(eState)]
265 [
static_cast<size_t>(eClass)];
268void ReverseString(std::vector<CFGAS_Char>* chars,
271 DCHECK(fxcrt::IndexInBounds(*chars, iStart));
272 DCHECK(iStart + iCount <= chars->size());
274 std::reverse(chars->begin() + iStart, chars->begin() + iStart + iCount);
277void SetDeferredRunClass(std::vector<CFGAS_Char>* chars,
281 DCHECK(iStart <= chars->size());
284 size_t iLast = iStart - iCount;
285 for (size_t i = iStart; i > iLast; --i)
286 (*chars)[i - 1].m_iBidiClass = eValue;
289void SetDeferredRunLevel(std::vector<CFGAS_Char>* chars,
293 DCHECK(iStart <= chars->size());
296 size_t iLast = iStart - iCount;
297 for (size_t i = iStart; i > iLast; --i)
298 (*chars)[i - 1].m_iBidiLevel =
static_cast<int16_t>(iValue);
301void Classify(std::vector<CFGAS_Char>* chars, size_t iCount) {
302 for (size_t i = 0; i < iCount; ++i) {
308void ClassifyWithTransform(std::vector<CFGAS_Char>* chars, size_t iCount) {
309 for (size_t i = 0; i < iCount; ++i) {
316void ResolveExplicit(std::vector<CFGAS_Char>* chars, size_t iCount) {
317 for (size_t i = 0; i < iCount; ++i)
318 (*chars)[i].m_iBidiLevel = 0;
321void ResolveWeak(std::vector<CFGAS_Char>* chars, size_t iCount) {
326 int32_t iLevelCur = 0;
328 FX_BIDIWEAKSTATE eState = FX_BWSxl;
333 for (; i <= iCount; ++i) {
338 if (i == iCount && iLevelCur != 0) {
339 eClsCur = Direction(iLevelCur);
341 }
else if (i < iCount) {
346 int32_t iLevelNew =
std::max(iLevelNext, iLevelCur);
348 eClsCur = Direction(iLevelNew);
350 iLevelCur = iLevelNext;
365 FX_BIDIWEAKACTION eAction = GetWeakAction(eState, eClsCur);
366 eClsRun = GetDeferredType(eAction);
367 if (eClsRun !=
static_cast<
FX_BIDICLASS>(0xF) && iNum > 0) {
368 SetDeferredRunClass(chars, i, iNum, eClsRun);
371 eClsNew = GetResolvedType(eAction);
374 if (FX_BWAIX & eAction)
377 eState = GetWeakState(eState, eClsCur);
382 eClsCur = Direction(0);
383 eClsRun = GetDeferredType(GetWeakAction(eState, eClsCur));
385 SetDeferredRunClass(chars, i, iNum, eClsRun);
388void ResolveNeutrals(std::vector<CFGAS_Char>* chars, size_t iCount) {
397 FX_BIDINEUTRALSTATE eState = FX_BNSl;
401 for (; i <= iCount; ++i) {
412 FX_BIDINEUTRALACTION eAction = GetNeutralAction(eState, eClsCur);
413 eClsRun = GetDeferredNeutrals(eAction, iLevel);
415 SetDeferredRunClass(chars, i, iNum, eClsRun);
419 eClsNew = GetResolvedNeutrals(eAction);
422 if (FX_BNAIn & eAction)
425 eState = GetNeutralState(eState, eClsCur);
431 eClsCur = Direction(iLevel);
432 eClsRun = GetDeferredNeutrals(GetNeutralAction(eState, eClsCur), iLevel);
434 SetDeferredRunClass(chars, i, iNum, eClsRun);
437void ResolveImplicit(std::vector<CFGAS_Char>* chars, size_t iCount) {
438 for (size_t i = 0; i < iCount; ++i) {
444 (*chars)[i].m_iBidiLevel +=
445 kAddLevelTable[
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,
496 DCHECK(iBaseLevel <= kBidiMaxLevel);
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)