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 #include "xfa/src/foxitlib.h"
      8 #include "xfa/src/fxfa/src/common/xfa_common.h"
      9 #include "xfa_ffwidget.h"
     10 #include "xfa_ffdraw.h"
     11 #include "xfa_fftext.h"
     12 #include "xfa_textlayout.h"
     13 #include "xfa_ffpageview.h"
     14 #include "xfa_ffdoc.h"
     15 #include "xfa_ffapp.h"
     16 CXFA_FFText::CXFA_FFText(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc)
     17     : CXFA_FFDraw(pPageView, pDataAcc) {}
     18 CXFA_FFText::~CXFA_FFText() {}
     19 void CXFA_FFText::RenderWidget(CFX_Graphics* pGS,
     20                                CFX_Matrix* pMatrix,
     21                                FX_DWORD dwStatus,
     22                                int32_t iRotate) {
     23   if (!IsMatchVisibleStatus(dwStatus)) {
     24     return;
     25   }
     26   {
     27     CFX_Matrix mtRotate;
     28     GetRotateMatrix(mtRotate);
     29     if (pMatrix) {
     30       mtRotate.Concat(*pMatrix);
     31     }
     32     CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
     33     CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
     34     if (pTextLayout) {
     35       CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
     36       CFX_RectF rtText;
     37       GetRectWithoutRotate(rtText);
     38       if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
     39         CXFA_LayoutItem* pItem = this;
     40         if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
     41           XFA_RectWidthoutMargin(rtText, mgWidget);
     42         } else {
     43           FX_FLOAT fLeftInset, fRightInset, fTopInset = 0, fBottomInset = 0;
     44           mgWidget.GetLeftInset(fLeftInset);
     45           mgWidget.GetRightInset(fRightInset);
     46           if (pItem->GetPrev() == NULL) {
     47             mgWidget.GetTopInset(fTopInset);
     48           } else if (pItem->GetNext() == NULL) {
     49             mgWidget.GetBottomInset(fBottomInset);
     50           }
     51           rtText.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
     52         }
     53       }
     54       CFX_Matrix mt;
     55       mt.Set(1, 0, 0, 1, rtText.left, rtText.top);
     56       CFX_RectF rtClip = rtText;
     57       mtRotate.TransformRect(rtClip);
     58       mt.Concat(mtRotate);
     59       pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex());
     60     }
     61   }
     62 }
     63 FX_BOOL CXFA_FFText::IsLoaded() {
     64   CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
     65   return pTextLayout != NULL && !pTextLayout->m_bHasBlock;
     66 }
     67 FX_BOOL CXFA_FFText::PerformLayout() {
     68   CXFA_FFDraw::PerformLayout();
     69   CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
     70   if (!pTextLayout) {
     71     return FALSE;
     72   }
     73   if (!pTextLayout->m_bHasBlock) {
     74     return TRUE;
     75   }
     76   pTextLayout->m_Blocks.RemoveAll();
     77   CXFA_LayoutItem* pItem = this;
     78   if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
     79     return TRUE;
     80   }
     81   pItem = pItem->GetFirst();
     82   while (pItem) {
     83     CFX_RectF rtText;
     84     pItem->GetRect(rtText);
     85     if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
     86       if (pItem->GetPrev() == NULL) {
     87         FX_FLOAT fTopInset;
     88         mgWidget.GetTopInset(fTopInset);
     89         rtText.height -= fTopInset;
     90       } else if (pItem->GetNext() == NULL) {
     91         FX_FLOAT fBottomInset;
     92         mgWidget.GetBottomInset(fBottomInset);
     93         rtText.height -= fBottomInset;
     94       }
     95     }
     96     pTextLayout->ItemBlocks(rtText, pItem->GetIndex());
     97     pItem = pItem->GetNext();
     98   }
     99   pTextLayout->m_bHasBlock = FALSE;
    100   return TRUE;
    101 }
    102 FX_BOOL CXFA_FFText::OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
    103   CFX_RectF rtBox;
    104   GetRectWithoutRotate(rtBox);
    105   if (!rtBox.Contains(fx, fy)) {
    106     return FALSE;
    107   }
    108   const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
    109   if (NULL == wsURLContent) {
    110     return FALSE;
    111   }
    112   SetButtonDown(TRUE);
    113   return TRUE;
    114 }
    115 FX_BOOL CXFA_FFText::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
    116   CFX_RectF rtBox;
    117   GetRectWithoutRotate(rtBox);
    118   if (!rtBox.Contains(fx, fy)) {
    119     return FALSE;
    120   }
    121   const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
    122   if (NULL == wsURLContent) {
    123     return FALSE;
    124   }
    125   return TRUE;
    126 }
    127 FX_BOOL CXFA_FFText::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
    128   if (!IsButtonDown()) {
    129     return FALSE;
    130   }
    131   SetButtonDown(FALSE);
    132   const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
    133   if (NULL == wsURLContent) {
    134     return FALSE;
    135   }
    136   CXFA_FFDoc* pDoc = GetDoc();
    137   pDoc->GetDocProvider()->GotoURL(pDoc, CFX_WideStringC(wsURLContent), FALSE);
    138   return TRUE;
    139 }
    140 FX_DWORD CXFA_FFText::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) {
    141   CFX_RectF rtBox;
    142   GetRectWithoutRotate(rtBox);
    143   if (!rtBox.Contains(fx, fy)) {
    144     return FWL_WGTHITTEST_Unknown;
    145   }
    146   if (!GetLinkURLAtPoint(fx, fy)) {
    147     return FWL_WGTHITTEST_Unknown;
    148   }
    149   return FWL_WGTHITTEST_HyperLink;
    150 }
    151 const FX_WCHAR* CXFA_FFText::GetLinkURLAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
    152   CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
    153   if (NULL == pTextLayout) {
    154     return NULL;
    155   }
    156   FX_FLOAT x(fx), y(fy);
    157   FWLToClient(x, y);
    158   const CXFA_PieceLineArray* pPieceLines = pTextLayout->GetPieceLines();
    159   int32_t iCount = pPieceLines->GetSize();
    160   for (int32_t i = 0; i < iCount; i++) {
    161     CXFA_PieceLine* pPieceLine = pPieceLines->GetAt(i);
    162     int32_t iPieces = pPieceLine->m_textPieces.GetSize();
    163     for (int32_t j = 0; j < iPieces; j++) {
    164       XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j);
    165       if (pPiece->pLinkData && pPiece->rtPiece.Contains(x, y)) {
    166         return pPiece->pLinkData->GetLinkURL();
    167       }
    168     }
    169   }
    170   return NULL;
    171 }
    172 void CXFA_FFText::FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy) {
    173   CFX_RectF rtWidget;
    174   GetRectWithoutRotate(rtWidget);
    175   fx -= rtWidget.left;
    176   fy -= rtWidget.top;
    177 }
    178