From 19a33e4ece99c4bb438d870c52fbc5ed5e80c897 Mon Sep 17 00:00:00 2001 From: Henrique Nakashima Date: Wed, 21 Mar 2018 20:00:47 +0000 Subject: Rewrite CPDFXFA_DocEnvironment::GetPopupPos. This is a step to fix XFA combobox popups being rendered outside the page. The rest of the fix is in: https://chromium-review.googlesource.com/c/chromium/src/+/961249 Bug: chromium:820106 Change-Id: I51e5667bc08cdb2028c0afafa6e29e929e661c94 Reviewed-on: https://pdfium-review.googlesource.com/28371 Commit-Queue: Henrique Nakashima Reviewed-by: dsinclair --- fpdfsdk/cpdfsdk_formfillenvironment.cpp | 2 - fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp | 135 ++++++++++++++++------------- 2 files changed, 76 insertions(+), 61 deletions(-) diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp index 7ac7a0ea32..156314fd5a 100644 --- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp +++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp @@ -389,8 +389,6 @@ void CPDFSDK_FormFillEnvironment::GetPageViewRect(CPDFXFA_Page* page, double right; double bottom; m_pInfo->FFI_GetPageViewRect(m_pInfo, page, &left, &top, &right, &bottom); - if (top < bottom) - std::swap(top, bottom); dstRect.left = static_cast(left); dstRect.top = static_cast(top); diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp index cb6ce1ccf8..c9087e8a0b 100644 --- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp +++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp @@ -123,98 +123,115 @@ bool CPDFXFA_DocEnvironment::GetPopupPos(CXFA_FFWidget* hWidget, if (!pFormFillEnv) return false; - FS_RECTF pageViewRect = {0.0f, 0.0f, 0.0f, 0.0f}; - pFormFillEnv->GetPageViewRect(pPage.Get(), pageViewRect); + FS_RECTF page_view_rect = {0.0f, 0.0f, 0.0f, 0.0f}; + pFormFillEnv->GetPageViewRect(pPage.Get(), page_view_rect); - int t1; - int t2; - CFX_FloatRect rcAnchor = rtAnchor.ToFloatRect(); int nRotate = hWidget->GetNode()->GetRotate(); + + int space_available_below_anchor; + int space_available_above_anchor; switch (nRotate) { + case 0: + default: { + space_available_below_anchor = + static_cast(page_view_rect.bottom - rtAnchor.bottom()); + space_available_above_anchor = + static_cast(rtAnchor.top - page_view_rect.top); + + if (rtAnchor.left < page_view_rect.left) + rtPopup.left += page_view_rect.left - rtAnchor.left; + if (rtAnchor.right() > page_view_rect.right) + rtPopup.left -= rtAnchor.right() - page_view_rect.right; + break; + } case 90: { - t1 = (int)(pageViewRect.right - rcAnchor.right); - t2 = (int)(rcAnchor.left - pageViewRect.left); - if (rcAnchor.bottom < pageViewRect.bottom) - rtPopup.left += rcAnchor.bottom - pageViewRect.bottom; + space_available_below_anchor = + static_cast(page_view_rect.right - rtAnchor.right()); + space_available_above_anchor = + static_cast(rtAnchor.left - page_view_rect.left); + + if (rtAnchor.bottom() > page_view_rect.bottom) + rtPopup.left += rtAnchor.bottom() - page_view_rect.bottom; + if (rtAnchor.top < page_view_rect.top) + rtPopup.left -= page_view_rect.top - rtAnchor.top; break; } case 180: { - t2 = (int)(pageViewRect.top - rcAnchor.top); - t1 = (int)(rcAnchor.bottom - pageViewRect.bottom); - if (rcAnchor.left < pageViewRect.left) - rtPopup.left += rcAnchor.left - pageViewRect.left; + space_available_below_anchor = + static_cast(rtAnchor.top - page_view_rect.top); + space_available_above_anchor = + static_cast(page_view_rect.bottom - rtAnchor.bottom()); + + if (rtAnchor.right() > page_view_rect.right) + rtPopup.left += rtAnchor.right() - page_view_rect.right; + if (rtAnchor.left < page_view_rect.left) + rtPopup.left -= page_view_rect.left - rtAnchor.left; break; } case 270: { - t1 = (int)(rcAnchor.left - pageViewRect.left); - t2 = (int)(pageViewRect.right - rcAnchor.right); - if (rcAnchor.top > pageViewRect.top) - rtPopup.left -= rcAnchor.top - pageViewRect.top; - break; - } - case 0: - default: { - t1 = (int)(pageViewRect.top - rcAnchor.top); - t2 = (int)(rcAnchor.bottom - pageViewRect.bottom); - if (rcAnchor.right > pageViewRect.right) - rtPopup.left -= rcAnchor.right - pageViewRect.right; + space_available_below_anchor = + static_cast(rtAnchor.left - page_view_rect.left); + space_available_above_anchor = + static_cast(page_view_rect.right - rtAnchor.right()); + + if (rtAnchor.top < page_view_rect.top) + rtPopup.left += page_view_rect.top - rtAnchor.top; + if (rtAnchor.bottom() > page_view_rect.bottom) + rtPopup.left -= rtAnchor.bottom() - page_view_rect.bottom; break; } } - int t; - uint32_t dwPos; - if (t1 <= 0 && t2 <= 0) + // If there is no space on either side, the popup can't be rendered. + if (space_available_below_anchor <= 0 && space_available_above_anchor <= 0) return false; - if (t1 <= 0) { - t = t2; - dwPos = 1; - } else if (t2 <= 0) { - t = t1; - dwPos = 0; - } else if (t1 > t2) { - t = t1; - dwPos = 0; - } else { - t = t2; - dwPos = 1; - } - float fPopupHeight; - if (t < fMinPopup) - fPopupHeight = fMinPopup; - else if (t > fMaxPopup) - fPopupHeight = fMaxPopup; + // Determine whether to draw above or below the anchor. + bool draw_below_anchor; + if (space_available_below_anchor <= 0) + draw_below_anchor = false; + else if (space_available_above_anchor <= 0) + draw_below_anchor = true; + else if (space_available_below_anchor > space_available_above_anchor) + draw_below_anchor = true; + else + draw_below_anchor = false; + + int space_available = (draw_below_anchor ? space_available_below_anchor + : space_available_above_anchor); + + // Set the popup height and y position according to what was decided above. + float popup_height; + if (space_available < fMinPopup) + popup_height = fMinPopup; + else if (space_available > fMaxPopup) + popup_height = fMaxPopup; else - fPopupHeight = static_cast(t); + popup_height = static_cast(space_available); switch (nRotate) { case 0: case 180: { - if (dwPos == 0) { + if (draw_below_anchor) rtPopup.top = rtAnchor.height; - rtPopup.height = fPopupHeight; - } else { - rtPopup.top = -fPopupHeight; - rtPopup.height = fPopupHeight; - } + else + rtPopup.top = -popup_height; break; } case 90: case 270: { - if (dwPos == 0) { + if (draw_below_anchor) rtPopup.top = rtAnchor.width; - rtPopup.height = fPopupHeight; - } else { - rtPopup.top = -fPopupHeight; - rtPopup.height = fPopupHeight; - } + else + rtPopup.top = -popup_height; break; } default: break; } + rtPopup.height = popup_height; + return true; } -- cgit v1.2.3