30#include <winrt/base.h>
31#include <winrt/Windows.Foundation.h>
32#include <winrt/Windows.Foundation.Collections.h>
33#include <winrt/Windows.Graphics.Printing.h>
34#include <winrt/Windows.UI.Xaml.h>
35#include <winrt/Windows.UI.Xaml.Controls.h>
36#include <winrt/Windows.UI.Xaml.Media.h>
37#include <winrt/Windows.UI.Xaml.Printing.h>
38#include <winrt/Windows.UI.Xaml.Hosting.h>
39#include <winrt/Windows.Storage.h>
40#include <winrt/Windows.Storage.Streams.h>
41#include <winrt/Windows.Data.Pdf.h>
42#include <winrt/Windows.Graphics.Imaging.h>
44#include <winrt/base.h>
45#include <winrt/Windows.Foundation.h>
46#include <winrt/Windows.Foundation.Collections.h>
47#include <winrt/Windows.Graphics.Printing.h>
48#include <winrt/Windows.UI.Xaml.h>
49#include <winrt/Windows.UI.Xaml.Controls.h>
50#include <winrt/Windows.UI.Xaml.Media.Imaging.h>
51#include <winrt/Windows.UI.Xaml.Printing.h>
52#include <winrt/Windows.UI.Xaml.Hosting.h>
53#include <winrt/Windows.Storage.h>
54#include <winrt/Windows.Storage.Streams.h>
55#include <winrt/Windows.Data.Pdf.h>
56#include <winrt/Windows.Graphics.Imaging.h>
63MIDL_INTERFACE(
"C5435A42-8D43-4E7B-A68A-EF311E392087")
64IPrintManagerInterop : public ::IInspectable
67 virtual HRESULT STDMETHODCALLTYPE GetForWindow(
74 void **operation) = 0;
78MIDL_INTERFACE(
"3cbcf1bf-2f76-4e9c-96ab-e84b37972554")
79IDesktopWindowXamlSourceNative : public ::IUnknown
82 virtual HRESULT STDMETHODCALLTYPE AttachToWindow(
89static inline std::pair<uint32_t, uint32_t>
DpToPixels( winrt::Windows::Data::Pdf::PdfPage
const& page,
double dpi )
91 const auto s = page.Size();
92 const double scale = dpi / 96.0;
93 uint32_t w =
static_cast<uint32_t
>( std::max( 1.0, std::floor( s.Width *
scale + 0.5 ) ) );
94 uint32_t h =
static_cast<uint32_t
>( std::max( 1.0, std::floor( s.Height *
scale + 0.5 ) ) );
101 winrt::Windows::UI::Xaml::Controls::Image
image;
102 winrt::Windows::Storage::Streams::InMemoryRandomAccessStream
stream;
105 ManagedImage(winrt::Windows::UI::Xaml::Controls::Image img, winrt::Windows::Storage::Streams::InMemoryRandomAccessStream str) :
image(img),
stream(str) {}
108 :
image(std::move(other.image)),
stream(std::move(other.stream)) {}
111 if (
this != &other) {
112 image = std::move(other.image);
113 stream = std::move(other.stream);
124 auto page = pdf.GetPage( pageIndex );
128 wxLogTrace(
PRINTING_TRACE,
"Failed to get page %u from PDF document", pageIndex );
134 winrt::Windows::Data::Pdf::PdfPageRenderOptions opts;
135 opts.DestinationWidth( pxW );
136 opts.DestinationHeight( pxH );
138 winrt::Windows::Storage::Streams::InMemoryRandomAccessStream stream;
142 page.RenderToStreamAsync( stream, opts ).get();
144 catch( std::exception& e )
146 wxLogTrace(
PRINTING_TRACE,
"Failed to render page %u to image: %s", pageIndex, e.what() );
151 winrt::Windows::UI::Xaml::Media::Imaging::BitmapImage bmp;
156 bmp.SetSourceAsync( stream ).get();
158 catch(
const winrt::hresult_error& e )
160 wxLogTrace(
PRINTING_TRACE,
"Failed to set BitmapImage source for page %u: %s", pageIndex, e.message().c_str() );
163 catch( std::exception& e )
165 wxLogTrace(
PRINTING_TRACE,
"Failed to set BitmapImage source for page %u: %s", pageIndex, e.what() );
169 winrt::Windows::UI::Xaml::Controls::Image img;
171 img.Stretch( winrt::Windows::UI::Xaml::Media::Stretch::Uniform );
184 WIN_PDF_PRINTER( HWND hwndOwner, winrt::Windows::Data::Pdf::PdfDocument
const& pdf ) :
199 m_xamlSource = winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource();
200 auto native =
m_xamlSource.as<IDesktopWindowXamlSourceNative>();
204 wxLogTrace(
PRINTING_TRACE,
"Failed to create XAML Island host" );
208 RECT rc{ 0, 0, 100, 100 };
209 m_host = ::CreateWindowExW( 0, L
"STATIC", L
"", WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
210 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
m_hwnd,
nullptr,
211 ::GetModuleHandleW(
nullptr ),
nullptr );
213 auto cleanup_guard = std::unique_ptr<void, std::function<void(
void* )>>
214 ( (
void*) 1, [
this](
void* ){ this->
cleanup(); } );
222 if( FAILED( native->AttachToWindow(
m_host ) ) )
224 wxLogTrace(
PRINTING_TRACE,
"Failed to attach XAML Island to host window" );
228 m_root = winrt::Windows::UI::Xaml::Controls::Grid();
231 m_printDoc = winrt::Windows::UI::Xaml::Printing::PrintDocument();
236 [
this]( winrt::Windows::Foundation::IInspectable
const& sender, winrt::Windows::UI::Xaml::Printing::PaginateEventArgs
const& e )
238 m_printDoc.SetPreviewPageCount(
m_pageCount, winrt::Windows::UI::Xaml::Printing::PreviewPageCountType::Final );
242 [
this]( winrt::Windows::Foundation::IInspectable
const& sender, winrt::Windows::UI::Xaml::Printing::GetPreviewPageEventArgs
const& e )
244 const uint32_t index = e.PageNumber() - 1;
246 if( managedImg.image )
255 [
this]( winrt::Windows::Foundation::IInspectable
const& sender, winrt::Windows::UI::Xaml::Printing::AddPagesEventArgs
const& e )
260 if( managedImg.image )
272 auto factory = winrt::get_activation_factory<winrt::Windows::Graphics::Printing::PrintManager>();
273 auto pmInterop = factory.as<IPrintManagerInterop>();
275 winrt::Windows::Graphics::Printing::PrintManager
printManager{
nullptr };
277 if( FAILED( pmInterop->GetForWindow(
m_hwnd,
278 winrt::guid_of<winrt::Windows::Graphics::Printing::PrintManager>(),
281 wxLogTrace(
PRINTING_TRACE,
"Failed to get PrintManager for window" );
288 [
this]( winrt::Windows::Foundation::IInspectable
const& sender, winrt::Windows::Graphics::Printing::PrintTaskRequestedEventArgs
const& e )
290 auto task = e.Request().CreatePrintTask( L
"KiCad PDF Print",
291 [
this]( winrt::Windows::Graphics::Printing::PrintTaskSourceRequestedArgs
const& sourceRequestedArgs )
294 sourceRequestedArgs.SetSource(
m_docSrc );
298 winrt::Windows::Foundation::IAsyncOperation<bool> asyncOp{
nullptr };
301 if( FAILED( pmInterop->ShowPrintUIForWindowAsync(
m_hwnd, winrt::put_abi(asyncOp) ) ) )
303 wxLogTrace(
PRINTING_TRACE,
"Failed to show print UI for window" );
311 shown = asyncOp.GetResults();
313 catch( std::exception& e )
315 wxLogTrace(
PRINTING_TRACE,
"GetResults threw an exception for the print window: %s", e.what() );
321 catch( std::exception& e )
323 wxLogTrace(
PRINTING_TRACE,
"Exception caught in print operation: %s", e.what() );
354 ::DestroyWindow(
m_host );
363 winrt::Windows::Data::Pdf::PdfDocument
m_pdf{
nullptr };
365 winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource
m_xamlSource{
nullptr };
366 winrt::Windows::UI::Xaml::Controls::Grid
m_root{
nullptr };
367 winrt::Windows::UI::Xaml::Printing::PrintDocument
m_printDoc{
nullptr };
368 winrt::Windows::Graphics::Printing::IPrintDocumentSource
m_docSrc{
nullptr };
371 winrt::Windows::Graphics::Printing::PrintManager
m_rtPM{
nullptr };
388 if( s.empty() )
return {};
390 int len = MultiByteToWideChar( CP_UTF8, 0, s.data(), (
int) s.size(),
nullptr, 0 );
391 std::wstring out( len, L
'\0' );
393 MultiByteToWideChar( CP_UTF8, 0, s.data(), (
int) s.size(), out.data(), len );
400 DWORD attrs = GetFileAttributesA( aFile.c_str() );
402 if( attrs == INVALID_FILE_ATTRIBUTES )
406 winrt::Windows::Data::Pdf::PdfDocument pdf{
nullptr };
411 auto file = winrt::Windows::Storage::StorageFile::GetFileFromPathAsync( winrt::hstring(
path ) ).get();
412 pdf = winrt::Windows::Data::Pdf::PdfDocument::LoadFromFileAsync( file ).get();
421 HWND hwndOwner = ::GetActiveWindow();
422 if( !hwndOwner ) hwndOwner = ::GetForegroundWindow();
428 return printer.Run();
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