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 "SkDocument.h"
9#include "SkXPSDevice.h"
10#include "SkStream.h"
11
12class SkDocument_XPS : public SkDocument {
13public:
14    SkDocument_XPS(SkWStream* stream,
15                   void (*doneProc)(SkWStream*, bool),
16                   SkScalar dpi)
17        : SkDocument(stream, doneProc) {
18        const SkScalar kPointsPerMeter = SkDoubleToScalar(360000.0 / 127.0);
19        fUnitsPerMeter.set(kPointsPerMeter, kPointsPerMeter);
20        SkScalar pixelsPerMeterScale = SkDoubleToScalar(dpi * 5000.0 / 127.0);
21        fPixelsPerMeter.set(pixelsPerMeterScale, pixelsPerMeterScale);
22        fDevice.beginPortfolio(stream);
23    }
24
25    virtual ~SkDocument_XPS() {
26        // subclasses must call close() in their destructors
27        this->close();
28    }
29
30protected:
31    SkCanvas* onBeginPage(SkScalar width,
32                          SkScalar height,
33                          const SkRect& trimBox) override {
34        fDevice.beginSheet(fUnitsPerMeter, fPixelsPerMeter,
35                           SkSize::Make(width, height));
36        fCanvas.reset(SkNEW_ARGS(SkCanvas, (&fDevice)));
37        fCanvas->clipRect(trimBox);
38        fCanvas->translate(trimBox.x(), trimBox.y());
39        return fCanvas.get();
40    }
41
42    void onEndPage() override {
43        SkASSERT(fCanvas.get());
44        fCanvas->flush();
45        fCanvas.reset(NULL);
46        fDevice.endSheet();
47    }
48
49    bool onClose(SkWStream*) override {
50        SkASSERT(!fCanvas.get());
51        return fDevice.endPortfolio();
52    }
53
54    void onAbort() override {}
55
56private:
57    SkXPSDevice fDevice;
58    SkAutoTUnref<SkCanvas> fCanvas;
59    SkVector fUnitsPerMeter;
60    SkVector fPixelsPerMeter;
61};
62
63///////////////////////////////////////////////////////////////////////////////
64
65SkDocument* SkDocument::CreateXPS(SkWStream* stream, SkScalar dpi) {
66    return stream ? SkNEW_ARGS(SkDocument_XPS, (stream, NULL, dpi)) : NULL;
67}
68
69static void delete_wstream(SkWStream* stream, bool aborted) {
70    SkDELETE(stream);
71}
72
73SkDocument* SkDocument::CreateXPS(const char path[], SkScalar dpi) {
74    SkAutoTDelete<SkFILEWStream> stream(SkNEW_ARGS(SkFILEWStream, (path)));
75    if (!stream->isValid()) {
76        return NULL;
77    }
78    return SkNEW_ARGS(SkDocument_XPS, (stream.detach(), delete_wstream, dpi));
79}
80