Home | History | Annotate | Download | only in src
      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:
     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 
     31 SkPdfContext::SkPdfContext(SkPdfNativeDoc* doc)
     32     : fPdfDoc(doc)
     33 {
     34     SkASSERT(fPdfDoc != NULL);
     35 }
     36 
     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:
     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.
     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 
     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 
    121 void PdfMainLooper::loop() {
    122     PdfToken token;
    123     while (fTokenizer->readToken(&token, true)) {
    124         this->consumeToken(token);
    125     }
    126 }
    127