Home | History | Annotate | Download | only in app
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #ifndef _FXFA_TEXTLAYOUT_H
      8 #define _FXFA_TEXTLAYOUT_H
      9 #define XFA_LOADERCNTXTFLG_FILTERSPACE 0x001
     10 class CXFA_TextTabstopsContext;
     11 class IXFA_TextProvider {
     12  public:
     13   virtual ~IXFA_TextProvider() {}
     14   virtual CXFA_Node* GetTextNode(FX_BOOL& bRichText) = 0;
     15   virtual CXFA_Para GetParaNode() = 0;
     16   virtual CXFA_Font GetFontNode() = 0;
     17   virtual FX_BOOL IsCheckButtonAndAutoWidth() = 0;
     18   virtual CXFA_FFDoc* GetDocNode() = 0;
     19   virtual FX_BOOL GetEmbbedObj(FX_BOOL bURI,
     20                                FX_BOOL bRaw,
     21                                const CFX_WideString& wsAttr,
     22                                CFX_WideString& wsValue) = 0;
     23 };
     24 class CXFA_CSSTagProvider : public IFDE_CSSTagProvider {
     25  public:
     26   CXFA_CSSTagProvider() : m_bTagAviliable(FALSE), m_bContent(FALSE) {}
     27   virtual ~CXFA_CSSTagProvider();
     28   virtual CFX_WideStringC GetTagName() { return m_wsTagName; }
     29   virtual FX_POSITION GetFirstAttribute() {
     30     return m_Attributes.GetStartPosition();
     31   }
     32   virtual void GetNextAttribute(FX_POSITION& pos,
     33                                 CFX_WideStringC& wsAttr,
     34                                 CFX_WideStringC& wsValue);
     35   void SetTagNameObj(const CFX_WideString& wsName) { m_wsTagName = wsName; }
     36   void SetAttribute(const CFX_WideString& wsAttr,
     37                     const CFX_WideString& wsValue);
     38   FX_BOOL m_bTagAviliable;
     39   FX_BOOL m_bContent;
     40 
     41  protected:
     42   CFX_WideString m_wsTagName;
     43   CFX_MapPtrToPtr m_Attributes;
     44 };
     45 class CXFA_TextParseContext : public CFX_Target {
     46  public:
     47   CXFA_TextParseContext()
     48       : m_pParentStyle(nullptr),
     49         m_ppMatchedDecls(nullptr),
     50         m_dwMatchedDecls(0),
     51         m_eDisplay(FDE_CSSDISPLAY_None) {}
     52   ~CXFA_TextParseContext() {
     53     if (m_pParentStyle)
     54       m_pParentStyle->Release();
     55     FX_Free(m_ppMatchedDecls);
     56   }
     57   void SetDisplay(FDE_CSSDISPLAY eDisplay) { m_eDisplay = eDisplay; }
     58   FDE_CSSDISPLAY GetDisplay() const { return m_eDisplay; }
     59   void SetDecls(const IFDE_CSSDeclaration** ppDeclArray, int32_t iDeclCount);
     60   const IFDE_CSSDeclaration** GetDecls() {
     61     return (const IFDE_CSSDeclaration**)m_ppMatchedDecls;
     62   }
     63   FX_DWORD CountDecls() const { return m_dwMatchedDecls; }
     64   IFDE_CSSComputedStyle* m_pParentStyle;
     65 
     66  protected:
     67   IFDE_CSSDeclaration** m_ppMatchedDecls;
     68   FX_DWORD m_dwMatchedDecls : 28;
     69   FDE_CSSDISPLAY m_eDisplay : 4;
     70 };
     71 class CXFA_TextParser {
     72  public:
     73   CXFA_TextParser() : m_pAllocator(NULL), m_pSelector(NULL), m_pUASheet(NULL) {}
     74   virtual ~CXFA_TextParser();
     75   void Reset();
     76   void DoParse(IFDE_XMLNode* pXMLContainer, IXFA_TextProvider* pTextProvider);
     77   IFDE_CSSComputedStyle* CreateRootStyle(IXFA_TextProvider* pTextProvider);
     78   IFDE_CSSComputedStyle* ComputeStyle(IFDE_XMLNode* pXMLNode,
     79                                       IFDE_CSSComputedStyle* pParentStyle);
     80   FX_BOOL IsParsed() const { return m_pAllocator != NULL; }
     81 
     82   int32_t GetVAlgin(IXFA_TextProvider* pTextProvider) const;
     83   FX_FLOAT GetTabInterval(IFDE_CSSComputedStyle* pStyle) const;
     84   int32_t CountTabs(IFDE_CSSComputedStyle* pStyle) const;
     85   FX_BOOL IsSpaceRun(IFDE_CSSComputedStyle* pStyle) const;
     86   FX_BOOL GetTabstops(IFDE_CSSComputedStyle* pStyle,
     87                       CXFA_TextTabstopsContext* pTabstopContext);
     88   IFX_Font* GetFont(IXFA_TextProvider* pTextProvider,
     89                     IFDE_CSSComputedStyle* pStyle) const;
     90   FX_FLOAT GetFontSize(IXFA_TextProvider* pTextProvider,
     91                        IFDE_CSSComputedStyle* pStyle) const;
     92   int32_t GetHorScale(IXFA_TextProvider* pTextProvider,
     93                       IFDE_CSSComputedStyle* pStyle,
     94                       IFDE_XMLNode* pXMLNode) const;
     95   int32_t GetVerScale(IXFA_TextProvider* pTextProvider,
     96                       IFDE_CSSComputedStyle* pStyle) const;
     97   void GetUnderline(IXFA_TextProvider* pTextProvider,
     98                     IFDE_CSSComputedStyle* pStyle,
     99                     int32_t& iUnderline,
    100                     int32_t& iPeriod) const;
    101   void GetLinethrough(IXFA_TextProvider* pTextProvider,
    102                       IFDE_CSSComputedStyle* pStyle,
    103                       int32_t& iLinethrough) const;
    104   FX_ARGB GetColor(IXFA_TextProvider* pTextProvider,
    105                    IFDE_CSSComputedStyle* pStyle) const;
    106   FX_FLOAT GetBaseline(IXFA_TextProvider* pTextProvider,
    107                        IFDE_CSSComputedStyle* pStyle) const;
    108   FX_FLOAT GetLineHeight(IXFA_TextProvider* pTextProvider,
    109                          IFDE_CSSComputedStyle* pStyle,
    110                          FX_BOOL bFirst,
    111                          FX_FLOAT fVerScale) const;
    112   FX_BOOL GetEmbbedObj(IXFA_TextProvider* pTextProvider,
    113                        IFDE_XMLNode* pXMLNode,
    114                        CFX_WideString& wsValue);
    115   CXFA_TextParseContext* GetParseContextFromMap(IFDE_XMLNode* pXMLNode);
    116 
    117  private:
    118   void InitCSSData(IXFA_TextProvider* pTextProvider);
    119   void ParseRichText(IFDE_XMLNode* pXMLNode,
    120                      IFDE_CSSComputedStyle* pParentStyle);
    121   void ParseTagInfo(IFDE_XMLNode* pXMLNode, CXFA_CSSTagProvider& tagProvider);
    122   IFDE_CSSStyleSheet* LoadDefaultSheetStyle();
    123   IFDE_CSSComputedStyle* CreateStyle(IFDE_CSSComputedStyle* pParentStyle);
    124   IFX_MEMAllocator* m_pAllocator;
    125   IFDE_CSSStyleSelector* m_pSelector;
    126   IFDE_CSSStyleSheet* m_pUASheet;
    127   CFX_MapPtrTemplate<IFDE_XMLNode*, CXFA_TextParseContext*>
    128       m_mapXMLNodeToParseContext;
    129 };
    130 class CXFA_LoaderContext {
    131  public:
    132   CXFA_LoaderContext()
    133       : m_bSaveLineHeight(FALSE),
    134         m_fWidth(0),
    135         m_fHeight(0),
    136         m_fLastPos(0),
    137         m_fStartLineOffset(0),
    138         m_iChar(0),
    139         m_iTotalLines(-1),
    140         m_pXMLNode(NULL),
    141         m_pNode(NULL),
    142         m_pParentStyle(NULL),
    143         m_dwFlags(0) {}
    144   FX_BOOL m_bSaveLineHeight;
    145   FX_FLOAT m_fWidth;
    146   FX_FLOAT m_fHeight;
    147   FX_FLOAT m_fLastPos;
    148   FX_FLOAT m_fStartLineOffset;
    149   int32_t m_iChar;
    150   int32_t m_iLines;
    151   int32_t m_iTotalLines;
    152   IFDE_XMLNode* m_pXMLNode;
    153   CXFA_Node* m_pNode;
    154   IFDE_CSSComputedStyle* m_pParentStyle;
    155   CFX_ArrayTemplate<FX_FLOAT> m_lineHeights;
    156   FX_DWORD m_dwFlags;
    157   CFX_FloatArray m_BlocksHeight;
    158 };
    159 class CXFA_LinkUserData : public IFX_Unknown, public CFX_Target {
    160  public:
    161   CXFA_LinkUserData(IFX_MEMAllocator* pAllocator, FX_WCHAR* pszText)
    162       : m_pAllocator(pAllocator), m_dwRefCount(1) {
    163     m_pszURLContent = pszText;
    164   }
    165   ~CXFA_LinkUserData() {}
    166   virtual FX_DWORD Release() {
    167     FX_DWORD dwRefCount = --m_dwRefCount;
    168     if (dwRefCount <= 0) {
    169       FDE_DeleteWith(CXFA_LinkUserData, m_pAllocator, this);
    170     }
    171     return dwRefCount;
    172   }
    173   virtual FX_DWORD AddRef() { return ++m_dwRefCount; }
    174 
    175  public:
    176   const FX_WCHAR* GetLinkURL() { return m_pszURLContent; };
    177 
    178  protected:
    179   IFX_MEMAllocator* m_pAllocator;
    180   FX_DWORD m_dwRefCount;
    181   CFX_WideString m_pszURLContent;
    182 };
    183 class CXFA_TextUserData : public IFX_Unknown, public CFX_Target {
    184  public:
    185   CXFA_TextUserData(IFX_MEMAllocator* pAllocator, IFDE_CSSComputedStyle* pStyle)
    186       : m_pStyle(pStyle),
    187         m_pLinkData(nullptr),
    188         m_pAllocator(pAllocator),
    189         m_dwRefCount(0) {
    190     FXSYS_assert(m_pAllocator);
    191     if (m_pStyle)
    192       m_pStyle->AddRef();
    193   }
    194   CXFA_TextUserData(IFX_MEMAllocator* pAllocator,
    195                     IFDE_CSSComputedStyle* pStyle,
    196                     CXFA_LinkUserData* pLinkData)
    197       : m_pStyle(pStyle),
    198         m_pLinkData(pLinkData),
    199         m_pAllocator(pAllocator),
    200         m_dwRefCount(0) {
    201     FXSYS_assert(m_pAllocator);
    202     if (m_pStyle)
    203       m_pStyle->AddRef();
    204   }
    205   ~CXFA_TextUserData() {
    206     if (m_pStyle)
    207       m_pStyle->Release();
    208     if (m_pLinkData)
    209       m_pLinkData->Release();
    210   }
    211   virtual FX_DWORD Release() {
    212     FX_DWORD dwRefCount = --m_dwRefCount;
    213     if (dwRefCount == 0) {
    214       FDE_DeleteWith(CXFA_TextUserData, m_pAllocator, this);
    215     }
    216     return dwRefCount;
    217   }
    218   virtual FX_DWORD AddRef() { return ++m_dwRefCount; }
    219 
    220   IFDE_CSSComputedStyle* m_pStyle;
    221   CXFA_LinkUserData* m_pLinkData;
    222 
    223  protected:
    224   IFX_MEMAllocator* m_pAllocator;
    225   FX_DWORD m_dwRefCount;
    226 };
    227 typedef struct _XFA_TEXTPIECE : public CFX_Target {
    228   FX_WCHAR* pszText;
    229   int32_t iChars;
    230   int32_t* pWidths;
    231   int32_t iHorScale;
    232   int32_t iVerScale;
    233   int32_t iBidiLevel;
    234   int32_t iUnderline;
    235   int32_t iPeriod;
    236   int32_t iLineThrough;
    237   IFX_Font* pFont;
    238   FX_ARGB dwColor;
    239   FX_FLOAT fFontSize;
    240   CFX_RectF rtPiece;
    241   CXFA_LinkUserData* pLinkData;
    242 
    243   _XFA_TEXTPIECE() : pszText(NULL), pFont(NULL), pLinkData(NULL) {
    244     pszText = NULL;
    245   }
    246   ~_XFA_TEXTPIECE() {
    247     pszText = NULL;
    248     if (NULL != pLinkData) {
    249       pLinkData->Release();
    250       pLinkData = NULL;
    251     }
    252   }
    253 } XFA_TEXTPIECE, *XFA_LPTEXTPIECE;
    254 typedef XFA_TEXTPIECE const* XFA_LPCTEXTPIECE;
    255 typedef CFX_ArrayTemplate<XFA_LPTEXTPIECE> CXFA_PieceArray;
    256 class CXFA_PieceLine : public CFX_Target {
    257  public:
    258   CXFA_PieceLine() {}
    259   CXFA_PieceArray m_textPieces;
    260   CFX_Int32Array m_charCounts;
    261 };
    262 typedef CFX_ArrayTemplate<CXFA_PieceLine*> CXFA_PieceLineArray;
    263 struct XFA_TABSTOPS {
    264   FX_DWORD dwAlign;
    265   FX_FLOAT fTabstops;
    266 };
    267 class CXFA_TextTabstopsContext {
    268  public:
    269   CXFA_TextTabstopsContext()
    270       : m_iTabCount(0),
    271         m_iTabIndex(-1),
    272         m_bTabstops(FALSE),
    273         m_fTabWidth(0),
    274         m_fLeft(0) {}
    275   void Append(FX_DWORD dwAlign, FX_FLOAT fTabstops) {
    276     int32_t i = 0;
    277     for (i = 0; i < m_iTabCount; i++) {
    278       XFA_TABSTOPS* pTabstop = m_tabstops.GetDataPtr(i);
    279       if (fTabstops < pTabstop->fTabstops) {
    280         break;
    281       }
    282     }
    283     m_tabstops.InsertSpaceAt(i, 1);
    284     XFA_TABSTOPS tabstop;
    285     tabstop.dwAlign = dwAlign;
    286     tabstop.fTabstops = fTabstops;
    287     m_tabstops.SetAt(i, tabstop);
    288     m_iTabCount++;
    289   }
    290   void RemoveAll() {
    291     m_tabstops.RemoveAll();
    292     m_iTabCount = 0;
    293   }
    294   void Reset() {
    295     m_iTabIndex = -1;
    296     m_bTabstops = FALSE;
    297     m_fTabWidth = 0;
    298     m_fLeft = 0;
    299   }
    300   CFX_ArrayTemplate<XFA_TABSTOPS> m_tabstops;
    301   int32_t m_iTabCount;
    302   int32_t m_iTabIndex;
    303   FX_BOOL m_bTabstops;
    304   FX_FLOAT m_fTabWidth;
    305   FX_FLOAT m_fLeft;
    306 };
    307 class CXFA_TextLayout {
    308  public:
    309   CXFA_TextLayout(IXFA_TextProvider* pTextProvider);
    310   virtual ~CXFA_TextLayout();
    311   int32_t GetText(CFX_WideString& wsText);
    312   FX_FLOAT GetLayoutHeight();
    313   FX_FLOAT StartLayout(FX_FLOAT fWidth = -1);
    314   FX_BOOL DoLayout(int32_t iBlockIndex,
    315                    FX_FLOAT& fCalcHeight,
    316                    FX_FLOAT fContentAreaHeight = -1,
    317                    FX_FLOAT fTextHeight = -1);
    318 
    319   FX_BOOL CalcSize(const CFX_SizeF& minSize,
    320                    const CFX_SizeF& maxSize,
    321                    CFX_SizeF& defaultSize);
    322   FX_BOOL Layout(const CFX_SizeF& size, FX_FLOAT* fHeight = NULL);
    323   void ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex);
    324   FX_BOOL DrawString(CFX_RenderDevice* pFxDevice,
    325                      const CFX_Matrix& tmDoc2Device,
    326                      const CFX_RectF& rtClip,
    327                      int32_t iBlock = 0);
    328   FX_BOOL IsLoaded() const { return m_pieceLines.GetSize() > 0; }
    329   void Unload();
    330   const CXFA_PieceLineArray* GetPieceLines();
    331 
    332   FX_BOOL m_bHasBlock;
    333   CFX_Int32Array m_Blocks;
    334 
    335  private:
    336   void GetTextDataNode();
    337   IFDE_XMLNode* GetXMLContainerNode();
    338   IFX_RTFBreak* CreateBreak(FX_BOOL bDefault);
    339   void InitBreak(FX_FLOAT fLineWidth);
    340   void InitBreak(IFDE_CSSComputedStyle* pStyle,
    341                  FDE_CSSDISPLAY eDisplay,
    342                  FX_FLOAT fLineWidth,
    343                  IFDE_XMLNode* pXMLNode,
    344                  IFDE_CSSComputedStyle* pParentStyle = NULL);
    345   FX_BOOL Loader(const CFX_SizeF& szText,
    346                  FX_FLOAT& fLinePos,
    347                  FX_BOOL bSavePieces = TRUE);
    348   void LoadText(CXFA_Node* pNode,
    349                 const CFX_SizeF& szText,
    350                 FX_FLOAT& fLinePos,
    351                 FX_BOOL bSavePieces);
    352   FX_BOOL LoadRichText(IFDE_XMLNode* pXMLNode,
    353                        const CFX_SizeF& szText,
    354                        FX_FLOAT& fLinePos,
    355                        IFDE_CSSComputedStyle* pParentStyle,
    356                        FX_BOOL bSavePieces,
    357                        CXFA_LinkUserData* pLinkData = NULL,
    358                        FX_BOOL bEndBreak = TRUE,
    359                        FX_BOOL bIsOl = FALSE,
    360                        int32_t iLiCount = 0);
    361   FX_BOOL AppendChar(const CFX_WideString& wsText,
    362                      FX_FLOAT& fLinePos,
    363                      FX_FLOAT fSpaceAbove,
    364                      FX_BOOL bSavePieces);
    365   void AppendTextLine(FX_DWORD dwStatus,
    366                       FX_FLOAT& fLinePos,
    367                       FX_BOOL bSavePieces,
    368                       FX_BOOL bEndBreak = FALSE);
    369   void EndBreak(FX_DWORD dwStatus, FX_FLOAT& fLinePos, FX_BOOL bDefault);
    370   FX_BOOL IsEnd(FX_BOOL bSavePieces);
    371   void ProcessText(CFX_WideString& wsText);
    372   void UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom);
    373   void RenderString(IFDE_RenderDevice* pDevice,
    374                     IFDE_SolidBrush* pBrush,
    375                     CXFA_PieceLine* pPieceLine,
    376                     int32_t iPiece,
    377                     FXTEXT_CHARPOS* pCharPos,
    378                     const CFX_Matrix& tmDoc2Device);
    379   void RenderPath(IFDE_RenderDevice* pDevice,
    380                   IFDE_Pen* pPen,
    381                   CXFA_PieceLine* pPieceLine,
    382                   int32_t iPiece,
    383                   FXTEXT_CHARPOS* pCharPos,
    384                   const CFX_Matrix& tmDoc2Device);
    385   int32_t GetDisplayPos(XFA_LPCTEXTPIECE pPiece,
    386                         FXTEXT_CHARPOS* pCharPos,
    387                         FX_BOOL bCharCode = FALSE);
    388   FX_BOOL ToRun(XFA_LPCTEXTPIECE pPiece, FX_RTFTEXTOBJ& tr);
    389   void DoTabstops(IFDE_CSSComputedStyle* pStyle, CXFA_PieceLine* pPieceLine);
    390   FX_BOOL Layout(int32_t iBlock);
    391   int32_t CountBlocks() const;
    392 
    393   IXFA_TextProvider* m_pTextProvider;
    394   CXFA_Node* m_pTextDataNode;
    395   FX_BOOL m_bRichText;
    396   IFX_MEMAllocator* m_pAllocator;
    397   IFX_RTFBreak* m_pBreak;
    398   CXFA_LoaderContext* m_pLoader;
    399   int32_t m_iLines;
    400   FX_FLOAT m_fMaxWidth;
    401   CXFA_TextParser m_textParser;
    402   CXFA_PieceLineArray m_pieceLines;
    403   CXFA_TextTabstopsContext* m_pTabstopContext;
    404   FX_BOOL m_bBlockContinue;
    405 };
    406 #endif
    407