summaryrefslogtreecommitdiff
path: root/xfa/src/fxfa/src/app/xfa_textlayout.h
blob: a47189cb3fcf5c81b93b237a75db201897876145 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
// Copyright 2014 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 _FXFA_TEXTLAYOUT_H
#define _FXFA_TEXTLAYOUT_H
#define XFA_LOADERCNTXTFLG_FILTERSPACE			0x001
class CXFA_TextTabstopsContext;
class IXFA_TextProvider
{
public:
    virtual CXFA_Node*			GetTextNode(FX_BOOL &bRichText) = 0;
    virtual CXFA_Para			GetParaNode() = 0;
    virtual CXFA_Font			GetFontNode() = 0;
    virtual FX_BOOL				IsCheckButtonAndAutoWidth() = 0;
    virtual	CXFA_FFDoc*			GetDocNode() = 0;
    virtual FX_BOOL				GetEmbbedObj(FX_BOOL bURI, FX_BOOL bRaw, const CFX_WideString &wsAttr, CFX_WideString &wsValue) = 0;
};
class CXFA_CSSTagProvider : public IFDE_CSSTagProvider
{
public:
    CXFA_CSSTagProvider ()
        : m_bTagAviliable(FALSE),
          m_bContent(FALSE)
    {}
    virtual ~CXFA_CSSTagProvider();
    virtual CFX_WideStringC		GetTagName()
    {
        return m_wsTagName;
    }
    virtual FX_POSITION			GetFirstAttribute()
    {
        return m_Attributes.GetStartPosition();
    }
    virtual void				GetNextAttribute(FX_POSITION &pos, CFX_WideStringC &wsAttr, CFX_WideStringC &wsValue);
    void						SetTagNameObj(const CFX_WideString &wsName)
    {
        m_wsTagName = wsName;
    }
    void						SetAttribute(const CFX_WideString &wsAttr, const CFX_WideString &wsValue);
    FX_BOOL					m_bTagAviliable;
    FX_BOOL					m_bContent;
protected:
    CFX_WideString			m_wsTagName;
    CFX_MapPtrToPtr			m_Attributes;
};
class CXFA_TextParseContext : public CFX_Target
{
public:
    CXFA_TextParseContext() : m_ppMatchedDecls(NULL), m_dwMatchedDecls(0), m_eDisplay(FDE_CSSDISPLAY_None), m_pParentStyle(NULL) {}
    ~CXFA_TextParseContext()
    {
        if (m_ppMatchedDecls != NULL) {
            FDE_Free(m_ppMatchedDecls);
        }
    }
    void						SetDisplay(FDE_CSSDISPLAY eDisplay)
    {
        m_eDisplay = eDisplay;
    }
    FDE_CSSDISPLAY				GetDisplay() const
    {
        return m_eDisplay;
    }
    void						SetDecls(const IFDE_CSSDeclaration **ppDeclArray, FX_INT32 iDeclCount);
    const IFDE_CSSDeclaration**	GetDecls()
    {
        return (const IFDE_CSSDeclaration**)m_ppMatchedDecls;
    }
    FX_DWORD					CountDecls() const
    {
        return m_dwMatchedDecls;
    }
    IFDE_CSSComputedStyle *		m_pParentStyle;
protected:
    IFDE_CSSDeclaration		**m_ppMatchedDecls;
    FX_DWORD				m_dwMatchedDecls : 28;
    FDE_CSSDISPLAY			m_eDisplay		 : 4;
};
class CXFA_TextParser
{
public:
    CXFA_TextParser() : m_pAllocator(NULL), m_pSelector(NULL), m_pUASheet(NULL) {}
    virtual ~CXFA_TextParser();
    void						Reset();
    void						DoParse(IFDE_XMLNode *pXMLContainer, IXFA_TextProvider *pTextProvider);
    IFDE_CSSComputedStyle*		CreateRootStyle(IXFA_TextProvider *pTextProvider);
    IFDE_CSSComputedStyle*		ComputeStyle(IFDE_XMLNode *pXMLNode, IFDE_CSSComputedStyle *pParentStyle);
    FX_BOOL						IsParsed() const
    {
        return m_pAllocator != NULL;
    }

    FX_INT32					GetVAlgin(IXFA_TextProvider *pTextProvider) const;
    FX_FLOAT					GetTabInterval(IFDE_CSSComputedStyle *pStyle) const;
    FX_INT32					CountTabs(IFDE_CSSComputedStyle *pStyle) const;
    FX_BOOL						IsSpaceRun(IFDE_CSSComputedStyle *pStyle) const;
    FX_BOOL						GetTabstops(IFDE_CSSComputedStyle *pStyle, CXFA_TextTabstopsContext	*pTabstopContext);
    IFX_Font*					GetFont(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const;
    FX_FLOAT					GetFontSize(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const;
    FX_INT32					GetHorScale(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle, IFDE_XMLNode *pXMLNode) const;
    FX_INT32					GetVerScale(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const;
    void						GetUnderline(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle, FX_INT32 &iUnderline, FX_INT32 &iPeriod) const;
    void						GetLinethrough(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle, FX_INT32 &iLinethrough) const;
    FX_ARGB						GetColor(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const;
    FX_FLOAT					GetBaseline(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const;
    FX_FLOAT					GetLineHeight(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle, FX_BOOL bFirst, FX_FLOAT fVerScale) const;
    FX_BOOL						GetEmbbedObj(IXFA_TextProvider *pTextProvider, IFDE_XMLNode *pXMLNode, CFX_WideString &wsValue);
    CXFA_TextParseContext*		GetParseContextFromMap(IFDE_XMLNode *pXMLNode);
private:
    void						InitCSSData(IXFA_TextProvider *pTextProvider);
    void						ParseRichText(IFDE_XMLNode *pXMLNode, IFDE_CSSComputedStyle *pParentStyle);
    void						ParseTagInfo(IFDE_XMLNode *pXMLNode, CXFA_CSSTagProvider &tagProvider);
    IFDE_CSSStyleSheet*			LoadDefaultSheetStyle();
    IFDE_CSSComputedStyle*		CreateStyle(IFDE_CSSComputedStyle *pParentStyle);
    IFX_MEMAllocator		*m_pAllocator;
    IFDE_CSSStyleSelector	*m_pSelector;
    IFDE_CSSStyleSheet		*m_pUASheet;
    CFX_MapPtrTemplate<IFDE_XMLNode*, CXFA_TextParseContext*>	m_mapXMLNodeToParseContext;
};
class CXFA_LoaderContext
{
public:
    CXFA_LoaderContext() : m_bSaveLineHeight(FALSE)
        , m_fWidth(0)
        , m_fHeight(0)
        , m_fLastPos(0)
        , m_fStartLineOffset(0)
        , m_iChar(0)
        , m_iTotalLines(-1)
        , m_pXMLNode(NULL)
        , m_pNode(NULL)
        , m_pParentStyle(NULL)
        , m_dwFlags(0)
    {}
    FX_BOOL				m_bSaveLineHeight;
    FX_FLOAT			m_fWidth;
    FX_FLOAT			m_fHeight;
    FX_FLOAT			m_fLastPos;
    FX_FLOAT			m_fStartLineOffset;
    FX_INT32			m_iChar;
    FX_INT32			m_iLines;
    FX_INT32			m_iTotalLines;
    IFDE_XMLNode		*m_pXMLNode;
    CXFA_Node			*m_pNode;
    IFDE_CSSComputedStyle		*m_pParentStyle;
    CFX_ArrayTemplate<FX_FLOAT> m_lineHeights;
    FX_DWORD			m_dwFlags;
    CFX_FloatArray		m_BlocksHeight;
};
class CXFA_LinkUserData : public IFX_Unknown, public CFX_Target
{
public:
    CXFA_LinkUserData(IFX_MEMAllocator *pAllocator, FX_LPWSTR pszText)
        : m_pAllocator(pAllocator)
        , m_dwRefCount(1)
    {
        m_pszURLContent = pszText;
    }
    ~CXFA_LinkUserData() { }
    virtual FX_DWORD	Release()
    {
        FX_DWORD dwRefCount = --m_dwRefCount;
        if (dwRefCount <= 0) {
            FDE_DeleteWith(CXFA_LinkUserData, m_pAllocator, this);
        }
        return dwRefCount;
    }
    virtual FX_DWORD	AddRef()
    {
        return ++m_dwRefCount;
    }
public:
    FX_LPCWSTR GetLinkURL()
    {
        return m_pszURLContent;
    };
protected:
    IFX_MEMAllocator		*m_pAllocator;
    FX_DWORD				m_dwRefCount;
    CFX_WideString			m_pszURLContent;
};
class CXFA_TextUserData : public IFX_Unknown, public CFX_Target
{
public:
    CXFA_TextUserData(IFX_MEMAllocator *pAllocator, IFDE_CSSComputedStyle *pStyle)
        : m_pStyle(pStyle)
        , m_pAllocator(pAllocator)
        , m_dwRefCount(0)
        , m_pLinkData(NULL)
    {
        FXSYS_assert(m_pAllocator != NULL);
        if (m_pStyle != NULL) {
            m_pStyle->AddRef();
        }
    }
    CXFA_TextUserData(IFX_MEMAllocator *pAllocator, IFDE_CSSComputedStyle *pStyle, CXFA_LinkUserData* pLinkData)
        : m_pStyle(pStyle)
        , m_pAllocator(pAllocator)
        , m_dwRefCount(0)
        , m_pLinkData(pLinkData)
    {
        FXSYS_assert(m_pAllocator != NULL);
        if (m_pStyle != NULL) {
            m_pStyle->AddRef();
        }
    }
    ~CXFA_TextUserData()
    {
        if (m_pStyle != NULL) {
            m_pStyle->Release();
        }
        if (m_pLinkData != NULL) {
            m_pLinkData->Release();
        }
    }
    virtual FX_DWORD	Release()
    {
        FX_DWORD dwRefCount = --m_dwRefCount;
        if (dwRefCount == 0) {
            FDE_DeleteWith(CXFA_TextUserData, m_pAllocator, this);
        }
        return dwRefCount;
    }
    virtual FX_DWORD	AddRef()
    {
        return ++m_dwRefCount;
    }

    IFDE_CSSComputedStyle	*m_pStyle;
    CXFA_LinkUserData		*m_pLinkData;
protected:
    IFX_MEMAllocator			*m_pAllocator;
    FX_DWORD				m_dwRefCount;
};
typedef struct _XFA_TEXTPIECE : public CFX_Target {
    FX_LPWSTR		pszText;
    FX_INT32		iChars;
    FX_INT32		*pWidths;
    FX_INT32		iHorScale;
    FX_INT32		iVerScale;
    FX_INT32		iBidiLevel;
    FX_INT32		iUnderline;
    FX_INT32		iPeriod;
    FX_INT32		iLineThrough;
    IFX_Font		*pFont;
    FX_ARGB			dwColor;
    FX_FLOAT		fFontSize;
    CFX_RectF		rtPiece;
    CXFA_LinkUserData*	pLinkData;

    _XFA_TEXTPIECE() : pszText(NULL), pFont(NULL), pLinkData(NULL)
    {
        pszText = NULL;
    }
    ~_XFA_TEXTPIECE()
    {
        pszText = NULL;
        if (NULL != pLinkData) {
            pLinkData->Release();
            pLinkData = NULL;
        }
    }
} XFA_TEXTPIECE, * XFA_LPTEXTPIECE;
typedef XFA_TEXTPIECE const * XFA_LPCTEXTPIECE;
typedef CFX_ArrayTemplate<XFA_LPTEXTPIECE>	CXFA_PieceArray;
class CXFA_PieceLine : public CFX_Target
{
public:
    CXFA_PieceLine() {}
    CXFA_PieceArray		m_textPieces;
    CFX_Int32Array		m_charCounts;
};
typedef CFX_ArrayTemplate<CXFA_PieceLine*>	CXFA_PieceLineArray;
struct XFA_TABSTOPS {
    FX_DWORD dwAlign;
    FX_FLOAT fTabstops;
};
class CXFA_TextTabstopsContext
{
public:
    CXFA_TextTabstopsContext() : m_iTabCount(0), m_iTabIndex(-1), m_bTabstops(FALSE), m_fTabWidth(0), m_fLeft(0) {}
    void Append(FX_DWORD dwAlign, FX_FLOAT fTabstops)
    {
        FX_INT32 i = 0;
        for (i = 0; i < m_iTabCount; i++) {
            XFA_TABSTOPS *pTabstop = m_tabstops.GetDataPtr(i);
            if (fTabstops < pTabstop->fTabstops) {
                break;
            }
        }
        m_tabstops.InsertSpaceAt(i, 1);
        XFA_TABSTOPS tabstop;
        tabstop.dwAlign		= dwAlign;
        tabstop.fTabstops	= fTabstops;
        m_tabstops.SetAt(i, tabstop);
        m_iTabCount++;
    }
    void RemoveAll()
    {
        m_tabstops.RemoveAll();
        m_iTabCount = 0;
    }
    void Reset()
    {
        m_iTabIndex = -1;
        m_bTabstops = FALSE;
        m_fTabWidth = 0;
        m_fLeft = 0;
    }
    CFX_ArrayTemplate<XFA_TABSTOPS>		m_tabstops;
    FX_INT32		m_iTabCount;
    FX_INT32		m_iTabIndex;
    FX_BOOL			m_bTabstops;
    FX_FLOAT		m_fTabWidth;
    FX_FLOAT		m_fLeft;
};
class CXFA_TextLayout
{
public:
    CXFA_TextLayout(IXFA_TextProvider *pTextProvider);
    virtual ~CXFA_TextLayout();
    FX_INT32			GetText(CFX_WideString &wsText);
    FX_FLOAT			GetLayoutHeight();
    FX_FLOAT			StartLayout(FX_FLOAT fWidth = -1);
    FX_BOOL				DoLayout(FX_INT32 iBlockIndex, FX_FLOAT &fCalcHeight, FX_FLOAT fContentAreaHeight = -1, FX_FLOAT fTextHeight = -1);

    FX_BOOL				CalcSize(const CFX_SizeF &minSize, const CFX_SizeF &maxSize, CFX_SizeF &defaultSize);
    FX_BOOL				Layout(const CFX_SizeF &size, FX_FLOAT* fHeight = NULL);
    void				ItemBlocks(const CFX_RectF& rtText, FX_INT32 iBlockIndex);
    FX_BOOL				DrawString(CFX_RenderDevice *pFxDevice, const CFX_Matrix &tmDoc2Device, const CFX_RectF &rtClip, FX_INT32 iBlock = 0);

    FX_BOOL				IsLoaded() const
    {
        return m_pieceLines.GetSize() > 0;
    }
    void				Unload();
    const CXFA_PieceLineArray*	GetPieceLines();
private:
    void				GetTextDataNode();
    IFDE_XMLNode*		GetXMLContainerNode();
    IFX_RTFBreak*		CreateBreak(FX_BOOL bDefault);
    void				InitBreak(FX_FLOAT fLineWidth);
    void				InitBreak(IFDE_CSSComputedStyle *pStyle, FDE_CSSDISPLAY eDisplay, FX_FLOAT fLineWidth, IFDE_XMLNode *pXMLNode, IFDE_CSSComputedStyle *pParentStyle = NULL);
    FX_BOOL				Loader(const CFX_SizeF &szText, FX_FLOAT &fLinePos, FX_BOOL bSavePieces = TRUE);

    void				LoadText(CXFA_Node *pNode, const CFX_SizeF &szText, FX_FLOAT &fLinePos, FX_BOOL bSavePieces);
    FX_BOOL				LoadRichText(IFDE_XMLNode *pXMLNode, const CFX_SizeF &szText, FX_FLOAT &fLinePos, IFDE_CSSComputedStyle *pParentStyle, FX_BOOL bSavePieces, CXFA_LinkUserData* pLinkData = NULL, FX_BOOL bEndBreak = TRUE, FX_BOOL bIsOl = FALSE, FX_INT32 iLiCount = 0);

    FX_BOOL				AppendChar(const CFX_WideString &wsText, FX_FLOAT &fLinePos,  FX_FLOAT fSpaceAbove, FX_BOOL bSavePieces);

    void				AppendTextLine(FX_DWORD dwStatus, FX_FLOAT &fLinePos, FX_BOOL bSavePieces, FX_BOOL bEndBreak = FALSE);
    void				EndBreak(FX_DWORD dwStatus, FX_FLOAT &fLinePos, FX_BOOL bDefault);
    FX_BOOL				IsEnd(FX_BOOL bSavePieces);

    void				ProcessText(CFX_WideString &wsText);
    void				UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom);

    void				RenderString(IFDE_RenderDevice *pDevice, IFDE_SolidBrush *pBrush, CXFA_PieceLine *pPieceLine,
                                     FX_INT32 iPiece, FXTEXT_CHARPOS *pCharPos, const CFX_Matrix &tmDoc2Device);
    void				RenderPath(IFDE_RenderDevice *pDevice, IFDE_Pen *pPen, CXFA_PieceLine *pPieceLine, FX_INT32 iPiece,
                                   FXTEXT_CHARPOS *pCharPos, const CFX_Matrix &tmDoc2Device);

    FX_INT32			GetDisplayPos(XFA_LPCTEXTPIECE pPiece, FXTEXT_CHARPOS *pCharPos, FX_BOOL bCharCode = FALSE);
    FX_BOOL				ToRun(XFA_LPCTEXTPIECE pPiece, FX_RTFTEXTOBJ &tr);

    void				DoTabstops(IFDE_CSSComputedStyle *pStyle, CXFA_PieceLine *pPieceLine);
    FX_BOOL				Layout(FX_INT32 iBlock);
    FX_INT32			CountBlocks() const;
    IXFA_TextProvider	*m_pTextProvider;
    CXFA_Node			*m_pTextDataNode;
    FX_BOOL				m_bRichText;
    IFX_MEMAllocator	*m_pAllocator;
    IFX_RTFBreak		*m_pBreak;
    FX_DWORD			m_dwTextData;

    CXFA_LoaderContext	*m_pLoader;
    FX_INT32			m_iLines;
    FX_FLOAT			m_fMaxWidth;

    CXFA_TextParser		m_textParser;
    CXFA_PieceLineArray	m_pieceLines;
    CXFA_TextTabstopsContext	*m_pTabstopContext;
    FX_BOOL				m_bBlockContinue;
public:
    FX_BOOL				m_bHasBlock;
    CFX_Int32Array		m_Blocks;
};
#endif