From 12fb2449ace62b14887aa52e52e91216ecda1a3e Mon Sep 17 00:00:00 2001 From: Jesse Bishop <16565497+jesbis@users.noreply.github.com> Date: Wed, 12 Feb 2020 16:36:33 -0800 Subject: [PATCH 01/12] radial gradient API review PR --- .../RadialGradientBrush.md | 244 ++++++++++++++++++ .../images/ColorRadialGradientBrush.png | Bin 0 -> 40065 bytes .../images/OffsetRadialGradientBrush.png | Bin 0 -> 11857 bytes api_review/readme.md | 5 + 4 files changed, 249 insertions(+) create mode 100644 api_review/RadialGradientBrush/RadialGradientBrush.md create mode 100644 api_review/RadialGradientBrush/images/ColorRadialGradientBrush.png create mode 100644 api_review/RadialGradientBrush/images/OffsetRadialGradientBrush.png create mode 100644 api_review/readme.md diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md new file mode 100644 index 000000000..dc000ed79 --- /dev/null +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -0,0 +1,244 @@ + + + + +# Background + + + + + + + + + + + +## Composition brush usage + +The Xaml RadialGradientBrush will inherit from [XamlCompositionBrushBase](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.xamlcompositionbrushbase) and use a [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush), which is supported on Windows 10 1903 (v10.0.18362+). This seems like a useful model for new brushes going forward for both WinUI 2 and 3, and we aren't too concerned about duplicating some properties from other candidate base classes [GradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientbrush). + +The RadialGradientBrush API will more closely mirror the behavior of the Composition API than the WPF API: for example, the gradient origin defaults to center and provides a `GradientOriginOffset` property to specify an offset rather than providing a `GradientOrigin` property. + +Notable inconsistencies with the composition API include: +1. Usage of [Point](https://docs.microsoft.com/uwp/api/windows.foundation.point) rather than [Vector2](https://docs.microsoft.com/uwp/api/windows.foundation.numerics.vector2)/[float2](https://docs.microsoft.com/windows/win32/numerics_h/float2-structure) +2. Usage of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) rather than [CompositionColorGradientStop](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorgradientstop) + +The main reason for the above is to enable Xaml markup parsing for brushes defined in markup. + +### Animation support + +Ideally, RadialGradientBrush would support animation of GradientStops and other properties using composition animations by implementing [IAnimationObject](https://docs.microsoft.com/uwp/api/windows.ui.composition.ianimationobject). However, the `IAnimationObject` interface and support for animation of non-composition types is only supported on Windows 10 1809 (v10.0.17763) and newer. This could be revisited with WinUI 3. + +## Downlevel fallback behavior + +The options for fallback behavior on downlevel pre-1903 OS versions are: + +1. Draw a gradient using another renderer, e.g. Direct2D + * This would require loading additional expensive dependencies which WinUI doesn't currently rely on. +2. Draw a custom gradient surface, e.g. using a CompositionSurfaceBrush or WriteableBitmap + * This would require largely reimplementing the complex CompositionRadialGradientBrush. +3. **Rely on FallbackColor** + * Since [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) should be available downlevel with WinUI 3, #1 (FallbackColor) seems like a reasonable approach in the meantime. + +## InterpolationSpace + +The underlying [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) currently only supports the following [CompositionColorSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorspace) values: + +* `Auto` +* `Rgb` +* `RgbLinear` + +Applying any other interpolation color space will have no effect. + +# Description + + + +Paints an area with a radial gradient. A center point defines the origin of the gradient, and an ellipse defines the outer bounds of the gradient. + +# Examples + + + + + + + +This example creates a radial gradient with six gradient stops and uses it to paint a Rectangle. + +![A rectangle filled with a radial gradient.](images/ColorRadialGradientBrush.png) + +XAML +```XAML + + + + + + + + + + + + + + + + +``` + +This example creates a radial gradient with that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset`: + +![A rectangle filled with an offset radial gradient.](images/OffsetRadialGradientBrush.png) + +```XAML + + + + + + + + + + + + +``` + +# Remarks + + + + +## Gradient layout + +The gradient is drawn within an ellipse that is defined by the `EllipseCenter` and `EllipseRadius` properties. Colors for the gradient start at the center of the ellipse and end at the radius. + +The colors for the radial gradient are defined by color stops added to the `GradientStops` collection property. Each gradient stop specifies a color and an offset along the gradient. + +The gradient origin defaults to center and can be offset using the `GradientOriginOffset` property. + +`MappingMode` defines whether `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset` represent relative or absolute coordinates. + +When `MappingMode` is set to `RelativeTBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOriginOffset` property. + +When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the brush's rendered bounds. + +## Windows 10 Version Support + +Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and higher. On previous OS versions the brush will render a solid color specified by the `FallbackColor` property. + +## See Also + +* [LinearGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Media.LinearGradientBrush) + +* [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) + +# API Notes + + + + + +## Fields + +| | | +| - | - | +| EllipseCenter | The center of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | +| EllipseRadius | The radius of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | +| GradientOriginOffset | The gradient origin's offset from the center of the element. | +| GradientStops | A collection of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) objects that define the gradient. | +| InterpolationSpace | The color space used to interpolate the gradient's colors. The default is `Auto`. For supported values, see [CompositionRadialGradientBrush.InterpolationSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositiongradientbrush.interpolationspace#Windows_UI_Composition_CompositionGradientBrush_InterpolationSpace) | +| MappingMode | Defines whether `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset` represent relative coordinates in the range 0 to 1 or absolute coordinates. The default is `RelativeToBoundingBox`. | +| SpreadMethod | Gets or sets the type of spread method that specifies how to draw a gradient that starts or ends inside the bounds of the object to be painted. The default is `Pad`. | + +# API Details + + +```C++ +[WUXC_VERSION_PREVIEW] +[webhosthidden] +[contentproperty("GradientStops")] +unsealed runtimeclass RadialGradientBrush : Windows.UI.Xaml.Media.XamlCompositionBrushBase +{ + RadialGradientBrush(); + + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::Point(0.5,0.5)")] + Windows.Foundation.Point EllipseCenter { get; set; }; + + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::Point(0.5,0.5)")] + Windows.Foundation.Point EllipseRadius { get; set; }; + + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + Windows.Foundation.Point GradientOriginOffset { get; set; }; + + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::BrushMappingMode::RelativeToBoundingBox")] + Windows.UI.Xaml.Media.BrushMappingMode MappingMode { get; set; }; + + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::Windows::UI::Composition::CompositionColorSpace::Auto")] + Windows.UI.Composition.CompositionColorSpace InterpolationSpace { get; set; }; + + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::GradientSpreadMethod::Pad")] + Windows.UI.Xaml.Media.GradientSpreadMethod SpreadMethod { get; set; }; + + Windows.Foundation.Collections.IObservableVector GradientStops { get; }; + + static Windows.UI.Xaml.DependencyProperty EllipseCenterProperty { get; }; + static Windows.UI.Xaml.DependencyProperty EllipseRadiusProperty { get; }; + static Windows.UI.Xaml.DependencyProperty GradientOriginOffsetProperty { get; }; + static Windows.UI.Xaml.DependencyProperty InterpolationSpaceProperty { get; }; + static Windows.UI.Xaml.DependencyProperty MappingModeProperty { get; }; + static Windows.UI.Xaml.DependencyProperty SpreadMethodProperty { get; }; +} +``` + + + diff --git a/api_review/RadialGradientBrush/images/ColorRadialGradientBrush.png b/api_review/RadialGradientBrush/images/ColorRadialGradientBrush.png new file mode 100644 index 0000000000000000000000000000000000000000..92e2eff36c505caa676ec26161dea4c42a9f4248 GIT binary patch literal 40065 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 literal 0 HcmV?d00001 diff --git a/api_review/RadialGradientBrush/images/OffsetRadialGradientBrush.png b/api_review/RadialGradientBrush/images/OffsetRadialGradientBrush.png new file mode 100644 index 0000000000000000000000000000000000000000..1d8f5805e8272ed7fee7a3a2f1fc8e0e9b62c1cc GIT binary patch literal 11857 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 Date: Sat, 15 Feb 2020 12:07:06 -0800 Subject: [PATCH 02/12] Background updates (#68) --- .../RadialGradientBrush.md | 88 +++--------------- .../images/LinearGradientBrush.png | Bin 0 -> 2042 bytes 2 files changed, 14 insertions(+), 74 deletions(-) create mode 100644 active/RadialGradientBrush/images/LinearGradientBrush.png diff --git a/active/RadialGradientBrush/RadialGradientBrush.md b/active/RadialGradientBrush/RadialGradientBrush.md index dc000ed79..3615a8ac0 100644 --- a/active/RadialGradientBrush/RadialGradientBrush.md +++ b/active/RadialGradientBrush/RadialGradientBrush.md @@ -1,32 +1,15 @@ - - - # Background - +Xaml has a [LinearGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Media.LinearGradientBrush) to paint an area with a linear gradient. For example - +![A rectangle filled with a linear gradient.](images/LinearGradientBrush.png) - +This spec adds a new _radial_ gradient brush. - +This is roughly the same as WPF's [RadialGradientBrush](https://docs.microsoft.com/dotnet/api/System.Windows.Media.RadialGradientBrush), and is actually implemented using the existing Windows [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Composition.CompositionRadialGradientBrush). - +This brush will ship in the WinUI 2 NuGet/Framework package. Since it can be used on older Windows 10 versions, where the CompositionRadialGradientBrush isn't available, it has fallback behavior to draw a solid color instead when necessary, as is done by [AcrylicBrush](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Media.AcrylicBrush). ## Composition brush usage @@ -38,7 +21,7 @@ Notable inconsistencies with the composition API include: 1. Usage of [Point](https://docs.microsoft.com/uwp/api/windows.foundation.point) rather than [Vector2](https://docs.microsoft.com/uwp/api/windows.foundation.numerics.vector2)/[float2](https://docs.microsoft.com/windows/win32/numerics_h/float2-structure) 2. Usage of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) rather than [CompositionColorGradientStop](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorgradientstop) -The main reason for the above is to enable Xaml markup parsing for brushes defined in markup. +The main reason for the above is to enable Xaml markup parsing for brushes defined in markup and consistency with the rest of the Xaml API. ### Animation support @@ -46,18 +29,20 @@ Ideally, RadialGradientBrush would support animation of GradientStops and other ## Downlevel fallback behavior -The options for fallback behavior on downlevel pre-1903 OS versions are: +When this brush is used on pre-1903 versions of Windows, where [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Composition.CompositionRadialGradientBrush) isn't available, the options for fallback behavior are: 1. Draw a gradient using another renderer, e.g. Direct2D * This would require loading additional expensive dependencies which WinUI doesn't currently rely on. 2. Draw a custom gradient surface, e.g. using a CompositionSurfaceBrush or WriteableBitmap * This would require largely reimplementing the complex CompositionRadialGradientBrush. 3. **Rely on FallbackColor** - * Since [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) should be available downlevel with WinUI 3, #1 (FallbackColor) seems like a reasonable approach in the meantime. + * Draw a solid color, as specified by the [XamlCompositionBrushBase.FallbackColor](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Media.XamlCompositionBrushBase.FallbackColor) (which RadialGradientBrush will inherit from its base class). + +Using FallbackColor follows the precedence of [AcrylicBrush](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Media.AcrylicBrush). And since CompositionRadialGradientBrush should be available downlevel with WinUI 3, this seems like a reasonable approach in the meantime. ## InterpolationSpace -The underlying [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) currently only supports the following [CompositionColorSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorspace) values: +Note that the underlying [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) currently only supports the following [CompositionColorSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorspace) values: * `Auto` * `Rgb` @@ -67,27 +52,10 @@ Applying any other interpolation color space will have no effect. # Description - - -Paints an area with a radial gradient. A center point defines the origin of the gradient, and an ellipse defines the outer bounds of the gradient. +RadialGradientBrush paints an area with a radial gradient. A center point defines the origin of the gradient, and an ellipse defines the outer bounds of the gradient. # Examples - - - - - - This example creates a radial gradient with six gradient stops and uses it to paint a Rectangle. ![A rectangle filled with a radial gradient.](images/ColorRadialGradientBrush.png) @@ -113,7 +81,7 @@ XAML ``` -This example creates a radial gradient with that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset`: +This example creates a radial gradient that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset`: ![A rectangle filled with an offset radial gradient.](images/OffsetRadialGradientBrush.png) @@ -139,12 +107,6 @@ This example creates a radial gradient with that uses Absolute mapping mode with ``` # Remarks - - - ## Gradient layout @@ -156,7 +118,7 @@ The gradient origin defaults to center and can be offset using the `GradientOrig `MappingMode` defines whether `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset` represent relative or absolute coordinates. -When `MappingMode` is set to `RelativeTBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOriginOffset` property. +When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOriginOffset` property. When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the brush's rendered bounds. @@ -172,15 +134,6 @@ Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and h # API Notes - - - - ## Fields | | | @@ -194,37 +147,24 @@ with a "///" comment above the member or type. --> | SpreadMethod | Gets or sets the type of spread method that specifies how to draw a gradient that starts or ends inside the bounds of the object to be painted. The default is `Pad`. | # API Details - ```C++ -[WUXC_VERSION_PREVIEW] [webhosthidden] [contentproperty("GradientStops")] unsealed runtimeclass RadialGradientBrush : Windows.UI.Xaml.Media.XamlCompositionBrushBase { RadialGradientBrush(); - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::Point(0.5,0.5)")] Windows.Foundation.Point EllipseCenter { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::Point(0.5,0.5)")] Windows.Foundation.Point EllipseRadius { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] Windows.Foundation.Point GradientOriginOffset { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::BrushMappingMode::RelativeToBoundingBox")] Windows.UI.Xaml.Media.BrushMappingMode MappingMode { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::Windows::UI::Composition::CompositionColorSpace::Auto")] Windows.UI.Composition.CompositionColorSpace InterpolationSpace { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::GradientSpreadMethod::Pad")] Windows.UI.Xaml.Media.GradientSpreadMethod SpreadMethod { get; set; }; Windows.Foundation.Collections.IObservableVector GradientStops { get; }; diff --git a/active/RadialGradientBrush/images/LinearGradientBrush.png b/active/RadialGradientBrush/images/LinearGradientBrush.png new file mode 100644 index 0000000000000000000000000000000000000000..62a2ecc3ca5fcc15979b8983442048588241205c GIT binary patch literal 2042 zcmY*adsGu=77rLqLXZJv5fCR>3MpHjm1=;on1Z6M1pC-SSsoDqL3|(&vx7i_i4d(& z6s(~T6Jw8}wx?7Pp%TOZqKJpU0bNl^CSnS#)(jF!Ag>*sZU6Y@yZ86q$M4?z&CH3N zjHng1ZniiaZpHR(kzZo__t-j1w8oy_e4Tg`+pKcGjQSM!ORxJlrr^`*(R3W{S_Rpd zY=h~fL)+qVaX9;q*=2Pv>vAd%N2u5yN&gy7`a@WLaD--etSY$3LO58Z*m>6XJ9dtO z)pV)YinyD0KBsy5)X%RsJ%7ixY;JAiC^Ww*l&Vu1Hz-5(;*rARd?lwKB8yd%tq;lX zoVcf+(ck*SUl60MfAu&z!9Vzd;M_2!c6`^`{^2OoIHL_U-bxC{+Bo>}VP<#!$my%u zHD934rTmqUTR(Nzec@{@+2RbkQ+9f~{Sh@~Q*rJi^FEkW2wZk7pYk+t?=f6C%fJVt zYTm1e{gMBarPP(R;ep1#=>(vWs{ZO(BV}kc#Co9r3H`MXzmZ&1G-td57$z(#)H@N= zgRF%#qGdp1-A(G)d{WVJ;A6XMj#uy)0TBrp@y(dyBC-QoNsBN5s24e`LnKoUYfgWL zKJiI$fDY(vUvV*k#3A0ojRTA2qKvzi;nrAEPXm8+o z%|Q}X@(z_P7?xIM4TOQJ3^(?} zkO|e0E(Xoq+8bvrnwT~G*&0Y;bNt|z1_wxM9Az%Mlp)J~MEkLXS=v-&!3Tu($Rgx& zAgua=jr?CDWzLMFI{l8n=)GLsHjUhk!5zJty_HOD=ViPJn3qS}8XUh zK&?T{nLltuhI9e+l~8Q?`hOFx0Z%UJa!mSWGFaXnXAO3~o0bxjMzEqsqEWZ>b#ULtW7pR|xkVBrI&*bzm&F|Af2R>6 zY3U)@2}QUBALDyY8Gb8CYflrDAg#tbxhncg4YO*&iO&xjX3|=G@ftN@YcXHM4o_qi z6bAP`?3lmhT%8-(Rf`-*d1SiJaED!{&6O{H%-#bokN7>cj_DxvL_MCHyzWMgJcR5@ zA9gd^JYa$<*;glUQaY!B>AxojrZQMFHnK2#pw-B>RrCO5Bp_wRc!xNg z_u(z|SbvPuszuug#{rJ5CZvc>TclUmsojVqyKf42U#J24WcN$~8px6ZeA%gxq4CxD zii&FU2B^$vJmg~cL)AGp9n~Kn7vJd^6H)AW>vFFT1Q0<=kSPKlQ~xbfIM&S~%U?}m z5tX>oVmOifrjepph#Zf4=*=&3>J!n-%xBGM2VNw=F2km~>ZBIr(csPOo~NDTXy3Sr zn!I_nwC3rCgK@RTaX@RK1)oKS^{0&Hs=)JP(Mg~3_{ZMXvX-JDLriTE9i+?II75#}W>;5H{tY>d2FJ0NTuJ)--K%J{2Xg*-E zn9{MKV_o$@`+Be!)Hiw+S;k|(GdF~CW4B_xjfBSrbYiX`<*+9usK_76xZQRhi}vI(+>zX z<{*`%Nh6<~ojn<-QOqB^f=7xt-Wa>QLvY`;?yK2B>QRr^^O6@re?IGwWCQ-s8-8DX9>48PL^#{uz3&2~HX`&v zLmlEr0QTJG*ebro!W*dY$@Yk0d{!ddm&cK03j4W;`dk%4|F3~O`z68$XoLh{_l$Xe zsCN|lw)YC^@jye33Rzp_3FnXQhsPdjaCWkuFe`)}#wP3{CMix>0Yy0$_cT8^pK1q< z^_z0fG-4sQp}!6dheySclN6-ofJtrg3gHU=^FqcGDVbOm`PBCzZTCEQp`8Z~&x3)G zcEYe8i+@c;pEP;R1%)8(l-UQ)Pq)D+Tb!iQ1|p Date: Sat, 15 Feb 2020 13:51:13 -0800 Subject: [PATCH 03/12] Make RadialGradientBrush updates to the correct file --- .../RadialGradientBrush.md | 88 +++++++++++++++--- .../RadialGradientBrush.md | 88 +++--------------- .../images/LinearGradientBrush.png | Bin 3 files changed, 88 insertions(+), 88 deletions(-) rename {active => api_review}/RadialGradientBrush/images/LinearGradientBrush.png (100%) diff --git a/active/RadialGradientBrush/RadialGradientBrush.md b/active/RadialGradientBrush/RadialGradientBrush.md index 3615a8ac0..dc000ed79 100644 --- a/active/RadialGradientBrush/RadialGradientBrush.md +++ b/active/RadialGradientBrush/RadialGradientBrush.md @@ -1,15 +1,32 @@ + + + # Background -Xaml has a [LinearGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Media.LinearGradientBrush) to paint an area with a linear gradient. For example + -![A rectangle filled with a linear gradient.](images/LinearGradientBrush.png) + -This spec adds a new _radial_ gradient brush. + -This is roughly the same as WPF's [RadialGradientBrush](https://docs.microsoft.com/dotnet/api/System.Windows.Media.RadialGradientBrush), and is actually implemented using the existing Windows [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Composition.CompositionRadialGradientBrush). + -This brush will ship in the WinUI 2 NuGet/Framework package. Since it can be used on older Windows 10 versions, where the CompositionRadialGradientBrush isn't available, it has fallback behavior to draw a solid color instead when necessary, as is done by [AcrylicBrush](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Media.AcrylicBrush). + ## Composition brush usage @@ -21,7 +38,7 @@ Notable inconsistencies with the composition API include: 1. Usage of [Point](https://docs.microsoft.com/uwp/api/windows.foundation.point) rather than [Vector2](https://docs.microsoft.com/uwp/api/windows.foundation.numerics.vector2)/[float2](https://docs.microsoft.com/windows/win32/numerics_h/float2-structure) 2. Usage of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) rather than [CompositionColorGradientStop](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorgradientstop) -The main reason for the above is to enable Xaml markup parsing for brushes defined in markup and consistency with the rest of the Xaml API. +The main reason for the above is to enable Xaml markup parsing for brushes defined in markup. ### Animation support @@ -29,20 +46,18 @@ Ideally, RadialGradientBrush would support animation of GradientStops and other ## Downlevel fallback behavior -When this brush is used on pre-1903 versions of Windows, where [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Composition.CompositionRadialGradientBrush) isn't available, the options for fallback behavior are: +The options for fallback behavior on downlevel pre-1903 OS versions are: 1. Draw a gradient using another renderer, e.g. Direct2D * This would require loading additional expensive dependencies which WinUI doesn't currently rely on. 2. Draw a custom gradient surface, e.g. using a CompositionSurfaceBrush or WriteableBitmap * This would require largely reimplementing the complex CompositionRadialGradientBrush. 3. **Rely on FallbackColor** - * Draw a solid color, as specified by the [XamlCompositionBrushBase.FallbackColor](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Media.XamlCompositionBrushBase.FallbackColor) (which RadialGradientBrush will inherit from its base class). - -Using FallbackColor follows the precedence of [AcrylicBrush](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Media.AcrylicBrush). And since CompositionRadialGradientBrush should be available downlevel with WinUI 3, this seems like a reasonable approach in the meantime. + * Since [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) should be available downlevel with WinUI 3, #1 (FallbackColor) seems like a reasonable approach in the meantime. ## InterpolationSpace -Note that the underlying [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) currently only supports the following [CompositionColorSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorspace) values: +The underlying [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) currently only supports the following [CompositionColorSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorspace) values: * `Auto` * `Rgb` @@ -52,10 +67,27 @@ Applying any other interpolation color space will have no effect. # Description -RadialGradientBrush paints an area with a radial gradient. A center point defines the origin of the gradient, and an ellipse defines the outer bounds of the gradient. + + +Paints an area with a radial gradient. A center point defines the origin of the gradient, and an ellipse defines the outer bounds of the gradient. # Examples + + + + + + This example creates a radial gradient with six gradient stops and uses it to paint a Rectangle. ![A rectangle filled with a radial gradient.](images/ColorRadialGradientBrush.png) @@ -81,7 +113,7 @@ XAML ``` -This example creates a radial gradient that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset`: +This example creates a radial gradient with that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset`: ![A rectangle filled with an offset radial gradient.](images/OffsetRadialGradientBrush.png) @@ -107,6 +139,12 @@ This example creates a radial gradient that uses Absolute mapping mode with cust ``` # Remarks + + + ## Gradient layout @@ -118,7 +156,7 @@ The gradient origin defaults to center and can be offset using the `GradientOrig `MappingMode` defines whether `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset` represent relative or absolute coordinates. -When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOriginOffset` property. +When `MappingMode` is set to `RelativeTBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOriginOffset` property. When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the brush's rendered bounds. @@ -134,6 +172,15 @@ Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and h # API Notes + + + + ## Fields | | | @@ -147,24 +194,37 @@ Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and h | SpreadMethod | Gets or sets the type of spread method that specifies how to draw a gradient that starts or ends inside the bounds of the object to be painted. The default is `Pad`. | # API Details + ```C++ +[WUXC_VERSION_PREVIEW] [webhosthidden] [contentproperty("GradientStops")] unsealed runtimeclass RadialGradientBrush : Windows.UI.Xaml.Media.XamlCompositionBrushBase { RadialGradientBrush(); + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::Point(0.5,0.5)")] Windows.Foundation.Point EllipseCenter { get; set; }; + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::Point(0.5,0.5)")] Windows.Foundation.Point EllipseRadius { get; set; }; + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] Windows.Foundation.Point GradientOriginOffset { get; set; }; + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::BrushMappingMode::RelativeToBoundingBox")] Windows.UI.Xaml.Media.BrushMappingMode MappingMode { get; set; }; + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::Windows::UI::Composition::CompositionColorSpace::Auto")] Windows.UI.Composition.CompositionColorSpace InterpolationSpace { get; set; }; + [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] + [MUX_DEFAULT_VALUE("winrt::GradientSpreadMethod::Pad")] Windows.UI.Xaml.Media.GradientSpreadMethod SpreadMethod { get; set; }; Windows.Foundation.Collections.IObservableVector GradientStops { get; }; diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index dc000ed79..3615a8ac0 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -1,32 +1,15 @@ - - - # Background - +Xaml has a [LinearGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Media.LinearGradientBrush) to paint an area with a linear gradient. For example - +![A rectangle filled with a linear gradient.](images/LinearGradientBrush.png) - +This spec adds a new _radial_ gradient brush. - +This is roughly the same as WPF's [RadialGradientBrush](https://docs.microsoft.com/dotnet/api/System.Windows.Media.RadialGradientBrush), and is actually implemented using the existing Windows [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Composition.CompositionRadialGradientBrush). - +This brush will ship in the WinUI 2 NuGet/Framework package. Since it can be used on older Windows 10 versions, where the CompositionRadialGradientBrush isn't available, it has fallback behavior to draw a solid color instead when necessary, as is done by [AcrylicBrush](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Media.AcrylicBrush). ## Composition brush usage @@ -38,7 +21,7 @@ Notable inconsistencies with the composition API include: 1. Usage of [Point](https://docs.microsoft.com/uwp/api/windows.foundation.point) rather than [Vector2](https://docs.microsoft.com/uwp/api/windows.foundation.numerics.vector2)/[float2](https://docs.microsoft.com/windows/win32/numerics_h/float2-structure) 2. Usage of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) rather than [CompositionColorGradientStop](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorgradientstop) -The main reason for the above is to enable Xaml markup parsing for brushes defined in markup. +The main reason for the above is to enable Xaml markup parsing for brushes defined in markup and consistency with the rest of the Xaml API. ### Animation support @@ -46,18 +29,20 @@ Ideally, RadialGradientBrush would support animation of GradientStops and other ## Downlevel fallback behavior -The options for fallback behavior on downlevel pre-1903 OS versions are: +When this brush is used on pre-1903 versions of Windows, where [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Composition.CompositionRadialGradientBrush) isn't available, the options for fallback behavior are: 1. Draw a gradient using another renderer, e.g. Direct2D * This would require loading additional expensive dependencies which WinUI doesn't currently rely on. 2. Draw a custom gradient surface, e.g. using a CompositionSurfaceBrush or WriteableBitmap * This would require largely reimplementing the complex CompositionRadialGradientBrush. 3. **Rely on FallbackColor** - * Since [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) should be available downlevel with WinUI 3, #1 (FallbackColor) seems like a reasonable approach in the meantime. + * Draw a solid color, as specified by the [XamlCompositionBrushBase.FallbackColor](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Media.XamlCompositionBrushBase.FallbackColor) (which RadialGradientBrush will inherit from its base class). + +Using FallbackColor follows the precedence of [AcrylicBrush](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Media.AcrylicBrush). And since CompositionRadialGradientBrush should be available downlevel with WinUI 3, this seems like a reasonable approach in the meantime. ## InterpolationSpace -The underlying [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) currently only supports the following [CompositionColorSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorspace) values: +Note that the underlying [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) currently only supports the following [CompositionColorSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorspace) values: * `Auto` * `Rgb` @@ -67,27 +52,10 @@ Applying any other interpolation color space will have no effect. # Description - - -Paints an area with a radial gradient. A center point defines the origin of the gradient, and an ellipse defines the outer bounds of the gradient. +RadialGradientBrush paints an area with a radial gradient. A center point defines the origin of the gradient, and an ellipse defines the outer bounds of the gradient. # Examples - - - - - - This example creates a radial gradient with six gradient stops and uses it to paint a Rectangle. ![A rectangle filled with a radial gradient.](images/ColorRadialGradientBrush.png) @@ -113,7 +81,7 @@ XAML ``` -This example creates a radial gradient with that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset`: +This example creates a radial gradient that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset`: ![A rectangle filled with an offset radial gradient.](images/OffsetRadialGradientBrush.png) @@ -139,12 +107,6 @@ This example creates a radial gradient with that uses Absolute mapping mode with ``` # Remarks - - - ## Gradient layout @@ -156,7 +118,7 @@ The gradient origin defaults to center and can be offset using the `GradientOrig `MappingMode` defines whether `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset` represent relative or absolute coordinates. -When `MappingMode` is set to `RelativeTBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOriginOffset` property. +When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOriginOffset` property. When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the brush's rendered bounds. @@ -172,15 +134,6 @@ Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and h # API Notes - - - - ## Fields | | | @@ -194,37 +147,24 @@ with a "///" comment above the member or type. --> | SpreadMethod | Gets or sets the type of spread method that specifies how to draw a gradient that starts or ends inside the bounds of the object to be painted. The default is `Pad`. | # API Details - ```C++ -[WUXC_VERSION_PREVIEW] [webhosthidden] [contentproperty("GradientStops")] unsealed runtimeclass RadialGradientBrush : Windows.UI.Xaml.Media.XamlCompositionBrushBase { RadialGradientBrush(); - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::Point(0.5,0.5)")] Windows.Foundation.Point EllipseCenter { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::Point(0.5,0.5)")] Windows.Foundation.Point EllipseRadius { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] Windows.Foundation.Point GradientOriginOffset { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::BrushMappingMode::RelativeToBoundingBox")] Windows.UI.Xaml.Media.BrushMappingMode MappingMode { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::Windows::UI::Composition::CompositionColorSpace::Auto")] Windows.UI.Composition.CompositionColorSpace InterpolationSpace { get; set; }; - [MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] - [MUX_DEFAULT_VALUE("winrt::GradientSpreadMethod::Pad")] Windows.UI.Xaml.Media.GradientSpreadMethod SpreadMethod { get; set; }; Windows.Foundation.Collections.IObservableVector GradientStops { get; }; diff --git a/active/RadialGradientBrush/images/LinearGradientBrush.png b/api_review/RadialGradientBrush/images/LinearGradientBrush.png similarity index 100% rename from active/RadialGradientBrush/images/LinearGradientBrush.png rename to api_review/RadialGradientBrush/images/LinearGradientBrush.png From 641a39bbf5bd1c15609b845ea9a2f2169091685a Mon Sep 17 00:00:00 2001 From: MikeHillberg <18429489+MikeHillberg@users.noreply.github.com> Date: Mon, 30 Mar 2020 14:06:30 -0700 Subject: [PATCH 04/12] Update GradientOriginOffset to GradientOrigin --- .../RadialGradientBrush.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index 3615a8ac0..5465ae59a 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -15,7 +15,7 @@ This brush will ship in the WinUI 2 NuGet/Framework package. Since it can be use The Xaml RadialGradientBrush will inherit from [XamlCompositionBrushBase](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.xamlcompositionbrushbase) and use a [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush), which is supported on Windows 10 1903 (v10.0.18362+). This seems like a useful model for new brushes going forward for both WinUI 2 and 3, and we aren't too concerned about duplicating some properties from other candidate base classes [GradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientbrush). -The RadialGradientBrush API will more closely mirror the behavior of the Composition API than the WPF API: for example, the gradient origin defaults to center and provides a `GradientOriginOffset` property to specify an offset rather than providing a `GradientOrigin` property. +The RadialGradientBrush API will more closely mirror the behavior of the Composition API than the WPF API: for example, the gradient origin defaults to center and provides a `GradientOrigin` property to specify an offset rather than providing a `GradientOrigin` property. Notable inconsistencies with the composition API include: 1. Usage of [Point](https://docs.microsoft.com/uwp/api/windows.foundation.point) rather than [Vector2](https://docs.microsoft.com/uwp/api/windows.foundation.numerics.vector2)/[float2](https://docs.microsoft.com/windows/win32/numerics_h/float2-structure) @@ -35,7 +35,7 @@ When this brush is used on pre-1903 versions of Windows, where [CompositionRadia * This would require loading additional expensive dependencies which WinUI doesn't currently rely on. 2. Draw a custom gradient surface, e.g. using a CompositionSurfaceBrush or WriteableBitmap * This would require largely reimplementing the complex CompositionRadialGradientBrush. -3. **Rely on FallbackColor** +3. **Rely on FallbackColor** (chosen option) * Draw a solid color, as specified by the [XamlCompositionBrushBase.FallbackColor](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Media.XamlCompositionBrushBase.FallbackColor) (which RadialGradientBrush will inherit from its base class). Using FallbackColor follows the precedence of [AcrylicBrush](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Media.AcrylicBrush). And since CompositionRadialGradientBrush should be available downlevel with WinUI 3, this seems like a reasonable approach in the meantime. @@ -81,7 +81,7 @@ XAML ``` -This example creates a radial gradient that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset`: +This example creates a radial gradient that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOrigin`: ![A rectangle filled with an offset radial gradient.](images/OffsetRadialGradientBrush.png) @@ -93,9 +93,9 @@ This example creates a radial gradient that uses Absolute mapping mode with cust @@ -114,11 +114,11 @@ The gradient is drawn within an ellipse that is defined by the `EllipseCenter` a The colors for the radial gradient are defined by color stops added to the `GradientStops` collection property. Each gradient stop specifies a color and an offset along the gradient. -The gradient origin defaults to center and can be offset using the `GradientOriginOffset` property. +The gradient origin defaults to center and can be offset using the `GradientOrigin` property. -`MappingMode` defines whether `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset` represent relative or absolute coordinates. +`MappingMode` defines whether `EllipseCenter`, `EllipseRadius` and `GradientOrigin` represent relative or absolute coordinates. -When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOriginOffset` property. +When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOrigin` property. When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the brush's rendered bounds. @@ -140,10 +140,10 @@ Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and h | - | - | | EllipseCenter | The center of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | | EllipseRadius | The radius of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | -| GradientOriginOffset | The gradient origin's offset from the center of the element. | +| GradientOrigin | The gradient origin's offset from the center of the element. | | GradientStops | A collection of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) objects that define the gradient. | | InterpolationSpace | The color space used to interpolate the gradient's colors. The default is `Auto`. For supported values, see [CompositionRadialGradientBrush.InterpolationSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositiongradientbrush.interpolationspace#Windows_UI_Composition_CompositionGradientBrush_InterpolationSpace) | -| MappingMode | Defines whether `EllipseCenter`, `EllipseRadius` and `GradientOriginOffset` represent relative coordinates in the range 0 to 1 or absolute coordinates. The default is `RelativeToBoundingBox`. | +| MappingMode | Defines whether `EllipseCenter`, `EllipseRadius` and `GradientOrigin` represent relative coordinates in the range 0 to 1 or absolute coordinates. The default is `RelativeToBoundingBox`. | | SpreadMethod | Gets or sets the type of spread method that specifies how to draw a gradient that starts or ends inside the bounds of the object to be painted. The default is `Pad`. | # API Details @@ -159,7 +159,7 @@ unsealed runtimeclass RadialGradientBrush : Windows.UI.Xaml.Media.XamlCompositio Windows.Foundation.Point EllipseRadius { get; set; }; - Windows.Foundation.Point GradientOriginOffset { get; set; }; + Windows.Foundation.Point GradientOrigin { get; set; }; Windows.UI.Xaml.Media.BrushMappingMode MappingMode { get; set; }; @@ -171,7 +171,7 @@ unsealed runtimeclass RadialGradientBrush : Windows.UI.Xaml.Media.XamlCompositio static Windows.UI.Xaml.DependencyProperty EllipseCenterProperty { get; }; static Windows.UI.Xaml.DependencyProperty EllipseRadiusProperty { get; }; - static Windows.UI.Xaml.DependencyProperty GradientOriginOffsetProperty { get; }; + static Windows.UI.Xaml.DependencyProperty GradientOriginProperty { get; }; static Windows.UI.Xaml.DependencyProperty InterpolationSpaceProperty { get; }; static Windows.UI.Xaml.DependencyProperty MappingModeProperty { get; }; static Windows.UI.Xaml.DependencyProperty SpreadMethodProperty { get; }; From f3bed500070767012969a15ac85a9c7d4fa23cb7 Mon Sep 17 00:00:00 2001 From: MikeHillberg <18429489+MikeHillberg@users.noreply.github.com> Date: Wed, 1 Apr 2020 11:26:30 -0700 Subject: [PATCH 05/12] Updates for mapping mode, WPF comparison --- .../RadialGradientBrush/RadialGradientBrush.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index 5465ae59a..97f035cee 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -15,9 +15,9 @@ This brush will ship in the WinUI 2 NuGet/Framework package. Since it can be use The Xaml RadialGradientBrush will inherit from [XamlCompositionBrushBase](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.xamlcompositionbrushbase) and use a [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush), which is supported on Windows 10 1903 (v10.0.18362+). This seems like a useful model for new brushes going forward for both WinUI 2 and 3, and we aren't too concerned about duplicating some properties from other candidate base classes [GradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientbrush). -The RadialGradientBrush API will more closely mirror the behavior of the Composition API than the WPF API: for example, the gradient origin defaults to center and provides a `GradientOrigin` property to specify an offset rather than providing a `GradientOrigin` property. +The RadialGradientBrush API aligns with the WPF API, but differs from the Composition API, by having a GradientOrigin property rather than a GradientOriginOffset. The GradientOrigin has a coordinate space where (0,0) is the upper left corner, and defaults to (0.5,0.5). -Notable inconsistencies with the composition API include: +Other inconsistencies with the composition API include: 1. Usage of [Point](https://docs.microsoft.com/uwp/api/windows.foundation.point) rather than [Vector2](https://docs.microsoft.com/uwp/api/windows.foundation.numerics.vector2)/[float2](https://docs.microsoft.com/windows/win32/numerics_h/float2-structure) 2. Usage of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) rather than [CompositionColorGradientStop](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositioncolorgradientstop) @@ -93,9 +93,9 @@ This example creates a radial gradient that uses Absolute mapping mode with cust @@ -140,7 +140,7 @@ Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and h | - | - | | EllipseCenter | The center of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | | EllipseRadius | The radius of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | -| GradientOrigin | The gradient origin's offset from the center of the element. | +| GradientOrigin | The gradient origin's offset from the center of the element. The default is `(0.5, 0,5)`.| | GradientStops | A collection of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) objects that define the gradient. | | InterpolationSpace | The color space used to interpolate the gradient's colors. The default is `Auto`. For supported values, see [CompositionRadialGradientBrush.InterpolationSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositiongradientbrush.interpolationspace#Windows_UI_Composition_CompositionGradientBrush_InterpolationSpace) | | MappingMode | Defines whether `EllipseCenter`, `EllipseRadius` and `GradientOrigin` represent relative coordinates in the range 0 to 1 or absolute coordinates. The default is `RelativeToBoundingBox`. | From e2ee88d144500da6ef0a9c6ea32293b991b65184 Mon Sep 17 00:00:00 2001 From: MikeHillberg <18429489+MikeHillberg@users.noreply.github.com> Date: Wed, 1 Apr 2020 11:31:14 -0700 Subject: [PATCH 06/12] Update GradientOrigin API note --- api_review/RadialGradientBrush/RadialGradientBrush.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index 97f035cee..1c1508079 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -140,7 +140,7 @@ Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and h | - | - | | EllipseCenter | The center of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | | EllipseRadius | The radius of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | -| GradientOrigin | The gradient origin's offset from the center of the element. The default is `(0.5, 0,5)`.| +| GradientOrigin | The gradient's origin (relative to the top left corner). The default is `(0.5, 0,5)`.| | GradientStops | A collection of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) objects that define the gradient. | | InterpolationSpace | The color space used to interpolate the gradient's colors. The default is `Auto`. For supported values, see [CompositionRadialGradientBrush.InterpolationSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositiongradientbrush.interpolationspace#Windows_UI_Composition_CompositionGradientBrush_InterpolationSpace) | | MappingMode | Defines whether `EllipseCenter`, `EllipseRadius` and `GradientOrigin` represent relative coordinates in the range 0 to 1 or absolute coordinates. The default is `RelativeToBoundingBox`. | From aa25347601588feed38de7fb12f423a4df151a5f Mon Sep 17 00:00:00 2001 From: Savoy Schuler Date: Sun, 26 Apr 2020 22:26:34 -0700 Subject: [PATCH 07/12] IDL: Renamed EllipseCenter to Center and broke up EllipseRadius into RadiusX and RadiusY. --- api_review/RadialGradientBrush/RadialGradientBrush.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index 1c1508079..2ace8cedf 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -155,9 +155,11 @@ unsealed runtimeclass RadialGradientBrush : Windows.UI.Xaml.Media.XamlCompositio { RadialGradientBrush(); - Windows.Foundation.Point EllipseCenter { get; set; }; + Windows.Foundation.Point Center { get; set; }; - Windows.Foundation.Point EllipseRadius { get; set; }; + Windows.Foundation.Point RadiusX { get; set; }; + + Windows.Foundation.Point RadiusY { get; set; }; Windows.Foundation.Point GradientOrigin { get; set; }; @@ -169,8 +171,9 @@ unsealed runtimeclass RadialGradientBrush : Windows.UI.Xaml.Media.XamlCompositio Windows.Foundation.Collections.IObservableVector GradientStops { get; }; - static Windows.UI.Xaml.DependencyProperty EllipseCenterProperty { get; }; - static Windows.UI.Xaml.DependencyProperty EllipseRadiusProperty { get; }; + static Windows.UI.Xaml.DependencyProperty CenterProperty { get; }; + static Windows.UI.Xaml.DependencyProperty RadiusXProperty { get; }; + static Windows.UI.Xaml.DependencyProperty RadiusYProperty { get; }; static Windows.UI.Xaml.DependencyProperty GradientOriginProperty { get; }; static Windows.UI.Xaml.DependencyProperty InterpolationSpaceProperty { get; }; static Windows.UI.Xaml.DependencyProperty MappingModeProperty { get; }; From f503159cb2babe3970d1588e4e93603a5af7f6b8 Mon Sep 17 00:00:00 2001 From: Savoy Schuler Date: Sun, 26 Apr 2020 22:29:37 -0700 Subject: [PATCH 08/12] Replaced EllipseCenter to Center throughout spec. --- .../RadialGradientBrush/RadialGradientBrush.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index 2ace8cedf..828c62488 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -81,7 +81,7 @@ XAML ``` -This example creates a radial gradient that uses Absolute mapping mode with custom values for `EllipseCenter`, `EllipseRadius` and `GradientOrigin`: +This example creates a radial gradient that uses Absolute mapping mode with custom values for `Center`, `EllipseRadius` and `GradientOrigin`: ![A rectangle filled with an offset radial gradient.](images/OffsetRadialGradientBrush.png) @@ -93,7 +93,7 @@ This example creates a radial gradient that uses Absolute mapping mode with cust @@ -110,15 +110,15 @@ This example creates a radial gradient that uses Absolute mapping mode with cust ## Gradient layout -The gradient is drawn within an ellipse that is defined by the `EllipseCenter` and `EllipseRadius` properties. Colors for the gradient start at the center of the ellipse and end at the radius. +The gradient is drawn within an ellipse that is defined by the `Center` and `EllipseRadius` properties. Colors for the gradient start at the center of the ellipse and end at the radius. The colors for the radial gradient are defined by color stops added to the `GradientStops` collection property. Each gradient stop specifies a color and an offset along the gradient. The gradient origin defaults to center and can be offset using the `GradientOrigin` property. -`MappingMode` defines whether `EllipseCenter`, `EllipseRadius` and `GradientOrigin` represent relative or absolute coordinates. +`MappingMode` defines whether `Center`, `EllipseRadius` and `GradientOrigin` represent relative or absolute coordinates. -When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `EllipseCenter` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOrigin` property. +When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `Center` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOrigin` property. When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the brush's rendered bounds. @@ -138,12 +138,12 @@ Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and h | | | | - | - | -| EllipseCenter | The center of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | +| Center | The center of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | | EllipseRadius | The radius of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | | GradientOrigin | The gradient's origin (relative to the top left corner). The default is `(0.5, 0,5)`.| | GradientStops | A collection of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) objects that define the gradient. | | InterpolationSpace | The color space used to interpolate the gradient's colors. The default is `Auto`. For supported values, see [CompositionRadialGradientBrush.InterpolationSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositiongradientbrush.interpolationspace#Windows_UI_Composition_CompositionGradientBrush_InterpolationSpace) | -| MappingMode | Defines whether `EllipseCenter`, `EllipseRadius` and `GradientOrigin` represent relative coordinates in the range 0 to 1 or absolute coordinates. The default is `RelativeToBoundingBox`. | +| MappingMode | Defines whether `Center`, `EllipseRadius` and `GradientOrigin` represent relative coordinates in the range 0 to 1 or absolute coordinates. The default is `RelativeToBoundingBox`. | | SpreadMethod | Gets or sets the type of spread method that specifies how to draw a gradient that starts or ends inside the bounds of the object to be painted. The default is `Pad`. | # API Details From cc30b6f83892b1f05f9ef4c328e20061bfb5f3c9 Mon Sep 17 00:00:00 2001 From: Savoy Schuler Date: Sun, 26 Apr 2020 22:36:06 -0700 Subject: [PATCH 09/12] Broke up EllipseRadius into RadiusX and RadiusY throughout spec. --- .../RadialGradientBrush/RadialGradientBrush.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index 828c62488..0617cd180 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -81,7 +81,7 @@ XAML ``` -This example creates a radial gradient that uses Absolute mapping mode with custom values for `Center`, `EllipseRadius` and `GradientOrigin`: +This example creates a radial gradient that uses Absolute mapping mode with custom values for `Center`, `RadiusX`, `RadiusY` and `GradientOrigin`: ![A rectangle filled with an offset radial gradient.](images/OffsetRadialGradientBrush.png) @@ -94,7 +94,8 @@ This example creates a radial gradient that uses Absolute mapping mode with cust @@ -110,15 +111,15 @@ This example creates a radial gradient that uses Absolute mapping mode with cust ## Gradient layout -The gradient is drawn within an ellipse that is defined by the `Center` and `EllipseRadius` properties. Colors for the gradient start at the center of the ellipse and end at the radius. +The gradient is drawn within an ellipse that is defined by the `Center`, `RadiusX`, and `RadiusY` properties. Colors for the gradient start at the center of the ellipse and end at the radius. The colors for the radial gradient are defined by color stops added to the `GradientStops` collection property. Each gradient stop specifies a color and an offset along the gradient. The gradient origin defaults to center and can be offset using the `GradientOrigin` property. -`MappingMode` defines whether `Center`, `EllipseRadius` and `GradientOrigin` represent relative or absolute coordinates. +`MappingMode` defines whether `Center`, `RadiusX`, `RadiusY`, and `GradientOrigin` represent relative or absolute coordinates. -When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `Center` and `EllipseRadius` properties and `(0,0)` represents the center for the `GradientOrigin` property. +When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `Center`, `RadiusX`, and `RadiusY` properties and `(0,0)` represents the center for the `GradientOrigin` property. When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the brush's rendered bounds. @@ -139,11 +140,12 @@ Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and h | | | | - | - | | Center | The center of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | -| EllipseRadius | The radius of the ellipse that contains the gradient. The default is `(0.5, 0.5)`. | +| RadiusX | The X axis radius of the ellipse that contains the gradient. The default is `0.5`. | +| RadiusY | The Y axis radius of the ellipse that contains the gradient. The default is `0.5`. | | GradientOrigin | The gradient's origin (relative to the top left corner). The default is `(0.5, 0,5)`.| | GradientStops | A collection of [GradientStop](https://docs.microsoft.com/uwp/api/windows.ui.xaml.media.gradientstop) objects that define the gradient. | | InterpolationSpace | The color space used to interpolate the gradient's colors. The default is `Auto`. For supported values, see [CompositionRadialGradientBrush.InterpolationSpace](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositiongradientbrush.interpolationspace#Windows_UI_Composition_CompositionGradientBrush_InterpolationSpace) | -| MappingMode | Defines whether `Center`, `EllipseRadius` and `GradientOrigin` represent relative coordinates in the range 0 to 1 or absolute coordinates. The default is `RelativeToBoundingBox`. | +| MappingMode | Defines whether `Center`, `RadiusX`, `RadiusY`, and `GradientOrigin` represent relative coordinates in the range 0 to 1 or absolute coordinates. The default is `RelativeToBoundingBox`. | | SpreadMethod | Gets or sets the type of spread method that specifies how to draw a gradient that starts or ends inside the bounds of the object to be painted. The default is `Pad`. | # API Details From 96c5d09b41df8bf797c0eefd387d00d871c1c189 Mon Sep 17 00:00:00 2001 From: Savoy Schuler Date: Tue, 28 Apr 2020 01:22:55 -0700 Subject: [PATCH 10/12] Brush's rendered bounds -> element bounds --- api_review/RadialGradientBrush/RadialGradientBrush.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index 0617cd180..319fb16c1 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -119,9 +119,9 @@ The gradient origin defaults to center and can be offset using the `GradientOrig `MappingMode` defines whether `Center`, `RadiusX`, `RadiusY`, and `GradientOrigin` represent relative or absolute coordinates. -When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the brush's rendered bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the brush's rendered bounds for the `Center`, `RadiusX`, and `RadiusY` properties and `(0,0)` represents the center for the `GradientOrigin` property. +When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the three properties are treated as relative to the element bounds, where `(0,0)` represents the top left and `(1,1)` represents the bottom right of the element bounds for the `Center`, `RadiusX`, and `RadiusY` properties and `(0,0)` represents the center for the `GradientOrigin` property. -When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the brush's rendered bounds. +When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the element bounds. ## Windows 10 Version Support From 7b5c3c18a8a7f6ad81d35c41ddaa68be85cb69be Mon Sep 17 00:00:00 2001 From: MikeHillberg <18429489+MikeHillberg@users.noreply.github.com> Date: Thu, 17 Dec 2020 15:45:31 -0800 Subject: [PATCH 11/12] Fix radius type --- api_review/RadialGradientBrush/RadialGradientBrush.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index 319fb16c1..33b59eefe 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -159,9 +159,9 @@ unsealed runtimeclass RadialGradientBrush : Windows.UI.Xaml.Media.XamlCompositio Windows.Foundation.Point Center { get; set; }; - Windows.Foundation.Point RadiusX { get; set; }; + double RadiusX { get; set; }; - Windows.Foundation.Point RadiusY { get; set; }; + double RadiusY { get; set; }; Windows.Foundation.Point GradientOrigin { get; set; }; From a8fe70c764b76523a74413ef8ec808cdf1e0856f Mon Sep 17 00:00:00 2001 From: MikeHillberg <18429489+MikeHillberg@users.noreply.github.com> Date: Thu, 17 Dec 2020 15:52:10 -0800 Subject: [PATCH 12/12] Formatting --- .../RadialGradientBrush.md | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/api_review/RadialGradientBrush/RadialGradientBrush.md b/api_review/RadialGradientBrush/RadialGradientBrush.md index 33b59eefe..f0e9bcc4c 100644 --- a/api_review/RadialGradientBrush/RadialGradientBrush.md +++ b/api_review/RadialGradientBrush/RadialGradientBrush.md @@ -50,17 +50,16 @@ Note that the underlying [CompositionRadialGradientBrush](https://docs.microsoft Applying any other interpolation color space will have no effect. -# Description +# API Pages + +## RadialGradientBrush class RadialGradientBrush paints an area with a radial gradient. A center point defines the origin of the gradient, and an ellipse defines the outer bounds of the gradient. -# Examples +### Examples This example creates a radial gradient with six gradient stops and uses it to paint a Rectangle. -![A rectangle filled with a radial gradient.](images/ColorRadialGradientBrush.png) - -XAML ```XAML @@ -81,9 +80,9 @@ XAML ``` -This example creates a radial gradient that uses Absolute mapping mode with custom values for `Center`, `RadiusX`, `RadiusY` and `GradientOrigin`: +![A rectangle filled with a radial gradient.](images/ColorRadialGradientBrush.png) -![A rectangle filled with an offset radial gradient.](images/OffsetRadialGradientBrush.png) +This example creates a radial gradient that uses Absolute mapping mode with custom values for `Center`, `RadiusX`, `RadiusY` and `GradientOrigin`: ```XAML ``` -# Remarks +![A rectangle filled with an offset radial gradient.](images/OffsetRadialGradientBrush.png) -## Gradient layout +### Remarks + +**Gradient Layout** The gradient is drawn within an ellipse that is defined by the `Center`, `RadiusX`, and `RadiusY` properties. Colors for the gradient start at the center of the ellipse and end at the radius. @@ -123,19 +124,17 @@ When `MappingMode` is set to `RelativeToBoundingBox`, the X and Y values of the When `MappingMode` is set to `Absolute`, the X and Y values of the three properties are treated as absolute coordinates within the element bounds. -## Windows 10 Version Support +**Windows 10 Version Support** Gradient rendering is supported on Windows 10 version 1903 (v10.0.18362.0) and higher. On previous OS versions the brush will render a solid color specified by the `FallbackColor` property. -## See Also +### See Also * [LinearGradientBrush](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Media.LinearGradientBrush) * [CompositionRadialGradientBrush](https://docs.microsoft.com/uwp/api/windows.ui.composition.compositionradialgradientbrush) -# API Notes - -## Fields +### Member info | | | | - | - |