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