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