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/src/foxitlib.h"
8 #include "xfa/src/fxfa/src/common/xfa_common.h"
9 #include "xfa_ffwidget.h"
10 #include "xfa_ffdraw.h"
11 #include "xfa_fftext.h"
12 #include "xfa_textlayout.h"
13 #include "xfa_ffpageview.h"
14 #include "xfa_ffdoc.h"
15 #include "xfa_ffapp.h"
CXFA_FFText(CXFA_FFPageView * pPageView,CXFA_WidgetAcc * pDataAcc)16 CXFA_FFText::CXFA_FFText(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc)
17 : CXFA_FFDraw(pPageView, pDataAcc) {}
~CXFA_FFText()18 CXFA_FFText::~CXFA_FFText() {}
RenderWidget(CFX_Graphics * pGS,CFX_Matrix * pMatrix,FX_DWORD dwStatus,int32_t iRotate)19 void CXFA_FFText::RenderWidget(CFX_Graphics* pGS,
20 CFX_Matrix* pMatrix,
21 FX_DWORD dwStatus,
22 int32_t iRotate) {
23 if (!IsMatchVisibleStatus(dwStatus)) {
24 return;
25 }
26 {
27 CFX_Matrix mtRotate;
28 GetRotateMatrix(mtRotate);
29 if (pMatrix) {
30 mtRotate.Concat(*pMatrix);
31 }
32 CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
33 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
34 if (pTextLayout) {
35 CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
36 CFX_RectF rtText;
37 GetRectWithoutRotate(rtText);
38 if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
39 CXFA_LayoutItem* pItem = this;
40 if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
41 XFA_RectWidthoutMargin(rtText, mgWidget);
42 } else {
43 FX_FLOAT fLeftInset, fRightInset, fTopInset = 0, fBottomInset = 0;
44 mgWidget.GetLeftInset(fLeftInset);
45 mgWidget.GetRightInset(fRightInset);
46 if (pItem->GetPrev() == NULL) {
47 mgWidget.GetTopInset(fTopInset);
48 } else if (pItem->GetNext() == NULL) {
49 mgWidget.GetBottomInset(fBottomInset);
50 }
51 rtText.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
52 }
53 }
54 CFX_Matrix mt;
55 mt.Set(1, 0, 0, 1, rtText.left, rtText.top);
56 CFX_RectF rtClip = rtText;
57 mtRotate.TransformRect(rtClip);
58 mt.Concat(mtRotate);
59 pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex());
60 }
61 }
62 }
IsLoaded()63 FX_BOOL CXFA_FFText::IsLoaded() {
64 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
65 return pTextLayout != NULL && !pTextLayout->m_bHasBlock;
66 }
PerformLayout()67 FX_BOOL CXFA_FFText::PerformLayout() {
68 CXFA_FFDraw::PerformLayout();
69 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
70 if (!pTextLayout) {
71 return FALSE;
72 }
73 if (!pTextLayout->m_bHasBlock) {
74 return TRUE;
75 }
76 pTextLayout->m_Blocks.RemoveAll();
77 CXFA_LayoutItem* pItem = this;
78 if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
79 return TRUE;
80 }
81 pItem = pItem->GetFirst();
82 while (pItem) {
83 CFX_RectF rtText;
84 pItem->GetRect(rtText);
85 if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
86 if (pItem->GetPrev() == NULL) {
87 FX_FLOAT fTopInset;
88 mgWidget.GetTopInset(fTopInset);
89 rtText.height -= fTopInset;
90 } else if (pItem->GetNext() == NULL) {
91 FX_FLOAT fBottomInset;
92 mgWidget.GetBottomInset(fBottomInset);
93 rtText.height -= fBottomInset;
94 }
95 }
96 pTextLayout->ItemBlocks(rtText, pItem->GetIndex());
97 pItem = pItem->GetNext();
98 }
99 pTextLayout->m_bHasBlock = FALSE;
100 return TRUE;
101 }
OnLButtonDown(FX_DWORD dwFlags,FX_FLOAT fx,FX_FLOAT fy)102 FX_BOOL CXFA_FFText::OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
103 CFX_RectF rtBox;
104 GetRectWithoutRotate(rtBox);
105 if (!rtBox.Contains(fx, fy)) {
106 return FALSE;
107 }
108 const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
109 if (NULL == wsURLContent) {
110 return FALSE;
111 }
112 SetButtonDown(TRUE);
113 return TRUE;
114 }
OnMouseMove(FX_DWORD dwFlags,FX_FLOAT fx,FX_FLOAT fy)115 FX_BOOL CXFA_FFText::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
116 CFX_RectF rtBox;
117 GetRectWithoutRotate(rtBox);
118 if (!rtBox.Contains(fx, fy)) {
119 return FALSE;
120 }
121 const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
122 if (NULL == wsURLContent) {
123 return FALSE;
124 }
125 return TRUE;
126 }
OnLButtonUp(FX_DWORD dwFlags,FX_FLOAT fx,FX_FLOAT fy)127 FX_BOOL CXFA_FFText::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
128 if (!IsButtonDown()) {
129 return FALSE;
130 }
131 SetButtonDown(FALSE);
132 const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
133 if (NULL == wsURLContent) {
134 return FALSE;
135 }
136 CXFA_FFDoc* pDoc = GetDoc();
137 pDoc->GetDocProvider()->GotoURL(pDoc, CFX_WideStringC(wsURLContent), FALSE);
138 return TRUE;
139 }
OnHitTest(FX_FLOAT fx,FX_FLOAT fy)140 FX_DWORD CXFA_FFText::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) {
141 CFX_RectF rtBox;
142 GetRectWithoutRotate(rtBox);
143 if (!rtBox.Contains(fx, fy)) {
144 return FWL_WGTHITTEST_Unknown;
145 }
146 if (!GetLinkURLAtPoint(fx, fy)) {
147 return FWL_WGTHITTEST_Unknown;
148 }
149 return FWL_WGTHITTEST_HyperLink;
150 }
GetLinkURLAtPoint(FX_FLOAT fx,FX_FLOAT fy)151 const FX_WCHAR* CXFA_FFText::GetLinkURLAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
152 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
153 if (NULL == pTextLayout) {
154 return NULL;
155 }
156 FX_FLOAT x(fx), y(fy);
157 FWLToClient(x, y);
158 const CXFA_PieceLineArray* pPieceLines = pTextLayout->GetPieceLines();
159 int32_t iCount = pPieceLines->GetSize();
160 for (int32_t i = 0; i < iCount; i++) {
161 CXFA_PieceLine* pPieceLine = pPieceLines->GetAt(i);
162 int32_t iPieces = pPieceLine->m_textPieces.GetSize();
163 for (int32_t j = 0; j < iPieces; j++) {
164 XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j);
165 if (pPiece->pLinkData && pPiece->rtPiece.Contains(x, y)) {
166 return pPiece->pLinkData->GetLinkURL();
167 }
168 }
169 }
170 return NULL;
171 }
FWLToClient(FX_FLOAT & fx,FX_FLOAT & fy)172 void CXFA_FFText::FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy) {
173 CFX_RectF rtWidget;
174 GetRectWithoutRotate(rtWidget);
175 fx -= rtWidget.left;
176 fy -= rtWidget.top;
177 }
178