Diff
Modified: trunk/LayoutTests/ChangeLog (272748 => 272749)
--- trunk/LayoutTests/ChangeLog 2021-02-11 21:49:12 UTC (rev 272748)
+++ trunk/LayoutTests/ChangeLog 2021-02-11 21:57:38 UTC (rev 272749)
@@ -1,3 +1,23 @@
+2021-02-11 Aditya Keerthi <[email protected]>
+
+ [iOS] Some checkboxes and radio buttons are clipped on top
+ https://bugs.webkit.org/show_bug.cgi?id=221736
+ <rdar://problem/73956812>
+
+ Reviewed by Simon Fraser.
+
+ Added reference mismatch tests to verify that the clipping no longer
+ occurs. The tests work by drawing an overlay smaller than the actual
+ size of the checkbox/radio input. If the input is clipped, only the
+ overlay will be visible, matching the "-expected-mismatch.html".
+ However, if the input is drawn correctly, the overlay will not cover
+ the entire input, and a mismatch will occur.
+
+ * fast/forms/ios/form-control-refresh/checkbox/subpixel-clipping-expected-mismatch.html: Added.
+ * fast/forms/ios/form-control-refresh/checkbox/subpixel-clipping.html: Added.
+ * fast/forms/ios/form-control-refresh/radio/subpixel-clipping-expected-mismatch.html: Added.
+ * fast/forms/ios/form-control-refresh/radio/subpixel-clipping.html: Added.
+
2021-02-11 Chris Dumez <[email protected]>
[ MacOS Debug wk2] imported/w3c/web-platform-tests/worklets/animation-worklet-service-worker-interception.https.html is a flakey text failure
Added: trunk/LayoutTests/fast/forms/ios/form-control-refresh/checkbox/subpixel-clipping-expected-mismatch.html (0 => 272749)
--- trunk/LayoutTests/fast/forms/ios/form-control-refresh/checkbox/subpixel-clipping-expected-mismatch.html (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/form-control-refresh/checkbox/subpixel-clipping-expected-mismatch.html 2021-02-11 21:57:38 UTC (rev 272749)
@@ -0,0 +1,20 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ IOSFormControlRefreshEnabled=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+ #overlay {
+ position: absolute;
+ top: 1.5px;
+ left: 0px;
+ height: 15.5px;
+ width: 16px;
+ margin: 0px;
+ background-color: red;
+ }
+</style>
+</head>
+<body>
+<div id="overlay"></div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/forms/ios/form-control-refresh/checkbox/subpixel-clipping.html (0 => 272749)
--- trunk/LayoutTests/fast/forms/ios/form-control-refresh/checkbox/subpixel-clipping.html (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/form-control-refresh/checkbox/subpixel-clipping.html 2021-02-11 21:57:38 UTC (rev 272749)
@@ -0,0 +1,30 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ IOSFormControlRefreshEnabled=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+ input {
+ position: absolute;
+ top: 1.5px;
+ left: 0px;
+ height: 16px;
+ width: 16px;
+ margin: 0px;
+ }
+
+ #overlay {
+ position: absolute;
+ top: 1.5px;
+ left: 0px;
+ height: 15.5px;
+ width: 16px;
+ margin: 0px;
+ background-color: red;
+ }
+</style>
+</head>
+<body>
+<input type="checkbox" checked disabled>
+<div id="overlay"></div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/forms/ios/form-control-refresh/radio/subpixel-clipping-expected-mismatch.html (0 => 272749)
--- trunk/LayoutTests/fast/forms/ios/form-control-refresh/radio/subpixel-clipping-expected-mismatch.html (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/form-control-refresh/radio/subpixel-clipping-expected-mismatch.html 2021-02-11 21:57:38 UTC (rev 272749)
@@ -0,0 +1,20 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ IOSFormControlRefreshEnabled=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+ #overlay {
+ position: absolute;
+ top: 1.5px;
+ left: 0px;
+ height: 15.5px;
+ width: 16px;
+ margin: 0px;
+ background-color: red;
+ }
+</style>
+</head>
+<body>
+<div id="overlay"></div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/forms/ios/form-control-refresh/radio/subpixel-clipping.html (0 => 272749)
--- trunk/LayoutTests/fast/forms/ios/form-control-refresh/radio/subpixel-clipping.html (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/form-control-refresh/radio/subpixel-clipping.html 2021-02-11 21:57:38 UTC (rev 272749)
@@ -0,0 +1,30 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ IOSFormControlRefreshEnabled=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+ input {
+ position: absolute;
+ top: 1.5px;
+ left: 0px;
+ height: 16px;
+ width: 16px;
+ margin: 0px;
+ }
+
+ #overlay {
+ position: absolute;
+ top: 1.5px;
+ left: 0px;
+ height: 15.5px;
+ width: 16px;
+ margin: 0px;
+ background-color: red;
+ }
+</style>
+</head>
+<body>
+<input type="radio" checked disabled>
+<div id="overlay"></div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (272748 => 272749)
--- trunk/Source/WebCore/ChangeLog 2021-02-11 21:49:12 UTC (rev 272748)
+++ trunk/Source/WebCore/ChangeLog 2021-02-11 21:57:38 UTC (rev 272749)
@@ -1,3 +1,54 @@
+2021-02-11 Aditya Keerthi <[email protected]>
+
+ [iOS] Some checkboxes and radio buttons are clipped on top
+ https://bugs.webkit.org/show_bug.cgi?id=221736
+ <rdar://problem/73956812>
+
+ Reviewed by Simon Fraser.
+
+ The clipping occurs due to integral rounding of the paint rect in
+ both RenderBox::paintBoxDecorations, as well as using the integral
+ rect in RenderTheme::paint. To fix, use FloatRect and the device
+ pixel snapped rect when painting these elements.
+
+ Tests: fast/forms/ios/form-control-refresh/checkbox/subpixel-clipping.html
+ fast/forms/ios/form-control-refresh/radio/subpixel-clipping.html
+
+ * rendering/RenderBox.cpp:
+ (WebCore::RenderBox::paintBoxDecorations):
+
+ Moved into RenderTheme to avoid duplication.
+
+ * rendering/RenderElement.cpp:
+ (WebCore::RenderElement::paintOutline):
+
+ Moved into RenderTheme to avoid duplication.
+
+ * rendering/RenderTheme.cpp:
+ (WebCore::RenderTheme::paint):
+
+ Use the device pixel snapped rect when painting checkboxes and radio
+ buttons.
+
+ * rendering/RenderTheme.h:
+ (WebCore::RenderTheme::adjustedPaintRect):
+
+ On most platforms, no adjustment is performed.
+
+ (WebCore::RenderTheme::paintCheckbox):
+ (WebCore::RenderTheme::paintRadio):
+ * rendering/RenderThemeIOS.h:
+ * rendering/RenderThemeIOS.mm:
+ (WebCore::RenderThemeIOS::adjustedPaintRect):
+
+ On iOS, radio buttons and checkboxes always have a square painting
+ rect. Updated to use FloatRect, rather than IntRect, to avoid
+ clipping.
+
+ (WebCore::RenderThemeIOS::paintCheckbox):
+ (WebCore::RenderThemeIOS::paintRadio):
+ * rendering/RenderThemeWin.h:
+
2021-02-11 Jer Noble <[email protected]>
[Cocoa][GPUP] Move RemoteCommandListener into the GPU Process
Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (272748 => 272749)
--- trunk/Source/WebCore/rendering/RenderBox.cpp 2021-02-11 21:49:12 UTC (rev 272748)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp 2021-02-11 21:57:38 UTC (rev 272749)
@@ -1425,15 +1425,7 @@
paintRect.moveBy(paintOffset);
adjustBorderBoxRectForPainting(paintRect);
-#if PLATFORM(IOS_FAMILY)
- // Workaround for <rdar://problem/6209763>. Force the painting bounds of checkboxes and radio controls to be square.
- // FIXME: Consolidate this code with the same code in RenderElement::paintOutline(). See <https://bugs.webkit.org/show_bug.cgi?id=194781>.
- if (style().appearance() == CheckboxPart || style().appearance() == RadioPart) {
- int width = std::min(paintRect.width(), paintRect.height());
- int height = width;
- paintRect = IntRect { paintRect.x(), paintRect.y() + (this->height() - height) / 2, width, height }; // Vertically center the checkbox, like on desktop
- }
-#endif
+ paintRect = theme().adjustedPaintRect(*this, paintRect);
BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context());
// FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (272748 => 272749)
--- trunk/Source/WebCore/rendering/RenderElement.cpp 2021-02-11 21:49:12 UTC (rev 272748)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp 2021-02-11 21:57:38 UTC (rev 272749)
@@ -2047,15 +2047,8 @@
if (styleToUse.outlineStyleIsAuto() == OutlineIsAuto::On && !theme().supportsFocusRing(styleToUse)) {
Vector<LayoutRect> focusRingRects;
LayoutRect paintRectToUse { paintRect };
-#if PLATFORM(IOS_FAMILY)
- // Workaround for <rdar://problem/6209763>. Force the painting bounds of checkboxes and radio controls to be square.
- // FIXME: Consolidate this code with the same code in RenderBox::paintBoxDecorations(). See <https://bugs.webkit.org/show_bug.cgi?id=194781>.
- if (style().appearance() == CheckboxPart || style().appearance() == RadioPart) {
- int width = std::min(paintRect.width(), paintRect.height());
- int height = width;
- paintRectToUse = IntRect { paintRect.x(), paintRect.y() + (downcast<RenderBox>(*this).height() - height) / 2, width, height }; // Vertically center the checkbox, like on desktop
- }
-#endif
+ if (is<RenderBox>(*this))
+ paintRectToUse = theme().adjustedPaintRect(downcast<RenderBox>(*this), paintRectToUse);
addFocusRingRects(focusRingRects, paintRectToUse.location(), paintInfo.paintContainer);
paintFocusRing(paintInfo, styleToUse, focusRingRects);
}
Modified: trunk/Source/WebCore/rendering/RenderTheme.cpp (272748 => 272749)
--- trunk/Source/WebCore/rendering/RenderTheme.cpp 2021-02-11 21:49:12 UTC (rev 272748)
+++ trunk/Source/WebCore/rendering/RenderTheme.cpp 2021-02-11 21:57:38 UTC (rev 272749)
@@ -324,9 +324,9 @@
switch (part) {
#if !USE(NEW_THEME)
case CheckboxPart:
- return paintCheckbox(box, paintInfo, integralSnappedRect);
+ return paintCheckbox(box, paintInfo, devicePixelSnappedRect);
case RadioPart:
- return paintRadio(box, paintInfo, integralSnappedRect);
+ return paintRadio(box, paintInfo, devicePixelSnappedRect);
#if ENABLE(INPUT_TYPE_COLOR)
case ColorWellPart:
return paintColorWell(box, paintInfo, integralSnappedRect);
Modified: trunk/Source/WebCore/rendering/RenderTheme.h (272748 => 272749)
--- trunk/Source/WebCore/rendering/RenderTheme.h 2021-02-11 21:49:12 UTC (rev 272748)
+++ trunk/Source/WebCore/rendering/RenderTheme.h 2021-02-11 21:57:38 UTC (rev 272749)
@@ -101,6 +101,8 @@
virtual String colorInputStyleSheet(const Settings&) const;
#endif
+ virtual LayoutRect adjustedPaintRect(const RenderBox&, const LayoutRect& paintRect) const { return paintRect; }
+
// A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline
// position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
// controls that need to do this.
@@ -287,11 +289,11 @@
#if !USE(NEW_THEME)
// Methods for each appearance value.
virtual void adjustCheckboxStyle(RenderStyle&, const Element*) const;
- virtual bool paintCheckbox(const RenderObject&, const PaintInfo&, const IntRect&) { return true; }
+ virtual bool paintCheckbox(const RenderObject&, const PaintInfo&, const FloatRect&) { return true; }
virtual void setCheckboxSize(RenderStyle&) const { }
virtual void adjustRadioStyle(RenderStyle&, const Element*) const;
- virtual bool paintRadio(const RenderObject&, const PaintInfo&, const IntRect&) { return true; }
+ virtual bool paintRadio(const RenderObject&, const PaintInfo&, const FloatRect&) { return true; }
virtual void setRadioSize(RenderStyle&) const { }
virtual void adjustButtonStyle(RenderStyle&, const Element*) const;
Modified: trunk/Source/WebCore/rendering/RenderThemeIOS.h (272748 => 272749)
--- trunk/Source/WebCore/rendering/RenderThemeIOS.h 2021-02-11 21:49:12 UTC (rev 272748)
+++ trunk/Source/WebCore/rendering/RenderThemeIOS.h 2021-02-11 21:57:38 UTC (rev 272749)
@@ -72,6 +72,8 @@
LengthBox popupInternalPaddingBox(const RenderStyle&, const Settings&) const override;
+ LayoutRect adjustedPaintRect(const RenderBox&, const LayoutRect&) const override;
+
int baselinePosition(const RenderBox&) const override;
bool isControlStyled(const RenderStyle&, const RenderStyle& userAgentStyle) const override;
@@ -112,8 +114,8 @@
void paintSearchFieldDecorations(const RenderObject&, const PaintInfo&, const IntRect&) override;
#if ENABLE(IOS_FORM_CONTROL_REFRESH)
- bool paintCheckbox(const RenderObject&, const PaintInfo&, const IntRect&) override;
- bool paintRadio(const RenderObject&, const PaintInfo&, const IntRect&) override;
+ bool paintCheckbox(const RenderObject&, const PaintInfo&, const FloatRect&) override;
+ bool paintRadio(const RenderObject&, const PaintInfo&, const FloatRect&) override;
Seconds animationRepeatIntervalForProgressBar(const RenderProgress&) const final;
Modified: trunk/Source/WebCore/rendering/RenderThemeIOS.mm (272748 => 272749)
--- trunk/Source/WebCore/rendering/RenderThemeIOS.mm 2021-02-11 21:49:12 UTC (rev 272748)
+++ trunk/Source/WebCore/rendering/RenderThemeIOS.mm 2021-02-11 21:57:38 UTC (rev 272749)
@@ -453,6 +453,18 @@
}
}
+LayoutRect RenderThemeIOS::adjustedPaintRect(const RenderBox& box, const LayoutRect& paintRect) const
+{
+ // Workaround for <rdar://problem/6209763>. Force the painting bounds of checkboxes and radio controls to be square.
+ if (box.style().appearance() == CheckboxPart || box.style().appearance() == RadioPart) {
+ float width = std::min(paintRect.width(), paintRect.height());
+ float height = width;
+ return enclosingLayoutRect(FloatRect(paintRect.x(), paintRect.y() + (box.height() - height) / 2, width, height)); // Vertically center the checkbox, like on desktop
+ }
+
+ return paintRect;
+}
+
int RenderThemeIOS::baselinePosition(const RenderBox& box) const
{
if (box.style().appearance() == CheckboxPart || box.style().appearance() == RadioPart)
@@ -2050,7 +2062,7 @@
constexpr auto menulistButtonColor = SRGBA<uint8_t> { 97, 172, 255 };
-bool RenderThemeIOS::paintCheckbox(const RenderObject& box, const PaintInfo& paintInfo, const IntRect& rect)
+bool RenderThemeIOS::paintCheckbox(const RenderObject& box, const PaintInfo& paintInfo, const FloatRect& rect)
{
if (!box.settings().iOSFormControlRefreshEnabled())
return true;
@@ -2108,7 +2120,7 @@
return false;
}
-bool RenderThemeIOS::paintRadio(const RenderObject& box, const PaintInfo& paintInfo, const IntRect& rect)
+bool RenderThemeIOS::paintRadio(const RenderObject& box, const PaintInfo& paintInfo, const FloatRect& rect)
{
if (!box.settings().iOSFormControlRefreshEnabled())
return true;
Modified: trunk/Source/WebCore/rendering/RenderThemeWin.h (272748 => 272749)
--- trunk/Source/WebCore/rendering/RenderThemeWin.h 2021-02-11 21:49:12 UTC (rev 272748)
+++ trunk/Source/WebCore/rendering/RenderThemeWin.h 2021-02-11 21:57:38 UTC (rev 272749)
@@ -61,12 +61,12 @@
Color systemColor(CSSValueID, OptionSet<StyleColor::Options>) const override;
- bool paintCheckbox(const RenderObject& o, const PaintInfo& i, const IntRect& r) override
- { return paintButton(o, i, r); }
+ bool paintCheckbox(const RenderObject& o, const PaintInfo& i, const FloatRect& r) override
+ { return paintButton(o, i, IntRect(r)); }
void setCheckboxSize(RenderStyle&) const override;
- bool paintRadio(const RenderObject& o, const PaintInfo& i, const IntRect& r) override
- { return paintButton(o, i, r); }
+ bool paintRadio(const RenderObject& o, const PaintInfo& i, const FloatRect& r) override
+ { return paintButton(o, i, IntRect(r)); }
void setRadioSize(RenderStyle& style) const override
{ return setCheckboxSize(style); }