1 // Copyright 2017 The PDFium Authors 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_CXFA_TEXTLAYOUT_H_ 8 #define XFA_FXFA_CXFA_TEXTLAYOUT_H_ 9 10 #include <memory> 11 #include <vector> 12 13 #include "core/fxcrt/css/cfx_css.h" 14 #include "core/fxcrt/fx_coordinates.h" 15 #include "core/fxcrt/retain_ptr.h" 16 #include "core/fxcrt/unowned_ptr.h" 17 #include "core/fxcrt/widestring.h" 18 #include "core/fxge/dib/fx_dib.h" 19 #include "fxjs/gc/heap.h" 20 #include "v8/include/cppgc/garbage-collected.h" 21 #include "v8/include/cppgc/member.h" 22 #include "v8/include/cppgc/visitor.h" 23 #include "xfa/fgas/layout/cfgas_char.h" 24 #include "xfa/fgas/layout/cfgas_textpiece.h" 25 #include "xfa/fxfa/fxfa_basic.h" 26 27 class CFGAS_LinkUserData; 28 class CFGAS_RTFBreak; 29 class CFX_CSSComputedStyle; 30 class CFX_RenderDevice; 31 class CFX_XMLNode; 32 class CXFA_FFDoc; 33 class CXFA_Node; 34 class CXFA_TextParser; 35 class CXFA_TextProvider; 36 class CXFA_TextTabstopsContext; 37 class TextCharPos; 38 39 class CXFA_TextLayout final : public cppgc::GarbageCollected<CXFA_TextLayout> { 40 public: 41 CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; 42 ~CXFA_TextLayout(); 43 44 void Trace(cppgc::Visitor* visitor) const; 45 46 float GetLayoutHeight(); 47 float StartLayout(float fWidth); 48 float DoLayout(float fTextHeight); 49 float DoSplitLayout(size_t szBlockIndex, 50 float fCalcHeight, 51 float fTextHeight); 52 float Layout(const CFX_SizeF& size); 53 54 CFX_SizeF CalcSize(const CFX_SizeF& minSize, const CFX_SizeF& maxSize); 55 void ItemBlocks(const CFX_RectF& rtText, size_t szBlockIndex); 56 bool DrawString(CFX_RenderDevice* pFxDevice, 57 const CFX_Matrix& mtDoc2Device, 58 const CFX_RectF& rtClip, 59 size_t szBlockIndex); IsLoaded()60 bool IsLoaded() const { return !m_pieceLines.empty(); } 61 void Unload(); HasBlock()62 bool HasBlock() const { return m_bHasBlock; } ClearBlocks()63 void ClearBlocks() { m_Blocks.clear(); } ResetHasBlock()64 void ResetHasBlock() { m_bHasBlock = false; } 65 66 // Returns empty string when no link is present. 67 WideString GetLinkURLAtPoint(const CFX_PointF& point); 68 69 private: 70 class TextPiece : public CFGAS_TextPiece { 71 public: 72 TextPiece(); 73 ~TextPiece(); 74 75 int32_t iUnderline = 0; 76 int32_t iLineThrough = 0; 77 XFA_AttributeValue iPeriod = XFA_AttributeValue::All; 78 FX_ARGB dwColor = 0; 79 RetainPtr<CFGAS_LinkUserData> pLinkData; 80 }; 81 82 class PieceLine { 83 public: 84 PieceLine(); 85 ~PieceLine(); 86 87 std::vector<std::unique_ptr<TextPiece>> m_textPieces; 88 std::vector<size_t> m_charCounts; 89 }; 90 91 struct BlockData { 92 size_t szIndex; 93 size_t szLength; 94 }; 95 96 struct BlockHeight { 97 size_t szBlockIndex; 98 float fHeight; 99 }; 100 101 struct LoaderContext : public cppgc::GarbageCollected<LoaderContext> { 102 LoaderContext(); 103 ~LoaderContext(); 104 105 void Trace(cppgc::Visitor* visitor) const; 106 107 bool bSaveLineHeight = false; 108 bool bFilterSpace = false; 109 float fWidth = 0; 110 float fHeight = 0; 111 float fLastPos = 0; 112 float fStartLineOffset = 0; 113 size_t nCharIdx = 0; 114 // TODO(thestig): Make this size_t? 115 int32_t iTotalLines = -1; 116 UnownedPtr<const CFX_XMLNode> pXMLNode; 117 RetainPtr<CFX_CSSComputedStyle> pParentStyle; 118 cppgc::Member<CXFA_Node> pNode; 119 std::vector<float> lineHeights; 120 std::vector<BlockHeight> blockHeights; 121 }; 122 123 CXFA_TextLayout(CXFA_FFDoc* doc, CXFA_TextProvider* pTextProvider); 124 125 void GetTextDataNode(); 126 CFX_XMLNode* GetXMLContainerNode(); 127 std::unique_ptr<CFGAS_RTFBreak> CreateBreak(bool bDefault); 128 void InitBreak(float fLineWidth); 129 void InitBreak(CFX_CSSComputedStyle* pStyle, 130 CFX_CSSDisplay eDisplay, 131 float fLineWidth, 132 const CFX_XMLNode* pXMLNode, 133 CFX_CSSComputedStyle* pParentStyle); 134 void Loader(float textWidth, float* pLinePos, bool bSavePieces); 135 void LoadText(CXFA_Node* pNode, 136 float textWidth, 137 float* pLinePos, 138 bool bSavePieces); 139 bool LoadRichText(const CFX_XMLNode* pXMLNode, 140 float textWidth, 141 float* pLinePos, 142 RetainPtr<CFX_CSSComputedStyle> pParentStyle, 143 bool bSavePieces, 144 RetainPtr<CFGAS_LinkUserData> pLinkData, 145 bool bEndBreak, 146 bool bIsOl, 147 int32_t iLiCount); 148 bool AppendChar(const WideString& wsText, 149 float* pLinePos, 150 float fSpaceAbove, 151 bool bSavePieces); 152 void AppendTextLine(CFGAS_Char::BreakType dwStatus, 153 float* pLinePos, 154 bool bSavePieces, 155 bool bEndBreak); 156 void EndBreak(CFGAS_Char::BreakType dwStatus, float* pLinePos, bool bDefault); 157 bool IsEnd(bool bSavePieces); 158 void UpdateAlign(float fHeight, float fBottom); 159 void RenderString(CFX_RenderDevice* pDevice, 160 PieceLine* pPieceLine, 161 size_t szPiece, 162 std::vector<TextCharPos>* pCharPos, 163 const CFX_Matrix& mtDoc2Device); 164 void RenderPath(CFX_RenderDevice* pDevice, 165 const PieceLine* pPieceLine, 166 size_t szPiece, 167 std::vector<TextCharPos>* pCharPos, 168 const CFX_Matrix& mtDoc2Device); 169 size_t GetDisplayPos(const TextPiece* pPiece, 170 std::vector<TextCharPos>* pCharPos); 171 void DoTabstops(CFX_CSSComputedStyle* pStyle, PieceLine* pPieceLine); 172 bool LayoutInternal(size_t szBlockIndex); 173 size_t CountBlocks() const; 174 size_t GetNextIndexFromLastBlockData() const; 175 void UpdateLoaderHeight(float fTextHeight); 176 177 bool m_bHasBlock = false; 178 bool m_bRichText = false; 179 int32_t m_iLines = 0; 180 float m_fMaxWidth = 0; 181 std::vector<BlockData> m_Blocks; 182 cppgc::Member<CXFA_FFDoc> const m_pDoc; 183 cppgc::Member<CXFA_TextProvider> const m_pTextProvider; 184 cppgc::Member<CXFA_Node> m_pTextDataNode; 185 cppgc::Member<CXFA_TextParser> m_pTextParser; 186 cppgc::Member<LoaderContext> m_pLoader; 187 std::unique_ptr<CFGAS_RTFBreak> m_pBreak; 188 std::vector<std::unique_ptr<PieceLine>> m_pieceLines; 189 std::unique_ptr<CXFA_TextTabstopsContext> m_pTabstopContext; 190 }; 191 192 #endif // XFA_FXFA_CXFA_TEXTLAYOUT_H_ 193