Dis-entangle cfx_char.h from fx_bidi.h.
The one function in fx_bidi.h that references cfx_chars becomes a
static method in cfx_char.h. Then all of the other XFA-only code
moves to cfx_char.cpp, which is appropriate since it is twiddling
vectors of CFX_Char anyways. Some ifdef XFAs go away in the process.
Change-Id: I70c21be4865ceaa35852df77017f47cf1c58f440
Reviewed-on: https://pdfium-review.googlesource.com/c/48230
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/cfx_char.cpp b/core/fxcrt/cfx_char.cpp
index 15fe47d..02d051f 100644
--- a/core/fxcrt/cfx_char.cpp
+++ b/core/fxcrt/cfx_char.cpp
@@ -6,6 +6,547 @@
#include "core/fxcrt/cfx_char.h"
+#include <algorithm>
+
+#include "core/fxcrt/fx_extension.h"
+
+namespace {
+
+#ifndef NDEBUG
+constexpr int32_t kBidiMaxLevel = 61;
+#endif // NDEBUG
+
+#undef PACK_NIBBLES
+#define PACK_NIBBLES(hi, lo) \
+ ((static_cast<uint32_t>(hi) << 4) + static_cast<uint32_t>(lo))
+
+enum FX_BIDIWEAKSTATE : uint8_t {
+ FX_BWSxa = 0,
+ FX_BWSxr,
+ FX_BWSxl,
+ FX_BWSao,
+ FX_BWSro,
+ FX_BWSlo,
+ FX_BWSrt,
+ FX_BWSlt,
+ FX_BWScn,
+ FX_BWSra,
+ FX_BWSre,
+ FX_BWSla,
+ FX_BWSle,
+ FX_BWSac,
+ FX_BWSrc,
+ FX_BWSrs,
+ FX_BWSlc,
+ FX_BWSls,
+ FX_BWSret,
+ FX_BWSlet
+};
+
+// NOTE: Range of FX_BIDICLASS prevents encoding all possible values in this
+// manner, but the ones used manage to fit. Except that I suspect that 0xF
+// was intended to be used as a sentinel, even though it also means kRLE.
+// TODO(tsepez): pick a better representation.
+enum FX_BIDIWEAKACTION : uint16_t {
+ FX_BWAIX = 0x100,
+ FX_BWAXX = 0x0F,
+ FX_BWAxxx = 0xFF,
+ FX_BWAxIx = 0x100 + FX_BWAxxx,
+ FX_BWAxxN = PACK_NIBBLES(0x0F, FX_BIDICLASS::kON),
+ FX_BWAxxE = PACK_NIBBLES(0x0F, FX_BIDICLASS::kEN),
+ FX_BWAxxA = PACK_NIBBLES(0x0F, FX_BIDICLASS::kAN),
+ FX_BWAxxR = PACK_NIBBLES(0x0F, FX_BIDICLASS::kR),
+ FX_BWAxxL = PACK_NIBBLES(0x0F, FX_BIDICLASS::kL),
+ FX_BWANxx = PACK_NIBBLES(FX_BIDICLASS::kON, 0x0F),
+ FX_BWAAxx = PACK_NIBBLES(FX_BIDICLASS::kAN, 0x0F),
+ FX_BWAExE = PACK_NIBBLES(FX_BIDICLASS::kEN, FX_BIDICLASS::kEN),
+ FX_BWANIx = 0x100 + PACK_NIBBLES(FX_BIDICLASS::kON, 0x0F),
+ FX_BWANxN = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kON),
+ FX_BWANxR = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kR),
+ FX_BWANxE = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kEN),
+ FX_BWAAxA = PACK_NIBBLES(FX_BIDICLASS::kAN, FX_BIDICLASS::kAN),
+ FX_BWANxL = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kL),
+ FX_BWALxL = PACK_NIBBLES(FX_BIDICLASS::kL, FX_BIDICLASS::kL),
+ FX_BWAxIL = 0x100 + PACK_NIBBLES(0x0F, FX_BIDICLASS::kL),
+ FX_BWAAxR = PACK_NIBBLES(FX_BIDICLASS::kAN, FX_BIDICLASS::kR),
+ FX_BWALxx = PACK_NIBBLES(FX_BIDICLASS::kL, 0x0F),
+};
+
+enum FX_BIDINEUTRALSTATE : uint8_t {
+ FX_BNSr = 0,
+ FX_BNSl,
+ FX_BNSrn,
+ FX_BNSln,
+ FX_BNSa,
+ FX_BNSna
+};
+
+enum FX_BIDINEUTRALACTION : uint16_t {
+ // For placeholders in table.
+ FX_BNAZero = 0,
+
+ // Other values.
+ FX_BNAnL = PACK_NIBBLES(0, FX_BIDICLASS::kL),
+ FX_BNAEn = PACK_NIBBLES(FX_BIDICLASS::kAN, 0),
+ FX_BNARn = PACK_NIBBLES(FX_BIDICLASS::kR, 0),
+ FX_BNALn = PACK_NIBBLES(FX_BIDICLASS::kL, 0),
+ FX_BNAIn = FX_BWAIX,
+ FX_BNALnL = PACK_NIBBLES(FX_BIDICLASS::kL, FX_BIDICLASS::kL),
+};
+#undef PACK_NIBBLES
+
+const FX_BIDICLASS kNTypes[] = {
+ FX_BIDICLASS::kN, FX_BIDICLASS::kL, FX_BIDICLASS::kR,
+ FX_BIDICLASS::kAN, FX_BIDICLASS::kEN, FX_BIDICLASS::kAL,
+ FX_BIDICLASS::kNSM, FX_BIDICLASS::kCS, FX_BIDICLASS::kES,
+ FX_BIDICLASS::kET, FX_BIDICLASS::kBN, FX_BIDICLASS::kBN,
+ FX_BIDICLASS::kN, FX_BIDICLASS::kB, FX_BIDICLASS::kRLO,
+ FX_BIDICLASS::kRLE, FX_BIDICLASS::kLRO, FX_BIDICLASS::kLRE,
+ FX_BIDICLASS::kPDF, FX_BIDICLASS::kON,
+};
+
+const FX_BIDIWEAKSTATE kWeakStates[20][10] = {
+ {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSxa,
+ FX_BWSao, FX_BWSao, FX_BWSao},
+ {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSxr,
+ FX_BWSro, FX_BWSro, FX_BWSrt},
+ {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSxl,
+ FX_BWSlo, FX_BWSlo, FX_BWSlt},
+ {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
+ FX_BWSao, FX_BWSao, FX_BWSao},
+ {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
+ FX_BWSro, FX_BWSro, FX_BWSrt},
+ {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
+ FX_BWSlo, FX_BWSlo, FX_BWSlt},
+ {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSrt,
+ FX_BWSro, FX_BWSro, FX_BWSrt},
+ {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlt,
+ FX_BWSlo, FX_BWSlo, FX_BWSlt},
+ {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWScn,
+ FX_BWSac, FX_BWSao, FX_BWSao},
+ {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSra,
+ FX_BWSrc, FX_BWSro, FX_BWSrt},
+ {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSre,
+ FX_BWSrs, FX_BWSrs, FX_BWSret},
+ {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSla,
+ FX_BWSlc, FX_BWSlo, FX_BWSlt},
+ {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSle,
+ FX_BWSls, FX_BWSls, FX_BWSlet},
+ {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
+ FX_BWSao, FX_BWSao, FX_BWSao},
+ {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
+ FX_BWSro, FX_BWSro, FX_BWSrt},
+ {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
+ FX_BWSro, FX_BWSro, FX_BWSrt},
+ {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
+ FX_BWSlo, FX_BWSlo, FX_BWSlt},
+ {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
+ FX_BWSlo, FX_BWSlo, FX_BWSlt},
+ {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSret,
+ FX_BWSro, FX_BWSro, FX_BWSret},
+ {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlet,
+ FX_BWSlo, FX_BWSlo, FX_BWSlet},
+};
+
+const FX_BIDIWEAKACTION kWeakActions[20][10] = {
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
+ FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
+ FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
+ FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
+ FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
+ FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
+ FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
+ {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
+ FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
+ {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
+ FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
+ FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxxN},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
+ FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
+ FX_BWAxxE, FX_BWAxIx, FX_BWAxIx, FX_BWAxxE},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
+ FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
+ FX_BWAxxL, FX_BWAxIx, FX_BWAxIx, FX_BWAxxL},
+ {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWAAxA, FX_BWANxR,
+ FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANxN},
+ {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxE, FX_BWANxR,
+ FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
+ {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
+ FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
+ {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxL, FX_BWANxR,
+ FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
+ {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
+ FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
+ FX_BWAxxE, FX_BWAxxN, FX_BWAxxN, FX_BWAxxE},
+ {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
+ FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxxL},
+};
+
+const FX_BIDINEUTRALSTATE kNeutralStates[6][5] = {
+ {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
+ {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
+ {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
+ {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
+ {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
+ {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
+};
+
+const FX_BIDINEUTRALACTION kNeutralActions[6][5] = {
+ {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAZero},
+ {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAnL},
+ {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNARn},
+ {FX_BNAIn, FX_BNALn, FX_BNAEn, FX_BNAEn, FX_BNALnL},
+ {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAnL},
+ {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNAEn},
+};
+
+const uint8_t kAddLevel[2][4] = {
+ {0, 1, 2, 2},
+ {1, 0, 1, 1},
+};
+
+FX_BIDICLASS Direction(int32_t val) {
+ return FX_IsOdd(val) ? FX_BIDICLASS::kR : FX_BIDICLASS::kL;
+}
+
+FX_BIDICLASS GetDeferredType(int32_t val) {
+ return static_cast<FX_BIDICLASS>((val >> 4) & 0x0F);
+}
+
+FX_BIDICLASS GetResolvedType(int32_t val) {
+ return static_cast<FX_BIDICLASS>(val & 0x0F);
+}
+
+FX_BIDICLASS GetDeferredNeutrals(int32_t iAction, int32_t iLevel) {
+ FX_BIDICLASS eClass = GetDeferredType(iAction);
+ return eClass == FX_BIDICLASS::kAN ? Direction(iLevel) : eClass;
+}
+
+FX_BIDICLASS GetResolvedNeutrals(int32_t iAction) {
+ return GetResolvedType(iAction);
+}
+
+FX_BIDIWEAKSTATE GetWeakState(FX_BIDIWEAKSTATE eState, FX_BIDICLASS eClass) {
+ ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kWeakStates));
+ ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kWeakStates[0]));
+ return kWeakStates[static_cast<size_t>(eState)][static_cast<size_t>(eClass)];
+}
+
+FX_BIDIWEAKACTION GetWeakAction(FX_BIDIWEAKSTATE eState, FX_BIDICLASS eClass) {
+ ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kWeakActions));
+ ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kWeakActions[0]));
+ return kWeakActions[static_cast<size_t>(eState)][static_cast<size_t>(eClass)];
+}
+
+FX_BIDINEUTRALSTATE GetNeutralState(FX_BIDINEUTRALSTATE eState,
+ FX_BIDICLASS eClass) {
+ ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kNeutralStates));
+ ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kNeutralStates[0]));
+ return kNeutralStates[static_cast<size_t>(eState)]
+ [static_cast<size_t>(eClass)];
+}
+
+FX_BIDINEUTRALACTION GetNeutralAction(FX_BIDINEUTRALSTATE eState,
+ FX_BIDICLASS eClass) {
+ ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kNeutralActions));
+ ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kNeutralActions[0]));
+ return kNeutralActions[static_cast<size_t>(eState)]
+ [static_cast<size_t>(eClass)];
+}
+
+void ReverseString(std::vector<CFX_Char>* chars, size_t iStart, size_t iCount) {
+ ASSERT(pdfium::IndexInBounds(*chars, iStart));
+ ASSERT(iStart + iCount <= chars->size());
+
+ std::reverse(chars->begin() + iStart, chars->begin() + iStart + iCount);
+}
+
+void SetDeferredRunClass(std::vector<CFX_Char>* chars,
+ size_t iStart,
+ size_t iCount,
+ FX_BIDICLASS eValue) {
+ ASSERT(iStart <= chars->size());
+ ASSERT(iStart >= iCount);
+
+ size_t iLast = iStart - iCount;
+ for (size_t i = iStart; i > iLast; --i)
+ (*chars)[i - 1].m_iBidiClass = eValue;
+}
+
+void SetDeferredRunLevel(std::vector<CFX_Char>* chars,
+ size_t iStart,
+ size_t iCount,
+ int32_t iValue) {
+ ASSERT(iStart <= chars->size());
+ ASSERT(iStart >= iCount);
+
+ size_t iLast = iStart - iCount;
+ for (size_t i = iStart; i > iLast; --i)
+ (*chars)[i - 1].m_iBidiLevel = static_cast<int16_t>(iValue);
+}
+
+void Classify(std::vector<CFX_Char>* chars, size_t iCount) {
+ for (size_t i = 0; i < iCount; ++i) {
+ CFX_Char& cur = (*chars)[i];
+ cur.m_iBidiClass = FX_GetBidiClass(cur.char_code());
+ }
+}
+
+void ClassifyWithTransform(std::vector<CFX_Char>* chars, size_t iCount) {
+ for (size_t i = 0; i < iCount; ++i) {
+ CFX_Char& cur = (*chars)[i];
+ cur.m_iBidiClass =
+ kNTypes[static_cast<size_t>(FX_GetBidiClass(cur.char_code()))];
+ }
+}
+
+void ResolveExplicit(std::vector<CFX_Char>* chars, size_t iCount) {
+ for (size_t i = 0; i < iCount; ++i)
+ (*chars)[i].m_iBidiLevel = 0;
+}
+
+void ResolveWeak(std::vector<CFX_Char>* chars, size_t iCount) {
+ if (iCount <= 1)
+ return;
+ --iCount;
+
+ int32_t iLevelCur = 0;
+ size_t iNum = 0;
+ FX_BIDIWEAKSTATE eState = FX_BWSxl;
+ FX_BIDICLASS eClsCur;
+ FX_BIDICLASS eClsRun;
+ FX_BIDICLASS eClsNew;
+ size_t i = 0;
+ for (; i <= iCount; ++i) {
+ CFX_Char* pTC = &(*chars)[i];
+ eClsCur = pTC->m_iBidiClass;
+ if (eClsCur == FX_BIDICLASS::kBN) {
+ pTC->m_iBidiLevel = (int16_t)iLevelCur;
+ if (i == iCount && iLevelCur != 0) {
+ eClsCur = Direction(iLevelCur);
+ pTC->m_iBidiClass = eClsCur;
+ } else if (i < iCount) {
+ CFX_Char* pTCNext = &(*chars)[i + 1];
+ int32_t iLevelNext, iLevelNew;
+ eClsNew = pTCNext->m_iBidiClass;
+ iLevelNext = pTCNext->m_iBidiLevel;
+ if (eClsNew != FX_BIDICLASS::kBN && iLevelCur != iLevelNext) {
+ iLevelNew = std::max(iLevelNext, iLevelCur);
+ pTC->m_iBidiLevel = static_cast<int16_t>(iLevelNew);
+ eClsCur = Direction(iLevelNew);
+ pTC->m_iBidiClass = eClsCur;
+ iLevelCur = iLevelNext;
+ } else {
+ if (iNum > 0)
+ ++iNum;
+ continue;
+ }
+ } else {
+ if (iNum > 0)
+ ++iNum;
+ continue;
+ }
+ }
+ if (eClsCur > FX_BIDICLASS::kBN)
+ continue;
+
+ FX_BIDIWEAKACTION eAction = GetWeakAction(eState, eClsCur);
+ eClsRun = GetDeferredType(eAction);
+ if (eClsRun != static_cast<FX_BIDICLASS>(0xF) && iNum > 0) {
+ SetDeferredRunClass(chars, i, iNum, eClsRun);
+ iNum = 0;
+ }
+ eClsNew = GetResolvedType(eAction);
+ if (eClsNew != static_cast<FX_BIDICLASS>(0xF))
+ pTC->m_iBidiClass = eClsNew;
+ if (FX_BWAIX & eAction)
+ ++iNum;
+
+ eState = GetWeakState(eState, eClsCur);
+ }
+ if (iNum == 0)
+ return;
+
+ eClsCur = Direction(0);
+ eClsRun = GetDeferredType(GetWeakAction(eState, eClsCur));
+ if (eClsRun != static_cast<FX_BIDICLASS>(0xF))
+ SetDeferredRunClass(chars, i, iNum, eClsRun);
+}
+
+void ResolveNeutrals(std::vector<CFX_Char>* chars, size_t iCount) {
+ if (iCount <= 1)
+ return;
+ --iCount;
+
+ CFX_Char* pTC;
+ int32_t iLevel = 0;
+ size_t i = 0;
+ size_t iNum = 0;
+ FX_BIDINEUTRALSTATE eState = FX_BNSl;
+ FX_BIDICLASS eClsCur;
+ FX_BIDICLASS eClsRun;
+ FX_BIDICLASS eClsNew;
+ for (; i <= iCount; ++i) {
+ pTC = &(*chars)[i];
+ eClsCur = pTC->m_iBidiClass;
+ if (eClsCur == FX_BIDICLASS::kBN) {
+ if (iNum)
+ ++iNum;
+ continue;
+ }
+ if (eClsCur >= FX_BIDICLASS::kAL)
+ continue;
+
+ FX_BIDINEUTRALACTION eAction = GetNeutralAction(eState, eClsCur);
+ eClsRun = GetDeferredNeutrals(eAction, iLevel);
+ if (eClsRun != FX_BIDICLASS::kN && iNum > 0) {
+ SetDeferredRunClass(chars, i, iNum, eClsRun);
+ iNum = 0;
+ }
+
+ eClsNew = GetResolvedNeutrals(eAction);
+ if (eClsNew != FX_BIDICLASS::kN)
+ pTC->m_iBidiClass = eClsNew;
+ if (FX_BNAIn & eAction)
+ ++iNum;
+
+ eState = GetNeutralState(eState, eClsCur);
+ iLevel = pTC->m_iBidiLevel;
+ }
+ if (iNum == 0)
+ return;
+
+ eClsCur = Direction(iLevel);
+ eClsRun = GetDeferredNeutrals(GetNeutralAction(eState, eClsCur), iLevel);
+ if (eClsRun != FX_BIDICLASS::kN)
+ SetDeferredRunClass(chars, i, iNum, eClsRun);
+}
+
+void ResolveImplicit(std::vector<CFX_Char>* chars, size_t iCount) {
+ for (size_t i = 0; i < iCount; ++i) {
+ FX_BIDICLASS eCls = (*chars)[i].m_iBidiClass;
+ if (eCls == FX_BIDICLASS::kBN || eCls <= FX_BIDICLASS::kON ||
+ eCls >= FX_BIDICLASS::kAL) {
+ continue;
+ }
+ (*chars)[i].m_iBidiLevel += kAddLevel[FX_IsOdd((*chars)[i].m_iBidiLevel)]
+ [static_cast<size_t>(eCls) - 1];
+ }
+}
+
+void ResolveWhitespace(std::vector<CFX_Char>* chars, size_t iCount) {
+ if (iCount <= 1)
+ return;
+ iCount--;
+
+ int32_t iLevel = 0;
+ size_t i = 0;
+ size_t iNum = 0;
+ for (; i <= iCount; ++i) {
+ switch (static_cast<FX_BIDICLASS>((*chars)[i].m_iBidiClass)) {
+ case FX_BIDICLASS::kWS:
+ ++iNum;
+ break;
+ case FX_BIDICLASS::kRLE:
+ case FX_BIDICLASS::kLRE:
+ case FX_BIDICLASS::kLRO:
+ case FX_BIDICLASS::kRLO:
+ case FX_BIDICLASS::kPDF:
+ case FX_BIDICLASS::kBN:
+ (*chars)[i].m_iBidiLevel = static_cast<int16_t>(iLevel);
+ ++iNum;
+ break;
+ case FX_BIDICLASS::kS:
+ case FX_BIDICLASS::kB:
+ if (iNum > 0)
+ SetDeferredRunLevel(chars, i, iNum, 0);
+
+ (*chars)[i].m_iBidiLevel = 0;
+ iNum = 0;
+ break;
+ default:
+ iNum = 0;
+ break;
+ }
+ iLevel = (*chars)[i].m_iBidiLevel;
+ }
+ if (iNum > 0)
+ SetDeferredRunLevel(chars, i, iNum, 0);
+}
+
+size_t ReorderLevel(std::vector<CFX_Char>* chars,
+ size_t iCount,
+ int32_t iBaseLevel,
+ size_t iStart,
+ bool bReverse) {
+ ASSERT(iBaseLevel >= 0);
+ ASSERT(iBaseLevel <= kBidiMaxLevel);
+ ASSERT(iStart < iCount);
+
+ if (iCount < 1)
+ return 0;
+
+ bReverse = bReverse || FX_IsOdd(iBaseLevel);
+ size_t i = iStart;
+ for (; i < iCount; ++i) {
+ int32_t iLevel = (*chars)[i].m_iBidiLevel;
+ if (iLevel == iBaseLevel)
+ continue;
+ if (iLevel < iBaseLevel)
+ break;
+
+ i += ReorderLevel(chars, iCount, iBaseLevel + 1, i, bReverse) - 1;
+ }
+
+ size_t iNum = i - iStart;
+ if (bReverse && iNum > 1)
+ ReverseString(chars, iStart, iNum);
+
+ return iNum;
+}
+
+void Reorder(std::vector<CFX_Char>* chars, size_t iCount) {
+ for (size_t i = 0; i < iCount;)
+ i += ReorderLevel(chars, iCount, 0, i, false);
+}
+
+void Position(std::vector<CFX_Char>* chars, size_t iCount) {
+ for (size_t i = 0; i < iCount; ++i) {
+ if ((*chars)[i].m_iBidiPos > iCount)
+ continue;
+
+ (*chars)[(*chars)[i].m_iBidiPos].m_iBidiOrder = i;
+ }
+}
+
+} // namespace
+
+// static
+void CFX_Char::BidiLine(std::vector<CFX_Char>* chars, size_t iCount) {
+ ASSERT(iCount <= chars->size());
+ if (iCount < 2)
+ return;
+
+ ClassifyWithTransform(chars, iCount);
+ ResolveExplicit(chars, iCount);
+ ResolveWeak(chars, iCount);
+ ResolveNeutrals(chars, iCount);
+ ResolveImplicit(chars, iCount);
+ Classify(chars, iCount);
+ ResolveWhitespace(chars, iCount);
+ Reorder(chars, iCount);
+ Position(chars, iCount);
+}
+
CFX_Char::CFX_Char(uint16_t wCharCode) : CFX_Char(wCharCode, 100, 100) {}
CFX_Char::CFX_Char(uint16_t wCharCode,
diff --git a/core/fxcrt/cfx_char.h b/core/fxcrt/cfx_char.h
index 5a5268f..e6c6978 100644
--- a/core/fxcrt/cfx_char.h
+++ b/core/fxcrt/cfx_char.h
@@ -9,6 +9,8 @@
#include <stdint.h>
+#include <vector>
+
#include "core/fxcrt/fx_linebreak.h"
#include "core/fxcrt/fx_unicode.h"
#include "core/fxcrt/retain_ptr.h"
@@ -17,6 +19,8 @@
class CFX_Char {
public:
+ static void BidiLine(std::vector<CFX_Char>* chars, size_t iCount);
+
explicit CFX_Char(uint16_t wCharCode);
CFX_Char(uint16_t wCharCode,
int32_t iHorizontalScale,
diff --git a/core/fxcrt/fx_bidi.cpp b/core/fxcrt/fx_bidi.cpp
index 9fee05d..c5fb5c6 100644
--- a/core/fxcrt/fx_bidi.cpp
+++ b/core/fxcrt/fx_bidi.cpp
@@ -11,549 +11,6 @@
#include "core/fxcrt/fx_unicode.h"
#include "third_party/base/stl_util.h"
-#ifdef PDF_ENABLE_XFA
-#include "core/fxcrt/fx_extension.h"
-#endif // PDF_ENABLE_XFA
-
-namespace {
-
-#ifdef PDF_ENABLE_XFA
-
-#ifndef NDEBUG
-constexpr int32_t kBidiMaxLevel = 61;
-#endif // NDEBUG
-
-#undef PACK_NIBBLES
-#define PACK_NIBBLES(hi, lo) \
- ((static_cast<uint32_t>(hi) << 4) + static_cast<uint32_t>(lo))
-
-enum FX_BIDIWEAKSTATE : uint8_t {
- FX_BWSxa = 0,
- FX_BWSxr,
- FX_BWSxl,
- FX_BWSao,
- FX_BWSro,
- FX_BWSlo,
- FX_BWSrt,
- FX_BWSlt,
- FX_BWScn,
- FX_BWSra,
- FX_BWSre,
- FX_BWSla,
- FX_BWSle,
- FX_BWSac,
- FX_BWSrc,
- FX_BWSrs,
- FX_BWSlc,
- FX_BWSls,
- FX_BWSret,
- FX_BWSlet
-};
-
-// NOTE: Range of FX_BIDICLASS prevents encoding all possible values in this
-// manner, but the ones used manage to fit. Except that I suspect that 0xF
-// was intended to be used as a sentinel, even though it also means kRLE.
-// TODO(tsepez): pick a better representation.
-enum FX_BIDIWEAKACTION : uint16_t {
- FX_BWAIX = 0x100,
- FX_BWAXX = 0x0F,
- FX_BWAxxx = 0xFF,
- FX_BWAxIx = 0x100 + FX_BWAxxx,
- FX_BWAxxN = PACK_NIBBLES(0x0F, FX_BIDICLASS::kON),
- FX_BWAxxE = PACK_NIBBLES(0x0F, FX_BIDICLASS::kEN),
- FX_BWAxxA = PACK_NIBBLES(0x0F, FX_BIDICLASS::kAN),
- FX_BWAxxR = PACK_NIBBLES(0x0F, FX_BIDICLASS::kR),
- FX_BWAxxL = PACK_NIBBLES(0x0F, FX_BIDICLASS::kL),
- FX_BWANxx = PACK_NIBBLES(FX_BIDICLASS::kON, 0x0F),
- FX_BWAAxx = PACK_NIBBLES(FX_BIDICLASS::kAN, 0x0F),
- FX_BWAExE = PACK_NIBBLES(FX_BIDICLASS::kEN, FX_BIDICLASS::kEN),
- FX_BWANIx = 0x100 + PACK_NIBBLES(FX_BIDICLASS::kON, 0x0F),
- FX_BWANxN = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kON),
- FX_BWANxR = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kR),
- FX_BWANxE = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kEN),
- FX_BWAAxA = PACK_NIBBLES(FX_BIDICLASS::kAN, FX_BIDICLASS::kAN),
- FX_BWANxL = PACK_NIBBLES(FX_BIDICLASS::kON, FX_BIDICLASS::kL),
- FX_BWALxL = PACK_NIBBLES(FX_BIDICLASS::kL, FX_BIDICLASS::kL),
- FX_BWAxIL = 0x100 + PACK_NIBBLES(0x0F, FX_BIDICLASS::kL),
- FX_BWAAxR = PACK_NIBBLES(FX_BIDICLASS::kAN, FX_BIDICLASS::kR),
- FX_BWALxx = PACK_NIBBLES(FX_BIDICLASS::kL, 0x0F),
-};
-
-enum FX_BIDINEUTRALSTATE : uint8_t {
- FX_BNSr = 0,
- FX_BNSl,
- FX_BNSrn,
- FX_BNSln,
- FX_BNSa,
- FX_BNSna
-};
-
-enum FX_BIDINEUTRALACTION : uint16_t {
- // For placeholders in table.
- FX_BNAZero = 0,
-
- // Other values.
- FX_BNAnL = PACK_NIBBLES(0, FX_BIDICLASS::kL),
- FX_BNAEn = PACK_NIBBLES(FX_BIDICLASS::kAN, 0),
- FX_BNARn = PACK_NIBBLES(FX_BIDICLASS::kR, 0),
- FX_BNALn = PACK_NIBBLES(FX_BIDICLASS::kL, 0),
- FX_BNAIn = FX_BWAIX,
- FX_BNALnL = PACK_NIBBLES(FX_BIDICLASS::kL, FX_BIDICLASS::kL),
-};
-#undef PACK_NIBBLES
-
-const FX_BIDICLASS kNTypes[] = {
- FX_BIDICLASS::kN, FX_BIDICLASS::kL, FX_BIDICLASS::kR,
- FX_BIDICLASS::kAN, FX_BIDICLASS::kEN, FX_BIDICLASS::kAL,
- FX_BIDICLASS::kNSM, FX_BIDICLASS::kCS, FX_BIDICLASS::kES,
- FX_BIDICLASS::kET, FX_BIDICLASS::kBN, FX_BIDICLASS::kBN,
- FX_BIDICLASS::kN, FX_BIDICLASS::kB, FX_BIDICLASS::kRLO,
- FX_BIDICLASS::kRLE, FX_BIDICLASS::kLRO, FX_BIDICLASS::kLRE,
- FX_BIDICLASS::kPDF, FX_BIDICLASS::kON,
-};
-
-const FX_BIDIWEAKSTATE kWeakStates[20][10] = {
- {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSxa,
- FX_BWSao, FX_BWSao, FX_BWSao},
- {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSxr,
- FX_BWSro, FX_BWSro, FX_BWSrt},
- {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSxl,
- FX_BWSlo, FX_BWSlo, FX_BWSlt},
- {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
- FX_BWSao, FX_BWSao, FX_BWSao},
- {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
- FX_BWSro, FX_BWSro, FX_BWSrt},
- {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
- FX_BWSlo, FX_BWSlo, FX_BWSlt},
- {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSrt,
- FX_BWSro, FX_BWSro, FX_BWSrt},
- {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlt,
- FX_BWSlo, FX_BWSlo, FX_BWSlt},
- {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWScn,
- FX_BWSac, FX_BWSao, FX_BWSao},
- {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSra,
- FX_BWSrc, FX_BWSro, FX_BWSrt},
- {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSre,
- FX_BWSrs, FX_BWSrs, FX_BWSret},
- {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSla,
- FX_BWSlc, FX_BWSlo, FX_BWSlt},
- {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSle,
- FX_BWSls, FX_BWSls, FX_BWSlet},
- {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao,
- FX_BWSao, FX_BWSao, FX_BWSao},
- {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
- FX_BWSro, FX_BWSro, FX_BWSrt},
- {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro,
- FX_BWSro, FX_BWSro, FX_BWSrt},
- {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
- FX_BWSlo, FX_BWSlo, FX_BWSlt},
- {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo,
- FX_BWSlo, FX_BWSlo, FX_BWSlt},
- {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSret,
- FX_BWSro, FX_BWSro, FX_BWSret},
- {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlet,
- FX_BWSlo, FX_BWSlo, FX_BWSlet},
-};
-
-const FX_BIDIWEAKACTION kWeakActions[20][10] = {
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
- FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
- FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
- FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
- FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
- FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
- FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx},
- {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
- FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
- {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
- FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR,
- FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxxN},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
- FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
- FX_BWAxxE, FX_BWAxIx, FX_BWAxIx, FX_BWAxxE},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
- FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
- FX_BWAxxL, FX_BWAxIx, FX_BWAxIx, FX_BWAxxL},
- {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWAAxA, FX_BWANxR,
- FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANxN},
- {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxE, FX_BWANxR,
- FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
- {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR,
- FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
- {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxL, FX_BWANxR,
- FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
- {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR,
- FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR,
- FX_BWAxxE, FX_BWAxxN, FX_BWAxxN, FX_BWAxxE},
- {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR,
- FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxxL},
-};
-
-const FX_BIDINEUTRALSTATE kNeutralStates[6][5] = {
- {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
- {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
- {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr},
- {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
- {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
- {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl},
-};
-
-const FX_BIDINEUTRALACTION kNeutralActions[6][5] = {
- {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAZero},
- {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAnL},
- {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNARn},
- {FX_BNAIn, FX_BNALn, FX_BNAEn, FX_BNAEn, FX_BNALnL},
- {FX_BNAIn, FX_BNAZero, FX_BNAZero, FX_BNAZero, FX_BNAnL},
- {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNAEn},
-};
-
-const uint8_t kAddLevel[2][4] = {
- {0, 1, 2, 2},
- {1, 0, 1, 1},
-};
-
-FX_BIDICLASS Direction(int32_t val) {
- return FX_IsOdd(val) ? FX_BIDICLASS::kR : FX_BIDICLASS::kL;
-}
-
-FX_BIDICLASS GetDeferredType(int32_t val) {
- return static_cast<FX_BIDICLASS>((val >> 4) & 0x0F);
-}
-
-FX_BIDICLASS GetResolvedType(int32_t val) {
- return static_cast<FX_BIDICLASS>(val & 0x0F);
-}
-
-FX_BIDICLASS GetDeferredNeutrals(int32_t iAction, int32_t iLevel) {
- FX_BIDICLASS eClass = GetDeferredType(iAction);
- return eClass == FX_BIDICLASS::kAN ? Direction(iLevel) : eClass;
-}
-
-FX_BIDICLASS GetResolvedNeutrals(int32_t iAction) {
- return GetResolvedType(iAction);
-}
-
-FX_BIDIWEAKSTATE GetWeakState(FX_BIDIWEAKSTATE eState, FX_BIDICLASS eClass) {
- ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kWeakStates));
- ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kWeakStates[0]));
- return kWeakStates[static_cast<size_t>(eState)][static_cast<size_t>(eClass)];
-}
-
-FX_BIDIWEAKACTION GetWeakAction(FX_BIDIWEAKSTATE eState, FX_BIDICLASS eClass) {
- ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kWeakActions));
- ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kWeakActions[0]));
- return kWeakActions[static_cast<size_t>(eState)][static_cast<size_t>(eClass)];
-}
-
-FX_BIDINEUTRALSTATE GetNeutralState(FX_BIDINEUTRALSTATE eState,
- FX_BIDICLASS eClass) {
- ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kNeutralStates));
- ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kNeutralStates[0]));
- return kNeutralStates[static_cast<size_t>(eState)]
- [static_cast<size_t>(eClass)];
-}
-
-FX_BIDINEUTRALACTION GetNeutralAction(FX_BIDINEUTRALSTATE eState,
- FX_BIDICLASS eClass) {
- ASSERT(static_cast<size_t>(eState) < FX_ArraySize(kNeutralActions));
- ASSERT(static_cast<size_t>(eClass) < FX_ArraySize(kNeutralActions[0]));
- return kNeutralActions[static_cast<size_t>(eState)]
- [static_cast<size_t>(eClass)];
-}
-
-void ReverseString(std::vector<CFX_Char>* chars, size_t iStart, size_t iCount) {
- ASSERT(pdfium::IndexInBounds(*chars, iStart));
- ASSERT(iStart + iCount <= chars->size());
-
- std::reverse(chars->begin() + iStart, chars->begin() + iStart + iCount);
-}
-
-void SetDeferredRunClass(std::vector<CFX_Char>* chars,
- size_t iStart,
- size_t iCount,
- FX_BIDICLASS eValue) {
- ASSERT(iStart <= chars->size());
- ASSERT(iStart >= iCount);
-
- size_t iLast = iStart - iCount;
- for (size_t i = iStart; i > iLast; --i)
- (*chars)[i - 1].m_iBidiClass = eValue;
-}
-
-void SetDeferredRunLevel(std::vector<CFX_Char>* chars,
- size_t iStart,
- size_t iCount,
- int32_t iValue) {
- ASSERT(iStart <= chars->size());
- ASSERT(iStart >= iCount);
-
- size_t iLast = iStart - iCount;
- for (size_t i = iStart; i > iLast; --i)
- (*chars)[i - 1].m_iBidiLevel = static_cast<int16_t>(iValue);
-}
-
-void Classify(std::vector<CFX_Char>* chars, size_t iCount) {
- for (size_t i = 0; i < iCount; ++i) {
- CFX_Char& cur = (*chars)[i];
- cur.m_iBidiClass = FX_GetBidiClass(cur.char_code());
- }
-}
-
-void ClassifyWithTransform(std::vector<CFX_Char>* chars, size_t iCount) {
- for (size_t i = 0; i < iCount; ++i) {
- CFX_Char& cur = (*chars)[i];
- cur.m_iBidiClass =
- kNTypes[static_cast<size_t>(FX_GetBidiClass(cur.char_code()))];
- }
-}
-
-void ResolveExplicit(std::vector<CFX_Char>* chars, size_t iCount) {
- for (size_t i = 0; i < iCount; ++i)
- (*chars)[i].m_iBidiLevel = 0;
-}
-
-void ResolveWeak(std::vector<CFX_Char>* chars, size_t iCount) {
- if (iCount <= 1)
- return;
- --iCount;
-
- int32_t iLevelCur = 0;
- size_t iNum = 0;
- FX_BIDIWEAKSTATE eState = FX_BWSxl;
- FX_BIDICLASS eClsCur;
- FX_BIDICLASS eClsRun;
- FX_BIDICLASS eClsNew;
- size_t i = 0;
- for (; i <= iCount; ++i) {
- CFX_Char* pTC = &(*chars)[i];
- eClsCur = pTC->m_iBidiClass;
- if (eClsCur == FX_BIDICLASS::kBN) {
- pTC->m_iBidiLevel = (int16_t)iLevelCur;
- if (i == iCount && iLevelCur != 0) {
- eClsCur = Direction(iLevelCur);
- pTC->m_iBidiClass = eClsCur;
- } else if (i < iCount) {
- CFX_Char* pTCNext = &(*chars)[i + 1];
- int32_t iLevelNext, iLevelNew;
- eClsNew = pTCNext->m_iBidiClass;
- iLevelNext = pTCNext->m_iBidiLevel;
- if (eClsNew != FX_BIDICLASS::kBN && iLevelCur != iLevelNext) {
- iLevelNew = std::max(iLevelNext, iLevelCur);
- pTC->m_iBidiLevel = static_cast<int16_t>(iLevelNew);
- eClsCur = Direction(iLevelNew);
- pTC->m_iBidiClass = eClsCur;
- iLevelCur = iLevelNext;
- } else {
- if (iNum > 0)
- ++iNum;
- continue;
- }
- } else {
- if (iNum > 0)
- ++iNum;
- continue;
- }
- }
- if (eClsCur > FX_BIDICLASS::kBN)
- continue;
-
- FX_BIDIWEAKACTION eAction = GetWeakAction(eState, eClsCur);
- eClsRun = GetDeferredType(eAction);
- if (eClsRun != static_cast<FX_BIDICLASS>(0xF) && iNum > 0) {
- SetDeferredRunClass(chars, i, iNum, eClsRun);
- iNum = 0;
- }
- eClsNew = GetResolvedType(eAction);
- if (eClsNew != static_cast<FX_BIDICLASS>(0xF))
- pTC->m_iBidiClass = eClsNew;
- if (FX_BWAIX & eAction)
- ++iNum;
-
- eState = GetWeakState(eState, eClsCur);
- }
- if (iNum == 0)
- return;
-
- eClsCur = Direction(0);
- eClsRun = GetDeferredType(GetWeakAction(eState, eClsCur));
- if (eClsRun != static_cast<FX_BIDICLASS>(0xF))
- SetDeferredRunClass(chars, i, iNum, eClsRun);
-}
-
-void ResolveNeutrals(std::vector<CFX_Char>* chars, size_t iCount) {
- if (iCount <= 1)
- return;
- --iCount;
-
- CFX_Char* pTC;
- int32_t iLevel = 0;
- size_t i = 0;
- size_t iNum = 0;
- FX_BIDINEUTRALSTATE eState = FX_BNSl;
- FX_BIDICLASS eClsCur;
- FX_BIDICLASS eClsRun;
- FX_BIDICLASS eClsNew;
- for (; i <= iCount; ++i) {
- pTC = &(*chars)[i];
- eClsCur = pTC->m_iBidiClass;
- if (eClsCur == FX_BIDICLASS::kBN) {
- if (iNum)
- ++iNum;
- continue;
- }
- if (eClsCur >= FX_BIDICLASS::kAL)
- continue;
-
- FX_BIDINEUTRALACTION eAction = GetNeutralAction(eState, eClsCur);
- eClsRun = GetDeferredNeutrals(eAction, iLevel);
- if (eClsRun != FX_BIDICLASS::kN && iNum > 0) {
- SetDeferredRunClass(chars, i, iNum, eClsRun);
- iNum = 0;
- }
-
- eClsNew = GetResolvedNeutrals(eAction);
- if (eClsNew != FX_BIDICLASS::kN)
- pTC->m_iBidiClass = eClsNew;
- if (FX_BNAIn & eAction)
- ++iNum;
-
- eState = GetNeutralState(eState, eClsCur);
- iLevel = pTC->m_iBidiLevel;
- }
- if (iNum == 0)
- return;
-
- eClsCur = Direction(iLevel);
- eClsRun = GetDeferredNeutrals(GetNeutralAction(eState, eClsCur), iLevel);
- if (eClsRun != FX_BIDICLASS::kN)
- SetDeferredRunClass(chars, i, iNum, eClsRun);
-}
-
-void ResolveImplicit(std::vector<CFX_Char>* chars, size_t iCount) {
- for (size_t i = 0; i < iCount; ++i) {
- FX_BIDICLASS eCls = (*chars)[i].m_iBidiClass;
- if (eCls == FX_BIDICLASS::kBN || eCls <= FX_BIDICLASS::kON ||
- eCls >= FX_BIDICLASS::kAL) {
- continue;
- }
- (*chars)[i].m_iBidiLevel += kAddLevel[FX_IsOdd((*chars)[i].m_iBidiLevel)]
- [static_cast<size_t>(eCls) - 1];
- }
-}
-
-void ResolveWhitespace(std::vector<CFX_Char>* chars, size_t iCount) {
- if (iCount <= 1)
- return;
- iCount--;
-
- int32_t iLevel = 0;
- size_t i = 0;
- size_t iNum = 0;
- for (; i <= iCount; ++i) {
- switch (static_cast<FX_BIDICLASS>((*chars)[i].m_iBidiClass)) {
- case FX_BIDICLASS::kWS:
- ++iNum;
- break;
- case FX_BIDICLASS::kRLE:
- case FX_BIDICLASS::kLRE:
- case FX_BIDICLASS::kLRO:
- case FX_BIDICLASS::kRLO:
- case FX_BIDICLASS::kPDF:
- case FX_BIDICLASS::kBN:
- (*chars)[i].m_iBidiLevel = static_cast<int16_t>(iLevel);
- ++iNum;
- break;
- case FX_BIDICLASS::kS:
- case FX_BIDICLASS::kB:
- if (iNum > 0)
- SetDeferredRunLevel(chars, i, iNum, 0);
-
- (*chars)[i].m_iBidiLevel = 0;
- iNum = 0;
- break;
- default:
- iNum = 0;
- break;
- }
- iLevel = (*chars)[i].m_iBidiLevel;
- }
- if (iNum > 0)
- SetDeferredRunLevel(chars, i, iNum, 0);
-}
-
-size_t ReorderLevel(std::vector<CFX_Char>* chars,
- size_t iCount,
- int32_t iBaseLevel,
- size_t iStart,
- bool bReverse) {
- ASSERT(iBaseLevel >= 0);
- ASSERT(iBaseLevel <= kBidiMaxLevel);
- ASSERT(iStart < iCount);
-
- if (iCount < 1)
- return 0;
-
- bReverse = bReverse || FX_IsOdd(iBaseLevel);
- size_t i = iStart;
- for (; i < iCount; ++i) {
- int32_t iLevel = (*chars)[i].m_iBidiLevel;
- if (iLevel == iBaseLevel)
- continue;
- if (iLevel < iBaseLevel)
- break;
-
- i += ReorderLevel(chars, iCount, iBaseLevel + 1, i, bReverse) - 1;
- }
-
- size_t iNum = i - iStart;
- if (bReverse && iNum > 1)
- ReverseString(chars, iStart, iNum);
-
- return iNum;
-}
-
-void Reorder(std::vector<CFX_Char>* chars, size_t iCount) {
- for (size_t i = 0; i < iCount;)
- i += ReorderLevel(chars, iCount, 0, i, false);
-}
-
-void Position(std::vector<CFX_Char>* chars, size_t iCount) {
- for (size_t i = 0; i < iCount; ++i) {
- if ((*chars)[i].m_iBidiPos > iCount)
- continue;
-
- (*chars)[(*chars)[i].m_iBidiPos].m_iBidiOrder = i;
- }
-}
-
-void BidiLine(std::vector<CFX_Char>* chars, size_t iCount) {
- ASSERT(iCount <= chars->size());
- if (iCount < 2)
- return;
-
- ClassifyWithTransform(chars, iCount);
- ResolveExplicit(chars, iCount);
- ResolveWeak(chars, iCount);
- ResolveNeutrals(chars, iCount);
- ResolveImplicit(chars, iCount);
- Classify(chars, iCount);
- ResolveWhitespace(chars, iCount);
- Reorder(chars, iCount);
- Position(chars, iCount);
-}
-#endif // PDF_ENABLE_XFA
-
-} // namespace
-
CFX_BidiChar::CFX_BidiChar()
: m_CurrentSegment({0, 0, NEUTRAL}), m_LastSegment({0, 0, NEUTRAL}) {}
@@ -630,9 +87,3 @@
m_eOverallDirection = CFX_BidiChar::RIGHT;
}
}
-
-#ifdef PDF_ENABLE_XFA
-void FX_BidiLine(std::vector<CFX_Char>* chars, size_t iCount) {
- BidiLine(chars, iCount);
-}
-#endif // PDF_ENABLE_XFA
diff --git a/core/fxcrt/fx_bidi.h b/core/fxcrt/fx_bidi.h
index f64fc67..ade9a2a 100644
--- a/core/fxcrt/fx_bidi.h
+++ b/core/fxcrt/fx_bidi.h
@@ -12,10 +12,6 @@
#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/fx_system.h"
-#ifdef PDF_ENABLE_XFA
-#include "core/fxcrt/cfx_char.h"
-#endif // PDF_ENABLE_XFA
-
// Processes characters and group them into segments based on text direction.
class CFX_BidiChar {
public:
@@ -71,8 +67,4 @@
CFX_BidiChar::Direction m_eOverallDirection = CFX_BidiChar::LEFT;
};
-#ifdef PDF_ENABLE_XFA
-void FX_BidiLine(std::vector<CFX_Char>* chars, size_t iCount);
-#endif // PDF_ENABLE_XFA
-
#endif // CORE_FXCRT_FX_BIDI_H_
diff --git a/testing/fuzzers/pdf_bidi_fuzzer.cc b/testing/fuzzers/pdf_bidi_fuzzer.cc
index fb3209c..276e3df 100644
--- a/testing/fuzzers/pdf_bidi_fuzzer.cc
+++ b/testing/fuzzers/pdf_bidi_fuzzer.cc
@@ -4,7 +4,7 @@
#include <cstdint>
-#include "core/fxcrt/fx_bidi.h"
+#include "core/fxcrt/cfx_char.h"
#include "core/fxcrt/widestring.h"
#include "core/fxge/cfx_font.h"
#include "third_party/base/ptr_util.h"
@@ -31,6 +31,6 @@
rtf_break.AppendChar(ch);
auto chars = rtf_break.GetCurrentLineForTesting()->m_LineChars;
- FX_BidiLine(&chars, chars.size());
+ CFX_Char::BidiLine(&chars, chars.size());
return 0;
}
diff --git a/xfa/fgas/layout/cfx_rtfbreak.cpp b/xfa/fgas/layout/cfx_rtfbreak.cpp
index 61fb9d9..40f73fb 100644
--- a/xfa/fgas/layout/cfx_rtfbreak.cpp
+++ b/xfa/fgas/layout/cfx_rtfbreak.cpp
@@ -8,8 +8,8 @@
#include <algorithm>
+#include "core/fxcrt/cfx_char.h"
#include "core/fxcrt/fx_arabic.h"
-#include "core/fxcrt/fx_bidi.h"
#include "core/fxcrt/fx_linebreak.h"
#include "core/fxge/cfx_renderdevice.h"
#include "third_party/base/numerics/safe_math.h"
@@ -427,7 +427,7 @@
if (i == 0)
pTC->m_iBidiLevel = 1;
}
- FX_BidiLine(&chars, iBidiNum + 1);
+ CFX_Char::BidiLine(&chars, iBidiNum + 1);
} else {
for (size_t i = 0; i < m_pCurLine->m_LineChars.size(); ++i) {
pTC = &chars[i];
diff --git a/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp b/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp
index e7146c0..307fc8c 100644
--- a/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp
+++ b/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp
@@ -9,7 +9,7 @@
#include <memory>
#include <utility>
-#include "core/fxcrt/fx_bidi.h"
+#include "core/fxcrt/cfx_char.h"
#include "core/fxge/cfx_font.h"
#include "core/fxge/cfx_gemodule.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -86,6 +86,6 @@
rtf_break->AppendChar(ch);
auto chars = rtf_break->GetCurrentLineForTesting()->m_LineChars;
- FX_BidiLine(&chars, chars.size());
+ CFX_Char::BidiLine(&chars, chars.size());
EXPECT_EQ(3u, chars.size());
}
diff --git a/xfa/fgas/layout/cfx_txtbreak.cpp b/xfa/fgas/layout/cfx_txtbreak.cpp
index d5a6cb4..f2a3f67 100644
--- a/xfa/fgas/layout/cfx_txtbreak.cpp
+++ b/xfa/fgas/layout/cfx_txtbreak.cpp
@@ -8,8 +8,8 @@
#include <algorithm>
+#include "core/fxcrt/cfx_char.h"
#include "core/fxcrt/fx_arabic.h"
-#include "core/fxcrt/fx_bidi.h"
#include "core/fxcrt/fx_linebreak.h"
#include "third_party/base/stl_util.h"
#include "xfa/fde/cfde_texteditengine.h"
@@ -323,7 +323,7 @@
if (i == 0)
pTC->m_iBidiLevel = 1;
}
- FX_BidiLine(&chars, iBidiNum + 1);
+ CFX_Char::BidiLine(&chars, iBidiNum + 1);
}
if (bDone) {
diff --git a/xfa/fgas/layout/cfx_txtbreak_unittest.cpp b/xfa/fgas/layout/cfx_txtbreak_unittest.cpp
index fcfc1d9..4b71df3 100644
--- a/xfa/fgas/layout/cfx_txtbreak_unittest.cpp
+++ b/xfa/fgas/layout/cfx_txtbreak_unittest.cpp
@@ -7,7 +7,7 @@
#include <memory>
#include <utility>
-#include "core/fxcrt/fx_bidi.h"
+#include "core/fxcrt/cfx_char.h"
#include "core/fxge/cfx_font.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"
@@ -43,6 +43,6 @@
txt_break->AppendChar(ch);
auto chars = txt_break->GetCurrentLineForTesting()->m_LineChars;
- FX_BidiLine(&chars, chars.size());
+ CFX_Char::BidiLine(&chars, chars.size());
EXPECT_EQ(3u, chars.size());
}