#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*, SkScalar dpi, 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,
SkScalar dpi,
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(dpi * 5000.0 / 127.0);
fPixelsPerMeter.set(pixelsPerMeterScale, pixelsPerMeterScale);
SkASSERT(fXpsFactory);
fDevice.beginPortfolio(stream, fXpsFactory.get());
}
SkXPSDocument::~SkXPSDocument() {
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,
SkScalar dpi) {
SkTScopedComPtr<IXpsOMObjectFactory> factory(SkSafeRefComPtr(factoryPtr));
return stream && factory
? sk_make_sp<SkXPSDocument>(stream, dpi, std::move(factory))
: nullptr;
}
#endif