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_FXFA_APP_XFA_TEXTLAYOUT_H_
8 #define XFA_FXFA_APP_XFA_TEXTLAYOUT_H_
9 
10 #include <map>
11 #include <memory>
12 
13 #include "xfa/fde/css/fde_css.h"
14 #include "xfa/fde/fde_gedevice.h"
15 #include "xfa/fxfa/include/xfa_ffdoc.h"
16 #include "xfa/fgas/layout/fgas_rtfbreak.h"
17 #include "xfa/fxfa/parser/xfa_object.h"
18 
19 #define XFA_LOADERCNTXTFLG_FILTERSPACE 0x001
20 
21 class CFDE_CSSStyleSelector;
22 class CXFA_Para;
23 class CXFA_Font;
24 class CXFA_TextProvider;
25 class CXFA_TextTabstopsContext;
26 
27 class CXFA_CSSTagProvider {
28  public:
29   using AttributeMap = std::map<CFX_WideString, CFX_WideString>;
30 
31   CXFA_CSSTagProvider();
32   ~CXFA_CSSTagProvider();
33 
GetTagName()34   CFX_WideString GetTagName() { return m_wsTagName; }
35 
begin()36   AttributeMap::iterator begin() { return m_Attributes.begin(); }
end()37   AttributeMap::iterator end() { return m_Attributes.end(); }
38 
empty()39   bool empty() const { return m_Attributes.empty(); }
40 
SetTagNameObj(const CFX_WideString & wsName)41   void SetTagNameObj(const CFX_WideString& wsName) { m_wsTagName = wsName; }
SetAttribute(const CFX_WideString & wsAttr,const CFX_WideString & wsValue)42   void SetAttribute(const CFX_WideString& wsAttr,
43                     const CFX_WideString& wsValue) {
44     m_Attributes.insert({wsAttr, wsValue});
45   }
46 
47   FX_BOOL m_bTagAvailable;
48   FX_BOOL m_bContent;
49 
50  protected:
51   CFX_WideString m_wsTagName;
52   AttributeMap m_Attributes;
53 };
54 
55 class CXFA_TextParseContext : public CFX_Target {
56  public:
57   CXFA_TextParseContext();
58   ~CXFA_TextParseContext() override;
59 
SetDisplay(FDE_CSSDISPLAY eDisplay)60   void SetDisplay(FDE_CSSDISPLAY eDisplay) { m_eDisplay = eDisplay; }
GetDisplay()61   FDE_CSSDISPLAY GetDisplay() const { return m_eDisplay; }
62   void SetDecls(const CFDE_CSSDeclaration** ppDeclArray, int32_t iDeclCount);
GetDecls()63   const CFDE_CSSDeclaration** GetDecls() {
64     return const_cast<const CFDE_CSSDeclaration**>(m_ppMatchedDecls);
65   }
CountDecls()66   uint32_t CountDecls() const { return m_dwMatchedDecls; }
67 
68   IFDE_CSSComputedStyle* m_pParentStyle;
69 
70  protected:
71   CFDE_CSSDeclaration** m_ppMatchedDecls;
72   uint32_t m_dwMatchedDecls;
73   FDE_CSSDISPLAY m_eDisplay;
74 };
75 
76 class CXFA_TextParser {
77  public:
78   CXFA_TextParser();
79   virtual ~CXFA_TextParser();
80 
81   void Reset();
82   void DoParse(CFDE_XMLNode* pXMLContainer, CXFA_TextProvider* pTextProvider);
83   IFDE_CSSComputedStyle* CreateRootStyle(CXFA_TextProvider* pTextProvider);
84   IFDE_CSSComputedStyle* ComputeStyle(CFDE_XMLNode* pXMLNode,
85                                       IFDE_CSSComputedStyle* pParentStyle);
IsParsed()86   FX_BOOL IsParsed() const { return !!m_pAllocator; }
87 
88   int32_t GetVAlign(CXFA_TextProvider* pTextProvider) const;
89   FX_FLOAT GetTabInterval(IFDE_CSSComputedStyle* pStyle) const;
90   int32_t CountTabs(IFDE_CSSComputedStyle* pStyle) const;
91   FX_BOOL IsSpaceRun(IFDE_CSSComputedStyle* pStyle) const;
92   FX_BOOL GetTabstops(IFDE_CSSComputedStyle* pStyle,
93                       CXFA_TextTabstopsContext* pTabstopContext);
94   CFGAS_GEFont* GetFont(CXFA_TextProvider* pTextProvider,
95                         IFDE_CSSComputedStyle* pStyle) const;
96   FX_FLOAT GetFontSize(CXFA_TextProvider* pTextProvider,
97                        IFDE_CSSComputedStyle* pStyle) const;
98   int32_t GetHorScale(CXFA_TextProvider* pTextProvider,
99                       IFDE_CSSComputedStyle* pStyle,
100                       CFDE_XMLNode* pXMLNode) const;
101   int32_t GetVerScale(CXFA_TextProvider* pTextProvider,
102                       IFDE_CSSComputedStyle* pStyle) const;
103   void GetUnderline(CXFA_TextProvider* pTextProvider,
104                     IFDE_CSSComputedStyle* pStyle,
105                     int32_t& iUnderline,
106                     int32_t& iPeriod) const;
107   void GetLinethrough(CXFA_TextProvider* pTextProvider,
108                       IFDE_CSSComputedStyle* pStyle,
109                       int32_t& iLinethrough) const;
110   FX_ARGB GetColor(CXFA_TextProvider* pTextProvider,
111                    IFDE_CSSComputedStyle* pStyle) const;
112   FX_FLOAT GetBaseline(CXFA_TextProvider* pTextProvider,
113                        IFDE_CSSComputedStyle* pStyle) const;
114   FX_FLOAT GetLineHeight(CXFA_TextProvider* pTextProvider,
115                          IFDE_CSSComputedStyle* pStyle,
116                          FX_BOOL bFirst,
117                          FX_FLOAT fVerScale) const;
118   FX_BOOL GetEmbbedObj(CXFA_TextProvider* pTextProvider,
119                        CFDE_XMLNode* pXMLNode,
120                        CFX_WideString& wsValue);
121   CXFA_TextParseContext* GetParseContextFromMap(CFDE_XMLNode* pXMLNode);
122 
123  protected:
124   bool TagValidate(const CFX_WideString& str) const;
125 
126  private:
127   void InitCSSData(CXFA_TextProvider* pTextProvider);
128   void ParseRichText(CFDE_XMLNode* pXMLNode,
129                      IFDE_CSSComputedStyle* pParentStyle);
130   void ParseTagInfo(CFDE_XMLNode* pXMLNode, CXFA_CSSTagProvider& tagProvider);
131   IFDE_CSSStyleSheet* LoadDefaultSheetStyle();
132   IFDE_CSSComputedStyle* CreateStyle(IFDE_CSSComputedStyle* pParentStyle);
133   std::unique_ptr<IFX_MemoryAllocator> m_pAllocator;
134   std::unique_ptr<CFDE_CSSStyleSelector> m_pSelector;
135   IFDE_CSSStyleSheet* m_pUASheet;
136   CFX_MapPtrTemplate<CFDE_XMLNode*, CXFA_TextParseContext*>
137       m_mapXMLNodeToParseContext;
138 };
139 
140 class CXFA_LoaderContext {
141  public:
142   CXFA_LoaderContext();
143   ~CXFA_LoaderContext();
144 
145   FX_BOOL m_bSaveLineHeight;
146   FX_FLOAT m_fWidth;
147   FX_FLOAT m_fHeight;
148   FX_FLOAT m_fLastPos;
149   FX_FLOAT m_fStartLineOffset;
150   int32_t m_iChar;
151   int32_t m_iLines;
152   int32_t m_iTotalLines;
153   CFDE_XMLNode* m_pXMLNode;
154   CXFA_Node* m_pNode;
155   IFDE_CSSComputedStyle* m_pParentStyle;
156   CFX_ArrayTemplate<FX_FLOAT> m_lineHeights;
157   uint32_t m_dwFlags;
158   CFX_FloatArray m_BlocksHeight;
159 };
160 
161 class CXFA_LinkUserData : public IFX_Retainable, public CFX_Target {
162  public:
163   CXFA_LinkUserData(IFX_MemoryAllocator* pAllocator, FX_WCHAR* pszText);
164   ~CXFA_LinkUserData() override;
165 
166   // IFX_Retainable:
167   uint32_t Retain() override;
168   uint32_t Release() override;
169 
170   const FX_WCHAR* GetLinkURL();
171 
172  protected:
173   IFX_MemoryAllocator* m_pAllocator;
174   uint32_t m_dwRefCount;
175   CFX_WideString m_wsURLContent;
176 };
177 
178 class CXFA_TextUserData : public IFX_Retainable, public CFX_Target {
179  public:
180   CXFA_TextUserData(IFX_MemoryAllocator* pAllocator,
181                     IFDE_CSSComputedStyle* pStyle);
182   CXFA_TextUserData(IFX_MemoryAllocator* pAllocator,
183                     IFDE_CSSComputedStyle* pStyle,
184                     CXFA_LinkUserData* pLinkData);
185   ~CXFA_TextUserData() override;
186 
187   // IFX_Retainable:
188   uint32_t Retain() override;
189   uint32_t Release() override;
190 
191   IFDE_CSSComputedStyle* m_pStyle;
192   CXFA_LinkUserData* m_pLinkData;
193 
194  protected:
195   IFX_MemoryAllocator* m_pAllocator;
196   uint32_t m_dwRefCount;
197 };
198 
199 class XFA_TextPiece : public CFX_Target {
200  public:
201   XFA_TextPiece();
202   ~XFA_TextPiece() override;
203 
204   FX_WCHAR* pszText;
205   int32_t iChars;
206   int32_t* pWidths;
207   int32_t iHorScale;
208   int32_t iVerScale;
209   int32_t iBidiLevel;
210   int32_t iUnderline;
211   int32_t iPeriod;
212   int32_t iLineThrough;
213   CFGAS_GEFont* pFont;
214   FX_ARGB dwColor;
215   FX_FLOAT fFontSize;
216   CFX_RectF rtPiece;
217   CXFA_LinkUserData* pLinkData;
218 };
219 typedef CFX_ArrayTemplate<XFA_TextPiece*> CXFA_PieceArray;
220 
221 class CXFA_PieceLine : public CFX_Target {
222  public:
223   CXFA_PieceLine();
224   ~CXFA_PieceLine() override;
225 
226   CXFA_PieceArray m_textPieces;
227   CFX_Int32Array m_charCounts;
228 };
229 typedef CFX_ArrayTemplate<CXFA_PieceLine*> CXFA_PieceLineArray;
230 
231 struct XFA_TABSTOPS {
232   uint32_t dwAlign;
233   FX_FLOAT fTabstops;
234 };
235 
236 class CXFA_TextTabstopsContext {
237  public:
238   CXFA_TextTabstopsContext();
239   ~CXFA_TextTabstopsContext();
240 
241   void Append(uint32_t dwAlign, FX_FLOAT fTabstops);
242   void RemoveAll();
243   void Reset();
244 
245   CFX_ArrayTemplate<XFA_TABSTOPS> m_tabstops;
246   int32_t m_iTabCount;
247   int32_t m_iTabIndex;
248   FX_BOOL m_bTabstops;
249   FX_FLOAT m_fTabWidth;
250   FX_FLOAT m_fLeft;
251 };
252 
253 class CXFA_TextLayout {
254  public:
255   explicit CXFA_TextLayout(CXFA_TextProvider* pTextProvider);
256   ~CXFA_TextLayout();
257 
258   int32_t GetText(CFX_WideString& wsText);
259   FX_FLOAT GetLayoutHeight();
260   FX_FLOAT StartLayout(FX_FLOAT fWidth = -1);
261   FX_BOOL DoLayout(int32_t iBlockIndex,
262                    FX_FLOAT& fCalcHeight,
263                    FX_FLOAT fContentAreaHeight = -1,
264                    FX_FLOAT fTextHeight = -1);
265 
266   FX_BOOL CalcSize(const CFX_SizeF& minSize,
267                    const CFX_SizeF& maxSize,
268                    CFX_SizeF& defaultSize);
269   FX_BOOL Layout(const CFX_SizeF& size, FX_FLOAT* fHeight = nullptr);
270   void ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex);
271   FX_BOOL DrawString(CFX_RenderDevice* pFxDevice,
272                      const CFX_Matrix& tmDoc2Device,
273                      const CFX_RectF& rtClip,
274                      int32_t iBlock = 0);
IsLoaded()275   FX_BOOL IsLoaded() const { return m_pieceLines.GetSize() > 0; }
276   void Unload();
277   const CXFA_PieceLineArray* GetPieceLines();
278 
279   FX_BOOL m_bHasBlock;
280   CFX_Int32Array m_Blocks;
281 
282  private:
283   void GetTextDataNode();
284   CFDE_XMLNode* GetXMLContainerNode();
285   CFX_RTFBreak* CreateBreak(FX_BOOL bDefault);
286   void InitBreak(FX_FLOAT fLineWidth);
287   void InitBreak(IFDE_CSSComputedStyle* pStyle,
288                  FDE_CSSDISPLAY eDisplay,
289                  FX_FLOAT fLineWidth,
290                  CFDE_XMLNode* pXMLNode,
291                  IFDE_CSSComputedStyle* pParentStyle = nullptr);
292   FX_BOOL Loader(const CFX_SizeF& szText,
293                  FX_FLOAT& fLinePos,
294                  FX_BOOL bSavePieces = TRUE);
295   void LoadText(CXFA_Node* pNode,
296                 const CFX_SizeF& szText,
297                 FX_FLOAT& fLinePos,
298                 FX_BOOL bSavePieces);
299   FX_BOOL LoadRichText(CFDE_XMLNode* pXMLNode,
300                        const CFX_SizeF& szText,
301                        FX_FLOAT& fLinePos,
302                        IFDE_CSSComputedStyle* pParentStyle,
303                        FX_BOOL bSavePieces,
304                        CXFA_LinkUserData* pLinkData = nullptr,
305                        FX_BOOL bEndBreak = TRUE,
306                        FX_BOOL bIsOl = FALSE,
307                        int32_t iLiCount = 0);
308   FX_BOOL AppendChar(const CFX_WideString& wsText,
309                      FX_FLOAT& fLinePos,
310                      FX_FLOAT fSpaceAbove,
311                      FX_BOOL bSavePieces);
312   void AppendTextLine(uint32_t dwStatus,
313                       FX_FLOAT& fLinePos,
314                       FX_BOOL bSavePieces,
315                       FX_BOOL bEndBreak = FALSE);
316   void EndBreak(uint32_t dwStatus, FX_FLOAT& fLinePos, FX_BOOL bDefault);
317   FX_BOOL IsEnd(FX_BOOL bSavePieces);
318   void ProcessText(CFX_WideString& wsText);
319   void UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom);
320   void RenderString(CFDE_RenderDevice* pDevice,
321                     CFDE_Brush* pBrush,
322                     CXFA_PieceLine* pPieceLine,
323                     int32_t iPiece,
324                     FXTEXT_CHARPOS* pCharPos,
325                     const CFX_Matrix& tmDoc2Device);
326   void RenderPath(CFDE_RenderDevice* pDevice,
327                   CFDE_Pen* pPen,
328                   CXFA_PieceLine* pPieceLine,
329                   int32_t iPiece,
330                   FXTEXT_CHARPOS* pCharPos,
331                   const CFX_Matrix& tmDoc2Device);
332   int32_t GetDisplayPos(const XFA_TextPiece* pPiece,
333                         FXTEXT_CHARPOS* pCharPos,
334                         FX_BOOL bCharCode = FALSE);
335   FX_BOOL ToRun(const XFA_TextPiece* pPiece, FX_RTFTEXTOBJ& tr);
336   void DoTabstops(IFDE_CSSComputedStyle* pStyle, CXFA_PieceLine* pPieceLine);
337   FX_BOOL Layout(int32_t iBlock);
338   int32_t CountBlocks() const;
339 
340   CXFA_TextProvider* m_pTextProvider;
341   CXFA_Node* m_pTextDataNode;
342   FX_BOOL m_bRichText;
343   std::unique_ptr<IFX_MemoryAllocator> m_pAllocator;
344   std::unique_ptr<CFX_RTFBreak> m_pBreak;
345   std::unique_ptr<CXFA_LoaderContext> m_pLoader;
346   int32_t m_iLines;
347   FX_FLOAT m_fMaxWidth;
348   CXFA_TextParser m_textParser;
349   CXFA_PieceLineArray m_pieceLines;
350   std::unique_ptr<CXFA_TextTabstopsContext> m_pTabstopContext;
351   FX_BOOL m_bBlockContinue;
352 };
353 
354 #endif  // XFA_FXFA_APP_XFA_TEXTLAYOUT_H_
355