aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
diff options
context:
space:
mode:
authorGravatar edisonn@google.com <edisonn@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-09-13 19:33:42 +0000
committerGravatar edisonn@google.com <edisonn@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-09-13 19:33:42 +0000
commitaf54a513a5b7723b53f61730afe0ad6256881749 (patch)
tree1da9eecfbdbbf951076e219629cc61f3160e1e3d /experimental
parent1fb04e25405d5ec75aea4a099819d6feca348ff6 (diff)
pdfviewer: do not submit, uploaded for backup, and will be done actually after I refactor the params for functions, to put the char* params in a structure: report errors and warnings in pdf, infrastructure
Review URL: https://codereview.chromium.org/23902018 git-svn-id: http://skia.googlecode.com/svn/trunk@11262 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'experimental')
-rw-r--r--experimental/PdfViewer/SkPdfConfig.h33
-rw-r--r--experimental/PdfViewer/SkPdfRenderer.cpp372
-rw-r--r--experimental/PdfViewer/SkPdfRenderer.h6
-rw-r--r--experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp45
-rw-r--r--experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp15
-rw-r--r--experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h36
-rw-r--r--experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp8
7 files changed, 352 insertions, 163 deletions
diff --git a/experimental/PdfViewer/SkPdfConfig.h b/experimental/PdfViewer/SkPdfConfig.h
index 905041bab6..11e0319ae4 100644
--- a/experimental/PdfViewer/SkPdfConfig.h
+++ b/experimental/PdfViewer/SkPdfConfig.h
@@ -8,8 +8,12 @@
#ifndef SkPdfConfig_DEFINED
#define SkPdfConfig_DEFINED
+#include "stddef.h"
+class SkPdfNativeObject;
+
//#define PDF_TRACK_OBJECT_USAGE
//#define PDF_TRACK_STREAM_OFFSETS
+//#define PDF_REPORT
//#define PDF_TRACE
//#define PDF_TRACE_READ_TOKEN
//#define PDF_TRACE_DRAWTEXT
@@ -73,5 +77,34 @@
#define STORE_TRACK_PARAMETER_OFFSET_END(obj,offsetEnd)
#endif //PDF_TRACK_STREAM_OFFSETS
+// TODO(edisonn): move it somewhere else?
+struct SkPdfInputStream {
+#ifdef PDF_TRACK_STREAM_OFFSETS
+ // no parent object -> original file to be rendered
+ // no parent file -> stream object
+ // both -> external stream object
+ int fParentFileID;
+ const SkPdfNativeObject* fParentObject;
+
+ size_t fDelta; // delta in parent stream
+ const unsigned char* fStart;
+#endif // PDF_TRACK_STREAM_OFFSETS
+
+ const unsigned char* fEnd;
+};
+
+struct SkPdfInputStreamLocation {
+ SkPdfInputStream fInputStream;
+ const unsigned char* fNow;
+};
+
+#ifdef PDF_TRACK_STREAM_OFFSETS
+struct SkPdfInputStreamRange {
+ SkPdfInputStream fInputStream;
+ const unsigned char* fRangeStart;
+ const unsigned char* fRangeEnd;
+};
+#endif // PDF_TRACK_STREAM_OFFSETS
+
#endif // SkPdfConfig_DEFINED
diff --git a/experimental/PdfViewer/SkPdfRenderer.cpp b/experimental/PdfViewer/SkPdfRenderer.cpp
index e18c339925..04d9d28fde 100644
--- a/experimental/PdfViewer/SkPdfRenderer.cpp
+++ b/experimental/PdfViewer/SkPdfRenderer.cpp
@@ -5,6 +5,8 @@
* found in the LICENSE file.
*/
+#include "SkPdfRenderer.h"
+
#include "SkBitmapDevice.h"
#include "SkCanvas.h"
#include "SkDevice.h"
@@ -21,11 +23,13 @@
#include "SkPdfGraphicsState.h"
#include "SkPdfNativeTokenizer.h"
+#include "SkPdfReporter.h"
extern "C" SkPdfContext* gPdfContext;
extern "C" SkBitmap* gDumpBitmap;
extern "C" SkCanvas* gDumpCanvas;
+
__SK_FORCE_IMAGE_DECODER_LINKING;
// TODO(edisonn): tool, show what objects were read at least, show the ones not even read
@@ -72,8 +76,11 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
* - deal with specific type in spec directly, add all dictionary types to known types
*/
-#define EXPECT_OPERANDS(pdfContext,n) \
+#define EXPECT_OPERANDS(name,pdfContext,n) \
bool __failed = pdfContext->fObjectStack.count() < n; \
+ SkPdfREPORTCODE(const char* __operator_name = name); \
+ SkPdfREPORTCODE((void)__operator_name); \
+ SkPdfReportIf(pdfContext->fObjectStack.count() < n, kIgnoreError_SkPdfIssueSeverity, kStackOverflow_SkPdfIssue, "Not enought parameters.", NULL, pdfContext); \
SkDEBUGCODE(int __cnt = n);
#define POP_OBJ(pdfContext,name) \
@@ -86,18 +93,21 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
pdfContext->fObjectStack.pop(); \
}
+// TODO(edisonn): make all pop function to use name##_obj
#define POP_NUMBER(pdfContext,name) \
SkDEBUGCODE(__cnt--); \
SkASSERT(__cnt >= 0); \
double name = 0; \
+ SkPdfNativeObject* name##_obj = NULL; \
__failed = __failed || pdfContext->fObjectStack.count() == 0; \
if (pdfContext->fObjectStack.count() > 0) { \
- SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
+ name##_obj = pdfContext->fObjectStack.top(); \
pdfContext->fObjectStack.pop(); \
- if (!tmp || !tmp->isNumber()) { \
+ if (!name##_obj || !name##_obj->isNumber()) { \
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, __operator_name, name##_obj, SkPdfNativeObject::_kNumber_PdfObjectType, NULL);\
__failed = true;\
} else { \
- name = tmp->numberValue(); \
+ name = name##_obj->numberValue(); \
} \
}
@@ -106,13 +116,15 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
SkASSERT(__cnt >= 0); \
int64_t name = 0; \
__failed = __failed || pdfContext->fObjectStack.count() == 0; \
+ SkPdfNativeObject* name##_obj = NULL; \
if (pdfContext->fObjectStack.count() > 0) { \
- SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
+ name##_obj = pdfContext->fObjectStack.top(); \
pdfContext->fObjectStack.pop(); \
- if (!tmp || !tmp->isInteger()) { \
+ if (!name##_obj || !name##_obj->isInteger()) { \
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, __operator_name, name##_obj, SkPdfNativeObject::kInteger_PdfObjectType, NULL);\
__failed = true;\
} else { \
- name = tmp->intValue(); \
+ name = name##_obj->intValue(); \
} \
}
@@ -124,6 +136,7 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
pdfContext->fObjectStack.pop(); \
if (!tmp || !tmp->isNumber()) { \
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, __operator_name, tmp, SkPdfNativeObject::kInteger_PdfObjectType | SkPdfNativeObject::kReal_PdfObjectType, NULL);\
__failed = true;\
} else { \
var = tmp->numberValue(); \
@@ -140,6 +153,7 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
pdfContext->fObjectStack.pop(); \
if (!tmp || !tmp->isName()) { \
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, __operator_name, tmp, SkPdfNativeObject::kName_PdfObjectType, NULL);\
__failed = true;\
} else { \
name = tmp; \
@@ -155,6 +169,7 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
pdfContext->fObjectStack.pop(); \
if (!tmp || !tmp->isAnyString()) { \
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, __operator_name, tmp, SkPdfNativeObject::kString_PdfObjectType | SkPdfNativeObject::kHexString_PdfObjectType, NULL);\
__failed = true;\
} else { \
name = tmp; \
@@ -170,6 +185,7 @@ __SK_FORCE_IMAGE_DECODER_LINKING;
SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
pdfContext->fObjectStack.pop(); \
if (!tmp || !tmp->isArray()) { \
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, __operator_name, tmp, SkPdfNativeObject::kArray_PdfObjectType, NULL);\
__failed = true;\
} else { \
name = (SkPdfArray*)tmp; \
@@ -300,10 +316,21 @@ SkMatrix SkMatrixFromPdfArray(SkPdfArray* pdfArray) {
double array[6];
// TODO(edisonn): security issue, ret if size() != 6
+ if (pdfArray == NULL) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNullObject_SkPdfIssue, "null array passed to build matrix", NULL, NULL);
+ return SkMatrix::I();
+ }
+
+ if (pdfArray->size() != 6) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kUnexpectedArraySize_SkPdfIssue, "null array passed to build matrix", pdfArray, NULL);
+ return SkMatrix::I();
+ }
+
for (int i = 0; i < 6; i++) {
const SkPdfNativeObject* elem = pdfArray->operator [](i);
if (elem == NULL || !elem->isNumber()) {
- return SkMatrix::I(); // TODO(edisonn): report issue
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, elem, SkPdfNativeObject::_kNumber_PdfObjectType, NULL);
+ return SkMatrix::I();
}
array[i] = elem->numberValue();
}
@@ -462,9 +489,8 @@ static SkPdfResult DrawText(SkPdfContext* pdfContext,
skfont = SkPdfFont::Default();
}
-
if (_str == NULL || !_str->isAnyString()) {
- // TODO(edisonn): report warning
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "DrawText", _str, SkPdfNativeObject::_kAnyString_PdfObjectType, pdfContext);
return kIgnoreError_SkPdfResult;
}
const SkPdfString* str = (const SkPdfString*)_str;
@@ -474,7 +500,7 @@ static SkPdfResult DrawText(SkPdfContext* pdfContext,
SkDecodedText decoded;
if (skfont->encoding() == NULL) {
- // TODO(edisonn): report warning
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingEncoding_SkPdfIssue, "draw text", _str, pdfContext);
return kNYI_SkPdfResult;
}
@@ -518,10 +544,11 @@ static SkColorTable* getGrayColortable() {
return grayColortable;
}
-static SkBitmap* transferImageStreamToBitmap(const unsigned char* uncompressedStream, size_t uncompressedStreamLength,
- int width, int height, int bytesPerLine,
- int bpc, const SkString& colorSpace,
- bool transparencyMask) {
+static SkBitmap* transferImageStreamToBitmap(const unsigned char* uncompressedStream,
+ size_t uncompressedStreamLength,
+ int width, int height, int bytesPerLine,
+ int bpc, const SkString& colorSpace,
+ bool transparencyMask) {
SkBitmap* bitmap = new SkBitmap();
//int components = GetColorSpaceComponents(colorSpace);
@@ -566,7 +593,8 @@ static SkBitmap* transferImageStreamToBitmap(const unsigned char* uncompressedSt
bitmap->setPixels(uncompressedStreamA8, transparencyMask ? NULL : getGrayColortable());
}
- // TODO(edisonn): Report Warning, NYI, or error
+ // TODO(edisonn): pass color space and context here?
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "Color space NYI", NULL, NULL);
return bitmap;
}
@@ -581,7 +609,7 @@ static SkBitmap* transferImageStreamToBitmap(const unsigned char* uncompressedSt
static SkBitmap* getImageFromObjectCore(SkPdfContext* pdfContext, SkPdfImageDictionary* image, bool transparencyMask) {
if (image == NULL || !image->hasStream()) {
- // TODO(edisonn): report warning to be used in testing.
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "Missing stream", image, SkPdfNativeObject::_kStream_PdfObjectType, pdfContext);
return NULL;
}
@@ -594,7 +622,6 @@ static SkBitmap* getImageFromObjectCore(SkPdfContext* pdfContext, SkPdfImageDict
SkPMColor colors[256];
int cnt = 0;
- // TODO(edisonn): color space can be an array too!
if (image->isColorSpaceAName(pdfContext->fPdfDoc)) {
colorSpace = image->getColorSpaceAsName(pdfContext->fPdfDoc);
} else if (image->isColorSpaceAArray(pdfContext->fPdfDoc)) {
@@ -604,17 +631,17 @@ static SkBitmap* getImageFromObjectCore(SkPdfContext* pdfContext, SkPdfImageDict
array->objAtAIndex(2)->isInteger() &&
array->objAtAIndex(3)->isHexString()
) {
- // TODO(edisonn): suport only DeviceRGB for now.
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "Color space NYI", image, pdfContext);
indexed = true;
cnt = (int)array->objAtAIndex(2)->intValue() + 1;
if (cnt > 256) {
- // TODO(edionn): report NYIs
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "Color space feature NYI, cnt > 256", image, pdfContext);
return NULL;
}
SkColorTable colorTable(cnt);
NotOwnedString data = array->objAtAIndex(3)->strRef();
if (data.fBytes != (unsigned int)cnt * 3) {
- // TODO(edionn): report error/warning
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncostistentSizes_SkPdfIssue, "Image color table mismatch color space specs", array, pdfContext);
return NULL;
}
for (int i = 0 ; i < cnt; i++) {
@@ -642,7 +669,7 @@ static SkBitmap* getImageFromObjectCore(SkPdfContext* pdfContext, SkPdfImageDict
if (!stream || !stream->GetFilteredStreamRef(&uncompressedStream, &uncompressedStreamLength) ||
uncompressedStream == NULL || uncompressedStreamLength == 0) {
- // TODO(edisonn): report warning to be used in testing.
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "Missing stream", stream, SkPdfNativeObject::_kStream_PdfObjectType, pdfContext);
return NULL;
}
@@ -718,6 +745,8 @@ static SkBitmap* getSmaskFromObject(SkPdfContext* pdfContext, SkPdfImageDictiona
}
// TODO(edisonn): implement GS SMask. Default to empty right now.
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "implement GS SMask. Default to empty right now.", obj, pdfContext);
+
return pdfContext->fGraphicsState.fSMask;
}
@@ -756,6 +785,8 @@ static SkPdfResult doXObject_Image(SkPdfContext* pdfContext, SkCanvas* canvas, S
SkRect dst = SkRect::MakeXYWH(SkDoubleToScalar(0.0), SkDoubleToScalar(0.0), SkDoubleToScalar(1.0), SkDoubleToScalar(1.0));
// TODO(edisonn): soft mask type? alpha/luminosity.
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "implement soft mask type", skpdfimage, pdfContext);
+
SkPaint paint;
pdfContext->fGraphicsState.applyGraphicsState(&paint, false);
@@ -818,10 +849,12 @@ static void doGroup_before(SkPdfContext* pdfContext, SkCanvas* canvas, SkRect bb
static SkPdfResult doXObject_Form(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfType1FormDictionary* skobj) {
if (!skobj || !skobj->hasStream()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "Missing stream", skobj, SkPdfNativeObject::_kStream_PdfObjectType, pdfContext);
return kIgnoreError_SkPdfResult;
}
if (!skobj->has_BBox()) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingRequiredKey_SkPdfIssue, "BBox", skobj, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -885,10 +918,12 @@ static SkPdfResult doXObject_Form(SkPdfContext* pdfContext, SkCanvas* canvas, Sk
// TODO(edisonn): Extract a class like ObjWithStream
static SkPdfResult doXObject_Pattern(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfType1PatternDictionary* skobj) {
if (!skobj || !skobj->hasStream()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "Missing stream", skobj, SkPdfNativeObject::_kStream_PdfObjectType, pdfContext);
return kIgnoreError_SkPdfResult;
}
if (!skobj->has_BBox()) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingRequiredKey_SkPdfIssue, "BBox", skobj, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -940,6 +975,7 @@ static SkPdfResult doXObject_Pattern(SkPdfContext* pdfContext, SkCanvas* canvas,
SkPdfResult doType3Char(SkPdfContext* pdfContext, SkCanvas* canvas, const SkPdfNativeObject* skobj, SkRect bBox, SkMatrix matrix, double textSize) {
if (!skobj || !skobj->hasStream()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "Missing stream", skobj, SkPdfNativeObject::_kStream_PdfObjectType, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -1003,7 +1039,7 @@ public:
static SkPdfResult doXObject(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfNativeObject* obj) {
if (CheckRecursiveRendering::IsInRendering(obj)) {
- // Oops, corrupt PDF!
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kRecursiveReferencing_SkPdfIssue, "Recursive reverencing is invalid in draw objects", obj, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -1022,23 +1058,22 @@ static SkPdfResult doXObject(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfNa
SkPdfType1PatternDictionary* pattern = (SkPdfType1PatternDictionary*)obj;
return doXObject_Pattern(pdfContext, canvas, pattern);
}
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "doXObject", obj, pdfContext);
}
}
return kIgnoreError_SkPdfResult;
}
static SkPdfResult doPage(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfPageObjectDictionary* skobj) {
- if (!skobj) {
- return kIgnoreError_SkPdfResult;
- }
-
- if (!skobj->isContentsAStream(pdfContext->fPdfDoc)) {
+ if (!skobj || !skobj->isContentsAStream(pdfContext->fPdfDoc)) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "Missing stream", skobj, SkPdfNativeObject::_kStream_PdfObjectType, pdfContext);
return kNYI_SkPdfResult;
}
SkPdfStream* stream = skobj->getContentsAsStream(pdfContext->fPdfDoc);
if (!stream) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "Missing stream", skobj, SkPdfNativeObject::_kStream_PdfObjectType, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -1049,7 +1084,7 @@ static SkPdfResult doPage(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfPageO
}
if (CheckRecursiveRendering::IsInRendering(skobj)) {
- // Oops, corrupt PDF!
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kRecursiveReferencing_SkPdfIssue, "Recursive reverencing is invalid in draw objects", skobj, pdfContext);
return kIgnoreError_SkPdfResult;
}
CheckRecursiveRendering checkRecursion(skobj);
@@ -1058,6 +1093,8 @@ static SkPdfResult doPage(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfPageO
PdfOp_q(pdfContext, canvas, NULL);
// TODO(edisonn): MediaBox can be inherited!!!!
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "MediaBox inheritance NYI", NULL, pdfContext);
+
SkRect bbox = skobj->MediaBox(pdfContext->fPdfDoc);
if (skobj->has_Group()) {
SkPdfTransparencyGroupDictionary* tgroup = skobj->Group(pdfContext->fPdfDoc);
@@ -1097,12 +1134,14 @@ SkPdfResult PdfOp_Q(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper**
pdfContext->fStateStack.pop();
canvas->restore();
- if (pdfContext->fObjectStack.nests() <= 0) {
+ if (pdfContext->fObjectStack.nests() == 0) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kStackNestingOverflow_SkPdfIssue, "stack nesting overflow (q/Q)", NULL, pdfContext);
return kIgnoreError_SkPdfResult;
} else {
pdfContext->fObjectStack.unnest();
}
} else {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kStackOverflow_SkPdfIssue, "stack overflow (q/Q)", NULL, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -1110,7 +1149,7 @@ SkPdfResult PdfOp_Q(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper**
}
static SkPdfResult PdfOp_cm(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 6);
+ EXPECT_OPERANDS("cm", pdfContext, 6);
POP_NUMBER(pdfContext, f);
POP_NUMBER(pdfContext, e);
POP_NUMBER(pdfContext, d);
@@ -1151,7 +1190,7 @@ static SkPdfResult PdfOp_cm(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//, to leading, which is a number expressed in unscaled text
//space units. Text leading is used only by the T*, ', and " operators. Initial value: 0.
static SkPdfResult PdfOp_TL(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1)
+ EXPECT_OPERANDS("TL", pdfContext, 1);
POP_NUMBER(pdfContext, ty);
CHECK_PARAMETERS();
@@ -1161,7 +1200,7 @@ static SkPdfResult PdfOp_TL(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
}
static SkPdfResult PdfOp_Td(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 2);
+ EXPECT_OPERANDS("Td", pdfContext, 2);
POP_NUMBER(pdfContext, ty);
POP_NUMBER(pdfContext, tx);
CHECK_PARAMETERS();
@@ -1176,7 +1215,7 @@ static SkPdfResult PdfOp_Td(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
}
static SkPdfResult PdfOp_TD(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 2)
+ EXPECT_OPERANDS("TD", pdfContext, 2)
POP_NUMBER(pdfContext, ty);
POP_NUMBER(pdfContext, tx);
CHECK_PARAMETERS();
@@ -1202,7 +1241,7 @@ static SkPdfResult PdfOp_TD(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
}
static SkPdfResult PdfOp_Tm(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 6);
+ EXPECT_OPERANDS("Tm", pdfContext, 6);
POP_NUMBER(pdfContext, f);
POP_NUMBER(pdfContext, e);
POP_NUMBER(pdfContext, d);
@@ -1224,6 +1263,8 @@ static SkPdfResult PdfOp_Tm(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
matrix.preScale(SkDoubleToScalar(1), SkDoubleToScalar(-1));
// TODO(edisonn): Text positioning.
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "Text positioning not implemented for 2+ chars", NULL, pdfContext);
+
pdfContext->fGraphicsState.fMatrixTm = matrix;
pdfContext->fGraphicsState.fMatrixTlm = matrix;;
@@ -1251,7 +1292,7 @@ static SkPdfResult PdfOp_m(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
pdfContext->fGraphicsState.fPathClosed = false;
}
- EXPECT_OPERANDS(pdfContext, 2);
+ EXPECT_OPERANDS("m", pdfContext, 2);
POP_NUMBER(pdfContext, y);
POP_NUMBER(pdfContext, x);
CHECK_PARAMETERS();
@@ -1271,7 +1312,7 @@ static SkPdfResult PdfOp_l(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
pdfContext->fGraphicsState.fPathClosed = false;
}
- EXPECT_OPERANDS(pdfContext, 2);
+ EXPECT_OPERANDS("l", pdfContext, 2);
POP_NUMBER(pdfContext, y);
POP_NUMBER(pdfContext, x);
CHECK_PARAMETERS();
@@ -1291,7 +1332,7 @@ static SkPdfResult PdfOp_c(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
pdfContext->fGraphicsState.fPathClosed = false;
}
- EXPECT_OPERANDS(pdfContext, 6);
+ EXPECT_OPERANDS("c", pdfContext, 6);
POP_NUMBER(pdfContext, y3);
POP_NUMBER(pdfContext, x3);
POP_NUMBER(pdfContext, y2);
@@ -1316,7 +1357,7 @@ static SkPdfResult PdfOp_v(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
pdfContext->fGraphicsState.fPathClosed = false;
}
- EXPECT_OPERANDS(pdfContext, 4);
+ EXPECT_OPERANDS("v", pdfContext, 4);
POP_NUMBER(pdfContext, y3);
POP_NUMBER(pdfContext, x3);
POP_NUMBER(pdfContext, y2);
@@ -1342,7 +1383,7 @@ static SkPdfResult PdfOp_y(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
pdfContext->fGraphicsState.fPathClosed = false;
}
- EXPECT_OPERANDS(pdfContext, 4);
+ EXPECT_OPERANDS("y", pdfContext, 4);
POP_NUMBER(pdfContext, y3);
POP_NUMBER(pdfContext, x3);
POP_NUMBER(pdfContext, y1);
@@ -1368,7 +1409,7 @@ static SkPdfResult PdfOp_re(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
pdfContext->fGraphicsState.fPathClosed = false;
}
- EXPECT_OPERANDS(pdfContext, 4);
+ EXPECT_OPERANDS("re", pdfContext, 4);
POP_NUMBER(pdfContext, height);
POP_NUMBER(pdfContext, width);
POP_NUMBER(pdfContext, y);
@@ -1435,6 +1476,8 @@ static SkPdfResult PdfOp_fillAndStroke(SkPdfContext* pdfContext, SkCanvas* canva
int xStep = abs((int)pattern->XStep(pdfContext->fPdfDoc));
int yStep = abs((int)pattern->YStep(pdfContext->fPdfDoc));
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "paterns x/y step is forced to positive number", pattern, pdfContext);
+
SkRect bounds = path.getBounds();
// TODO(edisonn): xstep and ystep can be negative, and we need to iterate in reverse
@@ -1564,7 +1607,6 @@ static SkPdfResult PdfOp_n(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
#endif
}
- //pdfContext->fGraphicsState.fClipPath.reset();
pdfContext->fGraphicsState.fHasClipPathToApply = false;
pdfContext->fGraphicsState.fPathClosed = true;
@@ -1584,6 +1626,8 @@ static SkPdfResult PdfOp_BT(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
static SkPdfResult PdfOp_ET(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
if (!pdfContext->fGraphicsState.fTextBlock) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingBT_SkPdfIssue, "ET without BT", NULL, pdfContext);
+
return kIgnoreError_SkPdfResult;
}
// TODO(edisonn): anything else to be done once we are done with draw text? Like restore stack?
@@ -1597,6 +1641,7 @@ static SkPdfResult skpdfGraphicsStateApplyFontCore(SkPdfContext* pdfContext, con
if (!pdfContext->fGraphicsState.fResources->Font(pdfContext->fPdfDoc)) {
// TODO(edisonn): try to recover and draw it any way?
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingFont_SkPdfIssue, "No font", fontName, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -1604,6 +1649,7 @@ static SkPdfResult skpdfGraphicsStateApplyFontCore(SkPdfContext* pdfContext, con
objFont = pdfContext->fPdfDoc->resolveReference(objFont);
if (kNone_SkPdfNativeObjectType == pdfContext->fPdfDoc->mapper()->mapFontDictionary(objFont)) {
// TODO(edisonn): try to recover and draw it any way?
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kInvalidFont_SkPdfIssue, "Invalid font", objFont, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -1624,7 +1670,7 @@ static SkPdfResult skpdfGraphicsStateApplyFontCore(SkPdfContext* pdfContext, con
//a number representing a scale factor. There is no initial value for either font or
//size; they must be specified explicitly using Tf before any text is shown.
static SkPdfResult PdfOp_Tf(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 2);
+ EXPECT_OPERANDS("Tf", pdfContext, 2);
POP_NUMBER(pdfContext, fontSize);
POP_NAME(pdfContext, fontName);
CHECK_PARAMETERS();
@@ -1633,12 +1679,13 @@ static SkPdfResult PdfOp_Tf(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
}
static SkPdfResult PdfOp_Tj(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("Tj", pdfContext, 1);
POP_STRING(pdfContext, str);
CHECK_PARAMETERS();
if (!pdfContext->fGraphicsState.fTextBlock) {
// TODO(edisonn): try to recover and draw it any way?
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingBT_SkPdfIssue, "Tj without BT", NULL, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -1650,6 +1697,7 @@ static SkPdfResult PdfOp_Tj(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
static SkPdfResult PdfOp_quote(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
if (!pdfContext->fGraphicsState.fTextBlock) {
// TODO(edisonn): try to recover and draw it any way?
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingBT_SkPdfIssue, "' without BT", NULL, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -1661,10 +1709,11 @@ static SkPdfResult PdfOp_quote(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTo
static SkPdfResult PdfOp_doublequote(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
if (!pdfContext->fGraphicsState.fTextBlock) {
// TODO(edisonn): try to recover and draw it any way?
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingBT_SkPdfIssue, "\" without BT", NULL, pdfContext);
return kIgnoreError_SkPdfResult;
}
- EXPECT_OPERANDS(pdfContext, 3);
+ EXPECT_OPERANDS("\"", pdfContext, 3);
POP_OBJ(pdfContext, str);
POP_OBJ(pdfContext, ac);
POP_OBJ(pdfContext, aw);
@@ -1683,22 +1732,26 @@ static SkPdfResult PdfOp_doublequote(SkPdfContext* pdfContext, SkCanvas* canvas,
}
static SkPdfResult PdfOp_TJ(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("Tf", pdfContext, 1);
POP_ARRAY(pdfContext, array);
CHECK_PARAMETERS();
if (!pdfContext->fGraphicsState.fTextBlock) {
// TODO(edisonn): try to recover and draw it any way?
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingBT_SkPdfIssue, "TJ without BT", NULL, pdfContext);
return kIgnoreError_SkPdfResult;
}
if (!array->isArray()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, array, SkPdfNativeObject::kArray_PdfObjectType, pdfContext);
return kIgnoreError_SkPdfResult;
}
for( int i=0; i<static_cast<int>(array->size()); i++ )
{
- if( (*array)[i]->isAnyString()) {
+ if (!(*array)[i]) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "element [i] is null, no element should be null", array, SkPdfNativeObject::_kAnyString_PdfObjectType || SkPdfNativeObject::_kNumber_PdfObjectType, pdfContext);
+ } else if( (*array)[i]->isAnyString()) {
SkPdfNativeObject* obj = (*array)[i];
DrawText(pdfContext, obj, canvas);
} else if ((*array)[i]->isNumber()) {
@@ -1716,13 +1769,15 @@ static SkPdfResult PdfOp_TJ(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
SkDoubleToScalar(1));
pdfContext->fGraphicsState.fMatrixTm.preConcat(matrix);
+ } else {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "wrong type", (*array)[i], SkPdfNativeObject::kArray_PdfObjectType || SkPdfNativeObject::_kNumber_PdfObjectType, pdfContext);
}
}
return kPartial_SkPdfResult; // TODO(edisonn): Implement fully DrawText before returing OK.
}
static SkPdfResult PdfOp_CS_cs(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("CS/cs", pdfContext, 1);
POP_NAME(pdfContext, name);
CHECK_PARAMETERS();
@@ -1742,6 +1797,7 @@ static SkPdfResult PdfOp_CS_cs(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdf
} else if (colorSpace->isArray()) {
int cnt = colorSpace->size();
if (cnt == 0) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncostistentSizes_SkPdfIssue, "color space has length 0", colorSpace, pdfContext);
return kIgnoreError_SkPdfResult;
}
SkPdfNativeObject* type = colorSpace->objAtAIndex(0);
@@ -1749,6 +1805,7 @@ static SkPdfResult PdfOp_CS_cs(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdf
if (type->isName("ICCBased")) {
if (cnt != 2) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncostistentSizes_SkPdfIssue, "ICCBased color space must have an array with 2 elements", colorSpace, pdfContext);
return kIgnoreError_SkPdfResult;
}
SkPdfNativeObject* prop = colorSpace->objAtAIndex(1);
@@ -1792,7 +1849,7 @@ static SkPdfResult PdfOp_SC_sc(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdf
printf("color space = %s, N = %i\n", colorOperator->fColorSpace.fBuffer, n);
#endif
- EXPECT_OPERANDS(pdfContext, n);
+ EXPECT_OPERANDS("SC/sc", pdfContext, n);
for (int i = n - 1; i >= 0 ; i--) {
if (doubles) {
@@ -1852,7 +1909,7 @@ static SkPdfResult PdfOp_scn(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToke
}
static SkPdfResult PdfOp_G_g(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("G/g", pdfContext, 1);
POP_NUMBER(pdfContext, gray);
CHECK_PARAMETERS();
@@ -1871,7 +1928,7 @@ static SkPdfResult PdfOp_g(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
}
static SkPdfResult PdfOp_RG_rg(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
- EXPECT_OPERANDS(pdfContext, 3);
+ EXPECT_OPERANDS("RG/rg", pdfContext, 3);
POP_NUMBER(pdfContext, b);
POP_NUMBER(pdfContext, g);
POP_NUMBER(pdfContext, r);
@@ -1892,7 +1949,7 @@ static SkPdfResult PdfOp_rg(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
static SkPdfResult PdfOp_K_k(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
// TODO(edisonn): spec has some rules about overprint, implement them.
- EXPECT_OPERANDS(pdfContext, 4);
+ EXPECT_OPERANDS("K/k", pdfContext, 4);
POP_NUMBER(pdfContext, k);
POP_NUMBER(pdfContext, y);
POP_NUMBER(pdfContext, m);
@@ -1939,10 +1996,8 @@ static SkPdfResult PdfOp_BX(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
}
static SkPdfResult PdfOp_EX(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
-#ifdef ASSERT_BAD_PDF_OPS
- SkASSERT(false); // EX must be consumed by PdfCompatibilitySectionLooper, but let's
- // have the assert when testing good pdfs.
-#endif
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNullObject_SkPdfIssue, "EX operator should not be called, it is habdled in a looper, unless the file is corrupted, we should assert", NULL, pdfContext);
+
return kIgnoreError_SkPdfResult;
}
@@ -1952,22 +2007,15 @@ static SkPdfResult PdfOp_BI(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
}
static SkPdfResult PdfOp_ID(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
-#ifdef ASSERT_BAD_PDF_OPS
- SkASSERT(false); // must be processed in inline image looper, but let's
- // have the assert when testing good pdfs.
-#endif
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNullObject_SkPdfIssue, "ID operator should not be called, it is habdled in a looper, unless the file is corrupted, we should assert", NULL, pdfContext);
return kIgnoreError_SkPdfResult;
}
static SkPdfResult PdfOp_EI(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
-#ifdef ASSERT_BAD_PDF_OPS
- SkASSERT(false); // must be processed in inline image looper, but let's
- // have the assert when testing good pdfs.
-#endif
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNullObject_SkPdfIssue, "EI operator should not be called, it is habdled in a looper, unless the file is corrupted, we should assert", NULL, pdfContext);
return kIgnoreError_SkPdfResult;
}
-
// TODO(edisonn): security review here, make sure all parameters are valid, and safe.
static SkPdfResult skpdfGraphicsStateApply_ca(SkPdfContext* pdfContext, double ca) {
pdfContext->fGraphicsState.fNonStroking.fOpacity = ca;
@@ -2010,15 +2058,25 @@ static SkPdfResult skpdfGraphicsStateApplyML(SkPdfContext* pdfContext, double mi
*/
static SkPdfResult skpdfGraphicsStateApplyD(SkPdfContext* pdfContext, SkPdfArray* intervals, SkPdfNativeObject* phase) {
+ if (intervals == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, intervals, SkPdfNativeObject::_kNumber_PdfObjectType, pdfContext);
+ return kIgnoreError_SkPdfResult;
+ }
+
+ if (phase == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, phase, SkPdfNativeObject::_kNumber_PdfObjectType, pdfContext);
+ return kIgnoreError_SkPdfResult;
+ }
+
int cnt = intervals->size();
if (cnt >= 256) {
- // TODO(edisonn): report error/warning, unsuported;
// TODO(edisonn): alloc memory
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "dash array size unssuported, cnt > 256", intervals, pdfContext);
return kIgnoreError_SkPdfResult;
}
for (int i = 0; i < cnt; i++) {
- if (!intervals->objAtAIndex(i)->isNumber()) {
- // TODO(edisonn): report error/warning
+ if (!intervals->objAtAIndex(i) || !intervals->objAtAIndex(i)->isNumber()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, intervals->objAtAIndex(i), SkPdfNativeObject::_kNumber_PdfObjectType, NULL);
return kIgnoreError_SkPdfResult;
}
}
@@ -2048,26 +2106,58 @@ static SkPdfResult skpdfGraphicsStateApplyD(SkPdfContext* pdfContext, SkPdfArray
}
static SkPdfResult skpdfGraphicsStateApplyD(SkPdfContext* pdfContext, SkPdfArray* dash) {
- // TODO(edisonn): verify input
- if (!dash || dash->isArray() || dash->size() != 2 || !dash->objAtAIndex(0)->isArray() || !dash->objAtAIndex(1)->isNumber()) {
- // TODO(edisonn): report error/warning
+ if (!dash || dash->isArray()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, dash, SkPdfNativeObject::kArray_PdfObjectType, pdfContext);
+ return kIgnoreError_SkPdfResult;
+ }
+
+ if (dash->size() != 2) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncostistentSizes_SkPdfIssue, "hash array must have 2 elements", dash, pdfContext);
return kIgnoreError_SkPdfResult;
}
+
+ if (!dash->objAtAIndex(0) || !dash->objAtAIndex(0)->isArray()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, dash->objAtAIndex(0), SkPdfNativeObject::kArray_PdfObjectType, pdfContext);
+ return kIgnoreError_SkPdfResult;
+ }
+
+ if (!dash->objAtAIndex(1) || !dash->objAtAIndex(1)->isNumber()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, dash->objAtAIndex(1), SkPdfNativeObject::_kNumber_PdfObjectType, pdfContext);
+ return kIgnoreError_SkPdfResult;
+ }
+
return skpdfGraphicsStateApplyD(pdfContext, (SkPdfArray*)dash->objAtAIndex(0), dash->objAtAIndex(1));
}
static void skpdfGraphicsStateApplyFont(SkPdfContext* pdfContext, SkPdfArray* fontAndSize) {
- if (!fontAndSize || fontAndSize->isArray() || fontAndSize->size() != 2 || !fontAndSize->objAtAIndex(0)->isName() || !fontAndSize->objAtAIndex(1)->isNumber()) {
- // TODO(edisonn): report error/warning
+ if (!fontAndSize || !fontAndSize->isArray()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, fontAndSize, SkPdfNativeObject::kArray_PdfObjectType, pdfContext);
return;
}
+
+ if (fontAndSize->size() != 2) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncostistentSizes_SkPdfIssue, "font array must have 2 elements", fontAndSize, pdfContext);
+ return;
+ }
+
+ if (!fontAndSize->objAtAIndex(0) || !fontAndSize->objAtAIndex(0)->isName()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, fontAndSize->objAtAIndex(0), SkPdfNativeObject::kName_PdfObjectType, pdfContext);
+ return;
+ }
+
+
+ if (!fontAndSize->objAtAIndex(1) || !fontAndSize->objAtAIndex(1)->isNumber()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, fontAndSize->objAtAIndex(0), SkPdfNativeObject::_kNumber_PdfObjectType, pdfContext);
+ return;
+ }
+
skpdfGraphicsStateApplyFontCore(pdfContext, fontAndSize->objAtAIndex(0), fontAndSize->objAtAIndex(1)->numberValue());
}
//lineWidth w Set the line width in the graphics state (see “Line Width” on page 152).
static SkPdfResult PdfOp_w(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("w", pdfContext, 1);
POP_NUMBER(pdfContext, lw);
CHECK_PARAMETERS();
@@ -2077,7 +2167,7 @@ static SkPdfResult PdfOp_w(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
//lineCap J Set the line cap style in the graphics state (see “Line Cap Style” on page 153).
static SkPdfResult PdfOp_J(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
// TODO(edisonn): round/ceil to int?
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("J", pdfContext, 1);
POP_NUMBER(pdfContext, lc);
CHECK_PARAMETERS();
@@ -2087,7 +2177,7 @@ static SkPdfResult PdfOp_J(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
//lineJoin j Set the line join style in the graphics state (see “Line Join Style” on page 153).
static SkPdfResult PdfOp_j(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
// TODO(edisonn): round/ceil to int?
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("j", pdfContext, 1);
POP_NUMBER(pdfContext, lj);
CHECK_PARAMETERS();
@@ -2096,7 +2186,7 @@ static SkPdfResult PdfOp_j(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
//miterLimit M Set the miter limit in the graphics state (see “Miter Limit” on page 153).
static SkPdfResult PdfOp_M(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("M", pdfContext, 1);
POP_NUMBER(pdfContext, ml);
CHECK_PARAMETERS();
return skpdfGraphicsStateApplyML(pdfContext, ml);
@@ -2105,7 +2195,7 @@ static SkPdfResult PdfOp_M(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
//dashArray dashPhase d Set the line dash pattern in the graphics state (see “Line Dash Pattern” on
//page 155).
static SkPdfResult PdfOp_d(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 2);
+ EXPECT_OPERANDS("d", pdfContext, 2);
POP_OBJ(pdfContext, phase);
POP_ARRAY(pdfContext, array);
CHECK_PARAMETERS();
@@ -2117,6 +2207,8 @@ static SkPdfResult PdfOp_d(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenL
static SkPdfResult PdfOp_ri(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
pdfContext->fObjectStack.pop();
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "render intent NYI", NULL, pdfContext);
+
return kNYI_SkPdfResult;
}
@@ -2124,12 +2216,13 @@ static SkPdfResult PdfOp_ri(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//Tolerance”). flatness is a number in the range 0 to 100; a value of 0 speci-
//fies the output device’s default flatness tolerance.
static SkPdfResult PdfOp_i(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("i", pdfContext, 1);
POP_NUMBER(pdfContext, flatness);
CHECK_PARAMETERS();
if (flatness < 0 || flatness > 100) {
- return kError_SkPdfResult;
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kOutOfRange_SkPdfIssue, "flatness must be a real in [0, 100] range", flatness_obj, pdfContext);
+ return kIgnoreError_SkPdfResult;
}
return kNYI_SkPdfResult;
@@ -2180,26 +2273,32 @@ static void skpdfGraphicsStateApplyBM_name(SkPdfContext* pdfContext, const SkStr
pdfContext->fGraphicsState.fBlendModesLength = 1;
pdfContext->fGraphicsState.fBlendModes[0] = mode;
} else {
- // TODO(edisonn): report unknown blend mode
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kUnknownBlendMode_SkPdfIssue, blendMode.c_str(), NULL, pdfContext);
}
}
static void skpdfGraphicsStateApplyBM_array(SkPdfContext* pdfContext, SkPdfArray* blendModes) {
- if (!blendModes || blendModes->isArray() || blendModes->size() == 0 || blendModes->size() > 256) {
- // TODO(edisonn): report error/warning
+ if (!blendModes || !blendModes->isArray()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, blendModes, SkPdfNativeObject::kArray_PdfObjectType, pdfContext);
+ return;
+ }
+
+ if (blendModes->size() == 0 || blendModes->size() > 256) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncostistentSizes_SkPdfIssue, "length of blendmodes, 0, is an erro, 256+, is NYI", blendModes, pdfContext);
return;
}
+
SkXfermode::Mode modes[256];
int cnt = blendModes->size();
for (int i = 0; i < cnt; i++) {
SkPdfNativeObject* name = blendModes->objAtAIndex(i);
- if (!name->isName()) {
- // TODO(edisonn): report error/warning
+ if (!name || !name->isName()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, name, SkPdfNativeObject::kName_PdfObjectType, pdfContext);
return;
}
SkXfermode::Mode mode = xferModeFromBlendMode(name->c_str(), name->lenstr());
if (mode > SkXfermode::kLastMode) {
- // TODO(edisonn): report error/warning
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kUnknownBlendMode_SkPdfIssue, NULL, name, pdfContext);
return;
}
}
@@ -2211,14 +2310,19 @@ static void skpdfGraphicsStateApplyBM_array(SkPdfContext* pdfContext, SkPdfArray
}
static void skpdfGraphicsStateApplySMask_dict(SkPdfContext* pdfContext, SkPdfDictionary* sMask) {
- // TODO(edisonn): verify input
+ if (!sMask || !sMask->isName()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, sMask, SkPdfNativeObject::kArray_PdfObjectType, pdfContext);
+ return;
+ }
+
if (pdfContext->fPdfDoc->mapper()->mapSoftMaskDictionary(sMask)) {
pdfContext->fGraphicsState.fSoftMaskDictionary = (SkPdfSoftMaskDictionary*)sMask;
} else if (pdfContext->fPdfDoc->mapper()->mapSoftMaskImageDictionary(sMask)) {
SkPdfSoftMaskImageDictionary* smid = (SkPdfSoftMaskImageDictionary*)sMask;
pdfContext->fGraphicsState.fSMask = getImageFromObject(pdfContext, smid, true);
} else {
- // TODO (edisonn): report error/warning
+ // TODO(edisonn): make the dictionary types an enum?
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "Dictionary must be SoftMask, or SoftMaskImage", sMask, SkPdfNativeObject::kDictionary_PdfObjectType, pdfContext);
}
}
@@ -2233,16 +2337,13 @@ static void skpdfGraphicsStateApplySMask_name(SkPdfContext* pdfContext, const Sk
SkPdfDictionary* extGStateDictionary = pdfContext->fGraphicsState.fResources->ExtGState(pdfContext->fPdfDoc);
if (extGStateDictionary == NULL) {
-#ifdef PDF_TRACE
- printf("ExtGState is NULL!\n");
-#endif
- // TODO (edisonn): report error/warning
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingExtGState_SkPdfIssue, NULL, pdfContext->fGraphicsState.fResources, pdfContext);
return;
}
SkPdfNativeObject* obj = pdfContext->fPdfDoc->resolveReference(extGStateDictionary->get(sMask.c_str()));
if (!obj || !obj->isDictionary()) {
- // TODO (edisonn): report error/warning
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, obj, SkPdfNativeObject::kDictionary_PdfObjectType, pdfContext);
return;
}
@@ -2260,7 +2361,7 @@ static void skpdfGraphicsStateApplyAIS(SkPdfContext* pdfContext, bool alphaSourc
//dictName gs (PDF 1.2) Set the specified parameters in the graphics state. dictName is
//the name of a graphics state parameter dictionary in the ExtGState subdictionary of the current resource dictionary (see the next section).
static SkPdfResult PdfOp_gs(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("gs", pdfContext, 1);
POP_NAME(pdfContext, name);
CHECK_PARAMETERS();
@@ -2272,9 +2373,7 @@ static SkPdfResult PdfOp_gs(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
SkPdfDictionary* extGStateDictionary = pdfContext->fGraphicsState.fResources->ExtGState(pdfContext->fPdfDoc);
if (extGStateDictionary == NULL) {
-#ifdef PDF_TRACE
- printf("ExtGState is NULL!\n");
-#endif
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingExtGState_SkPdfIssue, NULL, pdfContext->fGraphicsState.fResources, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -2287,6 +2386,7 @@ static SkPdfResult PdfOp_gs(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
// TODO(edisonn): now load all those properties in graphic state.
if (gs == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, gs, SkPdfNativeObject::kDictionary_PdfObjectType, pdfContext);
return kIgnoreError_SkPdfResult;
}
@@ -2320,7 +2420,7 @@ static SkPdfResult PdfOp_gs(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
} else if (gs->isBMAArray(pdfContext->fPdfDoc)) {
skpdfGraphicsStateApplyBM_array(pdfContext, gs->getBMAsArray(pdfContext->fPdfDoc));
} else {
- // TODO(edisonn): report/warn
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "wrong type", gs->get("BM"), SkPdfNativeObject::kArray_PdfObjectType || SkPdfNativeObject::kName_PdfObjectType, pdfContext);
}
}
@@ -2330,7 +2430,7 @@ static SkPdfResult PdfOp_gs(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
} else if (gs->isSMaskADictionary(pdfContext->fPdfDoc)) {
skpdfGraphicsStateApplySMask_dict(pdfContext, gs->getSMaskAsDictionary(pdfContext->fPdfDoc));
} else {
- // TODO(edisonn): report/warn
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "wrong type", gs->get("BM"), SkPdfNativeObject::kDictionary_PdfObjectType || SkPdfNativeObject::kName_PdfObjectType, pdfContext);
}
}
@@ -2353,7 +2453,7 @@ static SkPdfResult PdfOp_gs(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//, to charSpace, which is a number expressed in unscaled text space units. Character spacing is used by the Tj, TJ, and ' operators.
//Initial value: 0.
SkPdfResult PdfOp_Tc(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("Tc", pdfContext, 1);
POP_NUMBER(pdfContext, charSpace);
CHECK_PARAMETERS();
@@ -2368,7 +2468,7 @@ SkPdfResult PdfOp_Tc(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper*
//text space units. Word spacing is used by the Tj, TJ, and ' operators. Initial
//value: 0.
SkPdfResult PdfOp_Tw(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("Tw", pdfContext, 1);
POP_NUMBER(pdfContext, wordSpace);
CHECK_PARAMETERS();
@@ -2381,11 +2481,12 @@ SkPdfResult PdfOp_Tw(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper*
//, to (scale ˜ 100). scale is a number specifying the
//percentage of the normal width. Initial value: 100 (normal width).
static SkPdfResult PdfOp_Tz(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("Tz", pdfContext, 1);
POP_NUMBER(pdfContext, scale);
CHECK_PARAMETERS();
if (scale < 0) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kOutOfRange_SkPdfIssue, "scale must a positive real number", scale_obj, pdfContext);
return kError_SkPdfResult;
}
@@ -2395,11 +2496,12 @@ static SkPdfResult PdfOp_Tz(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//render Tr Set the text rendering mode, T
//mode, to render, which is an integer. Initial value: 0.
static SkPdfResult PdfOp_Tr(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("Tr", pdfContext, 1);
POP_INTEGER(pdfContext, mode);
CHECK_PARAMETERS();
if (mode < 0) { // TODO(edisonn): function/enums with supported modes
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kOutOfRange_SkPdfIssue, "mode must a positive integer or 0", mode_obj, pdfContext);
return kError_SkPdfResult;
}
@@ -2408,11 +2510,12 @@ static SkPdfResult PdfOp_Tr(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//rise Ts Set the text rise, Trise, to rise, which is a number expressed in unscaled text space
//units. Initial value: 0.
static SkPdfResult PdfOp_Ts(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("Ts", pdfContext, 1);
POP_NUMBER(pdfContext, rise);
CHECK_PARAMETERS();
if (rise < 0) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kOutOfRange_SkPdfIssue, "rise must a positive real number", rise_obj, pdfContext);
return kNYI_SkPdfResult;
}
@@ -2421,12 +2524,18 @@ static SkPdfResult PdfOp_Ts(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//wx wy d0
static SkPdfResult PdfOp_d0(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 2);
+ EXPECT_OPERANDS("d0", pdfContext, 2);
POP_NUMBER(pdfContext, wy);
POP_NUMBER(pdfContext, wx);
CHECK_PARAMETERS();
- if (wx < 0 || wy < 0) {
+ if (wx < 0) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kOutOfRange_SkPdfIssue, "wx must a positive real number", wx_obj, pdfContext);
+ return kError_SkPdfResult;
+ }
+
+ if (wy < 0) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kOutOfRange_SkPdfIssue, "wy must a positive real number", wy_obj, pdfContext);
return kError_SkPdfResult;
}
@@ -2435,7 +2544,7 @@ static SkPdfResult PdfOp_d0(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//wx wy llx lly urx ury d1
static SkPdfResult PdfOp_d1(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 6);
+ EXPECT_OPERANDS("d1", pdfContext, 6);
POP_NUMBER(pdfContext, ury);
POP_NUMBER(pdfContext, urx);
POP_NUMBER(pdfContext, lly);
@@ -2444,6 +2553,7 @@ static SkPdfResult PdfOp_d1(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
POP_NUMBER(pdfContext, wx);
CHECK_PARAMETERS();
+ // TODO(edisonn): silly way to remove warning
if (wx + wy + llx + lly + urx + ury) {
return kNYI_SkPdfResult;
}
@@ -2453,11 +2563,12 @@ static SkPdfResult PdfOp_d1(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//name sh
static SkPdfResult PdfOp_sh(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("sh", pdfContext, 1);
POP_NAME(pdfContext, name);
CHECK_PARAMETERS();
if (name == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, name, SkPdfNativeObject::kName_PdfObjectType, pdfContext);
return kError_SkPdfResult;
}
@@ -2466,41 +2577,36 @@ static SkPdfResult PdfOp_sh(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//name Do
static SkPdfResult PdfOp_Do(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("Do", pdfContext, 1);
POP_NAME(pdfContext, name);
CHECK_PARAMETERS();
SkPdfDictionary* xObject = pdfContext->fGraphicsState.fResources->XObject(pdfContext->fPdfDoc);
if (xObject == NULL) {
-#ifdef PDF_TRACE
- printf("XObject is NULL!\n");
-#endif
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingXObject_SkPdfIssue, NULL, pdfContext->fGraphicsState.fResources, pdfContext);
return kIgnoreError_SkPdfResult;
}
SkPdfNativeObject* value = xObject->get(name);
value = pdfContext->fPdfDoc->resolveReference(value);
-#ifdef PDF_TRACE
-// value->ToString(str);
-// printf("Do object value: %s\n", str);
-#endif
-
return doXObject(pdfContext, canvas, value);
}
//tag MP Designate a marked-content point. tag is a name object indicating the role or
//significance of the point.
static SkPdfResult PdfOp_MP(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("MP", pdfContext, 1);
POP_OBJ(pdfContext, tag);
CHECK_PARAMETERS();
if (tag == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, tag, SkPdfNativeObject::_kObject_PdfObjectType, pdfContext);
return kNYI_SkPdfResult;
}
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "MP NYI", NULL, NULL);
return kNYI_SkPdfResult;
}
@@ -2510,29 +2616,38 @@ static SkPdfResult PdfOp_MP(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToken
//associated with it in the Properties subdictionary of the current resource
//dictionary (see Section 9.5.1, “Property Lists”).
static SkPdfResult PdfOp_DP(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 2);
+ EXPECT_OPERANDS("DP", pdfContext, 2);
POP_OBJ(pdfContext, properties);
POP_OBJ(pdfContext, tag);
CHECK_PARAMETERS();
- if (tag == NULL || properties == NULL) {
+ if (tag == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, tag, SkPdfNativeObject::_kObject_PdfObjectType, pdfContext);
+ return kNYI_SkPdfResult;
+ }
+
+ if (properties == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, properties, SkPdfNativeObject::_kObject_PdfObjectType, pdfContext);
return kNYI_SkPdfResult;
}
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "DP NYI", NULL, NULL);
return kNYI_SkPdfResult;
}
//tag BMC Begin a marked-content sequence terminated by a balancing EMC operator.
//tag is a name object indicating the role or significance of the sequence.
static SkPdfResult PdfOp_BMC(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 1);
+ EXPECT_OPERANDS("BMC", pdfContext, 1);
POP_OBJ(pdfContext, tag);
CHECK_PARAMETERS();
if (tag == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, tag, SkPdfNativeObject::_kObject_PdfObjectType, pdfContext);
return kNYI_SkPdfResult;
}
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "BMC NYI", NULL, NULL);
return kNYI_SkPdfResult;
}
@@ -2540,20 +2655,28 @@ static SkPdfResult PdfOp_BMC(SkPdfContext* pdfContext, SkCanvas* canvas, PdfToke
//by a balancing EMCoperator. tag is a name object indicating the role or significance of the sequence; propertiesis either an inline dictionary containing the
//property list or a name object associated with it in the Properties subdictionary of the current resource dictionary (see Section 9.5.1, “Property Lists”).
static SkPdfResult PdfOp_BDC(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
- EXPECT_OPERANDS(pdfContext, 2);
+ EXPECT_OPERANDS("BDC", pdfContext, 2);
POP_OBJ(pdfContext, properties);
POP_OBJ(pdfContext, tag);
CHECK_PARAMETERS();
- if (tag == NULL || properties == NULL) {
+ if (tag == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, tag, SkPdfNativeObject::_kObject_PdfObjectType, pdfContext);
+ return kNYI_SkPdfResult;
+ }
+
+ if (properties == NULL) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, NULL, properties, SkPdfNativeObject::_kObject_PdfObjectType, pdfContext);
return kNYI_SkPdfResult;
}
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "BDC NYI", NULL, NULL);
return kNYI_SkPdfResult;
}
//— EMC End a marked-content sequence begun by a BMC or BDC operator.
static SkPdfResult PdfOp_EMC(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "EMC NYI", NULL, NULL);
return kNYI_SkPdfResult;
}
@@ -2705,7 +2828,8 @@ SkPdfResult PdfMainLooper::consumeToken(PdfToken& token) {
fPdfContext->fObjectStack.push( token.fObject );
}
else {
- // TODO(edisonn): deine or use assert not reached
+ // TODO(edisonn): store the keyword as a object, so we can track the location in file, and report it
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, token.fKeyword, NULL, fPdfContext);
return kIgnoreError_SkPdfResult;
}
return kOK_SkPdfResult;
diff --git a/experimental/PdfViewer/SkPdfRenderer.h b/experimental/PdfViewer/SkPdfRenderer.h
index df8f56c005..0a37c6024f 100644
--- a/experimental/PdfViewer/SkPdfRenderer.h
+++ b/experimental/PdfViewer/SkPdfRenderer.h
@@ -9,11 +9,17 @@
#ifndef SkPdfRenderer_DEFINED
#define SkPdfRenderer_DEFINED
+// TODO(edisonn): how to remove this dependency? Should I remove the ref counting?
+#include "SkRefCnt.h"
+// TODO(edisonn): remove this dependency
+#include "SkString.h"
+
class SkBitmap;
class SkCanvas;
class SkPdfNativeDoc;
struct SkRect;
class SkStream;
+class SkString;
enum SkPdfContent {
kNoForms_SkPdfContent,
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp
index f278ea1a2e..ef5276bf30 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp
@@ -8,6 +8,7 @@
#include "SkPdfNativeDoc.h"
#include "SkPdfNativeTokenizer.h"
#include "SkPdfNativeObject.h"
+#include "SkPdfReporter.h"
#include <stdio.h>
#include <string.h>
@@ -107,7 +108,7 @@ SkPdfNativeDoc::SkPdfNativeDoc(const char* path)
fclose(file);
if (!ok) {
sk_free(content);
- // TODO(edisonn): report read error
+ SkPdfReport(kFatalError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "could not read file", NULL, NULL);
// TODO(edisonn): not nice to return like this from constructor, create a static
// function that can report NULL for failures.
return; // Doc will have 0 pages
@@ -125,7 +126,7 @@ void SkPdfNativeDoc::init(const void* bytes, size_t length) {
const unsigned char* xrefstartKeywordLine = previousLineHome(fFileContent, xrefByteOffsetLine);
if (strcmp((char*)xrefstartKeywordLine, "startxref") != 0) {
- // TODO(edisonn): report/issue
+ SkPdfReport(kWarning_SkPdfIssueSeverity, kMissingToken_SkPdfIssue, "Could not find startxref", NULL, NULL);
}
long xrefByteOffset = atol((const char*)xrefByteOffsetLine);
@@ -189,6 +190,7 @@ void SkPdfNativeDoc::loadWithoutXRef() {
current = nextObject(0, current, end, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
// TODO(edisonn): must be obj, return error if not? ignore ?
if (!token.isKeyword("obj")) {
+ SkPdfReport(kWarning_SkPdfIssueSeverity, kMissingToken_SkPdfIssue, "Could not find obj", NULL, NULL);
continue;
}
@@ -203,6 +205,8 @@ void SkPdfNativeDoc::loadWithoutXRef() {
fObjects[id].fResolvedReference = obj;
fObjects[id].fObj = obj;
+ fObjects[id].fIsReferenceResolved = true;
+
// set objects
} else if (token.isKeyword("trailer")) {
@@ -227,7 +231,6 @@ void SkPdfNativeDoc::loadWithoutXRef() {
}
}
-
if (fRootCatalogRef) {
fRootCatalog = (SkPdfCatalogDictionary*)resolveReference(fRootCatalogRef);
if (fRootCatalog->isDictionary() && fRootCatalog->valid()) {
@@ -252,6 +255,7 @@ const unsigned char* SkPdfNativeDoc::readCrossReferenceSection(const unsigned ch
const unsigned char* current = nextObject(0, xrefStart, trailerEnd, &xref, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
if (!xref.isKeyword("xref")) {
+ SkPdfReport(kWarning_SkPdfIssueSeverity, kMissingToken_SkPdfIssue, "Could not find sref", NULL, NULL);
return trailerEnd;
}
@@ -261,6 +265,7 @@ const unsigned char* SkPdfNativeDoc::readCrossReferenceSection(const unsigned ch
const unsigned char* previous = current;
current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
if (!token.isInteger()) {
+ SkPdfReport(kInfo_SkPdfIssueSeverity, kNoIssue_SkPdfIssue, "Done readCrossReferenceSection", NULL, NULL);
return previous;
}
@@ -269,7 +274,7 @@ const unsigned char* SkPdfNativeDoc::readCrossReferenceSection(const unsigned ch
current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
if (!token.isInteger()) {
- // TODO(edisonn): report/warning
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readCrossReferenceSection", &token, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
return current;
}
@@ -279,7 +284,7 @@ const unsigned char* SkPdfNativeDoc::readCrossReferenceSection(const unsigned ch
token.reset();
current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
if (!token.isInteger()) {
- // TODO(edisonn): report/warning
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readCrossReferenceSection", &token, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
return current;
}
int offset = (int)token.intValue();
@@ -287,7 +292,7 @@ const unsigned char* SkPdfNativeDoc::readCrossReferenceSection(const unsigned ch
token.reset();
current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
if (!token.isInteger()) {
- // TODO(edisonn): report/warning
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readCrossReferenceSection", &token, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
return current;
}
int generation = (int)token.intValue();
@@ -295,14 +300,14 @@ const unsigned char* SkPdfNativeDoc::readCrossReferenceSection(const unsigned ch
token.reset();
current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
if (!token.isKeyword() || token.lenstr() != 1 || (*token.c_str() != 'f' && *token.c_str() != 'n')) {
- // TODO(edisonn): report/warning
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readCrossReferenceSection: f or n expected", &token, SkPdfNativeObject::kKeyword_PdfObjectType, NULL);
return current;
}
addCrossSectionInfo(startId + i, generation, offset, *token.c_str() == 'f');
}
}
- // TODO(edisonn): it should never get here? there is no trailer?
+ SkPdfReport(kInfo_SkPdfIssueSeverity, kNoIssue_SkPdfIssue, "Unexpected end of readCrossReferenceSection", NULL, NULL);
return current;
}
@@ -319,6 +324,7 @@ const unsigned char* SkPdfNativeDoc::readTrailer(const unsigned char* trailerSta
if (!trailerKeyword.isKeyword() || strlen("trailer") != trailerKeyword.lenstr() ||
strncmp(trailerKeyword.c_str(), "trailer", strlen("trailer")) != 0) {
// TODO(edisonn): report warning, rebuild trailer from objects.
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readTrailer: trailer keyword expected", &trailerKeyword, SkPdfNativeObject::kKeyword_PdfObjectType, NULL);
return current;
}
}
@@ -336,7 +342,7 @@ const unsigned char* SkPdfNativeDoc::readTrailer(const unsigned char* trailerSta
if (storeCatalog) {
SkPdfNativeObject* ref = trailer->Root(NULL);
if (ref == NULL || !ref->isReference()) {
- // TODO(edisonn): oops, we have to fix the corrup pdf file
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readTrailer: unexpected root reference", ref, SkPdfNativeObject::kReference_PdfObjectType, NULL);
return current;
}
fRootCatalogRef = ref;
@@ -381,28 +387,33 @@ SkPdfNativeObject* SkPdfNativeDoc::readObject(int id/*, int expectedGeneration*/
current = nextObject(0, current, end, &idObj, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
if (current >= end) {
- // TODO(edisonn): report warning/error
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "reading id", NULL, NULL);
return NULL;
}
current = nextObject(0, current, end, &generationObj, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
if (current >= end) {
- // TODO(edisonn): report warning/error
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "reading generation", NULL, NULL);
return NULL;
}
current = nextObject(0, current, end, &objKeyword, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
if (current >= end) {
- // TODO(edisonn): report warning/error
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "reading keyword obj", NULL, NULL);
return NULL;
}
- if (!idObj.isInteger() || !generationObj.isInteger() || id != idObj.intValue()/* || generation != generationObj.intValue()*/) {
- // TODO(edisonn): report warning/error
+ if (!idObj.isInteger() || id != idObj.intValue()) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readObject: unexpected id", &idObj, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
+ }
+
+ // TODO(edisonn): verify that the generation is the right one
+ if (!generationObj.isInteger() /* || generation != generationObj.intValue()*/) {
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readObject: unexpected generation", &generationObj, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
}
if (!objKeyword.isKeyword() || strcmp(objKeyword.c_str(), "obj") != 0) {
- // TODO(edisonn): report warning/error
+ SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readObject: unexpected obj keyword", &objKeyword, SkPdfNativeObject::kKeyword_PdfObjectType, NULL);
}
current = nextObject(1, current, end, dict, fAllocator, this PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
@@ -543,7 +554,7 @@ SkPdfNativeObject* SkPdfNativeDoc::resolveReference(SkPdfNativeObject* ref) {
// TODO(edisonn): verify id and gen expected
if (id < 0 || id >= fObjects.count()) {
- // TODO(edisonn): report error/warning
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "resolve reference id out of bounds", NULL, NULL);
return NULL;
}
@@ -553,7 +564,7 @@ SkPdfNativeObject* SkPdfNativeDoc::resolveReference(SkPdfNativeObject* ref) {
printf("\nresolve(%s) = %s\n", ref->toString(0).c_str(), fObjects[id].fResolvedReference->toString(0, ref->toString().size() + 13).c_str());
#endif
- // TODO(edisonn): for known good documents, assert here THAT THE REFERENCE IS NOT null
+ SkPdfReportIf(!fObjects[id].fResolvedReference, kIgnoreError_SkPdfIssueSeverity, kBadReference_SkPdfIssue, "ref is NULL", NULL, NULL);
return fObjects[id].fResolvedReference;
}
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp
index 54daf17275..73f765d3c7 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp
@@ -18,11 +18,13 @@
#include "SkBitmap.h"
#include "SkPdfFont.h"
+#include "SkPdfReporter.h"
+
SkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull(PUT_TRACK_PARAMETERS_SRC0);
bool SkPdfNativeObject::applyFlateDecodeFilter() {
if (!SkFlate::HaveFlate()) {
- // TODO(edisonn): warn, make callers handle it
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNoFlateLibrary_SkPdfIssue, "forgot to link with flate library?", NULL, NULL);
return false;
}
@@ -43,7 +45,7 @@ bool SkPdfNativeObject::applyFlateDecodeFilter() {
return true;
} else {
- // TODO(edisonn): warn, make callers handle it
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "inflate failed", this, NULL);
return false;
}
}
@@ -61,7 +63,7 @@ bool SkPdfNativeObject::applyFilter(const char* name) {
} else if (strcmp(name, "DCTDecode") == 0) {
return applyDCTDecodeFilter();
}
- // TODO(edisonn): allert, not supported, but should be implemented asap
+ SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "filter not supported", this, NULL);
return false;
}
@@ -69,6 +71,7 @@ bool SkPdfNativeObject::filterStream() {
SkPdfMarkObjectUsed();
if (!hasStream()) {
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "No Stream", this, NULL);
return false;
}
@@ -93,7 +96,7 @@ bool SkPdfNativeObject::filterStream() {
break;
}
} else {
- // TODO(edisonn): report warning
+ SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncositentSyntax_SkPdfIssue, "filter name should be a Name", this, NULL);
}
}
}
@@ -102,7 +105,9 @@ bool SkPdfNativeObject::filterStream() {
}
void SkPdfNativeObject::releaseData() {
- // TODO(edisonn): report here unused objects
+#ifdef PDF_TRACK_OBJECT_USAGE
+ SkPdfReportIf(!fUsed, kInfo_SkPdfIssueSeverity, NULL, this, "Unused object in rendering");
+#endif // PDF_TRACK_OBJECT_USAGE
SkPdfMarkObjectUnused();
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h
index 344d6c668d..94c0547c22 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h
@@ -38,25 +38,31 @@ SkMatrix SkMatrixFromPdfMatrix(double array[6]);
class SkPdfNativeObject {
public:
enum ObjectType {
- kInvalid_PdfObjectType,
-
- kBoolean_PdfObjectType,
- kInteger_PdfObjectType,
- kReal_PdfObjectType,
- kString_PdfObjectType,
- kHexString_PdfObjectType,
- kName_PdfObjectType,
- kKeyword_PdfObjectType,
- //kStream_PdfObjectType, // attached to a Dictionary
- kArray_PdfObjectType,
- kDictionary_PdfObjectType,
- kNull_PdfObjectType,
+ // The type will have only one of these values, but for error reporting, we make it an enum
+ // so it can easily report that something was expected to be one of a few types
+ kInvalid_PdfObjectType = 1 << 1,
+
+ kBoolean_PdfObjectType = 1 << 2,
+ kInteger_PdfObjectType = 1 << 3,
+ kReal_PdfObjectType = 1 << 4,
+ _kNumber_PdfObjectType = kInteger_PdfObjectType | kReal_PdfObjectType,
+ kString_PdfObjectType = 1 << 5,
+ kHexString_PdfObjectType = 1 << 6,
+ _kAnyString_PdfObjectType = kString_PdfObjectType | kHexString_PdfObjectType,
+ kName_PdfObjectType = 1 << 7,
+ kKeyword_PdfObjectType = 1 << 8,
+ _kStream_PdfObjectType = 1 << 9, // attached to a Dictionary, do not use
+ kArray_PdfObjectType = 1 << 10,
+ kDictionary_PdfObjectType = 1 << 11,
+ kNull_PdfObjectType = 1 << 12,
// TODO(edisonn): after the pdf has been loaded completely, resolve all references
// try the same thing with delayed loaded ...
- kReference_PdfObjectType,
+ kReference_PdfObjectType = 1 << 13,
- kUndefined_PdfObjectType, // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined
+ kUndefined_PdfObjectType = 1 << 14, // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined
+
+ _kObject_PdfObjectType = -1,
};
enum DataType {
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
index 4e0e4c404a..64388552a5 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
@@ -811,11 +811,15 @@ const unsigned char* nextObject(int level, const unsigned char* start, const uns
// skip white spaces
start = skipPdfWhiteSpaces(level, start, end);
+ if (start >= end) {
+ return end;
+ }
+
current = endOfPdfToken(level, start, end);
// no token, len would be 0
- if (current == start) {
- return NULL;
+ if (current == start || current == end) {
+ return end;
}
int tokenLen = current - start;