@@ -886,146 +886,164 @@ 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
- }
904
+ var transformOrigin = linearGradient . TransformOrigin . ToPixels ( targetRect ) ;
905
+ var offset = Matrix . CreateTranslation ( transformOrigin ) ;
906
+ var transform = ( - offset ) * linearGradient . Transform . Value * ( offset ) ;
914
907
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 ) ) ;
908
+ using ( var shader =
909
+ SKShader . CreateLinearGradient ( start , end , stopColors , stopOffsets , tileMode , transform . ToSKMatrix ( ) ) )
910
+ {
911
+ paintWrapper . Paint . Shader = shader ;
912
+ }
913
+ }
924
914
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 ;
915
+ break ;
942
916
}
943
-
944
- if ( originPoint . Equals ( centerPoint ) )
917
+ case IRadialGradientBrush radialGradient :
945
918
{
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
- )
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 ;
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 )
953
937
{
954
- paintWrapper . Paint . Shader = shader ;
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 ;
955
942
}
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
943
961
- 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 ( ) ;
967
-
968
- // reverse the order of the stops to match D2D
969
- var reversedColors = new SKColor [ stopColors . Length ] ;
970
- Array . Copy ( stopColors , reversedColors , stopColors . Length ) ;
971
- Array . Reverse ( reversedColors ) ;
972
-
973
- // and then reverse the reference point of the stops
974
- var reversedStops = new float [ stopOffsets . Length ] ;
975
- for ( var i = 0 ; i < stopOffsets . Length ; i ++ )
944
+ if ( originPoint . Equals ( centerPoint ) )
976
945
{
977
- reversedStops [ i ] = stopOffsets [ i ] ;
978
- if ( reversedStops [ i ] > 0 && reversedStops [ i ] < 1 )
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
+ )
979
953
{
980
- reversedStops [ i ] = Math . Abs ( 1 - stopOffsets [ i ] ) ;
954
+ paintWrapper . Paint . Shader = shader ;
981
955
}
982
956
}
983
-
984
- // compose with a background colour of the final stop to match D2D's behaviour of filling with the final color
985
- using ( var shader = SKShader . CreateCompose (
986
- SKShader . CreateColor ( reversedColors [ 0 ] ) ,
987
- transform . HasValue
988
- ? SKShader . CreateTwoPointConicalGradient ( center , ( float ) radiusX , origin , 0 ,
989
- reversedColors , reversedStops , tileMode , transform . Value . ToSKMatrix ( ) )
990
- : SKShader . CreateTwoPointConicalGradient ( center , ( float ) radiusX , origin , 0 ,
991
- reversedColors , reversedStops , tileMode )
992
-
993
- )
994
- )
957
+ else
995
958
{
996
- paintWrapper . Paint . Shader = shader ;
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
+
965
+ var origin = originPoint . ToSKPoint ( ) ;
966
+ var endOffset = 0.0 ;
967
+
968
+ // and then reverse the reference point of the stops
969
+ var reversedStops = new float [ stopOffsets . Length ] ;
970
+
971
+ for ( var i = 0 ; i < stopOffsets . Length ; i ++ )
972
+ {
973
+ var offset = stopOffsets [ i ] ;
974
+ if ( endOffset < offset )
975
+ {
976
+ endOffset = offset ;
977
+ }
978
+ reversedStops [ i ] = offset ;
979
+ if ( reversedStops [ i ] > 0 && reversedStops [ i ] < 1 )
980
+ {
981
+ reversedStops [ i ] = Math . Abs ( 1 - offset ) ;
982
+ }
983
+ }
984
+
985
+ var start = origin ;
986
+ var radiusStart = 0f ;
987
+ var end = center ;
988
+ var radiusEnd = ( float ) radiusX ;
989
+ var reverse = MathUtilities . AreClose ( 1 , endOffset ) ;
990
+
991
+ if ( reverse )
992
+ {
993
+ ( start , radiusStart , end , radiusEnd ) = ( end , radiusEnd , start , radiusStart ) ;
994
+
995
+ // reverse the order of the stops to match D2D
996
+ var reversedColors = new SKColor [ stopColors . Length ] ;
997
+ Array . Copy ( stopColors , reversedColors , stopColors . Length ) ;
998
+ Array . Reverse ( reversedColors ) ;
999
+ stopColors = reversedColors ;
1000
+ stopOffsets = reversedStops ;
1001
+ }
1002
+
1003
+ // compose with a background colour of the final stop to match D2D's behaviour of filling with the final color
1004
+ using ( var shader = SKShader . CreateCompose (
1005
+ SKShader . CreateColor ( stopColors [ 0 ] ) ,
1006
+ transform . HasValue
1007
+ ? SKShader . CreateTwoPointConicalGradient ( start , radiusStart , end , radiusEnd ,
1008
+ stopColors , stopOffsets , tileMode , transform . Value . ToSKMatrix ( ) )
1009
+ : SKShader . CreateTwoPointConicalGradient ( start , radiusStart , end , radiusEnd ,
1010
+ stopColors , stopOffsets , tileMode )
1011
+ )
1012
+ )
1013
+ {
1014
+ paintWrapper . Paint . Shader = shader ;
1015
+ }
997
1016
}
998
- }
999
1017
1000
- break ;
1001
- }
1018
+ break ;
1019
+ }
1002
1020
case IConicGradientBrush conicGradient :
1003
- {
1004
- var center = conicGradient . Center . ToPixels ( targetRect ) . ToSKPoint ( ) ;
1021
+ {
1022
+ var center = conicGradient . Center . ToPixels ( targetRect ) . ToSKPoint ( ) ;
1005
1023
1006
- // Skia's default is that angle 0 is from the right hand side of the center point
1007
- // but we are matching CSS where the vertical point above the center is 0.
1008
- var angle = ( float ) ( conicGradient . Angle - 90 ) ;
1009
- var rotation = SKMatrix . CreateRotationDegrees ( angle , center . X , center . Y ) ;
1024
+ // Skia's default is that angle 0 is from the right hand side of the center point
1025
+ // but we are matching CSS where the vertical point above the center is 0.
1026
+ var angle = ( float ) ( conicGradient . Angle - 90 ) ;
1027
+ var rotation = SKMatrix . CreateRotationDegrees ( angle , center . X , center . Y ) ;
1010
1028
1011
- if ( conicGradient . Transform is { } )
1012
- {
1013
-
1014
- var transformOrigin = conicGradient . TransformOrigin . ToPixels ( targetRect ) ;
1015
- var offset = Matrix . CreateTranslation ( transformOrigin ) ;
1016
- var transform = ( - offset ) * conicGradient . Transform . Value * ( offset ) ;
1029
+ if ( conicGradient . Transform is { } )
1030
+ {
1017
1031
1018
- rotation = rotation . PreConcat ( transform . ToSKMatrix ( ) ) ;
1019
- }
1032
+ var transformOrigin = conicGradient . TransformOrigin . ToPixels ( targetRect ) ;
1033
+ var offset = Matrix . CreateTranslation ( transformOrigin ) ;
1034
+ var transform = ( - offset ) * conicGradient . Transform . Value * ( offset ) ;
1020
1035
1021
- using ( var shader =
1022
- SKShader . CreateSweepGradient ( center , stopColors , stopOffsets , rotation ) )
1023
- {
1024
- paintWrapper . Paint . Shader = shader ;
1025
- }
1036
+ rotation = rotation . PreConcat ( transform . ToSKMatrix ( ) ) ;
1037
+ }
1026
1038
1027
- break ;
1028
- }
1039
+ using ( var shader =
1040
+ SKShader . CreateSweepGradient ( center , stopColors , stopOffsets , rotation ) )
1041
+ {
1042
+ paintWrapper . Paint . Shader = shader ;
1043
+ }
1044
+
1045
+ break ;
1046
+ }
1029
1047
}
1030
1048
}
1031
1049
0 commit comments