mirror of
https://github.com/storytold/winprint.rs.git
synced 2026-10-13 23:17:45 +00:00
chore!: upgrade windows crate
This commit is contained in:
8 files changed
+88
-92
No files matched your search
+14
-6
@@ -1,22 +1,30 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
name = "winprint"
|
||||
version = "0.1.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.4.0"
|
||||
scopeguard = "1.1"
|
||||
thiserror = "1.0"
|
||||
windows = "0.20"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "0.54"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Security",
|
||||
"Win32_Graphics_Gdi",
|
||||
"Win32_System_Com",
|
||||
"Win32_Storage_Xps_Printing",
|
||||
"Win32_System_Threading",
|
||||
"Win32_Graphics_Printing",
|
||||
]
|
||||
|
||||
[build-dependencies]
|
||||
windows = "0.20"
|
||||
reqwest = { version = "0.11", features = ["blocking"] }
|
||||
flate2 = "1.0"
|
||||
tar = "0.4"
|
||||
|
||||
[features]
|
||||
default = ["pdfium"]
|
||||
pdfium = []
|
||||
pdfium = []
|
||||
@@ -21,21 +21,18 @@ fn try_link_pdfium() -> Result<(), Box<dyn Error>> {
|
||||
target_path.push("pdfium_binaries");
|
||||
fs::create_dir_all(target_path.as_path())?;
|
||||
let has_bin = fs::read_dir(target_path.as_path())?.any(|x| {
|
||||
bin_ext
|
||||
.iter()
|
||||
.find(|s| {
|
||||
x.as_ref()
|
||||
.ok()
|
||||
.and_then(|d| {
|
||||
if Path::new(d.file_name().as_os_str()).extension() == Some(s) {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.is_some()
|
||||
})
|
||||
.is_some()
|
||||
bin_ext.iter().any(|s| {
|
||||
x.as_ref()
|
||||
.ok()
|
||||
.and_then(|d| {
|
||||
if Path::new(d.file_name().as_os_str()).extension() == Some(s) {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.is_some()
|
||||
})
|
||||
});
|
||||
if !has_bin {
|
||||
let build_id = 4660;
|
||||
@@ -52,7 +49,7 @@ fn try_link_pdfium() -> Result<(), Box<dyn Error>> {
|
||||
if file.header().entry_type() == EntryType::Regular {
|
||||
let file_path = file.path()?;
|
||||
let file_extension = file_path.extension();
|
||||
let is_bin = bin_ext.iter().find(|s| file_extension == Some(s)).is_some();
|
||||
let is_bin = bin_ext.iter().any(|s| file_extension == Some(s));
|
||||
if is_bin {
|
||||
if let Some(file_name_raw) = file_path.file_name() {
|
||||
let mut file_name_str = file_name_raw.to_string_lossy();
|
||||
@@ -79,18 +76,4 @@ fn try_link_pdfium() -> Result<(), Box<dyn Error>> {
|
||||
fn main() {
|
||||
#[cfg(feature = "pdfium")]
|
||||
try_link_pdfium().unwrap();
|
||||
windows::build! {
|
||||
Windows::Win32::Graphics::Gdi::{
|
||||
CreateDCW, DeleteDC, GetDeviceCaps, SetViewportOrgEx, GET_DEVICE_CAPS_INDEX, HDC,
|
||||
LOGPIXELSX, LOGPIXELSY, PHYSICALHEIGHT, PHYSICALOFFSETX, PHYSICALOFFSETY,
|
||||
PHYSICALWIDTH,
|
||||
},
|
||||
Windows::Win32::Graphics::Printing::*,
|
||||
Windows::Win32::System::Com::{CoCreateInstance, CoInitializeEx, CoUninitialize},
|
||||
Windows::Win32::Storage::Xps::*,
|
||||
Windows::Win32::Storage::Xps::Printing::*,
|
||||
Windows::Win32::Foundation::CloseHandle,
|
||||
Windows::Win32::System::Threading::{CreateEventW, SetEvent, WaitForSingleObject},
|
||||
Windows::Win32::System::WindowsProgramming::INFINITE
|
||||
};
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
windows::include_bindings!();
|
||||
#[cfg(feature = "pdfium")]
|
||||
pub(crate) mod pdfium;
|
||||
@@ -1,6 +1,6 @@
|
||||
#![allow(warnings, unused)]
|
||||
|
||||
use super::Windows::Win32::Graphics::Gdi::HDC;
|
||||
use windows::Win32::Graphics::Gdi::HDC;
|
||||
/*
|
||||
generated by rust-bindgen 0.59.1
|
||||
cmdline:
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ mod tests {
|
||||
use std::path::Path;
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let printers = PrinterInfo::all();
|
||||
let printers = PrinterInfo::all().unwrap();
|
||||
println!("{:#?}", printers);
|
||||
let my_printer = printers.iter().find(|x| x.name() == "pdfFactory Pro").unwrap();
|
||||
let xps = XpsPrinter::new(my_printer.clone());
|
||||
|
||||
+21
-10
@@ -3,7 +3,9 @@ use scopeguard::defer;
|
||||
use std::alloc::{alloc, dealloc, Layout};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use thiserror::Error;
|
||||
use windows::core::PCWSTR;
|
||||
use windows::Win32::Graphics::Printing::*;
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PrinterInfo {
|
||||
name: String,
|
||||
@@ -11,20 +13,26 @@ pub struct PrinterInfo {
|
||||
os_name: OsString,
|
||||
os_attributes: u32,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum EnumPrinterError {
|
||||
#[error("Failed to enum printer: {0}")]
|
||||
FailedToEnumPrinter(windows::core::Error),
|
||||
}
|
||||
|
||||
impl PrinterInfo {
|
||||
pub fn all() -> Vec<Self> {
|
||||
pub fn all() -> Result<Vec<Self>, EnumPrinterError> {
|
||||
let mut bytes_needed = 0;
|
||||
let mut count_returned = 0;
|
||||
let flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;
|
||||
let name = PWSTR::default();
|
||||
let name = PCWSTR::null();
|
||||
let level = 4;
|
||||
unsafe {
|
||||
EnumPrintersW(
|
||||
let _ = EnumPrintersW(
|
||||
flags,
|
||||
name,
|
||||
level,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
None,
|
||||
&mut bytes_needed,
|
||||
&mut count_returned,
|
||||
);
|
||||
@@ -40,11 +48,14 @@ impl PrinterInfo {
|
||||
flags,
|
||||
name,
|
||||
level,
|
||||
buffer,
|
||||
bytes_needed,
|
||||
Some(std::slice::from_raw_parts_mut(
|
||||
buffer,
|
||||
bytes_needed as usize,
|
||||
)),
|
||||
&mut bytes_needed,
|
||||
&mut count_returned,
|
||||
);
|
||||
)
|
||||
.map_err(EnumPrinterError::FailedToEnumPrinter)?;
|
||||
let mut result = Vec::<PrinterInfo>::with_capacity(count_returned as usize);
|
||||
for i in 0..count_returned {
|
||||
let info = &*(buffer as *const PRINTER_INFO_4W).offset(i as isize);
|
||||
@@ -56,7 +67,7 @@ impl PrinterInfo {
|
||||
os_name,
|
||||
});
|
||||
}
|
||||
result
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+23
-28
@@ -2,25 +2,21 @@ use crate::bindings::pdfium::*;
|
||||
use crate::printer::FilePrinter;
|
||||
use crate::printer::FilePrinterError;
|
||||
use crate::printer::PrinterInfo;
|
||||
use crate::utils::pdfium::PdfiumCustomDocument;
|
||||
use crate::utils::pdfium::PdfiumGuard;
|
||||
use crate::utils::wchar;
|
||||
use crate::{
|
||||
bindings::Windows::Win32::{
|
||||
Foundation::PWSTR,
|
||||
Graphics::Gdi::{
|
||||
CreateDCW, DeleteDC, GetDeviceCaps, SetViewportOrgEx, GET_DEVICE_CAPS_INDEX, HDC,
|
||||
LOGPIXELSX, LOGPIXELSY, PHYSICALHEIGHT, PHYSICALOFFSETX, PHYSICALOFFSETY,
|
||||
PHYSICALWIDTH,
|
||||
},
|
||||
Storage::Xps::*,
|
||||
},
|
||||
utils::pdfium::PdfiumCustomDocument,
|
||||
};
|
||||
use scopeguard::defer;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::{fs::File, mem};
|
||||
use windows::Handle;
|
||||
use windows::{
|
||||
core::PCWSTR,
|
||||
Win32::Graphics::Gdi::{
|
||||
CreateDCW, DeleteDC, GetDeviceCaps, SetViewportOrgEx, GET_DEVICE_CAPS_INDEX, LOGPIXELSX,
|
||||
LOGPIXELSY, PHYSICALHEIGHT, PHYSICALOFFSETX, PHYSICALOFFSETY, PHYSICALWIDTH,
|
||||
},
|
||||
Win32::Storage::Xps::*,
|
||||
};
|
||||
pub struct PdfiumPrinter {
|
||||
printer: PrinterInfo,
|
||||
}
|
||||
@@ -34,25 +30,25 @@ impl PdfiumPrinter {
|
||||
impl FilePrinter for PdfiumPrinter {
|
||||
fn print(&self, path: &Path) -> std::result::Result<(), FilePrinterError> {
|
||||
unsafe {
|
||||
let created_hdc_print = CreateDCW(
|
||||
let hdc_print = CreateDCW(
|
||||
None,
|
||||
PWSTR(wchar::to_wide_chars(self.printer.os_name()).as_mut_ptr()),
|
||||
PCWSTR(wchar::to_wide_chars(self.printer.os_name()).as_ptr()),
|
||||
None,
|
||||
ptr::null(),
|
||||
)
|
||||
.ok()
|
||||
.map_err(|_| FilePrinterError::FailedToOpenPrinter)?;
|
||||
None,
|
||||
);
|
||||
if hdc_print.is_invalid() {
|
||||
return Err(FilePrinterError::FailedToOpenPrinter);
|
||||
}
|
||||
defer! {
|
||||
DeleteDC(created_hdc_print);
|
||||
DeleteDC(hdc_print);
|
||||
}
|
||||
let hdc_print = HDC(created_hdc_print.0);
|
||||
let mut doc_name = wchar::to_wide_chars(path.file_name().unwrap_or(path.as_ref()));
|
||||
let doc_info = DOCINFOW {
|
||||
cbSize: mem::size_of::<DOCINFOW>() as i32,
|
||||
fwType: 0,
|
||||
lpszDocName: PWSTR(doc_name.as_mut_ptr()),
|
||||
lpszOutput: PWSTR::default(),
|
||||
lpszDatatype: PWSTR::default(),
|
||||
lpszDocName: PCWSTR(doc_name.as_mut_ptr()),
|
||||
lpszOutput: PCWSTR::null(),
|
||||
lpszDatatype: PCWSTR::null(),
|
||||
};
|
||||
StartDocW(hdc_print, &doc_info);
|
||||
{
|
||||
@@ -71,9 +67,8 @@ impl FilePrinter for PdfiumPrinter {
|
||||
FPDF_ClosePage(page);
|
||||
}
|
||||
StartPage(hdc_print);
|
||||
let get_attr = |kind: u32| -> i32 {
|
||||
GetDeviceCaps(hdc_print, GET_DEVICE_CAPS_INDEX(kind))
|
||||
};
|
||||
let get_attr =
|
||||
|kind: GET_DEVICE_CAPS_INDEX| -> i32 { GetDeviceCaps(hdc_print, kind) };
|
||||
let dpi_x = get_attr(LOGPIXELSX);
|
||||
let dpi_y = get_attr(LOGPIXELSY);
|
||||
let page_width = FPDF_GetPageWidth(page) * dpi_x as f64 / 72.0;
|
||||
@@ -86,7 +81,7 @@ impl FilePrinter for PdfiumPrinter {
|
||||
let h = page_height * scale;
|
||||
let org_x = -get_attr(PHYSICALOFFSETX);
|
||||
let org_y = -get_attr(PHYSICALOFFSETY);
|
||||
SetViewportOrgEx(hdc_print, org_x, org_y, ptr::null_mut());
|
||||
SetViewportOrgEx(hdc_print, org_x, org_y, None);
|
||||
FPDF_RenderPage(hdc_print, page, 0, 0, w as i32, h as i32, 0, FPDF_PRINTING);
|
||||
EndPage(hdc_print);
|
||||
}
|
||||
|
||||
+15
-15
@@ -1,8 +1,3 @@
|
||||
use crate::bindings::Windows::Win32::{
|
||||
Foundation::{CloseHandle, PWSTR},
|
||||
Storage::Xps::{Printing::*, *},
|
||||
System::{Com::*, Threading::*, WindowsProgramming::INFINITE},
|
||||
};
|
||||
use crate::printer::FilePrinter;
|
||||
use crate::printer::FilePrinterError;
|
||||
use crate::printer::PrinterInfo;
|
||||
@@ -10,7 +5,14 @@ use crate::utils::wchar;
|
||||
use scopeguard::defer;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use windows::Handle;
|
||||
use windows::{
|
||||
core::PCWSTR,
|
||||
Win32::{
|
||||
Foundation::CloseHandle,
|
||||
Storage::Xps::{Printing::*, *},
|
||||
System::{Com::*, Threading::*},
|
||||
},
|
||||
};
|
||||
|
||||
pub struct XpsPrinter {
|
||||
printer: PrinterInfo,
|
||||
@@ -25,28 +27,26 @@ impl XpsPrinter {
|
||||
impl FilePrinter for XpsPrinter {
|
||||
fn print(&self, path: &Path) -> std::result::Result<(), FilePrinterError> {
|
||||
unsafe {
|
||||
let _ = CoInitializeEx(std::ptr::null_mut(), COINIT_MULTITHREADED);
|
||||
let _ = CoInitializeEx(None, COINIT_MULTITHREADED);
|
||||
defer! {
|
||||
CoUninitialize();
|
||||
}
|
||||
let event = CreateEventW(ptr::null_mut(), true, false, None)
|
||||
.ok()
|
||||
let event = CreateEventW(None, true, false, None)
|
||||
.map_err(|_| FilePrinterError::FailedToCreateJob)?;
|
||||
defer! {
|
||||
CloseHandle(event);
|
||||
let _ = CloseHandle(event);
|
||||
}
|
||||
let xps_factory: IXpsOMObjectFactory =
|
||||
CoCreateInstance(&XpsOMObjectFactory, None, CLSCTX_ALL)
|
||||
.map_err(|_| FilePrinterError::FailedToOpenPrinter)?;
|
||||
let mut document_stream_container = Option::<IXpsPrintJobStream>::None;
|
||||
StartXpsPrintJob(
|
||||
PWSTR(wchar::to_wide_chars(self.printer.os_name()).as_mut_ptr()),
|
||||
PWSTR(wchar::to_wide_chars(path.file_name().unwrap_or(path.as_ref())).as_mut_ptr()),
|
||||
PCWSTR(wchar::to_wide_chars(self.printer.os_name()).as_ptr()),
|
||||
PCWSTR(wchar::to_wide_chars(path.file_name().unwrap_or(path.as_ref())).as_ptr()),
|
||||
None,
|
||||
None,
|
||||
event,
|
||||
ptr::null(),
|
||||
0,
|
||||
&[],
|
||||
ptr::null_mut(),
|
||||
ptr::addr_of_mut!(document_stream_container),
|
||||
ptr::null_mut(),
|
||||
@@ -55,7 +55,7 @@ impl FilePrinter for XpsPrinter {
|
||||
let document_stream =
|
||||
document_stream_container.ok_or(FilePrinterError::FailedToCreateJob)?;
|
||||
let xps_package = xps_factory
|
||||
.CreatePackageFromFile(PWSTR(wchar::to_wide_chars(path).as_mut_ptr()), false)
|
||||
.CreatePackageFromFile(PCWSTR(wchar::to_wide_chars(path).as_ptr()), false)
|
||||
.map_err(|_| FilePrinterError::FailedToWriteDocument)?;
|
||||
xps_package
|
||||
.WriteToStream(&document_stream, false)
|
||||
|
||||
Reference in new issue
Block a user