winprint_ext/ticket/
page_imageable_size.rs1use super::{
2 document::{
3 reader::{ParsableXmlDocument, ParsePrintSchemaError},
4 PrintCapabilitiesDocument, WithProperties, NS_PSK,
5 },
6 FetchPrintCapabilitiesError, MediaSizeTuple, PageMediaSize, PrintCapabilities, PrintTicket,
7};
8use crate::printer::PrinterDevice;
9use thiserror::Error;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
12pub struct PageImageableSize {
14 pub size: MediaSizeTuple,
16 pub origin: MediaSizeTuple,
18 pub extent: MediaSizeTuple,
20}
21
22#[derive(Error, Debug)]
23pub enum PageImageableSizeError {
25 #[error("Failed to fetch print capabilities")]
27 FetchCapabilitiesError(#[from] FetchPrintCapabilitiesError),
28 #[error("Failed to parse print capabilities")]
30 ParseCapabilitiesError(#[from] ParsePrintSchemaError),
31 #[error("Field error: {field}")]
33 FieldError {
34 field: &'static str,
36 },
37}
38
39fn get_u32_property(
40 properties: &impl WithProperties,
41 name: &'static str,
42 ns: Option<&str>,
43) -> Result<u32, PageImageableSizeError> {
44 properties
45 .get_property(name, ns)
46 .and_then(|x| x.value.as_ref())
47 .and_then(|x| x.integer())
48 .and_then(|x| u32::try_from(x).ok())
49 .ok_or(PageImageableSizeError::FieldError { field: name })
50}
51
52impl PageImageableSize {
53 pub fn try_fetch(
55 device: &PrinterDevice,
56 media: PageMediaSize,
57 ) -> Result<Self, PageImageableSizeError> {
58 let ticket = PrintTicket::from(media);
59 let caps_xml = PrintCapabilities::fetch_xml_for_ticket(device, Some(&ticket))?;
60 let caps = PrintCapabilitiesDocument::parse_from_bytes(&caps_xml)?;
61 let imageable_size = caps.get_property("PageImageableSize", Some(NS_PSK)).ok_or(
62 PageImageableSizeError::FieldError {
63 field: "PageImageableSize",
64 },
65 )?;
66 let size_w = get_u32_property(imageable_size, "ImageableSizeWidth", Some(NS_PSK))?;
67 let size_h = get_u32_property(imageable_size, "ImageableSizeHeight", Some(NS_PSK))?;
68 let imageable_area = imageable_size
69 .get_property("ImageableArea", Some(NS_PSK))
70 .ok_or(PageImageableSizeError::FieldError {
71 field: "ImageableArea",
72 })?;
73 let origin_w = get_u32_property(imageable_area, "OriginWidth", Some(NS_PSK))?;
74 let origin_h = get_u32_property(imageable_area, "OriginHeight", Some(NS_PSK))?;
75 let extent_w = get_u32_property(imageable_area, "ExtentWidth", Some(NS_PSK))?;
76 let extent_h = get_u32_property(imageable_area, "ExtentHeight", Some(NS_PSK))?;
77 Ok(Self {
78 size: MediaSizeTuple::micron(size_w, size_h),
79 origin: MediaSizeTuple::micron(origin_w, origin_h),
80 extent: MediaSizeTuple::micron(extent_w, extent_h),
81 })
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::PageImageableSize;
88 use crate::{test_utils::null_device, ticket::PrintCapabilities};
89
90 #[test]
91 fn get_imageable_size() {
92 let device = null_device::thread_local();
93 let capabilities = PrintCapabilities::fetch(&device).unwrap();
94 for media in capabilities.page_media_sizes() {
95 let imageable_size = PageImageableSize::try_fetch(&device, media);
96 assert!(imageable_size.is_ok());
97 println!("{:#?}", imageable_size);
98 }
99 }
100}