15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "stdafx.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "win8/metro_driver/print_document_source.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.graphics.display.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/numerics/safe_conversions.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class D2DFactoryAutoLock { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit D2DFactoryAutoLock(ID2D1Factory* d2d_factory) { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = d2d_factory->QueryInterface(IID_PPV_ARGS(&d2d_multithread_)); 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (d2d_multithread_.Get()) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_multithread_->Enter(); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Failed to QI for ID2D1Multithread " << std::hex << hr; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~D2DFactoryAutoLock() { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (d2d_multithread_.Get()) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_multithread_->Leave(); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1Multithread> d2d_multithread_; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(mad): remove once we don't run mixed SDK/OS anymore. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GUID kOldPackageTargetGuid = 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {0xfb2a33c0, 0x8c35, 0x465f, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {0xbe, 0xd5, 0x9f, 0x36, 0x89, 0x51, 0x77, 0x52}}; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GUID kNewPackageTargetGuid = 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {0x1a6dd0ad, 0x1e2a, 0x4e99, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {0xa5, 0xba, 0x91, 0xf1, 0x78, 0x18, 0x29, 0x0e}}; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace metro_driver { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintDocumentSource::PrintDocumentSource() 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : page_count_ready_(true, false), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_lock_(NULL), 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) height_(0), 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width_(0), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dpi_(96), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aborted_(false), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using_old_preview_interface_(false) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT PrintDocumentSource::RuntimeClassInitialize( 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DirectXContext& directx_context, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock* parent_lock) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(parent_lock != NULL); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(directx_context.d2d_context.Get() != NULL); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(directx_context.d2d_device.Get() != NULL); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(directx_context.d2d_factory.Get() != NULL); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(directx_context.d3d_device.Get() != NULL); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(directx_context.wic_factory.Get() != NULL); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directx_context_ = directx_context; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No other method can be called before RuntimeClassInitialize which is called 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // during the construction via mswr::MakeAndInitialize(), so it's safe for all 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other methods to use the parent_lock_ without checking if it's NULL. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(parent_lock_ == NULL); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_lock_ = parent_lock; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintDocumentSource::Abort() { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(*parent_lock_); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aborted_ = true; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_count_ready_.IsSignaled()) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pages_.clear(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < pages_ready_state_.size(); ++i) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pages_ready_state_[i]->Broadcast(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pages_.empty() && pages_ready_state_.empty()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP PrintDocumentSource::GetPreviewPageCollection( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPrintDocumentPackageTarget* package_target, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPrintPreviewPageCollection** page_collection) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(package_target != NULL); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(page_collection != NULL); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = package_target->GetPackageTarget( 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __uuidof(IPrintPreviewDxgiPackageTarget), 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IID_PPV_ARGS(&dxgi_preview_target_)); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mad): remove once we don't run mixed SDK/OS anymore. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The IID changed from one version of the SDK to another, so try the other 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one in case we are running a build from a different SDK than the one 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // related to the OS version we are running. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GUID package_target_uuid = kNewPackageTargetGuid; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (package_target_uuid == __uuidof(IPrintPreviewDxgiPackageTarget)) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package_target_uuid = kOldPackageTargetGuid; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using_old_preview_interface_ = true; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = package_target->GetPackageTarget(package_target_uuid, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package_target_uuid, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dxgi_preview_target_); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to get IPrintPreviewDXGIPackageTarget " << std::hex 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << hr; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using_old_preview_interface_ = (__uuidof(IPrintPreviewDxgiPackageTarget) == 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kOldPackageTargetGuid); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<IPrintPreviewPageCollection> preview_page_collection; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<PrintDocumentSource> print_document_source(this); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = print_document_source.As(&preview_page_collection); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to get preview_page_collection " << std::hex << hr; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = preview_page_collection.CopyTo(page_collection); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to copy preview_page_collection " << std::hex << hr; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP PrintDocumentSource::MakeDocument( 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IInspectable* options, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPrintDocumentPackageTarget* package_target) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(options != NULL); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(package_target != NULL); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<wingfx::Printing::IPrintTaskOptionsCore> print_task_options; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = options->QueryInterface( 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wingfx::Printing::IID_IPrintTaskOptionsCore, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void**>(print_task_options.GetAddressOf())); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to QI for IPrintTaskOptionsCore " << std::hex << hr; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the first page's description for the whole document. Page numbers 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are 1-based in this context. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mad): Check if it would be useful to use per page descriptions. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wingfx::Printing::PrintPageDescription page_desc = {}; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = print_task_options->GetPageDescription(1 /* page */, &page_desc); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to GetPageDescription " << std::hex << hr; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D2D1_PRINT_CONTROL_PROPERTIES print_control_properties; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_desc.DpiX > page_desc.DpiY) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_control_properties.rasterDPI = static_cast<float>(page_desc.DpiY); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_control_properties.rasterDPI = static_cast<float>(page_desc.DpiX); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Color space for vector graphics in D2D print control. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_control_properties.colorSpace = D2D1_COLOR_SPACE_SRGB; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_control_properties.fontSubset = D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1PrintControl> print_control; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = directx_context_.d2d_device->CreatePrintControl( 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directx_context_.wic_factory.Get(), 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package_target, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_control_properties, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_control.GetAddressOf()); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to CreatePrintControl " << std::hex << hr; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D2D1_SIZE_F page_size = D2D1::SizeF(page_desc.PageSize.Width, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_desc.PageSize.Height); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the number of pages to be available. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If an abort occured, we'll get 0 and won't enter the loop below. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t page_count = WaitAndGetPageCount(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1GdiMetafile> gdi_metafile; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t page = 0; page < page_count; ++page) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdi_metafile.Reset(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = WaitAndGetPage(page, gdi_metafile.GetAddressOf()); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, FAILED(hr)) << "Failed to get page's metafile " << std::hex 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << hr; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // S_FALSE means we got aborted. 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hr == S_FALSE || FAILED(hr)) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = PrintPage(print_control.Get(), gdi_metafile.Get(), page_size); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT close_hr = print_control->Close(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(close_hr) && SUCCEEDED(hr)) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return close_hr; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP PrintDocumentSource::Paginate(uint32 page, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IInspectable* options) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ << ", page = " << page; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(options != NULL); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetPreviewPageCollection must have been successfuly called. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(dxgi_preview_target_.Get() != NULL); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get print settings from PrintTaskOptions for preview, such as page 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // description, which contains page size, imageable area, DPI. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mad): obtain other print settings in the same way, such as ColorMode, 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NumberOfCopies, etc... 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<wingfx::Printing::IPrintTaskOptionsCore> print_options; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = options->QueryInterface( 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wingfx::Printing::IID_IPrintTaskOptionsCore, 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void**>(print_options.GetAddressOf())); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to QI for IPrintTaskOptionsCore " << std::hex << hr; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wingfx::Printing::PrintPageDescription page_desc = {}; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = print_options->GetPageDescription(1 /* page */, &page_desc); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to GetPageDescription " << std::hex << hr; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width_ = page_desc.PageSize.Width; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) height_ = page_desc.PageSize.Height; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = dxgi_preview_target_->InvalidatePreview(); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to InvalidatePreview " << std::hex << hr; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t page_count = WaitAndGetPageCount(); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A page_count of 0 means abort... 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_count == 0) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_FALSE; 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hr = dxgi_preview_target_->SetJobPageCount( 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PageCountType::FinalPageCount, 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::checked_cast<UINT32>(page_count)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to SetJobPageCount " << std::hex << hr; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP PrintDocumentSource::MakePage(uint32 job_page, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float width, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float height) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ << ", width: " << width << ", height: " << height 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", job_page: " << job_page; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(width > 0 && height > 0); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Paginate must have been called before this. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (width_ <= 0.0 || height_ <= 0.0) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_FALSE; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When job_page is JOB_PAGE_APPLICATION_DEFINED, it means a new preview 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // begins. TODO(mad): Double check if we need to cancel pending resources. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (job_page == JOB_PAGE_APPLICATION_DEFINED) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_page = 1; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winfoundtn::Size preview_size; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preview_size.Width = width; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preview_size.Height = height; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float scale = width_ / width; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1Factory> factory; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directx_context_.d2d_device->GetFactory(&factory); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1GdiMetafile> gdi_metafile; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = WaitAndGetPage(job_page - 1, gdi_metafile.GetAddressOf()); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, FAILED(hr)) << "Failed to get page's metafile " << std::hex 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << hr; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Again, S_FALSE means we got aborted. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hr == S_FALSE || FAILED(hr)) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are accessing D3D resources directly without D2D's knowledge, so we 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must manually acquire the D2D factory lock. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D2DFactoryAutoLock factory_lock(directx_context_.d2d_factory.Get()); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CD3D11_TEXTURE2D_DESC texture_desc( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DXGI_FORMAT_B8G8R8A8_UNORM, 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<UINT32>(ceil(width * dpi_ / 96)), 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<UINT32>(ceil(height * dpi_ / 96)), 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID3D11Texture2D> texture; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = directx_context_.d3d_device->CreateTexture2D( 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &texture_desc, NULL, &texture); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to create a 2D texture " << std::hex << hr; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<IDXGISurface> dxgi_surface; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = texture.As<IDXGISurface>(&dxgi_surface); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to QI for IDXGISurface " << std::hex << hr; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // D2D device contexts are stateful, and hence a unique device context must 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be used on each call. 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1DeviceContext> d2d_context; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = directx_context_.d2d_device->CreateDeviceContext( 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &d2d_context); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_context->SetDpi(dpi_, dpi_); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1Bitmap1> d2dSurfaceBitmap; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = d2d_context->CreateBitmapFromDxgiSurface(dxgi_surface.Get(), 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // default properties. 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &d2dSurfaceBitmap); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to CreateBitmapFromDxgiSurface " << std::hex << hr; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_context->SetTarget(d2dSurfaceBitmap.Get()); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_context->BeginDraw(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_context->Clear(); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_context->SetTransform(D2D1::Matrix3x2F(1/scale, 0, 0, 1/scale, 0, 0)); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_context->DrawGdiMetafile(gdi_metafile.Get()); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = d2d_context->EndDraw(); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to EndDraw " << std::hex << hr; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(mad): remove once we don't run mixed SDK/OS anymore. 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __IPrintPreviewDxgiPackageTarget_FWD_DEFINED__ 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLOAT dpi = dpi_; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (using_old_preview_interface_) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We compiled with the new API but run on the old OS, so we must cheat 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and send something that looks like a float but has a UINT32 value. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *reinterpret_cast<UINT32*>(&dpi) = static_cast<UINT32>(dpi_); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT32 dpi = static_cast<UINT32>(dpi_); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!using_old_preview_interface_) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We compiled with the old API but run on the new OS, so we must cheat 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and send something that looks like a UINT32 but has a float value. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *reinterpret_cast<FLOAT*>(&dpi) = dpi_; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // __IPrintPreviewDxgiPackageTarget_FWD_DEFINED__ 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = dxgi_preview_target_->DrawPage(job_page, dxgi_surface.Get(), dpi, dpi); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to DrawPage " << std::hex << hr; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintDocumentSource::ResetDpi(float dpi) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(*parent_lock_); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dpi == dpi_) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dpi_ = dpi; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directx_context_.d2d_context->SetDpi(dpi, dpi); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintDocumentSource::SetPageCount(size_t page_count) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(page_count > 0); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(*parent_lock_); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!page_count_ready_.IsSignaled()); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pages_.empty() && pages_ready_state_.empty()); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pages_.resize(page_count); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pages_ready_state_.resize(page_count); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < page_count; ++i) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pages_ready_state_[i].reset(new base::ConditionVariable(parent_lock_)); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_count_ready_.Signal(); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintDocumentSource::AddPage(size_t page_number, 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* metafile_stream) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(metafile_stream != NULL); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(*parent_lock_); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(page_count_ready_.IsSignaled()); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(page_number < pages_.size()); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pages_[page_number] = metafile_stream; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pages_ready_state_[page_number]->Signal(); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT PrintDocumentSource::PrintPage(ID2D1PrintControl* print_control, 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ID2D1GdiMetafile* gdi_metafile, 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D2D1_SIZE_F page_size) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ << ", page_size: (" << page_size.width << ", " 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << page_size.height << ")"; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(print_control != NULL); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(gdi_metafile != NULL); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // D2D device contexts are stateful, and hence a unique device context must 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be used on each call. 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1DeviceContext> d2d_context; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = directx_context_.d2d_device->CreateDeviceContext( 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &d2d_context); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to CreateDeviceContext " << std::hex << hr; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1CommandList> print_command_list; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = d2d_context->CreateCommandList(&print_command_list); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to CreateCommandList " << std::hex << hr; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_context->SetTarget(print_command_list.Get()); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_context->BeginDraw(); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d2d_context->DrawGdiMetafile(gdi_metafile); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = d2d_context->EndDraw(); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, FAILED(hr)) << "Failed to EndDraw " << std::hex << hr; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure to always close the command list. 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT close_hr = print_command_list->Close(); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, FAILED(close_hr)) << "Failed to close command list " << std::hex 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << hr; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr) && SUCCEEDED(close_hr)) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = print_control->AddPage(print_command_list.Get(), page_size, NULL); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return close_hr; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t PrintDocumentSource::WaitAndGetPageCount() { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Properly protect the wait/access to the page count. 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(*parent_lock_); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (aborted_) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pages_.size() == pages_ready_state_.size()); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pages_.empty()) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pages_.size(); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_count_ready_.Wait(); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(*parent_lock_); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!aborted_) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pages_.size() == pages_ready_state_.size()); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pages_.size(); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A page count of 0 means abort. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT PrintDocumentSource::WaitAndGetPage(size_t page_number, 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ID2D1GdiMetafile** gdi_metafile) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Properly protect the wait/access to the page data. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(*parent_lock_); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we weren't canceled before getting here. 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And the page count should have been received before we get here too. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (aborted_) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_FALSE; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We shouldn't be asked for a page until we got the page count. 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(page_count_ready_.IsSignaled()); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(page_number <= pages_ready_state_.size()); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pages_.size() == pages_ready_state_.size()); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!aborted_ && pages_[page_number].Get() == NULL) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pages_ready_state_[page_number]->Wait(); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we weren't aborted while we waited unlocked. 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (aborted_) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_FALSE; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(page_number < pages_.size()); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1Factory> factory; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directx_context_.d2d_device->GetFactory(&factory); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID2D1Factory1> factory1; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = factory.As(&factory1); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to QI for ID2D1Factory1 " << std::hex << hr; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULARGE_INTEGER result; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LARGE_INTEGER seek_pos; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) seek_pos.QuadPart = 0; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = pages_[page_number]->Seek(seek_pos, STREAM_SEEK_SET, &result); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to Seek page stream " << std::hex << hr; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = factory1->CreateGdiMetafile(pages_[page_number].Get(), gdi_metafile); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to CreateGdiMetafile " << std::hex << hr; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace metro_driver 528