// Copyright 2014 The PDFium Authors // 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/check_op.h" #include "core/fxcrt/fx_unicode.h" CFX_BidiChar::CFX_BidiChar() : m_CurrentSegment({0, 0, Direction::kNeutral}), m_LastSegment({0, 0, Direction::kNeutral}) {} bool CFX_BidiChar::AppendChar(wchar_t wch) { Direction direction; switch (pdfium::unicode::GetBidiClass(wch)) { case FX_BIDICLASS::kL: direction = Direction::kLeft; break; case FX_BIDICLASS::kAN: case FX_BIDICLASS::kEN: case FX_BIDICLASS::kNSM: case FX_BIDICLASS::kCS: case FX_BIDICLASS::kES: case FX_BIDICLASS::kET: case FX_BIDICLASS::kBN: direction = Direction::kLeftWeak; break; case FX_BIDICLASS::kR: case FX_BIDICLASS::kAL: direction = Direction::kRight; break; default: direction = Direction::kNeutral; break; } bool bChangeDirection = (direction != m_CurrentSegment.direction); if (bChangeDirection) StartNewSegment(direction); m_CurrentSegment.count++; return bChangeDirection; } bool CFX_BidiChar::EndChar() { StartNewSegment(Direction::kNeutral); 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::Direction::kRight; }); size_t nL2R = std::count_if( m_Order.begin(), m_Order.end(), [](const CFX_BidiChar::Segment& seg) { return seg.direction == CFX_BidiChar::Direction::kLeft; }); if (nR2L > 0 && nR2L >= nL2R) SetOverallDirectionRight(); } CFX_BidiString::~CFX_BidiString() = default; CFX_BidiChar::Direction CFX_BidiString::OverallDirection() const { DCHECK_NE(m_eOverallDirection, CFX_BidiChar::Direction::kNeutral); DCHECK_NE(m_eOverallDirection, CFX_BidiChar::Direction::kLeftWeak); return m_eOverallDirection; } void CFX_BidiString::SetOverallDirectionRight() { if (m_eOverallDirection != CFX_BidiChar::Direction::kRight) { std::reverse(m_Order.begin(), m_Order.end()); m_eOverallDirection = CFX_BidiChar::Direction::kRight; } }