1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! Helper functions for the UI, mostly pixbuf functions.


use errors::*;
use gdk_pixbuf;
use gdk_pixbuf_sys;
use glib::translate::FromGlibPtrFull;
use glib::translate::ToGlibPtr;
use gtk::prelude::*;
use gtk;
use std::path::*;



/// Copy a `Pixbuf` explicitly, since they don't implement the `Copy` trait.
/// Currently does not call `gdk_pixbuf_copy_options()`.
pub fn copy_pixbuf(pixbuf: &gdk_pixbuf::Pixbuf) -> gdk_pixbuf::Pixbuf {

    let new_pixbuf = unsafe {
        let gdk_pixbuf = pixbuf.to_glib_full();
        let copy = gdk_pixbuf_sys::gdk_pixbuf_copy(gdk_pixbuf);
        FromGlibPtrFull::from_glib_full(copy)
    };

    return new_pixbuf;
}


/// Get a pixbuf by name from the given theme with the requested size.
/// Note that the size is not enforced, but rather a hint.
pub fn pixbuf_new_from_theme(icon_name: &str,
                             size: i32,
                             theme: &gtk::IconTheme)
                             -> Result<gdk_pixbuf::Pixbuf> {

    let icon_info =
        theme.lookup_icon(icon_name, size, gtk::IconLookupFlags::empty())
            .ok_or(format!("Couldn't find icon {}", icon_name))?;

    debug!("Loading stock icon {} from {:?}",
           icon_name,
           icon_info.get_filename().unwrap_or(PathBuf::new()));

    // TODO: propagate error
    let pixbuf = icon_info.load_icon().unwrap();

    return Ok(pixbuf);
}


#[macro_export]
/// Create a pixbuf from the given PNG file. Includes the file as bytes
/// in the binary and decodes it.
macro_rules! pixbuf_new_from_png {
    ($name:expr) => {
        {
            use gdk_pixbuf;
            use png;

            let bytes = include_bytes!($name);
            let pixbuf_new_from_bytes = |bytes| -> Result<gdk_pixbuf::Pixbuf> {
                let decoder = png::Decoder::new(bytes);
                let (info, mut reader) = decoder.read_info()?;
                let mut buf = vec![0; info.buffer_size()];
                reader.next_frame(&mut buf).unwrap();

                ensure!(info.color_type == png::ColorType::RGB ||
                        info.color_type == png::ColorType::RGBA,
                        "Only RGB is supported for GDKPixbuf");

                debug!("Loading icon from {}", $name);

                return Ok(gdk_pixbuf::Pixbuf::new_from_vec(buf,
                                                 gdk_pixbuf_sys::GDK_COLORSPACE_RGB,
                                                 true,
                                                 info.bit_depth as i32,
                                                 info.width as i32,
                                                 info.height as i32,
                                                 info.line_size as i32));
            };
            pixbuf_new_from_bytes(bytes as &[u8])
        }
    }
}