xref: /aosp_15_r20/external/pdfium/xfa/fxfa/cxfa_fftext.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2014 The PDFium Authors
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/fgas/graphics/cfgas_gegraphics.h"
10 #include "xfa/fgas/layout/cfgas_linkuserdata.h"
11 #include "xfa/fwl/fwl_widgethit.h"
12 #include "xfa/fxfa/cxfa_ffapp.h"
13 #include "xfa/fxfa/cxfa_ffdoc.h"
14 #include "xfa/fxfa/cxfa_ffpageview.h"
15 #include "xfa/fxfa/cxfa_ffwidget.h"
16 #include "xfa/fxfa/cxfa_textlayout.h"
17 #include "xfa/fxfa/parser/cxfa_margin.h"
18 
CXFA_FFText(CXFA_Node * pNode)19 CXFA_FFText::CXFA_FFText(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {}
20 
21 CXFA_FFText::~CXFA_FFText() = default;
22 
RenderWidget(CFGAS_GEGraphics * pGS,const CFX_Matrix & matrix,HighlightOption highlight)23 void CXFA_FFText::RenderWidget(CFGAS_GEGraphics* pGS,
24                                const CFX_Matrix& matrix,
25                                HighlightOption highlight) {
26   if (!HasVisibleStatus())
27     return;
28 
29   CFX_Matrix mtRotate = GetRotateMatrix();
30   mtRotate.Concat(matrix);
31 
32   CXFA_FFWidget::RenderWidget(pGS, mtRotate, highlight);
33 
34   CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
35   if (!pTextLayout)
36     return;
37 
38   CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
39   CFX_RectF rtText = GetRectWithoutRotate();
40   CXFA_Margin* margin = m_pNode->GetMarginIfExists();
41   if (margin) {
42     CXFA_ContentLayoutItem* pItem = GetLayoutItem();
43     if (!pItem->GetPrev() && !pItem->GetNext()) {
44       XFA_RectWithoutMargin(&rtText, margin);
45     } else {
46       float fTopInset = 0;
47       float fBottomInset = 0;
48       if (!pItem->GetPrev())
49         fTopInset = margin->GetTopInset();
50       else if (!pItem->GetNext())
51         fBottomInset = margin->GetBottomInset();
52 
53       rtText.Deflate(margin->GetLeftInset(), fTopInset, margin->GetRightInset(),
54                      fBottomInset);
55     }
56   }
57 
58   CFX_Matrix mt(1, 0, 0, 1, rtText.left, rtText.top);
59   CFX_RectF rtClip = mtRotate.TransformRect(rtText);
60   mt.Concat(mtRotate);
61   pTextLayout->DrawString(pRenderDevice, mt, rtClip,
62                           GetLayoutItem()->GetIndex());
63 }
64 
IsLoaded()65 bool CXFA_FFText::IsLoaded() {
66   CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
67   return pTextLayout && !pTextLayout->HasBlock();
68 }
69 
PerformLayout()70 bool CXFA_FFText::PerformLayout() {
71   CXFA_FFWidget::PerformLayout();
72   CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
73   if (!pTextLayout)
74     return false;
75   if (!pTextLayout->HasBlock())
76     return true;
77 
78   pTextLayout->ClearBlocks();
79   CXFA_ContentLayoutItem* pItem = GetLayoutItem();
80   if (!pItem->GetPrev() && !pItem->GetNext())
81     return true;
82 
83   pItem = pItem->GetFirst();
84   while (pItem) {
85     CFX_RectF rtText = pItem->GetAbsoluteRect();
86     CXFA_Margin* margin = m_pNode->GetMarginIfExists();
87     if (margin) {
88       if (!pItem->GetPrev())
89         rtText.height -= margin->GetTopInset();
90       else if (!pItem->GetNext())
91         rtText.height -= margin->GetBottomInset();
92     }
93     pTextLayout->ItemBlocks(rtText, pItem->GetIndex());
94     pItem = pItem->GetNext();
95   }
96   pTextLayout->ResetHasBlock();
97   return true;
98 }
99 
AcceptsFocusOnButtonDown(Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point,CFWL_MessageMouse::MouseCommand command)100 bool CXFA_FFText::AcceptsFocusOnButtonDown(
101     Mask<XFA_FWL_KeyFlag> dwFlags,
102     const CFX_PointF& point,
103     CFWL_MessageMouse::MouseCommand command) {
104   return command == CFWL_MessageMouse::MouseCommand::kLeftButtonDown &&
105          GetRectWithoutRotate().Contains(point) &&
106          !GetLinkURLAtPoint(point).IsEmpty();
107 }
108 
OnLButtonDown(Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)109 bool CXFA_FFText::OnLButtonDown(Mask<XFA_FWL_KeyFlag> dwFlags,
110                                 const CFX_PointF& point) {
111   SetButtonDown(true);
112   return true;
113 }
114 
OnMouseMove(Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)115 bool CXFA_FFText::OnMouseMove(Mask<XFA_FWL_KeyFlag> dwFlags,
116                               const CFX_PointF& point) {
117   return GetRectWithoutRotate().Contains(point) &&
118          !GetLinkURLAtPoint(point).IsEmpty();
119 }
120 
OnLButtonUp(Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)121 bool CXFA_FFText::OnLButtonUp(Mask<XFA_FWL_KeyFlag> dwFlags,
122                               const CFX_PointF& point) {
123   if (!IsButtonDown())
124     return false;
125 
126   SetButtonDown(false);
127   WideString wsURLContent = GetLinkURLAtPoint(point);
128   if (wsURLContent.IsEmpty())
129     return false;
130 
131   GetDoc()->GotoURL(wsURLContent);
132   return true;
133 }
134 
HitTest(const CFX_PointF & point)135 FWL_WidgetHit CXFA_FFText::HitTest(const CFX_PointF& point) {
136   if (GetRectWithoutRotate().Contains(point) &&
137       !GetLinkURLAtPoint(point).IsEmpty()) {
138     return FWL_WidgetHit::HyperLink;
139   }
140   return FWL_WidgetHit::Unknown;
141 }
142 
GetLinkURLAtPoint(const CFX_PointF & point)143 WideString CXFA_FFText::GetLinkURLAtPoint(const CFX_PointF& point) {
144   CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
145   if (!pTextLayout)
146     return WideString();
147 
148   CFX_RectF rect = GetRectWithoutRotate();
149   return pTextLayout->GetLinkURLAtPoint(point - rect.TopLeft());
150 }
151