1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_UI_METRO_DRIVER_PRINT_DOCUMENT_SOURCE_H_ 6 #define CHROME_BROWSER_UI_METRO_DRIVER_PRINT_DOCUMENT_SOURCE_H_ 7 8 #include <documentsource.h> 9 #include <printpreview.h> 10 #include <windows.graphics.printing.h> 11 12 #include <vector> 13 14 #include "base/basictypes.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "base/synchronization/condition_variable.h" 18 #include "base/synchronization/waitable_event.h" 19 #include "win8/metro_driver/winrt_utils.h" 20 21 // Hack to be removed once we don't need to build with an SDK earlier than 22 // 8441 where the name of the interface has been changed. 23 // TODO(mad): remove once we don't run mixed SDK/OS anymore. 24 #ifndef __IPrintPreviewDxgiPackageTarget_FWD_DEFINED__ 25 typedef IPrintPreviewDXGIPackageTarget IPrintPreviewDxgiPackageTarget; 26 #endif 27 28 29 namespace base { 30 class Lock; 31 }; // namespace base 32 33 namespace metro_driver { 34 35 // This class is given to Metro as a source for print documents. 36 // The methodless IPrintDocumentSource interface is used to identify it as such. 37 // Then, the other interfaces are used to generate preview and print documents. 38 // It also exposes a few methods for the print handler to control the document. 39 class PrintDocumentSource 40 : public mswr::RuntimeClass< 41 mswr::RuntimeClassFlags<mswr::WinRtClassicComMix>, 42 wingfx::Printing::IPrintDocumentSource, 43 IPrintDocumentPageSource, 44 IPrintPreviewPageCollection> { 45 public: 46 // A set of interfaces for the DirectX context that our parent owns 47 // and that don't need to change from document to document. 48 struct DirectXContext { 49 DirectXContext() {} 50 DirectXContext(ID3D11Device1* device_3d, 51 ID2D1Factory1* factory_2d, 52 ID2D1Device* device_2d, 53 ID2D1DeviceContext* context_2d, 54 IWICImagingFactory2* factory_wic) 55 : d3d_device(device_3d), 56 d2d_factory(factory_2d), 57 d2d_device(device_2d), 58 d2d_context(context_2d), 59 wic_factory(factory_wic) { 60 } 61 DirectXContext(const DirectXContext& other) 62 : d3d_device(other.d3d_device), 63 d2d_factory(other.d2d_factory), 64 d2d_device(other.d2d_device), 65 d2d_context(other.d2d_context), 66 wic_factory(other.wic_factory) { 67 } 68 mswr::ComPtr<ID3D11Device1> d3d_device; 69 mswr::ComPtr<ID2D1Factory1> d2d_factory; 70 mswr::ComPtr<ID2D1Device> d2d_device; 71 mswr::ComPtr<ID2D1DeviceContext> d2d_context; 72 mswr::ComPtr<IWICImagingFactory2> wic_factory; 73 }; 74 75 // Construction / Initialization. 76 explicit PrintDocumentSource(); 77 HRESULT RuntimeClassInitialize(const DirectXContext& directx_context, 78 base::Lock* parent_lock); 79 // Aborts any pending asynchronous operation. 80 void Abort(); 81 82 // classic COM interface IPrintDocumentPageSource methods 83 STDMETHOD(GetPreviewPageCollection) ( 84 IPrintDocumentPackageTarget* package_target, 85 IPrintPreviewPageCollection** page_collection); 86 STDMETHOD(MakeDocument)(IInspectable* options, 87 IPrintDocumentPackageTarget* package_target); 88 89 // classic COM interface IPrintPreviewPageCollection methods 90 STDMETHOD(Paginate)(uint32 page, IInspectable* options); 91 STDMETHOD(MakePage)(uint32 desired_page, float width, float height); 92 93 // If the screen DPI changes, we must be warned here. 94 void ResetDpi(float dpi); 95 96 // When the page count is known, this is called and we can setup our data. 97 void SetPageCount(size_t page_count); 98 99 // Every time a page is ready, this is called and we can read the data if 100 // we were waiting for it, or store it for later use. 101 void AddPage(size_t page_number, IStream* metafile_stream); 102 103 private: 104 // Print the page given in the metafile stream to the given print control. 105 HRESULT PrintPage(ID2D1PrintControl* print_control, 106 ID2D1GdiMetafile* metafile_stream, 107 D2D1_SIZE_F pageSize); 108 109 // Helper function to wait for the page count to be ready. 110 // Returns 0 when aborted. 111 size_t WaitAndGetPageCount(); 112 113 // Helper function to wait for a given page to be ready. 114 // Returns S_FALSE when aborted. 115 HRESULT WaitAndGetPage(size_t page_number, 116 ID2D1GdiMetafile** metafile_stream); 117 118 DirectXContext directx_context_; 119 120 // Once page data is available, it's added to this vector. 121 std::vector<mswr::ComPtr<IStream>> pages_; 122 123 // When page count is set, the size of this vector is set to that number. 124 // Then, every time page data is added to pages_, the associated condition 125 // variable in this vector is signaled. This is only filled when we receive 126 // the page count, so we must wait on page_count_ready_ before accessing 127 // the content of this vector. 128 std::vector<scoped_ptr<base::ConditionVariable> > pages_ready_state_; 129 130 // This event is signaled when we receive a page count from Chrome. We should 131 // not receive any page data before the count, so we can check this event 132 // while waiting for pages too, in case we ask for page data before we got 133 // the count, so before we properly initialized pages_ready_state_. 134 base::WaitableEvent page_count_ready_; 135 136 // The preview target interface set from within GetPreviewPageCollection 137 // but used from within MakePage. 138 mswr::ComPtr<IPrintPreviewDxgiPackageTarget> dxgi_preview_target_; 139 140 // Our parent's lock (to make sure it is initialized and destroyed early 141 // enough), which we use to protect access to our data members. 142 base::Lock* parent_lock_; 143 144 // The width/height requested in Paginate and used in MakePage. 145 // TODO(mad): Height is currently not used, and width is only used for 146 // scaling. We need to add a way to specify width and height when we request 147 // pages from Chrome. 148 float height_; 149 float width_; 150 151 // The DPI is set by Windows and we need to give it to DirectX. 152 float dpi_; 153 154 // A flag identiying that we have been aborted. Needed to properly handle 155 // asynchronous callbacks. 156 bool aborted_; 157 158 // TODO(mad): remove once we don't run mixed SDK/OS anymore. 159 bool using_old_preview_interface_; 160 }; 161 162 } // namespace metro_driver 163 164 #endif // CHROME_BROWSER_UI_METRO_DRIVER_PRINT_DOCUMENT_SOURCE_H_ 165