Home | History | Annotate | Download | only in xps
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkTypes.h"
      9 #if defined(SK_BUILD_FOR_WIN)
     10 
     11 #include "SkXPSDocument.h"
     12 
     13 #include "SkHRESULT.h"
     14 #include "SkStream.h"
     15 #include "SkTScopedComPtr.h"
     16 #include "SkXPSDevice.h"
     17 
     18 #include <XpsObjectModel.h>
     19 
     20 namespace {
     21 struct SkXPSDocument final : public SkDocument {
     22     SkTScopedComPtr<IXpsOMObjectFactory> fXpsFactory;
     23     SkXPSDevice fDevice;
     24     std::unique_ptr<SkCanvas> fCanvas;
     25     SkVector fUnitsPerMeter;
     26     SkVector fPixelsPerMeter;
     27 
     28     SkXPSDocument(SkWStream*, SkScalar dpi, SkTScopedComPtr<IXpsOMObjectFactory>);
     29     ~SkXPSDocument() override;
     30     SkCanvas* onBeginPage(SkScalar w, SkScalar h) override;
     31     void onEndPage() override;
     32     void onClose(SkWStream*) override;
     33     void onAbort() override;
     34 };
     35 }
     36 
     37 SkXPSDocument::SkXPSDocument(SkWStream* stream,
     38                    SkScalar dpi,
     39                    SkTScopedComPtr<IXpsOMObjectFactory> xpsFactory)
     40         : SkDocument(stream)
     41         , fXpsFactory(std::move(xpsFactory))
     42         , fDevice(SkISize{10000, 10000})
     43 {
     44     const SkScalar kPointsPerMeter = SkDoubleToScalar(360000.0 / 127.0);
     45     fUnitsPerMeter.set(kPointsPerMeter, kPointsPerMeter);
     46     SkScalar pixelsPerMeterScale = SkDoubleToScalar(dpi * 5000.0 / 127.0);
     47     fPixelsPerMeter.set(pixelsPerMeterScale, pixelsPerMeterScale);
     48     SkASSERT(fXpsFactory);
     49     fDevice.beginPortfolio(stream, fXpsFactory.get());
     50 }
     51 
     52 SkXPSDocument::~SkXPSDocument() {
     53     // subclasses must call close() in their destructors
     54     this->close();
     55 }
     56 
     57 SkCanvas* SkXPSDocument::onBeginPage(SkScalar width, SkScalar height) {
     58     fDevice.beginSheet(fUnitsPerMeter, fPixelsPerMeter, {width, height});
     59     fCanvas.reset(new SkCanvas(sk_ref_sp(&fDevice)));
     60     return fCanvas.get();
     61 }
     62 
     63 void SkXPSDocument::onEndPage() {
     64     SkASSERT(fCanvas.get());
     65     fCanvas->flush();
     66     fCanvas.reset(nullptr);
     67     fDevice.endSheet();
     68 }
     69 
     70 void SkXPSDocument::onClose(SkWStream*) {
     71     SkASSERT(!fCanvas.get());
     72     (void)fDevice.endPortfolio();
     73 }
     74 
     75 void SkXPSDocument::onAbort() {}
     76 
     77 ///////////////////////////////////////////////////////////////////////////////
     78 
     79 sk_sp<SkDocument> SkXPS::MakeDocument(SkWStream* stream,
     80                                       IXpsOMObjectFactory* factoryPtr,
     81                                       SkScalar dpi) {
     82     SkTScopedComPtr<IXpsOMObjectFactory> factory(SkSafeRefComPtr(factoryPtr));
     83     return stream && factory
     84            ? sk_make_sp<SkXPSDocument>(stream, dpi, std::move(factory))
     85            : nullptr;
     86 }
     87 #endif  // defined(SK_BUILD_FOR_WIN)
     88