| // Copyright 2017 PDFium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| #include "xfa/fgas/layout/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, | |
| int32_t iHorizontalScale, | |
| int32_t iVerticalScale) | |
| : m_wCharCode(wCharCode), | |
| m_iHorizontalScale(iHorizontalScale), | |
| m_iVerticalScale(iVerticalScale) {} | |
| CFX_Char::CFX_Char(const CFX_Char& other) = default; | |
| CFX_Char::~CFX_Char() = default; | |
| FX_CHARTYPE CFX_Char::GetCharType() const { | |
| return FX_GetCharType(m_wCharCode); | |
| } |