Remove default parameters from CXFA_FFWidget methods.

Also remove an unused method and move a bunch of internal methods into
an anonymous namespace.

Change-Id: Ic7b4a975852cc2a7384bf3f681b953a5bf7e7d29
Reviewed-on: https://pdfium-review.googlesource.com/11112
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/xfa/fxfa/cxfa_ffcheckbutton.cpp b/xfa/fxfa/cxfa_ffcheckbutton.cpp
index 65eb17d..34fd843 100644
--- a/xfa/fxfa/cxfa_ffcheckbutton.cpp
+++ b/xfa/fxfa/cxfa_ffcheckbutton.cpp
@@ -234,10 +234,11 @@
 
   CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
   CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
-  DrawBorder(pGS, borderUI, m_rtUI, &mtRotate,
-             m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round
-                 ? XFA_DRAWBOX_ForceRound
-                 : 0);
+  DrawBorderWithFlags(
+      pGS, borderUI, m_rtUI, &mtRotate,
+      m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round
+          ? XFA_DRAWBOX_ForceRound
+          : 0);
   RenderCaption(pGS, &mtRotate);
   DrawHighlight(pGS, &mtRotate, dwStatus,
                 m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round);
diff --git a/xfa/fxfa/cxfa_ffnotify.cpp b/xfa/fxfa/cxfa_ffnotify.cpp
index 27ff31c..9c2ac91 100644
--- a/xfa/fxfa/cxfa_ffnotify.cpp
+++ b/xfa/fxfa/cxfa_ffnotify.cpp
@@ -521,7 +521,7 @@
   } else {
     pWidget->LoadWidget();
   }
-  pWidget->AddInvalidateRect(nullptr);
+  pWidget->AddInvalidateRect();
 }
 
 void CXFA_FFNotify::OnLayoutItemRemoving(CXFA_LayoutProcessor* pLayout,
@@ -536,5 +536,5 @@
 
   pDocView->DeleteLayoutItem(pWidget);
   m_pDoc->GetDocEnvironment()->WidgetPreRemove(pWidget, pWidget->GetDataAcc());
-  pWidget->AddInvalidateRect(nullptr);
+  pWidget->AddInvalidateRect();
 }
diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp
index ee5a55e..6996b64 100644
--- a/xfa/fxfa/cxfa_ffwidget.cpp
+++ b/xfa/fxfa/cxfa_ffwidget.cpp
@@ -36,6 +36,871 @@
 #include "xfa/fxgraphics/cxfa_pattern.h"
 #include "xfa/fxgraphics/cxfa_shading.h"
 
+namespace {
+
+void XFA_BOX_GetPath_Arc(CXFA_Box box,
+                         CFX_RectF rtDraw,
+                         CXFA_Path& fillPath,
+                         uint32_t dwFlags) {
+  float a, b;
+  a = rtDraw.width / 2.0f;
+  b = rtDraw.height / 2.0f;
+  if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
+    a = b = std::min(a, b);
+  }
+  CFX_PointF center = rtDraw.Center();
+  rtDraw.left = center.x - a;
+  rtDraw.top = center.y - b;
+  rtDraw.width = a + a;
+  rtDraw.height = b + b;
+  float startAngle = 0, sweepAngle = 360;
+  bool bStart = box.GetStartAngle(startAngle);
+  bool bEnd = box.GetSweepAngle(sweepAngle);
+  if (!bStart && !bEnd) {
+    fillPath.AddEllipse(rtDraw);
+    return;
+  }
+  startAngle = -startAngle * FX_PI / 180.0f;
+  sweepAngle = -sweepAngle * FX_PI / 180.0f;
+  fillPath.AddArc(rtDraw.TopLeft(), rtDraw.Size(), startAngle, sweepAngle);
+}
+
+void XFA_BOX_GetPath(CXFA_Box box,
+                     const std::vector<CXFA_Stroke>& strokes,
+                     CFX_RectF rtWidget,
+                     CXFA_Path& path,
+                     int32_t nIndex,
+                     bool bStart,
+                     bool bCorner) {
+  ASSERT(nIndex >= 0 && nIndex < 8);
+  int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex;
+  CXFA_Corner corner1(strokes[n].GetNode());
+  CXFA_Corner corner2(strokes[(n + 2) % 8].GetNode());
+  float fRadius1 = bCorner ? corner1.GetRadius() : 0.0f;
+  float fRadius2 = bCorner ? corner2.GetRadius() : 0.0f;
+  bool bInverted = corner1.IsInverted();
+  float offsetY = 0.0f;
+  float offsetX = 0.0f;
+  bool bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
+  float halfAfter = 0.0f;
+  float halfBefore = 0.0f;
+  CXFA_Stroke stroke = strokes[nIndex];
+  if (stroke.IsCorner()) {
+    CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8];
+    CXFA_Stroke edgeAfter = strokes[nIndex + 1];
+    if (stroke.IsInverted()) {
+      if (!stroke.SameStyles(edgeBefore)) {
+        halfBefore = edgeBefore.GetThickness() / 2;
+      }
+      if (!stroke.SameStyles(edgeAfter)) {
+        halfAfter = edgeAfter.GetThickness() / 2;
+      }
+    }
+  } else {
+    CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8];
+    CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8];
+    if (!bRound && !bInverted) {
+      halfBefore = edgeBefore.GetThickness() / 2;
+      halfAfter = edgeAfter.GetThickness() / 2;
+    }
+  }
+  float offsetEX = 0.0f;
+  float offsetEY = 0.0f;
+  float sx = 0.0f;
+  float sy = 0.0f;
+  float vx = 1.0f;
+  float vy = 1.0f;
+  float nx = 1.0f;
+  float ny = 1.0f;
+  CFX_PointF cpStart;
+  CFX_PointF cp1;
+  CFX_PointF cp2;
+  if (bRound) {
+    sy = FX_PI / 2;
+  }
+  switch (nIndex) {
+    case 0:
+    case 1:
+      cp1 = rtWidget.TopLeft();
+      cp2 = rtWidget.TopRight();
+      if (nIndex == 0) {
+        cpStart.x = cp1.x - halfBefore;
+        cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter;
+      } else {
+        cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y,
+        offsetEX = halfAfter;
+      }
+      vx = 1, vy = 1;
+      nx = -1, ny = 0;
+      if (bRound) {
+        sx = bInverted ? FX_PI / 2 : FX_PI;
+      } else {
+        sx = 1, sy = 0;
+      }
+      break;
+    case 2:
+    case 3:
+      cp1 = rtWidget.TopRight();
+      cp2 = rtWidget.BottomRight();
+      if (nIndex == 2) {
+        cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore,
+        offsetX = halfAfter;
+      } else {
+        cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore,
+        offsetEY = halfAfter;
+      }
+      vx = -1, vy = 1;
+      nx = 0, ny = -1;
+      if (bRound) {
+        sx = bInverted ? FX_PI : FX_PI * 3 / 2;
+      } else {
+        sx = 0, sy = 1;
+      }
+      break;
+    case 4:
+    case 5:
+      cp1 = rtWidget.BottomRight();
+      cp2 = rtWidget.BottomLeft();
+      if (nIndex == 4) {
+        cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1,
+        offsetY = halfAfter;
+      } else {
+        cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y,
+        offsetEX = -halfAfter;
+      }
+      vx = -1, vy = -1;
+      nx = 1, ny = 0;
+      if (bRound) {
+        sx = bInverted ? FX_PI * 3 / 2 : 0;
+      } else {
+        sx = -1, sy = 0;
+      }
+      break;
+    case 6:
+    case 7:
+      cp1 = rtWidget.BottomLeft();
+      cp2 = rtWidget.TopLeft();
+      if (nIndex == 6) {
+        cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore,
+        offsetX = -halfAfter;
+      } else {
+        cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore,
+        offsetEY = -halfAfter;
+      }
+      vx = 1;
+      vy = -1;
+      nx = 0;
+      ny = 1;
+      if (bRound) {
+        sx = bInverted ? 0 : FX_PI / 2;
+      } else {
+        sx = 0;
+        sy = -1;
+      }
+      break;
+  }
+  if (bStart) {
+    path.MoveTo(cpStart);
+  }
+  if (nIndex & 1) {
+    path.LineTo(CFX_PointF(cp2.x + fRadius2 * nx + offsetEX,
+                           cp2.y + fRadius2 * ny + offsetEY));
+    return;
+  }
+  if (bRound) {
+    if (fRadius1 < 0)
+      sx -= FX_PI;
+    if (bInverted)
+      sy *= -1;
+
+    CFX_RectF rtRadius(cp1.x + offsetX * 2, cp1.y + offsetY * 2,
+                       fRadius1 * 2 * vx - offsetX * 2,
+                       fRadius1 * 2 * vy - offsetY * 2);
+    rtRadius.Normalize();
+    if (bInverted)
+      rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
+
+    path.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy);
+  } else {
+    CFX_PointF cp;
+    if (bInverted) {
+      cp.x = cp1.x + fRadius1 * vx;
+      cp.y = cp1.y + fRadius1 * vy;
+    } else {
+      cp = cp1;
+    }
+    path.LineTo(cp);
+    path.LineTo(CFX_PointF(cp1.x + fRadius1 * sx + offsetX,
+                           cp1.y + fRadius1 * sy + offsetY));
+  }
+}
+
+void XFA_BOX_GetFillPath(CXFA_Box box,
+                         const std::vector<CXFA_Stroke>& strokes,
+                         CFX_RectF rtWidget,
+                         CXFA_Path& fillPath,
+                         uint16_t dwFlags) {
+  if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
+    CXFA_Edge edge = box.GetEdge(0);
+    float fThickness = edge.GetThickness();
+    if (fThickness < 0) {
+      fThickness = 0;
+    }
+    float fHalf = fThickness / 2;
+    int32_t iHand = box.GetHand();
+    if (iHand == XFA_ATTRIBUTEENUM_Left) {
+      rtWidget.Inflate(fHalf, fHalf);
+    } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+      rtWidget.Deflate(fHalf, fHalf);
+    }
+    XFA_BOX_GetPath_Arc(box, rtWidget, fillPath, dwFlags);
+    return;
+  }
+  bool bSameStyles = true;
+  CXFA_Stroke stroke1 = strokes[0];
+  for (int32_t i = 1; i < 8; i++) {
+    CXFA_Stroke stroke2 = strokes[i];
+    if (!stroke1.SameStyles(stroke2)) {
+      bSameStyles = false;
+      break;
+    }
+    stroke1 = stroke2;
+  }
+  if (bSameStyles) {
+    stroke1 = strokes[0];
+    for (int32_t i = 2; i < 8; i += 2) {
+      CXFA_Stroke stroke2 = strokes[i];
+      if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
+                                           XFA_STROKE_SAMESTYLE_Corner)) {
+        bSameStyles = false;
+        break;
+      }
+      stroke1 = stroke2;
+    }
+    if (bSameStyles) {
+      stroke1 = strokes[0];
+      if (stroke1.IsInverted()) {
+        bSameStyles = false;
+      }
+      if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) {
+        bSameStyles = false;
+      }
+    }
+  }
+  if (bSameStyles) {
+    fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width,
+                          rtWidget.height);
+    return;
+  }
+
+  for (int32_t i = 0; i < 8; i += 2) {
+    float sx = 0.0f;
+    float sy = 0.0f;
+    float vx = 1.0f;
+    float vy = 1.0f;
+    float nx = 1.0f;
+    float ny = 1.0f;
+    CFX_PointF cp1, cp2;
+    CXFA_Corner corner1(strokes[i].GetNode());
+    CXFA_Corner corner2(strokes[(i + 2) % 8].GetNode());
+    float fRadius1 = corner1.GetRadius();
+    float fRadius2 = corner2.GetRadius();
+    bool bInverted = corner1.IsInverted();
+    bool bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
+    if (bRound) {
+      sy = FX_PI / 2;
+    }
+    switch (i) {
+      case 0:
+        cp1 = rtWidget.TopLeft();
+        cp2 = rtWidget.TopRight();
+        vx = 1, vy = 1;
+        nx = -1, ny = 0;
+        if (bRound) {
+          sx = bInverted ? FX_PI / 2 : FX_PI;
+        } else {
+          sx = 1, sy = 0;
+        }
+        break;
+      case 2:
+        cp1 = rtWidget.TopRight();
+        cp2 = rtWidget.BottomRight();
+        vx = -1, vy = 1;
+        nx = 0, ny = -1;
+        if (bRound) {
+          sx = bInverted ? FX_PI : FX_PI * 3 / 2;
+        } else {
+          sx = 0, sy = 1;
+        }
+        break;
+      case 4:
+        cp1 = rtWidget.BottomRight();
+        cp2 = rtWidget.BottomLeft();
+        vx = -1, vy = -1;
+        nx = 1, ny = 0;
+        if (bRound) {
+          sx = bInverted ? FX_PI * 3 / 2 : 0;
+        } else {
+          sx = -1, sy = 0;
+        }
+        break;
+      case 6:
+        cp1 = rtWidget.BottomLeft();
+        cp2 = rtWidget.TopLeft();
+        vx = 1, vy = -1;
+        nx = 0, ny = 1;
+        if (bRound) {
+          sx = bInverted ? 0 : FX_PI / 2;
+        } else {
+          sx = 0;
+          sy = -1;
+        }
+        break;
+    }
+    if (i == 0)
+      fillPath.MoveTo(CFX_PointF(cp1.x, cp1.y + fRadius1));
+
+    if (bRound) {
+      if (fRadius1 < 0)
+        sx -= FX_PI;
+      if (bInverted)
+        sy *= -1;
+
+      CFX_RectF rtRadius(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy);
+      rtRadius.Normalize();
+      if (bInverted)
+        rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
+
+      fillPath.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy);
+    } else {
+      CFX_PointF cp;
+      if (bInverted) {
+        cp.x = cp1.x + fRadius1 * vx;
+        cp.y = cp1.y + fRadius1 * vy;
+      } else {
+        cp = cp1;
+      }
+      fillPath.LineTo(cp);
+      fillPath.LineTo(CFX_PointF(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy));
+    }
+    fillPath.LineTo(CFX_PointF(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny));
+  }
+}
+
+void XFA_BOX_Fill_Radial(CXFA_Box box,
+                         CXFA_Graphics* pGS,
+                         CXFA_Path& fillPath,
+                         CFX_RectF rtFill,
+                         CFX_Matrix* pMatrix) {
+  CXFA_Fill fill = box.GetFill();
+  FX_ARGB crStart, crEnd;
+  crStart = fill.GetColor();
+  int32_t iType = fill.GetRadial(crEnd);
+  if (iType != XFA_ATTRIBUTEENUM_ToEdge) {
+    FX_ARGB temp = crEnd;
+    crEnd = crStart;
+    crStart = temp;
+  }
+  CXFA_Shading shading(rtFill.Center(), rtFill.Center(), 0,
+                       sqrt(rtFill.Width() * rtFill.Width() +
+                            rtFill.Height() * rtFill.Height()) /
+                           2,
+                       true, true, crStart, crEnd);
+  pGS->SetFillColor(CXFA_Color(&shading));
+  pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
+}
+
+void XFA_BOX_Fill_Pattern(CXFA_Box box,
+                          CXFA_Graphics* pGS,
+                          CXFA_Path& fillPath,
+                          CFX_RectF rtFill,
+                          CFX_Matrix* pMatrix) {
+  CXFA_Fill fill = box.GetFill();
+  FX_ARGB crStart, crEnd;
+  crStart = fill.GetColor();
+  int32_t iType = fill.GetPattern(crEnd);
+  FX_HatchStyle iHatch = FX_HatchStyle::Cross;
+  switch (iType) {
+    case XFA_ATTRIBUTEENUM_CrossDiagonal:
+      iHatch = FX_HatchStyle::DiagonalCross;
+      break;
+    case XFA_ATTRIBUTEENUM_DiagonalLeft:
+      iHatch = FX_HatchStyle::ForwardDiagonal;
+      break;
+    case XFA_ATTRIBUTEENUM_DiagonalRight:
+      iHatch = FX_HatchStyle::BackwardDiagonal;
+      break;
+    case XFA_ATTRIBUTEENUM_Horizontal:
+      iHatch = FX_HatchStyle::Horizontal;
+      break;
+    case XFA_ATTRIBUTEENUM_Vertical:
+      iHatch = FX_HatchStyle::Vertical;
+      break;
+    default:
+      break;
+  }
+
+  CXFA_Pattern pattern(iHatch, crEnd, crStart);
+  pGS->SetFillColor(CXFA_Color(&pattern, 0x0));
+  pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
+}
+
+void XFA_BOX_Fill_Linear(CXFA_Box box,
+                         CXFA_Graphics* pGS,
+                         CXFA_Path& fillPath,
+                         CFX_RectF rtFill,
+                         CFX_Matrix* pMatrix) {
+  CXFA_Fill fill = box.GetFill();
+  FX_ARGB crStart = fill.GetColor();
+  FX_ARGB crEnd;
+  int32_t iType = fill.GetLinear(crEnd);
+  CFX_PointF ptStart;
+  CFX_PointF ptEnd;
+  switch (iType) {
+    case XFA_ATTRIBUTEENUM_ToRight:
+      ptStart = CFX_PointF(rtFill.left, rtFill.top);
+      ptEnd = CFX_PointF(rtFill.right(), rtFill.top);
+      break;
+    case XFA_ATTRIBUTEENUM_ToBottom:
+      ptStart = CFX_PointF(rtFill.left, rtFill.top);
+      ptEnd = CFX_PointF(rtFill.left, rtFill.bottom());
+      break;
+    case XFA_ATTRIBUTEENUM_ToLeft:
+      ptStart = CFX_PointF(rtFill.right(), rtFill.top);
+      ptEnd = CFX_PointF(rtFill.left, rtFill.top);
+      break;
+    case XFA_ATTRIBUTEENUM_ToTop:
+      ptStart = CFX_PointF(rtFill.left, rtFill.bottom());
+      ptEnd = CFX_PointF(rtFill.left, rtFill.top);
+      break;
+    default:
+      break;
+  }
+  CXFA_Shading shading(ptStart, ptEnd, false, false, crStart, crEnd);
+  pGS->SetFillColor(CXFA_Color(&shading));
+  pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
+}
+
+void XFA_BOX_Fill(CXFA_Box box,
+                  const std::vector<CXFA_Stroke>& strokes,
+                  CXFA_Graphics* pGS,
+                  const CFX_RectF& rtWidget,
+                  CFX_Matrix* pMatrix,
+                  uint32_t dwFlags) {
+  CXFA_Fill fill = box.GetFill();
+  if (!fill || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
+    return;
+
+  pGS->SaveGraphState();
+  CXFA_Path fillPath;
+  XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath,
+                      (dwFlags & XFA_DRAWBOX_ForceRound) != 0);
+  fillPath.Close();
+  XFA_Element eType = fill.GetFillType();
+  switch (eType) {
+    case XFA_Element::Radial:
+      XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix);
+      break;
+    case XFA_Element::Pattern:
+      XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix);
+      break;
+    case XFA_Element::Linear:
+      XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix);
+      break;
+    default: {
+      FX_ARGB cr;
+      if (eType == XFA_Element::Stipple) {
+        int32_t iRate = fill.GetStipple(cr);
+        if (iRate == 0)
+          iRate = 100;
+        int32_t a;
+        FX_COLORREF rgb;
+        std::tie(a, rgb) = ArgbToColorRef(cr);
+        cr = ArgbEncode(iRate * a / 100, rgb);
+      } else {
+        cr = fill.GetColor();
+      }
+      pGS->SetFillColor(CXFA_Color(cr));
+      pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
+    } break;
+  }
+  pGS->RestoreGraphState();
+}
+
+void XFA_BOX_StrokePath(CXFA_Stroke stroke,
+                        CXFA_Path* pPath,
+                        CXFA_Graphics* pGS,
+                        CFX_Matrix* pMatrix) {
+  if (!stroke || !stroke.IsVisible()) {
+    return;
+  }
+  float fThickness = stroke.GetThickness();
+  if (fThickness < 0.001f) {
+    return;
+  }
+  pGS->SaveGraphState();
+  if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) {
+    fThickness = 2 * stroke.GetRadius();
+  }
+  pGS->SetLineWidth(fThickness);
+  pGS->EnableActOnDash();
+  pGS->SetLineCap(CFX_GraphStateData::LineCapButt);
+  XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(),
+                            XFA_ATTRIBUTEENUM_Butt);
+  pGS->SetStrokeColor(CXFA_Color(stroke.GetColor()));
+  pGS->StrokePath(pPath, pMatrix);
+  pGS->RestoreGraphState();
+}
+
+void XFA_BOX_StrokeArc(CXFA_Box box,
+                       CXFA_Graphics* pGS,
+                       CFX_RectF rtWidget,
+                       CFX_Matrix* pMatrix,
+                       uint32_t dwFlags) {
+  CXFA_Edge edge = box.GetEdge(0);
+  if (!edge || !edge.IsVisible()) {
+    return;
+  }
+  bool bVisible = false;
+  float fThickness = 0;
+  int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
+  if (i3DType) {
+    if (bVisible && fThickness >= 0.001f) {
+      dwFlags |= XFA_DRAWBOX_Lowered3D;
+    }
+  }
+  float fHalf = edge.GetThickness() / 2;
+  if (fHalf < 0) {
+    fHalf = 0;
+  }
+  int32_t iHand = box.GetHand();
+  if (iHand == XFA_ATTRIBUTEENUM_Left) {
+    rtWidget.Inflate(fHalf, fHalf);
+  } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+    rtWidget.Deflate(fHalf, fHalf);
+  }
+  if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 ||
+      (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) {
+    if (fHalf < 0.001f)
+      return;
+
+    CXFA_Path arcPath;
+    XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags);
+    XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix);
+    return;
+  }
+  pGS->SaveGraphState();
+  pGS->SetLineWidth(fHalf);
+
+  float a, b;
+  a = rtWidget.width / 2.0f;
+  b = rtWidget.height / 2.0f;
+  if (dwFlags & XFA_DRAWBOX_ForceRound) {
+    a = std::min(a, b);
+    b = a;
+  }
+
+  CFX_PointF center = rtWidget.Center();
+  rtWidget.left = center.x - a;
+  rtWidget.top = center.y - b;
+  rtWidget.width = a + a;
+  rtWidget.height = b + b;
+
+  float startAngle = 0, sweepAngle = 360;
+  startAngle = startAngle * FX_PI / 180.0f;
+  sweepAngle = -sweepAngle * FX_PI / 180.0f;
+
+  CXFA_Path arcPath;
+  arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f,
+                 FX_PI);
+
+  pGS->SetStrokeColor(CXFA_Color(0xFF808080));
+  pGS->StrokePath(&arcPath, pMatrix);
+  arcPath.Clear();
+  arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f,
+                 FX_PI);
+
+  pGS->SetStrokeColor(CXFA_Color(0xFFFFFFFF));
+  pGS->StrokePath(&arcPath, pMatrix);
+  rtWidget.Deflate(fHalf, fHalf);
+  arcPath.Clear();
+  arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f,
+                 FX_PI);
+
+  pGS->SetStrokeColor(CXFA_Color(0xFF404040));
+  pGS->StrokePath(&arcPath, pMatrix);
+  arcPath.Clear();
+  arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f,
+                 FX_PI);
+
+  pGS->SetStrokeColor(CXFA_Color(0xFFC0C0C0));
+  pGS->StrokePath(&arcPath, pMatrix);
+  pGS->RestoreGraphState();
+}
+
+void XFA_Draw3DRect(CXFA_Graphics* pGraphic,
+                    const CFX_RectF& rt,
+                    float fLineWidth,
+                    CFX_Matrix* pMatrix,
+                    FX_ARGB argbTopLeft,
+                    FX_ARGB argbBottomRight) {
+  float fBottom = rt.bottom();
+  float fRight = rt.right();
+  CXFA_Path pathLT;
+  pathLT.MoveTo(CFX_PointF(rt.left, fBottom));
+  pathLT.LineTo(CFX_PointF(rt.left, rt.top));
+  pathLT.LineTo(CFX_PointF(fRight, rt.top));
+  pathLT.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth));
+  pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, rt.top + fLineWidth));
+  pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth));
+  pathLT.LineTo(CFX_PointF(rt.left, fBottom));
+  pGraphic->SetFillColor(CXFA_Color(argbTopLeft));
+  pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix);
+
+  CXFA_Path pathRB;
+  pathRB.MoveTo(CFX_PointF(fRight, rt.top));
+  pathRB.LineTo(CFX_PointF(fRight, fBottom));
+  pathRB.LineTo(CFX_PointF(rt.left, fBottom));
+  pathRB.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth));
+  pathRB.LineTo(CFX_PointF(fRight - fLineWidth, fBottom - fLineWidth));
+  pathRB.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth));
+  pathRB.LineTo(CFX_PointF(fRight, rt.top));
+  pGraphic->SetFillColor(CXFA_Color(argbBottomRight));
+  pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix);
+}
+
+void XFA_BOX_Stroke_3DRect_Lowered(CXFA_Graphics* pGS,
+                                   CFX_RectF rt,
+                                   float fThickness,
+                                   CFX_Matrix* pMatrix) {
+  float fHalfWidth = fThickness / 2.0f;
+  CFX_RectF rtInner(rt);
+  rtInner.Deflate(fHalfWidth, fHalfWidth);
+
+  CXFA_Path path;
+  path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
+  path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
+  pGS->SetFillColor(CXFA_Color(0xFF000000));
+  pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
+  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0);
+}
+
+void XFA_BOX_Stroke_3DRect_Raised(CXFA_Graphics* pGS,
+                                  CFX_RectF rt,
+                                  float fThickness,
+                                  CFX_Matrix* pMatrix) {
+  float fHalfWidth = fThickness / 2.0f;
+  CFX_RectF rtInner(rt);
+  rtInner.Deflate(fHalfWidth, fHalfWidth);
+
+  CXFA_Path path;
+  path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
+  path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
+  pGS->SetFillColor(CXFA_Color(0xFF000000));
+  pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
+  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
+}
+
+void XFA_BOX_Stroke_3DRect_Etched(CXFA_Graphics* pGS,
+                                  CFX_RectF rt,
+                                  float fThickness,
+                                  CFX_Matrix* pMatrix) {
+  float fHalfWidth = fThickness / 2.0f;
+  XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF);
+  CFX_RectF rtInner(rt);
+  rtInner.Deflate(fHalfWidth, fHalfWidth);
+  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
+}
+
+void XFA_BOX_Stroke_3DRect_Embossed(CXFA_Graphics* pGS,
+                                    CFX_RectF rt,
+                                    float fThickness,
+                                    CFX_Matrix* pMatrix) {
+  float fHalfWidth = fThickness / 2.0f;
+  XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000);
+  CFX_RectF rtInner(rt);
+  rtInner.Deflate(fHalfWidth, fHalfWidth);
+  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080);
+}
+
+void XFA_BOX_Stroke_Rect(CXFA_Box box,
+                         const std::vector<CXFA_Stroke>& strokes,
+                         CXFA_Graphics* pGS,
+                         CFX_RectF rtWidget,
+                         CFX_Matrix* pMatrix) {
+  bool bVisible = false;
+  float fThickness = 0;
+  int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
+  if (i3DType) {
+    if (!bVisible || fThickness < 0.001f) {
+      return;
+    }
+    switch (i3DType) {
+      case XFA_ATTRIBUTEENUM_Lowered:
+        XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix);
+        break;
+      case XFA_ATTRIBUTEENUM_Raised:
+        XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix);
+        break;
+      case XFA_ATTRIBUTEENUM_Etched:
+        XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix);
+        break;
+      case XFA_ATTRIBUTEENUM_Embossed:
+        XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix);
+        break;
+    }
+    return;
+  }
+  bool bClose = false;
+  bool bSameStyles = true;
+  CXFA_Stroke stroke1 = strokes[0];
+  for (int32_t i = 1; i < 8; i++) {
+    CXFA_Stroke stroke2 = strokes[i];
+    if (!stroke1.SameStyles(stroke2)) {
+      bSameStyles = false;
+      break;
+    }
+    stroke1 = stroke2;
+  }
+  if (bSameStyles) {
+    stroke1 = strokes[0];
+    bClose = true;
+    for (int32_t i = 2; i < 8; i += 2) {
+      CXFA_Stroke stroke2 = strokes[i];
+      if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
+                                           XFA_STROKE_SAMESTYLE_Corner)) {
+        bSameStyles = false;
+        break;
+      }
+      stroke1 = stroke2;
+    }
+    if (bSameStyles) {
+      stroke1 = strokes[0];
+      if (stroke1.IsInverted())
+        bSameStyles = false;
+      if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square)
+        bSameStyles = false;
+    }
+  }
+  bool bStart = true;
+  CXFA_Path path;
+  for (int32_t i = 0; i < 8; i++) {
+    CXFA_Stroke stroke = strokes[i];
+    if ((i % 1) == 0 && stroke.GetRadius() < 0) {
+      bool bEmpty = path.IsEmpty();
+      if (!bEmpty) {
+        XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix);
+        path.Clear();
+      }
+      bStart = true;
+      continue;
+    }
+    XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles);
+    CXFA_Stroke stroke2 = strokes[(i + 1) % 8];
+    bStart = !stroke.SameStyles(stroke2);
+    if (bStart) {
+      XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix);
+      path.Clear();
+    }
+  }
+  bool bEmpty = path.IsEmpty();
+  if (!bEmpty) {
+    if (bClose) {
+      path.Close();
+    }
+    XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix);
+  }
+}
+
+void XFA_BOX_Stroke(CXFA_Box box,
+                    const std::vector<CXFA_Stroke>& strokes,
+                    CXFA_Graphics* pGS,
+                    CFX_RectF rtWidget,
+                    CFX_Matrix* pMatrix,
+                    uint32_t dwFlags) {
+  if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
+    XFA_BOX_StrokeArc(box, pGS, rtWidget, pMatrix, dwFlags);
+    return;
+  }
+  bool bVisible = false;
+  for (int32_t j = 0; j < 4; j++) {
+    if (strokes[j * 2 + 1].IsVisible()) {
+      bVisible = true;
+      break;
+    }
+  }
+  if (!bVisible) {
+    return;
+  }
+  for (int32_t i = 1; i < 8; i += 2) {
+    CXFA_Edge edge(strokes[i].GetNode());
+    float fThickness = edge.GetThickness();
+    if (fThickness < 0) {
+      fThickness = 0;
+    }
+    float fHalf = fThickness / 2;
+    int32_t iHand = box.GetHand();
+    switch (i) {
+      case 1:
+        if (iHand == XFA_ATTRIBUTEENUM_Left) {
+          rtWidget.top -= fHalf;
+          rtWidget.height += fHalf;
+        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+          rtWidget.top += fHalf;
+          rtWidget.height -= fHalf;
+        }
+        break;
+      case 3:
+        if (iHand == XFA_ATTRIBUTEENUM_Left) {
+          rtWidget.width += fHalf;
+        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+          rtWidget.width -= fHalf;
+        }
+        break;
+      case 5:
+        if (iHand == XFA_ATTRIBUTEENUM_Left) {
+          rtWidget.height += fHalf;
+        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+          rtWidget.height -= fHalf;
+        }
+        break;
+      case 7:
+        if (iHand == XFA_ATTRIBUTEENUM_Left) {
+          rtWidget.left -= fHalf;
+          rtWidget.width += fHalf;
+        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+          rtWidget.left += fHalf;
+          rtWidget.width -= fHalf;
+        }
+        break;
+    }
+  }
+  XFA_BOX_Stroke_Rect(box, strokes, pGS, rtWidget, pMatrix);
+}
+
+void XFA_DrawBox(CXFA_Box box,
+                 CXFA_Graphics* pGS,
+                 const CFX_RectF& rtWidget,
+                 CFX_Matrix* pMatrix,
+                 uint32_t dwFlags) {
+  if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
+    return;
+
+  XFA_Element eType = box.GetElementType();
+  if (eType != XFA_Element::Arc && eType != XFA_Element::Border &&
+      eType != XFA_Element::Rectangle) {
+    return;
+  }
+  std::vector<CXFA_Stroke> strokes;
+  if (!(dwFlags & XFA_DRAWBOX_ForceRound) && eType != XFA_Element::Arc)
+    box.GetStrokes(&strokes);
+
+  XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
+  XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
+}
+
+}  // namespace
+
 CXFA_FFWidget::CXFA_FFWidget(CXFA_WidgetAcc* pDataAcc)
     : CXFA_ContentLayoutItem(pDataAcc->GetNode()),
       m_pPageView(nullptr),
@@ -145,33 +1010,25 @@
   return false;
 }
 void CXFA_FFWidget::UpdateWidgetProperty() {}
+
 void CXFA_FFWidget::DrawBorder(CXFA_Graphics* pGS,
                                CXFA_Box box,
                                const CFX_RectF& rtBorder,
-                               CFX_Matrix* pMatrix,
-                               uint32_t dwFlags) {
+                               CFX_Matrix* pMatrix) {
+  XFA_DrawBox(box, pGS, rtBorder, pMatrix, 0);
+}
+
+void CXFA_FFWidget::DrawBorderWithFlags(CXFA_Graphics* pGS,
+                                        CXFA_Box box,
+                                        const CFX_RectF& rtBorder,
+                                        CFX_Matrix* pMatrix,
+                                        uint32_t dwFlags) {
   XFA_DrawBox(box, pGS, rtBorder, pMatrix, dwFlags);
 }
 
-void CXFA_FFWidget::InvalidateWidget(const CFX_RectF* pRect) {
-  if (pRect) {
-    GetDoc()->GetDocEnvironment()->InvalidateRect(m_pPageView, *pRect);
-    return;
-  }
-
+void CXFA_FFWidget::AddInvalidateRect() {
   CFX_RectF rtWidget = GetBBox(XFA_WidgetStatus_Focused);
   rtWidget.Inflate(2, 2);
-  GetDoc()->GetDocEnvironment()->InvalidateRect(m_pPageView, rtWidget);
-}
-
-void CXFA_FFWidget::AddInvalidateRect(const CFX_RectF* pRect) {
-  CFX_RectF rtWidget;
-  if (pRect) {
-    rtWidget = *pRect;
-  } else {
-    rtWidget = GetBBox(XFA_WidgetStatus_Focused);
-    rtWidget.Inflate(2, 2);
-  }
   m_pDocView->AddInvalidateRect(m_pPageView, rtWidget);
 }
 
@@ -926,6 +1783,7 @@
   pCP[j] = '\0';
   return pCP;
 }
+
 static int32_t XFA_Base64Decode(const char* pStr, uint8_t* pOutBuffer) {
   if (!pStr) {
     return 0;
@@ -1166,870 +2024,17 @@
   mg.GetBottomInset(fBottomInset);
   rt.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
 }
+
 CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
   if (XFA_IsCreateWidget(pLayoutItem->GetFormNode()->GetElementType()))
     return static_cast<CXFA_FFWidget*>(pLayoutItem);
   return nullptr;
 }
+
 bool XFA_IsCreateWidget(XFA_Element eType) {
   return eType == XFA_Element::Field || eType == XFA_Element::Draw ||
          eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup;
 }
-static void XFA_BOX_GetPath_Arc(CXFA_Box box,
-                                CFX_RectF rtDraw,
-                                CXFA_Path& fillPath,
-                                uint32_t dwFlags) {
-  float a, b;
-  a = rtDraw.width / 2.0f;
-  b = rtDraw.height / 2.0f;
-  if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
-    a = b = std::min(a, b);
-  }
-  CFX_PointF center = rtDraw.Center();
-  rtDraw.left = center.x - a;
-  rtDraw.top = center.y - b;
-  rtDraw.width = a + a;
-  rtDraw.height = b + b;
-  float startAngle = 0, sweepAngle = 360;
-  bool bStart = box.GetStartAngle(startAngle);
-  bool bEnd = box.GetSweepAngle(sweepAngle);
-  if (!bStart && !bEnd) {
-    fillPath.AddEllipse(rtDraw);
-    return;
-  }
-  startAngle = -startAngle * FX_PI / 180.0f;
-  sweepAngle = -sweepAngle * FX_PI / 180.0f;
-  fillPath.AddArc(rtDraw.TopLeft(), rtDraw.Size(), startAngle, sweepAngle);
-}
-
-static void XFA_BOX_GetPath(CXFA_Box box,
-                            const std::vector<CXFA_Stroke>& strokes,
-                            CFX_RectF rtWidget,
-                            CXFA_Path& path,
-                            int32_t nIndex,
-                            bool bStart,
-                            bool bCorner) {
-  ASSERT(nIndex >= 0 && nIndex < 8);
-  int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex;
-  CXFA_Corner corner1(strokes[n].GetNode());
-  CXFA_Corner corner2(strokes[(n + 2) % 8].GetNode());
-  float fRadius1 = bCorner ? corner1.GetRadius() : 0.0f;
-  float fRadius2 = bCorner ? corner2.GetRadius() : 0.0f;
-  bool bInverted = corner1.IsInverted();
-  float offsetY = 0.0f;
-  float offsetX = 0.0f;
-  bool bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
-  float halfAfter = 0.0f;
-  float halfBefore = 0.0f;
-  CXFA_Stroke stroke = strokes[nIndex];
-  if (stroke.IsCorner()) {
-    CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8];
-    CXFA_Stroke edgeAfter = strokes[nIndex + 1];
-    if (stroke.IsInverted()) {
-      if (!stroke.SameStyles(edgeBefore)) {
-        halfBefore = edgeBefore.GetThickness() / 2;
-      }
-      if (!stroke.SameStyles(edgeAfter)) {
-        halfAfter = edgeAfter.GetThickness() / 2;
-      }
-    }
-  } else {
-    CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8];
-    CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8];
-    if (!bRound && !bInverted) {
-      halfBefore = edgeBefore.GetThickness() / 2;
-      halfAfter = edgeAfter.GetThickness() / 2;
-    }
-  }
-  float offsetEX = 0.0f;
-  float offsetEY = 0.0f;
-  float sx = 0.0f;
-  float sy = 0.0f;
-  float vx = 1.0f;
-  float vy = 1.0f;
-  float nx = 1.0f;
-  float ny = 1.0f;
-  CFX_PointF cpStart;
-  CFX_PointF cp1;
-  CFX_PointF cp2;
-  if (bRound) {
-    sy = FX_PI / 2;
-  }
-  switch (nIndex) {
-    case 0:
-    case 1:
-      cp1 = rtWidget.TopLeft();
-      cp2 = rtWidget.TopRight();
-      if (nIndex == 0) {
-        cpStart.x = cp1.x - halfBefore;
-        cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter;
-      } else {
-        cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y,
-        offsetEX = halfAfter;
-      }
-      vx = 1, vy = 1;
-      nx = -1, ny = 0;
-      if (bRound) {
-        sx = bInverted ? FX_PI / 2 : FX_PI;
-      } else {
-        sx = 1, sy = 0;
-      }
-      break;
-    case 2:
-    case 3:
-      cp1 = rtWidget.TopRight();
-      cp2 = rtWidget.BottomRight();
-      if (nIndex == 2) {
-        cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore,
-        offsetX = halfAfter;
-      } else {
-        cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore,
-        offsetEY = halfAfter;
-      }
-      vx = -1, vy = 1;
-      nx = 0, ny = -1;
-      if (bRound) {
-        sx = bInverted ? FX_PI : FX_PI * 3 / 2;
-      } else {
-        sx = 0, sy = 1;
-      }
-      break;
-    case 4:
-    case 5:
-      cp1 = rtWidget.BottomRight();
-      cp2 = rtWidget.BottomLeft();
-      if (nIndex == 4) {
-        cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1,
-        offsetY = halfAfter;
-      } else {
-        cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y,
-        offsetEX = -halfAfter;
-      }
-      vx = -1, vy = -1;
-      nx = 1, ny = 0;
-      if (bRound) {
-        sx = bInverted ? FX_PI * 3 / 2 : 0;
-      } else {
-        sx = -1, sy = 0;
-      }
-      break;
-    case 6:
-    case 7:
-      cp1 = rtWidget.BottomLeft();
-      cp2 = rtWidget.TopLeft();
-      if (nIndex == 6) {
-        cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore,
-        offsetX = -halfAfter;
-      } else {
-        cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore,
-        offsetEY = -halfAfter;
-      }
-      vx = 1;
-      vy = -1;
-      nx = 0;
-      ny = 1;
-      if (bRound) {
-        sx = bInverted ? 0 : FX_PI / 2;
-      } else {
-        sx = 0;
-        sy = -1;
-      }
-      break;
-  }
-  if (bStart) {
-    path.MoveTo(cpStart);
-  }
-  if (nIndex & 1) {
-    path.LineTo(CFX_PointF(cp2.x + fRadius2 * nx + offsetEX,
-                           cp2.y + fRadius2 * ny + offsetEY));
-    return;
-  }
-  if (bRound) {
-    if (fRadius1 < 0)
-      sx -= FX_PI;
-    if (bInverted)
-      sy *= -1;
-
-    CFX_RectF rtRadius(cp1.x + offsetX * 2, cp1.y + offsetY * 2,
-                       fRadius1 * 2 * vx - offsetX * 2,
-                       fRadius1 * 2 * vy - offsetY * 2);
-    rtRadius.Normalize();
-    if (bInverted)
-      rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
-
-    path.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy);
-  } else {
-    CFX_PointF cp;
-    if (bInverted) {
-      cp.x = cp1.x + fRadius1 * vx;
-      cp.y = cp1.y + fRadius1 * vy;
-    } else {
-      cp = cp1;
-    }
-    path.LineTo(cp);
-    path.LineTo(CFX_PointF(cp1.x + fRadius1 * sx + offsetX,
-                           cp1.y + fRadius1 * sy + offsetY));
-  }
-}
-static void XFA_BOX_GetFillPath(CXFA_Box box,
-                                const std::vector<CXFA_Stroke>& strokes,
-                                CFX_RectF rtWidget,
-                                CXFA_Path& fillPath,
-                                uint16_t dwFlags) {
-  if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
-    CXFA_Edge edge = box.GetEdge(0);
-    float fThickness = edge.GetThickness();
-    if (fThickness < 0) {
-      fThickness = 0;
-    }
-    float fHalf = fThickness / 2;
-    int32_t iHand = box.GetHand();
-    if (iHand == XFA_ATTRIBUTEENUM_Left) {
-      rtWidget.Inflate(fHalf, fHalf);
-    } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
-      rtWidget.Deflate(fHalf, fHalf);
-    }
-    XFA_BOX_GetPath_Arc(box, rtWidget, fillPath, dwFlags);
-    return;
-  }
-  bool bSameStyles = true;
-  CXFA_Stroke stroke1 = strokes[0];
-  for (int32_t i = 1; i < 8; i++) {
-    CXFA_Stroke stroke2 = strokes[i];
-    if (!stroke1.SameStyles(stroke2)) {
-      bSameStyles = false;
-      break;
-    }
-    stroke1 = stroke2;
-  }
-  if (bSameStyles) {
-    stroke1 = strokes[0];
-    for (int32_t i = 2; i < 8; i += 2) {
-      CXFA_Stroke stroke2 = strokes[i];
-      if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
-                                           XFA_STROKE_SAMESTYLE_Corner)) {
-        bSameStyles = false;
-        break;
-      }
-      stroke1 = stroke2;
-    }
-    if (bSameStyles) {
-      stroke1 = strokes[0];
-      if (stroke1.IsInverted()) {
-        bSameStyles = false;
-      }
-      if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) {
-        bSameStyles = false;
-      }
-    }
-  }
-  if (bSameStyles) {
-    fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width,
-                          rtWidget.height);
-    return;
-  }
-
-  for (int32_t i = 0; i < 8; i += 2) {
-    float sx = 0.0f;
-    float sy = 0.0f;
-    float vx = 1.0f;
-    float vy = 1.0f;
-    float nx = 1.0f;
-    float ny = 1.0f;
-    CFX_PointF cp1, cp2;
-    CXFA_Corner corner1(strokes[i].GetNode());
-    CXFA_Corner corner2(strokes[(i + 2) % 8].GetNode());
-    float fRadius1 = corner1.GetRadius();
-    float fRadius2 = corner2.GetRadius();
-    bool bInverted = corner1.IsInverted();
-    bool bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
-    if (bRound) {
-      sy = FX_PI / 2;
-    }
-    switch (i) {
-      case 0:
-        cp1 = rtWidget.TopLeft();
-        cp2 = rtWidget.TopRight();
-        vx = 1, vy = 1;
-        nx = -1, ny = 0;
-        if (bRound) {
-          sx = bInverted ? FX_PI / 2 : FX_PI;
-        } else {
-          sx = 1, sy = 0;
-        }
-        break;
-      case 2:
-        cp1 = rtWidget.TopRight();
-        cp2 = rtWidget.BottomRight();
-        vx = -1, vy = 1;
-        nx = 0, ny = -1;
-        if (bRound) {
-          sx = bInverted ? FX_PI : FX_PI * 3 / 2;
-        } else {
-          sx = 0, sy = 1;
-        }
-        break;
-      case 4:
-        cp1 = rtWidget.BottomRight();
-        cp2 = rtWidget.BottomLeft();
-        vx = -1, vy = -1;
-        nx = 1, ny = 0;
-        if (bRound) {
-          sx = bInverted ? FX_PI * 3 / 2 : 0;
-        } else {
-          sx = -1, sy = 0;
-        }
-        break;
-      case 6:
-        cp1 = rtWidget.BottomLeft();
-        cp2 = rtWidget.TopLeft();
-        vx = 1, vy = -1;
-        nx = 0, ny = 1;
-        if (bRound) {
-          sx = bInverted ? 0 : FX_PI / 2;
-        } else {
-          sx = 0;
-          sy = -1;
-        }
-        break;
-    }
-    if (i == 0)
-      fillPath.MoveTo(CFX_PointF(cp1.x, cp1.y + fRadius1));
-
-    if (bRound) {
-      if (fRadius1 < 0)
-        sx -= FX_PI;
-      if (bInverted)
-        sy *= -1;
-
-      CFX_RectF rtRadius(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy);
-      rtRadius.Normalize();
-      if (bInverted)
-        rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
-
-      fillPath.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy);
-    } else {
-      CFX_PointF cp;
-      if (bInverted) {
-        cp.x = cp1.x + fRadius1 * vx;
-        cp.y = cp1.y + fRadius1 * vy;
-      } else {
-        cp = cp1;
-      }
-      fillPath.LineTo(cp);
-      fillPath.LineTo(CFX_PointF(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy));
-    }
-    fillPath.LineTo(CFX_PointF(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny));
-  }
-}
-static void XFA_BOX_Fill_Radial(CXFA_Box box,
-                                CXFA_Graphics* pGS,
-                                CXFA_Path& fillPath,
-                                CFX_RectF rtFill,
-                                CFX_Matrix* pMatrix) {
-  CXFA_Fill fill = box.GetFill();
-  FX_ARGB crStart, crEnd;
-  crStart = fill.GetColor();
-  int32_t iType = fill.GetRadial(crEnd);
-  if (iType != XFA_ATTRIBUTEENUM_ToEdge) {
-    FX_ARGB temp = crEnd;
-    crEnd = crStart;
-    crStart = temp;
-  }
-  CXFA_Shading shading(rtFill.Center(), rtFill.Center(), 0,
-                       sqrt(rtFill.Width() * rtFill.Width() +
-                            rtFill.Height() * rtFill.Height()) /
-                           2,
-                       true, true, crStart, crEnd);
-  pGS->SetFillColor(CXFA_Color(&shading));
-  pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
-}
-
-static void XFA_BOX_Fill_Pattern(CXFA_Box box,
-                                 CXFA_Graphics* pGS,
-                                 CXFA_Path& fillPath,
-                                 CFX_RectF rtFill,
-                                 CFX_Matrix* pMatrix) {
-  CXFA_Fill fill = box.GetFill();
-  FX_ARGB crStart, crEnd;
-  crStart = fill.GetColor();
-  int32_t iType = fill.GetPattern(crEnd);
-  FX_HatchStyle iHatch = FX_HatchStyle::Cross;
-  switch (iType) {
-    case XFA_ATTRIBUTEENUM_CrossDiagonal:
-      iHatch = FX_HatchStyle::DiagonalCross;
-      break;
-    case XFA_ATTRIBUTEENUM_DiagonalLeft:
-      iHatch = FX_HatchStyle::ForwardDiagonal;
-      break;
-    case XFA_ATTRIBUTEENUM_DiagonalRight:
-      iHatch = FX_HatchStyle::BackwardDiagonal;
-      break;
-    case XFA_ATTRIBUTEENUM_Horizontal:
-      iHatch = FX_HatchStyle::Horizontal;
-      break;
-    case XFA_ATTRIBUTEENUM_Vertical:
-      iHatch = FX_HatchStyle::Vertical;
-      break;
-    default:
-      break;
-  }
-
-  CXFA_Pattern pattern(iHatch, crEnd, crStart);
-  pGS->SetFillColor(CXFA_Color(&pattern, 0x0));
-  pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
-}
-
-static void XFA_BOX_Fill_Linear(CXFA_Box box,
-                                CXFA_Graphics* pGS,
-                                CXFA_Path& fillPath,
-                                CFX_RectF rtFill,
-                                CFX_Matrix* pMatrix) {
-  CXFA_Fill fill = box.GetFill();
-  FX_ARGB crStart = fill.GetColor();
-  FX_ARGB crEnd;
-  int32_t iType = fill.GetLinear(crEnd);
-  CFX_PointF ptStart;
-  CFX_PointF ptEnd;
-  switch (iType) {
-    case XFA_ATTRIBUTEENUM_ToRight:
-      ptStart = CFX_PointF(rtFill.left, rtFill.top);
-      ptEnd = CFX_PointF(rtFill.right(), rtFill.top);
-      break;
-    case XFA_ATTRIBUTEENUM_ToBottom:
-      ptStart = CFX_PointF(rtFill.left, rtFill.top);
-      ptEnd = CFX_PointF(rtFill.left, rtFill.bottom());
-      break;
-    case XFA_ATTRIBUTEENUM_ToLeft:
-      ptStart = CFX_PointF(rtFill.right(), rtFill.top);
-      ptEnd = CFX_PointF(rtFill.left, rtFill.top);
-      break;
-    case XFA_ATTRIBUTEENUM_ToTop:
-      ptStart = CFX_PointF(rtFill.left, rtFill.bottom());
-      ptEnd = CFX_PointF(rtFill.left, rtFill.top);
-      break;
-    default:
-      break;
-  }
-  CXFA_Shading shading(ptStart, ptEnd, false, false, crStart, crEnd);
-  pGS->SetFillColor(CXFA_Color(&shading));
-  pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
-}
-
-static void XFA_BOX_Fill(CXFA_Box box,
-                         const std::vector<CXFA_Stroke>& strokes,
-                         CXFA_Graphics* pGS,
-                         const CFX_RectF& rtWidget,
-                         CFX_Matrix* pMatrix,
-                         uint32_t dwFlags) {
-  CXFA_Fill fill = box.GetFill();
-  if (!fill || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
-    return;
-
-  pGS->SaveGraphState();
-  CXFA_Path fillPath;
-  XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath,
-                      (dwFlags & XFA_DRAWBOX_ForceRound) != 0);
-  fillPath.Close();
-  XFA_Element eType = fill.GetFillType();
-  switch (eType) {
-    case XFA_Element::Radial:
-      XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix);
-      break;
-    case XFA_Element::Pattern:
-      XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix);
-      break;
-    case XFA_Element::Linear:
-      XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix);
-      break;
-    default: {
-      FX_ARGB cr;
-      if (eType == XFA_Element::Stipple) {
-        int32_t iRate = fill.GetStipple(cr);
-        if (iRate == 0)
-          iRate = 100;
-        int32_t a;
-        FX_COLORREF rgb;
-        std::tie(a, rgb) = ArgbToColorRef(cr);
-        cr = ArgbEncode(iRate * a / 100, rgb);
-      } else {
-        cr = fill.GetColor();
-      }
-      pGS->SetFillColor(CXFA_Color(cr));
-      pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
-    } break;
-  }
-  pGS->RestoreGraphState();
-}
-static void XFA_BOX_StrokePath(CXFA_Stroke stroke,
-                               CXFA_Path* pPath,
-                               CXFA_Graphics* pGS,
-                               CFX_Matrix* pMatrix) {
-  if (!stroke || !stroke.IsVisible()) {
-    return;
-  }
-  float fThickness = stroke.GetThickness();
-  if (fThickness < 0.001f) {
-    return;
-  }
-  pGS->SaveGraphState();
-  if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) {
-    fThickness = 2 * stroke.GetRadius();
-  }
-  pGS->SetLineWidth(fThickness);
-  pGS->EnableActOnDash();
-  pGS->SetLineCap(CFX_GraphStateData::LineCapButt);
-  XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(),
-                            XFA_ATTRIBUTEENUM_Butt);
-  pGS->SetStrokeColor(CXFA_Color(stroke.GetColor()));
-  pGS->StrokePath(pPath, pMatrix);
-  pGS->RestoreGraphState();
-}
-
-static void XFA_BOX_StrokeArc(CXFA_Box box,
-                              CXFA_Graphics* pGS,
-                              CFX_RectF rtWidget,
-                              CFX_Matrix* pMatrix,
-                              uint32_t dwFlags) {
-  CXFA_Edge edge = box.GetEdge(0);
-  if (!edge || !edge.IsVisible()) {
-    return;
-  }
-  bool bVisible = false;
-  float fThickness = 0;
-  int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
-  if (i3DType) {
-    if (bVisible && fThickness >= 0.001f) {
-      dwFlags |= XFA_DRAWBOX_Lowered3D;
-    }
-  }
-  float fHalf = edge.GetThickness() / 2;
-  if (fHalf < 0) {
-    fHalf = 0;
-  }
-  int32_t iHand = box.GetHand();
-  if (iHand == XFA_ATTRIBUTEENUM_Left) {
-    rtWidget.Inflate(fHalf, fHalf);
-  } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
-    rtWidget.Deflate(fHalf, fHalf);
-  }
-  if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 ||
-      (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) {
-    if (fHalf < 0.001f)
-      return;
-
-    CXFA_Path arcPath;
-    XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags);
-    XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix);
-    return;
-  }
-  pGS->SaveGraphState();
-  pGS->SetLineWidth(fHalf);
-
-  float a, b;
-  a = rtWidget.width / 2.0f;
-  b = rtWidget.height / 2.0f;
-  if (dwFlags & XFA_DRAWBOX_ForceRound) {
-    a = std::min(a, b);
-    b = a;
-  }
-
-  CFX_PointF center = rtWidget.Center();
-  rtWidget.left = center.x - a;
-  rtWidget.top = center.y - b;
-  rtWidget.width = a + a;
-  rtWidget.height = b + b;
-
-  float startAngle = 0, sweepAngle = 360;
-  startAngle = startAngle * FX_PI / 180.0f;
-  sweepAngle = -sweepAngle * FX_PI / 180.0f;
-
-  CXFA_Path arcPath;
-  arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f,
-                 FX_PI);
-
-  pGS->SetStrokeColor(CXFA_Color(0xFF808080));
-  pGS->StrokePath(&arcPath, pMatrix);
-  arcPath.Clear();
-  arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f,
-                 FX_PI);
-
-  pGS->SetStrokeColor(CXFA_Color(0xFFFFFFFF));
-  pGS->StrokePath(&arcPath, pMatrix);
-  rtWidget.Deflate(fHalf, fHalf);
-  arcPath.Clear();
-  arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f,
-                 FX_PI);
-
-  pGS->SetStrokeColor(CXFA_Color(0xFF404040));
-  pGS->StrokePath(&arcPath, pMatrix);
-  arcPath.Clear();
-  arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f,
-                 FX_PI);
-
-  pGS->SetStrokeColor(CXFA_Color(0xFFC0C0C0));
-  pGS->StrokePath(&arcPath, pMatrix);
-  pGS->RestoreGraphState();
-}
-
-static void XFA_Draw3DRect(CXFA_Graphics* pGraphic,
-                           const CFX_RectF& rt,
-                           float fLineWidth,
-                           CFX_Matrix* pMatrix,
-                           FX_ARGB argbTopLeft,
-                           FX_ARGB argbBottomRight) {
-  float fBottom = rt.bottom();
-  float fRight = rt.right();
-  CXFA_Path pathLT;
-  pathLT.MoveTo(CFX_PointF(rt.left, fBottom));
-  pathLT.LineTo(CFX_PointF(rt.left, rt.top));
-  pathLT.LineTo(CFX_PointF(fRight, rt.top));
-  pathLT.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth));
-  pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, rt.top + fLineWidth));
-  pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth));
-  pathLT.LineTo(CFX_PointF(rt.left, fBottom));
-  pGraphic->SetFillColor(CXFA_Color(argbTopLeft));
-  pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix);
-
-  CXFA_Path pathRB;
-  pathRB.MoveTo(CFX_PointF(fRight, rt.top));
-  pathRB.LineTo(CFX_PointF(fRight, fBottom));
-  pathRB.LineTo(CFX_PointF(rt.left, fBottom));
-  pathRB.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth));
-  pathRB.LineTo(CFX_PointF(fRight - fLineWidth, fBottom - fLineWidth));
-  pathRB.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth));
-  pathRB.LineTo(CFX_PointF(fRight, rt.top));
-  pGraphic->SetFillColor(CXFA_Color(argbBottomRight));
-  pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix);
-}
-
-static void XFA_BOX_Stroke_3DRect_Lowered(CXFA_Graphics* pGS,
-                                          CFX_RectF rt,
-                                          float fThickness,
-                                          CFX_Matrix* pMatrix) {
-  float fHalfWidth = fThickness / 2.0f;
-  CFX_RectF rtInner(rt);
-  rtInner.Deflate(fHalfWidth, fHalfWidth);
-
-  CXFA_Path path;
-  path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
-  path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
-  pGS->SetFillColor(CXFA_Color(0xFF000000));
-  pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
-  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0);
-}
-
-static void XFA_BOX_Stroke_3DRect_Raised(CXFA_Graphics* pGS,
-                                         CFX_RectF rt,
-                                         float fThickness,
-                                         CFX_Matrix* pMatrix) {
-  float fHalfWidth = fThickness / 2.0f;
-  CFX_RectF rtInner(rt);
-  rtInner.Deflate(fHalfWidth, fHalfWidth);
-
-  CXFA_Path path;
-  path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
-  path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
-  pGS->SetFillColor(CXFA_Color(0xFF000000));
-  pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
-  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
-}
-
-static void XFA_BOX_Stroke_3DRect_Etched(CXFA_Graphics* pGS,
-                                         CFX_RectF rt,
-                                         float fThickness,
-                                         CFX_Matrix* pMatrix) {
-  XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF);
-
-  float fHalfWidth = fThickness / 2.0f;
-  CFX_RectF rtInner(rt);
-  rtInner.Deflate(fHalfWidth, fHalfWidth);
-  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
-}
-
-static void XFA_BOX_Stroke_3DRect_Embossed(CXFA_Graphics* pGS,
-                                           CFX_RectF rt,
-                                           float fThickness,
-                                           CFX_Matrix* pMatrix) {
-  float fHalfWidth = fThickness / 2.0f;
-  XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000);
-  CFX_RectF rtInner(rt);
-  rtInner.Deflate(fHalfWidth, fHalfWidth);
-  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080);
-}
-static void XFA_BOX_Stroke_Rect(CXFA_Box box,
-                                const std::vector<CXFA_Stroke>& strokes,
-                                CXFA_Graphics* pGS,
-                                CFX_RectF rtWidget,
-                                CFX_Matrix* pMatrix) {
-  bool bVisible = false;
-  float fThickness = 0;
-  int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
-  if (i3DType) {
-    if (!bVisible || fThickness < 0.001f) {
-      return;
-    }
-    switch (i3DType) {
-      case XFA_ATTRIBUTEENUM_Lowered:
-        XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix);
-        break;
-      case XFA_ATTRIBUTEENUM_Raised:
-        XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix);
-        break;
-      case XFA_ATTRIBUTEENUM_Etched:
-        XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix);
-        break;
-      case XFA_ATTRIBUTEENUM_Embossed:
-        XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix);
-        break;
-    }
-    return;
-  }
-  bool bClose = false;
-  bool bSameStyles = true;
-  CXFA_Stroke stroke1 = strokes[0];
-  for (int32_t i = 1; i < 8; i++) {
-    CXFA_Stroke stroke2 = strokes[i];
-    if (!stroke1.SameStyles(stroke2)) {
-      bSameStyles = false;
-      break;
-    }
-    stroke1 = stroke2;
-  }
-  if (bSameStyles) {
-    stroke1 = strokes[0];
-    bClose = true;
-    for (int32_t i = 2; i < 8; i += 2) {
-      CXFA_Stroke stroke2 = strokes[i];
-      if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
-                                           XFA_STROKE_SAMESTYLE_Corner)) {
-        bSameStyles = false;
-        break;
-      }
-      stroke1 = stroke2;
-    }
-    if (bSameStyles) {
-      stroke1 = strokes[0];
-      if (stroke1.IsInverted())
-        bSameStyles = false;
-      if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square)
-        bSameStyles = false;
-    }
-  }
-  bool bStart = true;
-  CXFA_Path path;
-  for (int32_t i = 0; i < 8; i++) {
-    CXFA_Stroke stroke = strokes[i];
-    if ((i % 1) == 0 && stroke.GetRadius() < 0) {
-      bool bEmpty = path.IsEmpty();
-      if (!bEmpty) {
-        XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix);
-        path.Clear();
-      }
-      bStart = true;
-      continue;
-    }
-    XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles);
-    CXFA_Stroke stroke2 = strokes[(i + 1) % 8];
-    bStart = !stroke.SameStyles(stroke2);
-    if (bStart) {
-      XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix);
-      path.Clear();
-    }
-  }
-  bool bEmpty = path.IsEmpty();
-  if (!bEmpty) {
-    if (bClose) {
-      path.Close();
-    }
-    XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix);
-  }
-}
-static void XFA_BOX_Stroke(CXFA_Box box,
-                           const std::vector<CXFA_Stroke>& strokes,
-                           CXFA_Graphics* pGS,
-                           CFX_RectF rtWidget,
-                           CFX_Matrix* pMatrix,
-                           uint32_t dwFlags) {
-  if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
-    XFA_BOX_StrokeArc(box, pGS, rtWidget, pMatrix, dwFlags);
-    return;
-  }
-  bool bVisible = false;
-  for (int32_t j = 0; j < 4; j++) {
-    if (strokes[j * 2 + 1].IsVisible()) {
-      bVisible = true;
-      break;
-    }
-  }
-  if (!bVisible) {
-    return;
-  }
-  for (int32_t i = 1; i < 8; i += 2) {
-    CXFA_Edge edge(strokes[i].GetNode());
-    float fThickness = edge.GetThickness();
-    if (fThickness < 0) {
-      fThickness = 0;
-    }
-    float fHalf = fThickness / 2;
-    int32_t iHand = box.GetHand();
-    switch (i) {
-      case 1:
-        if (iHand == XFA_ATTRIBUTEENUM_Left) {
-          rtWidget.top -= fHalf;
-          rtWidget.height += fHalf;
-        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
-          rtWidget.top += fHalf;
-          rtWidget.height -= fHalf;
-        }
-        break;
-      case 3:
-        if (iHand == XFA_ATTRIBUTEENUM_Left) {
-          rtWidget.width += fHalf;
-        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
-          rtWidget.width -= fHalf;
-        }
-        break;
-      case 5:
-        if (iHand == XFA_ATTRIBUTEENUM_Left) {
-          rtWidget.height += fHalf;
-        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
-          rtWidget.height -= fHalf;
-        }
-        break;
-      case 7:
-        if (iHand == XFA_ATTRIBUTEENUM_Left) {
-          rtWidget.left -= fHalf;
-          rtWidget.width += fHalf;
-        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
-          rtWidget.left += fHalf;
-          rtWidget.width -= fHalf;
-        }
-        break;
-    }
-  }
-  XFA_BOX_Stroke_Rect(box, strokes, pGS, rtWidget, pMatrix);
-}
-void XFA_DrawBox(CXFA_Box box,
-                 CXFA_Graphics* pGS,
-                 const CFX_RectF& rtWidget,
-                 CFX_Matrix* pMatrix,
-                 uint32_t dwFlags) {
-  if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
-    return;
-
-  XFA_Element eType = box.GetElementType();
-  if (eType != XFA_Element::Arc && eType != XFA_Element::Border &&
-      eType != XFA_Element::Rectangle) {
-    return;
-  }
-  std::vector<CXFA_Stroke> strokes;
-  if (!(dwFlags & XFA_DRAWBOX_ForceRound) && eType != XFA_Element::Arc)
-    box.GetStrokes(&strokes);
-
-  XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
-  XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
-}
 
 CXFA_CalcData::CXFA_CalcData() : m_iRefCount(0) {}
 
diff --git a/xfa/fxfa/cxfa_ffwidget.h b/xfa/fxfa/cxfa_ffwidget.h
index 0e7c35e..d7d8707 100644
--- a/xfa/fxfa/cxfa_ffwidget.h
+++ b/xfa/fxfa/cxfa_ffwidget.h
@@ -68,13 +68,9 @@
                             bool bUI = false);
 CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem);
 bool XFA_IsCreateWidget(XFA_Element iType);
+
 #define XFA_DRAWBOX_ForceRound 1
 #define XFA_DRAWBOX_Lowered3D 2
-void XFA_DrawBox(CXFA_Box box,
-                 CXFA_Graphics* pGS,
-                 const CFX_RectF& rtWidget,
-                 CFX_Matrix* pMatrix,
-                 uint32_t dwFlags = 0);
 
 class CXFA_CalcData {
  public:
@@ -157,8 +153,7 @@
   CXFA_FFDoc* GetDoc();
   CXFA_FFApp* GetApp();
   IXFA_AppProvider* GetAppProvider();
-  void InvalidateWidget(const CFX_RectF* pRect = nullptr);
-  void AddInvalidateRect(const CFX_RectF* pRect = nullptr);
+  void AddInvalidateRect();
   bool GetCaptionText(CFX_WideString& wsCap);
   bool IsFocused() const { return !!(m_dwStatus & XFA_WidgetStatus_Focused); }
   CFX_PointF Rotate2Normal(const CFX_PointF& point);
@@ -174,8 +169,12 @@
   void DrawBorder(CXFA_Graphics* pGS,
                   CXFA_Box box,
                   const CFX_RectF& rtBorder,
-                  CFX_Matrix* pMatrix,
-                  uint32_t dwFlags = 0);
+                  CFX_Matrix* pMatrix);
+  void DrawBorderWithFlags(CXFA_Graphics* pGS,
+                           CXFA_Box box,
+                           const CFX_RectF& rtBorder,
+                           CFX_Matrix* pMatrix,
+                           uint32_t dwFlags);
 
   CFX_RectF GetRectWithoutRotate();
   bool IsMatchVisibleStatus(uint32_t dwStatus);
diff --git a/xfa/fxfa/cxfa_fwladapterwidgetmgr.cpp b/xfa/fxfa/cxfa_fwladapterwidgetmgr.cpp
index f4e7527..4dacd03 100644
--- a/xfa/fxfa/cxfa_fwladapterwidgetmgr.cpp
+++ b/xfa/fxfa/cxfa_fwladapterwidgetmgr.cpp
@@ -21,7 +21,7 @@
   if (!pFFWidget)
     return;
 
-  pFFWidget->AddInvalidateRect(nullptr);
+  pFFWidget->AddInvalidateRect();
 }
 
 bool CXFA_FWLAdapterWidgetMgr::GetPopupPos(CFWL_Widget* pWidget,