1 // Copyright 2014 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 #ifndef XFA_FGAS_LAYOUT_FGAS_TEXTBREAK_H_
8 #define XFA_FGAS_LAYOUT_FGAS_TEXTBREAK_H_
9 
10 #include <deque>
11 #include <memory>
12 #include <vector>
13 
14 #include "core/fxcrt/fx_ucd.h"
15 #include "core/fxge/cfx_renderdevice.h"
16 #include "third_party/base/stl_util.h"
17 #include "xfa/fgas/crt/fgas_utils.h"
18 
19 class CFX_Char;
20 class CFGAS_GEFont;
21 class CFX_TxtChar;
22 class CFX_TxtPiece;
23 class IFX_TxtAccess;
24 struct FDE_TEXTEDITPIECE;
25 
26 #define FX_TXTBREAKPOLICY_None 0x00
27 #define FX_TXTBREAKPOLICY_Pagination 0x01
28 #define FX_TXTBREAKPOLICY_SpaceBreak 0x02
29 #define FX_TXTBREAKPOLICY_NumberBreak 0x04
30 #define FX_TXTBREAK_None 0x00
31 #define FX_TXTBREAK_PieceBreak 0x01
32 #define FX_TXTBREAK_LineBreak 0x02
33 #define FX_TXTBREAK_ParagraphBreak 0x03
34 #define FX_TXTBREAK_PageBreak 0x04
35 #define FX_TXTBREAK_ControlChar 0x10
36 #define FX_TXTBREAK_BreakChar 0x20
37 #define FX_TXTBREAK_UnknownChar 0x40
38 #define FX_TXTBREAK_RemoveChar 0x80
39 #define FX_TXTLAYOUTSTYLE_MutipleFormat 0x0001
40 #define FX_TXTLAYOUTSTYLE_VerticalLayout 0x0002
41 #define FX_TXTLAYOUTSTYLE_VerticalChars 0x0004
42 #define FX_TXTLAYOUTSTYLE_ReverseLine 0x0008
43 #define FX_TXTLAYOUTSTYLE_ArabicContext 0x0010
44 #define FX_TXTLAYOUTSTYLE_ArabicShapes 0x0020
45 #define FX_TXTLAYOUTSTYLE_RTLReadingOrder 0x0040
46 #define FX_TXTLAYOUTSTYLE_ExpandTab 0x0100
47 #define FX_TXTLAYOUTSTYLE_SingleLine 0x0200
48 #define FX_TXTLAYOUTSTYLE_CombText 0x0400
49 #define FX_TXTCHARSTYLE_Alignment 0x000F
50 #define FX_TXTCHARSTYLE_ArabicNumber 0x0010
51 #define FX_TXTCHARSTYLE_ArabicShadda 0x0020
52 #define FX_TXTCHARSTYLE_OddBidiLevel 0x0040
53 #define FX_TXTCHARSTYLE_RTLReadingOrder 0x0080
54 #define FX_TXTCHARSTYLE_ArabicContext 0x0300
55 #define FX_TXTCHARSTYLE_ArabicIndic 0x0400
56 #define FX_TXTCHARSTYLE_ArabicComma 0x0800
57 #define FX_TXTLINEALIGNMENT_Left 0
58 #define FX_TXTLINEALIGNMENT_Center 1
59 #define FX_TXTLINEALIGNMENT_Right 2
60 #define FX_TXTLINEALIGNMENT_Justified (1 << 2)
61 #define FX_TXTLINEALIGNMENT_Distributed (2 << 2)
62 #define FX_TXTLINEALIGNMENT_JustifiedLeft \
63   (FX_TXTLINEALIGNMENT_Left | FX_TXTLINEALIGNMENT_Justified)
64 #define FX_TXTLINEALIGNMENT_JustifiedCenter \
65   (FX_TXTLINEALIGNMENT_Center | FX_TXTLINEALIGNMENT_Justified)
66 #define FX_TXTLINEALIGNMENT_JustifiedRight \
67   (FX_TXTLINEALIGNMENT_Right | FX_TXTLINEALIGNMENT_Justified)
68 #define FX_TXTLINEALIGNMENT_DistributedLeft \
69   (FX_TXTLINEALIGNMENT_Left | FX_TXTLINEALIGNMENT_Distributed)
70 #define FX_TXTLINEALIGNMENT_DistributedCenter \
71   (FX_TXTLINEALIGNMENT_Center | FX_TXTLINEALIGNMENT_Distributed)
72 #define FX_TXTLINEALIGNMENT_DistributedRight \
73   (FX_TXTLINEALIGNMENT_Right | FX_TXTLINEALIGNMENT_Distributed)
74 #define FX_TXTLINEALIGNMENT_LowerMask 0x03
75 #define FX_TXTLINEALIGNMENT_HigherMask 0x0C
76 #define FX_TXTBREAK_MinimumTabWidth 160000
77 
78 struct FX_TPO {
79   int32_t index;
80   int32_t pos;
81 
82   bool operator<(const FX_TPO& that) const { return pos < that.pos; }
83 };
84 
85 class IFX_TxtAccess {
86  public:
~IFX_TxtAccess()87   virtual ~IFX_TxtAccess() {}
88   virtual FX_WCHAR GetChar(const FDE_TEXTEDITPIECE* pIdentity,
89                            int32_t index) const = 0;
90   virtual int32_t GetWidth(const FDE_TEXTEDITPIECE* pIdentity,
91                            int32_t index) const = 0;
92 };
93 
94 struct FX_TXTRUN {
95   FX_TXTRUN();
96   FX_TXTRUN(const FX_TXTRUN& other);
97   ~FX_TXTRUN();
98 
99   IFX_TxtAccess* pAccess;
100   const FDE_TEXTEDITPIECE* pIdentity;
101   CFX_WideString wsStr;
102   int32_t* pWidths;
103   int32_t iLength;
104   CFX_RetainPtr<CFGAS_GEFont> pFont;
105   FX_FLOAT fFontSize;
106   uint32_t dwStyles;
107   int32_t iHorizontalScale;
108   int32_t iVerticalScale;
109   int32_t iCharRotation;
110   uint32_t dwCharStyles;
111   const CFX_RectF* pRect;
112   FX_WCHAR wLineBreakChar;
113   bool bSkipSpace;
114 };
115 
116 class CFX_TxtPiece {
117  public:
118   CFX_TxtPiece();
119 
GetEndPos()120   int32_t GetEndPos() const {
121     return m_iWidth < 0 ? m_iStartPos : m_iStartPos + m_iWidth;
122   }
GetLength()123   int32_t GetLength() const { return m_iChars; }
GetEndChar()124   int32_t GetEndChar() const { return m_iStartChar + m_iChars; }
GetCharPtr(int32_t index)125   CFX_TxtChar* GetCharPtr(int32_t index) const {
126     ASSERT(index > -1 && index < m_iChars && m_pChars);
127     return &(*m_pChars)[m_iStartChar + index];
128   }
GetString(FX_WCHAR * pText)129   void GetString(FX_WCHAR* pText) const {
130     ASSERT(pText);
131     int32_t iEndChar = m_iStartChar + m_iChars;
132     for (int32_t i = m_iStartChar; i < iEndChar; i++)
133       *pText++ = static_cast<FX_WCHAR>((*m_pChars)[i].m_wCharCode);
134   }
GetString(CFX_WideString & wsText)135   void GetString(CFX_WideString& wsText) const {
136     FX_WCHAR* pText = wsText.GetBuffer(m_iChars);
137     GetString(pText);
138     wsText.ReleaseBuffer(m_iChars);
139   }
GetWidths(int32_t * pWidths)140   void GetWidths(int32_t* pWidths) const {
141     ASSERT(pWidths);
142     int32_t iEndChar = m_iStartChar + m_iChars;
143     for (int32_t i = m_iStartChar; i < iEndChar; i++)
144       *pWidths++ = (*m_pChars)[i].m_iCharWidth;
145   }
146 
147   uint32_t m_dwStatus;
148   int32_t m_iStartPos;
149   int32_t m_iWidth;
150   int32_t m_iStartChar;
151   int32_t m_iChars;
152   int32_t m_iBidiLevel;
153   int32_t m_iBidiPos;
154   int32_t m_iHorizontalScale;
155   int32_t m_iVerticalScale;
156   uint32_t m_dwCharStyles;
157   std::vector<CFX_TxtChar>* m_pChars;
158   void* m_pUserData;
159 };
160 
161 typedef CFX_BaseArrayTemplate<CFX_TxtPiece> CFX_TxtPieceArray;
162 
163 class CFX_TxtLine {
164  public:
165   explicit CFX_TxtLine(int32_t iBlockSize);
166   ~CFX_TxtLine();
167 
CountChars()168   int32_t CountChars() const {
169     return pdfium::CollectionSize<int32_t>(*m_pLineChars);
170   }
171 
GetCharPtr(int32_t index)172   CFX_TxtChar* GetCharPtr(int32_t index) const {
173     ASSERT(index >= 0 &&
174            index < pdfium::CollectionSize<int32_t>(*m_pLineChars));
175     return &(*m_pLineChars)[index];
176   }
177 
CountPieces()178   int32_t CountPieces() const { return m_pLinePieces->GetSize(); }
GetPiecePtr(int32_t index)179   CFX_TxtPiece* GetPiecePtr(int32_t index) const {
180     ASSERT(index > -1 && index < m_pLinePieces->GetSize());
181     return m_pLinePieces->GetPtrAt(index);
182   }
183 
GetString(CFX_WideString & wsStr)184   void GetString(CFX_WideString& wsStr) const {
185     int32_t iCount = pdfium::CollectionSize<int32_t>(*m_pLineChars);
186     FX_WCHAR* pBuf = wsStr.GetBuffer(iCount);
187     for (int32_t i = 0; i < iCount; i++)
188       *pBuf++ = static_cast<FX_WCHAR>((*m_pLineChars)[i].m_wCharCode);
189     wsStr.ReleaseBuffer(iCount);
190   }
191 
192   void RemoveAll(bool bLeaveMemory = false) {
193     m_pLineChars->clear();
194     m_pLinePieces->RemoveAll(bLeaveMemory);
195     m_iWidth = 0;
196     m_iArabicChars = 0;
197   }
198 
199   std::unique_ptr<std::vector<CFX_TxtChar>> m_pLineChars;
200   std::unique_ptr<CFX_TxtPieceArray> m_pLinePieces;
201   int32_t m_iStart;
202   int32_t m_iWidth;
203   int32_t m_iArabicChars;
204 };
205 
206 class CFX_TxtBreak {
207  public:
208   explicit CFX_TxtBreak(uint32_t dwPolicies);
209   ~CFX_TxtBreak();
210 
211   void SetLineWidth(FX_FLOAT fLineWidth);
212   void SetLinePos(FX_FLOAT fLinePos);
GetLayoutStyles()213   uint32_t GetLayoutStyles() const { return m_dwLayoutStyles; }
214   void SetLayoutStyles(uint32_t dwLayoutStyles);
215   void SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont);
216   void SetFontSize(FX_FLOAT fFontSize);
217   void SetTabWidth(FX_FLOAT fTabWidth, bool bEquidistant);
218   void SetDefaultChar(FX_WCHAR wch);
219   void SetParagraphBreakChar(FX_WCHAR wch);
220   void SetLineBreakTolerance(FX_FLOAT fTolerance);
221   void SetHorizontalScale(int32_t iScale);
222   void SetCharRotation(int32_t iCharRotation);
223   void SetCharSpace(FX_FLOAT fCharSpace);
224   void SetAlignment(int32_t iAlignment);
225   void SetCombWidth(FX_FLOAT fCombWidth);
226   void SetUserData(void* pUserData);
227   uint32_t AppendChar(FX_WCHAR wch);
228   uint32_t EndBreak(uint32_t dwStatus = FX_TXTBREAK_PieceBreak);
229   int32_t CountBreakPieces() const;
230   const CFX_TxtPiece* GetBreakPiece(int32_t index) const;
231   void ClearBreakPieces();
232   void Reset();
233   int32_t GetDisplayPos(const FX_TXTRUN* pTxtRun,
234                         FXTEXT_CHARPOS* pCharPos,
235                         bool bCharCode = false,
236                         CFX_WideString* pWSForms = nullptr) const;
237   std::vector<CFX_RectF> GetCharRects(const FX_TXTRUN* pTxtRun,
238                                       bool bCharBBox = false) const;
239   void AppendChar_PageLoad(CFX_TxtChar* pCurChar, uint32_t dwProps);
240   uint32_t AppendChar_Combination(CFX_TxtChar* pCurChar, int32_t iRotation);
241   uint32_t AppendChar_Tab(CFX_TxtChar* pCurChar, int32_t iRotation);
242   uint32_t AppendChar_Control(CFX_TxtChar* pCurChar, int32_t iRotation);
243   uint32_t AppendChar_Arabic(CFX_TxtChar* pCurChar, int32_t iRotation);
244   uint32_t AppendChar_Others(CFX_TxtChar* pCurChar, int32_t iRotation);
245 
246  private:
247   void FontChanged();
248   void SetBreakStatus();
249   int32_t GetLineRotation(uint32_t dwStyles) const;
250   CFX_TxtChar* GetLastChar(int32_t index, bool bOmitChar = true) const;
251   CFX_TxtLine* GetTxtLine() const;
252   CFX_TxtPieceArray* GetTxtPieces() const;
253   FX_CHARTYPE GetUnifiedCharType(FX_CHARTYPE dwType) const;
254   void ResetArabicContext();
255   void ResetContextCharStyles();
256   void EndBreak_UpdateArabicShapes();
257   bool EndBreak_SplitLine(CFX_TxtLine* pNextLine,
258                           bool bAllChars,
259                           uint32_t dwStatus);
260   void EndBreak_BidiLine(std::deque<FX_TPO>* tpos, uint32_t dwStatus);
261   void EndBreak_Alignment(const std::deque<FX_TPO>& tpos,
262                           bool bAllChars,
263                           uint32_t dwStatus);
264   int32_t GetBreakPos(std::vector<CFX_TxtChar>& ca,
265                       int32_t& iEndPos,
266                       bool bAllChars = false,
267                       bool bOnlyBrk = false);
268   void SplitTextLine(CFX_TxtLine* pCurLine,
269                      CFX_TxtLine* pNextLine,
270                      bool bAllChars = false);
271 
272   uint32_t m_dwPolicies;
273   bool m_bPagination;
274   int32_t m_iLineWidth;
275   uint32_t m_dwLayoutStyles;
276   bool m_bVertical;
277   bool m_bArabicContext;
278   bool m_bArabicShapes;
279   bool m_bRTL;
280   bool m_bSingleLine;
281   bool m_bCombText;
282   int32_t m_iArabicContext;
283   int32_t m_iCurArabicContext;
284   CFX_RetainPtr<CFGAS_GEFont> m_pFont;
285   int32_t m_iFontSize;
286   bool m_bEquidistant;
287   int32_t m_iTabWidth;
288   FX_WCHAR m_wDefChar;
289   FX_WCHAR m_wParagBreakChar;
290   int32_t m_iDefChar;
291   int32_t m_iLineRotation;
292   int32_t m_iCharRotation;
293   int32_t m_iRotation;
294   int32_t m_iAlignment;
295   uint32_t m_dwContextCharStyles;
296   int32_t m_iCombWidth;
297   void* m_pUserData;
298   FX_CHARTYPE m_eCharType;
299   bool m_bCurRTL;
300   int32_t m_iCurAlignment;
301   bool m_bArabicNumber;
302   bool m_bArabicComma;
303   std::unique_ptr<CFX_TxtLine> m_pTxtLine1;
304   std::unique_ptr<CFX_TxtLine> m_pTxtLine2;
305   CFX_TxtLine* m_pCurLine;
306   int32_t m_iReady;
307   int32_t m_iTolerance;
308   int32_t m_iHorScale;
309   int32_t m_iCharSpace;
310 };
311 
312 #endif  // XFA_FGAS_LAYOUT_FGAS_TEXTBREAK_H_
313