Home | History | Annotate | Download | only in metro_driver
      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