| // 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/fx_string.h" | 
 | #include "core/fxcrt/retain_ptr.h" | 
 | #include "core/fxcrt/unowned_ptr.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; | 
 |     int32_t iChar = 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_ |