|  | // Copyright 2017 PDFium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 
|  |  | 
|  | #ifndef XFA_FXFA_CXFA_TEXTLAYOUT_H_ | 
|  | #define XFA_FXFA_CXFA_TEXTLAYOUT_H_ | 
|  |  | 
|  | #include <memory> | 
|  | #include <vector> | 
|  |  | 
|  | #include "core/fxcrt/css/cfx_css.h" | 
|  | #include "core/fxcrt/fx_coordinates.h" | 
|  | #include "core/fxcrt/retain_ptr.h" | 
|  | #include "core/fxcrt/unowned_ptr.h" | 
|  | #include "core/fxcrt/widestring.h" | 
|  | #include "core/fxge/dib/fx_dib.h" | 
|  | #include "fxjs/gc/heap.h" | 
|  | #include "v8/include/cppgc/garbage-collected.h" | 
|  | #include "v8/include/cppgc/member.h" | 
|  | #include "v8/include/cppgc/visitor.h" | 
|  | #include "xfa/fgas/layout/cfgas_char.h" | 
|  | #include "xfa/fgas/layout/cfgas_textpiece.h" | 
|  | #include "xfa/fxfa/fxfa_basic.h" | 
|  |  | 
|  | class CFGAS_LinkUserData; | 
|  | class CFGAS_RTFBreak; | 
|  | class CFX_CSSComputedStyle; | 
|  | class CFX_RenderDevice; | 
|  | class CFX_XMLNode; | 
|  | class CXFA_FFDoc; | 
|  | class CXFA_Node; | 
|  | class CXFA_TextParser; | 
|  | class CXFA_TextProvider; | 
|  | class CXFA_TextTabstopsContext; | 
|  | class TextCharPos; | 
|  |  | 
|  | class CXFA_TextLayout final : public cppgc::GarbageCollected<CXFA_TextLayout> { | 
|  | public: | 
|  | CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; | 
|  | ~CXFA_TextLayout(); | 
|  |  | 
|  | void Trace(cppgc::Visitor* visitor) const; | 
|  |  | 
|  | float GetLayoutHeight(); | 
|  | float StartLayout(float fWidth); | 
|  | float DoLayout(float fTextHeight); | 
|  | float DoSplitLayout(size_t szBlockIndex, | 
|  | float fCalcHeight, | 
|  | float fTextHeight); | 
|  | float Layout(const CFX_SizeF& size); | 
|  |  | 
|  | CFX_SizeF CalcSize(const CFX_SizeF& minSize, const CFX_SizeF& maxSize); | 
|  | void ItemBlocks(const CFX_RectF& rtText, size_t szBlockIndex); | 
|  | bool DrawString(CFX_RenderDevice* pFxDevice, | 
|  | const CFX_Matrix& mtDoc2Device, | 
|  | const CFX_RectF& rtClip, | 
|  | size_t szBlockIndex); | 
|  | bool IsLoaded() const { return !m_pieceLines.empty(); } | 
|  | void Unload(); | 
|  | bool HasBlock() const { return m_bHasBlock; } | 
|  | void ClearBlocks() { m_Blocks.clear(); } | 
|  | void ResetHasBlock() { m_bHasBlock = false; } | 
|  |  | 
|  | // Returns empty string when no link is present. | 
|  | WideString GetLinkURLAtPoint(const CFX_PointF& point); | 
|  |  | 
|  | private: | 
|  | class TextPiece : public CFGAS_TextPiece { | 
|  | public: | 
|  | TextPiece(); | 
|  | ~TextPiece(); | 
|  |  | 
|  | int32_t iUnderline = 0; | 
|  | int32_t iLineThrough = 0; | 
|  | XFA_AttributeValue iPeriod = XFA_AttributeValue::All; | 
|  | FX_ARGB dwColor = 0; | 
|  | RetainPtr<CFGAS_LinkUserData> pLinkData; | 
|  | }; | 
|  |  | 
|  | class PieceLine { | 
|  | public: | 
|  | PieceLine(); | 
|  | ~PieceLine(); | 
|  |  | 
|  | std::vector<std::unique_ptr<TextPiece>> m_textPieces; | 
|  | std::vector<size_t> m_charCounts; | 
|  | }; | 
|  |  | 
|  | struct BlockData { | 
|  | size_t szIndex; | 
|  | size_t szLength; | 
|  | }; | 
|  |  | 
|  | struct BlockHeight { | 
|  | size_t szBlockIndex; | 
|  | float fHeight; | 
|  | }; | 
|  |  | 
|  | struct LoaderContext { | 
|  | LoaderContext(); | 
|  | ~LoaderContext(); | 
|  |  | 
|  | void Trace(cppgc::Visitor* visitor) const; | 
|  |  | 
|  | bool bSaveLineHeight = false; | 
|  | bool bFilterSpace = false; | 
|  | float fWidth = 0; | 
|  | float fHeight = 0; | 
|  | float fLastPos = 0; | 
|  | float fStartLineOffset = 0; | 
|  | size_t nCharIdx = 0; | 
|  | // TODO(thestig): Make this size_t? | 
|  | int32_t iTotalLines = -1; | 
|  | UnownedPtr<const CFX_XMLNode> pXMLNode; | 
|  | RetainPtr<CFX_CSSComputedStyle> pParentStyle; | 
|  | cppgc::Member<CXFA_Node> pNode; | 
|  | std::vector<float> lineHeights; | 
|  | std::vector<BlockHeight> blockHeights; | 
|  | }; | 
|  |  | 
|  | CXFA_TextLayout(CXFA_FFDoc* doc, CXFA_TextProvider* pTextProvider); | 
|  |  | 
|  | void GetTextDataNode(); | 
|  | CFX_XMLNode* GetXMLContainerNode(); | 
|  | std::unique_ptr<CFGAS_RTFBreak> CreateBreak(bool bDefault); | 
|  | void InitBreak(float fLineWidth); | 
|  | void InitBreak(CFX_CSSComputedStyle* pStyle, | 
|  | CFX_CSSDisplay eDisplay, | 
|  | float fLineWidth, | 
|  | const CFX_XMLNode* pXMLNode, | 
|  | CFX_CSSComputedStyle* pParentStyle); | 
|  | void Loader(float textWidth, float* pLinePos, bool bSavePieces); | 
|  | void LoadText(CXFA_Node* pNode, | 
|  | float textWidth, | 
|  | float* pLinePos, | 
|  | bool bSavePieces); | 
|  | bool LoadRichText(const CFX_XMLNode* pXMLNode, | 
|  | float textWidth, | 
|  | float* pLinePos, | 
|  | const RetainPtr<CFX_CSSComputedStyle>& pParentStyle, | 
|  | bool bSavePieces, | 
|  | RetainPtr<CFGAS_LinkUserData> pLinkData, | 
|  | bool bEndBreak, | 
|  | bool bIsOl, | 
|  | int32_t iLiCount); | 
|  | bool AppendChar(const WideString& wsText, | 
|  | float* pLinePos, | 
|  | float fSpaceAbove, | 
|  | bool bSavePieces); | 
|  | void AppendTextLine(CFGAS_Char::BreakType dwStatus, | 
|  | float* pLinePos, | 
|  | bool bSavePieces, | 
|  | bool bEndBreak); | 
|  | void EndBreak(CFGAS_Char::BreakType dwStatus, float* pLinePos, bool bDefault); | 
|  | bool IsEnd(bool bSavePieces); | 
|  | void UpdateAlign(float fHeight, float fBottom); | 
|  | void RenderString(CFX_RenderDevice* pDevice, | 
|  | PieceLine* pPieceLine, | 
|  | size_t szPiece, | 
|  | std::vector<TextCharPos>* pCharPos, | 
|  | const CFX_Matrix& mtDoc2Device); | 
|  | void RenderPath(CFX_RenderDevice* pDevice, | 
|  | const PieceLine* pPieceLine, | 
|  | size_t szPiece, | 
|  | std::vector<TextCharPos>* pCharPos, | 
|  | const CFX_Matrix& mtDoc2Device); | 
|  | size_t GetDisplayPos(const TextPiece* pPiece, | 
|  | std::vector<TextCharPos>* pCharPos); | 
|  | void DoTabstops(CFX_CSSComputedStyle* pStyle, PieceLine* pPieceLine); | 
|  | bool LayoutInternal(size_t szBlockIndex); | 
|  | size_t CountBlocks() const; | 
|  | size_t GetNextIndexFromLastBlockData() const; | 
|  | void UpdateLoaderHeight(float fTextHeight); | 
|  |  | 
|  | bool m_bHasBlock = false; | 
|  | bool m_bRichText = false; | 
|  | int32_t m_iLines = 0; | 
|  | float m_fMaxWidth = 0; | 
|  | std::vector<BlockData> m_Blocks; | 
|  | cppgc::Member<CXFA_FFDoc> const m_pDoc; | 
|  | cppgc::Member<CXFA_TextProvider> const m_pTextProvider; | 
|  | cppgc::Member<CXFA_Node> m_pTextDataNode; | 
|  | cppgc::Member<CXFA_TextParser> m_pTextParser; | 
|  | std::unique_ptr<CFGAS_RTFBreak> m_pBreak; | 
|  | std::unique_ptr<LoaderContext> m_pLoader; | 
|  | std::vector<std::unique_ptr<PieceLine>> m_pieceLines; | 
|  | std::unique_ptr<CXFA_TextTabstopsContext> m_pTabstopContext; | 
|  | }; | 
|  |  | 
|  | #endif  // XFA_FXFA_CXFA_TEXTLAYOUT_H_ |