Home | History | Annotate | Download | only in fxfa
      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/fxfa/cxfa_fftext.h"
      8 
      9 #include "xfa/fwl/fwl_widgetdef.h"
     10 #include "xfa/fwl/fwl_widgethit.h"
     11 #include "xfa/fxfa/cxfa_ffapp.h"
     12 #include "xfa/fxfa/cxfa_ffdoc.h"
     13 #include "xfa/fxfa/cxfa_ffdraw.h"
     14 #include "xfa/fxfa/cxfa_ffpageview.h"
     15 #include "xfa/fxfa/cxfa_ffwidget.h"
     16 #include "xfa/fxfa/cxfa_linkuserdata.h"
     17 #include "xfa/fxfa/cxfa_pieceline.h"
     18 #include "xfa/fxfa/cxfa_textlayout.h"
     19 #include "xfa/fxfa/cxfa_textpiece.h"
     20 #include "xfa/fxfa/parser/cxfa_margin.h"
     21 #include "xfa/fxgraphics/cxfa_graphics.h"
     22 
     23 CXFA_FFText::CXFA_FFText(CXFA_Node* pNode) : CXFA_FFDraw(pNode) {}
     24 
     25 CXFA_FFText::~CXFA_FFText() {}
     26 
     27 void CXFA_FFText::RenderWidget(CXFA_Graphics* pGS,
     28                                const CFX_Matrix& matrix,
     29                                uint32_t dwStatus) {
     30   if (!IsMatchVisibleStatus(dwStatus))
     31     return;
     32 
     33   CFX_Matrix mtRotate = GetRotateMatrix();
     34   mtRotate.Concat(matrix);
     35 
     36   CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus);
     37 
     38   CXFA_TextLayout* pTextLayout = m_pNode->GetWidgetAcc()->GetTextLayout();
     39   if (!pTextLayout)
     40     return;
     41 
     42   CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
     43   CFX_RectF rtText = GetRectWithoutRotate();
     44   CXFA_Margin* margin = m_pNode->GetMarginIfExists();
     45   if (margin) {
     46     CXFA_LayoutItem* pItem = this;
     47     if (!pItem->GetPrev() && !pItem->GetNext()) {
     48       XFA_RectWithoutMargin(rtText, margin);
     49     } else {
     50       float fTopInset = 0;
     51       float fBottomInset = 0;
     52       if (!pItem->GetPrev())
     53         fTopInset = margin->GetTopInset();
     54       else if (!pItem->GetNext())
     55         fBottomInset = margin->GetBottomInset();
     56 
     57       rtText.Deflate(margin->GetLeftInset(), fTopInset, margin->GetRightInset(),
     58                      fBottomInset);
     59     }
     60   }
     61 
     62   CFX_Matrix mt(1, 0, 0, 1, rtText.left, rtText.top);
     63   CFX_RectF rtClip = mtRotate.TransformRect(rtText);
     64   mt.Concat(mtRotate);
     65   pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex());
     66 }
     67 
     68 bool CXFA_FFText::IsLoaded() {
     69   CXFA_TextLayout* pTextLayout = m_pNode->GetWidgetAcc()->GetTextLayout();
     70   return pTextLayout && !pTextLayout->m_bHasBlock;
     71 }
     72 
     73 bool CXFA_FFText::PerformLayout() {
     74   CXFA_FFDraw::PerformLayout();
     75   CXFA_TextLayout* pTextLayout = m_pNode->GetWidgetAcc()->GetTextLayout();
     76   if (!pTextLayout)
     77     return false;
     78   if (!pTextLayout->m_bHasBlock)
     79     return true;
     80 
     81   pTextLayout->m_Blocks.clear();
     82   CXFA_LayoutItem* pItem = this;
     83   if (!pItem->GetPrev() && !pItem->GetNext())
     84     return true;
     85 
     86   pItem = pItem->GetFirst();
     87   while (pItem) {
     88     CFX_RectF rtText = pItem->GetRect(false);
     89     CXFA_Margin* margin = m_pNode->GetMarginIfExists();
     90     if (margin) {
     91       if (!pItem->GetPrev())
     92         rtText.height -= margin->GetTopInset();
     93       else if (!pItem->GetNext())
     94         rtText.height -= margin->GetBottomInset();
     95     }
     96     pTextLayout->ItemBlocks(rtText, pItem->GetIndex());
     97     pItem = pItem->GetNext();
     98   }
     99   pTextLayout->m_bHasBlock = false;
    100   return true;
    101 }
    102 
    103 bool CXFA_FFText::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
    104   if (!GetRectWithoutRotate().Contains(point))
    105     return false;
    106 
    107   const wchar_t* wsURLContent = GetLinkURLAtPoint(point);
    108   if (!wsURLContent)
    109     return false;
    110 
    111   SetButtonDown(true);
    112   return true;
    113 }
    114 
    115 bool CXFA_FFText::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) {
    116   return GetRectWithoutRotate().Contains(point) && !!GetLinkURLAtPoint(point);
    117 }
    118 
    119 bool CXFA_FFText::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
    120   if (!IsButtonDown())
    121     return false;
    122 
    123   SetButtonDown(false);
    124   const wchar_t* wsURLContent = GetLinkURLAtPoint(point);
    125   if (!wsURLContent)
    126     return false;
    127 
    128   CXFA_FFDoc* pDoc = GetDoc();
    129   pDoc->GetDocEnvironment()->GotoURL(pDoc, wsURLContent);
    130   return true;
    131 }
    132 
    133 FWL_WidgetHit CXFA_FFText::OnHitTest(const CFX_PointF& point) {
    134   if (!GetRectWithoutRotate().Contains(point))
    135     return FWL_WidgetHit::Unknown;
    136   if (!GetLinkURLAtPoint(point))
    137     return FWL_WidgetHit::Unknown;
    138   return FWL_WidgetHit::HyperLink;
    139 }
    140 
    141 const wchar_t* CXFA_FFText::GetLinkURLAtPoint(const CFX_PointF& point) {
    142   CXFA_TextLayout* pTextLayout = m_pNode->GetWidgetAcc()->GetTextLayout();
    143   if (!pTextLayout)
    144     return nullptr;
    145 
    146   CFX_RectF rect = GetRectWithoutRotate();
    147   for (const auto& pPieceLine : *pTextLayout->GetPieceLines()) {
    148     for (const auto& pPiece : pPieceLine->m_textPieces) {
    149       if (pPiece->pLinkData &&
    150           pPiece->rtPiece.Contains(point - rect.TopLeft())) {
    151         return pPiece->pLinkData->GetLinkURL();
    152       }
    153     }
    154   }
    155   return nullptr;
    156 }
    157