blob: 670e6ce48d62c6fc9e1aad3980edd94049f13146 [file] [log] [blame]
/*
* 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 <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);
}
}