@@ -886,151 +886,157 @@ private static void ConfigureGradientBrush(ref PaintWrapper paintWrapper, Rect t
886
886
switch ( gradientBrush )
887
887
{
888
888
case ILinearGradientBrush linearGradient :
889
- {
890
- var start = linearGradient . StartPoint . ToPixels ( targetRect ) . ToSKPoint ( ) ;
891
- var end = linearGradient . EndPoint . ToPixels ( targetRect ) . ToSKPoint ( ) ;
892
-
893
- // would be nice to cache these shaders possibly?
894
- if ( linearGradient . Transform is null )
895
889
{
896
- using ( var shader =
897
- SKShader . CreateLinearGradient ( start , end , stopColors , stopOffsets , tileMode ) )
890
+ var start = linearGradient . StartPoint . ToPixels ( targetRect ) . ToSKPoint ( ) ;
891
+ var end = linearGradient . EndPoint . ToPixels ( targetRect ) . ToSKPoint ( ) ;
892
+
893
+ // would be nice to cache these shaders possibly?
894
+ if ( linearGradient . Transform is null )
898
895
{
899
- paintWrapper . Paint . Shader = shader ;
896
+ using ( var shader =
897
+ SKShader . CreateLinearGradient ( start , end , stopColors , stopOffsets , tileMode ) )
898
+ {
899
+ paintWrapper . Paint . Shader = shader ;
900
+ }
900
901
}
901
- }
902
- else
903
- {
904
- var transformOrigin = linearGradient . TransformOrigin . ToPixels ( targetRect ) ;
905
- var offset = Matrix . CreateTranslation ( transformOrigin ) ;
906
- var transform = ( - offset ) * linearGradient . Transform . Value * ( offset ) ;
907
-
908
- using ( var shader =
909
- SKShader . CreateLinearGradient ( start , end , stopColors , stopOffsets , tileMode , transform . ToSKMatrix ( ) ) )
902
+ else
910
903
{
911
- paintWrapper . Paint . Shader = shader ;
912
- }
913
- }
914
-
915
- break ;
916
- }
917
- case IRadialGradientBrush radialGradient :
918
- {
919
- var centerPoint = radialGradient . Center . ToPixels ( targetRect ) ;
920
- var center = centerPoint . ToSKPoint ( ) ;
921
-
922
- var radiusX = ( radialGradient . RadiusX . ToValue ( targetRect . Width ) ) ;
923
- var radiusY = ( radialGradient . RadiusY . ToValue ( targetRect . Height ) ) ;
904
+ var transformOrigin = linearGradient . TransformOrigin . ToPixels ( targetRect ) ;
905
+ var offset = Matrix . CreateTranslation ( transformOrigin ) ;
906
+ var transform = ( - offset ) * linearGradient . Transform . Value * ( offset ) ;
924
907
925
- var originPoint = radialGradient . GradientOrigin . ToPixels ( targetRect ) ;
926
-
927
- Matrix ? transform = null ;
928
-
929
- if ( radiusX != radiusY )
930
- transform =
931
- Matrix . CreateTranslation ( - centerPoint )
932
- * Matrix . CreateScale ( 1 , radiusY / radiusX )
933
- * Matrix . CreateTranslation ( centerPoint ) ;
934
-
935
-
936
- if ( radialGradient . Transform != null )
937
- {
938
- var transformOrigin = radialGradient . TransformOrigin . ToPixels ( targetRect ) ;
939
- var offset = Matrix . CreateTranslation ( transformOrigin ) ;
940
- var brushTransform = ( - offset ) * radialGradient . Transform . Value * ( offset ) ;
941
- transform = transform . HasValue ? transform * brushTransform : brushTransform ;
942
- }
943
-
944
- if ( originPoint . Equals ( centerPoint ) )
945
- {
946
- // when the origin is the same as the center the Skia RadialGradient acts the same as D2D
947
- using ( var shader =
948
- transform . HasValue
949
- ? SKShader . CreateRadialGradient ( center , ( float ) radiusX , stopColors , stopOffsets , tileMode ,
950
- transform . Value . ToSKMatrix ( ) )
951
- : SKShader . CreateRadialGradient ( center , ( float ) radiusX , stopColors , stopOffsets , tileMode )
952
- )
953
- {
954
- paintWrapper . Paint . Shader = shader ;
908
+ using ( var shader =
909
+ SKShader . CreateLinearGradient ( start , end , stopColors , stopOffsets , tileMode , transform . ToSKMatrix ( ) ) )
910
+ {
911
+ paintWrapper . Paint . Shader = shader ;
912
+ }
955
913
}
914
+
915
+ break ;
956
916
}
957
- else
917
+ case IRadialGradientBrush radialGradient :
958
918
{
959
- // when the origin is different to the center use a two point ConicalGradient to match the behaviour of D2D
919
+ var centerPoint = radialGradient . Center . ToPixels ( targetRect ) ;
920
+ var center = centerPoint . ToSKPoint ( ) ;
921
+
922
+ var radiusX = ( radialGradient . RadiusX . ToValue ( targetRect . Width ) ) ;
923
+ var radiusY = ( radialGradient . RadiusY . ToValue ( targetRect . Height ) ) ;
924
+
925
+ var originPoint = radialGradient . GradientOrigin . ToPixels ( targetRect ) ;
926
+
927
+ Matrix ? transform = null ;
960
928
961
929
if ( radiusX != radiusY )
962
- // Adjust the origin point for radiusX/Y transformation by reversing it
963
- originPoint = originPoint . WithY (
964
- ( originPoint . Y - centerPoint . Y ) * radiusX / radiusY + centerPoint . Y ) ;
965
-
966
- var origin = originPoint . ToSKPoint ( ) ;
930
+ transform =
931
+ Matrix . CreateTranslation ( - centerPoint )
932
+ * Matrix . CreateScale ( 1 , radiusY / radiusX )
933
+ * Matrix . CreateTranslation ( centerPoint ) ;
967
934
968
- var endOffset = 0.0 ;
969
935
970
- // and then reverse the reference point of the stops
971
- var reversedStops = new float [ stopOffsets . Length ] ;
972
- for ( var i = 0 ; i < stopOffsets . Length ; i ++ )
936
+ if ( radialGradient . Transform != null )
973
937
{
974
- var offset = stopOffsets [ i ] ;
938
+ var transformOrigin = radialGradient . TransformOrigin . ToPixels ( targetRect ) ;
939
+ var offset = Matrix . CreateTranslation ( transformOrigin ) ;
940
+ var brushTransform = ( - offset ) * radialGradient . Transform . Value * ( offset ) ;
941
+ transform = transform . HasValue ? transform * brushTransform : brushTransform ;
942
+ }
975
943
976
- if ( endOffset < offset )
944
+ if ( originPoint . Equals ( centerPoint ) )
945
+ {
946
+ // when the origin is the same as the center the Skia RadialGradient acts the same as D2D
947
+ using ( var shader =
948
+ transform . HasValue
949
+ ? SKShader . CreateRadialGradient ( center , ( float ) radiusX , stopColors , stopOffsets , tileMode ,
950
+ transform . Value . ToSKMatrix ( ) )
951
+ : SKShader . CreateRadialGradient ( center , ( float ) radiusX , stopColors , stopOffsets , tileMode )
952
+ )
977
953
{
978
- endOffset = offset ;
954
+ paintWrapper . Paint . Shader = shader ;
979
955
}
980
-
981
- reversedStops [ i ] = offset ;
982
-
983
- if ( reversedStops [ i ] > 0 && reversedStops [ i ] < 1 )
956
+ }
957
+ else
958
+ {
959
+ // when the origin is different to the center use a two point ConicalGradient to match the behaviour of D2D
960
+ if ( radiusX != radiusY )
961
+ // Adjust the origin point for radiusX/Y transformation by reversing it
962
+ originPoint = originPoint . WithY (
963
+ ( originPoint . Y - centerPoint . Y ) * radiusX / radiusY + centerPoint . Y ) ;
964
+ var origin = originPoint . ToSKPoint ( ) ;
965
+ var endOffset = 0.0 ;
966
+ // and then reverse the reference point of the stops
967
+ var reversedStops = new float [ stopOffsets . Length ] ;
968
+ for ( var i = 0 ; i < stopOffsets . Length ; i ++ )
984
969
{
985
- reversedStops [ i ] = Math . Abs ( 1 - offset ) ;
970
+ var offset = stopOffsets [ i ] ;
971
+ if ( endOffset < offset )
972
+ {
973
+ endOffset = offset ;
974
+ }
975
+ reversedStops [ i ] = offset ;
976
+ if ( reversedStops [ i ] > 0 && reversedStops [ i ] < 1 )
977
+ {
978
+ reversedStops [ i ] = Math . Abs ( 1 - offset ) ;
979
+ }
986
980
}
987
- }
988
-
989
- // compose with a background colour of the final stop to match D2D's behaviour of filling with the final color
990
- using ( var shader = SKShader . CreateCompose (
991
- SKShader . CreateColor ( stopColors [ 0 ] ) ,
992
- transform . HasValue
993
- ? SKShader . CreateTwoPointConicalGradient ( start , radiusStart , end , radiusEnd ,
994
- stopColors , stopOffsets , tileMode , transform . Value . ToSKMatrix ( ) )
995
- : SKShader . CreateTwoPointConicalGradient ( start , radiusStart , end , radiusEnd ,
996
- stopColors , stopOffsets , tileMode )
997
-
981
+ var start = origin ;
982
+ var radiusStart = 0f ;
983
+ var end = center ;
984
+ var radiusEnd = ( float ) radiusX ;
985
+ var reverse = MathUtilities . AreClose ( 1 , endOffset ) ;
986
+ if ( reverse )
987
+ {
988
+ ( start , radiusStart , end , radiusEnd ) = ( end , radiusEnd , start , radiusStart ) ;
989
+ // reverse the order of the stops to match D2D
990
+ var reversedColors = new SKColor [ stopColors . Length ] ;
991
+ Array . Copy ( stopColors , reversedColors , stopColors . Length ) ;
992
+ Array . Reverse ( reversedColors ) ;
993
+ stopColors = reversedColors ;
994
+ stopOffsets = reversedStops ;
995
+ }
996
+ // compose with a background colour of the final stop to match D2D's behaviour of filling with the final color
997
+ using ( var shader = SKShader . CreateCompose (
998
+ SKShader . CreateColor ( stopColors [ 0 ] ) ,
999
+ transform . HasValue
1000
+ ? SKShader . CreateTwoPointConicalGradient ( start , radiusStart , end , radiusEnd ,
1001
+ stopColors , stopOffsets , tileMode , transform . Value . ToSKMatrix ( ) )
1002
+ : SKShader . CreateTwoPointConicalGradient ( start , radiusStart , end , radiusEnd ,
1003
+ stopColors , stopOffsets , tileMode )
998
1004
)
999
- )
1000
- {
1001
- paintWrapper . Paint . Shader = shader ;
1005
+ )
1006
+ {
1007
+ paintWrapper . Paint . Shader = shader ;
1008
+ }
1002
1009
}
1003
- }
1004
1010
1005
- break ;
1006
- }
1011
+ break ;
1012
+ }
1007
1013
case IConicGradientBrush conicGradient :
1008
- {
1009
- var center = conicGradient . Center . ToPixels ( targetRect ) . ToSKPoint ( ) ;
1014
+ {
1015
+ var center = conicGradient . Center . ToPixels ( targetRect ) . ToSKPoint ( ) ;
1010
1016
1011
- // Skia's default is that angle 0 is from the right hand side of the center point
1012
- // but we are matching CSS where the vertical point above the center is 0.
1013
- var angle = ( float ) ( conicGradient . Angle - 90 ) ;
1014
- var rotation = SKMatrix . CreateRotationDegrees ( angle , center . X , center . Y ) ;
1017
+ // Skia's default is that angle 0 is from the right hand side of the center point
1018
+ // but we are matching CSS where the vertical point above the center is 0.
1019
+ var angle = ( float ) ( conicGradient . Angle - 90 ) ;
1020
+ var rotation = SKMatrix . CreateRotationDegrees ( angle , center . X , center . Y ) ;
1015
1021
1016
- if ( conicGradient . Transform is { } )
1017
- {
1018
-
1019
- var transformOrigin = conicGradient . TransformOrigin . ToPixels ( targetRect ) ;
1020
- var offset = Matrix . CreateTranslation ( transformOrigin ) ;
1021
- var transform = ( - offset ) * conicGradient . Transform . Value * ( offset ) ;
1022
+ if ( conicGradient . Transform is { } )
1023
+ {
1022
1024
1023
- rotation = rotation . PreConcat ( transform . ToSKMatrix ( ) ) ;
1024
- }
1025
+ var transformOrigin = conicGradient . TransformOrigin . ToPixels ( targetRect ) ;
1026
+ var offset = Matrix . CreateTranslation ( transformOrigin ) ;
1027
+ var transform = ( - offset ) * conicGradient . Transform . Value * ( offset ) ;
1025
1028
1026
- using ( var shader =
1027
- SKShader . CreateSweepGradient ( center , stopColors , stopOffsets , rotation ) )
1028
- {
1029
- paintWrapper . Paint . Shader = shader ;
1030
- }
1029
+ rotation = rotation . PreConcat ( transform . ToSKMatrix ( ) ) ;
1030
+ }
1031
1031
1032
- break ;
1033
- }
1032
+ using ( var shader =
1033
+ SKShader . CreateSweepGradient ( center , stopColors , stopOffsets , rotation ) )
1034
+ {
1035
+ paintWrapper . Paint . Shader = shader ;
1036
+ }
1037
+
1038
+ break ;
1039
+ }
1034
1040
}
1035
1041
}
1036
1042
0 commit comments