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