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.
5 #ifndef CHROME_BROWSER_UI_METRO_DRIVER_PRINT_DOCUMENT_SOURCE_H_
6 #define CHROME_BROWSER_UI_METRO_DRIVER_PRINT_DOCUMENT_SOURCE_H_
8 #include <documentsource.h>
9 #include <printpreview.h>
10 #include <windows.graphics.printing.h>
14 #include "base/basictypes.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_vector.h"
17 #include "base/synchronization/condition_variable.h"
18 #include "base/synchronization/waitable_event.h"
19 #include "win8/metro_driver/winrt_utils.h"
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
;
33 namespace metro_driver
{
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
> {
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
{
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
) {
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
) {
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
;
75 // Construction / Initialization.
76 explicit PrintDocumentSource();
77 HRESULT
RuntimeClassInitialize(const DirectXContext
& directx_context
,
78 base::Lock
* parent_lock
);
79 // Aborts any pending asynchronous operation.
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
);
89 // classic COM interface IPrintPreviewPageCollection methods
90 STDMETHOD(Paginate
)(uint32 page
, IInspectable
* options
);
91 STDMETHOD(MakePage
)(uint32 desired_page
, float width
, float height
);
93 // If the screen DPI changes, we must be warned here.
94 void ResetDpi(float dpi
);
96 // When the page count is known, this is called and we can setup our data.
97 void SetPageCount(size_t page_count
);
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
);
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
);
109 // Helper function to wait for the page count to be ready.
110 // Returns 0 when aborted.
111 size_t WaitAndGetPageCount();
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
);
118 DirectXContext directx_context_
;
120 // Once page data is available, it's added to this vector.
121 std::vector
<mswr::ComPtr
<IStream
>> pages_
;
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 ScopedVector
<base::ConditionVariable
> pages_ready_state_
;
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_
;
136 // The preview target interface set from within GetPreviewPageCollection
137 // but used from within MakePage.
138 mswr::ComPtr
<IPrintPreviewDxgiPackageTarget
> dxgi_preview_target_
;
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_
;
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.
151 // The DPI is set by Windows and we need to give it to DirectX.
154 // A flag identiying that we have been aborted. Needed to properly handle
155 // asynchronous callbacks.
158 // TODO(mad): remove once we don't run mixed SDK/OS anymore.
159 bool using_old_preview_interface_
;
162 } // namespace metro_driver
164 #endif // CHROME_BROWSER_UI_METRO_DRIVER_PRINT_DOCUMENT_SOURCE_H_