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