diff --git a/docs/README.md b/docs/README.md index 01663cc01776..98ae1ad9a79a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -96,9 +96,8 @@ These individual tutorials expand on topics discussed in the guide above. * [Chrome Extensions Support](api/extensions.md) * [Breaking API Changes](breaking-changes.md) -### Custom Web Features: +### Custom DOM Elements: -* [`-electron-corner-smoothing` CSS Rule](api/corner-smoothing-css.md) * [`` Tag](api/webview-tag.md) * [`window.open` Function](api/window-open.md) diff --git a/docs/api/corner-smoothing-css.md b/docs/api/corner-smoothing-css.md deleted file mode 100644 index 029e74657ff3..000000000000 --- a/docs/api/corner-smoothing-css.md +++ /dev/null @@ -1,78 +0,0 @@ -## CSS Rule: `-electron-corner-smoothing` - -> Smoothes out the corner rounding of the `border-radius` CSS rule. - -The rounded corners of elements with [the `border-radius` CSS rule](https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius) can be smoothed out using the `-electron-corner-smoothing` CSS rule. This smoothness is very similar to Apple's "continuous" rounded corners in SwiftUI and Figma's "corner smoothing" control on design elements. - -![There is a black rectangle on the left using simple rounded corners, and a blue rectangle on the right using smooth rounded corners. In between those rectangles is a magnified view of the same corner from both rectangles overlapping to show the subtle difference in shape.](../images/corner-smoothing-summary.svg) - -Integrating with the operating system and its design language is important to many desktop applications. The shape of a rounded corner can be a subtle detail to many users. However, aligning closely to the system's design language that users are familiar with makes the application's design feel familiar too. Beyond matching the design language of macOS, designers may decide to use smoother round corners for many other reasons. - -`-electron-corner-smoothing` affects the shape of borders, outlines, and shadows on the target element. Mirroring the behavior of `border-radius`, smoothing will gradually back off if an element's size is too small for the chosen value. - -The `-electron-corner-smoothing` CSS rule is **only implemented for Electron** and has no effect in browsers. Avoid using this rule outside of Electron. This CSS rule is considered experimental and may require migration in the future if replaced by a CSS standard. - -### Example - -The following example shows the effect of corner smoothing at different percents. - -```css -.box { - width: 128px; - height: 128px; - background-color: cornflowerblue; - border-radius: 24px; - -electron-corner-smoothing: var(--percent); /* Column header in table below. */ -} -``` - -| 0% | 30% | 60% | 100% | -| --- | --- | --- | --- | -| ![A rectangle with round corners at 0% smoothness](../images/corner-smoothing-example-0.svg) | ![A rectangle with round corners at 30% smoothness](../images/corner-smoothing-example-30.svg) | ![A rectangle with round corners at 60% smoothness](../images/corner-smoothing-example-60.svg) | ![A rectangle with round corners at 100% smoothness](../images/corner-smoothing-example-100.svg) | - -### Matching the system UI - -Use the `system-ui` keyword to match the smoothness to the OS design language. - -```css -.box { - width: 128px; - height: 128px; - background-color: cornflowerblue; - border-radius: 24px; - -electron-corner-smoothing: system-ui; /* Match the system UI design. */ -} -``` - -| OS: | macOS | Windows, Linux | -| --- | --- | --- | -| Value: | `60%` | `0%` | -| Example: | ![A rectangle with round corners whose smoothness matches macOS](../images/corner-smoothing-example-60.svg) | ![A rectangle with round corners whose smoothness matches Windows and Linux](../images/corner-smoothing-example-0.svg) | - -### Controlling availibility - -This CSS rule can be disabled by setting [the `cornerSmoothingCSS` web preference](./structures/web-preferences.md) to `false`. - -```js -const myWindow = new BrowserWindow({ - // [...] - webPreferences: { - enableCornerSmoothingCSS: false // Disables the `-electron-corner-smoothing` CSS rule - } -}) -``` - -The CSS rule will still parse, but will have no visual effect. - -### Formal reference - -* **Initial value**: `0%` -* **Inherited**: No -* **Animatable**: No -* **Computed value**: As specified - -```css --electron-corner-smoothing = - | - system-ui -``` diff --git a/docs/api/structures/web-preferences.md b/docs/api/structures/web-preferences.md index 4e6710523615..26ead57c2329 100644 --- a/docs/api/structures/web-preferences.md +++ b/docs/api/structures/web-preferences.md @@ -149,7 +149,6 @@ `WebContents` when the preferred size changes. Default is `false`. * `transparent` boolean (optional) - Whether to enable background transparency for the guest page. Default is `true`. **Note:** The guest page's text and background colors are derived from the [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme) of its root element. When transparency is enabled, the text color will still change accordingly but the background will remain transparent. * `enableDeprecatedPaste` boolean (optional) _Deprecated_ - Whether to enable the `paste` [execCommand](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand). Default is `false`. -* `enableCornerSmoothingCSS` boolean (optional) _Experimental_ - Whether the [`-electron-corner-smoothing` CSS rule](../corner-smoothing-css.md) is enabled. Default is `true`. [chrome-content-scripts]: https://developer.chrome.com/extensions/content_scripts#execution-environment [runtime-enabled-features]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5 diff --git a/docs/images/corner-smoothing-example-0.svg b/docs/images/corner-smoothing-example-0.svg deleted file mode 100644 index 928435ed0b00..000000000000 --- a/docs/images/corner-smoothing-example-0.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/docs/images/corner-smoothing-example-100.svg b/docs/images/corner-smoothing-example-100.svg deleted file mode 100644 index 34d0802239be..000000000000 --- a/docs/images/corner-smoothing-example-100.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/docs/images/corner-smoothing-example-30.svg b/docs/images/corner-smoothing-example-30.svg deleted file mode 100644 index 4996a25253ce..000000000000 --- a/docs/images/corner-smoothing-example-30.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/docs/images/corner-smoothing-example-60.svg b/docs/images/corner-smoothing-example-60.svg deleted file mode 100644 index cb1e68a8ff68..000000000000 --- a/docs/images/corner-smoothing-example-60.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/docs/images/corner-smoothing-summary.svg b/docs/images/corner-smoothing-summary.svg deleted file mode 100644 index 75bffa8e259d..000000000000 --- a/docs/images/corner-smoothing-summary.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/filenames.auto.gni b/filenames.auto.gni index df963e2c831b..a2514d5e9967 100644 --- a/filenames.auto.gni +++ b/filenames.auto.gni @@ -14,7 +14,6 @@ auto_filenames = { "docs/api/content-tracing.md", "docs/api/context-bridge.md", "docs/api/cookies.md", - "docs/api/corner-smoothing-css.md", "docs/api/crash-reporter.md", "docs/api/debugger.md", "docs/api/desktop-capturer.md", diff --git a/filenames.gni b/filenames.gni index ea1637c99030..0d58b9e147ff 100644 --- a/filenames.gni +++ b/filenames.gni @@ -718,8 +718,6 @@ filenames = { "shell/renderer/electron_renderer_client.h", "shell/renderer/electron_sandboxed_renderer_client.cc", "shell/renderer/electron_sandboxed_renderer_client.h", - "shell/renderer/electron_smooth_round_rect.cc", - "shell/renderer/electron_smooth_round_rect.h", "shell/renderer/preload_realm_context.cc", "shell/renderer/preload_realm_context.h", "shell/renderer/preload_utils.cc", diff --git a/patches/chromium/.patches b/patches/chromium/.patches index a6ba4a2558fd..4ed5a6dec20b 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -134,7 +134,6 @@ fix_software_compositing_infinite_loop.patch fix_add_method_which_disables_headless_mode_on_native_widget.patch refactor_unfilter_unresponsive_events.patch build_disable_thin_lto_mac.patch -feat_corner_smoothing_css_rule_and_blink_painting.patch build_add_public_config_simdutf_config.patch revert_code_health_clean_up_stale_macwebcontentsocclusion.patch ignore_parse_errors_for_pkey_appusermodel_toastactivatorclsid.patch diff --git a/patches/chromium/feat_corner_smoothing_css_rule_and_blink_painting.patch b/patches/chromium/feat_corner_smoothing_css_rule_and_blink_painting.patch deleted file mode 100644 index 9b3b2ae085da..000000000000 --- a/patches/chromium/feat_corner_smoothing_css_rule_and_blink_painting.patch +++ /dev/null @@ -1,522 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Calvin Watford -Date: Mon, 9 Dec 2024 16:58:15 -0700 -Subject: feat: Corner Smoothing CSS rule and Blink painting - -This patch implements the `-electron-corner-smoothing` CSS rule by -making three primary changes to Blink: - -1. Adds the `-electron-corner-smoothing` CSS rule: - * Metadata in `blink/renderer/core/css/css_properties.json5` - * Parsing in `blink/renderer/core/css/properties/longhands/longhands_custom.cc` - * Other required definitions for all CSS rules (`css_property_id.mojom`, `css_property_equality.cc`) - -2. Modifies how Blink paints rounded rectangles: - * Augments `blink::FloatRoundedRect` to store smoothness & hook into - drawing smooth corners. - * Modifies all call sites of `blink::FloatRoundedRect::operator SkRRect` - to identify and use smooth rounded corners. - -3. Adds a renderer preference / web setting: - * Controls whether the CSS rule is available. - -diff --git a/third_party/blink/common/renderer_preferences/renderer_preferences_mojom_traits.cc b/third_party/blink/common/renderer_preferences/renderer_preferences_mojom_traits.cc -index 25cf6b544dcee15a9616b6963eaae0264aba3db6..13d5b30d00ce8dca96eb3bc5454f9d353375d4c6 100644 ---- a/third_party/blink/common/renderer_preferences/renderer_preferences_mojom_traits.cc -+++ b/third_party/blink/common/renderer_preferences/renderer_preferences_mojom_traits.cc -@@ -128,6 +128,8 @@ bool StructTraitselectron_corner_smoothing_css = data.electron_corner_smoothing_css(); -+ - return true; - } - -diff --git a/third_party/blink/public/common/renderer_preferences/renderer_preferences.h b/third_party/blink/public/common/renderer_preferences/renderer_preferences.h -index cae096396b0635f1c4bba6ac8fee47fd957dc698..03db6cddab5cd1b9f3f7c90390bc53baa9e14b65 100644 ---- a/third_party/blink/public/common/renderer_preferences/renderer_preferences.h -+++ b/third_party/blink/public/common/renderer_preferences/renderer_preferences.h -@@ -91,6 +91,7 @@ struct BLINK_COMMON_EXPORT RendererPreferences { - bool caret_browsing_enabled{false}; - bool uses_platform_autofill{false}; - std::vector explicitly_allowed_network_ports; -+ bool electron_corner_smoothing_css; - - RendererPreferences(); - RendererPreferences(const RendererPreferences& other); -diff --git a/third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h b/third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h -index 33b4bd3f0c9488f1013aea026c7fe559ba750cd8..6b4157199c14a4c276e65512e89f2429253aec5c 100644 ---- a/third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h -+++ b/third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h -@@ -275,6 +275,11 @@ struct BLINK_COMMON_EXPORT - return data.explicitly_allowed_network_ports; - } - -+ static const bool& electron_corner_smoothing_css( -+ const ::blink::RendererPreferences& data) { -+ return data.electron_corner_smoothing_css; -+ } -+ - static bool Read(blink::mojom::RendererPreferencesDataView, - ::blink::RendererPreferences* out); - }; -diff --git a/third_party/blink/public/mojom/renderer_preferences.mojom b/third_party/blink/public/mojom/renderer_preferences.mojom -index bbcec1dcdaaaf932b3d82c64e8aeb2e7c04b05bf..689205607a763c1d6e040069b1357d84e8ba4bd5 100644 ---- a/third_party/blink/public/mojom/renderer_preferences.mojom -+++ b/third_party/blink/public/mojom/renderer_preferences.mojom -@@ -201,4 +201,6 @@ struct RendererPreferences { - bool uses_platform_autofill = false; - - array explicitly_allowed_network_ports; -+ -+ bool electron_corner_smoothing_css; - }; -diff --git a/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom b/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom -index ff34492a1b3e0d57847a35f5921337debdf14d10..02e77d7f080de9311f8ac70e3e935dbd38cb285f 100644 ---- a/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom -+++ b/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom -@@ -48,6 +48,7 @@ enum CSSSampleId { - kInternalForcedVisitedColor = 0, - kInternalOverflowBlock = 0, - kInternalOverflowInline = 0, -+ kElectronCornerSmoothing = 0, - - // This CSSSampleId represents page load for CSS histograms. It is recorded once - // per page visit for each CSS histogram being logged on the blink side and the -diff --git a/third_party/blink/public/web/web_settings.h b/third_party/blink/public/web/web_settings.h -index 0255879e4ae048554041ca03891fbc7ba8484187..8248d8f54eb5d35caa39a306a6477ace6597b03a 100644 ---- a/third_party/blink/public/web/web_settings.h -+++ b/third_party/blink/public/web/web_settings.h -@@ -284,6 +284,7 @@ class WebSettings { - virtual void SetModalContextMenu(bool) = 0; - virtual void SetRequireTransientActivationAndAuthorizationForSubAppsAPIs( - bool) = 0; -+ virtual void SetCornerSmoothingCSS(bool) = 0; - - protected: - ~WebSettings() = default; -diff --git a/third_party/blink/renderer/build/scripts/core/css/css_properties.py b/third_party/blink/renderer/build/scripts/core/css/css_properties.py -index 753ba8990f722bafd1770a5e70307cff3764d3f1..16cec517d72887c089f85867e8e37c03199ab394 100755 ---- a/third_party/blink/renderer/build/scripts/core/css/css_properties.py -+++ b/third_party/blink/renderer/build/scripts/core/css/css_properties.py -@@ -311,7 +311,13 @@ class CSSProperties(object): - name_without_leading_dash = property_.name.original - if name_without_leading_dash.startswith('-'): - name_without_leading_dash = name_without_leading_dash[1:] -+ # Extra sort level to avoid -internal-* properties being assigned -+ # values too large to fit in a byte. -+ internal_weight = 0 -+ if property_.name.original.startswith('-internal'): -+ internal_weight = -1 - property_.sorting_key = (-property_.priority, -+ internal_weight, - name_without_leading_dash) - - sorting_keys = {} -diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5 -index 561cf75a5fc16e94485296e4607df70037e53525..23ece6535cab358fdc8f9dfc1481c1a020475daf 100644 ---- a/third_party/blink/renderer/core/css/css_properties.json5 -+++ b/third_party/blink/renderer/core/css/css_properties.json5 -@@ -8732,6 +8732,24 @@ - property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"], - }, - -+ { -+ name: "-electron-corner-smoothing", -+ property_methods: ["ParseSingleValue"], -+ field_group: "*", -+ field_template: "external", -+ // To keep this patch small, Length is used instead of a more descriptive -+ // custom type. -+ // - `system-ui` = `Length::Auto()` -+ // - percent = `Length::Percent` -+ type_name: "Length", -+ converter: "ConvertCornerSmoothing", -+ keywords: ["system-ui"], -+ default_value: "Length::None()", -+ typedom_types: ["Keyword", "Percentage"], -+ is_border_radius: true, -+ invalidate: ["paint", "border-radius", "clip"], -+ }, -+ - // Visited properties. - { - name: "-internal-visited-color", -diff --git a/third_party/blink/renderer/core/css/css_property_equality.cc b/third_party/blink/renderer/core/css/css_property_equality.cc -index d0c6c6b54dd773c6d3f8b9767b126689198df4ee..2348a1d8ebb1d734ee8cea32b9d67adf3f5fb605 100644 ---- a/third_party/blink/renderer/core/css/css_property_equality.cc -+++ b/third_party/blink/renderer/core/css/css_property_equality.cc -@@ -346,6 +346,8 @@ bool CSSPropertyEquality::PropertiesEqual(const PropertyHandle& property, - return a.DominantBaseline() == b.DominantBaseline(); - case CSSPropertyID::kDynamicRangeLimit: - return a.GetDynamicRangeLimit() == b.GetDynamicRangeLimit(); -+ case CSSPropertyID::kElectronCornerSmoothing: -+ return a.ElectronCornerSmoothing() == b.ElectronCornerSmoothing(); - case CSSPropertyID::kEmptyCells: - return a.EmptyCells() == b.EmptyCells(); - case CSSPropertyID::kFill: -diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc -index b1b513c8d89055f3e77d406f0d889243b5e7ad7f..2b0a37f496fad6b7b56896cc1811f624e89e9aad 100644 ---- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc -+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc -@@ -11826,5 +11826,25 @@ const CSSValue* InternalEmptyLineHeight::ParseSingleValue( - CSSValueID::kNone>(stream); - } - -+const CSSValue* ElectronCornerSmoothing::ParseSingleValue( -+ CSSParserTokenStream& stream, -+ const CSSParserContext& context, -+ const CSSParserLocalContext&) const { -+ // Fail parsing if this rule is disabled by document settings. -+ if (Settings* settings = context.GetDocument()->GetSettings(); -+ settings && !settings->GetElectronCornerSmoothingCSS()) { -+ return nullptr; -+ } -+ -+ // Try to parse `system-ui` keyword first. -+ if (auto* ident = -+ css_parsing_utils::ConsumeIdent(stream)) { -+ return ident; -+ } -+ // Try to parse as percent. -+ return css_parsing_utils::ConsumePercent( -+ stream, context, CSSPrimitiveValue::ValueRange::kNonNegative); -+} -+ - } // namespace css_longhand - } // namespace blink -diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc -index 26222ba06232da5d98b35173a7ab0e55a3e6d076..92cdc2aed6a68581187ae654358cc7f2b2409cb3 100644 ---- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc -+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc -@@ -3875,4 +3875,12 @@ PositionArea StyleBuilderConverter::ConvertPositionArea( - return PositionArea(span[0], span[1], span[2], span[3]); - } - -+Length StyleBuilderConverter::ConvertCornerSmoothing(StyleResolverState& state, const CSSValue& value) { -+ auto* ident = DynamicTo(value); -+ if (ident && ident->GetValueID() == CSSValueID::kSystemUi) { -+ return Length::Auto(); -+ } -+ return ConvertLength(state, value); -+} -+ - } // namespace blink -diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h -index c0f4544a38dc486708dec5a4b3646fb3f15ff2e0..8b3d4e95fb690f9e7b38265be0a77d6e49271944 100644 ---- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h -+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h -@@ -421,6 +421,8 @@ class StyleBuilderConverter { - const CSSValue&); - - static PositionArea ConvertPositionArea(StyleResolverState&, const CSSValue&); -+ -+ static Length ConvertCornerSmoothing(StyleResolverState&, const CSSValue&); - }; - - template -diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.cc b/third_party/blink/renderer/core/exported/web_settings_impl.cc -index 673bafce059a21da812155ef1c6c5577fe211a91..40dfafd5828cac131bb1b4bbc0c8d64f2d09d4f2 100644 ---- a/third_party/blink/renderer/core/exported/web_settings_impl.cc -+++ b/third_party/blink/renderer/core/exported/web_settings_impl.cc -@@ -809,4 +809,8 @@ void WebSettingsImpl:: - is_required); - } - -+void WebSettingsImpl::SetCornerSmoothingCSS(bool available) { -+ settings_->SetElectronCornerSmoothingCSS(available); -+} -+ - } // namespace blink -diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.h b/third_party/blink/renderer/core/exported/web_settings_impl.h -index ea27e0cfabfec4cba6d39b4dbfbaca59cae84f8e..48abf7909b9e6b095d431739094bf8145282a01c 100644 ---- a/third_party/blink/renderer/core/exported/web_settings_impl.h -+++ b/third_party/blink/renderer/core/exported/web_settings_impl.h -@@ -236,6 +236,7 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings { - void SetModalContextMenu(bool) override; - void SetRequireTransientActivationAndAuthorizationForSubAppsAPIs( - bool) override; -+ void SetCornerSmoothingCSS(bool) override; - - bool RenderVSyncNotificationEnabled() const { - return render_v_sync_notification_enabled_; -diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc -index 64f243d595920a87e7115ca8047822a7368752df..1a1b92ae3dd892413c76d3d61a41d33736c04d9f 100644 ---- a/third_party/blink/renderer/core/exported/web_view_impl.cc -+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc -@@ -3579,6 +3579,9 @@ void WebViewImpl::UpdateRendererPreferences( - #endif - - MaybePreloadSystemFonts(GetPage()); -+ -+ GetSettings()->SetCornerSmoothingCSS( -+ renderer_preferences_.electron_corner_smoothing_css); - } - - void WebViewImpl::SetHistoryIndexAndLength(int32_t history_index, -diff --git a/third_party/blink/renderer/core/frame/settings.json5 b/third_party/blink/renderer/core/frame/settings.json5 -index 6566580ef5e20ac5a66507e6ef625db9258ca906..b36ed88cf2f8c3e1554803caf9fd31c8ac70f733 100644 ---- a/third_party/blink/renderer/core/frame/settings.json5 -+++ b/third_party/blink/renderer/core/frame/settings.json5 -@@ -1252,5 +1252,10 @@ - initial: false, - type: "bool" - }, -+ { -+ name: "electronCornerSmoothingCSS", -+ initial: true, -+ invalidate: ["Style"], -+ }, - ], - } -diff --git a/third_party/blink/renderer/core/paint/box_border_painter.cc b/third_party/blink/renderer/core/paint/box_border_painter.cc -index 7996ba931a2482e9941ce4642b2c017c294fe89d..abc87db736b47b1bbaa8b9717b0520a747b1725f 100644 ---- a/third_party/blink/renderer/core/paint/box_border_painter.cc -+++ b/third_party/blink/renderer/core/paint/box_border_painter.cc -@@ -246,7 +246,7 @@ FloatRoundedRect CalculateAdjustedInnerBorder( - break; - } - -- return FloatRoundedRect(new_rect, new_radii); -+ return FloatRoundedRect(new_rect, new_radii, inner_border.GetSmoothness()); - } - - void DrawSolidBorderRect(GraphicsContext& context, -diff --git a/third_party/blink/renderer/core/paint/box_painter_base.cc b/third_party/blink/renderer/core/paint/box_painter_base.cc -index 5c3e86f6476c58e771b16b485c4f5c0081af3f7b..6e49fcce3c7b6a9664a4a1bd63200fdb85d05980 100644 ---- a/third_party/blink/renderer/core/paint/box_painter_base.cc -+++ b/third_party/blink/renderer/core/paint/box_painter_base.cc -@@ -319,7 +319,8 @@ void BoxPainterBase::PaintNormalBoxShadow(const PaintInfo& info, - context.SetDrawLooper(draw_looper_builder.DetachDrawLooper()); - - if (has_border_radius) { -- FloatRoundedRect rounded_fill_rect(fill_rect, border.GetRadii()); -+ FloatRoundedRect rounded_fill_rect(fill_rect, border.GetRadii(), -+ border.GetSmoothness()); - ApplySpreadToShadowShape(rounded_fill_rect, shadow.Spread()); - context.FillRoundedRect( - rounded_fill_rect, Color::kBlack, -@@ -403,7 +404,8 @@ void BoxPainterBase::PaintInsetBoxShadow(const PaintInfo& info, - - gfx::RectF inner_rect = bounds.Rect(); - AdjustRectForSideClipping(inner_rect, shadow, sides_to_include); -- FloatRoundedRect inner_rounded_rect(inner_rect, bounds.GetRadii()); -+ FloatRoundedRect inner_rounded_rect(inner_rect, bounds.GetRadii(), -+ bounds.GetSmoothness()); - ApplySpreadToShadowShape(inner_rounded_rect, -shadow.Spread()); - if (inner_rounded_rect.IsEmpty()) { - // |AutoDarkMode::Disabled()| is used because |shadow_color| has already -diff --git a/third_party/blink/renderer/core/paint/rounded_border_geometry.cc b/third_party/blink/renderer/core/paint/rounded_border_geometry.cc -index 7f4026755c285897a0892edfa40a91201a8a4830..795cece5a853662ede5a7439d17b4bee67d51fff 100644 ---- a/third_party/blink/renderer/core/paint/rounded_border_geometry.cc -+++ b/third_party/blink/renderer/core/paint/rounded_border_geometry.cc -@@ -52,6 +52,24 @@ FloatRoundedRect::CornerCurvature CalcCurvatureFor( - EffectiveCurvature(style.CornerBottomLeftShape(), radii.BottomLeft())); - } - -+float SmoothnessFromLength(const Length& length) { -+ // `none` = 0% -+ if (length.IsNone()) { -+ return 0.0f; -+ } -+ -+ // `system-ui` keyword, represented internally as "auto" length -+ if (length.HasAuto()) { -+#if BUILDFLAG(IS_MAC) -+ return 0.6f; -+#else -+ return 0.0f; -+#endif // BUILDFLAG(IS_MAC) -+ } -+ -+ return length.Percent() / 100.0f; -+} -+ - FloatRoundedRect PixelSnappedRoundedBorderInternal( - const ComputedStyle& style, - const PhysicalRect& border_rect, -@@ -64,6 +82,8 @@ FloatRoundedRect PixelSnappedRoundedBorderInternal( - rounded_rect.ConstrainRadii(); - rounded_rect.SetCornerCurvature( - CalcCurvatureFor(style, rounded_rect.GetRadii())); -+ rounded_rect.SetSmoothness( -+ SmoothnessFromLength(style.ElectronCornerSmoothing())); - } - return rounded_rect; - } -@@ -80,6 +100,8 @@ FloatRoundedRect RoundedBorderGeometry::RoundedBorder( - rounded_rect.ConstrainRadii(); - rounded_rect.SetCornerCurvature( - CalcCurvatureFor(style, rounded_rect.GetRadii())); -+ rounded_rect.SetSmoothness( -+ SmoothnessFromLength(style.ElectronCornerSmoothing())); - } - return rounded_rect; - } -@@ -167,6 +189,8 @@ FloatRoundedRect RoundedBorderGeometry::RoundedInnerBorder( - .set_right(style.BorderRightWidth()) - .set_bottom(style.BorderBottomWidth()) - .set_left(style.BorderLeftWidth())); -+ rounded_border.SetSmoothness( -+ SmoothnessFromLength(style.ElectronCornerSmoothing())); - return rounded_border; - } - -@@ -214,6 +238,7 @@ FloatRoundedRect RoundedBorderGeometry::PixelSnappedRoundedBorderWithOutsets( - rounded_rect.SetRadii(pixel_snapped_rounded_border.GetRadii()); - rounded_rect.SetCornerCurvature( - pixel_snapped_rounded_border.GetCornerCurvature()); -+ rounded_rect.SetSmoothness(pixel_snapped_rounded_border.GetSmoothness()); - } - return rounded_rect; - } -diff --git a/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc b/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc -index f9f0cc13c043e4653d8a616d0ef4f2f776aace74..6217ca2a6c507c90980be54b1e3d12ce621be099 100644 ---- a/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc -+++ b/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc -@@ -28,16 +28,16 @@ RoundedInnerRectClipper::RoundedInnerRectClipper( - rect.Bottom() - clip_rect.Rect().y()); - FloatRoundedRect::Radii top_corner_radii; - top_corner_radii.SetTopLeft(clip_rect.GetRadii().TopLeft()); -- rounded_rect_clips.push_back( -- FloatRoundedRect(top_corner, top_corner_radii)); -+ rounded_rect_clips.push_back(FloatRoundedRect( -+ top_corner, top_corner_radii, clip_rect.GetSmoothness())); - - gfx::RectF bottom_corner(rect.X().ToFloat(), rect.Y().ToFloat(), - clip_rect.Rect().right() - rect.X().ToFloat(), - clip_rect.Rect().bottom() - rect.Y().ToFloat()); - FloatRoundedRect::Radii bottom_corner_radii; - bottom_corner_radii.SetBottomRight(clip_rect.GetRadii().BottomRight()); -- rounded_rect_clips.push_back( -- FloatRoundedRect(bottom_corner, bottom_corner_radii)); -+ rounded_rect_clips.push_back(FloatRoundedRect( -+ bottom_corner, bottom_corner_radii, clip_rect.GetSmoothness())); - } - - if (!clip_rect.GetRadii().TopRight().IsEmpty() || -@@ -47,16 +47,16 @@ RoundedInnerRectClipper::RoundedInnerRectClipper( - rect.Bottom() - clip_rect.Rect().y()); - FloatRoundedRect::Radii top_corner_radii; - top_corner_radii.SetTopRight(clip_rect.GetRadii().TopRight()); -- rounded_rect_clips.push_back( -- FloatRoundedRect(top_corner, top_corner_radii)); -+ rounded_rect_clips.push_back(FloatRoundedRect( -+ top_corner, top_corner_radii, clip_rect.GetSmoothness())); - - gfx::RectF bottom_corner(clip_rect.Rect().x(), rect.Y().ToFloat(), - rect.Right() - clip_rect.Rect().x(), - clip_rect.Rect().bottom() - rect.Y().ToFloat()); - FloatRoundedRect::Radii bottom_corner_radii; - bottom_corner_radii.SetBottomLeft(clip_rect.GetRadii().BottomLeft()); -- rounded_rect_clips.push_back( -- FloatRoundedRect(bottom_corner, bottom_corner_radii)); -+ rounded_rect_clips.push_back(FloatRoundedRect( -+ bottom_corner, bottom_corner_radii, clip_rect.GetSmoothness())); - } - } - -diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn -index 8546d85128cc970cb2fd7b0b98642c1403fa5c7d..59f503cbde358d999ffc3a8499a94e1f785d7bed 100644 ---- a/third_party/blink/renderer/platform/BUILD.gn -+++ b/third_party/blink/renderer/platform/BUILD.gn -@@ -1634,6 +1634,8 @@ component("platform") { - "widget/widget_base.h", - "widget/widget_base_client.h", - "windows_keyboard_codes.h", -+ "//electron/shell/renderer/electron_smooth_round_rect.h", -+ "//electron/shell/renderer/electron_smooth_round_rect.cc", - ] - - sources -= blink_platform_avx_files -diff --git a/third_party/blink/renderer/platform/geometry/float_rounded_rect.h b/third_party/blink/renderer/platform/geometry/float_rounded_rect.h -index 7bf6608b57f8fc2283026dac6bff0c81bca380fd..09f34525343dacacf966f7ab4918ee57ae0c1470 100644 ---- a/third_party/blink/renderer/platform/geometry/float_rounded_rect.h -+++ b/third_party/blink/renderer/platform/geometry/float_rounded_rect.h -@@ -197,15 +197,19 @@ class PLATFORM_EXPORT FloatRoundedRect { - : rect_(rect), radii_(radius) {} - FloatRoundedRect(const gfx::RectF& r, float radius_x, float radius_y) - : FloatRoundedRect(r, Radii(radius_x, radius_y)) {} -+ FloatRoundedRect(const gfx::RectF& r, const Radii& radii, float smoothness) -+ : rect_(r), radii_(radii), smoothness_(smoothness) {} - - constexpr const gfx::RectF& Rect() const { return rect_; } - constexpr const Radii& GetRadii() const { return radii_; } - constexpr const CornerCurvature& GetCornerCurvature() const { - return corner_curvature_; - } -+ constexpr float GetSmoothness() const { return smoothness_; } - constexpr bool IsRounded() const { return !radii_.IsZero(); } -+ constexpr bool IsSmooth() const { return smoothness_ > 0.0f; } - constexpr bool HasSimpleRoundedCurvature() const { -- return !IsRounded() || corner_curvature_.IsRound(); -+ return !IsRounded() || (corner_curvature_.IsRound() && !IsSmooth()); - } - constexpr bool IsEmpty() const { return rect_.IsEmpty(); } - -@@ -214,6 +218,7 @@ class PLATFORM_EXPORT FloatRoundedRect { - void SetCornerCurvature(const CornerCurvature& curvature) { - corner_curvature_ = curvature; - } -+ void SetSmoothness(float smoothness) { smoothness_ = smoothness; } - - void Move(const gfx::Vector2dF& offset) { rect_.Offset(offset); } - -@@ -297,6 +302,7 @@ class PLATFORM_EXPORT FloatRoundedRect { - gfx::RectF rect_; - Radii radii_; - CornerCurvature corner_curvature_; -+ float smoothness_ = 0.0f; - }; - - inline FloatRoundedRect::operator SkRRect() const { -diff --git a/third_party/blink/renderer/platform/geometry/path.cc b/third_party/blink/renderer/platform/geometry/path.cc -index 96a1f38db9f42e8d47d70b82b6e1ee8034b96b47..08bc720fe0337f947461d74e29f7ce6f35509643 100644 ---- a/third_party/blink/renderer/platform/geometry/path.cc -+++ b/third_party/blink/renderer/platform/geometry/path.cc -@@ -33,6 +33,7 @@ - - #include - -+#include "electron/shell/renderer/electron_smooth_round_rect.h" - #include "third_party/blink/renderer/platform/geometry/skia_geometry_utils.h" - #include "third_party/blink/renderer/platform/geometry/stroke_data.h" - #include "third_party/blink/renderer/platform/transforms/affine_transform.h" -@@ -657,6 +658,18 @@ void Path::AddRoundedRect(const FloatRoundedRect& rect, bool clockwise) { - // no canvas API (at this moment) to change corner curvature. - DCHECK(clockwise); - -+ // TODO(clavin): decompose `electron::DrawSmoothRoundRect` into corners -+ if (rect.IsSmooth()) { -+ const gfx::RectF& box = rect.Rect(); -+ const FloatRoundedRect::Radii& radii = rect.GetRadii(); -+ path_.addPath(electron::DrawSmoothRoundRect( -+ box.x(), box.y(), box.width(), box.height(), -+ std::min(rect.GetSmoothness(), 1.0f), radii.TopLeft().width(), -+ radii.TopRight().width(), radii.BottomRight().width(), -+ radii.BottomLeft().width())); -+ return; -+ } -+ - path_.moveTo(gfx::PointFToSkPoint(rect.TopLeftCorner().top_right())); - - path_.lineTo(gfx::PointFToSkPoint((rect.TopRightCorner().origin()))); -diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc -index 5d7887ae589af529a9f4c3e29b9fa314903e26bb..0d2f753a3b189bae69729b4da3cc2af72a98453a 100644 ---- a/third_party/blink/renderer/platform/graphics/graphics_context.cc -+++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc -@@ -819,6 +819,13 @@ void GraphicsContext::FillRoundedRect(const FloatRoundedRect& rrect, - return; - } - -+ if (!rrect.HasSimpleRoundedCurvature()) { -+ Path path; -+ path.AddRoundedRect(rrect); -+ FillPath(path, auto_dark_mode); -+ return; -+ } -+ - const cc::PaintFlags& fill_flags = ImmutableState()->FillFlags(); - const SkColor4f sk_color = color.toSkColor4f(); - if (sk_color == fill_flags.getColor4f()) { diff --git a/shell/browser/web_contents_preferences.cc b/shell/browser/web_contents_preferences.cc index 7096c8bc5f81..5066bc2e00d2 100644 --- a/shell/browser/web_contents_preferences.cc +++ b/shell/browser/web_contents_preferences.cc @@ -149,7 +149,6 @@ void WebContentsPreferences::Clear() { preload_path_ = std::nullopt; v8_cache_options_ = blink::mojom::V8CacheOptions::kDefault; deprecated_paste_enabled_ = false; - corner_smoothing_css_ = true; #if BUILDFLAG(IS_MAC) scroll_bounce_ = false; @@ -229,8 +228,6 @@ void WebContentsPreferences::SetFromDictionary( if (web_preferences.Get(options::kDisableBlinkFeatures, &disable_blink_features)) disable_blink_features_ = disable_blink_features; - web_preferences.Get(options::kEnableCornerSmoothingCSS, - &corner_smoothing_css_); base::FilePath::StringType preload_path; if (web_preferences.Get(options::kPreloadScript, &preload_path)) { @@ -481,8 +478,6 @@ void WebContentsPreferences::OverrideWebkitPrefs( prefs->v8_cache_options = v8_cache_options_; prefs->dom_paste_enabled = deprecated_paste_enabled_; - - renderer_prefs->electron_corner_smoothing_css = corner_smoothing_css_; } WEB_CONTENTS_USER_DATA_KEY_IMPL(WebContentsPreferences); diff --git a/shell/browser/web_contents_preferences.h b/shell/browser/web_contents_preferences.h index 1e0b47631f47..4bb6132752cc 100644 --- a/shell/browser/web_contents_preferences.h +++ b/shell/browser/web_contents_preferences.h @@ -134,7 +134,6 @@ class WebContentsPreferences std::optional preload_path_; blink::mojom::V8CacheOptions v8_cache_options_; bool deprecated_paste_enabled_ = false; - bool corner_smoothing_css_; #if BUILDFLAG(IS_MAC) bool scroll_bounce_; diff --git a/shell/common/options_switches.h b/shell/common/options_switches.h index 6d0895d4cbb3..7f2608410c4a 100644 --- a/shell/common/options_switches.h +++ b/shell/common/options_switches.h @@ -210,10 +210,6 @@ inline constexpr std::string_view kSpellcheck = "spellcheck"; // document.execCommand("paste"). inline constexpr std::string_view kEnableDeprecatedPaste = "enableDeprecatedPaste"; - -// Whether the -electron-corner-smoothing CSS rule is enabled. -inline constexpr std::string_view kEnableCornerSmoothingCSS = - "enableCornerSmoothingCSS"; } // namespace options // Following are actually command line switches, should be moved to other files. diff --git a/shell/renderer/electron_smooth_round_rect.cc b/shell/renderer/electron_smooth_round_rect.cc deleted file mode 100644 index dcd681387c1f..000000000000 --- a/shell/renderer/electron_smooth_round_rect.cc +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright (c) 2024 Salesforce, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "electron/shell/renderer/electron_smooth_round_rect.h" - -#include -#include "base/check.h" - -namespace electron { - -namespace { - -// Applies quarter rotations (n * 90°) to a point relative to the origin. -constexpr SkPoint QuarterRotate(const SkPoint& p, - unsigned int quarter_rotations) { - switch (quarter_rotations % 4) { - case 0: - return p; - case 1: - return {-p.y(), p.x()}; - case 2: - return {-p.x(), -p.y()}; - // case 3: - default: - return {p.y(), -p.x()}; - } -} - -// Edge length consumed for a given smoothness and corner radius. -constexpr float LengthForCornerSmoothness(float smoothness, float radius) { - return (1.0f + smoothness) * radius; -} - -// The smoothness value when consuming an edge length for a corner with a given -// radius. -// -// This function complements `LengthForCornerSmoothness`: -// SmoothnessForCornerLength(LengthForCornerSmoothness(s, r), r) = s -constexpr float SmoothnessForCornerLength(float length, float radius) { - return (length / radius) - 1.0f; -} - -// Geometric measurements for constructing the curves of smooth round corners on -// a rectangle. -// -// Each measurement's value is relative to the rectangle's natural corner point. -// An "offset" measurement is a one-dimensional length and a "vector" -// measurement is a two-dimensional pair of lengths. -// -// Each measurement's direction is relative to the direction of an edge towards -// the corner. Offsets are in the same direction as the edge toward the corner. -// For vectors, the X direction is parallel and the Y direction is -// perpendicular. -struct CurveGeometry { - constexpr CurveGeometry(float radius, float smoothness); - - constexpr SkVector edge_connecting_vector() const { - return {edge_connecting_offset, 0.0f}; - } - constexpr SkVector edge_curve_vector() const { - return {edge_curve_offset, 0.0f}; - } - constexpr SkVector arc_curve_vector() const { - return {arc_curve_offset, 0.0f}; - } - constexpr SkVector arc_connecting_vector_transposed() const { - return {arc_connecting_vector.y(), arc_connecting_vector.x()}; - } - - // The point where the edge connects to the curve. - float edge_connecting_offset; - - // The control point for the curvature where the edge connects to the curve. - float edge_curve_offset; - - // The control point for the curvature where the arc connects to the curve. - float arc_curve_offset; - - // The point where the arc connects to the curve. - SkVector arc_connecting_vector; -}; - -constexpr CurveGeometry::CurveGeometry(float radius, float smoothness) { - edge_connecting_offset = LengthForCornerSmoothness(smoothness, radius); - - float arc_angle = (std::numbers::pi / 4.0f) * smoothness; - - arc_connecting_vector = - SkVector::Make(1.0f - std::sin(arc_angle), 1.0f - std::cos(arc_angle)) * - radius; - - arc_curve_offset = (1.0f - std::tan(arc_angle / 2.0f)) * radius; - - constexpr float EDGE_CURVE_POINT_RATIO = 2.0f / 3.0f; - edge_curve_offset = - edge_connecting_offset - - ((edge_connecting_offset - arc_curve_offset) * EDGE_CURVE_POINT_RATIO); -} - -void DrawCorner(SkPath& path, - float radius, - const CurveGeometry& curve1, - const CurveGeometry& curve2, - const SkPoint& corner, - unsigned int quarter_rotations) { - // Move/Line to the edge connecting point - { - SkPoint edge_connecting_point = - corner + - QuarterRotate(curve1.edge_connecting_vector(), quarter_rotations + 1); - - if (quarter_rotations == 0) { - path.moveTo(edge_connecting_point); - } else { - path.lineTo(edge_connecting_point); - } - } - - // Draw the first smoothing curve - { - SkPoint edge_curve_point = - corner + - QuarterRotate(curve1.edge_curve_vector(), quarter_rotations + 1); - SkPoint arc_curve_point = corner + QuarterRotate(curve1.arc_curve_vector(), - quarter_rotations + 1); - SkPoint arc_connecting_point = - corner + QuarterRotate(curve1.arc_connecting_vector_transposed(), - quarter_rotations); - path.cubicTo(edge_curve_point, arc_curve_point, arc_connecting_point); - } - - // Draw the arc - { - SkPoint arc_connecting_point = - corner + QuarterRotate(curve2.arc_connecting_vector, quarter_rotations); - path.arcTo(SkPoint::Make(radius, radius), 0.0f, SkPath::kSmall_ArcSize, - SkPathDirection::kCW, arc_connecting_point); - } - - // Draw the second smoothing curve - { - SkPoint arc_curve_point = - corner + QuarterRotate(curve2.arc_curve_vector(), quarter_rotations); - SkPoint edge_curve_point = - corner + QuarterRotate(curve2.edge_curve_vector(), quarter_rotations); - SkPoint edge_connecting_point = - corner + - QuarterRotate(curve2.edge_connecting_vector(), quarter_rotations); - path.cubicTo(arc_curve_point, edge_curve_point, edge_connecting_point); - } -} - -// Constrains the smoothness of two corners along the same edge. -// -// If the smoothness value needs to be constrained, it will try to keep the -// ratio of the smoothness values the same as the ratio of the radii -// (`s1/s2 = r1/r2`). -constexpr std::pair ConstrainSmoothness(float size, - float smoothness, - float radius1, - float radius2) { - float edge_consumed1 = LengthForCornerSmoothness(smoothness, radius1); - float edge_consumed2 = LengthForCornerSmoothness(smoothness, radius2); - - // If both corners fit within the edge size then keep the smoothness - if (edge_consumed1 + edge_consumed2 <= size) { - return {smoothness, smoothness}; - } - - float ratio = radius1 / (radius1 + radius2); - float length1 = size * ratio; - float length2 = size - length1; - - float smoothness1 = - std::max(SmoothnessForCornerLength(length1, radius1), 0.0f); - float smoothness2 = - std::max(SmoothnessForCornerLength(length2, radius2), 0.0f); - - return {smoothness1, smoothness2}; -} - -} // namespace - -// The algorithm for drawing this shape is based on the article -// "Desperately seeking squircles" by Daniel Furse. A brief summary: -// -// In a simple round rectangle, each corner of a plain rectangle is replaced -// with a quarter circle and connected to each edge of the corner. -// -// Edge -// ←------→ ↖ -// ----------o--__ `、 Corner (Quarter Circle) -// `、 `、 -// | ↘ -// | -// o -// | ↑ -// | | Edge -// | ↓ -// -// This creates sharp changes in the curvature at the points where the edge -// transitions to the corner, suddenly curving at a constant rate. Our primary -// goal is to smooth out that curvature profile, slowly ramping up and back -// down, like turning a car with the steering wheel. -// -// To achieve this, we "expand" that point where the circular corner meets the -// straight edge in both directions. We use this extra space to construct a -// small curved path that eases the curvature from the edge to the corner -// circle. -// -// Edge Curve -// ←--→ ←-----→ -// -----o----___o ↖、 Corner (Circular Arc) -// `、 `↘ -// o -// | ↑ -// | | Curve -// | ↓ -// o -// | ↕ Edge -// -// Each curve is implemented as a cubic Bézier curve, composed of four control -// points: -// -// * The first control point connects to the straight edge. -// * The fourth (last) control point connects to the circular arc. -// * The second & third control points both lie on the infinite line extending -// from the straight edge. -// * The third control point (only) also lies on the infinite line tangent to -// the circular arc at the fourth control point. -// -// The first and fourth (last) control points are firmly fixed by attaching to -// the straight edge and circular arc, respectively. The third control point is -// fixed at the intersection between the edge and tangent lines. The second -// control point, however, is only constrained to the infinite edge line, but -// we may choose where. -SkPath DrawSmoothRoundRect(float x, - float y, - float width, - float height, - float smoothness, - float top_left_radius, - float top_right_radius, - float bottom_right_radius, - float bottom_left_radius) { - DCHECK(0.0f <= smoothness && smoothness <= 1.0f); - - // Assume the radii are already constrained within the rectangle size - DCHECK(top_left_radius + top_right_radius <= width); - DCHECK(bottom_left_radius + bottom_right_radius <= width); - DCHECK(top_left_radius + bottom_left_radius <= height); - DCHECK(top_right_radius + bottom_right_radius <= height); - - if (width <= 0.0f || height <= 0.0f) { - return SkPath(); - } - - // Constrain the smoothness for each curve on each edge - auto [top_left_smoothness, top_right_smoothness] = - ConstrainSmoothness(width, smoothness, top_left_radius, top_right_radius); - auto [right_top_smoothness, right_bottom_smoothness] = ConstrainSmoothness( - height, smoothness, top_right_radius, bottom_right_radius); - auto [bottom_left_smoothness, bottom_right_smoothness] = ConstrainSmoothness( - width, smoothness, bottom_left_radius, bottom_right_radius); - auto [left_top_smoothness, left_bottom_smoothness] = ConstrainSmoothness( - height, smoothness, top_left_radius, bottom_left_radius); - - SkPath path; - - // Top left corner - DrawCorner(path, top_left_radius, - CurveGeometry(top_left_radius, left_top_smoothness), - CurveGeometry(top_left_radius, top_left_smoothness), - SkPoint::Make(x, y), 0); - - // Top right corner - DrawCorner(path, top_right_radius, - CurveGeometry(top_right_radius, top_right_smoothness), - CurveGeometry(top_right_radius, right_top_smoothness), - SkPoint::Make(x + width, y), 1); - - // Bottom right corner - DrawCorner(path, bottom_right_radius, - CurveGeometry(bottom_right_radius, right_bottom_smoothness), - CurveGeometry(bottom_right_radius, bottom_right_smoothness), - SkPoint::Make(x + width, y + height), 2); - - // Bottom left corner - DrawCorner(path, bottom_left_radius, - CurveGeometry(bottom_left_radius, bottom_left_smoothness), - CurveGeometry(bottom_left_radius, left_bottom_smoothness), - SkPoint::Make(x, y + height), 3); - - path.close(); - return path; -} - -} // namespace electron diff --git a/shell/renderer/electron_smooth_round_rect.h b/shell/renderer/electron_smooth_round_rect.h deleted file mode 100644 index 1c84da904838..000000000000 --- a/shell/renderer/electron_smooth_round_rect.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2024 Salesforce, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ELECTRON_SHELL_RENDERER_API_ELECTRON_SMOOTH_ROUND_RECT_H_ -#define ELECTRON_SHELL_RENDERER_API_ELECTRON_SMOOTH_ROUND_RECT_H_ - -#include "third_party/skia/include/core/SkPath.h" - -namespace electron { - -// Draws a rectangle that has smooth round corners for a given "smoothness" -// value between 0.0 and 1.0 (representing 0% to 100%). -// -// The smoothness value determines how much edge length can be consumed by each -// corner, scaling with respect to that corner's radius. The smoothness will -// dynamically scale back if there is not enough edge length, similar to how -// the corner radius backs off when there isn't enough edge length. -// -// Each corner's radius can be supplied independently. Corner radii are expected -// to already be balanced (Radius1 + Radius2 <= Length, for each given side). -// -// Elliptical corner radii are not currently supported. -SkPath DrawSmoothRoundRect(float x, - float y, - float width, - float height, - float smoothness, - float top_left_radius, - float top_right_radius, - float bottom_right_radius, - float bottom_left_radius); - -} // namespace electron - -#endif // ELECTRON_SHELL_RENDERER_API_ELECTRON_SMOOTH_ROUND_RECT_H_ diff --git a/spec/api-corner-smoothing-spec.ts b/spec/api-corner-smoothing-spec.ts deleted file mode 100644 index a25a787db762..000000000000 --- a/spec/api-corner-smoothing-spec.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { NativeImage, nativeImage } from 'electron/common'; -import { BrowserWindow } from 'electron/main'; - -import { AssertionError, expect } from 'chai'; - -import path = require('node:path'); - -import { createArtifact } from './lib/artifacts'; -import { ifdescribe } from './lib/spec-helpers'; -import { closeAllWindows } from './lib/window-helpers'; - -const FIXTURE_PATH = path.resolve( - __dirname, - 'fixtures', - 'api', - 'corner-smoothing' -); - -/** - * Rendered images may "match" but slightly differ due to rendering artifacts - * like anti-aliasing and vector path resolution, among others. This tolerance - * is the cutoff for whether two images "match" or not. - * - * From testing, matching images were found to have an average global difference - * up to about 1.3 and mismatched images were found to have a difference of at - * least about 7.3. - * - * See the documentation on `compareImages` for more information. - */ -const COMPARISON_TOLERANCE = 2.5; - -/** - * Compares the average global difference of two images to determine if they - * are similar enough to "match" each other. - * - * "Average global difference" is the average difference of pixel components - * (RGB each) across an entire image. - * - * The cutoff for matching/not-matching is defined by the `COMPARISON_TOLERANCE` - * constant. - */ -function compareImages (img1: NativeImage, img2: NativeImage): boolean { - expect(img1.getSize()).to.deep.equal( - img2.getSize(), - 'Cannot compare images with different sizes' - ); - - const bitmap1 = img1.toBitmap(); - const bitmap2 = img2.toBitmap(); - - const { width, height } = img1.getSize(); - - let totalDiff = 0; - for (let x = 0; x < width; x++) { - for (let y = 0; y < height; y++) { - const index = (x + y * width) * 4; - const pixel1 = bitmap1.subarray(index, index + 4); - const pixel2 = bitmap2.subarray(index, index + 4); - const diff = - Math.abs(pixel1[0] - pixel2[0]) + - Math.abs(pixel1[1] - pixel2[1]) + - Math.abs(pixel1[2] - pixel2[2]); - totalDiff += diff; - } - } - - const avgDiff = totalDiff / (width * height); - return avgDiff <= COMPARISON_TOLERANCE; -} - -/** - * Recipe for tests. - * - * The page is rendered, captured as an image, then compared to an expected - * result image. - */ -async function pageCaptureTestRecipe ( - pagePath: string, - expectedImgPath: string, - artifactName: string, - cornerSmoothingAvailable: boolean = true -): Promise { - const w = new BrowserWindow({ - show: false, - width: 800, - height: 600, - useContentSize: true, - webPreferences: { - enableCornerSmoothingCSS: cornerSmoothingAvailable - } - }); - await w.loadFile(pagePath); - w.show(); - - // Wait for a render frame to prepare the page. - await w.webContents.executeJavaScript( - 'new Promise((resolve) => { requestAnimationFrame(() => resolve()); })' - ); - - const actualImg = await w.webContents.capturePage(); - expect(actualImg.isEmpty()).to.be.false('Failed to capture page image'); - - const expectedImg = nativeImage.createFromPath(expectedImgPath); - expect(expectedImg.isEmpty()).to.be.false( - 'Failed to read expected reference image' - ); - - const matches = compareImages(actualImg, expectedImg); - if (!matches) { - const artifactFileName = `corner-rounding-expected-${artifactName}.png`; - await createArtifact(artifactFileName, actualImg.toPNG()); - - throw new AssertionError( - `Actual image did not match expected reference image. Actual: "${artifactFileName}" in artifacts, Expected: "${path.relative( - path.resolve(__dirname, '..'), - expectedImgPath - )}" in source` - ); - } -} - -// FIXME: these tests rely on live rendering results, which are too variable to -// reproduce outside of CI, primarily due to display scaling. -ifdescribe(!!process.env.CI)('-electron-corner-smoothing', () => { - afterEach(async () => { - await closeAllWindows(); - }); - - describe('shape', () => { - for (const available of [true, false]) { - it(`matches the reference with web preference = ${available}`, async () => { - await pageCaptureTestRecipe( - path.join(FIXTURE_PATH, 'shape', 'test.html'), - path.join(FIXTURE_PATH, 'shape', `expected-${available}.png`), - `shape-${available}`, - available - ); - }); - } - }); - - describe('system-ui keyword', () => { - const { platform } = process; - it(`matches the reference for platform = ${platform}`, async () => { - await pageCaptureTestRecipe( - path.join(FIXTURE_PATH, 'system-ui-keyword', 'test.html'), - path.join( - FIXTURE_PATH, - 'system-ui-keyword', - `expected-${platform}.png` - ), - `system-ui-${platform}` - ); - }); - }); -}); diff --git a/spec/fixtures/api/corner-smoothing/shape/expected-false.png b/spec/fixtures/api/corner-smoothing/shape/expected-false.png deleted file mode 100644 index 31aea673f8b0..000000000000 Binary files a/spec/fixtures/api/corner-smoothing/shape/expected-false.png and /dev/null differ diff --git a/spec/fixtures/api/corner-smoothing/shape/expected-true.png b/spec/fixtures/api/corner-smoothing/shape/expected-true.png deleted file mode 100644 index 3abb97a2a13e..000000000000 Binary files a/spec/fixtures/api/corner-smoothing/shape/expected-true.png and /dev/null differ diff --git a/spec/fixtures/api/corner-smoothing/shape/image.png b/spec/fixtures/api/corner-smoothing/shape/image.png deleted file mode 100644 index 44a04bf32e5e..000000000000 Binary files a/spec/fixtures/api/corner-smoothing/shape/image.png and /dev/null differ diff --git a/spec/fixtures/api/corner-smoothing/shape/test.html b/spec/fixtures/api/corner-smoothing/shape/test.html deleted file mode 100644 index 994e1bd76ee2..000000000000 --- a/spec/fixtures/api/corner-smoothing/shape/test.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - -
-
- -
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
- -
-
-
-
-
-
- - \ No newline at end of file diff --git a/spec/fixtures/api/corner-smoothing/system-ui-keyword/expected-darwin.png b/spec/fixtures/api/corner-smoothing/system-ui-keyword/expected-darwin.png deleted file mode 100644 index e1d753c50fa4..000000000000 Binary files a/spec/fixtures/api/corner-smoothing/system-ui-keyword/expected-darwin.png and /dev/null differ diff --git a/spec/fixtures/api/corner-smoothing/system-ui-keyword/expected-linux.png b/spec/fixtures/api/corner-smoothing/system-ui-keyword/expected-linux.png deleted file mode 100644 index 79341eecfd76..000000000000 Binary files a/spec/fixtures/api/corner-smoothing/system-ui-keyword/expected-linux.png and /dev/null differ diff --git a/spec/fixtures/api/corner-smoothing/system-ui-keyword/expected-win32.png b/spec/fixtures/api/corner-smoothing/system-ui-keyword/expected-win32.png deleted file mode 100644 index 79341eecfd76..000000000000 Binary files a/spec/fixtures/api/corner-smoothing/system-ui-keyword/expected-win32.png and /dev/null differ diff --git a/spec/fixtures/api/corner-smoothing/system-ui-keyword/test.html b/spec/fixtures/api/corner-smoothing/system-ui-keyword/test.html deleted file mode 100644 index ccb17205ec41..000000000000 --- a/spec/fixtures/api/corner-smoothing/system-ui-keyword/test.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - -
-
-
- - \ No newline at end of file