@@ -9,7 +9,7 @@ use std::{
99 cmp:: min,
1010 panic:: { self , AssertUnwindSafe }
1111} ;
12- use cairo:: { ImageSurface , Format , Context , Surface , Rectangle , FontFace } ;
12+ use cairo:: { ImageSurface , Format , Context , Surface , Rectangle , FontFace , Antialias } ;
1313use rsvg:: { Loader , CairoRenderer , SvgHandle } ;
1414use drm:: control:: ClipRect ;
1515use anyhow:: { Error , Result } ;
@@ -70,7 +70,8 @@ struct ConfigProxy {
7070#[ derive( Deserialize ) ]
7171#[ serde( rename_all = "PascalCase" ) ]
7272struct ButtonConfig {
73- svg : Option < String > ,
73+ #[ serde( alias = "Svg" ) ]
74+ icon : Option < String > ,
7475 text : Option < String > ,
7576 action : Key
7677}
@@ -83,7 +84,8 @@ struct Config {
8384
8485enum ButtonImage {
8586 Text ( String ) ,
86- Svg ( SvgHandle )
87+ Svg ( SvgHandle ) ,
88+ Bitmap ( ImageSurface )
8789}
8890
8991struct Button {
@@ -93,14 +95,38 @@ struct Button {
9395 action : Key
9496}
9597
98+ fn try_load_svg ( path : & str ) -> Result < ButtonImage > {
99+ let handle = Loader :: new ( ) . read_path ( format ! ( "/etc/tiny-dfr/{}.svg" , path) ) . or_else ( |_| {
100+ Loader :: new ( ) . read_path ( format ! ( "/usr/share/tiny-dfr/{}.svg" , path) )
101+ } ) ?;
102+ Ok ( ButtonImage :: Svg ( handle) )
103+ }
104+
105+ fn try_load_png ( path : & str ) -> Result < ButtonImage > {
106+ let mut file = File :: open ( format ! ( "/etc/tiny-dfr/{}.png" , path) ) . or_else ( |_| {
107+ File :: open ( format ! ( "/usr/share/tiny-dfr/{}.png" , path) )
108+ } ) ?;
109+ let surf = ImageSurface :: create_from_png ( & mut file) ?;
110+ if surf. height ( ) == ICON_SIZE && surf. width ( ) == ICON_SIZE {
111+ return Ok ( ButtonImage :: Bitmap ( surf) ) ;
112+ }
113+ let resized = ImageSurface :: create ( Format :: ARgb32 , ICON_SIZE , ICON_SIZE ) . unwrap ( ) ;
114+ let c = Context :: new ( & resized) . unwrap ( ) ;
115+ c. scale ( ICON_SIZE as f64 / surf. width ( ) as f64 , ICON_SIZE as f64 / surf. height ( ) as f64 ) ;
116+ c. set_source_surface ( surf, 0.0 , 0.0 ) . unwrap ( ) ;
117+ c. set_antialias ( Antialias :: Best ) ;
118+ c. paint ( ) . unwrap ( ) ;
119+ return Ok ( ButtonImage :: Bitmap ( resized) ) ;
120+ }
121+
96122impl Button {
97123 fn with_config ( cfg : ButtonConfig ) -> Button {
98124 if let Some ( text) = cfg. text {
99125 Button :: new_text ( text, cfg. action )
100- } else if let Some ( svg ) = cfg. svg {
101- Button :: new_svg ( & svg , cfg. action )
126+ } else if let Some ( icon ) = cfg. icon {
127+ Button :: new_icon ( & icon , cfg. action )
102128 } else {
103- panic ! ( "Invalid config, a button must have either Text or Svg " )
129+ panic ! ( "Invalid config, a button must have either Text or Icon " )
104130 }
105131 }
106132 fn new_text ( text : String , action : Key ) -> Button {
@@ -111,15 +137,12 @@ impl Button {
111137 image : ButtonImage :: Text ( text)
112138 }
113139 }
114- fn new_svg ( path : & str , action : Key ) -> Button {
115- let svg = Loader :: new ( ) . read_path ( format ! ( "/etc/tiny-dfr/{}.svg" , path) ) . or_else ( |_| {
116- Loader :: new ( ) . read_path ( format ! ( "/usr/share/tiny-dfr/{}.svg" , path) )
117- } ) . unwrap ( ) ;
140+ fn new_icon ( path : & str , action : Key ) -> Button {
141+ let image = try_load_svg ( path) . or_else ( |_| try_load_png ( path) ) . unwrap ( ) ;
118142 Button {
119- action,
143+ action, image ,
120144 active : false ,
121145 changed : false ,
122- image : ButtonImage :: Svg ( svg)
123146 }
124147 }
125148 fn render ( & self , c : & Context , button_left_edge : f64 , button_width : u64 , y_shift : f64 ) {
@@ -141,6 +164,13 @@ impl Button {
141164 & Rectangle :: new ( x, y, ICON_SIZE as f64 , ICON_SIZE as f64 )
142165 ) . unwrap ( ) ;
143166 }
167+ ButtonImage :: Bitmap ( surf) => {
168+ let x = button_left_edge + ( button_width as f64 / 2.0 - ( ICON_SIZE / 2 ) as f64 ) . round ( ) ;
169+ let y = y_shift + ( ( DFR_HEIGHT as f64 - ICON_SIZE as f64 ) / 2.0 ) . round ( ) ;
170+ c. set_source_surface ( surf, x, y) . unwrap ( ) ;
171+ c. rectangle ( x, y, ICON_SIZE as f64 , ICON_SIZE as f64 ) ;
172+ c. fill ( ) . unwrap ( ) ;
173+ }
144174 }
145175 }
146176 fn set_active < F > ( & mut self , uinput : & mut UInputHandle < F > , active : bool ) where F : AsRawFd {
0 commit comments