1
pub mod compare_surfaces;
2
pub mod reference_utils;
3

            
4
use cairo;
5
use gio;
6
use glib;
7
use std::env;
8
use std::path::PathBuf;
9
use std::sync::Once;
10

            
11
use crate::{
12
    surface_utils::shared_surface::{SharedImageSurface, SurfaceType},
13
    CairoRenderer, Loader, LoadingError, RenderingError, SvgHandle,
14
};
15

            
16
1710
pub fn load_svg(input: &'static [u8]) -> Result<SvgHandle, LoadingError> {
17
1710
    let bytes = glib::Bytes::from_static(input);
18
1710
    let stream = gio::MemoryInputStream::from_bytes(&bytes);
19
1710

            
20
1710
    Loader::new().read_stream(&stream, None::<&gio::File>, None::<&gio::Cancellable>)
21
1710
}
22

            
23
#[derive(Copy, Clone)]
24
pub struct SurfaceSize(pub i32, pub i32);
25

            
26
2000
pub fn render_document<F: FnOnce(&cairo::Context)>(
27
2000
    svg: &SvgHandle,
28
2000
    surface_size: SurfaceSize,
29
2000
    cr_transform: F,
30
2000
    viewport: cairo::Rectangle,
31
2000
) -> Result<SharedImageSurface, RenderingError> {
32
2000
    let renderer = CairoRenderer::new(svg);
33
2000

            
34
2000
    let SurfaceSize(width, height) = surface_size;
35
2000

            
36
2000
    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height).unwrap();
37

            
38
2000
    let res = {
39
2000
        let cr = cairo::Context::new(&output).expect("Failed to create a cairo context");
40
2000
        cr_transform(&cr);
41
2000
        Ok(renderer.render_document(&cr, &viewport)?)
42
    };
43

            
44
2000
    res.and_then(|_| Ok(SharedImageSurface::wrap(output, SurfaceType::SRgb)?))
45
2000
}
46

            
47
#[cfg(all(
48
    all(not(target_os = "macos"), not(target_os = "windows")),
49
    system_deps_have_fontconfig,
50
    system_deps_have_pangoft2
51
))]
52
mod pango_ft2 {
53
    use super::*;
54
    use glib::prelude::*;
55
    use glib::translate::*;
56
    use libc;
57
    use pangocairo::FontMap;
58
    use std::ffi::CString;
59

            
60
    extern "C" {
61
        // pango_fc_font_map_set_config (PangoFcFontMap *fcfontmap,
62
        //                               FcConfig       *fcconfig);
63
        // This is not bound in gtk-rs, and PangoFcFontMap is not even exposed, so we'll bind it by hand.
64
        fn pango_fc_font_map_set_config(
65
            font_map: *mut libc::c_void,
66
            config: *mut fontconfig_sys::FcConfig,
67
        );
68
    }
69

            
70
14858
    pub unsafe fn load_test_fonts() {
71
14858
        let tests_resources_path: PathBuf = [
72
14858
            env::var("CARGO_MANIFEST_DIR")
73
14858
                .expect("Manifest directory unknown")
74
14858
                .as_str(),
75
14858
            "tests",
76
14858
            "resources",
77
14858
        ]
78
14858
        .iter()
79
14858
        .collect();
80
14858

            
81
14858
        let config = fontconfig_sys::FcConfigCreate();
82
14858
        if fontconfig_sys::FcConfigSetCurrent(config) == 0 {
83
            panic!("Could not set a fontconfig configuration");
84
14858
        }
85
14858

            
86
14858
        let fonts_dot_conf_path = tests_resources_path.clone().join("fonts.conf");
87
14858
        let fonts_dot_conf_cstring = CString::new(fonts_dot_conf_path.to_str().unwrap()).unwrap();
88
14858
        if fontconfig_sys::FcConfigParseAndLoad(config, fonts_dot_conf_cstring.as_ptr().cast(), 1)
89
14858
            == 0
90
        {
91
            panic!("Could not parse fontconfig configuration from tests/resources/fonts.conf");
92
14858
        }
93
14858

            
94
14858
        let tests_resources_cstring = CString::new(tests_resources_path.to_str().unwrap()).unwrap();
95
14858
        if fontconfig_sys::FcConfigAppFontAddDir(config, tests_resources_cstring.as_ptr().cast())
96
14858
            == 0
97
        {
98
            panic!("Could not load fonts from directory tests/resources");
99
14858
        }
100
14858

            
101
14858
        let font_map = FontMap::for_font_type(cairo::FontType::FontTypeFt).unwrap();
102
14858
        let raw_font_map: *mut pango::ffi::PangoFontMap = font_map.to_glib_none().0;
103
14858

            
104
14858
        pango_fc_font_map_set_config(raw_font_map as *mut _, config);
105
14858
        fontconfig_sys::FcConfigDestroy(config);
106
14858

            
107
14858
        FontMap::set_default(Some(&font_map.downcast::<pangocairo::FontMap>().unwrap()));
108
14858
    }
109
}
110

            
111
#[cfg(all(
112
    all(not(target_os = "macos"), not(target_os = "windows")),
113
    system_deps_have_fontconfig,
114
    system_deps_have_pangoft2
115
))]
116
14858
pub fn setup_font_map() {
117
14858
    unsafe {
118
14858
        self::pango_ft2::load_test_fonts();
119
14858
    }
120
14858
}
121

            
122
#[cfg(any(
123
    any(target_os = "macos", target_os = "windows"),
124
    not(system_deps_have_fontconfig),
125
    not(system_deps_have_pangoft2)
126
))]
127
pub fn setup_font_map() {}
128

            
129
13851
pub fn setup_language() {
130
    static ONCE: Once = Once::new();
131

            
132
13851
    ONCE.call_once(|| {
133
38
        // For systemLanguage attribute tests.
134
38
        // The trailing ":" is intentional to test gitlab#425.
135
38
        env::set_var("LANGUAGE", "de:en_US:en:");
136
38
        env::set_var("LC_ALL", "de:en_US:en:");
137
13851
    });
138
13851
}