@@ -6,7 +6,6 @@ import { LinearGradient } from './linear-gradient';
6
6
import { Color } from '../../color' ;
7
7
import { Screen } from '../../platform' ;
8
8
import { isDataURI , isFileOrResourcePath , layout } from '../../utils' ;
9
- import { extendPointsToTargetY } from '../../utils/number-utils' ;
10
9
import { ios as iosViewUtils , NativeScriptUIView } from '../utils' ;
11
10
import { ImageSource } from '../../image-source' ;
12
11
import { CSSValue , parse as cssParse } from '../../css-value' ;
@@ -301,26 +300,22 @@ export namespace ios {
301
300
302
301
export function generateNonUniformBorderInnerClipRoundedPath ( view : View , bounds : CGRect ) : any {
303
302
const background = view . style . backgroundInternal ;
304
- const nativeView = < NativeScriptUIView > view . nativeViewProtected ;
305
303
306
304
const cappedOuterRadii = calculateNonUniformBorderCappedRadii ( bounds , background ) ;
307
305
return generateNonUniformBorderInnerClipPath ( bounds , background , cappedOuterRadii ) ;
308
306
}
309
307
310
308
export function generateNonUniformBorderOuterClipRoundedPath ( view : View , bounds : CGRect ) : any {
311
309
const background = view . style . backgroundInternal ;
312
- const nativeView = < NativeScriptUIView > view . nativeViewProtected ;
313
310
314
311
const cappedOuterRadii = calculateNonUniformBorderCappedRadii ( bounds , background ) ;
315
312
return generateNonUniformBorderOuterClipPath ( bounds , cappedOuterRadii ) ;
316
313
}
317
314
318
315
export function generateNonUniformMultiColorBorderRoundedPaths ( view : View , bounds : CGRect ) : Array < any > {
319
316
const background = view . style . backgroundInternal ;
320
- const nativeView = < NativeScriptUIView > view . nativeViewProtected ;
321
317
322
- const cappedOuterRadii = calculateNonUniformBorderCappedRadii ( bounds , background ) ;
323
- return generateNonUniformMultiColorBorderPaths ( bounds , background , cappedOuterRadii ) ;
318
+ return generateNonUniformMultiColorBorderPaths ( bounds , background ) ;
324
319
}
325
320
}
326
321
@@ -779,7 +774,7 @@ function drawNonUniformBorders(nativeView: NativeScriptUIView, background: Backg
779
774
borderLeftLayer = nativeView . borderLayer . sublayers [ 3 ] ;
780
775
}
781
776
782
- const paths = generateNonUniformMultiColorBorderPaths ( layerBounds , background , cappedOuterRadii ) ;
777
+ const paths = generateNonUniformMultiColorBorderPaths ( layerBounds , background ) ;
783
778
784
779
borderTopLayer . fillColor = background . borderTopColor ?. ios ?. CGColor || UIColor . blackColor . CGColor ;
785
780
borderTopLayer . path = paths [ 0 ] ;
@@ -918,16 +913,55 @@ function generateNonUniformBorderInnerClipPath(bounds: CGRect, background: Backg
918
913
}
919
914
920
915
/**
921
- * Generates paths for visualizing borders with different color per side.
922
- * This is achieved by extending all borders enough to consume entire view size and
923
- * use an inner path along with even-odd fill rule to render borders according to their corresponding width.
916
+ * Calculates the needed widths for creating triangular shapes for each border.
917
+ * To achieve this, all border widths are scaled according to view bounds.
924
918
*
925
919
* @param bounds
926
920
* @param background
927
- * @param cappedOuterRadii
928
921
* @returns
929
922
*/
930
- function generateNonUniformMultiColorBorderPaths ( bounds : CGRect , background : BackgroundDefinition , cappedOuterRadii : CappedOuterRadii ) : Array < any > {
923
+ function getBorderTriangleWidths ( bounds : CGRect , background : BackgroundDefinition ) : Position {
924
+ const width : number = bounds . origin . x + bounds . size . width ;
925
+ const height : number = bounds . origin . y + bounds . size . height ;
926
+
927
+ const borderTopWidth : number = Math . max ( 0 , layout . toDeviceIndependentPixels ( background . borderTopWidth ) ) ;
928
+ const borderRightWidth : number = Math . max ( 0 , layout . toDeviceIndependentPixels ( background . borderRightWidth ) ) ;
929
+ const borderBottomWidth : number = Math . max ( 0 , layout . toDeviceIndependentPixels ( background . borderBottomWidth ) ) ;
930
+ const borderLeftWidth : number = Math . max ( 0 , layout . toDeviceIndependentPixels ( background . borderLeftWidth ) ) ;
931
+
932
+ const verticalBorderWidth : number = borderTopWidth + borderBottomWidth ;
933
+ const horizontalBorderWidth : number = borderLeftWidth + borderRightWidth ;
934
+
935
+ let verticalBorderMultiplier = verticalBorderWidth > 0 ? height / verticalBorderWidth : 0 ;
936
+ let horizontalBorderMultiplier = horizontalBorderWidth > 0 ? width / horizontalBorderWidth : 0 ;
937
+
938
+ // Both directions should consider each other in order to scale widths properly, as a view might have different width and height
939
+ if ( verticalBorderMultiplier > 0 && verticalBorderMultiplier < horizontalBorderMultiplier ) {
940
+ horizontalBorderMultiplier -= horizontalBorderMultiplier - verticalBorderMultiplier ;
941
+ }
942
+
943
+ if ( horizontalBorderMultiplier > 0 && horizontalBorderMultiplier < verticalBorderMultiplier ) {
944
+ verticalBorderMultiplier -= verticalBorderMultiplier - horizontalBorderMultiplier ;
945
+ }
946
+
947
+ return {
948
+ top : borderTopWidth * verticalBorderMultiplier ,
949
+ right : borderRightWidth * horizontalBorderMultiplier ,
950
+ bottom : borderBottomWidth * verticalBorderMultiplier ,
951
+ left : borderLeftWidth * horizontalBorderMultiplier ,
952
+ } ;
953
+ }
954
+
955
+ /**
956
+ * Generates paths for visualizing borders with different colors per side.
957
+ * This is achieved by extending all borders enough to consume entire view size,
958
+ * then using an even-odd inner mask to clip and eventually render borders according to their corresponding width.
959
+ *
960
+ * @param bounds
961
+ * @param background
962
+ * @returns
963
+ */
964
+ function generateNonUniformMultiColorBorderPaths ( bounds : CGRect , background : BackgroundDefinition ) : Array < any > {
931
965
const { width, height } = bounds . size ;
932
966
const { x, y } = bounds . origin ;
933
967
@@ -938,139 +972,97 @@ function generateNonUniformMultiColorBorderPaths(bounds: CGRect, background: Bac
938
972
right : x + width ,
939
973
} ;
940
974
941
- const topWidth : number = layout . toDeviceIndependentPixels ( background . borderTopWidth ) ;
942
- const rightWidth : number = layout . toDeviceIndependentPixels ( background . borderRightWidth ) ;
943
- const bottomWidth : number = layout . toDeviceIndependentPixels ( background . borderBottomWidth ) ;
944
- const leftWidth : number = layout . toDeviceIndependentPixels ( background . borderLeftWidth ) ;
945
-
946
- // These values have 1 as fallback in order to handler borders with zero values
947
- const safeTopWidth : number = Math . max ( topWidth , 1 ) ;
948
- const safeRightWidth : number = Math . max ( rightWidth , 1 ) ;
949
- const safeBottomWidth : number = Math . max ( bottomWidth , 1 ) ;
950
- const safeLeftWidth : number = Math . max ( leftWidth , 1 ) ;
951
-
975
+ const borderWidths : Position = getBorderTriangleWidths ( bounds , background ) ;
952
976
const paths = new Array ( 4 ) ;
953
977
954
978
const lto : Point = {
955
979
x : position . left ,
956
980
y : position . top ,
957
981
} ; // left-top-outside
958
982
const lti : Point = {
959
- x : position . left + safeLeftWidth ,
960
- y : position . top + safeTopWidth ,
983
+ x : position . left + borderWidths . left ,
984
+ y : position . top + borderWidths . top ,
961
985
} ; // left-top-inside
962
986
963
987
const rto : Point = {
964
988
x : position . right ,
965
989
y : position . top ,
966
990
} ; // right-top-outside
967
991
const rti : Point = {
968
- x : position . right - safeRightWidth ,
969
- y : position . top + safeTopWidth ,
992
+ x : position . right - borderWidths . right ,
993
+ y : position . top + borderWidths . top ,
970
994
} ; // right-top-inside
971
995
972
996
const rbo : Point = {
973
997
x : position . right ,
974
998
y : position . bottom ,
975
999
} ; // right-bottom-outside
976
1000
const rbi : Point = {
977
- x : position . right - safeRightWidth ,
978
- y : position . bottom - safeBottomWidth ,
1001
+ x : position . right - borderWidths . right ,
1002
+ y : position . bottom - borderWidths . bottom ,
979
1003
} ; // right-bottom-inside
980
1004
981
1005
const lbo : Point = {
982
1006
x : position . left ,
983
1007
y : position . bottom ,
984
1008
} ; // left-bottom-outside
985
1009
const lbi : Point = {
986
- x : position . left + safeLeftWidth ,
987
- y : position . bottom - safeBottomWidth ,
1010
+ x : position . left + borderWidths . left ,
1011
+ y : position . bottom - borderWidths . bottom ,
988
1012
} ; // left-bottom-inside
989
1013
990
- const centerX : number = position . right / 2 ;
991
- const centerY : number = position . bottom / 2 ;
992
-
993
- // These values help calculate the size that each border shape should consume
994
- const averageHorizontalBorderWidth : number = Math . max ( ( leftWidth + rightWidth ) / 2 , 1 ) ;
995
- const averageVerticalBorderWidth : number = Math . max ( ( topWidth + bottomWidth ) / 2 , 1 ) ;
996
- const viewRatioMultiplier : number = width > 0 && height > 0 ? width / height : 1 ;
997
-
998
1014
const borderTopColor = background . borderTopColor ;
999
1015
const borderRightColor = background . borderRightColor ;
1000
1016
const borderBottomColor = background . borderBottomColor ;
1001
1017
const borderLeftColor = background . borderLeftColor ;
1002
1018
1003
- let borderTopY : number = centerY * ( safeTopWidth / averageHorizontalBorderWidth ) * viewRatioMultiplier ;
1004
- let borderRightX : number = position . right - ( centerX * ( safeRightWidth / averageVerticalBorderWidth ) ) / viewRatioMultiplier ;
1005
- let borderBottomY : number = position . bottom - centerY * ( safeBottomWidth / averageHorizontalBorderWidth ) * viewRatioMultiplier ;
1006
- let borderLeftX : number = ( centerX * ( safeLeftWidth / averageVerticalBorderWidth ) ) / viewRatioMultiplier ;
1007
-
1008
- // Adjust border triangle width in case of borders colliding between each other or borders being less than 4
1009
- const hasHorizontalIntersection : boolean = borderLeftX > borderRightX ;
1010
- const hasVerticalIntersection : boolean = borderTopY > borderBottomY ;
1011
- if ( hasVerticalIntersection ) {
1012
- borderTopY = extendPointsToTargetY ( lto . y , lto . x , lti . y , lti . x , borderLeftX ) ;
1013
- borderBottomY = extendPointsToTargetY ( lbo . y , lbo . x , lbi . y , lbi . x , borderLeftX ) ;
1014
- } else if ( hasHorizontalIntersection ) {
1015
- borderLeftX = extendPointsToTargetY ( lto . x , lto . y , lti . x , lti . y , borderTopY ) ;
1016
- borderRightX = extendPointsToTargetY ( rto . x , rto . y , rti . x , rti . y , borderTopY ) ;
1017
- }
1018
-
1019
- if ( topWidth > 0 && borderTopColor ?. ios ) {
1019
+ if ( borderWidths . top > 0 && borderTopColor ?. ios ) {
1020
1020
const topBorderPath = CGPathCreateMutable ( ) ;
1021
- const borderTopLeftX : number = extendPointsToTargetY ( lto . x , lto . y , lti . x , lti . y , borderTopY ) ;
1022
- const borderTopRightX : number = extendPointsToTargetY ( rto . x , rto . y , rti . x , rti . y , borderTopY ) ;
1023
1021
1024
1022
CGPathMoveToPoint ( topBorderPath , null , lto . x , lto . y ) ;
1025
1023
CGPathAddLineToPoint ( topBorderPath , null , rto . x , rto . y ) ;
1026
- CGPathAddLineToPoint ( topBorderPath , null , borderTopRightX , borderTopY ) ;
1027
- if ( borderTopRightX !== borderTopLeftX ) {
1028
- CGPathAddLineToPoint ( topBorderPath , null , borderTopLeftX , borderTopY ) ;
1024
+ CGPathAddLineToPoint ( topBorderPath , null , rti . x , rti . y ) ;
1025
+ if ( rti . x !== lti . x ) {
1026
+ CGPathAddLineToPoint ( topBorderPath , null , lti . x , lti . y ) ;
1029
1027
}
1030
1028
CGPathAddLineToPoint ( topBorderPath , null , lto . x , lto . y ) ;
1031
1029
1032
1030
paths [ 0 ] = topBorderPath ;
1033
1031
}
1034
- if ( rightWidth > 0 && borderRightColor ?. ios ) {
1032
+ if ( borderWidths . right > 0 && borderRightColor ?. ios ) {
1035
1033
const rightBorderPath = CGPathCreateMutable ( ) ;
1036
- const borderRightBottomY : number = extendPointsToTargetY ( rbo . y , rbo . x , rbi . y , rbi . x , borderRightX ) ;
1037
- const borderRightTopY : number = extendPointsToTargetY ( rto . y , rto . x , rti . y , rti . x , borderRightX ) ;
1038
1034
1039
1035
CGPathMoveToPoint ( rightBorderPath , null , rto . x , rto . y ) ;
1040
1036
CGPathAddLineToPoint ( rightBorderPath , null , rbo . x , rbo . y ) ;
1041
- CGPathAddLineToPoint ( rightBorderPath , null , borderRightX , borderRightBottomY ) ;
1042
- if ( borderRightBottomY !== borderRightTopY ) {
1043
- CGPathAddLineToPoint ( rightBorderPath , null , borderRightX , borderRightTopY ) ;
1037
+ CGPathAddLineToPoint ( rightBorderPath , null , rbi . x , rbi . y ) ;
1038
+ if ( rbi . y !== rti . y ) {
1039
+ CGPathAddLineToPoint ( rightBorderPath , null , rti . x , rti . y ) ;
1044
1040
}
1045
1041
CGPathAddLineToPoint ( rightBorderPath , null , rto . x , rto . y ) ;
1046
1042
1047
1043
paths [ 1 ] = rightBorderPath ;
1048
1044
}
1049
- if ( bottomWidth > 0 && borderBottomColor ?. ios ) {
1045
+ if ( borderWidths . bottom > 0 && borderBottomColor ?. ios ) {
1050
1046
const bottomBorderPath = CGPathCreateMutable ( ) ;
1051
- const borderBottomLeftX : number = extendPointsToTargetY ( lbo . x , lbo . y , lbi . x , lbi . y , borderBottomY ) ;
1052
- const borderBottomRightX : number = extendPointsToTargetY ( rbo . x , rbo . y , rbi . x , rbi . y , borderBottomY ) ;
1053
1047
1054
1048
CGPathMoveToPoint ( bottomBorderPath , null , rbo . x , rbo . y ) ;
1055
1049
CGPathAddLineToPoint ( bottomBorderPath , null , lbo . x , lbo . y ) ;
1056
- CGPathAddLineToPoint ( bottomBorderPath , null , borderBottomLeftX , borderBottomY ) ;
1057
- if ( borderBottomLeftX !== borderBottomRightX ) {
1058
- CGPathAddLineToPoint ( bottomBorderPath , null , borderBottomRightX , borderBottomY ) ;
1050
+ CGPathAddLineToPoint ( bottomBorderPath , null , lbi . x , lbi . y ) ;
1051
+ if ( lbi . x !== rbi . x ) {
1052
+ CGPathAddLineToPoint ( bottomBorderPath , null , rbi . x , rbi . y ) ;
1059
1053
}
1060
1054
CGPathAddLineToPoint ( bottomBorderPath , null , rbo . x , rbo . y ) ;
1061
1055
1062
1056
paths [ 2 ] = bottomBorderPath ;
1063
1057
}
1064
- if ( leftWidth > 0 && borderLeftColor ?. ios ) {
1058
+ if ( borderWidths . left > 0 && borderLeftColor ?. ios ) {
1065
1059
const leftBorderPath = CGPathCreateMutable ( ) ;
1066
- const borderLeftTopY : number = extendPointsToTargetY ( lto . y , lto . x , lti . y , lti . x , borderLeftX ) ;
1067
- const borderLeftBottomY : number = extendPointsToTargetY ( lbo . y , lbo . x , lbi . y , lbi . x , borderLeftX ) ;
1068
1060
1069
1061
CGPathMoveToPoint ( leftBorderPath , null , lbo . x , lbo . y ) ;
1070
1062
CGPathAddLineToPoint ( leftBorderPath , null , lto . x , lto . y ) ;
1071
- CGPathAddLineToPoint ( leftBorderPath , null , borderLeftX , borderLeftTopY ) ;
1072
- if ( borderLeftTopY !== borderLeftBottomY ) {
1073
- CGPathAddLineToPoint ( leftBorderPath , null , borderLeftX , borderLeftBottomY ) ;
1063
+ CGPathAddLineToPoint ( leftBorderPath , null , lti . x , lti . y ) ;
1064
+ if ( lti . y !== lbi . y ) {
1065
+ CGPathAddLineToPoint ( leftBorderPath , null , lbi . x , lbi . y ) ;
1074
1066
}
1075
1067
CGPathAddLineToPoint ( leftBorderPath , null , lbo . x , lbo . y ) ;
1076
1068
0 commit comments