Source code

Revision control

Other Tools

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
use std::fs::File;
6
use std::path::{Path, PathBuf};
7
8
use api::{CaptureBits, ExternalImageData, ImageDescriptor};
9
#[cfg(feature = "png")]
10
use api::ImageFormat;
11
use api::units::TexelRect;
12
#[cfg(feature = "png")]
13
use api::units::DeviceIntSize;
14
#[cfg(feature = "capture")]
15
use crate::print_tree::{PrintableTree, PrintTree};
16
use ron;
17
use serde;
18
19
20
#[derive(Clone)]
21
pub struct CaptureConfig {
22
pub root: PathBuf,
23
pub bits: CaptureBits,
24
#[cfg(feature = "capture")]
25
pretty: ron::ser::PrettyConfig,
26
}
27
28
impl CaptureConfig {
29
#[cfg(feature = "capture")]
30
pub fn new(root: PathBuf, bits: CaptureBits) -> Self {
31
CaptureConfig {
32
root,
33
bits,
34
#[cfg(feature = "capture")]
35
pretty: ron::ser::PrettyConfig {
36
enumerate_arrays: true,
37
.. ron::ser::PrettyConfig::default()
38
},
39
}
40
}
41
42
#[cfg(feature = "capture")]
43
pub fn file_path<P>(&self, name: P, ext: &str) -> PathBuf
44
where P: AsRef<Path> {
45
self.root.join(name).with_extension(ext)
46
}
47
48
#[cfg(feature = "capture")]
49
pub fn serialize<T, P>(&self, data: &T, name: P)
50
where
51
T: serde::Serialize,
52
P: AsRef<Path>,
53
{
54
use std::io::Write;
55
56
let ron = ron::ser::to_string_pretty(data, self.pretty.clone())
57
.unwrap();
58
let path = self.file_path(name, "ron");
59
let mut file = File::create(path)
60
.unwrap();
61
write!(file, "{}\n", ron)
62
.unwrap();
63
}
64
65
#[cfg(feature = "capture")]
66
pub fn serialize_tree<T, P>(&self, data: &T, name: P)
67
where
68
T: PrintableTree,
69
P: AsRef<Path>
70
{
71
let path = self.root
72
.join(name)
73
.with_extension("tree");
74
let file = File::create(path)
75
.unwrap();
76
let mut pt = PrintTree::new_with_sink("", file);
77
data.print_with(&mut pt);
78
}
79
80
#[cfg(feature = "replay")]
81
pub fn deserialize<T, P>(root: &PathBuf, name: P) -> Option<T>
82
where
83
T: for<'a> serde::Deserialize<'a>,
84
P: AsRef<Path>,
85
{
86
use std::io::Read;
87
88
let mut string = String::new();
89
let path = root
90
.join(name.as_ref())
91
.with_extension("ron");
92
File::open(path)
93
.ok()?
94
.read_to_string(&mut string)
95
.unwrap();
96
match ron::de::from_str(&string) {
97
Ok(out) => Some(out),
98
Err(e) => panic!("File {:?} deserialization failed: {:?}", name.as_ref(), e),
99
}
100
}
101
102
#[cfg(feature = "png")]
103
pub fn save_png(
104
path: PathBuf, size: DeviceIntSize, format: ImageFormat, stride: Option<i32>, data: &[u8],
105
) {
106
use png::{BitDepth, ColorType, Encoder};
107
use std::io::BufWriter;
108
use std::borrow::Cow;
109
110
// `png` expects
111
let data = match stride {
112
Some(stride) if stride != format.bytes_per_pixel() * size.width => {
113
let mut unstrided = Vec::new();
114
for y in 0..size.height {
115
let start = (y * stride) as usize;
116
unstrided.extend_from_slice(&data[start..start+(size.width * format.bytes_per_pixel()) as usize]);
117
}
118
Cow::from(unstrided)
119
}
120
_ => Cow::from(data),
121
};
122
123
let color_type = match format {
124
ImageFormat::RGBA8 => ColorType::RGBA,
125
ImageFormat::BGRA8 => {
126
warn!("Unable to swizzle PNG of BGRA8 type");
127
ColorType::RGBA
128
},
129
ImageFormat::R8 => ColorType::Grayscale,
130
ImageFormat::RG8 => ColorType::GrayscaleAlpha,
131
_ => {
132
error!("Unable to save PNG of {:?}", format);
133
return;
134
}
135
};
136
let w = BufWriter::new(File::create(path).unwrap());
137
let mut enc = Encoder::new(w, size.width as u32, size.height as u32);
138
enc.set_color(color_type);
139
enc.set_depth(BitDepth::Eight);
140
enc
141
.write_header()
142
.unwrap()
143
.write_image_data(&*data)
144
.unwrap();
145
}
146
}
147
148
/// An image that `ResourceCache` is unable to resolve during a capture.
149
/// The image has to be transferred to `Renderer` and locked with the
150
/// external image handler to get the actual contents and serialize them.
151
#[derive(Deserialize, Serialize)]
152
pub struct ExternalCaptureImage {
153
pub short_path: String,
154
pub descriptor: ImageDescriptor,
155
pub external: ExternalImageData,
156
}
157
158
/// A short description of an external image to be saved separately as
159
/// "externals/XX.ron", redirecting into a specific texture/blob with
160
/// the corresponding UV rectangle.
161
#[derive(Deserialize, Serialize)]
162
pub struct PlainExternalImage {
163
/// Path to the RON file describing the texel data.
164
pub data: String,
165
/// External image data source.
166
pub external: ExternalImageData,
167
/// UV sub-rectangle of the image.
168
pub uv: TexelRect,
169
}