• 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/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 
CXFA_FFText(CXFA_Node * pNode)23 CXFA_FFText::CXFA_FFText(CXFA_Node* pNode) : CXFA_FFDraw(pNode) {}
24 
~CXFA_FFText()25 CXFA_FFText::~CXFA_FFText() {}
26 
RenderWidget(CXFA_Graphics * pGS,const CFX_Matrix & matrix,uint32_t dwStatus)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 
IsLoaded()68 bool CXFA_FFText::IsLoaded() {
69   CXFA_TextLayout* pTextLayout = m_pNode->GetWidgetAcc()->GetTextLayout();
70   return pTextLayout && !pTextLayout->m_bHasBlock;
71 }
72 
PerformLayout()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 
OnLButtonDown(uint32_t dwFlags,const CFX_PointF & point)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 
OnMouseMove(uint32_t dwFlags,const CFX_PointF & point)115 bool CXFA_FFText::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) {
116   return GetRectWithoutRotate().Contains(point) && !!GetLinkURLAtPoint(point);
117 }
118 
OnLButtonUp(uint32_t dwFlags,const CFX_PointF & point)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 
OnHitTest(const CFX_PointF & point)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 
GetLinkURLAtPoint(const CFX_PointF & point)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