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 <hnakashima@chromium.org>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
index 7ac7a0e..156314f 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
@@ -389,8 +389,6 @@
   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<float>(left);
   dstRect.top = static_cast<float>(top);
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
index cb6ce1c..c9087e8 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
@@ -123,98 +123,115 @@
   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<int>(page_view_rect.bottom - rtAnchor.bottom());
+      space_available_above_anchor =
+          static_cast<int>(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<int>(page_view_rect.right - rtAnchor.right());
+      space_available_above_anchor =
+          static_cast<int>(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<int>(rtAnchor.top - page_view_rect.top);
+      space_available_above_anchor =
+          static_cast<int>(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<int>(rtAnchor.left - page_view_rect.left);
+      space_available_above_anchor =
+          static_cast<int>(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
-    fPopupHeight = static_cast<float>(t);
+    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
+    popup_height = static_cast<float>(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;
 }