/* * 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) {} virtual SkPdfResult consumeToken(PdfToken& token) SK_OVERRIDE; virtual 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 class SkTDictWithDefaultConstructor : public SkTDict { public: SkTDictWithDefaultConstructor() : SkTDict(10) {} }; SkTDictWithDefaultConstructor 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::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); } }