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