blob: 0cc6651d21b3630e5c8afe9e6b236c992e286c96 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// 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
dsinclair447b1f32016-12-08 10:06:32 -08009#include "xfa/fwl/fwl_widgetdef.h"
10#include "xfa/fwl/fwl_widgethit.h"
Dan Sinclair1f5d4982017-01-10 16:37:32 -050011#include "xfa/fxfa/app/cxfa_linkuserdata.h"
12#include "xfa/fxfa/app/cxfa_pieceline.h"
13#include "xfa/fxfa/app/cxfa_textlayout.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040014#include "xfa/fxfa/app/xfa_ffdraw.h"
Dan Sinclair1f5d4982017-01-10 16:37:32 -050015#include "xfa/fxfa/app/xfa_textpiece.h"
dsinclair5b493092016-09-29 20:20:24 -070016#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"
dsinclair202ad722016-09-29 17:41:42 -070020#include "xfa/fxgraphics/cfx_graphics.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040021
dan sinclairaaf0bdc2017-02-04 10:16:21 -050022CXFA_FFText::CXFA_FFText(CXFA_WidgetAcc* pDataAcc) : CXFA_FFDraw(pDataAcc) {}
23
Dan Sinclair1770c022016-03-14 14:14:16 -040024CXFA_FFText::~CXFA_FFText() {}
dan sinclairaaf0bdc2017-02-04 10:16:21 -050025
Dan Sinclair1770c022016-03-14 14:14:16 -040026void CXFA_FFText::RenderWidget(CFX_Graphics* pGS,
27 CFX_Matrix* pMatrix,
dsinclair9d6ca992016-06-16 10:51:56 -070028 uint32_t dwStatus) {
Dan Sinclair1770c022016-03-14 14:14:16 -040029 if (!IsMatchVisibleStatus(dwStatus)) {
30 return;
31 }
32 {
33 CFX_Matrix mtRotate;
34 GetRotateMatrix(mtRotate);
35 if (pMatrix) {
36 mtRotate.Concat(*pMatrix);
37 }
38 CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
39 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
40 if (pTextLayout) {
41 CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
42 CFX_RectF rtText;
43 GetRectWithoutRotate(rtText);
44 if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
45 CXFA_LayoutItem* pItem = this;
dsinclair85d1f2c2016-06-23 12:40:16 -070046 if (!pItem->GetPrev() && !pItem->GetNext()) {
Dan Sinclair1770c022016-03-14 14:14:16 -040047 XFA_RectWidthoutMargin(rtText, mgWidget);
48 } else {
49 FX_FLOAT fLeftInset, fRightInset, fTopInset = 0, fBottomInset = 0;
50 mgWidget.GetLeftInset(fLeftInset);
51 mgWidget.GetRightInset(fRightInset);
dsinclair85d1f2c2016-06-23 12:40:16 -070052 if (!pItem->GetPrev()) {
Dan Sinclair1770c022016-03-14 14:14:16 -040053 mgWidget.GetTopInset(fTopInset);
dsinclair85d1f2c2016-06-23 12:40:16 -070054 } else if (!pItem->GetNext()) {
Dan Sinclair1770c022016-03-14 14:14:16 -040055 mgWidget.GetBottomInset(fBottomInset);
56 }
57 rtText.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
58 }
59 }
60 CFX_Matrix mt;
61 mt.Set(1, 0, 0, 1, rtText.left, rtText.top);
62 CFX_RectF rtClip = rtText;
63 mtRotate.TransformRect(rtClip);
64 mt.Concat(mtRotate);
65 pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex());
66 }
67 }
68}
tsepezd19e9122016-11-02 15:43:18 -070069bool CXFA_FFText::IsLoaded() {
Dan Sinclair1770c022016-03-14 14:14:16 -040070 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
71 return pTextLayout && !pTextLayout->m_bHasBlock;
72}
tsepezd19e9122016-11-02 15:43:18 -070073bool CXFA_FFText::PerformLayout() {
Dan Sinclair1770c022016-03-14 14:14:16 -040074 CXFA_FFDraw::PerformLayout();
75 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
76 if (!pTextLayout) {
tsepezd19e9122016-11-02 15:43:18 -070077 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040078 }
79 if (!pTextLayout->m_bHasBlock) {
tsepezd19e9122016-11-02 15:43:18 -070080 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -040081 }
82 pTextLayout->m_Blocks.RemoveAll();
83 CXFA_LayoutItem* pItem = this;
dsinclair85d1f2c2016-06-23 12:40:16 -070084 if (!pItem->GetPrev() && !pItem->GetNext()) {
tsepezd19e9122016-11-02 15:43:18 -070085 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -040086 }
87 pItem = pItem->GetFirst();
88 while (pItem) {
89 CFX_RectF rtText;
90 pItem->GetRect(rtText);
91 if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
dsinclair85d1f2c2016-06-23 12:40:16 -070092 if (!pItem->GetPrev()) {
Dan Sinclair1770c022016-03-14 14:14:16 -040093 FX_FLOAT fTopInset;
94 mgWidget.GetTopInset(fTopInset);
95 rtText.height -= fTopInset;
dsinclair85d1f2c2016-06-23 12:40:16 -070096 } else if (!pItem->GetNext()) {
Dan Sinclair1770c022016-03-14 14:14:16 -040097 FX_FLOAT fBottomInset;
98 mgWidget.GetBottomInset(fBottomInset);
99 rtText.height -= fBottomInset;
100 }
101 }
102 pTextLayout->ItemBlocks(rtText, pItem->GetIndex());
103 pItem = pItem->GetNext();
104 }
tsepezd19e9122016-11-02 15:43:18 -0700105 pTextLayout->m_bHasBlock = false;
106 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400107}
tsepezd19e9122016-11-02 15:43:18 -0700108bool CXFA_FFText::OnLButtonDown(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400109 CFX_RectF rtBox;
110 GetRectWithoutRotate(rtBox);
111 if (!rtBox.Contains(fx, fy)) {
tsepezd19e9122016-11-02 15:43:18 -0700112 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400113 }
114 const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
dsinclair85d1f2c2016-06-23 12:40:16 -0700115 if (!wsURLContent) {
tsepezd19e9122016-11-02 15:43:18 -0700116 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400117 }
tsepezd19e9122016-11-02 15:43:18 -0700118 SetButtonDown(true);
119 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400120}
tsepezd19e9122016-11-02 15:43:18 -0700121bool CXFA_FFText::OnMouseMove(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400122 CFX_RectF rtBox;
123 GetRectWithoutRotate(rtBox);
124 if (!rtBox.Contains(fx, fy)) {
tsepezd19e9122016-11-02 15:43:18 -0700125 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400126 }
127 const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
dsinclair85d1f2c2016-06-23 12:40:16 -0700128 if (!wsURLContent) {
tsepezd19e9122016-11-02 15:43:18 -0700129 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400130 }
tsepezd19e9122016-11-02 15:43:18 -0700131 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400132}
tsepezd19e9122016-11-02 15:43:18 -0700133bool CXFA_FFText::OnLButtonUp(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400134 if (!IsButtonDown()) {
tsepezd19e9122016-11-02 15:43:18 -0700135 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400136 }
tsepezd19e9122016-11-02 15:43:18 -0700137 SetButtonDown(false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400138 const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
dsinclair85d1f2c2016-06-23 12:40:16 -0700139 if (!wsURLContent) {
tsepezd19e9122016-11-02 15:43:18 -0700140 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400141 }
142 CXFA_FFDoc* pDoc = GetDoc();
dsinclair577ad2c2016-09-22 10:20:43 -0700143 pDoc->GetDocEnvironment()->GotoURL(pDoc, wsURLContent);
tsepezd19e9122016-11-02 15:43:18 -0700144 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400145}
dsinclair89fcde82016-05-03 13:00:25 -0700146FWL_WidgetHit CXFA_FFText::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400147 CFX_RectF rtBox;
148 GetRectWithoutRotate(rtBox);
dsinclair89fcde82016-05-03 13:00:25 -0700149 if (!rtBox.Contains(fx, fy))
150 return FWL_WidgetHit::Unknown;
151 if (!GetLinkURLAtPoint(fx, fy))
152 return FWL_WidgetHit::Unknown;
153 return FWL_WidgetHit::HyperLink;
Dan Sinclair1770c022016-03-14 14:14:16 -0400154}
155const FX_WCHAR* CXFA_FFText::GetLinkURLAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
156 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
tsepez783a7e02017-01-17 11:05:57 -0800157 if (!pTextLayout)
dsinclair85d1f2c2016-06-23 12:40:16 -0700158 return nullptr;
tsepez783a7e02017-01-17 11:05:57 -0800159
160 FX_FLOAT x(fx);
161 FX_FLOAT y(fy);
Dan Sinclair1770c022016-03-14 14:14:16 -0400162 FWLToClient(x, y);
tsepez783a7e02017-01-17 11:05:57 -0800163
164 for (const auto& pPieceLine : *pTextLayout->GetPieceLines()) {
165 for (const auto& pPiece : pPieceLine->m_textPieces) {
166 if (pPiece->pLinkData && pPiece->rtPiece.Contains(x, y))
Dan Sinclair1770c022016-03-14 14:14:16 -0400167 return pPiece->pLinkData->GetLinkURL();
Dan Sinclair1770c022016-03-14 14:14:16 -0400168 }
169 }
dsinclair85d1f2c2016-06-23 12:40:16 -0700170 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400171}
172void 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}