| // 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" |
| #include "third_party/base/check.h" |
| #include "third_party/base/stl_util.h" |
| |
| namespace { |
| |
| #if DCHECK_IS_ON() |
| constexpr int32_t kBidiMaxLevel = 61; |
| #endif |
| |
| #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) { |
| DCHECK(static_cast<size_t>(eState) < pdfium::size(kWeakStates)); |
| DCHECK(static_cast<size_t>(eClass) < pdfium::size(kWeakStates[0])); |
| return kWeakStates[static_cast<size_t>(eState)][static_cast<size_t>(eClass)]; |
| } |
| |
| FX_BIDIWEAKACTION GetWeakAction(FX_BIDIWEAKSTATE eState, FX_BIDICLASS eClass) { |
| DCHECK(static_cast<size_t>(eState) < pdfium::size(kWeakActions)); |
| DCHECK(static_cast<size_t>(eClass) < pdfium::size(kWeakActions[0])); |
| return kWeakActions[static_cast<size_t>(eState)][static_cast<size_t>(eClass)]; |
| } |
| |
| FX_BIDINEUTRALSTATE GetNeutralState(FX_BIDINEUTRALSTATE eState, |
| FX_BIDICLASS eClass) { |
| DCHECK(static_cast<size_t>(eState) < pdfium::size(kNeutralStates)); |
| DCHECK(static_cast<size_t>(eClass) < pdfium::size(kNeutralStates[0])); |
| return kNeutralStates[static_cast<size_t>(eState)] |
| [static_cast<size_t>(eClass)]; |
| } |
| |
| FX_BIDINEUTRALACTION GetNeutralAction(FX_BIDINEUTRALSTATE eState, |
| FX_BIDICLASS eClass) { |
| DCHECK(static_cast<size_t>(eState) < pdfium::size(kNeutralActions)); |
| DCHECK(static_cast<size_t>(eClass) < pdfium::size(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) { |
| DCHECK(pdfium::IndexInBounds(*chars, iStart)); |
| DCHECK(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) { |
| DCHECK(iStart <= chars->size()); |
| DCHECK(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) { |
| DCHECK(iStart <= chars->size()); |
| DCHECK(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) { |
| DCHECK(iBaseLevel >= 0); |
| DCHECK(iBaseLevel <= kBidiMaxLevel); |
| DCHECK(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) { |
| DCHECK(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); |
| } |