// Copyright 2014 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 "core/fxcrt/fx_bidi.h" #include #include "core/fxcrt/fx_unicode.h" #include "third_party/base/stl_util.h" CFX_BidiChar::CFX_BidiChar() : m_CurrentSegment({0, 0, NEUTRAL}), m_LastSegment({0, 0, NEUTRAL}) {} bool CFX_BidiChar::AppendChar(wchar_t wch) { Direction direction; switch (FX_GetBidiClass(wch)) { case FX_BIDICLASS::kL: case FX_BIDICLASS::kAN: case FX_BIDICLASS::kEN: direction = LEFT; break; case FX_BIDICLASS::kR: case FX_BIDICLASS::kAL: direction = RIGHT; break; default: direction = NEUTRAL; break; } bool bChangeDirection = (direction != m_CurrentSegment.direction); if (bChangeDirection) StartNewSegment(direction); m_CurrentSegment.count++; return bChangeDirection; } bool CFX_BidiChar::EndChar() { StartNewSegment(NEUTRAL); return m_LastSegment.count > 0; } void CFX_BidiChar::StartNewSegment(CFX_BidiChar::Direction direction) { m_LastSegment = m_CurrentSegment; m_CurrentSegment.start += m_CurrentSegment.count; m_CurrentSegment.count = 0; m_CurrentSegment.direction = direction; } CFX_BidiString::CFX_BidiString(const WideString& str) : m_Str(str) { CFX_BidiChar bidi; for (wchar_t c : m_Str) { if (bidi.AppendChar(c)) m_Order.push_back(bidi.GetSegmentInfo()); } if (bidi.EndChar()) m_Order.push_back(bidi.GetSegmentInfo()); size_t nR2L = std::count_if(m_Order.begin(), m_Order.end(), [](const CFX_BidiChar::Segment& seg) { return seg.direction == CFX_BidiChar::RIGHT; }); size_t nL2R = std::count_if(m_Order.begin(), m_Order.end(), [](const CFX_BidiChar::Segment& seg) { return seg.direction == CFX_BidiChar::LEFT; }); if (nR2L > 0 && nR2L >= nL2R) SetOverallDirectionRight(); } CFX_BidiString::~CFX_BidiString() {} CFX_BidiChar::Direction CFX_BidiString::OverallDirection() const { ASSERT(m_eOverallDirection != CFX_BidiChar::NEUTRAL); return m_eOverallDirection; } void CFX_BidiString::SetOverallDirectionRight() { if (m_eOverallDirection != CFX_BidiChar::RIGHT) { std::reverse(m_Order.begin(), m_Order.end()); m_eOverallDirection = CFX_BidiChar::RIGHT; } }