xref: /aosp_15_r20/external/pdfium/xfa/fxfa/cxfa_textlayout.h (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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