diff options
Diffstat (limited to 'xfa/fxfa/app/xfa_textlayout.h')
-rw-r--r-- | xfa/fxfa/app/xfa_textlayout.h | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/xfa/fxfa/app/xfa_textlayout.h b/xfa/fxfa/app/xfa_textlayout.h new file mode 100644 index 0000000000..9cc1e29f3b --- /dev/null +++ b/xfa/fxfa/app/xfa_textlayout.h @@ -0,0 +1,425 @@ +// 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 XFA_FXFA_APP_XFA_TEXTLAYOUT_H_ +#define XFA_FXFA_APP_XFA_TEXTLAYOUT_H_ + +#include "xfa/fde/css/fde_css.h" +#include "xfa/fde/fde_brush.h" +#include "xfa/fde/fde_renderdevice.h" +#include "xfa/fgas/layout/fgas_rtfbreak.h" +#include "xfa/fxfa/app/xfa_ffdoc.h" +#include "xfa/fxfa/parser/xfa_object.h" + +#define XFA_LOADERCNTXTFLG_FILTERSPACE 0x001 + +class CXFA_Para; +class CXFA_Font; +class CXFA_TextTabstopsContext; + +class IXFA_TextProvider { + public: + virtual ~IXFA_TextProvider() {} + 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_pParentStyle(nullptr), + m_ppMatchedDecls(nullptr), + m_dwMatchedDecls(0), + m_eDisplay(FDE_CSSDISPLAY_None) {} + ~CXFA_TextParseContext() { + if (m_pParentStyle) + m_pParentStyle->Release(); + FX_Free(m_ppMatchedDecls); + } + void SetDisplay(FDE_CSSDISPLAY eDisplay) { m_eDisplay = eDisplay; } + FDE_CSSDISPLAY GetDisplay() const { return m_eDisplay; } + void SetDecls(const IFDE_CSSDeclaration** ppDeclArray, int32_t 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; + FDE_CSSDISPLAY m_eDisplay; +}; + +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; } + + int32_t GetVAlgin(IXFA_TextProvider* pTextProvider) const; + FX_FLOAT GetTabInterval(IFDE_CSSComputedStyle* pStyle) const; + int32_t 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; + int32_t GetHorScale(IXFA_TextProvider* pTextProvider, + IFDE_CSSComputedStyle* pStyle, + IFDE_XMLNode* pXMLNode) const; + int32_t GetVerScale(IXFA_TextProvider* pTextProvider, + IFDE_CSSComputedStyle* pStyle) const; + void GetUnderline(IXFA_TextProvider* pTextProvider, + IFDE_CSSComputedStyle* pStyle, + int32_t& iUnderline, + int32_t& iPeriod) const; + void GetLinethrough(IXFA_TextProvider* pTextProvider, + IFDE_CSSComputedStyle* pStyle, + int32_t& 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; + int32_t m_iChar; + int32_t m_iLines; + int32_t 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_WCHAR* pszText) + : m_pAllocator(pAllocator), m_dwRefCount(1) { + m_pszURLContent = pszText; + } + ~CXFA_LinkUserData() {} + virtual FX_DWORD Release() { + FX_DWORD dwRefCount = --m_dwRefCount; + if (dwRefCount <= 0) { + FXTARGET_DeleteWith(CXFA_LinkUserData, m_pAllocator, this); + } + return dwRefCount; + } + virtual FX_DWORD AddRef() { return ++m_dwRefCount; } + + public: + const FX_WCHAR* 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_pLinkData(nullptr), + m_pAllocator(pAllocator), + m_dwRefCount(0) { + FXSYS_assert(m_pAllocator); + if (m_pStyle) + m_pStyle->AddRef(); + } + CXFA_TextUserData(IFX_MEMAllocator* pAllocator, + IFDE_CSSComputedStyle* pStyle, + CXFA_LinkUserData* pLinkData) + : m_pStyle(pStyle), + m_pLinkData(pLinkData), + m_pAllocator(pAllocator), + m_dwRefCount(0) { + FXSYS_assert(m_pAllocator); + if (m_pStyle) + m_pStyle->AddRef(); + } + ~CXFA_TextUserData() { + if (m_pStyle) + m_pStyle->Release(); + if (m_pLinkData) + m_pLinkData->Release(); + } + virtual FX_DWORD Release() { + FX_DWORD dwRefCount = --m_dwRefCount; + if (dwRefCount == 0) { + FXTARGET_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; +}; + +class XFA_TextPiece : public CFX_Target { + public: + XFA_TextPiece() : pszText(nullptr), pFont(nullptr), pLinkData(nullptr) {} + ~XFA_TextPiece() { + if (pLinkData) + pLinkData->Release(); + } + + FX_WCHAR* pszText; + int32_t iChars; + int32_t* pWidths; + int32_t iHorScale; + int32_t iVerScale; + int32_t iBidiLevel; + int32_t iUnderline; + int32_t iPeriod; + int32_t iLineThrough; + IFX_Font* pFont; + FX_ARGB dwColor; + FX_FLOAT fFontSize; + CFX_RectF rtPiece; + CXFA_LinkUserData* pLinkData; +}; +typedef CFX_ArrayTemplate<XFA_TextPiece*> 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) { + int32_t 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; + int32_t m_iTabCount; + int32_t 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(); + int32_t GetText(CFX_WideString& wsText); + FX_FLOAT GetLayoutHeight(); + FX_FLOAT StartLayout(FX_FLOAT fWidth = -1); + FX_BOOL DoLayout(int32_t 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, int32_t iBlockIndex); + FX_BOOL DrawString(CFX_RenderDevice* pFxDevice, + const CFX_Matrix& tmDoc2Device, + const CFX_RectF& rtClip, + int32_t iBlock = 0); + FX_BOOL IsLoaded() const { return m_pieceLines.GetSize() > 0; } + void Unload(); + const CXFA_PieceLineArray* GetPieceLines(); + + FX_BOOL m_bHasBlock; + CFX_Int32Array m_Blocks; + + 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, + int32_t 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, + int32_t iPiece, + FXTEXT_CHARPOS* pCharPos, + const CFX_Matrix& tmDoc2Device); + void RenderPath(IFDE_RenderDevice* pDevice, + IFDE_Pen* pPen, + CXFA_PieceLine* pPieceLine, + int32_t iPiece, + FXTEXT_CHARPOS* pCharPos, + const CFX_Matrix& tmDoc2Device); + int32_t GetDisplayPos(const XFA_TextPiece* pPiece, + FXTEXT_CHARPOS* pCharPos, + FX_BOOL bCharCode = FALSE); + FX_BOOL ToRun(const XFA_TextPiece* pPiece, FX_RTFTEXTOBJ& tr); + void DoTabstops(IFDE_CSSComputedStyle* pStyle, CXFA_PieceLine* pPieceLine); + FX_BOOL Layout(int32_t iBlock); + int32_t CountBlocks() const; + + IXFA_TextProvider* m_pTextProvider; + CXFA_Node* m_pTextDataNode; + FX_BOOL m_bRichText; + IFX_MEMAllocator* m_pAllocator; + IFX_RTFBreak* m_pBreak; + CXFA_LoaderContext* m_pLoader; + int32_t m_iLines; + FX_FLOAT m_fMaxWidth; + CXFA_TextParser m_textParser; + CXFA_PieceLineArray m_pieceLines; + CXFA_TextTabstopsContext* m_pTabstopContext; + FX_BOOL m_bBlockContinue; +}; + +#endif // XFA_FXFA_APP_XFA_TEXTLAYOUT_H_ |