Chromium Code Reviews| Index: experimental/PdfViewer/src/SkPdfContext.cpp |
| diff --git a/experimental/PdfViewer/src/SkPdfContext.cpp b/experimental/PdfViewer/src/SkPdfContext.cpp |
| index 2ce01e75fabee85aaf47bc1d214c6fcac7c46452..b87e078c0fe446f54d5b6faacae8ee6a32baee09 100644 |
| --- a/experimental/PdfViewer/src/SkPdfContext.cpp |
| +++ b/experimental/PdfViewer/src/SkPdfContext.cpp |
| @@ -6,13 +6,126 @@ |
| */ |
| #include "SkPdfContext.h" |
| -#include "SkPdfNativeTokenizer.h" |
| +#include "SkPdfNativeDoc.h" |
| +#include "SkPdfReporter.h" |
| +#include "SkPdfTokenLooper.h" |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +class PdfMainLooper : public SkPdfTokenLooper { |
| +public: |
| + PdfMainLooper(SkPdfTokenLooper* parent, |
| + SkPdfNativeTokenizer* tokenizer, |
| + SkPdfContext* pdfContext, |
| + SkCanvas* canvas) |
| + : SkPdfTokenLooper(parent, tokenizer, pdfContext, canvas) {} |
| + |
| + virtual SkPdfResult consumeToken(PdfToken& token); |
| + virtual void loop(); |
| +}; |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| SkPdfContext::SkPdfContext(SkPdfNativeDoc* doc) |
| : fPdfDoc(doc) |
| - , fTmpPageAllocator(new SkPdfAllocator()) { |
| +{ |
| + SkASSERT(fPdfDoc != NULL); |
| +} |
| + |
| +void SkPdfContext::parseStream(SkPdfNativeObject* stream, SkCanvas* canvas) { |
| + SkPdfNativeTokenizer* tokenizer = fPdfDoc->tokenizerOfStream(stream, &fTmpPageAllocator); |
| + if (NULL == tokenizer) { |
| + // Nothing to parse. |
| + return; |
| + } |
| + PdfMainLooper looper(NULL, tokenizer, this, canvas); |
| + looper.loop(); |
| + // FIXME: SkDELETE, once tokenizerOfStream uses SkNEW. |
|
mtklein
2013/11/22 14:40:20
Or really, SkAutoTDelete for the whole thing?
scroggo
2013/11/22 15:03:00
In a future CL, I put the object on the stack (cou
|
| + delete tokenizer; |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +// 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" |
| +}; |
| + |
| +void reportPdfRenderStats() { |
|
mtklein
2013/11/22 14:40:20
can we make this guy static and report_pdf_render_
scroggo
2013/11/22 15:03:00
It cannot be static, since we need to access it fr
|
| + 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) { |
| + printf("%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) { |
| + SkPdfTokenLooper* childLooper = NULL; |
| + // Main work is done by pdfOperatorRenderer(...) |
| + SkPdfResult result = pdfOperatorRenderer(fPdfContext, fCanvas, &childLooper); |
| + |
| + int cnt = 0; |
| + gRenderStats[result].find(token.fKeyword, token.fKeywordLength, &cnt); |
| + gRenderStats[result].set(token.fKeyword, token.fKeywordLength, cnt + 1); |
| + if (childLooper) { |
| + childLooper->setUp(this); |
| + childLooper->loop(); |
| + delete childLooper; |
|
mtklein
2013/11/22 14:40:20
It'd be nice if we could get this to be an SkAutoT
scroggo
2013/11/22 15:03:00
Agreed. I added a fixme, so I can leave the code a
|
| + } |
| + } 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; |
| } |
| -SkPdfContext::~SkPdfContext() { |
| - delete fTmpPageAllocator; |
| +void PdfMainLooper::loop() { |
| + PdfToken token; |
| + // readToken defined in SkPdfTokenLooper.h |
| + while (readToken(fTokenizer, &token)) { |
|
mtklein
2013/11/22 14:40:20
hmm, it wants to be named ReadToken then right?
I
scroggo
2013/11/22 15:03:00
The next patch (https://codereview.chromium.org/80
|
| + this->consumeToken(token); |
| + } |
| } |