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 _FXFA_TEXTLAYOUT_H
8 #define _FXFA_TEXTLAYOUT_H
9 #define XFA_LOADERCNTXTFLG_FILTERSPACE 0x001
10 class CXFA_TextTabstopsContext;
11 class IXFA_TextProvider {
12  public:
~IXFA_TextProvider()13   virtual ~IXFA_TextProvider() {}
14   virtual CXFA_Node* GetTextNode(FX_BOOL& bRichText) = 0;
15   virtual CXFA_Para GetParaNode() = 0;
16   virtual CXFA_Font GetFontNode() = 0;
17   virtual FX_BOOL IsCheckButtonAndAutoWidth() = 0;
18   virtual CXFA_FFDoc* GetDocNode() = 0;
19   virtual FX_BOOL GetEmbbedObj(FX_BOOL bURI,
20                                FX_BOOL bRaw,
21                                const CFX_WideString& wsAttr,
22                                CFX_WideString& wsValue) = 0;
23 };
24 class CXFA_CSSTagProvider : public IFDE_CSSTagProvider {
25  public:
CXFA_CSSTagProvider()26   CXFA_CSSTagProvider() : m_bTagAviliable(FALSE), m_bContent(FALSE) {}
27   virtual ~CXFA_CSSTagProvider();
GetTagName()28   virtual CFX_WideStringC GetTagName() { return m_wsTagName; }
GetFirstAttribute()29   virtual FX_POSITION GetFirstAttribute() {
30     return m_Attributes.GetStartPosition();
31   }
32   virtual void GetNextAttribute(FX_POSITION& pos,
33                                 CFX_WideStringC& wsAttr,
34                                 CFX_WideStringC& wsValue);
SetTagNameObj(const CFX_WideString & wsName)35   void SetTagNameObj(const CFX_WideString& wsName) { m_wsTagName = wsName; }
36   void SetAttribute(const CFX_WideString& wsAttr,
37                     const CFX_WideString& wsValue);
38   FX_BOOL m_bTagAviliable;
39   FX_BOOL m_bContent;
40 
41  protected:
42   CFX_WideString m_wsTagName;
43   CFX_MapPtrToPtr m_Attributes;
44 };
45 class CXFA_TextParseContext : public CFX_Target {
46  public:
CXFA_TextParseContext()47   CXFA_TextParseContext()
48       : m_pParentStyle(nullptr),
49         m_ppMatchedDecls(nullptr),
50         m_dwMatchedDecls(0),
51         m_eDisplay(FDE_CSSDISPLAY_None) {}
~CXFA_TextParseContext()52   ~CXFA_TextParseContext() {
53     if (m_pParentStyle)
54       m_pParentStyle->Release();
55     FX_Free(m_ppMatchedDecls);
56   }
SetDisplay(FDE_CSSDISPLAY eDisplay)57   void SetDisplay(FDE_CSSDISPLAY eDisplay) { m_eDisplay = eDisplay; }
GetDisplay()58   FDE_CSSDISPLAY GetDisplay() const { return m_eDisplay; }
59   void SetDecls(const IFDE_CSSDeclaration** ppDeclArray, int32_t iDeclCount);
GetDecls()60   const IFDE_CSSDeclaration** GetDecls() {
61     return (const IFDE_CSSDeclaration**)m_ppMatchedDecls;
62   }
CountDecls()63   FX_DWORD CountDecls() const { return m_dwMatchedDecls; }
64   IFDE_CSSComputedStyle* m_pParentStyle;
65 
66  protected:
67   IFDE_CSSDeclaration** m_ppMatchedDecls;
68   FX_DWORD m_dwMatchedDecls : 28;
69   FDE_CSSDISPLAY m_eDisplay : 4;
70 };
71 class CXFA_TextParser {
72  public:
CXFA_TextParser()73   CXFA_TextParser() : m_pAllocator(NULL), m_pSelector(NULL), m_pUASheet(NULL) {}
74   virtual ~CXFA_TextParser();
75   void Reset();
76   void DoParse(IFDE_XMLNode* pXMLContainer, IXFA_TextProvider* pTextProvider);
77   IFDE_CSSComputedStyle* CreateRootStyle(IXFA_TextProvider* pTextProvider);
78   IFDE_CSSComputedStyle* ComputeStyle(IFDE_XMLNode* pXMLNode,
79                                       IFDE_CSSComputedStyle* pParentStyle);
IsParsed()80   FX_BOOL IsParsed() const { return m_pAllocator != NULL; }
81 
82   int32_t GetVAlgin(IXFA_TextProvider* pTextProvider) const;
83   FX_FLOAT GetTabInterval(IFDE_CSSComputedStyle* pStyle) const;
84   int32_t CountTabs(IFDE_CSSComputedStyle* pStyle) const;
85   FX_BOOL IsSpaceRun(IFDE_CSSComputedStyle* pStyle) const;
86   FX_BOOL GetTabstops(IFDE_CSSComputedStyle* pStyle,
87                       CXFA_TextTabstopsContext* pTabstopContext);
88   IFX_Font* GetFont(IXFA_TextProvider* pTextProvider,
89                     IFDE_CSSComputedStyle* pStyle) const;
90   FX_FLOAT GetFontSize(IXFA_TextProvider* pTextProvider,
91                        IFDE_CSSComputedStyle* pStyle) const;
92   int32_t GetHorScale(IXFA_TextProvider* pTextProvider,
93                       IFDE_CSSComputedStyle* pStyle,
94                       IFDE_XMLNode* pXMLNode) const;
95   int32_t GetVerScale(IXFA_TextProvider* pTextProvider,
96                       IFDE_CSSComputedStyle* pStyle) const;
97   void GetUnderline(IXFA_TextProvider* pTextProvider,
98                     IFDE_CSSComputedStyle* pStyle,
99                     int32_t& iUnderline,
100                     int32_t& iPeriod) const;
101   void GetLinethrough(IXFA_TextProvider* pTextProvider,
102                       IFDE_CSSComputedStyle* pStyle,
103                       int32_t& iLinethrough) const;
104   FX_ARGB GetColor(IXFA_TextProvider* pTextProvider,
105                    IFDE_CSSComputedStyle* pStyle) const;
106   FX_FLOAT GetBaseline(IXFA_TextProvider* pTextProvider,
107                        IFDE_CSSComputedStyle* pStyle) const;
108   FX_FLOAT GetLineHeight(IXFA_TextProvider* pTextProvider,
109                          IFDE_CSSComputedStyle* pStyle,
110                          FX_BOOL bFirst,
111                          FX_FLOAT fVerScale) const;
112   FX_BOOL GetEmbbedObj(IXFA_TextProvider* pTextProvider,
113                        IFDE_XMLNode* pXMLNode,
114                        CFX_WideString& wsValue);
115   CXFA_TextParseContext* GetParseContextFromMap(IFDE_XMLNode* pXMLNode);
116 
117  private:
118   void InitCSSData(IXFA_TextProvider* pTextProvider);
119   void ParseRichText(IFDE_XMLNode* pXMLNode,
120                      IFDE_CSSComputedStyle* pParentStyle);
121   void ParseTagInfo(IFDE_XMLNode* pXMLNode, CXFA_CSSTagProvider& tagProvider);
122   IFDE_CSSStyleSheet* LoadDefaultSheetStyle();
123   IFDE_CSSComputedStyle* CreateStyle(IFDE_CSSComputedStyle* pParentStyle);
124   IFX_MEMAllocator* m_pAllocator;
125   IFDE_CSSStyleSelector* m_pSelector;
126   IFDE_CSSStyleSheet* m_pUASheet;
127   CFX_MapPtrTemplate<IFDE_XMLNode*, CXFA_TextParseContext*>
128       m_mapXMLNodeToParseContext;
129 };
130 class CXFA_LoaderContext {
131  public:
CXFA_LoaderContext()132   CXFA_LoaderContext()
133       : m_bSaveLineHeight(FALSE),
134         m_fWidth(0),
135         m_fHeight(0),
136         m_fLastPos(0),
137         m_fStartLineOffset(0),
138         m_iChar(0),
139         m_iTotalLines(-1),
140         m_pXMLNode(NULL),
141         m_pNode(NULL),
142         m_pParentStyle(NULL),
143         m_dwFlags(0) {}
144   FX_BOOL m_bSaveLineHeight;
145   FX_FLOAT m_fWidth;
146   FX_FLOAT m_fHeight;
147   FX_FLOAT m_fLastPos;
148   FX_FLOAT m_fStartLineOffset;
149   int32_t m_iChar;
150   int32_t m_iLines;
151   int32_t m_iTotalLines;
152   IFDE_XMLNode* m_pXMLNode;
153   CXFA_Node* m_pNode;
154   IFDE_CSSComputedStyle* m_pParentStyle;
155   CFX_ArrayTemplate<FX_FLOAT> m_lineHeights;
156   FX_DWORD m_dwFlags;
157   CFX_FloatArray m_BlocksHeight;
158 };
159 class CXFA_LinkUserData : public IFX_Unknown, public CFX_Target {
160  public:
CXFA_LinkUserData(IFX_MEMAllocator * pAllocator,FX_WCHAR * pszText)161   CXFA_LinkUserData(IFX_MEMAllocator* pAllocator, FX_WCHAR* pszText)
162       : m_pAllocator(pAllocator), m_dwRefCount(1) {
163     m_pszURLContent = pszText;
164   }
~CXFA_LinkUserData()165   ~CXFA_LinkUserData() {}
Release()166   virtual FX_DWORD Release() {
167     FX_DWORD dwRefCount = --m_dwRefCount;
168     if (dwRefCount <= 0) {
169       FDE_DeleteWith(CXFA_LinkUserData, m_pAllocator, this);
170     }
171     return dwRefCount;
172   }
AddRef()173   virtual FX_DWORD AddRef() { return ++m_dwRefCount; }
174 
175  public:
GetLinkURL()176   const FX_WCHAR* GetLinkURL() { return m_pszURLContent; };
177 
178  protected:
179   IFX_MEMAllocator* m_pAllocator;
180   FX_DWORD m_dwRefCount;
181   CFX_WideString m_pszURLContent;
182 };
183 class CXFA_TextUserData : public IFX_Unknown, public CFX_Target {
184  public:
CXFA_TextUserData(IFX_MEMAllocator * pAllocator,IFDE_CSSComputedStyle * pStyle)185   CXFA_TextUserData(IFX_MEMAllocator* pAllocator, IFDE_CSSComputedStyle* pStyle)
186       : m_pStyle(pStyle),
187         m_pLinkData(nullptr),
188         m_pAllocator(pAllocator),
189         m_dwRefCount(0) {
190     FXSYS_assert(m_pAllocator);
191     if (m_pStyle)
192       m_pStyle->AddRef();
193   }
CXFA_TextUserData(IFX_MEMAllocator * pAllocator,IFDE_CSSComputedStyle * pStyle,CXFA_LinkUserData * pLinkData)194   CXFA_TextUserData(IFX_MEMAllocator* pAllocator,
195                     IFDE_CSSComputedStyle* pStyle,
196                     CXFA_LinkUserData* pLinkData)
197       : m_pStyle(pStyle),
198         m_pLinkData(pLinkData),
199         m_pAllocator(pAllocator),
200         m_dwRefCount(0) {
201     FXSYS_assert(m_pAllocator);
202     if (m_pStyle)
203       m_pStyle->AddRef();
204   }
~CXFA_TextUserData()205   ~CXFA_TextUserData() {
206     if (m_pStyle)
207       m_pStyle->Release();
208     if (m_pLinkData)
209       m_pLinkData->Release();
210   }
Release()211   virtual FX_DWORD Release() {
212     FX_DWORD dwRefCount = --m_dwRefCount;
213     if (dwRefCount == 0) {
214       FDE_DeleteWith(CXFA_TextUserData, m_pAllocator, this);
215     }
216     return dwRefCount;
217   }
AddRef()218   virtual FX_DWORD AddRef() { return ++m_dwRefCount; }
219 
220   IFDE_CSSComputedStyle* m_pStyle;
221   CXFA_LinkUserData* m_pLinkData;
222 
223  protected:
224   IFX_MEMAllocator* m_pAllocator;
225   FX_DWORD m_dwRefCount;
226 };
227 typedef struct _XFA_TEXTPIECE : public CFX_Target {
228   FX_WCHAR* pszText;
229   int32_t iChars;
230   int32_t* pWidths;
231   int32_t iHorScale;
232   int32_t iVerScale;
233   int32_t iBidiLevel;
234   int32_t iUnderline;
235   int32_t iPeriod;
236   int32_t iLineThrough;
237   IFX_Font* pFont;
238   FX_ARGB dwColor;
239   FX_FLOAT fFontSize;
240   CFX_RectF rtPiece;
241   CXFA_LinkUserData* pLinkData;
242 
_XFA_TEXTPIECE_XFA_TEXTPIECE243   _XFA_TEXTPIECE() : pszText(NULL), pFont(NULL), pLinkData(NULL) {
244     pszText = NULL;
245   }
~_XFA_TEXTPIECE_XFA_TEXTPIECE246   ~_XFA_TEXTPIECE() {
247     pszText = NULL;
248     if (NULL != pLinkData) {
249       pLinkData->Release();
250       pLinkData = NULL;
251     }
252   }
253 } XFA_TEXTPIECE, *XFA_LPTEXTPIECE;
254 typedef XFA_TEXTPIECE const* XFA_LPCTEXTPIECE;
255 typedef CFX_ArrayTemplate<XFA_LPTEXTPIECE> CXFA_PieceArray;
256 class CXFA_PieceLine : public CFX_Target {
257  public:
CXFA_PieceLine()258   CXFA_PieceLine() {}
259   CXFA_PieceArray m_textPieces;
260   CFX_Int32Array m_charCounts;
261 };
262 typedef CFX_ArrayTemplate<CXFA_PieceLine*> CXFA_PieceLineArray;
263 struct XFA_TABSTOPS {
264   FX_DWORD dwAlign;
265   FX_FLOAT fTabstops;
266 };
267 class CXFA_TextTabstopsContext {
268  public:
CXFA_TextTabstopsContext()269   CXFA_TextTabstopsContext()
270       : m_iTabCount(0),
271         m_iTabIndex(-1),
272         m_bTabstops(FALSE),
273         m_fTabWidth(0),
274         m_fLeft(0) {}
Append(FX_DWORD dwAlign,FX_FLOAT fTabstops)275   void Append(FX_DWORD dwAlign, FX_FLOAT fTabstops) {
276     int32_t i = 0;
277     for (i = 0; i < m_iTabCount; i++) {
278       XFA_TABSTOPS* pTabstop = m_tabstops.GetDataPtr(i);
279       if (fTabstops < pTabstop->fTabstops) {
280         break;
281       }
282     }
283     m_tabstops.InsertSpaceAt(i, 1);
284     XFA_TABSTOPS tabstop;
285     tabstop.dwAlign = dwAlign;
286     tabstop.fTabstops = fTabstops;
287     m_tabstops.SetAt(i, tabstop);
288     m_iTabCount++;
289   }
RemoveAll()290   void RemoveAll() {
291     m_tabstops.RemoveAll();
292     m_iTabCount = 0;
293   }
Reset()294   void Reset() {
295     m_iTabIndex = -1;
296     m_bTabstops = FALSE;
297     m_fTabWidth = 0;
298     m_fLeft = 0;
299   }
300   CFX_ArrayTemplate<XFA_TABSTOPS> m_tabstops;
301   int32_t m_iTabCount;
302   int32_t m_iTabIndex;
303   FX_BOOL m_bTabstops;
304   FX_FLOAT m_fTabWidth;
305   FX_FLOAT m_fLeft;
306 };
307 class CXFA_TextLayout {
308  public:
309   CXFA_TextLayout(IXFA_TextProvider* pTextProvider);
310   virtual ~CXFA_TextLayout();
311   int32_t GetText(CFX_WideString& wsText);
312   FX_FLOAT GetLayoutHeight();
313   FX_FLOAT StartLayout(FX_FLOAT fWidth = -1);
314   FX_BOOL DoLayout(int32_t iBlockIndex,
315                    FX_FLOAT& fCalcHeight,
316                    FX_FLOAT fContentAreaHeight = -1,
317                    FX_FLOAT fTextHeight = -1);
318 
319   FX_BOOL CalcSize(const CFX_SizeF& minSize,
320                    const CFX_SizeF& maxSize,
321                    CFX_SizeF& defaultSize);
322   FX_BOOL Layout(const CFX_SizeF& size, FX_FLOAT* fHeight = NULL);
323   void ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex);
324   FX_BOOL DrawString(CFX_RenderDevice* pFxDevice,
325                      const CFX_Matrix& tmDoc2Device,
326                      const CFX_RectF& rtClip,
327                      int32_t iBlock = 0);
IsLoaded()328   FX_BOOL IsLoaded() const { return m_pieceLines.GetSize() > 0; }
329   void Unload();
330   const CXFA_PieceLineArray* GetPieceLines();
331 
332   FX_BOOL m_bHasBlock;
333   CFX_Int32Array m_Blocks;
334 
335  private:
336   void GetTextDataNode();
337   IFDE_XMLNode* GetXMLContainerNode();
338   IFX_RTFBreak* CreateBreak(FX_BOOL bDefault);
339   void InitBreak(FX_FLOAT fLineWidth);
340   void InitBreak(IFDE_CSSComputedStyle* pStyle,
341                  FDE_CSSDISPLAY eDisplay,
342                  FX_FLOAT fLineWidth,
343                  IFDE_XMLNode* pXMLNode,
344                  IFDE_CSSComputedStyle* pParentStyle = NULL);
345   FX_BOOL Loader(const CFX_SizeF& szText,
346                  FX_FLOAT& fLinePos,
347                  FX_BOOL bSavePieces = TRUE);
348   void LoadText(CXFA_Node* pNode,
349                 const CFX_SizeF& szText,
350                 FX_FLOAT& fLinePos,
351                 FX_BOOL bSavePieces);
352   FX_BOOL LoadRichText(IFDE_XMLNode* pXMLNode,
353                        const CFX_SizeF& szText,
354                        FX_FLOAT& fLinePos,
355                        IFDE_CSSComputedStyle* pParentStyle,
356                        FX_BOOL bSavePieces,
357                        CXFA_LinkUserData* pLinkData = NULL,
358                        FX_BOOL bEndBreak = TRUE,
359                        FX_BOOL bIsOl = FALSE,
360                        int32_t iLiCount = 0);
361   FX_BOOL AppendChar(const CFX_WideString& wsText,
362                      FX_FLOAT& fLinePos,
363                      FX_FLOAT fSpaceAbove,
364                      FX_BOOL bSavePieces);
365   void AppendTextLine(FX_DWORD dwStatus,
366                       FX_FLOAT& fLinePos,
367                       FX_BOOL bSavePieces,
368                       FX_BOOL bEndBreak = FALSE);
369   void EndBreak(FX_DWORD dwStatus, FX_FLOAT& fLinePos, FX_BOOL bDefault);
370   FX_BOOL IsEnd(FX_BOOL bSavePieces);
371   void ProcessText(CFX_WideString& wsText);
372   void UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom);
373   void RenderString(IFDE_RenderDevice* pDevice,
374                     IFDE_SolidBrush* pBrush,
375                     CXFA_PieceLine* pPieceLine,
376                     int32_t iPiece,
377                     FXTEXT_CHARPOS* pCharPos,
378                     const CFX_Matrix& tmDoc2Device);
379   void RenderPath(IFDE_RenderDevice* pDevice,
380                   IFDE_Pen* pPen,
381                   CXFA_PieceLine* pPieceLine,
382                   int32_t iPiece,
383                   FXTEXT_CHARPOS* pCharPos,
384                   const CFX_Matrix& tmDoc2Device);
385   int32_t GetDisplayPos(XFA_LPCTEXTPIECE pPiece,
386                         FXTEXT_CHARPOS* pCharPos,
387                         FX_BOOL bCharCode = FALSE);
388   FX_BOOL ToRun(XFA_LPCTEXTPIECE pPiece, FX_RTFTEXTOBJ& tr);
389   void DoTabstops(IFDE_CSSComputedStyle* pStyle, CXFA_PieceLine* pPieceLine);
390   FX_BOOL Layout(int32_t iBlock);
391   int32_t CountBlocks() const;
392 
393   IXFA_TextProvider* m_pTextProvider;
394   CXFA_Node* m_pTextDataNode;
395   FX_BOOL m_bRichText;
396   IFX_MEMAllocator* m_pAllocator;
397   IFX_RTFBreak* m_pBreak;
398   CXFA_LoaderContext* m_pLoader;
399   int32_t m_iLines;
400   FX_FLOAT m_fMaxWidth;
401   CXFA_TextParser m_textParser;
402   CXFA_PieceLineArray m_pieceLines;
403   CXFA_TextTabstopsContext* m_pTabstopContext;
404   FX_BOOL m_bBlockContinue;
405 };
406 #endif
407