aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/tools/PageCachingDocument.cpp
blob: 7822d55e9e39e7934293f7465d59f5efb7eb1156 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "PageCachingDocument.h"
#include "SkCanvas.h"
#include "SkDocument.h"
#include "SkPictureRecorder.h"
#include "SkRect.h"
#include "SkTDArray.h"

namespace {

typedef void (*DoneProc)(SkWStream*, bool);
typedef SkData* (*Encoder)(size_t*, const SkBitmap&);

// This class allows us to compare the relative memory consumption of
// the PDF and SkPicture backends.
class PageCachingDocument : public SkDocument {
public:
    PageCachingDocument(SkWStream*, DoneProc, Encoder, SkScalar rasterDpi);
    virtual ~PageCachingDocument();
    virtual SkCanvas* onBeginPage(SkScalar width,
                                  SkScalar height,
                                  const SkRect& content) SK_OVERRIDE;
    void onEndPage() SK_OVERRIDE;
    bool onClose(SkWStream*) SK_OVERRIDE;
    void onAbort() SK_OVERRIDE;

private:
    struct Page {
        SkScalar fWidth;
        SkScalar fHeight;
        SkAutoTUnref<SkPicture> fPic;
    };
    SkPictureRecorder fRecorder;
    SkTDArray<Page> fPages;
    Encoder fEncoder;
    SkScalar fRasterDpi;
};

PageCachingDocument::PageCachingDocument(SkWStream* stream,
                                         DoneProc done,
                                         Encoder encoder,
                                         SkScalar rasterDpi)
    : SkDocument(stream, done), fEncoder(encoder), fRasterDpi(rasterDpi) {
}

PageCachingDocument::~PageCachingDocument() {
    for (Page* p = fPages.begin(); p != fPages.end(); ++p) {
        p->~Page();
    }
}

SkCanvas* PageCachingDocument::onBeginPage(SkScalar width,
                                           SkScalar height,
                                           const SkRect& content) {
    Page* page = fPages.push();
    sk_bzero(page, sizeof(*page));
    page->fWidth = width;
    page->fHeight = height;
    SkASSERT(!page->fPic.get());
    SkCanvas* canvas = fRecorder.beginRecording(content);
    return canvas;
}

void PageCachingDocument::onEndPage() {
    SkASSERT(fPages.count() > 0);
    SkASSERT(!fPages[fPages.count() - 1].fPic);
    fPages[fPages.count() - 1].fPic.reset(fRecorder.endRecording());
}

bool PageCachingDocument::onClose(SkWStream* stream) {
    SkAutoTUnref<SkDocument> doc(
        SkDocument::CreatePDF(stream, NULL, fEncoder, fRasterDpi));
    for (Page* page = fPages.begin(); page != fPages.end(); ++page) {
        SkRect cullRect = page->fPic->cullRect();
        SkCanvas* canvas =
            doc->beginPage(page->fWidth, page->fHeight, &cullRect);
        canvas->drawPicture(page->fPic);
        doc->endPage();
    }
    return doc->close();
}

void PageCachingDocument::onAbort() {
}
}  // namespace

SkDocument* CreatePageCachingDocument(SkWStream* stream,
                                      DoneProc done,
                                      Encoder encoder,
                                      SkScalar rasterDpi) {
    return SkNEW_ARGS(PageCachingDocument, (stream, done, encoder, rasterDpi));
}