@@ -1083,11 +1083,15 @@ fn normalize_android_frame_orientation(
10831083 let ( width, height) = if ( width > height) == ( target. width > target. height ) {
10841084 ( width, height)
10851085 } else {
1086- rgba = rotate_rgba_clockwise ( & rgba, width, height) ;
1086+ rgba = if target. rotation_quarter_turns == 3 {
1087+ rotate_rgba_counterclockwise ( & rgba, width, height)
1088+ } else {
1089+ rotate_rgba_clockwise ( & rgba, width, height)
1090+ } ;
10871091 ( height, width)
10881092 } ;
10891093
1090- if target. rotation_quarter_turns >= 2 {
1094+ if target. width > target . height {
10911095 rotate_rgba_180_in_place ( & mut rgba, width, height) ;
10921096 }
10931097
@@ -1120,6 +1124,22 @@ fn rotate_rgba_180_in_place(rgba: &mut [u8], width: u32, height: u32) {
11201124 }
11211125}
11221126
1127+ fn rotate_rgba_counterclockwise ( rgba : & [ u8 ] , width : u32 , height : u32 ) -> Vec < u8 > {
1128+ let width = width as usize ;
1129+ let height = height as usize ;
1130+ let mut out = vec ! [ 0 ; rgba. len( ) ] ;
1131+ for y in 0 ..height {
1132+ for x in 0 ..width {
1133+ let src = ( y * width + x) * 4 ;
1134+ let dst_x = y;
1135+ let dst_y = width - 1 - x;
1136+ let dst = ( dst_y * height + dst_x) * 4 ;
1137+ out[ dst..dst + 4 ] . copy_from_slice ( & rgba[ src..src + 4 ] ) ;
1138+ }
1139+ }
1140+ out
1141+ }
1142+
11231143fn flatten_android_frame_alpha ( rgba : & mut [ u8 ] , width : u32 , height : u32 ) {
11241144 if !rgba. chunks_exact ( 4 ) . any ( |pixel| pixel[ 3 ] != 255 ) {
11251145 return ;
@@ -1942,6 +1962,34 @@ DisplayDeviceInfo{"Built-in Screen", 1080 x 2400, roundedCorners RoundedCorners{
19421962 assert_eq ! ( out, rgba) ;
19431963 }
19441964
1965+ #[ test]
1966+ fn android_frame_orientation_flips_landscape_streams ( ) {
1967+ let rgba = vec ! [
1968+ 1 , 0 , 0 , 255 , 2 , 0 , 0 , 255 , 3 , 0 , 0 , 255 , //
1969+ 4 , 0 , 0 , 255 , 5 , 0 , 0 , 255 , 6 , 0 , 0 , 255 ,
1970+ ] ;
1971+
1972+ let ( width, height, rotated) = normalize_android_frame_orientation (
1973+ 3 ,
1974+ 2 ,
1975+ rgba,
1976+ Some ( AndroidFrameTarget {
1977+ width : 3 ,
1978+ height : 2 ,
1979+ rotation_quarter_turns : 1 ,
1980+ } ) ,
1981+ ) ;
1982+
1983+ assert_eq ! ( ( width, height) , ( 3 , 2 ) ) ;
1984+ assert_eq ! (
1985+ rotated,
1986+ vec![
1987+ 6 , 0 , 0 , 255 , 5 , 0 , 0 , 255 , 4 , 0 , 0 , 255 , //
1988+ 3 , 0 , 0 , 255 , 2 , 0 , 0 , 255 , 1 , 0 , 0 , 255 ,
1989+ ]
1990+ ) ;
1991+ }
1992+
19451993 #[ test]
19461994 fn android_frame_alpha_flattens_transparent_edges_to_nearest_row_pixel ( ) {
19471995 let mut rgba = vec ! [ 0 , 0 , 0 , 0 , 10 , 20 , 30 , 255 , 40 , 50 , 60 , 255 , 0 , 0 , 0 , 0 ] ;
@@ -1964,15 +2012,15 @@ DisplayDeviceInfo{"Built-in Screen", 1080 x 2400, roundedCorners RoundedCorners{
19642012 }
19652013
19662014 #[ test]
1967- fn android_frame_orientation_rotates_reverse_orientations_180 ( ) {
2015+ fn android_frame_orientation_rotates_counterclockwise_then_flips_reverse_landscape ( ) {
19682016 let rgba = vec ! [
19692017 1 , 0 , 0 , 255 , 2 , 0 , 0 , 255 , 3 , 0 , 0 , 255 , //
19702018 4 , 0 , 0 , 255 , 5 , 0 , 0 , 255 , 6 , 0 , 0 , 255 ,
19712019 ] ;
19722020
19732021 let ( width, height, rotated) = normalize_android_frame_orientation (
1974- 3 ,
19752022 2 ,
2023+ 3 ,
19762024 rgba,
19772025 Some ( AndroidFrameTarget {
19782026 width : 3 ,
@@ -1985,8 +2033,8 @@ DisplayDeviceInfo{"Built-in Screen", 1080 x 2400, roundedCorners RoundedCorners{
19852033 assert_eq ! (
19862034 rotated,
19872035 vec![
1988- 6 , 0 , 0 , 255 , 5 , 0 , 0 , 255 , 4 , 0 , 0 , 255 , //
1989- 3 , 0 , 0 , 255 , 2 , 0 , 0 , 255 , 1 , 0 , 0 , 255 ,
2036+ 5 , 0 , 0 , 255 , 3 , 0 , 0 , 255 , 1 , 0 , 0 , 255 , //
2037+ 6 , 0 , 0 , 255 , 4 , 0 , 0 , 255 , 2 , 0 , 0 , 255 ,
19902038 ]
19912039 ) ;
19922040 }
0 commit comments