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_RTFBREAK_H_
8 #define XFA_FGAS_LAYOUT_FGAS_RTFBREAK_H_
9 
10 #include "core/fxcrt/include/fx_basic.h"
11 #include "core/fxcrt/include/fx_ucd.h"
12 #include "xfa/fgas/crt/fgas_memory.h"
13 #include "xfa/fgas/crt/fgas_utils.h"
14 #include "xfa/fgas/layout/fgas_textbreak.h"
15 #include "xfa/fgas/layout/fgas_unicode.h"
16 
17 class CFGAS_GEFont;
18 
19 #define FX_RTFBREAKPOLICY_None 0x00
20 #define FX_RTFBREAKPOLICY_SpaceBreak 0x01
21 #define FX_RTFBREAKPOLICY_NumberBreak 0x02
22 #define FX_RTFBREAKPOLICY_InfixBreak 0x04
23 #define FX_RTFBREAKPOLICY_TabBreak 0x08
24 #define FX_RTFBREAKPOLICY_OrphanPositionedTab 0x10
25 #define FX_RTFBREAK_None 0x00
26 #define FX_RTFBREAK_PieceBreak 0x01
27 #define FX_RTFBREAK_LineBreak 0x02
28 #define FX_RTFBREAK_ParagraphBreak 0x03
29 #define FX_RTFBREAK_PageBreak 0x04
30 #define FX_RTFLAYOUTSTYLE_Pagination 0x01
31 #define FX_RTFLAYOUTSTYLE_VerticalLayout 0x02
32 #define FX_RTFLAYOUTSTYLE_VerticalChars 0x04
33 #define FX_RTFLAYOUTSTYLE_LineDirection 0x08
34 #define FX_RTFLAYOUTSTYLE_ExpandTab 0x10
35 #define FX_RTFLAYOUTSTYLE_ArabicNumber 0x20
36 #define FX_RTFLAYOUTSTYLE_SingleLine 0x40
37 #define FX_RTFLAYOUTSTYLE_MBCSCode 0x80
38 #define FX_RTFCHARSTYLE_Alignment 0x000F
39 #define FX_RTFCHARSTYLE_ArabicNumber 0x0010
40 #define FX_RTFCHARSTYLE_ArabicShadda 0x0020
41 #define FX_RTFCHARSTYLE_OddBidiLevel 0x0040
42 #define FX_RTFCHARSTYLE_RTLReadingOrder 0x0080
43 #define FX_RTFCHARSTYLE_ArabicContext 0x0300
44 #define FX_RTFCHARSTYLE_ArabicIndic 0x0400
45 #define FX_RTFCHARSTYLE_ArabicComma 0x0800
46 #define FX_RTFLINEALIGNMENT_Left 0
47 #define FX_RTFLINEALIGNMENT_Center 1
48 #define FX_RTFLINEALIGNMENT_Right 2
49 #define FX_RTFLINEALIGNMENT_Justified (1 << 2)
50 #define FX_RTFLINEALIGNMENT_Distributed (2 << 2)
51 #define FX_RTFLINEALIGNMENT_JustifiedLeft \
52   (FX_RTFLINEALIGNMENT_Left | FX_RTFLINEALIGNMENT_Justified)
53 #define FX_RTFLINEALIGNMENT_JustifiedCenter \
54   (FX_RTFLINEALIGNMENT_Center | FX_RTFLINEALIGNMENT_Justified)
55 #define FX_RTFLINEALIGNMENT_JustifiedRight \
56   (FX_RTFLINEALIGNMENT_Right | FX_RTFLINEALIGNMENT_Justified)
57 #define FX_RTFLINEALIGNMENT_DistributedLeft \
58   (FX_RTFLINEALIGNMENT_Left | FX_RTFLINEALIGNMENT_Distributed)
59 #define FX_RTFLINEALIGNMENT_DistributedCenter \
60   (FX_RTFLINEALIGNMENT_Center | FX_RTFLINEALIGNMENT_Distributed)
61 #define FX_RTFLINEALIGNMENT_DistributedRight \
62   (FX_RTFLINEALIGNMENT_Right | FX_RTFLINEALIGNMENT_Distributed)
63 #define FX_RTFLINEALIGNMENT_LowerMask 0x03
64 #define FX_RTFLINEALIGNMENT_HigherMask 0x0C
65 
66 struct FX_RTFTEXTOBJ {
67   FX_RTFTEXTOBJ();
68 
69   const FX_WCHAR* pStr;
70   int32_t* pWidths;
71   int32_t iLength;
72   CFGAS_GEFont* pFont;
73   FX_FLOAT fFontSize;
74   uint32_t dwLayoutStyles;
75   int32_t iCharRotation;
76   int32_t iBidiLevel;
77   const CFX_RectF* pRect;
78   FX_WCHAR wLineBreakChar;
79   int32_t iHorizontalScale;
80   int32_t iVerticalScale;
81 };
82 
83 class CFX_RTFPiece : public CFX_Target {
84  public:
85   CFX_RTFPiece();
86   ~CFX_RTFPiece() override;
87 
AppendChar(const CFX_RTFChar & tc)88   void AppendChar(const CFX_RTFChar& tc) {
89     ASSERT(m_pChars);
90     m_pChars->Add(tc);
91     if (m_iWidth < 0) {
92       m_iWidth = tc.m_iCharWidth;
93     } else {
94       m_iWidth += tc.m_iCharWidth;
95     }
96     m_iChars++;
97   }
GetEndPos()98   int32_t GetEndPos() const {
99     return m_iWidth < 0 ? m_iStartPos : m_iStartPos + m_iWidth;
100   }
GetLength()101   int32_t GetLength() const { return m_iChars; }
GetEndChar()102   int32_t GetEndChar() const { return m_iStartChar + m_iChars; }
GetChar(int32_t index)103   CFX_RTFChar& GetChar(int32_t index) {
104     ASSERT(index > -1 && index < m_iChars && m_pChars);
105     return *m_pChars->GetDataPtr(m_iStartChar + index);
106   }
GetCharPtr(int32_t index)107   CFX_RTFChar* GetCharPtr(int32_t index) const {
108     ASSERT(index > -1 && index < m_iChars && m_pChars);
109     return m_pChars->GetDataPtr(m_iStartChar + index);
110   }
GetString(FX_WCHAR * pText)111   void GetString(FX_WCHAR* pText) const {
112     ASSERT(pText);
113     int32_t iEndChar = m_iStartChar + m_iChars;
114     CFX_RTFChar* pChar;
115     for (int32_t i = m_iStartChar; i < iEndChar; i++) {
116       pChar = m_pChars->GetDataPtr(i);
117       *pText++ = (FX_WCHAR)pChar->m_wCharCode;
118     }
119   }
GetString(CFX_WideString & wsText)120   void GetString(CFX_WideString& wsText) const {
121     FX_WCHAR* pText = wsText.GetBuffer(m_iChars);
122     GetString(pText);
123     wsText.ReleaseBuffer(m_iChars);
124   }
GetWidths(int32_t * pWidths)125   void GetWidths(int32_t* pWidths) const {
126     ASSERT(pWidths);
127     int32_t iEndChar = m_iStartChar + m_iChars;
128     CFX_RTFChar* pChar;
129     for (int32_t i = m_iStartChar; i < iEndChar; i++) {
130       pChar = m_pChars->GetDataPtr(i);
131       *pWidths++ = pChar->m_iCharWidth;
132     }
133   }
Reset()134   void Reset() {
135     m_dwStatus = FX_RTFBREAK_PieceBreak;
136     if (m_iWidth > -1) {
137       m_iStartPos += m_iWidth;
138     }
139     m_iWidth = -1;
140     m_iStartChar += m_iChars;
141     m_iChars = 0;
142     m_iBidiLevel = 0;
143     m_iBidiPos = 0;
144     m_iHorizontalScale = 100;
145     m_iVerticalScale = 100;
146   }
147 
148   uint32_t m_dwStatus;
149   int32_t m_iStartPos;
150   int32_t m_iWidth;
151   int32_t m_iStartChar;
152   int32_t m_iChars;
153   int32_t m_iBidiLevel;
154   int32_t m_iBidiPos;
155   int32_t m_iFontSize;
156   int32_t m_iFontHeight;
157   int32_t m_iHorizontalScale;
158   int32_t m_iVerticalScale;
159   uint32_t m_dwLayoutStyles;
160   uint32_t m_dwIdentity;
161   CFX_RTFCharArray* m_pChars;
162   IFX_Retainable* m_pUserData;
163 };
164 
165 typedef CFX_BaseArrayTemplate<CFX_RTFPiece> CFX_RTFPieceArray;
166 
167 class CFX_RTFLine {
168  public:
169   CFX_RTFLine();
170   ~CFX_RTFLine();
171 
CountChars()172   int32_t CountChars() const { return m_LineChars.GetSize(); }
GetChar(int32_t index)173   CFX_RTFChar& GetChar(int32_t index) {
174     ASSERT(index > -1 && index < m_LineChars.GetSize());
175     return *m_LineChars.GetDataPtr(index);
176   }
GetCharPtr(int32_t index)177   CFX_RTFChar* GetCharPtr(int32_t index) {
178     ASSERT(index > -1 && index < m_LineChars.GetSize());
179     return m_LineChars.GetDataPtr(index);
180   }
CountPieces()181   int32_t CountPieces() const { return m_LinePieces.GetSize(); }
GetPiece(int32_t index)182   CFX_RTFPiece& GetPiece(int32_t index) const {
183     ASSERT(index > -1 && index < m_LinePieces.GetSize());
184     return m_LinePieces.GetAt(index);
185   }
GetPiecePtr(int32_t index)186   CFX_RTFPiece* GetPiecePtr(int32_t index) const {
187     ASSERT(index > -1 && index < m_LinePieces.GetSize());
188     return m_LinePieces.GetPtrAt(index);
189   }
GetLineEnd()190   int32_t GetLineEnd() const { return m_iStart + m_iWidth; }
191   void RemoveAll(FX_BOOL bLeaveMemory = FALSE) {
192     CFX_RTFChar* pChar;
193     int32_t iCount = m_LineChars.GetSize();
194     for (int32_t i = 0; i < iCount; i++) {
195       pChar = m_LineChars.GetDataPtr(i);
196       if (pChar->m_pUserData)
197         pChar->m_pUserData->Release();
198     }
199     m_LineChars.RemoveAll();
200     m_LinePieces.RemoveAll(bLeaveMemory);
201     m_iWidth = 0;
202     m_iArabicChars = 0;
203     m_iMBCSChars = 0;
204   }
205 
206   CFX_RTFCharArray m_LineChars;
207   CFX_RTFPieceArray m_LinePieces;
208   int32_t m_iStart;
209   int32_t m_iWidth;
210   int32_t m_iArabicChars;
211   int32_t m_iMBCSChars;
212 };
213 
214 class CFX_RTFBreak {
215  public:
216   explicit CFX_RTFBreak(uint32_t dwPolicies);
217   ~CFX_RTFBreak();
218 
219   void SetLineBoundary(FX_FLOAT fLineStart, FX_FLOAT fLineEnd);
220   void SetLineStartPos(FX_FLOAT fLinePos);
GetLayoutStyles()221   uint32_t GetLayoutStyles() const { return m_dwLayoutStyles; }
222   void SetLayoutStyles(uint32_t dwLayoutStyles);
223   void SetFont(CFGAS_GEFont* pFont);
224   void SetFontSize(FX_FLOAT fFontSize);
225   void SetTabWidth(FX_FLOAT fTabWidth);
226   void AddPositionedTab(FX_FLOAT fTabPos);
227   void SetPositionedTabs(const CFX_FloatArray& tabs);
228   void ClearPositionedTabs();
229   void SetDefaultChar(FX_WCHAR wch);
230   void SetLineBreakChar(FX_WCHAR wch);
231   void SetLineBreakTolerance(FX_FLOAT fTolerance);
232   void SetHorizontalScale(int32_t iScale);
233   void SetVerticalScale(int32_t iScale);
234   void SetCharRotation(int32_t iCharRotation);
235   void SetCharSpace(FX_FLOAT fCharSpace);
236   void SetWordSpace(FX_BOOL bDefault, FX_FLOAT fWordSpace);
237   void SetReadingOrder(FX_BOOL bRTL = FALSE);
238   void SetAlignment(int32_t iAlignment = FX_RTFLINEALIGNMENT_Left);
239   void SetUserData(IFX_Retainable* pUserData);
240   uint32_t AppendChar(FX_WCHAR wch);
241   uint32_t EndBreak(uint32_t dwStatus = FX_RTFBREAK_PieceBreak);
242   int32_t CountBreakPieces() const;
243   const CFX_RTFPiece* GetBreakPiece(int32_t index) const;
244   void GetLineRect(CFX_RectF& rect) const;
245   void ClearBreakPieces();
246   void Reset();
247   int32_t GetDisplayPos(const FX_RTFTEXTOBJ* pText,
248                         FXTEXT_CHARPOS* pCharPos,
249                         FX_BOOL bCharCode = FALSE,
250                         CFX_WideString* pWSForms = nullptr,
251                         FX_AdjustCharDisplayPos pAdjustPos = nullptr) const;
252   int32_t GetCharRects(const FX_RTFTEXTOBJ* pText,
253                        CFX_RectFArray& rtArray,
254                        FX_BOOL bCharBBox = FALSE) const;
255   uint32_t AppendChar_CharCode(FX_WCHAR wch);
256   uint32_t AppendChar_Combination(CFX_RTFChar* pCurChar, int32_t iRotation);
257   uint32_t AppendChar_Tab(CFX_RTFChar* pCurChar, int32_t iRotation);
258   uint32_t AppendChar_Control(CFX_RTFChar* pCurChar, int32_t iRotation);
259   uint32_t AppendChar_Arabic(CFX_RTFChar* pCurChar, int32_t iRotation);
260   uint32_t AppendChar_Others(CFX_RTFChar* pCurChar, int32_t iRotation);
261 
262  protected:
263   int32_t GetLineRotation(uint32_t dwStyles) const;
264   void SetBreakStatus();
265   CFX_RTFChar* GetLastChar(int32_t index) const;
266   CFX_RTFLine* GetRTFLine(FX_BOOL bReady) const;
267   CFX_RTFPieceArray* GetRTFPieces(FX_BOOL bReady) const;
268   FX_CHARTYPE GetUnifiedCharType(FX_CHARTYPE chartype) const;
269   int32_t GetLastPositionedTab() const;
270   FX_BOOL GetPositionedTab(int32_t& iTabPos) const;
271 
272   int32_t GetBreakPos(CFX_RTFCharArray& tca,
273                       int32_t& iEndPos,
274                       FX_BOOL bAllChars = FALSE,
275                       FX_BOOL bOnlyBrk = FALSE);
276   void SplitTextLine(CFX_RTFLine* pCurLine,
277                      CFX_RTFLine* pNextLine,
278                      FX_BOOL bAllChars = FALSE);
279   FX_BOOL EndBreak_SplitLine(CFX_RTFLine* pNextLine,
280                              FX_BOOL bAllChars,
281                              uint32_t dwStatus);
282   void EndBreak_BidiLine(CFX_TPOArray& tpos, uint32_t dwStatus);
283   void EndBreak_Alignment(CFX_TPOArray& tpos,
284                           FX_BOOL bAllChars,
285                           uint32_t dwStatus);
286 
287   uint32_t m_dwPolicies;
288   int32_t m_iBoundaryStart;
289   int32_t m_iBoundaryEnd;
290   uint32_t m_dwLayoutStyles;
291   FX_BOOL m_bPagination;
292   FX_BOOL m_bVertical;
293   FX_BOOL m_bSingleLine;
294   FX_BOOL m_bCharCode;
295   CFGAS_GEFont* m_pFont;
296   int32_t m_iFontHeight;
297   int32_t m_iFontSize;
298   int32_t m_iTabWidth;
299   CFX_Int32Array m_PositionedTabs;
300   FX_BOOL m_bOrphanLine;
301   FX_WCHAR m_wDefChar;
302   int32_t m_iDefChar;
303   FX_WCHAR m_wLineBreakChar;
304   int32_t m_iHorizontalScale;
305   int32_t m_iVerticalScale;
306   int32_t m_iLineRotation;
307   int32_t m_iCharRotation;
308   int32_t m_iRotation;
309   int32_t m_iCharSpace;
310   FX_BOOL m_bWordSpace;
311   int32_t m_iWordSpace;
312   FX_BOOL m_bRTL;
313   int32_t m_iAlignment;
314   IFX_Retainable* m_pUserData;
315   FX_CHARTYPE m_eCharType;
316   uint32_t m_dwIdentity;
317   CFX_RTFLine m_RTFLine1;
318   CFX_RTFLine m_RTFLine2;
319   CFX_RTFLine* m_pCurLine;
320   int32_t m_iReady;
321   int32_t m_iTolerance;
322 };
323 
324 #endif  // XFA_FGAS_LAYOUT_FGAS_RTFBREAK_H_
325