text: // Copyright 2014 PDFium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
  
  #include "xfa/fxfa/cxfa_ffwidget.h"
  
  #include <algorithm>
  #include <memory>
  #include <utility>
  
  #include "core/fxcodec/fx_codec.h"
  #include "core/fxcodec/progressive_decoder.h"
  #include "core/fxcrt/maybe_owned.h"
  #include "core/fxge/cfx_fillrenderoptions.h"
  #include "core/fxge/cfx_path.h"
  #include "core/fxge/cfx_renderdevice.h"
  #include "core/fxge/dib/cfx_dibitmap.h"
  #include "third_party/base/check.h"
  #include "xfa/fgas/graphics/cfgas_gegraphics.h"
  #include "xfa/fwl/fwl_widgethit.h"
  #include "xfa/fxfa/cxfa_eventparam.h"
  #include "xfa/fxfa/cxfa_ffapp.h"
  #include "xfa/fxfa/cxfa_ffdoc.h"
  #include "xfa/fxfa/cxfa_ffdocview.h"
  #include "xfa/fxfa/cxfa_ffpageview.h"
  #include "xfa/fxfa/cxfa_ffwidgethandler.h"
  #include "xfa/fxfa/cxfa_imagerenderer.h"
  #include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
  #include "xfa/fxfa/parser/cxfa_border.h"
  #include "xfa/fxfa/parser/cxfa_box.h"
  #include "xfa/fxfa/parser/cxfa_edge.h"
  #include "xfa/fxfa/parser/cxfa_image.h"
  #include "xfa/fxfa/parser/cxfa_margin.h"
  #include "xfa/fxfa/parser/cxfa_node.h"
  
  namespace {
  
  FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,
                                int32_t iComponents,
                                int32_t iBitsPerComponent) {
    FXDIB_Format dibFormat = FXDIB_Format::kArgb;
    switch (type) {
      case FXCODEC_IMAGE_JPG:
  #ifdef PDF_ENABLE_XFA_BMP
      case FXCODEC_IMAGE_BMP:
  #endif  // PDF_ENABLE_XFA_BMP
  #ifdef PDF_ENABLE_XFA_TIFF
      case FXCODEC_IMAGE_TIFF:
  #endif  // PDF_ENABLE_XFA_TIFF
      {
        dibFormat = FXDIB_Format::kRgb32;
        int32_t bpp = iComponents * iBitsPerComponent;
        if (bpp <= 24) {
          dibFormat = FXDIB_Format::kRgb;
        }
      } break;
  #ifdef PDF_ENABLE_XFA_PNG
      case FXCODEC_IMAGE_PNG:
  #endif  // PDF_ENABLE_XFA_PNG
      default:
        break;
    }
    return dibFormat;
  }
  
  }  // namespace
  
  void XFA_DrawImage(CFGAS_GEGraphics* 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) {
    if (rtImage.IsEmpty())
      return;
    if (!pDIBitmap || !pDIBitmap->GetBuffer())
      return;
  
    CFX_RectF rtFit(rtImage.TopLeft(),
                    XFA_UnitPx2Pt(pDIBitmap->GetWidth(), dpi.width),
                    XFA_UnitPx2Pt(pDIBitmap->GetHeight(), dpi.height));
    switch (iAspect) {
      case XFA_AttributeValue::Fit: {
        float f1 = rtImage.height / rtFit.height;
        float f2 = rtImage.width / rtFit.width;
        f1 = std::min(f1, f2);
        rtFit.height = rtFit.height * f1;
        rtFit.width = rtFit.width * f1;
        break;
      }
      case XFA_AttributeValue::Height: {
        float f1 = rtImage.height / rtFit.height;
        rtFit.height = rtImage.height;
        rtFit.width = f1 * rtFit.width;
        break;
      }
      case XFA_AttributeValue::None:
        rtFit.height = rtImage.height;
        rtFit.width = rtImage.width;
        break;
      case XFA_AttributeValue::Width: {
        float f1 = rtImage.width / rtFit.width;
        rtFit.width = rtImage.width;
        rtFit.height = rtFit.height * f1;
        break;
      }
      case XFA_AttributeValue::Actual:
      default:
        break;
    }
  
    if (iHorzAlign == XFA_AttributeValue::Center)
      rtFit.left += (rtImage.width - rtFit.width) / 2;
    else if (iHorzAlign == XFA_AttributeValue::Right)
      rtFit.left = rtImage.right() - rtFit.width;
  
    if (iVertAlign == XFA_AttributeValue::Middle)
      rtFit.top += (rtImage.height - rtFit.height) / 2;
    else if (iVertAlign == XFA_AttributeValue::Bottom)
      rtFit.top = rtImage.bottom() - rtImage.height;
  
    CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
    CFX_RenderDevice::StateRestorer restorer(pRenderDevice);
    CFX_Path path;
    path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top);
    pRenderDevice->SetClip_PathFill(path, &matrix,
                                    CFX_FillRenderOptions::WindingOptions());
  
    CFX_Matrix mtImage(1, 0, 0, -1, 0, 1);
    mtImage.Concat(
        CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top));
    mtImage.Concat(matrix);
  
    CXFA_ImageRenderer imageRender(pRenderDevice, pDIBitmap, mtImage);
    if (!imageRender.Start()) {
      return;
    }
    while (imageRender.Continue())
      continue;
  }
  
  RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer(
      const RetainPtr<IFX_SeekableReadStream>& pImageFileRead,
      FXCODEC_IMAGE_TYPE type,
      int32_t& iImageXDpi,
      int32_t& iImageYDpi) {
    auto pProgressiveDecoder = std::make_unique<ProgressiveDecoder>();
  
    CFX_DIBAttribute dibAttr;
    pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false);
    switch (dibAttr.m_wDPIUnit) {
      case CFX_DIBAttribute::kResUnitCentimeter:
        dibAttr.m_nXDPI = static_cast<int32_t>(dibAttr.m_nXDPI * 2.54f);
        dibAttr.m_nYDPI = static_cast<int32_t>(dibAttr.m_nYDPI * 2.54f);
        break;
      case CFX_DIBAttribute::kResUnitMeter:
        dibAttr.m_nXDPI =
            static_cast<int32_t>(dibAttr.m_nXDPI / (float)100 * 2.54f);
        dibAttr.m_nYDPI =
            static_cast<int32_t>(dibAttr.m_nYDPI / (float)100 * 2.54f);
        break;
      default:
        break;
    }
    iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96);
    iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96);
    if (pProgressiveDecoder->GetWidth() <= 0 ||
        pProgressiveDecoder->GetHeight() <= 0) {
      return nullptr;
    }
  
    type = pProgressiveDecoder->GetType();
    int32_t iComponents = pProgressiveDecoder->GetNumComponents();
    int32_t iBpc = pProgressiveDecoder->GetBPC();
    FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc);
    RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
    pBitmap->Create(pProgressiveDecoder->GetWidth(),
                    pProgressiveDecoder->GetHeight(), dibFormat);
    pBitmap->Clear(0xffffffff);
  
    size_t nFrames;
    FXCODEC_STATUS status;
    std::tie(status, nFrames) = pProgressiveDecoder->GetFrames();
    if (status != FXCODEC_STATUS::kDecodeReady || nFrames == 0)
      return nullptr;
  
    status = pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(),
                                              pBitmap->GetHeight());
    if (status == FXCODEC_STATUS::kError)
      return nullptr;
  
    while (status == FXCODEC_STATUS::kDecodeToBeContinued) {
      status = pProgressiveDecoder->ContinueDecode();
      if (status == FXCODEC_STATUS::kError)
        return nullptr;
    }
  
    return pBitmap;
  }
  
  void XFA_RectWithoutMargin(CFX_RectF* rt, const CXFA_Margin* margin) {
    if (!margin)
      return;
  
    rt->Deflate(margin->GetLeftInset(), margin->GetTopInset(),
                margin->GetRightInset(), margin->GetBottomInset());
  }
  
  // static
  CXFA_FFWidget* CXFA_FFWidget::FromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
    if (!pLayoutItem->GetFormNode()->HasCreatedUIWidget())
      return nullptr;
  
    return GetFFWidget(ToContentLayoutItem(pLayoutItem));
  }
  
  CXFA_FFWidget::CXFA_FFWidget(CXFA_Node* node) : m_pNode(node) {}
  
  CXFA_FFWidget::~CXFA_FFWidget() = default;
  
  void CXFA_FFWidget::Trace(cppgc::Visitor* visitor) const {
    visitor->Trace(m_pLayoutItem);
    visitor->Trace(m_pDocView);
    visitor->Trace(m_pPageView);
    visitor->Trace(m_pNode);
  }
  
  CFWL_App* CXFA_FFWidget::GetFWLApp() const {
    return GetPageView()->GetDocView()->GetDoc()->GetApp()->GetFWLApp();
  }
  
  CXFA_FFWidget* CXFA_FFWidget::GetNextFFWidget() const {
    return GetFFWidget(GetLayoutItem()->GetNext());
  }
  
  const CFX_RectF& CXFA_FFWidget::GetWidgetRect() const {
    if (!GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kRectCached))
      RecacheWidgetRect();
    return m_WidgetRect;
  }
  
  const CFX_RectF& CXFA_FFWidget::RecacheWidgetRect() const {
    GetLayoutItem()->SetStatusBits(XFA_WidgetStatus::kRectCached);
    m_WidgetRect = GetLayoutItem()->GetAbsoluteRect();
    return m_WidgetRect;
  }
  
  CFX_RectF CXFA_FFWidget::GetRectWithoutRotate() {
    CFX_RectF rtWidget = GetWidgetRect();
    float fValue = 0;
    switch (m_pNode->GetRotate()) {
      case 90:
        rtWidget.top = rtWidget.bottom();
        fValue = rtWidget.width;
        rtWidget.width = rtWidget.height;
        rtWidget.height = fValue;
        break;
      case 180:
        rtWidget.left = rtWidget.right();
        rtWidget.top = rtWidget.bottom();
        break;
      case 270:
        rtWidget.left = rtWidget.right();
        fValue = rtWidget.width;
        rtWidget.width = rtWidget.height;
        rtWidget.height = fValue;
        break;
    }
    return rtWidget;
  }
  
  void CXFA_FFWidget::ModifyStatus(Mask<XFA_WidgetStatus> dwAdded,
                                   Mask<XFA_WidgetStatus> dwRemoved) {
    GetLayoutItem()->ClearStatusBits(dwRemoved);
    GetLayoutItem()->SetStatusBits(dwAdded);
  }
  
  CXFA_FFField* CXFA_FFWidget::AsField() {
    return nullptr;
  }
  
  CFX_RectF CXFA_FFWidget::GetBBox(FocusOption focus) {
    if (focus == kDrawFocus || !m_pPageView)
      return CFX_RectF();
    return m_pPageView->GetPageViewRect();
  }
  
  void CXFA_FFWidget::RenderWidget(CFGAS_GEGraphics* pGS,
                                   const CFX_Matrix& matrix,
                                   HighlightOption highlight) {
    if (!HasVisibleStatus())
      return;
  
    CXFA_Border* border = m_pNode->GetBorderIfExists();
    if (!border)
      return;
  
    CFX_RectF rtBorder = GetRectWithoutRotate();
    CXFA_Margin* margin = border->GetMarginIfExists();
    XFA_RectWithoutMargin(&rtBorder, margin);
    rtBorder.Normalize();
    DrawBorder(pGS, border, rtBorder, matrix);
  }
  
  bool CXFA_FFWidget::IsLoaded() {
    return !!m_pPageView;
  }
  
  bool CXFA_FFWidget::LoadWidget() {
    PerformLayout();
    return true;
  }
  
  bool CXFA_FFWidget::PerformLayout() {
    RecacheWidgetRect();
    return true;
  }
  
  bool CXFA_FFWidget::UpdateFWLData() {
    return false;
  }
  
  void CXFA_FFWidget::UpdateWidgetProperty() {}
  
  bool CXFA_FFWidget::HasEventUnderHandler(XFA_EVENTTYPE eEventType,
                                           CXFA_FFWidgetHandler* pHandler) {
    CXFA_Node* pNode = GetNode();
    return pNode->IsWidgetReady() && pHandler->HasEvent(pNode, eEventType);
  }
  
  bool CXFA_FFWidget::ProcessEventUnderHandler(CXFA_EventParam* params,
                                               CXFA_FFWidgetHandler* pHandler) {
    CXFA_Node* pNode = GetNode();
    if (!pNode->IsWidgetReady())
      return false;
  
    params->m_pTarget = pNode;
    return pHandler->ProcessEvent(pNode, params) == XFA_EventError::kSuccess;
  }
  
  void CXFA_FFWidget::DrawBorder(CFGAS_GEGraphics* pGS,
                                 CXFA_Box* box,
                                 const CFX_RectF& rtBorder,
                                 const CFX_Matrix& matrix) {
    if (box)
      box->Draw(pGS, rtBorder, matrix, false);
  }
  
  void CXFA_FFWidget::DrawBorderWithFlag(CFGAS_GEGraphics* pGS,
                                         CXFA_Box* box,
                                         const CFX_RectF& rtBorder,
                                         const CFX_Matrix& matrix,
                                         bool forceRound) {
    if (box)
      box->Draw(pGS, rtBorder, matrix, forceRound);
  }
  
  void CXFA_FFWidget::InvalidateRect() {
    CFX_RectF rtWidget = GetBBox(kDoNotDrawFocus);
    rtWidget.Inflate(2, 2);
    m_pDocView->InvalidateRect(m_pPageView.Get(), rtWidget);
  }
  
  bool CXFA_FFWidget::OnMouseEnter() {
    return false;
  }
  
  bool CXFA_FFWidget::OnMouseExit() {
    return false;
  }
  
  bool CXFA_FFWidget::AcceptsFocusOnButtonDown(
      Mask<XFA_FWL_KeyFlag> dwFlags,
      const CFX_PointF& point,
      CFWL_MessageMouse::MouseCommand command) {
    return false;
  }
  
  bool CXFA_FFWidget::OnLButtonDown(Mask<XFA_FWL_KeyFlag> dwFlags,
                                    const CFX_PointF& point) {
    return false;
  }
  
  bool CXFA_FFWidget::OnLButtonUp(Mask<XFA_FWL_KeyFlag> dwFlags,
                                  const CFX_PointF& point) {
    return false;
  }
  
  bool CXFA_FFWidget::OnLButtonDblClk(Mask<XFA_FWL_KeyFlag> dwFlags,
                                      const CFX_PointF& point) {
    return false;
  }
  
  bool CXFA_FFWidget::OnMouseMove(Mask<XFA_FWL_KeyFlag> dwFlags,
                                  const CFX_PointF& point) {
    return false;
  }
  
  bool CXFA_FFWidget::OnMouseWheel(Mask<XFA_FWL_KeyFlag> dwFlags,
                                   const CFX_PointF& point,
                                   const CFX_Vector& delta) {
    return false;
  }
  
  bool CXFA_FFWidget::OnRButtonDown(Mask<XFA_FWL_KeyFlag> dwFlags,
                                    const CFX_PointF& point) {
    return false;
  }
  
  bool CXFA_FFWidget::OnRButtonUp(Mask<XFA_FWL_KeyFlag> dwFlags,
                                  const CFX_PointF& point) {
    return false;
  }
  
  bool CXFA_FFWidget::OnRButtonDblClk(Mask<XFA_FWL_KeyFlag> dwFlags,
                                      const CFX_PointF& point) {
    return false;
  }
  
  bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) {
    CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
    if (pParent && !pParent->IsAncestorOf(pOldWidget)) {
      if (!pParent->OnSetFocus(pOldWidget))
        return false;
    }
    GetLayoutItem()->SetStatusBits(XFA_WidgetStatus::kFocused);
  
    CXFA_EventParam eParam;
    eParam.m_eType = XFA_EVENT_Enter;
    eParam.m_pTarget = m_pNode.Get();
    m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Enter, &eParam);
    return true;
  }
  
  bool CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) {
    GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus::kFocused);
    EventKillFocus();
    if (!pNewWidget)
      return true;
  
    CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
    if (pParent && !pParent->IsAncestorOf(pNewWidget)) {
      if (!pParent->OnKillFocus(pNewWidget))
        return false;
    }
    return true;
  }
  
  bool CXFA_FFWidget::OnKeyDown(XFA_FWL_VKEYCODE dwKeyCode,
                                Mask<XFA_FWL_KeyFlag> dwFlags) {
    return false;
  }
  
  bool CXFA_FFWidget::OnChar(uint32_t dwChar, Mask<XFA_FWL_KeyFlag> dwFlags) {
    return false;
  }
  
  FWL_WidgetHit CXFA_FFWidget::HitTest(const CFX_PointF& point) {
    return FWL_WidgetHit::Unknown;
  }
  
  bool CXFA_FFWidget::CanUndo() {
    return false;
  }
  
  bool CXFA_FFWidget::CanRedo() {
    return false;
  }
  
  bool CXFA_FFWidget::CanCopy() {
    return false;
  }
  
  bool CXFA_FFWidget::CanCut() {
    return false;
  }
  
  bool CXFA_FFWidget::CanPaste() {
    return false;
  }
  
  bool CXFA_FFWidget::CanSelectAll() {
    return false;
  }
  
  bool CXFA_FFWidget::CanDelete() {
    return CanCut();
  }
  
  bool CXFA_FFWidget::CanDeSelect() {
    return CanCopy();
  }
  
  bool CXFA_FFWidget::Undo() {
    return false;
  }
  
  bool CXFA_FFWidget::Redo() {
    return false;
  }
  
  absl::optional<WideString> CXFA_FFWidget::Copy() {
    return absl::nullopt;
  }
  
  absl::optional<WideString> CXFA_FFWidget::Cut() {
    return absl::nullopt;
  }
  
  bool CXFA_FFWidget::Paste(const WideString& wsPaste) {
    return false;
  }
  
  void CXFA_FFWidget::SelectAll() {}
  
  void CXFA_FFWidget::Delete() {}
  
  void CXFA_FFWidget::DeSelect() {}
  
  WideString CXFA_FFWidget::GetText() {
    return WideString();
  }
  
  FormFieldType CXFA_FFWidget::GetFormFieldType() {
    return FormFieldType::kXFA;
  }
  
  CFX_PointF CXFA_FFWidget::Rotate2Normal(const CFX_PointF& point) {
    CFX_Matrix mt = GetRotateMatrix();
    if (mt.IsIdentity())
      return point;
  
    return mt.GetInverse().Transform(point);
  }
  
  CFX_Matrix CXFA_FFWidget::GetRotateMatrix() {
    int32_t iRotate = m_pNode->GetRotate();
    if (!iRotate)
      return CFX_Matrix();
  
    CFX_RectF rcWidget = GetRectWithoutRotate();
    CFX_Matrix mt;
    switch (iRotate) {
      case 90:
        mt.a = 0;
        mt.b = -1;
        mt.c = 1;
        mt.d = 0;
        mt.e = rcWidget.left - rcWidget.top;
        mt.f = rcWidget.left + rcWidget.top;
        break;
      case 180:
        mt.a = -1;
        mt.b = 0;
        mt.c = 0;
        mt.d = -1;
        mt.e = rcWidget.left * 2;
        mt.f = rcWidget.top * 2;
        break;
      case 270:
        mt.a = 0;
        mt.b = 1;
        mt.c = -1;
        mt.d = 0;
        mt.e = rcWidget.left + rcWidget.top;
        mt.f = rcWidget.top - rcWidget.left;
        break;
    }
    return mt;
  }
  
  void CXFA_FFWidget::DisplayCaret(bool bVisible, const CFX_RectF* pRtAnchor) {
    GetDoc()->DisplayCaret(this, bVisible, pRtAnchor);
  }
  
  void CXFA_FFWidget::GetBorderColorAndThickness(FX_ARGB* cr, float* fWidth) {
    DCHECK(GetNode()->IsWidgetReady());
    CXFA_Border* borderUI = GetNode()->GetUIBorder();
    if (!borderUI)
      return;
  
    CXFA_Edge* edge = borderUI->GetEdgeIfExists(0);
    if (!edge)
      return;
  
    *cr = edge->GetColor();
    *fWidth = edge->GetThickness();
  }
  
  bool CXFA_FFWidget::IsLayoutRectEmpty() {
    CFX_RectF rtLayout = GetRectWithoutRotate();
    return rtLayout.width < 0.1f && rtLayout.height < 0.1f;
  }
  
  CXFA_LayoutItem* CXFA_FFWidget::GetParent() {
    CXFA_Node* pParentNode = m_pNode->GetParent();
    if (!pParentNode)
      return nullptr;
  
    CXFA_LayoutProcessor* layout = GetDocView()->GetLayoutProcessor();
    return layout->GetLayoutItem(pParentNode);
  }
  
  bool CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) {
    if (!pWidget)
      return false;
  
    CXFA_Node* pChildNode = pWidget->GetNode();
    while (pChildNode) {
      if (pChildNode == m_pNode)
        return true;
  
      pChildNode = pChildNode->GetParent();
    }
    return false;
  }
  
  bool CXFA_FFWidget::PtInActiveRect(const CFX_PointF& point) {
    return GetWidgetRect().Contains(point);
  }
  
  CXFA_FFDoc* CXFA_FFWidget::GetDoc() {
    return m_pDocView->GetDoc();
  }
  
  CXFA_FFApp* CXFA_FFWidget::GetApp() {
    return GetDoc()->GetApp();
  }
  
  CXFA_FFApp::CallbackIface* CXFA_FFWidget::GetAppProvider() {
    return GetApp()->GetAppProvider();
  }
  
  bool CXFA_FFWidget::HasVisibleStatus() const {
    return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kVisible);
  }
  
  void CXFA_FFWidget::EventKillFocus() {
    CXFA_ContentLayoutItem* pItem = GetLayoutItem();
    if (pItem->TestStatusBits(XFA_WidgetStatus::kAccess)) {
      pItem->ClearStatusBits(XFA_WidgetStatus::kAccess);
      return;
    }
    CXFA_EventParam eParam;
    eParam.m_eType = XFA_EVENT_Exit;
    eParam.m_pTarget = m_pNode.Get();
    m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Exit, &eParam);
  }
  
  bool CXFA_FFWidget::IsButtonDown() {
    return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kButtonDown);
  }
  
  void CXFA_FFWidget::SetButtonDown(bool bSet) {
    CXFA_ContentLayoutItem* pItem = GetLayoutItem();
    if (bSet)
      pItem->SetStatusBits(XFA_WidgetStatus::kButtonDown);
    else
      pItem->ClearStatusBits(XFA_WidgetStatus::kButtonDown);
  }
  