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_ffwidget.h"
8 
9 #include <algorithm>
10 #include <cmath>
11 #include <memory>
12 #include <utility>
13 #include <vector>
14 
15 #include "core/fxcodec/fx_codec.h"
16 #include "core/fxcodec/progressivedecoder.h"
17 #include "core/fxcrt/maybe_owned.h"
18 #include "core/fxge/cfx_pathdata.h"
19 #include "core/fxge/cfx_renderdevice.h"
20 #include "core/fxge/dib/cfx_dibitmap.h"
21 #include "xfa/fwl/fwl_widgethit.h"
22 #include "xfa/fxfa/cxfa_eventparam.h"
23 #include "xfa/fxfa/cxfa_ffapp.h"
24 #include "xfa/fxfa/cxfa_ffdoc.h"
25 #include "xfa/fxfa/cxfa_ffdocview.h"
26 #include "xfa/fxfa/cxfa_ffpageview.h"
27 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
28 #include "xfa/fxfa/cxfa_imagerenderer.h"
29 #include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
30 #include "xfa/fxfa/parser/cxfa_border.h"
31 #include "xfa/fxfa/parser/cxfa_box.h"
32 #include "xfa/fxfa/parser/cxfa_edge.h"
33 #include "xfa/fxfa/parser/cxfa_image.h"
34 #include "xfa/fxfa/parser/cxfa_margin.h"
35 #include "xfa/fxfa/parser/cxfa_node.h"
36 #include "xfa/fxgraphics/cxfa_graphics.h"
37 
38 namespace {
39 
XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,int32_t iComponents,int32_t iBitsPerComponent)40 FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,
41                               int32_t iComponents,
42                               int32_t iBitsPerComponent) {
43   FXDIB_Format dibFormat = FXDIB_Argb;
44   switch (type) {
45     case FXCODEC_IMAGE_JPG:
46 #ifdef PDF_ENABLE_XFA_BMP
47     case FXCODEC_IMAGE_BMP:
48 #endif  // PDF_ENABLE_XFA_BMP
49 #ifdef PDF_ENABLE_XFA_TIFF
50     case FXCODEC_IMAGE_TIFF:
51 #endif  // PDF_ENABLE_XFA_TIFF
52     {
53       dibFormat = FXDIB_Rgb32;
54       int32_t bpp = iComponents * iBitsPerComponent;
55       if (bpp <= 24) {
56         dibFormat = FXDIB_Rgb;
57       }
58     } break;
59 #ifdef PDF_ENABLE_XFA_PNG
60     case FXCODEC_IMAGE_PNG:
61 #endif  // PDF_ENABLE_XFA_PNG
62     default:
63       break;
64   }
65   return dibFormat;
66 }
67 
IsFXCodecErrorStatus(FXCODEC_STATUS status)68 bool IsFXCodecErrorStatus(FXCODEC_STATUS status) {
69   return (status == FXCODEC_STATUS_ERROR ||
70           status == FXCODEC_STATUS_ERR_MEMORY ||
71           status == FXCODEC_STATUS_ERR_READ ||
72           status == FXCODEC_STATUS_ERR_FLUSH ||
73           status == FXCODEC_STATUS_ERR_FORMAT ||
74           status == FXCODEC_STATUS_ERR_PARAMS);
75 }
76 
77 }  // namespace
78 
XFA_DrawImage(CXFA_Graphics * pGS,const CFX_RectF & rtImage,const CFX_Matrix & matrix,const RetainPtr<CFX_DIBitmap> & pDIBitmap,XFA_AttributeValue iAspect,const CFX_Size & dpi,XFA_AttributeValue iHorzAlign,XFA_AttributeValue iVertAlign)79 void XFA_DrawImage(CXFA_Graphics* pGS,
80                    const CFX_RectF& rtImage,
81                    const CFX_Matrix& matrix,
82                    const RetainPtr<CFX_DIBitmap>& pDIBitmap,
83                    XFA_AttributeValue iAspect,
84                    const CFX_Size& dpi,
85                    XFA_AttributeValue iHorzAlign,
86                    XFA_AttributeValue iVertAlign) {
87   if (rtImage.IsEmpty())
88     return;
89   if (!pDIBitmap || !pDIBitmap->GetBuffer())
90     return;
91 
92   CFX_RectF rtFit(rtImage.TopLeft(),
93                   XFA_UnitPx2Pt(pDIBitmap->GetWidth(), dpi.width),
94                   XFA_UnitPx2Pt(pDIBitmap->GetHeight(), dpi.height));
95   switch (iAspect) {
96     case XFA_AttributeValue::Fit: {
97       float f1 = rtImage.height / rtFit.height;
98       float f2 = rtImage.width / rtFit.width;
99       f1 = std::min(f1, f2);
100       rtFit.height = rtFit.height * f1;
101       rtFit.width = rtFit.width * f1;
102       break;
103     }
104     case XFA_AttributeValue::Height: {
105       float f1 = rtImage.height / rtFit.height;
106       rtFit.height = rtImage.height;
107       rtFit.width = f1 * rtFit.width;
108       break;
109     }
110     case XFA_AttributeValue::None:
111       rtFit.height = rtImage.height;
112       rtFit.width = rtImage.width;
113       break;
114     case XFA_AttributeValue::Width: {
115       float f1 = rtImage.width / rtFit.width;
116       rtFit.width = rtImage.width;
117       rtFit.height = rtFit.height * f1;
118       break;
119     }
120     case XFA_AttributeValue::Actual:
121     default:
122       break;
123   }
124 
125   if (iHorzAlign == XFA_AttributeValue::Center)
126     rtFit.left += (rtImage.width - rtFit.width) / 2;
127   else if (iHorzAlign == XFA_AttributeValue::Right)
128     rtFit.left = rtImage.right() - rtFit.width;
129 
130   if (iVertAlign == XFA_AttributeValue::Middle)
131     rtFit.top += (rtImage.height - rtFit.height) / 2;
132   else if (iVertAlign == XFA_AttributeValue::Bottom)
133     rtFit.top = rtImage.bottom() - rtImage.height;
134 
135   CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
136   CFX_RenderDevice::StateRestorer restorer(pRenderDevice);
137   CFX_PathData path;
138   path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top);
139   pRenderDevice->SetClip_PathFill(&path, &matrix, FXFILL_WINDING);
140 
141   CFX_Matrix mtImage(1, 0, 0, -1, 0, 1);
142   mtImage.Concat(
143       CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top));
144   mtImage.Concat(matrix);
145 
146   CXFA_ImageRenderer imageRender(pRenderDevice, pDIBitmap, &mtImage);
147   if (!imageRender.Start()) {
148     return;
149   }
150   while (imageRender.Continue())
151     continue;
152 }
153 
XFA_LoadImageFromBuffer(const RetainPtr<IFX_SeekableReadStream> & pImageFileRead,FXCODEC_IMAGE_TYPE type,int32_t & iImageXDpi,int32_t & iImageYDpi)154 RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer(
155     const RetainPtr<IFX_SeekableReadStream>& pImageFileRead,
156     FXCODEC_IMAGE_TYPE type,
157     int32_t& iImageXDpi,
158     int32_t& iImageYDpi) {
159   auto* pCodecMgr = fxcodec::ModuleMgr::GetInstance();
160   std::unique_ptr<ProgressiveDecoder> pProgressiveDecoder =
161       pCodecMgr->CreateProgressiveDecoder();
162 
163   CFX_DIBAttribute dibAttr;
164   pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false);
165   switch (dibAttr.m_wDPIUnit) {
166     case FXCODEC_RESUNIT_CENTIMETER:
167       dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f);
168       dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f);
169       break;
170     case FXCODEC_RESUNIT_METER:
171       dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (float)100 * 2.54f);
172       dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (float)100 * 2.54f);
173       break;
174     default:
175       break;
176   }
177   iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96);
178   iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96);
179   if (pProgressiveDecoder->GetWidth() <= 0 ||
180       pProgressiveDecoder->GetHeight() <= 0) {
181     return nullptr;
182   }
183 
184   type = pProgressiveDecoder->GetType();
185   int32_t iComponents = pProgressiveDecoder->GetNumComponents();
186   int32_t iBpc = pProgressiveDecoder->GetBPC();
187   FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc);
188   RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
189   pBitmap->Create(pProgressiveDecoder->GetWidth(),
190                   pProgressiveDecoder->GetHeight(), dibFormat);
191   pBitmap->Clear(0xffffffff);
192 
193   size_t nFrames;
194   FXCODEC_STATUS status;
195   std::tie(status, nFrames) = pProgressiveDecoder->GetFrames();
196   if (status != FXCODEC_STATUS_DECODE_READY || nFrames == 0) {
197     pBitmap = nullptr;
198     return pBitmap;
199   }
200 
201   status = pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(),
202                                             pBitmap->GetHeight());
203   if (IsFXCodecErrorStatus(status)) {
204     pBitmap = nullptr;
205     return pBitmap;
206   }
207 
208   while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
209     status = pProgressiveDecoder->ContinueDecode();
210     if (IsFXCodecErrorStatus(status)) {
211       pBitmap = nullptr;
212       return pBitmap;
213     }
214   }
215 
216   return pBitmap;
217 }
218 
XFA_RectWithoutMargin(CFX_RectF * rt,const CXFA_Margin * margin)219 void XFA_RectWithoutMargin(CFX_RectF* rt, const CXFA_Margin* margin) {
220   if (!margin)
221     return;
222 
223   rt->Deflate(margin->GetLeftInset(), margin->GetTopInset(),
224               margin->GetRightInset(), margin->GetBottomInset());
225 }
226 
XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem * pLayoutItem)227 CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
228   if (!pLayoutItem->GetFormNode()->HasCreatedUIWidget())
229     return nullptr;
230 
231   return GetFFWidget(ToContentLayoutItem(pLayoutItem));
232 }
233 
234 CXFA_CalcData::CXFA_CalcData() = default;
235 
236 CXFA_CalcData::~CXFA_CalcData() = default;
237 
CXFA_FFWidget(CXFA_Node * node)238 CXFA_FFWidget::CXFA_FFWidget(CXFA_Node* node) : m_pNode(node) {}
239 
240 CXFA_FFWidget::~CXFA_FFWidget() = default;
241 
GetFWLApp()242 const CFWL_App* CXFA_FFWidget::GetFWLApp() {
243   return GetPageView()->GetDocView()->GetDoc()->GetApp()->GetFWLApp();
244 }
245 
GetNextFFWidget() const246 CXFA_FFWidget* CXFA_FFWidget::GetNextFFWidget() const {
247   return GetFFWidget(GetLayoutItem()->GetNext());
248 }
249 
GetWidgetRect() const250 const CFX_RectF& CXFA_FFWidget::GetWidgetRect() const {
251   if (!GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_RectCached))
252     RecacheWidgetRect();
253   return m_rtWidget;
254 }
255 
RecacheWidgetRect() const256 const CFX_RectF& CXFA_FFWidget::RecacheWidgetRect() const {
257   GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_RectCached);
258   m_rtWidget = GetLayoutItem()->GetRect(false);
259   return m_rtWidget;
260 }
261 
GetRectWithoutRotate()262 CFX_RectF CXFA_FFWidget::GetRectWithoutRotate() {
263   CFX_RectF rtWidget = GetWidgetRect();
264   float fValue = 0;
265   switch (m_pNode->GetRotate()) {
266     case 90:
267       rtWidget.top = rtWidget.bottom();
268       fValue = rtWidget.width;
269       rtWidget.width = rtWidget.height;
270       rtWidget.height = fValue;
271       break;
272     case 180:
273       rtWidget.left = rtWidget.right();
274       rtWidget.top = rtWidget.bottom();
275       break;
276     case 270:
277       rtWidget.left = rtWidget.right();
278       fValue = rtWidget.width;
279       rtWidget.width = rtWidget.height;
280       rtWidget.height = fValue;
281       break;
282   }
283   return rtWidget;
284 }
285 
ModifyStatus(uint32_t dwAdded,uint32_t dwRemoved)286 void CXFA_FFWidget::ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved) {
287   GetLayoutItem()->ClearStatusBits(dwRemoved);
288   GetLayoutItem()->SetStatusBits(dwAdded);
289 }
290 
AsField()291 CXFA_FFField* CXFA_FFWidget::AsField() {
292   return nullptr;
293 }
294 
GetBBox(FocusOption focus)295 CFX_RectF CXFA_FFWidget::GetBBox(FocusOption focus) {
296   if (focus == kDrawFocus || !m_pPageView)
297     return CFX_RectF();
298   return m_pPageView->GetPageViewRect();
299 }
300 
RenderWidget(CXFA_Graphics * pGS,const CFX_Matrix & matrix,HighlightOption highlight)301 void CXFA_FFWidget::RenderWidget(CXFA_Graphics* pGS,
302                                  const CFX_Matrix& matrix,
303                                  HighlightOption highlight) {
304   if (!HasVisibleStatus())
305     return;
306 
307   CXFA_Border* border = m_pNode->GetBorderIfExists();
308   if (!border)
309     return;
310 
311   CFX_RectF rtBorder = GetRectWithoutRotate();
312   CXFA_Margin* margin = border->GetMarginIfExists();
313   XFA_RectWithoutMargin(&rtBorder, margin);
314   rtBorder.Normalize();
315   DrawBorder(pGS, border, rtBorder, matrix);
316 }
317 
IsLoaded()318 bool CXFA_FFWidget::IsLoaded() {
319   return !!m_pPageView;
320 }
321 
LoadWidget()322 bool CXFA_FFWidget::LoadWidget() {
323   PerformLayout();
324   return true;
325 }
326 
PerformLayout()327 bool CXFA_FFWidget::PerformLayout() {
328   RecacheWidgetRect();
329   return true;
330 }
331 
UpdateFWLData()332 bool CXFA_FFWidget::UpdateFWLData() {
333   return false;
334 }
335 
UpdateWidgetProperty()336 void CXFA_FFWidget::UpdateWidgetProperty() {}
337 
HasEventUnderHandler(XFA_EVENTTYPE eEventType,CXFA_FFWidgetHandler * pHandler)338 bool CXFA_FFWidget::HasEventUnderHandler(XFA_EVENTTYPE eEventType,
339                                          CXFA_FFWidgetHandler* pHandler) {
340   CXFA_Node* pNode = GetNode();
341   return pNode->IsWidgetReady() && pHandler->HasEvent(pNode, eEventType);
342 }
343 
ProcessEventUnderHandler(CXFA_EventParam * params,CXFA_FFWidgetHandler * pHandler)344 bool CXFA_FFWidget::ProcessEventUnderHandler(CXFA_EventParam* params,
345                                              CXFA_FFWidgetHandler* pHandler) {
346   CXFA_Node* pNode = GetNode();
347   if (!pNode->IsWidgetReady())
348     return false;
349 
350   params->m_pTarget = pNode;
351   return pHandler->ProcessEvent(pNode, params) == XFA_EventError::kSuccess;
352 }
353 
DrawBorder(CXFA_Graphics * pGS,CXFA_Box * box,const CFX_RectF & rtBorder,const CFX_Matrix & matrix)354 void CXFA_FFWidget::DrawBorder(CXFA_Graphics* pGS,
355                                CXFA_Box* box,
356                                const CFX_RectF& rtBorder,
357                                const CFX_Matrix& matrix) {
358   if (box)
359     box->Draw(pGS, rtBorder, matrix, false);
360 }
361 
DrawBorderWithFlag(CXFA_Graphics * pGS,CXFA_Box * box,const CFX_RectF & rtBorder,const CFX_Matrix & matrix,bool forceRound)362 void CXFA_FFWidget::DrawBorderWithFlag(CXFA_Graphics* pGS,
363                                        CXFA_Box* box,
364                                        const CFX_RectF& rtBorder,
365                                        const CFX_Matrix& matrix,
366                                        bool forceRound) {
367   if (box)
368     box->Draw(pGS, rtBorder, matrix, forceRound);
369 }
370 
InvalidateRect()371 void CXFA_FFWidget::InvalidateRect() {
372   CFX_RectF rtWidget = GetBBox(kDoNotDrawFocus);
373   rtWidget.Inflate(2, 2);
374   m_pDocView->InvalidateRect(m_pPageView.Get(), rtWidget);
375 }
376 
OnMouseEnter()377 bool CXFA_FFWidget::OnMouseEnter() {
378   return false;
379 }
380 
OnMouseExit()381 bool CXFA_FFWidget::OnMouseExit() {
382   return false;
383 }
384 
AcceptsFocusOnButtonDown(uint32_t dwFlags,const CFX_PointF & point,FWL_MouseCommand command)385 bool CXFA_FFWidget::AcceptsFocusOnButtonDown(uint32_t dwFlags,
386                                              const CFX_PointF& point,
387                                              FWL_MouseCommand command) {
388   return false;
389 }
390 
OnLButtonDown(uint32_t dwFlags,const CFX_PointF & point)391 bool CXFA_FFWidget::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
392   return false;
393 }
394 
OnLButtonUp(uint32_t dwFlags,const CFX_PointF & point)395 bool CXFA_FFWidget::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
396   return false;
397 }
398 
OnLButtonDblClk(uint32_t dwFlags,const CFX_PointF & point)399 bool CXFA_FFWidget::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
400   return false;
401 }
402 
OnMouseMove(uint32_t dwFlags,const CFX_PointF & point)403 bool CXFA_FFWidget::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) {
404   return false;
405 }
406 
OnMouseWheel(uint32_t dwFlags,int16_t zDelta,const CFX_PointF & point)407 bool CXFA_FFWidget::OnMouseWheel(uint32_t dwFlags,
408                                  int16_t zDelta,
409                                  const CFX_PointF& point) {
410   return false;
411 }
412 
OnRButtonDown(uint32_t dwFlags,const CFX_PointF & point)413 bool CXFA_FFWidget::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
414   return false;
415 }
416 
OnRButtonUp(uint32_t dwFlags,const CFX_PointF & point)417 bool CXFA_FFWidget::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
418   return false;
419 }
420 
OnRButtonDblClk(uint32_t dwFlags,const CFX_PointF & point)421 bool CXFA_FFWidget::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
422   return false;
423 }
424 
OnSetFocus(CXFA_FFWidget * pOldWidget)425 bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) {
426   // OnSetFocus event may remove this widget.
427   ObservedPtr<CXFA_FFWidget> pWatched(this);
428   CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
429   if (pParent && !pParent->IsAncestorOf(pOldWidget)) {
430     if (!pParent->OnSetFocus(pOldWidget))
431       return false;
432   }
433   if (!pWatched)
434     return false;
435 
436   GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_Focused);
437 
438   CXFA_EventParam eParam;
439   eParam.m_eType = XFA_EVENT_Enter;
440   eParam.m_pTarget = m_pNode.Get();
441   m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Enter, &eParam);
442 
443   return !!pWatched;
444 }
445 
OnKillFocus(CXFA_FFWidget * pNewWidget)446 bool CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) {
447   // OnKillFocus event may remove these widgets.
448   ObservedPtr<CXFA_FFWidget> pWatched(this);
449   ObservedPtr<CXFA_FFWidget> pNewWatched(pNewWidget);
450   GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_Focused);
451   EventKillFocus();
452   if (!pWatched)
453     return false;
454 
455   if (!pNewWidget)
456     return true;
457 
458   if (!pNewWatched)
459     return false;
460 
461   // OnKillFocus event may remove |pNewWidget|.
462   CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
463   if (pParent && !pParent->IsAncestorOf(pNewWidget)) {
464     if (!pParent->OnKillFocus(pNewWidget))
465       return false;
466   }
467   return pWatched && pNewWatched;
468 }
469 
OnKeyDown(uint32_t dwKeyCode,uint32_t dwFlags)470 bool CXFA_FFWidget::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) {
471   return false;
472 }
473 
OnKeyUp(uint32_t dwKeyCode,uint32_t dwFlags)474 bool CXFA_FFWidget::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) {
475   return false;
476 }
477 
OnChar(uint32_t dwChar,uint32_t dwFlags)478 bool CXFA_FFWidget::OnChar(uint32_t dwChar, uint32_t dwFlags) {
479   return false;
480 }
481 
HitTest(const CFX_PointF & point)482 FWL_WidgetHit CXFA_FFWidget::HitTest(const CFX_PointF& point) {
483   return FWL_WidgetHit::Unknown;
484 }
485 
OnSetCursor(const CFX_PointF & point)486 bool CXFA_FFWidget::OnSetCursor(const CFX_PointF& point) {
487   return false;
488 }
489 
CanUndo()490 bool CXFA_FFWidget::CanUndo() {
491   return false;
492 }
493 
CanRedo()494 bool CXFA_FFWidget::CanRedo() {
495   return false;
496 }
497 
Undo()498 bool CXFA_FFWidget::Undo() {
499   return false;
500 }
501 
Redo()502 bool CXFA_FFWidget::Redo() {
503   return false;
504 }
505 
CanCopy()506 bool CXFA_FFWidget::CanCopy() {
507   return false;
508 }
509 
CanCut()510 bool CXFA_FFWidget::CanCut() {
511   return false;
512 }
513 
CanPaste()514 bool CXFA_FFWidget::CanPaste() {
515   return false;
516 }
517 
CanSelectAll()518 bool CXFA_FFWidget::CanSelectAll() {
519   return false;
520 }
521 
CanDelete()522 bool CXFA_FFWidget::CanDelete() {
523   return CanCut();
524 }
525 
CanDeSelect()526 bool CXFA_FFWidget::CanDeSelect() {
527   return CanCopy();
528 }
529 
Copy()530 Optional<WideString> CXFA_FFWidget::Copy() {
531   return {};
532 }
533 
Cut()534 Optional<WideString> CXFA_FFWidget::Cut() {
535   return {};
536 }
537 
Paste(const WideString & wsPaste)538 bool CXFA_FFWidget::Paste(const WideString& wsPaste) {
539   return false;
540 }
541 
SelectAll()542 void CXFA_FFWidget::SelectAll() {}
543 
Delete()544 void CXFA_FFWidget::Delete() {}
545 
DeSelect()546 void CXFA_FFWidget::DeSelect() {}
547 
GetText()548 WideString CXFA_FFWidget::GetText() {
549   return WideString();
550 }
551 
GetFormFieldType()552 FormFieldType CXFA_FFWidget::GetFormFieldType() {
553   return FormFieldType::kXFA;
554 }
555 
Rotate2Normal(const CFX_PointF & point)556 CFX_PointF CXFA_FFWidget::Rotate2Normal(const CFX_PointF& point) {
557   CFX_Matrix mt = GetRotateMatrix();
558   if (mt.IsIdentity())
559     return point;
560 
561   return mt.GetInverse().Transform(point);
562 }
563 
GetRotateMatrix()564 CFX_Matrix CXFA_FFWidget::GetRotateMatrix() {
565   int32_t iRotate = m_pNode->GetRotate();
566   if (!iRotate)
567     return CFX_Matrix();
568 
569   CFX_RectF rcWidget = GetRectWithoutRotate();
570   CFX_Matrix mt;
571   switch (iRotate) {
572     case 90:
573       mt.a = 0;
574       mt.b = -1;
575       mt.c = 1;
576       mt.d = 0;
577       mt.e = rcWidget.left - rcWidget.top;
578       mt.f = rcWidget.left + rcWidget.top;
579       break;
580     case 180:
581       mt.a = -1;
582       mt.b = 0;
583       mt.c = 0;
584       mt.d = -1;
585       mt.e = rcWidget.left * 2;
586       mt.f = rcWidget.top * 2;
587       break;
588     case 270:
589       mt.a = 0;
590       mt.b = 1;
591       mt.c = -1;
592       mt.d = 0;
593       mt.e = rcWidget.left + rcWidget.top;
594       mt.f = rcWidget.top - rcWidget.left;
595       break;
596   }
597   return mt;
598 }
599 
DisplayCaret(bool bVisible,const CFX_RectF * pRtAnchor)600 void CXFA_FFWidget::DisplayCaret(bool bVisible, const CFX_RectF* pRtAnchor) {
601   IXFA_DocEnvironment* pDocEnvironment = GetDoc()->GetDocEnvironment();
602   if (!pDocEnvironment)
603     return;
604 
605   pDocEnvironment->DisplayCaret(this, bVisible, pRtAnchor);
606 }
607 
GetBorderColorAndThickness(FX_ARGB * cr,float * fWidth)608 void CXFA_FFWidget::GetBorderColorAndThickness(FX_ARGB* cr, float* fWidth) {
609   ASSERT(GetNode()->IsWidgetReady());
610   CXFA_Border* borderUI = GetNode()->GetUIBorder();
611   if (!borderUI)
612     return;
613 
614   CXFA_Edge* edge = borderUI->GetEdgeIfExists(0);
615   if (!edge)
616     return;
617 
618   *cr = edge->GetColor();
619   *fWidth = edge->GetThickness();
620 }
621 
IsLayoutRectEmpty()622 bool CXFA_FFWidget::IsLayoutRectEmpty() {
623   CFX_RectF rtLayout = GetRectWithoutRotate();
624   return rtLayout.width < 0.1f && rtLayout.height < 0.1f;
625 }
626 
GetParent()627 CXFA_LayoutItem* CXFA_FFWidget::GetParent() {
628   CXFA_Node* pParentNode = m_pNode->GetParent();
629   if (!pParentNode)
630     return nullptr;
631 
632   CXFA_LayoutProcessor* layout = GetDocView()->GetXFALayout();
633   return layout->GetLayoutItem(pParentNode);
634 }
635 
IsAncestorOf(CXFA_FFWidget * pWidget)636 bool CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) {
637   if (!pWidget)
638     return false;
639 
640   CXFA_Node* pChildNode = pWidget->GetNode();
641   while (pChildNode) {
642     if (pChildNode == m_pNode)
643       return true;
644 
645     pChildNode = pChildNode->GetParent();
646   }
647   return false;
648 }
649 
PtInActiveRect(const CFX_PointF & point)650 bool CXFA_FFWidget::PtInActiveRect(const CFX_PointF& point) {
651   return GetWidgetRect().Contains(point);
652 }
653 
GetDoc()654 CXFA_FFDoc* CXFA_FFWidget::GetDoc() {
655   return m_pDocView->GetDoc();
656 }
657 
GetApp()658 CXFA_FFApp* CXFA_FFWidget::GetApp() {
659   return GetDoc()->GetApp();
660 }
661 
GetAppProvider()662 IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() {
663   return GetApp()->GetAppProvider();
664 }
665 
HasVisibleStatus() const666 bool CXFA_FFWidget::HasVisibleStatus() const {
667   return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_Visible);
668 }
669 
EventKillFocus()670 void CXFA_FFWidget::EventKillFocus() {
671   CXFA_ContentLayoutItem* pItem = GetLayoutItem();
672   if (pItem->TestStatusBits(XFA_WidgetStatus_Access)) {
673     pItem->ClearStatusBits(XFA_WidgetStatus_Access);
674     return;
675   }
676   CXFA_EventParam eParam;
677   eParam.m_eType = XFA_EVENT_Exit;
678   eParam.m_pTarget = m_pNode.Get();
679   m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Exit, &eParam);
680 }
681 
IsButtonDown()682 bool CXFA_FFWidget::IsButtonDown() {
683   return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_ButtonDown);
684 }
685 
SetButtonDown(bool bSet)686 void CXFA_FFWidget::SetButtonDown(bool bSet) {
687   CXFA_ContentLayoutItem* pItem = GetLayoutItem();
688   if (bSet)
689     pItem->SetStatusBits(XFA_WidgetStatus_ButtonDown);
690   else
691     pItem->ClearStatusBits(XFA_WidgetStatus_ButtonDown);
692 }
693