Home | History | Annotate | Download | only in layout
      1 // Copyright 2017 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "xfa/fgas/layout/cfx_break.h"
      8 
      9 #include <algorithm>
     10 #include <vector>
     11 
     12 #include "third_party/base/stl_util.h"
     13 #include "xfa/fgas/font/cfgas_gefont.h"
     14 
     15 namespace {
     16 
     17 const int kMinimumTabWidth = 160000;
     18 
     19 }  // namespace
     20 
     21 CFX_Break::CFX_Break(uint32_t dwLayoutStyles)
     22     : m_eCharType(FX_CHARTYPE_Unknown),
     23       m_bSingleLine(false),
     24       m_bCombText(false),
     25       m_dwIdentity(0),
     26       m_dwLayoutStyles(dwLayoutStyles),
     27       m_iLineStart(0),
     28       m_iLineWidth(2000000),
     29       m_wParagraphBreakChar(L'\n'),
     30       m_iFontSize(240),
     31       m_iTabWidth(720000),
     32       m_iHorizontalScale(100),
     33       m_iVerticalScale(100),
     34       m_iTolerance(0),
     35       m_iCharSpace(0),
     36       m_iDefChar(0),
     37       m_wDefChar(0xFEFF),
     38       m_pFont(nullptr),
     39       m_pCurLine(nullptr),
     40       m_iReadyLineIndex(-1) {
     41   m_pCurLine = &m_Line[0];
     42 }
     43 
     44 CFX_Break::~CFX_Break() {}
     45 
     46 void CFX_Break::Reset() {
     47   m_eCharType = FX_CHARTYPE_Unknown;
     48   m_Line[0].Clear();
     49   m_Line[1].Clear();
     50 }
     51 
     52 void CFX_Break::SetLayoutStyles(uint32_t dwLayoutStyles) {
     53   m_dwLayoutStyles = dwLayoutStyles;
     54   m_bSingleLine = (m_dwLayoutStyles & FX_LAYOUTSTYLE_SingleLine) != 0;
     55   m_bCombText = (m_dwLayoutStyles & FX_LAYOUTSTYLE_CombText) != 0;
     56 }
     57 
     58 void CFX_Break::SetHorizontalScale(int32_t iScale) {
     59   iScale = std::max(iScale, 0);
     60   if (m_iHorizontalScale == iScale)
     61     return;
     62 
     63   SetBreakStatus();
     64   m_iHorizontalScale = iScale;
     65 }
     66 
     67 void CFX_Break::SetVerticalScale(int32_t iScale) {
     68   if (iScale < 0)
     69     iScale = 0;
     70   if (m_iVerticalScale == iScale)
     71     return;
     72 
     73   SetBreakStatus();
     74   m_iVerticalScale = iScale;
     75 }
     76 
     77 void CFX_Break::SetFont(const RetainPtr<CFGAS_GEFont>& pFont) {
     78   if (!pFont || pFont == m_pFont)
     79     return;
     80 
     81   SetBreakStatus();
     82   m_pFont = pFont;
     83   FontChanged();
     84 }
     85 
     86 void CFX_Break::SetFontSize(float fFontSize) {
     87   int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
     88   if (m_iFontSize == iFontSize)
     89     return;
     90 
     91   SetBreakStatus();
     92   m_iFontSize = iFontSize;
     93   FontChanged();
     94 }
     95 
     96 void CFX_Break::SetBreakStatus() {
     97   ++m_dwIdentity;
     98   int32_t iCount = m_pCurLine->CountChars();
     99   if (iCount < 1)
    100     return;
    101 
    102   CFX_Char* tc = m_pCurLine->GetChar(iCount - 1);
    103   if (tc->m_dwStatus == CFX_BreakType::None)
    104     tc->m_dwStatus = CFX_BreakType::Piece;
    105 }
    106 
    107 FX_CHARTYPE CFX_Break::GetUnifiedCharType(FX_CHARTYPE chartype) const {
    108   return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype;
    109 }
    110 
    111 void CFX_Break::FontChanged() {
    112   m_iDefChar = 0;
    113   if (!m_pFont || m_wDefChar == 0xFEFF)
    114     return;
    115 
    116   m_pFont->GetCharWidth(m_wDefChar, m_iDefChar);
    117   m_iDefChar *= m_iFontSize;
    118 }
    119 
    120 void CFX_Break::SetTabWidth(float fTabWidth) {
    121   // Note, the use of max here was only done in the TxtBreak code. Leaving this
    122   // in for the RTFBreak code for consistency. If we see issues with tab widths
    123   // we may need to fix this.
    124   m_iTabWidth = std::max(FXSYS_round(fTabWidth * 20000.0f), kMinimumTabWidth);
    125 }
    126 
    127 void CFX_Break::SetDefaultChar(wchar_t wch) {
    128   m_wDefChar = wch;
    129   m_iDefChar = 0;
    130   if (m_wDefChar == 0xFEFF || !m_pFont)
    131     return;
    132 
    133   m_pFont->GetCharWidth(m_wDefChar, m_iDefChar);
    134   if (m_iDefChar < 0)
    135     m_iDefChar = 0;
    136   else
    137     m_iDefChar *= m_iFontSize;
    138 }
    139 
    140 void CFX_Break::SetParagraphBreakChar(wchar_t wch) {
    141   if (wch != L'\r' && wch != L'\n')
    142     return;
    143   m_wParagraphBreakChar = wch;
    144 }
    145 
    146 void CFX_Break::SetLineBreakTolerance(float fTolerance) {
    147   m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
    148 }
    149 
    150 void CFX_Break::SetCharSpace(float fCharSpace) {
    151   m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
    152 }
    153 
    154 void CFX_Break::SetLineBoundary(float fLineStart, float fLineEnd) {
    155   if (fLineStart > fLineEnd)
    156     return;
    157 
    158   m_iLineStart = FXSYS_round(fLineStart * 20000.0f);
    159   m_iLineWidth = FXSYS_round(fLineEnd * 20000.0f);
    160   m_pCurLine->m_iStart = std::min(m_pCurLine->m_iStart, m_iLineWidth);
    161   m_pCurLine->m_iStart = std::max(m_pCurLine->m_iStart, m_iLineStart);
    162 }
    163 
    164 CFX_Char* CFX_Break::GetLastChar(int32_t index,
    165                                  bool bOmitChar,
    166                                  bool bRichText) const {
    167   std::vector<CFX_Char>& tca = m_pCurLine->m_LineChars;
    168   if (!pdfium::IndexInBounds(tca, index))
    169     return nullptr;
    170 
    171   int32_t iStart = pdfium::CollectionSize<int32_t>(tca) - 1;
    172   while (iStart > -1) {
    173     CFX_Char* pTC = &tca[iStart--];
    174     if (((bRichText && pTC->m_iCharWidth < 0) || bOmitChar) &&
    175         pTC->GetCharType() == FX_CHARTYPE_Combination) {
    176       continue;
    177     }
    178     if (--index < 0)
    179       return pTC;
    180   }
    181   return nullptr;
    182 }
    183 
    184 int32_t CFX_Break::CountBreakPieces() const {
    185   return HasLine() ? pdfium::CollectionSize<int32_t>(
    186                          m_Line[m_iReadyLineIndex].m_LinePieces)
    187                    : 0;
    188 }
    189 
    190 const CFX_BreakPiece* CFX_Break::GetBreakPieceUnstable(int32_t index) const {
    191   if (!HasLine())
    192     return nullptr;
    193   if (!pdfium::IndexInBounds(m_Line[m_iReadyLineIndex].m_LinePieces, index))
    194     return nullptr;
    195   return &m_Line[m_iReadyLineIndex].m_LinePieces[index];
    196 }
    197 
    198 void CFX_Break::ClearBreakPieces() {
    199   if (HasLine())
    200     m_Line[m_iReadyLineIndex].Clear();
    201   m_iReadyLineIndex = -1;
    202 }
    203