23#include <wx/cmndata.h>
33#include <winrt/base.h>
34#include <winrt/Windows.Foundation.h>
35#include <winrt/Windows.Foundation.Collections.h>
36#include <winrt/Windows.Graphics.Printing.h>
37#include <winrt/Windows.UI.Xaml.h>
38#include <winrt/Windows.UI.Xaml.Controls.h>
39#include <winrt/Windows.UI.Xaml.Media.h>
40#include <winrt/Windows.UI.Xaml.Printing.h>
41#include <winrt/Windows.UI.Xaml.Hosting.h>
42#include <winrt/Windows.Storage.h>
43#include <winrt/Windows.Storage.Streams.h>
44#include <winrt/Windows.Data.Pdf.h>
45#include <winrt/Windows.Graphics.Imaging.h>
47#include <winrt/base.h>
48#include <winrt/Windows.Foundation.h>
49#include <winrt/Windows.Foundation.Collections.h>
50#include <winrt/Windows.Graphics.Printing.h>
51#include <winrt/Windows.UI.Xaml.h>
52#include <winrt/Windows.UI.Xaml.Controls.h>
53#include <winrt/Windows.UI.Xaml.Media.Imaging.h>
54#include <winrt/Windows.UI.Xaml.Printing.h>
55#include <winrt/Windows.UI.Xaml.Hosting.h>
56#include <winrt/Windows.Storage.h>
57#include <winrt/Windows.Storage.Streams.h>
58#include <winrt/Windows.Data.Pdf.h>
59#include <winrt/Windows.Graphics.Imaging.h>
66MIDL_INTERFACE(
"C5435A42-8D43-4E7B-A68A-EF311E392087")
67IPrintManagerInterop : public ::IInspectable
70 virtual HRESULT STDMETHODCALLTYPE GetForWindow(
77 void **operation) = 0;
81MIDL_INTERFACE(
"3cbcf1bf-2f76-4e9c-96ab-e84b37972554")
82IDesktopWindowXamlSourceNative : public ::IUnknown
85 virtual HRESULT STDMETHODCALLTYPE AttachToWindow(
92static inline std::pair<uint32_t, uint32_t>
DpToPixels( winrt::Windows::Data::Pdf::PdfPage
const& page,
double dpi )
94 const auto s = page.Size();
95 const double scale = dpi / 96.0;
96 uint32_t w =
static_cast<uint32_t
>( std::max( 1.0, std::floor( s.Width *
scale + 0.5 ) ) );
97 uint32_t h =
static_cast<uint32_t
>( std::max( 1.0, std::floor( s.Height *
scale + 0.5 ) ) );
104 winrt::Windows::UI::Xaml::Controls::Image
image;
105 winrt::Windows::Storage::Streams::InMemoryRandomAccessStream
stream;
108 ManagedImage(winrt::Windows::UI::Xaml::Controls::Image img, winrt::Windows::Storage::Streams::InMemoryRandomAccessStream str) :
image(img),
stream(str) {}
111 :
image(std::move(other.image)),
stream(std::move(other.stream)) {}
114 if (
this != &other) {
115 image = std::move(other.image);
116 stream = std::move(other.stream);
127 auto page = pdf.GetPage( pageIndex );
131 wxLogTrace(
PRINTING_TRACE,
"Failed to get page %u from PDF document", pageIndex );
137 winrt::Windows::Data::Pdf::PdfPageRenderOptions opts;
138 opts.DestinationWidth( pxW );
139 opts.DestinationHeight( pxH );
141 winrt::Windows::Storage::Streams::InMemoryRandomAccessStream stream;
145 page.RenderToStreamAsync( stream, opts ).get();
147 catch( std::exception& e )
149 wxLogTrace(
PRINTING_TRACE,
"Failed to render page %u to image: %s", pageIndex, e.what() );
154 winrt::Windows::UI::Xaml::Media::Imaging::BitmapImage bmp;
159 bmp.SetSourceAsync( stream ).get();
161 catch(
const winrt::hresult_error& e )
163 wxLogTrace(
PRINTING_TRACE,
"Failed to set BitmapImage source for page %u: %s", pageIndex, e.message().c_str() );
166 catch( std::exception& e )
168 wxLogTrace(
PRINTING_TRACE,
"Failed to set BitmapImage source for page %u: %s", pageIndex, e.what() );
172 winrt::Windows::UI::Xaml::Controls::Image img;
174 img.Stretch( winrt::Windows::UI::Xaml::Media::Stretch::Uniform );
187 WIN_PDF_PRINTER( HWND hwndOwner, winrt::Windows::Data::Pdf::PdfDocument
const& pdf ) :
202 m_xamlSource = winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource();
203 auto native =
m_xamlSource.as<IDesktopWindowXamlSourceNative>();
207 wxLogTrace(
PRINTING_TRACE,
"Failed to create XAML Island host" );
211 RECT rc{ 0, 0, 100, 100 };
212 m_host = ::CreateWindowExW( 0,
L"STATIC",
L"", WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
213 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
m_hwnd,
nullptr,
214 ::GetModuleHandleW(
nullptr ),
nullptr );
216 auto cleanup_guard = std::unique_ptr<void, std::function<void(
void* )>>
217 ( (
void*) 1, [
this](
void* ){ this->
cleanup(); } );
225 if( FAILED( native->AttachToWindow(
m_host ) ) )
227 wxLogTrace(
PRINTING_TRACE,
"Failed to attach XAML Island to host window" );
231 m_root = winrt::Windows::UI::Xaml::Controls::Grid();
234 m_printDoc = winrt::Windows::UI::Xaml::Printing::PrintDocument();
239 [
this]( winrt::Windows::Foundation::IInspectable
const& sender, winrt::Windows::UI::Xaml::Printing::PaginateEventArgs
const& e )
241 m_printDoc.SetPreviewPageCount(
m_pageCount, winrt::Windows::UI::Xaml::Printing::PreviewPageCountType::Final );
245 [
this]( winrt::Windows::Foundation::IInspectable
const& sender, winrt::Windows::UI::Xaml::Printing::GetPreviewPageEventArgs
const& e )
247 const uint32_t
index = e.PageNumber() - 1;
249 if( managedImg.image )
258 [
this]( winrt::Windows::Foundation::IInspectable
const& sender, winrt::Windows::UI::Xaml::Printing::AddPagesEventArgs
const& e )
263 if( managedImg.image )
275 auto factory = winrt::get_activation_factory<winrt::Windows::Graphics::Printing::PrintManager>();
276 auto pmInterop = factory.as<IPrintManagerInterop>();
278 winrt::Windows::Graphics::Printing::PrintManager
printManager{
nullptr };
280 if( FAILED( pmInterop->GetForWindow(
m_hwnd,
281 winrt::guid_of<winrt::Windows::Graphics::Printing::PrintManager>(),
284 wxLogTrace(
PRINTING_TRACE,
"Failed to get PrintManager for window" );
291 [
this]( winrt::Windows::Foundation::IInspectable
const& sender, winrt::Windows::Graphics::Printing::PrintTaskRequestedEventArgs
const& e )
293 auto task = e.Request().CreatePrintTask(
L"KiCad PDF Print",
294 [
this]( winrt::Windows::Graphics::Printing::PrintTaskSourceRequestedArgs
const& sourceRequestedArgs )
297 sourceRequestedArgs.SetSource(
m_docSrc );
301 winrt::Windows::Foundation::IAsyncOperation<bool> asyncOp{
nullptr };
304 if( FAILED( pmInterop->ShowPrintUIForWindowAsync(
m_hwnd, winrt::put_abi(asyncOp) ) ) )
306 wxLogTrace(
PRINTING_TRACE,
"Failed to show print UI for window" );
314 shown = asyncOp.GetResults();
316 catch( std::exception& e )
318 wxLogTrace(
PRINTING_TRACE,
"GetResults threw an exception for the print window: %s", e.what() );
324 catch( std::exception& e )
326 wxLogTrace(
PRINTING_TRACE,
"Exception caught in print operation: %s", e.what() );
357 ::DestroyWindow(
m_host );
366 winrt::Windows::Data::Pdf::PdfDocument
m_pdf{
nullptr };
368 winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource
m_xamlSource{
nullptr };
369 winrt::Windows::UI::Xaml::Controls::Grid
m_root{
nullptr };
370 winrt::Windows::UI::Xaml::Printing::PrintDocument
m_printDoc{
nullptr };
371 winrt::Windows::Graphics::Printing::IPrintDocumentSource
m_docSrc{
nullptr };
374 winrt::Windows::Graphics::Printing::PrintManager
m_rtPM{
nullptr };
391 if( s.empty() )
return {};
393 int len = MultiByteToWideChar( CP_UTF8, 0, s.data(), (
int) s.size(),
nullptr, 0 );
394 std::wstring out( len,
L'\0' );
396 MultiByteToWideChar( CP_UTF8, 0, s.data(), (
int) s.size(), out.data(), len );
403 DWORD attrs = GetFileAttributesA( aFile.c_str() );
405 if( attrs == INVALID_FILE_ATTRIBUTES )
409 winrt::Windows::Data::Pdf::PdfDocument pdf{
nullptr };
414 auto file = winrt::Windows::Storage::StorageFile::GetFileFromPathAsync( winrt::hstring(
path ) ).get();
415 pdf = winrt::Windows::Data::Pdf::PdfDocument::LoadFromFileAsync( file ).get();
424 HWND hwndOwner = ::GetActiveWindow();
425 if( !hwndOwner ) hwndOwner = ::GetForegroundWindow();
431 return printer.Run();
465 aData.SetFilename( wxEmptyString );
ManagedImage & operator=(ManagedImage &&other) noexcept
winrt::Windows::UI::Xaml::Controls::Image image
winrt::Windows::Storage::Streams::InMemoryRandomAccessStream stream
ManagedImage(ManagedImage &&other) noexcept
ManagedImage(winrt::Windows::UI::Xaml::Controls::Image img, winrt::Windows::Storage::Streams::InMemoryRandomAccessStream str)
IPrintManagerInterop REFIID riid
static ManagedImage RenderPdfPageToImage(winrt::Windows::Data::Pdf::PdfDocument const &pdf, uint32_t pageIndex, double dpi)
virtual HRESULT STDMETHODCALLTYPE get_WindowHandle(HWND *hWnd)=0
virtual HRESULT STDMETHODCALLTYPE ShowPrintUIForWindowAsync(HWND appWindow, void **operation)=0
static std::pair< uint32_t, uint32_t > DpToPixels(winrt::Windows::Data::Pdf::PdfPage const &page, double dpi)
IPrintManagerInterop REFIID void ** printManager