From 235818f45eda6fd47114c076bfa818b2ef3ba894 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Thu, 31 Aug 2017 14:26:25 -0400 Subject: Move bidi code to fx_bidi This CL moves the BIDI code from fx_arabic to fx_bidi and conditionally compiles based on XFA. Change-Id: Iaba60486f03e48f0816d60e365a58a8622bc8254 Reviewed-on: https://pdfium-review.googlesource.com/12713 Commit-Queue: dsinclair Reviewed-by: Tom Sepez --- core/fxcrt/fx_bidi.cpp | 510 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) (limited to 'core/fxcrt/fx_bidi.cpp') diff --git a/core/fxcrt/fx_bidi.cpp b/core/fxcrt/fx_bidi.cpp index 25544546d3..8b20cfbf46 100644 --- a/core/fxcrt/fx_bidi.cpp +++ b/core/fxcrt/fx_bidi.cpp @@ -11,6 +11,509 @@ #include "core/fxcrt/fx_ucd.h" #include "third_party/base/ptr_util.h" +#ifdef PDF_ENABLE_XFA +#include "core/fxcrt/fx_extension.h" + +namespace { + +#ifndef NDEBUG +constexpr int32_t kBidiMaxLevel = 61; +#endif // NDEBUG + +enum FX_BIDIWEAKSTATE { + 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 +}; + +enum FX_BIDIWEAKACTION { + FX_BWAIX = 0x100, + FX_BWAXX = 0x0F, + FX_BWAxxx = (0x0F << 4) + 0x0F, + FX_BWAxIx = 0x100 + FX_BWAxxx, + FX_BWAxxN = (0x0F << 4) + FX_BIDICLASS_ON, + FX_BWAxxE = (0x0F << 4) + FX_BIDICLASS_EN, + FX_BWAxxA = (0x0F << 4) + FX_BIDICLASS_AN, + FX_BWAxxR = (0x0F << 4) + FX_BIDICLASS_R, + FX_BWAxxL = (0x0F << 4) + FX_BIDICLASS_L, + FX_BWANxx = (FX_BIDICLASS_ON << 4) + 0x0F, + FX_BWAAxx = (FX_BIDICLASS_AN << 4) + 0x0F, + FX_BWAExE = (FX_BIDICLASS_EN << 4) + FX_BIDICLASS_EN, + FX_BWANIx = (FX_BIDICLASS_ON << 4) + 0x0F + 0x100, + FX_BWANxN = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_ON, + FX_BWANxR = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_R, + FX_BWANxE = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_EN, + FX_BWAAxA = (FX_BIDICLASS_AN << 4) + FX_BIDICLASS_AN, + FX_BWANxL = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_L, + FX_BWALxL = (FX_BIDICLASS_L << 4) + FX_BIDICLASS_L, + FX_BWAxIL = (0x0F << 4) + FX_BIDICLASS_L + 0x100, + FX_BWAAxR = (FX_BIDICLASS_AN << 4) + FX_BIDICLASS_R, + FX_BWALxx = (FX_BIDICLASS_L << 4) + 0x0F, +}; + +enum FX_BIDINEUTRALSTATE { + FX_BNSr = 0, + FX_BNSl, + FX_BNSrn, + FX_BNSln, + FX_BNSa, + FX_BNSna +}; + +enum FX_BIDINEUTRALACTION { + FX_BNAnL = FX_BIDICLASS_L, + FX_BNAEn = (FX_BIDICLASS_AN << 4), + FX_BNARn = (FX_BIDICLASS_R << 4), + FX_BNALn = (FX_BIDICLASS_L << 4), + FX_BNAIn = FX_BWAIX, + FX_BNALnL = (FX_BIDICLASS_L << 4) + FX_BIDICLASS_L, +}; + +const int32_t gc_FX_BidiNTypes[] = { + FX_BIDICLASS_N, FX_BIDICLASS_L, FX_BIDICLASS_R, FX_BIDICLASS_AN, + FX_BIDICLASS_EN, FX_BIDICLASS_AL, FX_BIDICLASS_NSM, FX_BIDICLASS_CS, + FX_BIDICLASS_ES, FX_BIDICLASS_ET, FX_BIDICLASS_BN, FX_BIDICLASS_BN, + FX_BIDICLASS_N, FX_BIDICLASS_B, FX_BIDICLASS_RLO, FX_BIDICLASS_RLE, + FX_BIDICLASS_LRO, FX_BIDICLASS_LRE, FX_BIDICLASS_PDF, FX_BIDICLASS_ON, +}; + +const int32_t gc_FX_BidiWeakStates[][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 int32_t gc_FX_BidiWeakActions[][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 int32_t gc_FX_BidiNeutralStates[][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 int32_t gc_FX_BidiNeutralActions[][5] = { + {FX_BNAIn, 0, 0, 0, 0}, + {FX_BNAIn, 0, 0, 0, FX_BIDICLASS_L}, + {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNARn}, + {FX_BNAIn, FX_BNALn, FX_BNAEn, FX_BNAEn, FX_BNALnL}, + {FX_BNAIn, 0, 0, 0, FX_BIDICLASS_L}, + {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNAEn}, +}; + +const int32_t gc_FX_BidiAddLevel[][4] = { + {0, 1, 2, 2}, + {1, 0, 1, 1}, +}; + +class CFX_BidiLine { + public: + void BidiLine(std::vector* chars, int32_t iCount) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + if (iCount < 2) + return; + + Classify(chars, iCount, false); + ResolveExplicit(chars, iCount); + ResolveWeak(chars, iCount); + ResolveNeutrals(chars, iCount); + ResolveImplicit(chars, iCount); + Classify(chars, iCount, true); + ResolveWhitespace(chars, iCount); + Reorder(chars, iCount); + Position(chars, iCount); + } + + private: + int32_t Direction(int32_t val) { + return FX_IsOdd(val) ? FX_BIDICLASS_R : FX_BIDICLASS_L; + } + + int32_t GetDeferredType(int32_t val) { return (val >> 4) & 0x0F; } + + int32_t GetResolvedType(int32_t val) { return val & 0x0F; } + + int32_t GetDeferredNeutrals(int32_t iAction, int32_t iLevel) { + iAction = (iAction >> 4) & 0xF; + if (iAction == (FX_BNAEn >> 4)) + return Direction(iLevel); + return iAction; + } + + int32_t GetResolvedNeutrals(int32_t iAction) { + iAction &= 0xF; + return iAction == FX_BNAIn ? 0 : iAction; + } + + void ReverseString(std::vector* chars, + int32_t iStart, + int32_t iCount) { + ASSERT(pdfium::IndexInBounds(*chars, iStart)); + ASSERT(iCount >= 0 && + iStart + iCount <= pdfium::CollectionSize(*chars)); + std::reverse(chars->begin() + iStart, chars->begin() + iStart + iCount); + } + + void SetDeferredRun(std::vector* chars, + bool bClass, + int32_t iStart, + int32_t iCount, + int32_t iValue) { + ASSERT(iStart >= 0 && iStart <= pdfium::CollectionSize(*chars)); + ASSERT(iStart - iCount > -1); + int32_t iLast = iStart - iCount; + if (bClass) { + for (int32_t i = iStart - 1; i >= iLast; i--) + (*chars)[i].m_iBidiClass = static_cast(iValue); + return; + } + + for (int32_t i = iStart - 1; i >= iLast; i--) + (*chars)[i].m_iBidiLevel = static_cast(iValue); + } + + void Classify(std::vector* chars, int32_t iCount, bool bWS) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + if (bWS) { + for (int32_t i = 0; i < iCount; i++) { + CFX_Char& cur = (*chars)[i]; + cur.m_iBidiClass = + static_cast(cur.char_props() & FX_BIDICLASSBITSMASK) >> + FX_BIDICLASSBITS; + } + return; + } + + for (int32_t i = 0; i < iCount; i++) { + CFX_Char& cur = (*chars)[i]; + cur.m_iBidiClass = static_cast( + gc_FX_BidiNTypes[(cur.char_props() & FX_BIDICLASSBITSMASK) >> + FX_BIDICLASSBITS]); + } + } + + void ResolveExplicit(std::vector* chars, int32_t iCount) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + for (int32_t i = 0; i < iCount; i++) + (*chars)[i].m_iBidiLevel = 0; + } + + void ResolveWeak(std::vector* chars, int32_t iCount) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + iCount--; + if (iCount < 1) + return; + + int32_t iLevelCur = 0; + int32_t iState = FX_BWSxl; + int32_t i = 0; + int32_t iNum = 0; + int32_t iClsCur; + int32_t iClsRun; + int32_t iClsNew; + int32_t iAction; + for (; i <= iCount; i++) { + CFX_Char* pTC = &(*chars)[i]; + iClsCur = pTC->m_iBidiClass; + if (iClsCur == FX_BIDICLASS_BN) { + pTC->m_iBidiLevel = (int16_t)iLevelCur; + if (i == iCount && iLevelCur != 0) { + iClsCur = Direction(iLevelCur); + pTC->m_iBidiClass = (int16_t)iClsCur; + } else if (i < iCount) { + CFX_Char* pTCNext = &(*chars)[i + 1]; + int32_t iLevelNext, iLevelNew; + iClsNew = pTCNext->m_iBidiClass; + iLevelNext = pTCNext->m_iBidiLevel; + if (iClsNew != FX_BIDICLASS_BN && iLevelCur != iLevelNext) { + iLevelNew = std::max(iLevelNext, iLevelCur); + pTC->m_iBidiLevel = static_cast(iLevelNew); + iClsCur = Direction(iLevelNew); + pTC->m_iBidiClass = static_cast(iClsCur); + iLevelCur = iLevelNext; + } else { + if (iNum > 0) + iNum++; + continue; + } + } else { + if (iNum > 0) + iNum++; + continue; + } + } + + ASSERT(iClsCur <= FX_BIDICLASS_BN); + iAction = gc_FX_BidiWeakActions[iState][iClsCur]; + iClsRun = GetDeferredType(iAction); + if (iClsRun != FX_BWAXX && iNum > 0) { + SetDeferredRun(chars, true, i, iNum, iClsRun); + iNum = 0; + } + iClsNew = GetResolvedType(iAction); + if (iClsNew != FX_BWAXX) + pTC->m_iBidiClass = static_cast(iClsNew); + if (FX_BWAIX & iAction) + iNum++; + + iState = gc_FX_BidiWeakStates[iState][iClsCur]; + } + if (iNum > 0) { + iClsCur = Direction(0); + iClsRun = GetDeferredType(gc_FX_BidiWeakActions[iState][iClsCur]); + if (iClsRun != FX_BWAXX) + SetDeferredRun(chars, true, i, iNum, iClsRun); + } + } + + void ResolveNeutrals(std::vector* chars, int32_t iCount) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + iCount--; + if (iCount < 1) + return; + + CFX_Char* pTC; + int32_t iLevel = 0; + int32_t iState = FX_BNSl; + int32_t i = 0; + int32_t iNum = 0; + int32_t iClsCur; + int32_t iClsRun; + int32_t iClsNew; + int32_t iAction; + for (; i <= iCount; i++) { + pTC = &(*chars)[i]; + iClsCur = pTC->m_iBidiClass; + if (iClsCur == FX_BIDICLASS_BN) { + if (iNum) + iNum++; + continue; + } + + ASSERT(iClsCur < FX_BIDICLASS_AL); + iAction = gc_FX_BidiNeutralActions[iState][iClsCur]; + iClsRun = GetDeferredNeutrals(iAction, iLevel); + if (iClsRun != FX_BIDICLASS_N && iNum > 0) { + SetDeferredRun(chars, true, i, iNum, iClsRun); + iNum = 0; + } + + iClsNew = GetResolvedNeutrals(iAction); + if (iClsNew != FX_BIDICLASS_N) + pTC->m_iBidiClass = (int16_t)iClsNew; + if (FX_BNAIn & iAction) + iNum++; + + iState = gc_FX_BidiNeutralStates[iState][iClsCur]; + iLevel = pTC->m_iBidiLevel; + } + if (iNum > 0) { + iClsCur = Direction(iLevel); + iClsRun = GetDeferredNeutrals(gc_FX_BidiNeutralActions[iState][iClsCur], + iLevel); + if (iClsRun != FX_BIDICLASS_N) + SetDeferredRun(chars, true, i, iNum, iClsRun); + } + } + + void ResolveImplicit(std::vector* chars, int32_t iCount) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + for (int32_t i = 0; i < iCount; i++) { + int32_t iCls = (*chars)[i].m_iBidiClass; + if (iCls == FX_BIDICLASS_BN) + continue; + + ASSERT(iCls > FX_BIDICLASS_ON && iCls < FX_BIDICLASS_AL); + int32_t iLevel = (*chars)[i].m_iBidiLevel; + iLevel += gc_FX_BidiAddLevel[FX_IsOdd(iLevel)][iCls - 1]; + (*chars)[i].m_iBidiLevel = (int16_t)iLevel; + } + } + + void ResolveWhitespace(std::vector* chars, int32_t iCount) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + if (iCount < 1) + return; + + iCount--; + int32_t iLevel = 0; + int32_t i = 0; + int32_t iNum = 0; + for (; i <= iCount; i++) { + switch ((*chars)[i].m_iBidiClass) { + case FX_BIDICLASS_WS: + iNum++; + break; + case FX_BIDICLASS_RLE: + case FX_BIDICLASS_LRE: + case FX_BIDICLASS_LRO: + case FX_BIDICLASS_RLO: + case FX_BIDICLASS_PDF: + case FX_BIDICLASS_BN: + (*chars)[i].m_iBidiLevel = (int16_t)iLevel; + iNum++; + break; + case FX_BIDICLASS_S: + case FX_BIDICLASS_B: + if (iNum > 0) + SetDeferredRun(chars, false, i, iNum, 0); + + (*chars)[i].m_iBidiLevel = 0; + iNum = 0; + break; + default: + iNum = 0; + break; + } + iLevel = (*chars)[i].m_iBidiLevel; + } + if (iNum > 0) + SetDeferredRun(chars, false, i, iNum, 0); + } + + int32_t ReorderLevel(std::vector* chars, + int32_t iCount, + int32_t iBaseLevel, + int32_t iStart, + bool bReverse) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + ASSERT(iBaseLevel >= 0 && iBaseLevel <= kBidiMaxLevel); + ASSERT(iStart >= 0 && iStart < iCount); + + if (iCount < 1) + return 0; + + bReverse = bReverse || FX_IsOdd(iBaseLevel); + int32_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; + } + int32_t iNum = i - iStart; + if (bReverse && iNum > 1) + ReverseString(chars, iStart, iNum); + + return iNum; + } + + void Reorder(std::vector* chars, int32_t iCount) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + int32_t i = 0; + while (i < iCount) + i += ReorderLevel(chars, iCount, 0, i, false); + } + + void Position(std::vector* chars, int32_t iCount) { + ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(*chars)); + for (int32_t i = 0; i < iCount; ++i) + (*chars)[(*chars)[i].m_iBidiPos].m_iBidiOrder = i; + } +}; + +} // namespace + +#endif // PDF_ENABLE_XFA + CFX_BidiChar::CFX_BidiChar() : m_CurrentSegment({0, 0, NEUTRAL}), m_LastSegment({0, 0, NEUTRAL}) {} @@ -83,3 +586,10 @@ void CFX_BidiString::SetOverallDirectionRight() { m_eOverallDirection = CFX_BidiChar::RIGHT; } } + +#ifdef PDF_ENABLE_XFA +void FX_BidiLine(std::vector* chars, int32_t iCount) { + CFX_BidiLine blt; + blt.BidiLine(chars, iCount); +} +#endif // PDF_ENABLE_XFA -- cgit v1.2.3