blob: 86a2502ea99c9de084e6183159f67aa02aa16547 [file] [log] [blame] [edit]
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkTypes.h"
#if defined(SK_BUILD_FOR_WIN)
#include "include/docs/SkXPSDocument.h"
#include "include/core/SkStream.h"
#include "src/utils/win/SkHRESULT.h"
#include "src/utils/win/SkTScopedComPtr.h"
#include "src/xps/SkXPSDevice.h"
#include <XpsObjectModel.h>
namespace {
struct SkXPSDocument final : public SkDocument {
SkTScopedComPtr<IXpsOMObjectFactory> fXpsFactory;
SkXPSDevice fDevice;
std::unique_ptr<SkCanvas> fCanvas;
SkVector fUnitsPerMeter;
SkVector fPixelsPerMeter;
SkXPSDocument(SkWStream*, SkXPS::Options opts, SkTScopedComPtr<IXpsOMObjectFactory>);
~SkXPSDocument() override;
SkCanvas* onBeginPage(SkScalar w, SkScalar h) override;
void onEndPage() override;
void onClose(SkWStream*) override;
void onAbort() override;
};
}
SkXPSDocument::SkXPSDocument(SkWStream* stream,
SkXPS::Options opts,
SkTScopedComPtr<IXpsOMObjectFactory> xpsFactory)
: SkDocument(stream)
, fXpsFactory(std::move(xpsFactory))
, fDevice(SkISize{10000, 10000}, {}) {
const SkScalar kPointsPerMeter = SkDoubleToScalar(360000.0 / 127.0);
fUnitsPerMeter.set(kPointsPerMeter, kPointsPerMeter);
SkScalar pixelsPerMeterScale = SkDoubleToScalar(opts.dpi * 5000.0 / 127.0);
fPixelsPerMeter.set(pixelsPerMeterScale, pixelsPerMeterScale);
SkASSERT(fXpsFactory);
if (!opts.pngEncoder) {
if (!opts.allowNoPngs) {
SK_ABORT("Must set a PNG encoder to make XPS documents");
}
}
fDevice.beginPortfolio(stream, fXpsFactory.get());
}
SkXPSDocument::~SkXPSDocument() {
// subclasses must call close() in their destructors
this->close();
}
SkCanvas* SkXPSDocument::onBeginPage(SkScalar width, SkScalar height) {
fDevice.beginSheet(fUnitsPerMeter, fPixelsPerMeter, {width, height});
fCanvas.reset(new SkCanvas(sk_ref_sp(&fDevice)));
return fCanvas.get();
}
void SkXPSDocument::onEndPage() {
SkASSERT(fCanvas.get());
fCanvas.reset(nullptr);
fDevice.endSheet();
}
void SkXPSDocument::onClose(SkWStream*) {
SkASSERT(!fCanvas.get());
(void)fDevice.endPortfolio();
}
void SkXPSDocument::onAbort() {}
///////////////////////////////////////////////////////////////////////////////
sk_sp<SkDocument> SkXPS::MakeDocument(SkWStream* stream,
IXpsOMObjectFactory* factoryPtr,
Options opts) {
SkTScopedComPtr<IXpsOMObjectFactory> factory(SkSafeRefComPtr(factoryPtr));
return stream && factory ? sk_make_sp<SkXPSDocument>(stream, opts, std::move(factory))
: nullptr;
}
#endif // defined(SK_BUILD_FOR_WIN)