Reduce rounding errors when Invalidating rects.

Instead of using CFX_FloatRect::ToFxRect(), which always rounds down,
use GetOuterRect() which correctly rounds up / down depending on the
side of the rectangle.

Change-Id: I7abd3a65e8c0467ed4303292f26a72737a5d553b
Reviewed-on: https://pdfium-review.googlesource.com/12312
Commit-Queue: dsinclair <dsinclair@chromium.org>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/fpdfsdk/cfx_systemhandler.cpp b/fpdfsdk/cfx_systemhandler.cpp
index 6281b1b..c8b1ef4 100644
--- a/fpdfsdk/cfx_systemhandler.cpp
+++ b/fpdfsdk/cfx_systemhandler.cpp
@@ -40,7 +40,8 @@
 
 CFX_SystemHandler::~CFX_SystemHandler() {}
 
-void CFX_SystemHandler::InvalidateRect(CPDFSDK_Widget* widget, FX_RECT rect) {
+void CFX_SystemHandler::InvalidateRect(CPDFSDK_Widget* widget,
+                                       const CFX_FloatRect& rect) {
   CPDFSDK_PageView* pPageView = widget->GetPageView();
   UnderlyingPageType* pPage = widget->GetUnderlyingPage();
   if (!pPage || !pPageView)
@@ -51,14 +52,13 @@
 
   CFX_Matrix device2page = page2device.GetInverse();
 
-  CFX_PointF left_top = device2page.Transform(
-      CFX_PointF(static_cast<float>(rect.left), static_cast<float>(rect.top)));
-  CFX_PointF right_bottom = device2page.Transform(CFX_PointF(
-      static_cast<float>(rect.right), static_cast<float>(rect.bottom)));
+  CFX_PointF left_top = device2page.Transform(CFX_PointF(rect.left, rect.top));
+  CFX_PointF right_bottom =
+      device2page.Transform(CFX_PointF(rect.right, rect.bottom));
 
   CFX_FloatRect rcPDF(left_top.x, right_bottom.y, right_bottom.x, left_top.y);
   rcPDF.Normalize();
-  m_pFormFillEnv->Invalidate(pPage, rcPDF.ToFxRect());
+  m_pFormFillEnv->Invalidate(pPage, rcPDF.GetOuterRect());
 }
 
 void CFX_SystemHandler::OutputSelectedRect(CFFL_FormFiller* pFormFiller,
diff --git a/fpdfsdk/cfx_systemhandler.h b/fpdfsdk/cfx_systemhandler.h
index 7402ac3..c5da755 100644
--- a/fpdfsdk/cfx_systemhandler.h
+++ b/fpdfsdk/cfx_systemhandler.h
@@ -53,7 +53,7 @@
   explicit CFX_SystemHandler(CPDFSDK_FormFillEnvironment* pFormFillEnv);
   ~CFX_SystemHandler();
 
-  void InvalidateRect(CPDFSDK_Widget* widget, FX_RECT rect);
+  void InvalidateRect(CPDFSDK_Widget* widget, const CFX_FloatRect& rect);
   void OutputSelectedRect(CFFL_FormFiller* pFormFiller, CFX_FloatRect& rect);
   bool IsSelectionImplemented() const;
   void SetCursor(int32_t nCursorType);
diff --git a/fpdfsdk/cpdfsdk_interform.cpp b/fpdfsdk/cpdfsdk_interform.cpp
index 27db105..b60529d 100644
--- a/fpdfsdk/cpdfsdk_interform.cpp
+++ b/fpdfsdk/cpdfsdk_interform.cpp
@@ -327,12 +327,14 @@
     CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
     ASSERT(pFormCtrl);
 
-    if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl)) {
-      UnderlyingPageType* pPage = pWidget->GetUnderlyingPage();
-      m_pFormFillEnv->Invalidate(
-          pPage, formfiller->GetViewBBox(
-                     m_pFormFillEnv->GetPageView(pPage, false), pWidget));
-    }
+    CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
+    if (!pWidget)
+      continue;
+
+    UnderlyingPageType* pPage = pWidget->GetUnderlyingPage();
+    FX_RECT rect = formfiller->GetViewBBox(
+        m_pFormFillEnv->GetPageView(pPage, false), pWidget);
+    m_pFormFillEnv->Invalidate(pPage, rect);
   }
 }
 
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index c69f099..358f727 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -459,12 +459,12 @@
 
 void CPDFSDK_PageView::UpdateRects(const std::vector<CFX_FloatRect>& rects) {
   for (const auto& rc : rects)
-    m_pFormFillEnv->Invalidate(m_page, rc.ToFxRect());
+    m_pFormFillEnv->Invalidate(m_page, rc.GetOuterRect());
 }
 
 void CPDFSDK_PageView::UpdateView(CPDFSDK_Annot* pAnnot) {
   CFX_FloatRect rcWindow = pAnnot->GetRect();
-  m_pFormFillEnv->Invalidate(m_page, rcWindow.ToFxRect());
+  m_pFormFillEnv->Invalidate(m_page, rcWindow.GetOuterRect());
 }
 
 int CPDFSDK_PageView::GetPageIndex() const {
diff --git a/fpdfsdk/formfiller/cffl_formfiller.h b/fpdfsdk/formfiller/cffl_formfiller.h
index 2b276c2..b5bf1c8 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.h
+++ b/fpdfsdk/formfiller/cffl_formfiller.h
@@ -140,7 +140,6 @@
   CPDFSDK_PageView* GetCurPageView(bool renew);
   void SetChangeMark();
 
-  virtual void InvalidateRect(const FX_RECT& rect);
   CPDFSDK_Annot* GetSDKAnnot() { return m_pWidget.Get(); }
 
  protected:
@@ -154,6 +153,8 @@
   // until the PWL_Edit is done with it. pdfium:566
   void DestroyWindows();
 
+  void InvalidateRect(const FX_RECT& rect);
+
   CFX_UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
   CFX_UnownedPtr<CPDFSDK_Widget> m_pWidget;
   bool m_bValid;
diff --git a/fpdfsdk/formfiller/cffl_textfield.cpp b/fpdfsdk/formfiller/cffl_textfield.cpp
index d26b4a5..f6f768a 100644
--- a/fpdfsdk/formfiller/cffl_textfield.cpp
+++ b/fpdfsdk/formfiller/cffl_textfield.cpp
@@ -101,7 +101,7 @@
       ASSERT(pPageView);
       m_bValid = !m_bValid;
       m_pFormFillEnv->Invalidate(pAnnot->GetUnderlyingPage(),
-                                 pAnnot->GetRect().ToFxRect());
+                                 pAnnot->GetRect().GetOuterRect());
 
       if (m_bValid) {
         if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true))
diff --git a/fpdfsdk/pwl/cpwl_wnd.cpp b/fpdfsdk/pwl/cpwl_wnd.cpp
index 0198c63..53c692d 100644
--- a/fpdfsdk/pwl/cpwl_wnd.cpp
+++ b/fpdfsdk/pwl/cpwl_wnd.cpp
@@ -18,7 +18,6 @@
 namespace {
 
 constexpr float kDefaultFontSize = 9.0f;
-constexpr int kInvalidationInflate = 2;
 
 }  // namespace
 
@@ -302,11 +301,9 @@
     }
   }
 
-  FX_RECT rcWin = PWLtoWnd(rcRefresh);
-  rcWin.left -= kInvalidationInflate;
-  rcWin.top -= kInvalidationInflate;
-  rcWin.right += kInvalidationInflate;
-  rcWin.bottom += kInvalidationInflate;
+  CFX_FloatRect rcWin = PWLtoWnd(rcRefresh);
+  rcWin.Inflate(1, 1);
+  rcWin.Normalize();
 
   if (CFX_SystemHandler* pSH = GetSystemHandler()) {
     if (CPDFSDK_Widget* widget = static_cast<CPDFSDK_Widget*>(
@@ -737,11 +734,9 @@
   return mt;
 }
 
-FX_RECT CPWL_Wnd::PWLtoWnd(const CFX_FloatRect& rect) const {
+CFX_FloatRect CPWL_Wnd::PWLtoWnd(const CFX_FloatRect& rect) const {
   CFX_Matrix mt = GetWindowMatrix();
-  CFX_FloatRect rcTemp = mt.TransformRect(rect);
-  return FX_RECT((int32_t)(rcTemp.left + 0.5), (int32_t)(rcTemp.bottom + 0.5),
-                 (int32_t)(rcTemp.right + 0.5), (int32_t)(rcTemp.top + 0.5));
+  return mt.TransformRect(rect);
 }
 
 CFX_PointF CPWL_Wnd::ParentToChild(const CFX_PointF& point) const {
diff --git a/fpdfsdk/pwl/cpwl_wnd.h b/fpdfsdk/pwl/cpwl_wnd.h
index 3c6c282..9c913f1 100644
--- a/fpdfsdk/pwl/cpwl_wnd.h
+++ b/fpdfsdk/pwl/cpwl_wnd.h
@@ -318,7 +318,7 @@
   void DrawChildAppearance(CFX_RenderDevice* pDevice,
                            const CFX_Matrix& mtUser2Device);
 
-  FX_RECT PWLtoWnd(const CFX_FloatRect& rect) const;
+  CFX_FloatRect PWLtoWnd(const CFX_FloatRect& rect) const;
 
   void AddChild(CPWL_Wnd* pWnd);
   void RemoveChild(CPWL_Wnd* pWnd);