2
2
#![ allow( unused_imports) ]
3
3
#![ allow( unused_variables) ]
4
4
#![ allow( dead_code) ]
5
- use skia_safe:: { FilterMode , MipmapMode , SamplingOptions , CubicResampler } ;
6
- use skia_safe :: { Paint , Matrix , Point , Color , TileMode , MaskFilter , BlurStyle ,
5
+ use skia_safe:: { Paint , Matrix , Point , Color , MaskFilter , ImageFilter as SkImageFilter ,
6
+ BlurStyle , FilterMode , MipmapMode , SamplingOptions , TileMode ,
7
7
image_filters, color_filters, table_color_filter} ;
8
8
9
9
use crate :: utils:: * ;
@@ -17,139 +17,175 @@ pub enum FilterSpec{
17
17
#[ derive( Clone , Debug ) ]
18
18
pub struct Filter {
19
19
pub css : String ,
20
- specs : Vec < FilterSpec >
20
+ specs : Vec < FilterSpec > ,
21
+ _raster : Option < LastFilter > ,
22
+ _vector : Option < LastFilter >
23
+ }
24
+
25
+ #[ derive( Clone , Debug ) ]
26
+ pub struct LastFilter {
27
+ matrix : Matrix ,
28
+ mask : Option < MaskFilter > ,
29
+ image : Option < SkImageFilter >
30
+ }
31
+
32
+ impl LastFilter {
33
+ fn match_scale ( & self , matrix : Matrix ) -> Option < Self > {
34
+ if self . matrix . scale_x ( ) == matrix. scale_x ( ) && self . matrix . scale_y ( ) == matrix. scale_y ( ) {
35
+ Some ( self . clone ( ) )
36
+ } else {
37
+ None
38
+ }
39
+ }
21
40
}
22
41
23
42
impl Default for Filter {
24
43
fn default ( ) -> Self {
25
- Filter { css : "none" . to_string ( ) , specs : vec ! [ ] }
44
+ Filter { css : "none" . to_string ( ) , specs : vec ! [ ] , _raster : None , _vector : None }
26
45
}
27
46
}
28
47
29
48
impl Filter {
30
49
pub fn new ( css : & str , specs : & [ FilterSpec ] ) -> Self {
31
50
let css = css. to_string ( ) ;
32
51
let specs = specs. to_vec ( ) ;
33
- Filter { css, specs }
52
+ Filter { css, specs, _raster : None , _vector : None }
34
53
}
35
54
36
55
pub fn to_string ( & self ) -> String {
37
56
self . css . clone ( )
38
57
}
39
58
40
- pub fn mix_into < ' a > ( & self , paint : & ' a mut Paint , matrix : Matrix , raster : bool ) -> & ' a mut Paint {
41
- let image_filter = self . specs . iter ( ) . fold ( None , |chain, next_filter|
42
- match next_filter {
43
- FilterSpec :: Shadow { offset, blur, color } => {
44
- let scale = Point { x : matrix. scale_x ( ) , y : matrix. scale_y ( ) } ;
45
- let point = ( offset. x / scale. x , offset. y / scale. y ) ;
46
- let sigma = ( blur / scale. x , blur / scale. y ) ;
47
- image_filters:: drop_shadow ( point, sigma, * color, chain, None )
48
- } ,
49
- FilterSpec :: Plain { name, value } => match name. as_ref ( ) {
50
- "blur" => {
51
- if raster {
52
- let sigma_x = value / ( 2.0 * matrix. scale_x ( ) ) ;
53
- let sigma_y = value / ( 2.0 * matrix. scale_y ( ) ) ;
54
- image_filters:: blur ( ( sigma_x, sigma_y) , TileMode :: Decal , chain, None )
55
- } else {
56
- paint. set_mask_filter ( MaskFilter :: blur ( BlurStyle :: Normal , * value, false ) ) ;
57
- chain
58
- }
59
- } ,
59
+ pub fn mix_into < ' a > ( & mut self , paint : & ' a mut Paint , matrix : Matrix , raster : bool ) -> & ' a mut Paint {
60
+ let filters = self . filters_for ( matrix, raster) ;
61
+ paint. set_image_filter ( filters. image )
62
+ . set_mask_filter ( filters. mask )
63
+ }
60
64
61
- //
62
- // matrices and formulæ taken from: https://www.w3.org/TR/filter-effects-1/
63
- //
64
- "brightness" => {
65
- let amt = value. max ( 0.0 ) ;
66
- let color_matrix = color_filters:: matrix_row_major ( & [
67
- amt, 0.0 , 0.0 , 0.0 , 0.0 ,
68
- 0.0 , amt, 0.0 , 0.0 , 0.0 ,
69
- 0.0 , 0.0 , amt, 0.0 , 0.0 ,
70
- 0.0 , 0.0 , 0.0 , 1.0 , 0.0
71
- ] ) ;
72
- image_filters:: color_filter ( color_matrix, chain, None )
73
- } ,
74
- "contrast" => {
75
- let amt = value. max ( 0.0 ) ;
76
- let mut ramp = [ 0u8 ; 256 ] ;
77
- for ( i, val) in ramp. iter_mut ( ) . take ( 256 ) . enumerate ( ) {
78
- let orig = i as f32 ;
79
- * val = ( 127.0 + amt * orig - ( 127.0 * amt ) ) as u8 ;
80
- }
81
- let table = Some ( & ramp) ;
82
- let color_table = table_color_filter:: from_argb ( None , table, table, table) ;
83
- image_filters:: color_filter ( color_table, chain, None )
84
- } ,
85
- "grayscale" => {
86
- let amt = 1.0 - value. max ( 0.0 ) . min ( 1.0 ) ;
87
- let color_matrix = color_filters:: matrix_row_major ( & [
88
- ( 0.2126 + 0.7874 * amt) , ( 0.7152 - 0.7152 * amt) , ( 0.0722 - 0.0722 * amt) , 0.0 , 0.0 ,
89
- ( 0.2126 - 0.2126 * amt) , ( 0.7152 + 0.2848 * amt) , ( 0.0722 - 0.0722 * amt) , 0.0 , 0.0 ,
90
- ( 0.2126 - 0.2126 * amt) , ( 0.7152 - 0.7152 * amt) , ( 0.0722 + 0.9278 * amt) , 0.0 , 0.0 ,
91
- 0.0 , 0.0 , 0.0 , 1.0 , 0.0
92
- ] ) ;
93
- image_filters:: color_filter ( color_matrix, chain, None )
94
- } ,
95
- "invert" => {
96
- let amt = value. max ( 0.0 ) . min ( 1.0 ) ;
97
- let mut ramp = [ 0u8 ; 256 ] ;
98
- for ( i, val) in ramp. iter_mut ( ) . take ( 256 ) . enumerate ( ) . map ( |( i, v) | ( i as f32 , v) ) {
99
- let ( orig, inv) = ( i, 255.0 -i) ;
100
- * val = ( orig * ( 1.0 - amt) + inv * amt) as u8 ;
101
- }
102
- let table = Some ( & ramp) ;
103
- let color_table = table_color_filter:: from_argb ( None , table, table, table) ;
104
- image_filters:: color_filter ( color_table, chain, None )
105
- } ,
106
- "opacity" => {
107
- let amt = value. max ( 0.0 ) . min ( 1.0 ) ;
108
- let color_matrix = color_filters:: matrix_row_major ( & [
109
- 1.0 , 0.0 , 0.0 , 0.0 , 0.0 ,
110
- 0.0 , 1.0 , 0.0 , 0.0 , 0.0 ,
111
- 0.0 , 0.0 , 1.0 , 0.0 , 0.0 ,
112
- 0.0 , 0.0 , 0.0 , amt, 0.0
113
- ] ) ;
114
- image_filters:: color_filter ( color_matrix, chain, None )
115
- } ,
116
- "saturate" => {
117
- let amt = value. max ( 0.0 ) ;
118
- let color_matrix = color_filters:: matrix_row_major ( & [
119
- ( 0.2126 + 0.7874 * amt) , ( 0.7152 - 0.7152 * amt) , ( 0.0722 - 0.0722 * amt) , 0.0 , 0.0 ,
120
- ( 0.2126 - 0.2126 * amt) , ( 0.7152 + 0.2848 * amt) , ( 0.0722 - 0.0722 * amt) , 0.0 , 0.0 ,
121
- ( 0.2126 - 0.2126 * amt) , ( 0.7152 - 0.7152 * amt) , ( 0.0722 + 0.9278 * amt) , 0.0 , 0.0 ,
122
- 0.0 , 0.0 , 0.0 , 1.0 , 0.0
123
- ] ) ;
124
- image_filters:: color_filter ( color_matrix, chain, None )
125
- } ,
126
- "sepia" => {
127
- let amt = 1.0 - value. max ( 0.0 ) . min ( 1.0 ) ;
128
- let color_matrix = color_filters:: matrix_row_major ( & [
129
- ( 0.393 + 0.607 * amt) , ( 0.769 - 0.769 * amt) , ( 0.189 - 0.189 * amt) , 0.0 , 0.0 ,
130
- ( 0.349 - 0.349 * amt) , ( 0.686 + 0.314 * amt) , ( 0.168 - 0.168 * amt) , 0.0 , 0.0 ,
131
- ( 0.272 - 0.272 * amt) , ( 0.534 - 0.534 * amt) , ( 0.131 + 0.869 * amt) , 0.0 , 0.0 ,
132
- 0.0 , 0.0 , 0.0 , 1.0 , 0.0
133
- ] ) ;
134
- image_filters:: color_filter ( color_matrix, chain, None )
135
- } ,
136
- "hue-rotate" => {
137
- let cos = to_radians ( * value) . cos ( ) ;
138
- let sin = to_radians ( * value) . sin ( ) ;
139
- let color_matrix = color_filters:: matrix_row_major ( & [
140
- ( 0.213 + cos* 0.787 - sin* 0.213 ) , ( 0.715 - cos* 0.715 - sin* 0.715 ) , ( 0.072 - cos* 0.072 + sin* 0.928 ) , 0.0 , 0.0 ,
141
- ( 0.213 - cos* 0.213 + sin* 0.143 ) , ( 0.715 + cos* 0.285 + sin* 0.140 ) , ( 0.072 - cos* 0.072 - sin* 0.283 ) , 0.0 , 0.0 ,
142
- ( 0.213 - cos* 0.213 - sin* 0.787 ) , ( 0.715 - cos* 0.715 + sin* 0.715 ) , ( 0.072 + cos* 0.928 + sin* 0.072 ) , 0.0 , 0.0 ,
143
- 0.0 , 0.0 , 0.0 , 1.0 , 0.0
144
- ] ) ;
145
- image_filters:: color_filter ( color_matrix, chain, None )
65
+ fn filters_for ( & mut self , matrix : Matrix , raster : bool ) -> LastFilter {
66
+ let cached = match ( raster, & self . _raster , & self . _vector ) {
67
+ ( true , Some ( cached) , _) | ( false , _, Some ( cached) ) => cached. match_scale ( matrix) ,
68
+ _ => None
69
+ } ;
70
+
71
+ cached. or_else ( || {
72
+ let mut mask_filter = None ;
73
+ let image_filter = self . specs . iter ( ) . fold ( None , |chain, next_filter|
74
+ match next_filter {
75
+ FilterSpec :: Shadow { offset, blur, color } => {
76
+ let scale = Point { x : matrix. scale_x ( ) , y : matrix. scale_y ( ) } ;
77
+ let point = ( offset. x / scale. x , offset. y / scale. y ) ;
78
+ let sigma = ( blur / scale. x , blur / scale. y ) ;
79
+ image_filters:: drop_shadow ( point, sigma, * color, chain, None )
146
80
} ,
147
- _ => chain
81
+ FilterSpec :: Plain { name, value } => match name. as_ref ( ) {
82
+ "blur" => {
83
+ if raster {
84
+ let sigma_x = value / ( 2.0 * matrix. scale_x ( ) ) ;
85
+ let sigma_y = value / ( 2.0 * matrix. scale_y ( ) ) ;
86
+ image_filters:: blur ( ( sigma_x, sigma_y) , TileMode :: Decal , chain, None )
87
+ } else {
88
+ mask_filter = MaskFilter :: blur ( BlurStyle :: Normal , * value, false ) ;
89
+ chain
90
+ }
91
+ } ,
92
+
93
+ //
94
+ // matrices and formulæ taken from: https://www.w3.org/TR/filter-effects-1/
95
+ //
96
+ "brightness" => {
97
+ let amt = value. max ( 0.0 ) ;
98
+ let color_matrix = color_filters:: matrix_row_major ( & [
99
+ amt, 0.0 , 0.0 , 0.0 , 0.0 ,
100
+ 0.0 , amt, 0.0 , 0.0 , 0.0 ,
101
+ 0.0 , 0.0 , amt, 0.0 , 0.0 ,
102
+ 0.0 , 0.0 , 0.0 , 1.0 , 0.0
103
+ ] ) ;
104
+ image_filters:: color_filter ( color_matrix, chain, None )
105
+ } ,
106
+ "contrast" => {
107
+ let amt = value. max ( 0.0 ) ;
108
+ let mut ramp = [ 0u8 ; 256 ] ;
109
+ for ( i, val) in ramp. iter_mut ( ) . take ( 256 ) . enumerate ( ) {
110
+ let orig = i as f32 ;
111
+ * val = ( 127.0 + amt * orig - ( 127.0 * amt ) ) as u8 ;
112
+ }
113
+ let table = Some ( & ramp) ;
114
+ let color_table = table_color_filter:: from_argb ( None , table, table, table) ;
115
+ image_filters:: color_filter ( color_table, chain, None )
116
+ } ,
117
+ "grayscale" => {
118
+ let amt = 1.0 - value. max ( 0.0 ) . min ( 1.0 ) ;
119
+ let color_matrix = color_filters:: matrix_row_major ( & [
120
+ ( 0.2126 + 0.7874 * amt) , ( 0.7152 - 0.7152 * amt) , ( 0.0722 - 0.0722 * amt) , 0.0 , 0.0 ,
121
+ ( 0.2126 - 0.2126 * amt) , ( 0.7152 + 0.2848 * amt) , ( 0.0722 - 0.0722 * amt) , 0.0 , 0.0 ,
122
+ ( 0.2126 - 0.2126 * amt) , ( 0.7152 - 0.7152 * amt) , ( 0.0722 + 0.9278 * amt) , 0.0 , 0.0 ,
123
+ 0.0 , 0.0 , 0.0 , 1.0 , 0.0
124
+ ] ) ;
125
+ image_filters:: color_filter ( color_matrix, chain, None )
126
+ } ,
127
+ "invert" => {
128
+ let amt = value. max ( 0.0 ) . min ( 1.0 ) ;
129
+ let mut ramp = [ 0u8 ; 256 ] ;
130
+ for ( i, val) in ramp. iter_mut ( ) . take ( 256 ) . enumerate ( ) . map ( |( i, v) | ( i as f32 , v) ) {
131
+ let ( orig, inv) = ( i, 255.0 -i) ;
132
+ * val = ( orig * ( 1.0 - amt) + inv * amt) as u8 ;
133
+ }
134
+ let table = Some ( & ramp) ;
135
+ let color_table = table_color_filter:: from_argb ( None , table, table, table) ;
136
+ image_filters:: color_filter ( color_table, chain, None )
137
+ } ,
138
+ "opacity" => {
139
+ let amt = value. max ( 0.0 ) . min ( 1.0 ) ;
140
+ let color_matrix = color_filters:: matrix_row_major ( & [
141
+ 1.0 , 0.0 , 0.0 , 0.0 , 0.0 ,
142
+ 0.0 , 1.0 , 0.0 , 0.0 , 0.0 ,
143
+ 0.0 , 0.0 , 1.0 , 0.0 , 0.0 ,
144
+ 0.0 , 0.0 , 0.0 , amt, 0.0
145
+ ] ) ;
146
+ image_filters:: color_filter ( color_matrix, chain, None )
147
+ } ,
148
+ "saturate" => {
149
+ let amt = value. max ( 0.0 ) ;
150
+ let color_matrix = color_filters:: matrix_row_major ( & [
151
+ ( 0.2126 + 0.7874 * amt) , ( 0.7152 - 0.7152 * amt) , ( 0.0722 - 0.0722 * amt) , 0.0 , 0.0 ,
152
+ ( 0.2126 - 0.2126 * amt) , ( 0.7152 + 0.2848 * amt) , ( 0.0722 - 0.0722 * amt) , 0.0 , 0.0 ,
153
+ ( 0.2126 - 0.2126 * amt) , ( 0.7152 - 0.7152 * amt) , ( 0.0722 + 0.9278 * amt) , 0.0 , 0.0 ,
154
+ 0.0 , 0.0 , 0.0 , 1.0 , 0.0
155
+ ] ) ;
156
+ image_filters:: color_filter ( color_matrix, chain, None )
157
+ } ,
158
+ "sepia" => {
159
+ let amt = 1.0 - value. max ( 0.0 ) . min ( 1.0 ) ;
160
+ let color_matrix = color_filters:: matrix_row_major ( & [
161
+ ( 0.393 + 0.607 * amt) , ( 0.769 - 0.769 * amt) , ( 0.189 - 0.189 * amt) , 0.0 , 0.0 ,
162
+ ( 0.349 - 0.349 * amt) , ( 0.686 + 0.314 * amt) , ( 0.168 - 0.168 * amt) , 0.0 , 0.0 ,
163
+ ( 0.272 - 0.272 * amt) , ( 0.534 - 0.534 * amt) , ( 0.131 + 0.869 * amt) , 0.0 , 0.0 ,
164
+ 0.0 , 0.0 , 0.0 , 1.0 , 0.0
165
+ ] ) ;
166
+ image_filters:: color_filter ( color_matrix, chain, None )
167
+ } ,
168
+ "hue-rotate" => {
169
+ let cos = to_radians ( * value) . cos ( ) ;
170
+ let sin = to_radians ( * value) . sin ( ) ;
171
+ let color_matrix = color_filters:: matrix_row_major ( & [
172
+ ( 0.213 + cos* 0.787 - sin* 0.213 ) , ( 0.715 - cos* 0.715 - sin* 0.715 ) , ( 0.072 - cos* 0.072 + sin* 0.928 ) , 0.0 , 0.0 ,
173
+ ( 0.213 - cos* 0.213 + sin* 0.143 ) , ( 0.715 + cos* 0.285 + sin* 0.140 ) , ( 0.072 - cos* 0.072 - sin* 0.283 ) , 0.0 , 0.0 ,
174
+ ( 0.213 - cos* 0.213 - sin* 0.787 ) , ( 0.715 - cos* 0.715 + sin* 0.715 ) , ( 0.072 + cos* 0.928 + sin* 0.072 ) , 0.0 , 0.0 ,
175
+ 0.0 , 0.0 , 0.0 , 1.0 , 0.0
176
+ ] ) ;
177
+ image_filters:: color_filter ( color_matrix, chain, None )
178
+ } ,
179
+ _ => chain
180
+ }
148
181
}
149
- }
150
- ) ;
182
+ ) ;
151
183
152
- paint. set_image_filter ( image_filter)
184
+ let filters = Some ( LastFilter { matrix : matrix, mask : mask_filter, image : image_filter} ) ;
185
+ if raster{ self . _raster = filters. clone ( ) ; }
186
+ else { self . _vector = filters. clone ( ) ; }
187
+ filters
188
+ } ) . expect ( "Could not create filter" )
153
189
}
154
190
}
155
191
0 commit comments