Home | History | Annotate | Download | only in fwl
      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/fwl/cfwl_widgetmgr.h"
      8 
      9 #include <utility>
     10 
     11 #include "third_party/base/ptr_util.h"
     12 #include "xfa/fwl/cfwl_app.h"
     13 #include "xfa/fwl/cfwl_form.h"
     14 #include "xfa/fwl/cfwl_notedriver.h"
     15 #include "xfa/fxfa/cxfa_ffapp.h"
     16 #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
     17 
     18 namespace {
     19 
     20 const int kNeedRepaintHitPoints = 12;
     21 const int kNeedRepaintHitPiece = 3;
     22 
     23 struct FWL_NEEDREPAINTHITDATA {
     24   CFX_PointF hitPoint;
     25   bool bNotNeedRepaint;
     26   bool bNotContainByDirty;
     27 };
     28 
     29 }  // namespace
     30 
     31 CFWL_WidgetMgr::CFWL_WidgetMgr(CXFA_FFApp* pAdapterNative)
     32     : m_dwCapability(FWL_WGTMGR_DisableForm),
     33       m_pAdapter(pAdapterNative->GetFWLAdapterWidgetMgr()) {
     34   ASSERT(m_pAdapter);
     35   m_mapWidgetItem[nullptr] = pdfium::MakeUnique<Item>();
     36 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
     37   m_rtScreen.Reset();
     38 #endif  // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
     39 }
     40 
     41 CFWL_WidgetMgr::~CFWL_WidgetMgr() {}
     42 
     43 CFWL_Widget* CFWL_WidgetMgr::GetParentWidget(CFWL_Widget* pWidget) const {
     44   Item* pItem = GetWidgetMgrItem(pWidget);
     45   return pItem && pItem->pParent ? pItem->pParent->pWidget : nullptr;
     46 }
     47 
     48 CFWL_Widget* CFWL_WidgetMgr::GetOwnerWidget(CFWL_Widget* pWidget) const {
     49   Item* pItem = GetWidgetMgrItem(pWidget);
     50   return pItem && pItem->pOwner ? pItem->pOwner->pWidget : nullptr;
     51 }
     52 
     53 CFWL_Widget* CFWL_WidgetMgr::GetFirstSiblingWidget(CFWL_Widget* pWidget) const {
     54   Item* pItem = GetWidgetMgrItem(pWidget);
     55   if (!pItem)
     56     return nullptr;
     57 
     58   pItem = pItem->pPrevious;
     59   while (pItem && pItem->pPrevious)
     60     pItem = pItem->pPrevious;
     61   return pItem ? pItem->pWidget : nullptr;
     62 }
     63 
     64 CFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(CFWL_Widget* pWidget) const {
     65   Item* pItem = GetWidgetMgrItem(pWidget);
     66   return pItem && pItem->pPrevious ? pItem->pPrevious->pWidget : nullptr;
     67 }
     68 
     69 CFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(CFWL_Widget* pWidget) const {
     70   Item* pItem = GetWidgetMgrItem(pWidget);
     71   return pItem && pItem->pNext ? pItem->pNext->pWidget : nullptr;
     72 }
     73 
     74 CFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(CFWL_Widget* pWidget) const {
     75   Item* pItem = GetWidgetMgrItem(pWidget);
     76   return pItem && pItem->pChild ? pItem->pChild->pWidget : nullptr;
     77 }
     78 
     79 CFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(CFWL_Widget* pWidget) const {
     80   Item* pItem = GetWidgetMgrItem(pWidget);
     81   if (!pItem)
     82     return nullptr;
     83 
     84   pItem = pItem->pChild;
     85   while (pItem && pItem->pNext)
     86     pItem = pItem->pNext;
     87   return pItem ? pItem->pWidget : nullptr;
     88 }
     89 
     90 CFWL_Widget* CFWL_WidgetMgr::GetSystemFormWidget(CFWL_Widget* pWidget) const {
     91   Item* pItem = GetWidgetMgrItem(pWidget);
     92   while (pItem) {
     93     if (IsAbleNative(pItem->pWidget))
     94       return pItem->pWidget;
     95     pItem = pItem->pParent;
     96   }
     97   return nullptr;
     98 }
     99 
    100 void CFWL_WidgetMgr::AppendWidget(CFWL_Widget* pWidget) {
    101   Item* pItem = GetWidgetMgrItem(pWidget);
    102   if (!pItem)
    103     return;
    104   if (!pItem->pParent)
    105     return;
    106 
    107   Item* pChild = pItem->pParent->pChild;
    108   int32_t i = 0;
    109   while (pChild) {
    110     if (pChild == pItem) {
    111       if (pChild->pPrevious)
    112         pChild->pPrevious->pNext = pChild->pNext;
    113       if (pChild->pNext)
    114         pChild->pNext->pPrevious = pChild->pPrevious;
    115       if (pItem->pParent->pChild == pItem)
    116         pItem->pParent->pChild = pItem->pNext;
    117 
    118       pItem->pNext = nullptr;
    119       pItem->pPrevious = nullptr;
    120       break;
    121     }
    122     if (!pChild->pNext)
    123       break;
    124 
    125     pChild = pChild->pNext;
    126     ++i;
    127   }
    128 
    129   pChild = pItem->pParent->pChild;
    130   if (pChild) {
    131     while (pChild->pNext)
    132       pChild = pChild->pNext;
    133 
    134     pChild->pNext = pItem;
    135     pItem->pPrevious = pChild;
    136   } else {
    137     pItem->pParent->pChild = pItem;
    138     pItem->pPrevious = nullptr;
    139   }
    140   pItem->pNext = nullptr;
    141 }
    142 
    143 void CFWL_WidgetMgr::RepaintWidget(CFWL_Widget* pWidget,
    144                                    const CFX_RectF& rect) {
    145   if (!m_pAdapter)
    146     return;
    147 
    148   CFWL_Widget* pNative = pWidget;
    149   CFX_RectF transformedRect = rect;
    150   if (IsFormDisabled()) {
    151     CFWL_Widget* pOuter = pWidget->GetOuter();
    152     while (pOuter) {
    153       CFX_RectF rtTemp = pNative->GetWidgetRect();
    154       transformedRect.left += rtTemp.left;
    155       transformedRect.top += rtTemp.top;
    156       pNative = pOuter;
    157       pOuter = pOuter->GetOuter();
    158     }
    159   } else if (!IsAbleNative(pWidget)) {
    160     pNative = GetSystemFormWidget(pWidget);
    161     if (!pNative)
    162       return;
    163 
    164     CFX_PointF pos = pWidget->TransformTo(
    165         pNative, CFX_PointF(transformedRect.left, transformedRect.top));
    166     transformedRect.left = pos.x;
    167     transformedRect.top = pos.y;
    168   }
    169   AddRedrawCounts(pNative);
    170   m_pAdapter->RepaintWidget(pNative);
    171 }
    172 
    173 void CFWL_WidgetMgr::InsertWidget(CFWL_Widget* pParent, CFWL_Widget* pChild) {
    174   Item* pParentItem = GetWidgetMgrItem(pParent);
    175   if (!pParentItem) {
    176     auto item = pdfium::MakeUnique<Item>(pParent);
    177     pParentItem = item.get();
    178     m_mapWidgetItem[pParent] = std::move(item);
    179 
    180     pParentItem->pParent = GetWidgetMgrItem(nullptr);
    181     AppendWidget(pParent);
    182   }
    183 
    184   Item* pItem = GetWidgetMgrItem(pChild);
    185   if (!pItem) {
    186     auto item = pdfium::MakeUnique<Item>(pChild);
    187     pItem = item.get();
    188     m_mapWidgetItem[pChild] = std::move(item);
    189   }
    190   if (pItem->pParent && pItem->pParent != pParentItem) {
    191     if (pItem->pPrevious)
    192       pItem->pPrevious->pNext = pItem->pNext;
    193     if (pItem->pNext)
    194       pItem->pNext->pPrevious = pItem->pPrevious;
    195     if (pItem->pParent->pChild == pItem)
    196       pItem->pParent->pChild = pItem->pNext;
    197   }
    198   pItem->pParent = pParentItem;
    199   AppendWidget(pChild);
    200 }
    201 
    202 void CFWL_WidgetMgr::RemoveWidget(CFWL_Widget* pWidget) {
    203   Item* pItem = GetWidgetMgrItem(pWidget);
    204   if (!pItem)
    205     return;
    206   if (pItem->pPrevious)
    207     pItem->pPrevious->pNext = pItem->pNext;
    208   if (pItem->pNext)
    209     pItem->pNext->pPrevious = pItem->pPrevious;
    210   if (pItem->pParent && pItem->pParent->pChild == pItem)
    211     pItem->pParent->pChild = pItem->pNext;
    212 
    213   Item* pChild = pItem->pChild;
    214   while (pChild) {
    215     Item* pNext = pChild->pNext;
    216     RemoveWidget(pChild->pWidget);
    217     pChild = pNext;
    218   }
    219   m_mapWidgetItem.erase(pWidget);
    220 }
    221 
    222 void CFWL_WidgetMgr::SetOwner(CFWL_Widget* pOwner, CFWL_Widget* pOwned) {
    223   Item* pParentItem = GetWidgetMgrItem(pOwner);
    224   if (!pParentItem) {
    225     auto item = pdfium::MakeUnique<Item>(pOwner);
    226     pParentItem = item.get();
    227     m_mapWidgetItem[pOwner] = std::move(item);
    228 
    229     pParentItem->pParent = GetWidgetMgrItem(nullptr);
    230     AppendWidget(pOwner);
    231   }
    232 
    233   Item* pItem = GetWidgetMgrItem(pOwned);
    234   if (!pItem) {
    235     auto item = pdfium::MakeUnique<Item>(pOwned);
    236     pItem = item.get();
    237     m_mapWidgetItem[pOwned] = std::move(item);
    238   }
    239   pItem->pOwner = pParentItem;
    240 }
    241 void CFWL_WidgetMgr::SetParent(CFWL_Widget* pParent, CFWL_Widget* pChild) {
    242   Item* pParentItem = GetWidgetMgrItem(pParent);
    243   Item* pItem = GetWidgetMgrItem(pChild);
    244   if (!pItem)
    245     return;
    246   if (pItem->pParent && pItem->pParent != pParentItem) {
    247     if (pItem->pPrevious)
    248       pItem->pPrevious->pNext = pItem->pNext;
    249     if (pItem->pNext)
    250       pItem->pNext->pPrevious = pItem->pPrevious;
    251     if (pItem->pParent->pChild == pItem)
    252       pItem->pParent->pChild = pItem->pNext;
    253 
    254     pItem->pNext = nullptr;
    255     pItem->pPrevious = nullptr;
    256   }
    257   pItem->pParent = pParentItem;
    258   AppendWidget(pChild);
    259 }
    260 
    261 CFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(CFWL_Widget* parent,
    262                                               const CFX_PointF& point) const {
    263   if (!parent)
    264     return nullptr;
    265 
    266   CFX_PointF pos;
    267   CFWL_Widget* child = GetLastChildWidget(parent);
    268   while (child) {
    269     if ((child->GetStates() & FWL_WGTSTATE_Invisible) == 0) {
    270       pos = parent->GetMatrix().GetInverse().Transform(point);
    271 
    272       CFX_RectF bounds = child->GetWidgetRect();
    273       if (bounds.Contains(pos)) {
    274         pos -= bounds.TopLeft();
    275         return GetWidgetAtPoint(child, pos);
    276       }
    277     }
    278     child = GetPriorSiblingWidget(child);
    279   }
    280   return parent;
    281 }
    282 
    283 CFWL_Widget* CFWL_WidgetMgr::NextTab(CFWL_Widget* parent,
    284                                      CFWL_Widget* focus,
    285                                      bool& bFind) {
    286   CFWL_WidgetMgr* pMgr = parent->GetOwnerApp()->GetWidgetMgr();
    287   CFWL_Widget* child = pMgr->GetFirstChildWidget(parent);
    288   while (child) {
    289     if (focus == child)
    290       bFind = true;
    291 
    292     CFWL_Widget* bRet = NextTab(child, focus, bFind);
    293     if (bRet)
    294       return bRet;
    295 
    296     child = pMgr->GetNextSiblingWidget(child);
    297   }
    298   return nullptr;
    299 }
    300 
    301 int32_t CFWL_WidgetMgr::CountRadioButtonGroup(CFWL_Widget* pFirst) const {
    302   int32_t iRet = 0;
    303   CFWL_Widget* pChild = pFirst;
    304   while (pChild) {
    305     pChild = GetNextSiblingWidget(pChild);
    306     ++iRet;
    307   }
    308   return iRet;
    309 }
    310 
    311 CFWL_Widget* CFWL_WidgetMgr::GetRadioButtonGroupHeader(
    312     CFWL_Widget* pRadioButton) const {
    313   CFWL_Widget* pNext = pRadioButton;
    314   if (pNext && (pNext->GetStyles() & FWL_WGTSTYLE_Group))
    315     return pNext;
    316   return nullptr;
    317 }
    318 
    319 std::vector<CFWL_Widget*> CFWL_WidgetMgr::GetSameGroupRadioButton(
    320     CFWL_Widget* pRadioButton) const {
    321   CFWL_Widget* pFirst = GetFirstSiblingWidget(pRadioButton);
    322   if (!pFirst)
    323     pFirst = pRadioButton;
    324 
    325   if (CountRadioButtonGroup(pFirst) < 2)
    326     return std::vector<CFWL_Widget*>();
    327 
    328   std::vector<CFWL_Widget*> group;
    329   group.push_back(GetRadioButtonGroupHeader(pRadioButton));
    330   return group;
    331 }
    332 
    333 CFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(CFWL_Widget* pParent) const {
    334   if ((pParent->GetClassID() == FWL_Type::PushButton) &&
    335       (pParent->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
    336     return pParent;
    337   }
    338 
    339   CFWL_Widget* child =
    340       pParent->GetOwnerApp()->GetWidgetMgr()->GetFirstChildWidget(pParent);
    341   while (child) {
    342     if ((child->GetClassID() == FWL_Type::PushButton) &&
    343         (child->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
    344       return child;
    345     }
    346     if (CFWL_Widget* find = GetDefaultButton(child))
    347       return find;
    348 
    349     child = child->GetOwnerApp()->GetWidgetMgr()->GetNextSiblingWidget(child);
    350   }
    351   return nullptr;
    352 }
    353 
    354 void CFWL_WidgetMgr::AddRedrawCounts(CFWL_Widget* pWidget) {
    355   GetWidgetMgrItem(pWidget)->iRedrawCounter++;
    356 }
    357 
    358 void CFWL_WidgetMgr::ResetRedrawCounts(CFWL_Widget* pWidget) {
    359   GetWidgetMgrItem(pWidget)->iRedrawCounter = 0;
    360 }
    361 
    362 CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrItem(
    363     CFWL_Widget* pWidget) const {
    364   auto it = m_mapWidgetItem.find(pWidget);
    365   return it != m_mapWidgetItem.end() ? static_cast<Item*>(it->second.get())
    366                                      : nullptr;
    367 }
    368 
    369 bool CFWL_WidgetMgr::IsAbleNative(CFWL_Widget* pWidget) const {
    370   if (!pWidget)
    371     return false;
    372   if (!pWidget->IsInstance(FWL_CLASS_Form))
    373     return false;
    374 
    375   uint32_t dwStyles = pWidget->GetStyles();
    376   return ((dwStyles & FWL_WGTSTYLE_WindowTypeMask) ==
    377           FWL_WGTSTYLE_OverLapper) ||
    378          (dwStyles & FWL_WGTSTYLE_Popup);
    379 }
    380 
    381 void CFWL_WidgetMgr::GetAdapterPopupPos(CFWL_Widget* pWidget,
    382                                         float fMinHeight,
    383                                         float fMaxHeight,
    384                                         const CFX_RectF& rtAnchor,
    385                                         CFX_RectF& rtPopup) const {
    386   m_pAdapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor, rtPopup);
    387 }
    388 
    389 void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) {
    390   if (!pMessage)
    391     return;
    392   if (!pMessage->m_pDstTarget)
    393     return;
    394 
    395   CFWL_Widget* pDstWidget = pMessage->m_pDstTarget;
    396   const CFWL_App* pApp = pDstWidget->GetOwnerApp();
    397   if (!pApp)
    398     return;
    399 
    400   CFWL_NoteDriver* pNoteDriver =
    401       static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
    402   if (!pNoteDriver)
    403     return;
    404 
    405   if (IsFormDisabled())
    406     pNoteDriver->ProcessMessage(pMessage->Clone());
    407   else
    408     pNoteDriver->QueueMessage(pMessage->Clone());
    409 
    410 #if (_FX_OS_ == _FX_OS_MACOSX_)
    411   CFWL_NoteLoop* pTopLoop = pNoteDriver->GetTopLoop();
    412   if (pTopLoop)
    413     pNoteDriver->UnqueueMessageAndProcess(pTopLoop);
    414 #endif
    415 }
    416 
    417 void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget,
    418                                   CXFA_Graphics* pGraphics,
    419                                   const CFX_Matrix& matrix) {
    420   if (!pWidget || !pGraphics)
    421     return;
    422 
    423   CFX_RectF clipCopy(0, 0, pWidget->GetWidgetRect().Size());
    424   CFX_RectF clipBounds;
    425 
    426 #if _FX_OS_ == _FX_OS_MACOSX_
    427   if (IsFormDisabled()) {
    428 #endif  // _FX_OS_ == _FX_OS_MACOSX_
    429 
    430     pWidget->GetDelegate()->OnDrawWidget(pGraphics, matrix);
    431     clipBounds = pGraphics->GetClipRect();
    432     clipCopy = clipBounds;
    433 
    434 #if _FX_OS_ == _FX_OS_MACOSX_
    435   } else {
    436     clipBounds = CFX_RectF(matrix.a, matrix.b, matrix.c, matrix.d);
    437     // FIXME: const cast
    438     CFX_Matrix* pMatrixHack = const_cast<CFX_Matrix*>(&matrix);
    439     pMatrixHack->SetIdentity();
    440     pWidget->GetDelegate()->OnDrawWidget(pGraphics, *pMatrixHack);
    441   }
    442 #endif  // _FX_OS_ == _FX_OS_MACOSX_
    443 
    444   if (!IsFormDisabled())
    445     clipBounds.Intersect(pWidget->GetClientRect());
    446   if (!clipBounds.IsEmpty())
    447     DrawChild(pWidget, clipBounds, pGraphics, &matrix);
    448 
    449   GetWidgetMgrItem(pWidget)->iRedrawCounter = 0;
    450   ResetRedrawCounts(pWidget);
    451 }
    452 
    453 void CFWL_WidgetMgr::DrawChild(CFWL_Widget* parent,
    454                                const CFX_RectF& rtClip,
    455                                CXFA_Graphics* pGraphics,
    456                                const CFX_Matrix* pMatrix) {
    457   if (!parent)
    458     return;
    459 
    460   bool bFormDisable = IsFormDisabled();
    461   CFWL_Widget* pNextChild = GetFirstChildWidget(parent);
    462   while (pNextChild) {
    463     CFWL_Widget* child = pNextChild;
    464     pNextChild = GetNextSiblingWidget(child);
    465     if (child->GetStates() & FWL_WGTSTATE_Invisible)
    466       continue;
    467 
    468     CFX_RectF rtWidget = child->GetWidgetRect();
    469     if (rtWidget.IsEmpty())
    470       continue;
    471 
    472     CFX_Matrix widgetMatrix;
    473     CFX_RectF clipBounds(rtWidget);
    474     if (!bFormDisable)
    475       widgetMatrix = child->GetMatrix();
    476     if (pMatrix)
    477       widgetMatrix.Concat(*pMatrix);
    478 
    479     if (!bFormDisable) {
    480       CFX_PointF pos = widgetMatrix.Transform(clipBounds.TopLeft());
    481       clipBounds.left = pos.x;
    482       clipBounds.top = pos.y;
    483       clipBounds.Intersect(rtClip);
    484       if (clipBounds.IsEmpty())
    485         continue;
    486 
    487       pGraphics->SaveGraphState();
    488       pGraphics->SetClipRect(clipBounds);
    489     }
    490     widgetMatrix.Translate(rtWidget.left, rtWidget.top, true);
    491 
    492     if (IFWL_WidgetDelegate* pDelegate = child->GetDelegate()) {
    493       if (IsFormDisabled() || IsNeedRepaint(child, &widgetMatrix, rtClip))
    494         pDelegate->OnDrawWidget(pGraphics, widgetMatrix);
    495     }
    496     if (!bFormDisable)
    497       pGraphics->RestoreGraphState();
    498 
    499     DrawChild(child, clipBounds, pGraphics,
    500               bFormDisable ? &widgetMatrix : pMatrix);
    501     child = GetNextSiblingWidget(child);
    502   }
    503 }
    504 
    505 bool CFWL_WidgetMgr::IsNeedRepaint(CFWL_Widget* pWidget,
    506                                    CFX_Matrix* pMatrix,
    507                                    const CFX_RectF& rtDirty) {
    508   Item* pItem = GetWidgetMgrItem(pWidget);
    509   if (pItem && pItem->iRedrawCounter > 0) {
    510     pItem->iRedrawCounter = 0;
    511     return true;
    512   }
    513 
    514   CFX_RectF rtWidget =
    515       pMatrix->TransformRect(CFX_RectF(0, 0, pWidget->GetWidgetRect().Size()));
    516   if (!rtWidget.IntersectWith(rtDirty))
    517     return false;
    518 
    519   CFWL_Widget* pChild =
    520       pWidget->GetOwnerApp()->GetWidgetMgr()->GetFirstChildWidget(pWidget);
    521   if (!pChild)
    522     return true;
    523 
    524   CFX_RectF rtChilds;
    525   bool bChildIntersectWithDirty = false;
    526   bool bOrginPtIntersectWidthChild = false;
    527   bool bOrginPtIntersectWidthDirty = rtDirty.Contains(rtWidget.TopLeft());
    528   static FWL_NEEDREPAINTHITDATA hitPoint[kNeedRepaintHitPoints];
    529   memset(hitPoint, 0, sizeof(hitPoint));
    530   float fxPiece = rtWidget.width / kNeedRepaintHitPiece;
    531   float fyPiece = rtWidget.height / kNeedRepaintHitPiece;
    532   hitPoint[2].hitPoint.x = hitPoint[6].hitPoint.x = rtWidget.left;
    533   hitPoint[0].hitPoint.x = hitPoint[3].hitPoint.x = hitPoint[7].hitPoint.x =
    534       hitPoint[10].hitPoint.x = fxPiece + rtWidget.left;
    535   hitPoint[1].hitPoint.x = hitPoint[4].hitPoint.x = hitPoint[8].hitPoint.x =
    536       hitPoint[11].hitPoint.x = fxPiece * 2 + rtWidget.left;
    537   hitPoint[5].hitPoint.x = hitPoint[9].hitPoint.x =
    538       rtWidget.width + rtWidget.left;
    539   hitPoint[0].hitPoint.y = hitPoint[1].hitPoint.y = rtWidget.top;
    540   hitPoint[2].hitPoint.y = hitPoint[3].hitPoint.y = hitPoint[4].hitPoint.y =
    541       hitPoint[5].hitPoint.y = fyPiece + rtWidget.top;
    542   hitPoint[6].hitPoint.y = hitPoint[7].hitPoint.y = hitPoint[8].hitPoint.y =
    543       hitPoint[9].hitPoint.y = fyPiece * 2 + rtWidget.top;
    544   hitPoint[10].hitPoint.y = hitPoint[11].hitPoint.y =
    545       rtWidget.height + rtWidget.top;
    546   do {
    547     CFX_RectF rect = pChild->GetWidgetRect();
    548     CFX_RectF r(rect.left + rtWidget.left, rect.top + rtWidget.top, rect.width,
    549                 rect.height);
    550     if (r.IsEmpty())
    551       continue;
    552     if (r.Contains(rtDirty))
    553       return false;
    554     if (!bChildIntersectWithDirty && r.IntersectWith(rtDirty))
    555       bChildIntersectWithDirty = true;
    556     if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild)
    557       bOrginPtIntersectWidthChild = rect.Contains(CFX_PointF(0, 0));
    558 
    559     if (rtChilds.IsEmpty())
    560       rtChilds = rect;
    561     else if (!(pChild->GetStates() & FWL_WGTSTATE_Invisible))
    562       rtChilds.Union(rect);
    563 
    564     for (int32_t i = 0; i < kNeedRepaintHitPoints; i++) {
    565       if (hitPoint[i].bNotContainByDirty || hitPoint[i].bNotNeedRepaint)
    566         continue;
    567       if (!rtDirty.Contains(hitPoint[i].hitPoint)) {
    568         hitPoint[i].bNotContainByDirty = true;
    569         continue;
    570       }
    571       if (r.Contains(hitPoint[i].hitPoint))
    572         hitPoint[i].bNotNeedRepaint = true;
    573     }
    574     pChild =
    575         pChild->GetOwnerApp()->GetWidgetMgr()->GetNextSiblingWidget(pChild);
    576   } while (pChild);
    577 
    578   if (!bChildIntersectWithDirty)
    579     return true;
    580   if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild)
    581     return true;
    582   if (rtChilds.IsEmpty())
    583     return true;
    584 
    585   int32_t repaintPoint = kNeedRepaintHitPoints;
    586   for (int32_t i = 0; i < kNeedRepaintHitPoints; i++) {
    587     if (hitPoint[i].bNotNeedRepaint)
    588       repaintPoint--;
    589   }
    590   if (repaintPoint > 0)
    591     return true;
    592 
    593   rtChilds = pMatrix->TransformRect(rtChilds);
    594   if (rtChilds.Contains(rtDirty) || rtChilds.Contains(rtWidget))
    595     return false;
    596   return true;
    597 }
    598 
    599 CFWL_WidgetMgr::Item::Item() : CFWL_WidgetMgr::Item(nullptr) {}
    600 
    601 CFWL_WidgetMgr::Item::Item(CFWL_Widget* widget)
    602     : pParent(nullptr),
    603       pOwner(nullptr),
    604       pChild(nullptr),
    605       pPrevious(nullptr),
    606       pNext(nullptr),
    607       pWidget(widget),
    608       iRedrawCounter(0)
    609 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
    610       ,
    611       bOutsideChanged(false)
    612 #endif  // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
    613 {
    614 }
    615 
    616 CFWL_WidgetMgr::Item::~Item() {}
    617