• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CFX_Break(uint32_t dwLayoutStyles)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 
~CFX_Break()44 CFX_Break::~CFX_Break() {}
45 
Reset()46 void CFX_Break::Reset() {
47   m_eCharType = FX_CHARTYPE_Unknown;
48   m_Line[0].Clear();
49   m_Line[1].Clear();
50 }
51 
SetLayoutStyles(uint32_t dwLayoutStyles)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 
SetHorizontalScale(int32_t iScale)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 
SetVerticalScale(int32_t iScale)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 
SetFont(const RetainPtr<CFGAS_GEFont> & pFont)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 
SetFontSize(float fFontSize)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 
SetBreakStatus()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 
GetUnifiedCharType(FX_CHARTYPE chartype) const107 FX_CHARTYPE CFX_Break::GetUnifiedCharType(FX_CHARTYPE chartype) const {
108   return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype;
109 }
110 
FontChanged()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 
SetTabWidth(float fTabWidth)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 
SetDefaultChar(wchar_t wch)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 
SetParagraphBreakChar(wchar_t wch)140 void CFX_Break::SetParagraphBreakChar(wchar_t wch) {
141   if (wch != L'\r' && wch != L'\n')
142     return;
143   m_wParagraphBreakChar = wch;
144 }
145 
SetLineBreakTolerance(float fTolerance)146 void CFX_Break::SetLineBreakTolerance(float fTolerance) {
147   m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
148 }
149 
SetCharSpace(float fCharSpace)150 void CFX_Break::SetCharSpace(float fCharSpace) {
151   m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
152 }
153 
SetLineBoundary(float fLineStart,float fLineEnd)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 
GetLastChar(int32_t index,bool bOmitChar,bool bRichText) const164 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 
CountBreakPieces() const184 int32_t CFX_Break::CountBreakPieces() const {
185   return HasLine() ? pdfium::CollectionSize<int32_t>(
186                          m_Line[m_iReadyLineIndex].m_LinePieces)
187                    : 0;
188 }
189 
GetBreakPieceUnstable(int32_t index) const190 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 
ClearBreakPieces()198 void CFX_Break::ClearBreakPieces() {
199   if (HasLine())
200     m_Line[m_iReadyLineIndex].Clear();
201   m_iReadyLineIndex = -1;
202 }
203