aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/PdfViewer/src/SkPdfContext.cpp
blob: 038d38e84e32565932bade713856ea153cdf7f7a (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPdfContext.h"
#include "SkPdfNativeDoc.h"
#include "SkPdfReporter.h"
#include "SkPdfTokenLooper.h"

///////////////////////////////////////////////////////////////////////////////

class PdfMainLooper : public SkPdfTokenLooper {
public:
    PdfMainLooper(SkPdfNativeTokenizer* tokenizer,
                  SkPdfContext* pdfContext,
                  SkCanvas* canvas)
        : INHERITED(tokenizer, pdfContext, canvas) {}

    SkPdfResult consumeToken(PdfToken& token) SK_OVERRIDE;
    void loop() SK_OVERRIDE;

private:
    typedef SkPdfTokenLooper INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

SkPdfContext::SkPdfContext(SkPdfNativeDoc* doc)
    : fPdfDoc(doc)
{
    SkASSERT(fPdfDoc != NULL);
}

void SkPdfContext::parseStream(SkPdfNativeObject* stream, SkCanvas* canvas) {
    if (NULL == stream) {
        // Nothing to parse.
        return;
    }

    SkPdfNativeTokenizer tokenizer(stream, &fTmpPageAllocator, fPdfDoc);
    PdfMainLooper looper(&tokenizer, this, canvas);
    looper.loop();
}

///////////////////////////////////////////////////////////////////////////////

// FIXME (scroggo): This probably belongs in a debugging file.
// For reportRenderStats declaration.
#include "SkPdfRenderer.h"

// Temp code to measure what operands fail.
template <typename T> class SkTDictWithDefaultConstructor : public SkTDict<T> {
public:
    SkTDictWithDefaultConstructor() : SkTDict<T>(10) {}
};

SkTDictWithDefaultConstructor<int> gRenderStats[kCount_SkPdfResult];

const char* gRenderStatsNames[kCount_SkPdfResult] = {
    "Success",
    "Partially implemented",
    "Not yet implemented",
    "Ignore Error",
    "Error",
    "Unsupported/Unknown"
};

// Declared in SkPdfRenderer.h. Should be moved to a central debugging location.
void reportPdfRenderStats() {
    for (int i = 0 ; i < kCount_SkPdfResult; i++) {
        SkTDict<int>::Iter iter(gRenderStats[i]);
        const char* key;
        int value = 0;
        while ((key = iter.next(&value)) != NULL) {
            SkDebugf("%s: %s -> count %i\n", gRenderStatsNames[i], key, value);
        }
    }
}

#include "SkPdfOps.h"

SkPdfResult PdfMainLooper::consumeToken(PdfToken& token) {
    if (token.fType == kKeyword_TokenType && token.fKeywordLength < 256)
    {
        PdfOperatorRenderer pdfOperatorRenderer = NULL;
        if (gPdfOps.find(token.fKeyword, token.fKeywordLength, &pdfOperatorRenderer) &&
                    pdfOperatorRenderer) {
            // Main work is done by pdfOperatorRenderer(...)
            SkPdfResult result = pdfOperatorRenderer(fPdfContext, fCanvas, this);

            int cnt = 0;
            gRenderStats[result].find(token.fKeyword, token.fKeywordLength, &cnt);
            gRenderStats[result].set(token.fKeyword, token.fKeywordLength, cnt + 1);
        } else {
            int cnt = 0;
            gRenderStats[kUnsupported_SkPdfResult].find(token.fKeyword,
                                                        token.fKeywordLength,
                                                        &cnt);
            gRenderStats[kUnsupported_SkPdfResult].set(token.fKeyword,
                                                       token.fKeywordLength,
                                                       cnt + 1);
        }
    }
    else if (token.fType == kObject_TokenType)
    {
        fPdfContext->fObjectStack.push( token.fObject );
    }
    else {
        // TODO(edisonn): store the keyword as a object, so we can track the location in file,
        //                and report where the error was triggered
        SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, token.fKeyword, NULL,
                    fPdfContext);
        return kIgnoreError_SkPdfResult;
    }
    return kOK_SkPdfResult;
}

void PdfMainLooper::loop() {
    PdfToken token;
    while (fTokenizer->readToken(&token, true)) {
        this->consumeToken(token);
    }
}