Bug 1615830 - Don't allow checkboxes to loose aspect-ratio. r=spohl
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sun, 16 Feb 2020 16:04:31 +0000
changeset 514221 3b823d058ef541ec6abd5e781c6b9b4e1b893fbf
parent 514220 dbddba0b73226c95db10e35f3f373929cf728a2f
child 514222 80d17e69d2a5248185373a92851949c091664c0e
push id107465
push userealvarez@mozilla.com
push dateSun, 16 Feb 2020 16:56:11 +0000
treeherderautoland@3b823d058ef5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersspohl
bugs1615830
milestone75.0a1
first release with
nightly linux32
3b823d058ef5 / 75.0a1 / 20200216210001 / files
nightly linux64
3b823d058ef5 / 75.0a1 / 20200216210001 / files
nightly mac
3b823d058ef5 / 75.0a1 / 20200216210001 / files
nightly win32
3b823d058ef5 / 75.0a1 / 20200216210001 / files
nightly win64
3b823d058ef5 / 75.0a1 / 20200216210001 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1615830 - Don't allow checkboxes to loose aspect-ratio. r=spohl Differential Revision: https://phabricator.services.mozilla.com/D63006
widget/nsNativeBasicTheme.cpp
--- a/widget/nsNativeBasicTheme.cpp
+++ b/widget/nsNativeBasicTheme.cpp
@@ -129,16 +129,36 @@ static void ComputeCheckColors(const Eve
       borderColor = sBorderColor;
     }
   }
 
   aBackgroundColor = fillColor;
   aBorderColor = borderColor;
 }
 
+// Checkbox and radio need to preserve aspect-ratio for compat.
+static Rect FixAspectRatio(const Rect& aRect) {
+  Rect rect(aRect);
+  if (rect.width == rect.height) {
+    return rect;
+  }
+
+  if (rect.width > rect.height) {
+    auto diff = rect.width - rect.height;
+    rect.width = rect.height;
+    rect.x += diff / 2;
+  } else {
+    auto diff = rect.height - rect.width;
+    rect.height = rect.width;
+    rect.y += diff / 2;
+  }
+
+  return rect;
+}
+
 static void PaintCheckboxControl(DrawTarget* aDrawTarget, const Rect& aRect,
                                  const EventStates& aState, uint32_t aDpi) {
   uint32_t radius = 3 * aDpi;
   RectCornerRadii innerRadii(radius, radius, radius, radius);
   Rect rect(aRect);
   rect.Round();
   RefPtr<Path> roundedRect =
       MakePathForRoundedRect(*aDrawTarget, rect, innerRadii);
@@ -155,25 +175,27 @@ static void PaintCheckboxControl(DrawTar
 static void PaintCheckMark(DrawTarget* aDrawTarget, const Rect& aRect,
                            const EventStates& aState, uint32_t aDpi) {
   // Points come from the coordinates on a 7X7 unit box centered at 0,0
   const float checkPolygonX[] = {-2.5, -0.7, 2.5};
   const float checkPolygonY[] = {-0.3, 1.7, -1.5};
   const int32_t checkNumPoints = sizeof(checkPolygonX) / sizeof(float);
   const int32_t checkSize = 8;
 
+  auto center = aRect.Center();
+
   // Scale the checkmark based on the smallest dimension
   nscoord paintScale = std::min(aRect.width, aRect.height) / checkSize;
   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
-  Point p = aRect.Center() +
+  Point p = center +
             Point(checkPolygonX[0] * paintScale, checkPolygonY[0] * paintScale);
   builder->MoveTo(p);
   for (int32_t polyIndex = 1; polyIndex < checkNumPoints; polyIndex++) {
-    p = aRect.Center() + Point(checkPolygonX[polyIndex] * paintScale,
-                               checkPolygonY[polyIndex] * paintScale);
+    p = center + Point(checkPolygonX[polyIndex] * paintScale,
+                       checkPolygonY[polyIndex] * paintScale);
     builder->LineTo(p);
   }
   RefPtr<Path> path = builder->Finish();
   aDrawTarget->Stroke(path, ColorPattern(ToDeviceColor(sBackgroundColor)),
                       StrokeOptions(2.0f * aDpi));
 }
 
 static void PaintIndeterminateMark(DrawTarget* aDrawTarget, const Rect& aRect,
@@ -517,31 +539,35 @@ nsNativeBasicTheme::DrawWidgetBackground
       aFrame = parentFrame;
       eventState = GetContentState(parentFrame, aAppearance);
     }
   }
 
   uint32_t dpi = GetDPIRatio(aFrame);
 
   switch (aAppearance) {
-    case StyleAppearance::Radio:
-      PaintRadioControl(dt, devPxRect, eventState, dpi);
+    case StyleAppearance::Radio: {
+      auto rect = FixAspectRatio(devPxRect);
+      PaintRadioControl(dt, rect, eventState, dpi);
       if (IsSelected(aFrame)) {
-        PaintCheckedRadioButton(dt, devPxRect, dpi);
+        PaintCheckedRadioButton(dt, rect, dpi);
       }
       break;
-    case StyleAppearance::Checkbox:
-      PaintCheckboxControl(dt, devPxRect, eventState, dpi);
+    }
+    case StyleAppearance::Checkbox: {
+      auto rect = FixAspectRatio(devPxRect);
+      PaintCheckboxControl(dt, rect, eventState, dpi);
       if (IsChecked(aFrame)) {
-        PaintCheckMark(dt, devPxRect, eventState, dpi);
+        PaintCheckMark(dt, rect, eventState, dpi);
       }
       if (GetIndeterminate(aFrame)) {
-        PaintIndeterminateMark(dt, devPxRect, eventState);
+        PaintIndeterminateMark(dt, rect, eventState);
       }
       break;
+    }
     case StyleAppearance::Textarea:
     case StyleAppearance::Textfield:
     case StyleAppearance::NumberInput:
       PaintTextField(dt, devPxRect, eventState, dpi);
       break;
     case StyleAppearance::Listbox:
     case StyleAppearance::Menulist:
     case StyleAppearance::MenulistTextfield:
@@ -712,17 +738,17 @@ bool nsNativeBasicTheme::GetWidgetOverfl
 
   return false;
 }
 
 NS_IMETHODIMP
 nsNativeBasicTheme::GetMinimumWidgetSize(nsPresContext* aPresContext,
                                          nsIFrame* aFrame,
                                          StyleAppearance aAppearance,
-                                         mozilla::LayoutDeviceIntSize* aResult,
+                                         LayoutDeviceIntSize* aResult,
                                          bool* aIsOverridable) {
   aResult->width = aResult->height = 17 * GetDPIRatio(aFrame);
   *aIsOverridable = true;
   return NS_OK;
 }
 
 nsITheme::Transparency nsNativeBasicTheme::GetWidgetTransparency(
     nsIFrame* aFrame, StyleAppearance aAppearance) {