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