• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 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 "SkPdfContext.h"
9 #include "SkPdfNativeDoc.h"
10 #include "SkPdfReporter.h"
11 #include "SkPdfTokenLooper.h"
12 
13 ///////////////////////////////////////////////////////////////////////////////
14 
15 class PdfMainLooper : public SkPdfTokenLooper {
16 public:
PdfMainLooper(SkPdfNativeTokenizer * tokenizer,SkPdfContext * pdfContext,SkCanvas * canvas)17     PdfMainLooper(SkPdfNativeTokenizer* tokenizer,
18                   SkPdfContext* pdfContext,
19                   SkCanvas* canvas)
20         : INHERITED(tokenizer, pdfContext, canvas) {}
21 
22     virtual SkPdfResult consumeToken(PdfToken& token) SK_OVERRIDE;
23     virtual void loop() SK_OVERRIDE;
24 
25 private:
26     typedef SkPdfTokenLooper INHERITED;
27 };
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 
SkPdfContext(SkPdfNativeDoc * doc)31 SkPdfContext::SkPdfContext(SkPdfNativeDoc* doc)
32     : fPdfDoc(doc)
33 {
34     SkASSERT(fPdfDoc != NULL);
35 }
36 
parseStream(SkPdfNativeObject * stream,SkCanvas * canvas)37 void SkPdfContext::parseStream(SkPdfNativeObject* stream, SkCanvas* canvas) {
38     if (NULL == stream) {
39         // Nothing to parse.
40         return;
41     }
42 
43     SkPdfNativeTokenizer tokenizer(stream, &fTmpPageAllocator, fPdfDoc);
44     PdfMainLooper looper(&tokenizer, this, canvas);
45     looper.loop();
46 }
47 
48 ///////////////////////////////////////////////////////////////////////////////
49 
50 // FIXME (scroggo): This probably belongs in a debugging file.
51 // For reportRenderStats declaration.
52 #include "SkPdfRenderer.h"
53 
54 // Temp code to measure what operands fail.
55 template <typename T> class SkTDictWithDefaultConstructor : public SkTDict<T> {
56 public:
SkTDictWithDefaultConstructor()57     SkTDictWithDefaultConstructor() : SkTDict<T>(10) {}
58 };
59 
60 SkTDictWithDefaultConstructor<int> gRenderStats[kCount_SkPdfResult];
61 
62 const char* gRenderStatsNames[kCount_SkPdfResult] = {
63     "Success",
64     "Partially implemented",
65     "Not yet implemented",
66     "Ignore Error",
67     "Error",
68     "Unsupported/Unknown"
69 };
70 
71 // Declared in SkPdfRenderer.h. Should be moved to a central debugging location.
reportPdfRenderStats()72 void reportPdfRenderStats() {
73     for (int i = 0 ; i < kCount_SkPdfResult; i++) {
74         SkTDict<int>::Iter iter(gRenderStats[i]);
75         const char* key;
76         int value = 0;
77         while ((key = iter.next(&value)) != NULL) {
78             SkDebugf("%s: %s -> count %i\n", gRenderStatsNames[i], key, value);
79         }
80     }
81 }
82 
83 #include "SkPdfOps.h"
84 
consumeToken(PdfToken & token)85 SkPdfResult PdfMainLooper::consumeToken(PdfToken& token) {
86     if (token.fType == kKeyword_TokenType && token.fKeywordLength < 256)
87     {
88         PdfOperatorRenderer pdfOperatorRenderer = NULL;
89         if (gPdfOps.find(token.fKeyword, token.fKeywordLength, &pdfOperatorRenderer) &&
90                     pdfOperatorRenderer) {
91             // Main work is done by pdfOperatorRenderer(...)
92             SkPdfResult result = pdfOperatorRenderer(fPdfContext, fCanvas, this);
93 
94             int cnt = 0;
95             gRenderStats[result].find(token.fKeyword, token.fKeywordLength, &cnt);
96             gRenderStats[result].set(token.fKeyword, token.fKeywordLength, cnt + 1);
97         } else {
98             int cnt = 0;
99             gRenderStats[kUnsupported_SkPdfResult].find(token.fKeyword,
100                                                         token.fKeywordLength,
101                                                         &cnt);
102             gRenderStats[kUnsupported_SkPdfResult].set(token.fKeyword,
103                                                        token.fKeywordLength,
104                                                        cnt + 1);
105         }
106     }
107     else if (token.fType == kObject_TokenType)
108     {
109         fPdfContext->fObjectStack.push( token.fObject );
110     }
111     else {
112         // TODO(edisonn): store the keyword as a object, so we can track the location in file,
113         //                and report where the error was triggered
114         SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, token.fKeyword, NULL,
115                     fPdfContext);
116         return kIgnoreError_SkPdfResult;
117     }
118     return kOK_SkPdfResult;
119 }
120 
loop()121 void PdfMainLooper::loop() {
122     PdfToken token;
123     while (fTokenizer->readToken(&token, true)) {
124         this->consumeToken(token);
125     }
126 }
127