diff options
author | Michael Vrhel <michael.vrhel@artifex.com> | 2013-11-08 18:13:49 -0800 |
---|---|---|
committer | Michael Vrhel <michael.vrhel@artifex.com> | 2013-11-11 10:47:55 -0800 |
commit | 6afafa79e302e4d23b5c82182359619b59c64f6a (patch) | |
tree | f013fb415c1c7a1892c3b8f366e39671f293f033 /platform/winrt/mupdf_cpp/PrintPage.cpp | |
parent | 7570e7fa8a40cb41db6a1ab14b225cf00c4f56f5 (diff) | |
download | mupdf-6afafa79e302e4d23b5c82182359619b59c64f6a.tar.xz |
DirectX printing added
After much research it was determined that use of the DirectX 2D methods is the proper way
to add printing support to a Windows 8 application. This enables the pages to be rendered
as they are requested by the print thread. This occurs for both the print preview screen
as well as the print to the output device.
Diffstat (limited to 'platform/winrt/mupdf_cpp/PrintPage.cpp')
-rw-r--r-- | platform/winrt/mupdf_cpp/PrintPage.cpp | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/platform/winrt/mupdf_cpp/PrintPage.cpp b/platform/winrt/mupdf_cpp/PrintPage.cpp new file mode 100644 index 00000000..5e14f191 --- /dev/null +++ b/platform/winrt/mupdf_cpp/PrintPage.cpp @@ -0,0 +1,165 @@ +#include "pch.h" +#include "PrintPage.h" + +using namespace Microsoft::WRL; +using namespace Windows::Graphics::Printing; + +#pragma region IDocumentPageSource Methods + +/* This is the interface to the print thread calls */ +IFACEMETHODIMP +PrintPages::GetPreviewPageCollection(IPrintDocumentPackageTarget* doc_target, + IPrintPreviewPageCollection** doc_collection) +{ + HRESULT hr = (doc_target != nullptr) ? S_OK : E_INVALIDARG; + + if (SUCCEEDED(hr)) + { + hr = doc_target->GetPackageTarget(ID_PREVIEWPACKAGETARGET_DXGI, + IID_PPV_ARGS(&m_dxgi_previewtarget)); + } + ComPtr<IPrintPreviewPageCollection> page_collection; + if (SUCCEEDED(hr)) + { + ComPtr<PrintPages> docSource(this); + hr = docSource.As<IPrintPreviewPageCollection>(&page_collection); + } + if (SUCCEEDED(hr)) + hr = page_collection.CopyTo(doc_collection); + + if (SUCCEEDED(hr)) + this->m_renderer->SetPrintTarget((void*) this); + return hr; +} + +IFACEMETHODIMP +PrintPages::MakeDocument(IInspectable* doc_options, IPrintDocumentPackageTarget* doc_target) +{ + if (doc_options == nullptr || doc_target == nullptr) + return E_INVALIDARG; + + PrintTaskOptions^ option = reinterpret_cast<PrintTaskOptions^>(doc_options); + PrintPageDescription page_desc = option->GetPageDescription(1); + + D2D1_PRINT_CONTROL_PROPERTIES print_properties; + + print_properties.rasterDPI = (float)(min(page_desc.DpiX, page_desc.DpiY)); + print_properties.colorSpace = D2D1_COLOR_SPACE_SRGB; + print_properties.fontSubset = D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT; + + HRESULT hr = S_OK; + + try + { + m_renderer->CreatePrintControl(doc_target, &print_properties); + + D2D1_RECT_F imageableRect = D2D1::RectF(page_desc.ImageableRect.X, + page_desc.ImageableRect.Y, + page_desc.ImageableRect.X + page_desc.ImageableRect.Width, + page_desc.ImageableRect.Y + page_desc.ImageableRect.Height); + + D2D1_SIZE_F pageSize = D2D1::SizeF(page_desc.PageSize.Width, page_desc.PageSize.Height); + m_totalpages = m_renderer->GetPrintPageCount(); + + for (uint32 page_num = 1; page_num <= m_totalpages; ++page_num) + m_renderer->PrintPage(page_num, imageableRect, pageSize, page_desc.DpiX, nullptr); + } + catch (Platform::Exception^ e) + { + hr = e->HResult; + } + + HRESULT hrClose = m_renderer->ClosePrintControl(); + if (SUCCEEDED(hr)) + { + hr = hrClose; + } + return hr; +} + +#pragma endregion IDocumentPageSource Methods + +#pragma region IPrintPreviewPageCollection Methods + +IFACEMETHODIMP +PrintPages::Paginate(uint32 current_jobpage, IInspectable* doc_options) +{ + HRESULT hr = (doc_options != nullptr) ? S_OK : E_INVALIDARG; + + if (SUCCEEDED(hr)) + { + PrintTaskOptions^ option = reinterpret_cast<PrintTaskOptions^>(doc_options); + PrintPageDescription page_desc = option->GetPageDescription(current_jobpage); + + hr = m_dxgi_previewtarget->InvalidatePreview(); + m_totalpages = m_renderer->GetPrintPageCount(); + + if (SUCCEEDED(hr)) + hr = m_dxgi_previewtarget->SetJobPageCount(PageCountType::FinalPageCount, m_totalpages); + + if (SUCCEEDED(hr)) + { + m_width = page_desc.PageSize.Width; + m_height = page_desc.PageSize.Height; + m_imageable_rect = D2D1::RectF(page_desc.ImageableRect.X, page_desc.ImageableRect.Y, + page_desc.ImageableRect.X + page_desc.ImageableRect.Width, + page_desc.ImageableRect.Y + page_desc.ImageableRect.Height); + m_paginate_called = true; + } + } + return hr; +} + +float +PrintPages::TransformedPageSize(float desired_width, float desired_height, + Windows::Foundation::Size* preview_size) +{ + float scale = 1.0f; + + if (desired_width > 0 && desired_height > 0) + { + preview_size->Width = desired_width; + preview_size->Height = desired_height; + scale = m_width / desired_width; + } + else + { + preview_size->Width = 0; + preview_size->Height = 0; + } + return scale; +} + +void +PrintPages::ResetPreview() +{ + m_dxgi_previewtarget->InvalidatePreview(); +} + +IFACEMETHODIMP +PrintPages::MakePage(uint32 desired_jobpage, float width, float height) +{ + HRESULT hr = (width > 0 && height > 0) ? S_OK : E_INVALIDARG; + + if (desired_jobpage == JOB_PAGE_APPLICATION_DEFINED && m_paginate_called) + desired_jobpage = 1; + + if (SUCCEEDED(hr) && m_paginate_called) + { + Windows::Foundation::Size preview_size; + float scale = TransformedPageSize(width, height, &preview_size); + + try + { + m_renderer->DrawPreviewSurface(preview_size.Width, preview_size.Height, + scale, m_imageable_rect, desired_jobpage, + m_dxgi_previewtarget.Get()); + } + catch (Platform::Exception^ e) + { + hr = e->HResult; + } + } + return hr; +} +#pragma region IPrintPreviewPageCollection Methods |