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