| Index: experimental/PdfViewer/SkPdfRenderer.cpp
|
| ===================================================================
|
| --- experimental/PdfViewer/SkPdfRenderer.cpp (revision 10851)
|
| +++ experimental/PdfViewer/SkPdfRenderer.cpp (working copy)
|
| @@ -71,6 +71,116 @@
|
| * - deal with specific type in spec directly, add all dictionary types to known types
|
| */
|
|
|
| +#define EXPECT_OPERANDS(pdfContext,n) \
|
| + bool __failed = pdfContext->fObjectStack.count() < n; \
|
| + SkDEBUGCODE(int __cnt = n);
|
| +
|
| +#define POP_OBJ(pdfContext,name) \
|
| + SkDEBUGCODE(__cnt--); \
|
| + SkASSERT(__cnt >= 0); \
|
| + SkPdfNativeObject* name = NULL; \
|
| + __failed = __failed || pdfContext->fObjectStack.count() == 0; \
|
| + if (pdfContext->fObjectStack.count() > 0) { \
|
| + name = pdfContext->fObjectStack.top(); \
|
| + pdfContext->fObjectStack.pop(); \
|
| + }
|
| +
|
| +#define POP_NUMBER(pdfContext,name) \
|
| + SkDEBUGCODE(__cnt--); \
|
| + SkASSERT(__cnt >= 0); \
|
| + double name = 0; \
|
| + __failed = __failed || pdfContext->fObjectStack.count() == 0; \
|
| + if (pdfContext->fObjectStack.count() > 0) { \
|
| + SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
|
| + pdfContext->fObjectStack.pop(); \
|
| + if (!tmp || !tmp->isNumber()) { \
|
| + __failed = true;\
|
| + } else { \
|
| + name = tmp->numberValue(); \
|
| + } \
|
| + }
|
| +
|
| +#define POP_INTEGER(pdfContext,name) \
|
| + SkDEBUGCODE(__cnt--); \
|
| + SkASSERT(__cnt >= 0); \
|
| + int64_t name = 0; \
|
| + __failed = __failed || pdfContext->fObjectStack.count() == 0; \
|
| + if (pdfContext->fObjectStack.count() > 0) { \
|
| + SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
|
| + pdfContext->fObjectStack.pop(); \
|
| + if (!tmp || !tmp->isInteger()) { \
|
| + __failed = true;\
|
| + } else { \
|
| + name = tmp->intValue(); \
|
| + } \
|
| + }
|
| +
|
| +#define POP_NUMBER_INTO(pdfContext,var) \
|
| + SkDEBUGCODE(__cnt--); \
|
| + SkASSERT(__cnt >= 0); \
|
| + __failed = __failed || pdfContext->fObjectStack.count() == 0; \
|
| + if (pdfContext->fObjectStack.count() > 0) { \
|
| + SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
|
| + pdfContext->fObjectStack.pop(); \
|
| + if (!tmp || !tmp->isNumber()) { \
|
| + __failed = true;\
|
| + } else { \
|
| + var = tmp->numberValue(); \
|
| + } \
|
| + }
|
| +
|
| +
|
| +#define POP_NAME(pdfContext,name) \
|
| + SkDEBUGCODE(__cnt--); \
|
| + SkASSERT(__cnt >= 0); \
|
| + SkPdfNativeObject* name = NULL; \
|
| + __failed = __failed || pdfContext->fObjectStack.count() == 0; \
|
| + if (pdfContext->fObjectStack.count() > 0) { \
|
| + SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
|
| + pdfContext->fObjectStack.pop(); \
|
| + if (!tmp || !tmp->isName()) { \
|
| + __failed = true;\
|
| + } else { \
|
| + name = tmp; \
|
| + } \
|
| + }
|
| +
|
| +#define POP_STRING(pdfContext,name) \
|
| + SkDEBUGCODE(__cnt--); \
|
| + SkASSERT(__cnt >= 0); \
|
| + SkPdfNativeObject* name = NULL; \
|
| + __failed = __failed || pdfContext->fObjectStack.count() == 0; \
|
| + if (pdfContext->fObjectStack.count() > 0) { \
|
| + SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
|
| + pdfContext->fObjectStack.pop(); \
|
| + if (!tmp || !tmp->isAnyString()) { \
|
| + __failed = true;\
|
| + } else { \
|
| + name = tmp; \
|
| + } \
|
| + }
|
| +
|
| +#define POP_ARRAY(pdfContext,name) \
|
| + SkDEBUGCODE(__cnt--); \
|
| + SkASSERT(__cnt >= 0); \
|
| + SkPdfArray* name = NULL; \
|
| + __failed = __failed || pdfContext->fObjectStack.count() == 0; \
|
| + if (pdfContext->fObjectStack.count() > 0) { \
|
| + SkPdfNativeObject* tmp = pdfContext->fObjectStack.top(); \
|
| + pdfContext->fObjectStack.pop(); \
|
| + if (!tmp || !tmp->isArray()) { \
|
| + __failed = true;\
|
| + } else { \
|
| + name = (SkPdfArray*)tmp; \
|
| + } \
|
| + }
|
| +
|
| +// TODO(edisonn): ability to turn on asserts for known good files
|
| +// log error - add name of function? location in file?
|
| +#define CHECK_PARAMETERS() \
|
| + SkASSERT(__cnt == 0); \
|
| + if (__failed) return kIgnoreError_SkPdfResult;
|
| +
|
| NotOwnedString strings_DeviceRGB;
|
| NotOwnedString strings_DeviceCMYK;
|
|
|
| @@ -971,6 +1081,8 @@
|
| }
|
|
|
| SkPdfResult PdfOp_q(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| + // TODO(edisonn): create a new stack of parameters, so once we start a q,
|
| + // it is not possible to see under the previous q?
|
| pdfContext->fStateStack.push(pdfContext->fGraphicsState);
|
| canvas->save();
|
| return kOK_SkPdfResult;
|
| @@ -984,11 +1096,15 @@
|
| }
|
|
|
| static SkPdfResult PdfOp_cm(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| - double array[6];
|
| - for (int i = 0 ; i < 6 ; i++) {
|
| - array[5 - i] = pdfContext->fObjectStack.top()->numberValue();
|
| - pdfContext->fObjectStack.pop();
|
| - }
|
| + EXPECT_OPERANDS(pdfContext, 6);
|
| + POP_NUMBER(pdfContext, f);
|
| + POP_NUMBER(pdfContext, e);
|
| + POP_NUMBER(pdfContext, d);
|
| + POP_NUMBER(pdfContext, c);
|
| + POP_NUMBER(pdfContext, b);
|
| + POP_NUMBER(pdfContext, a);
|
| + CHECK_PARAMETERS();
|
| + double array[6] = {a, b, c, d, e, f};
|
|
|
| // a b
|
| // c d
|
| @@ -1021,7 +1137,9 @@
|
| //, 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) {
|
| - double ty = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1)
|
| + POP_NUMBER(pdfContext, ty);
|
| + CHECK_PARAMETERS();
|
|
|
| pdfContext->fGraphicsState.fTextLeading = ty;
|
|
|
| @@ -1029,11 +1147,10 @@
|
| }
|
|
|
| static SkPdfResult PdfOp_Td(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| -#ifdef PDF_TRACE
|
| - printf("stack size = %i\n", (int)pdfContext->fObjectStack.size());
|
| -#endif
|
| - double ty = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double tx = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 2);
|
| + POP_NUMBER(pdfContext, ty);
|
| + POP_NUMBER(pdfContext, tx);
|
| + CHECK_PARAMETERS();
|
|
|
| double array[6] = {1, 0, 0, 1, tx, -ty};
|
| SkMatrix matrix = SkMatrixFromPdfMatrix(array);
|
| @@ -1045,8 +1162,10 @@
|
| }
|
|
|
| static SkPdfResult PdfOp_TD(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| - double ty = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double tx = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 2)
|
| + POP_NUMBER(pdfContext, ty);
|
| + POP_NUMBER(pdfContext, tx);
|
| + CHECK_PARAMETERS();
|
|
|
| // TODO(edisonn): Create factory methods or constructors so native is hidden
|
| SkPdfReal* _ty = pdfContext->fPdfDoc->createReal(-ty);
|
| @@ -1069,12 +1188,14 @@
|
| }
|
|
|
| static SkPdfResult PdfOp_Tm(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| - double f = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double e = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double d = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double c = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double b = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double a = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 6);
|
| + POP_NUMBER(pdfContext, f);
|
| + POP_NUMBER(pdfContext, e);
|
| + POP_NUMBER(pdfContext, d);
|
| + POP_NUMBER(pdfContext, c);
|
| + POP_NUMBER(pdfContext, b);
|
| + POP_NUMBER(pdfContext, a);
|
| + CHECK_PARAMETERS();
|
|
|
| double array[6];
|
| array[0] = a;
|
| @@ -1116,11 +1237,16 @@
|
| pdfContext->fGraphicsState.fPathClosed = false;
|
| }
|
|
|
| - pdfContext->fGraphicsState.fCurPosY = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - pdfContext->fGraphicsState.fCurPosX = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 2);
|
| + POP_NUMBER(pdfContext, y);
|
| + POP_NUMBER(pdfContext, x);
|
| + CHECK_PARAMETERS();
|
|
|
| + pdfContext->fGraphicsState.fCurPosY = y;
|
| + pdfContext->fGraphicsState.fCurPosX = x;
|
| +
|
| pdfContext->fGraphicsState.fPath.moveTo(SkDoubleToScalar(pdfContext->fGraphicsState.fCurPosX),
|
| - SkDoubleToScalar(pdfContext->fGraphicsState.fCurPosY));
|
| + SkDoubleToScalar(pdfContext->fGraphicsState.fCurPosY));
|
|
|
| return kOK_SkPdfResult;
|
| }
|
| @@ -1131,11 +1257,16 @@
|
| pdfContext->fGraphicsState.fPathClosed = false;
|
| }
|
|
|
| - pdfContext->fGraphicsState.fCurPosY = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - pdfContext->fGraphicsState.fCurPosX = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 2);
|
| + POP_NUMBER(pdfContext, y);
|
| + POP_NUMBER(pdfContext, x);
|
| + CHECK_PARAMETERS();
|
|
|
| + pdfContext->fGraphicsState.fCurPosY = y;
|
| + pdfContext->fGraphicsState.fCurPosX = x;
|
| +
|
| pdfContext->fGraphicsState.fPath.lineTo(SkDoubleToScalar(pdfContext->fGraphicsState.fCurPosX),
|
| - SkDoubleToScalar(pdfContext->fGraphicsState.fCurPosY));
|
| + SkDoubleToScalar(pdfContext->fGraphicsState.fCurPosY));
|
|
|
| return kOK_SkPdfResult;
|
| }
|
| @@ -1146,16 +1277,18 @@
|
| pdfContext->fGraphicsState.fPathClosed = false;
|
| }
|
|
|
| - double y3 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double x3 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double y2 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double x2 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double y1 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double x1 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 6);
|
| + POP_NUMBER(pdfContext, y3);
|
| + POP_NUMBER(pdfContext, x3);
|
| + POP_NUMBER(pdfContext, y2);
|
| + POP_NUMBER(pdfContext, x2);
|
| + POP_NUMBER(pdfContext, y1);
|
| + POP_NUMBER(pdfContext, x1);
|
| + CHECK_PARAMETERS();
|
|
|
| pdfContext->fGraphicsState.fPath.cubicTo(SkDoubleToScalar(x1), SkDoubleToScalar(y1),
|
| - SkDoubleToScalar(x2), SkDoubleToScalar(y2),
|
| - SkDoubleToScalar(x3), SkDoubleToScalar(y3));
|
| + SkDoubleToScalar(x2), SkDoubleToScalar(y2),
|
| + SkDoubleToScalar(x3), SkDoubleToScalar(y3));
|
|
|
| pdfContext->fGraphicsState.fCurPosX = x3;
|
| pdfContext->fGraphicsState.fCurPosY = y3;
|
| @@ -1169,16 +1302,19 @@
|
| pdfContext->fGraphicsState.fPathClosed = false;
|
| }
|
|
|
| - double y3 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double x3 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double y2 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double x2 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 4);
|
| + POP_NUMBER(pdfContext, y3);
|
| + POP_NUMBER(pdfContext, x3);
|
| + POP_NUMBER(pdfContext, y2);
|
| + POP_NUMBER(pdfContext, x2);
|
| + CHECK_PARAMETERS();
|
| +
|
| double y1 = pdfContext->fGraphicsState.fCurPosY;
|
| double x1 = pdfContext->fGraphicsState.fCurPosX;
|
|
|
| pdfContext->fGraphicsState.fPath.cubicTo(SkDoubleToScalar(x1), SkDoubleToScalar(y1),
|
| - SkDoubleToScalar(x2), SkDoubleToScalar(y2),
|
| - SkDoubleToScalar(x3), SkDoubleToScalar(y3));
|
| + SkDoubleToScalar(x2), SkDoubleToScalar(y2),
|
| + SkDoubleToScalar(x3), SkDoubleToScalar(y3));
|
|
|
| pdfContext->fGraphicsState.fCurPosX = x3;
|
| pdfContext->fGraphicsState.fCurPosY = y3;
|
| @@ -1192,16 +1328,19 @@
|
| pdfContext->fGraphicsState.fPathClosed = false;
|
| }
|
|
|
| - double y3 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double x3 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 4);
|
| + POP_NUMBER(pdfContext, y3);
|
| + POP_NUMBER(pdfContext, x3);
|
| + POP_NUMBER(pdfContext, y1);
|
| + POP_NUMBER(pdfContext, x1);
|
| + CHECK_PARAMETERS();
|
| +
|
| double y2 = pdfContext->fGraphicsState.fCurPosY;
|
| double x2 = pdfContext->fGraphicsState.fCurPosX;
|
| - double y1 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double x1 = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
|
|
| pdfContext->fGraphicsState.fPath.cubicTo(SkDoubleToScalar(x1), SkDoubleToScalar(y1),
|
| - SkDoubleToScalar(x2), SkDoubleToScalar(y2),
|
| - SkDoubleToScalar(x3), SkDoubleToScalar(y3));
|
| + SkDoubleToScalar(x2), SkDoubleToScalar(y2),
|
| + SkDoubleToScalar(x3), SkDoubleToScalar(y3));
|
|
|
| pdfContext->fGraphicsState.fCurPosX = x3;
|
| pdfContext->fGraphicsState.fCurPosY = y3;
|
| @@ -1215,13 +1354,15 @@
|
| pdfContext->fGraphicsState.fPathClosed = false;
|
| }
|
|
|
| - double height = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double width = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double y = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double x = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 4);
|
| + POP_NUMBER(pdfContext, height);
|
| + POP_NUMBER(pdfContext, width);
|
| + POP_NUMBER(pdfContext, y);
|
| + POP_NUMBER(pdfContext, x);
|
| + CHECK_PARAMETERS();
|
|
|
| pdfContext->fGraphicsState.fPath.addRect(SkDoubleToScalar(x), SkDoubleToScalar(y),
|
| - SkDoubleToScalar(x + width), SkDoubleToScalar(y + height));
|
| + SkDoubleToScalar(x + width), SkDoubleToScalar(y + height));
|
|
|
| pdfContext->fGraphicsState.fCurPosX = x;
|
| pdfContext->fGraphicsState.fCurPosY = y + height;
|
| @@ -1469,21 +1610,25 @@
|
| //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) {
|
| - double fontSize = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - SkPdfNativeObject* fontName = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 2);
|
| + POP_NUMBER(pdfContext, fontSize);
|
| + POP_NAME(pdfContext, fontName);
|
| + CHECK_PARAMETERS();
|
| +
|
| return skpdfGraphicsStateApplyFontCore(pdfContext, fontName, fontSize);
|
| }
|
|
|
| static SkPdfResult PdfOp_Tj(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_STRING(pdfContext, str);
|
| + CHECK_PARAMETERS();
|
| +
|
| if (!pdfContext->fGraphicsState.fTextBlock) {
|
| // TODO(edisonn): try to recover and draw it any way?
|
| return kIgnoreError_SkPdfResult;
|
| }
|
|
|
| - SkPdfResult ret = DrawText(pdfContext,
|
| - pdfContext->fObjectStack.top(),
|
| - canvas);
|
| - pdfContext->fObjectStack.pop();
|
| + SkPdfResult ret = DrawText(pdfContext, str, canvas);
|
|
|
| return ret;
|
| }
|
| @@ -1505,9 +1650,11 @@
|
| return kIgnoreError_SkPdfResult;
|
| }
|
|
|
| - SkPdfNativeObject* str = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
| - SkPdfNativeObject* ac = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
| - SkPdfNativeObject* aw = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 3);
|
| + POP_OBJ(pdfContext, str);
|
| + POP_OBJ(pdfContext, ac);
|
| + POP_OBJ(pdfContext, aw);
|
| + CHECK_PARAMETERS();
|
|
|
| pdfContext->fObjectStack.push(aw);
|
| PdfOp_Tw(pdfContext, canvas, looper);
|
| @@ -1522,14 +1669,15 @@
|
| }
|
|
|
| static SkPdfResult PdfOp_TJ(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_ARRAY(pdfContext, array);
|
| + CHECK_PARAMETERS();
|
| +
|
| if (!pdfContext->fGraphicsState.fTextBlock) {
|
| // TODO(edisonn): try to recover and draw it any way?
|
| return kIgnoreError_SkPdfResult;
|
| }
|
|
|
| - SkPdfArray* array = (SkPdfArray*)pdfContext->fObjectStack.top();
|
| - pdfContext->fObjectStack.pop();
|
| -
|
| if (!array->isArray()) {
|
| return kIgnoreError_SkPdfResult;
|
| }
|
| @@ -1538,9 +1686,7 @@
|
| {
|
| if( (*array)[i]->isAnyString()) {
|
| SkPdfNativeObject* obj = (*array)[i];
|
| - DrawText(pdfContext,
|
| - obj,
|
| - canvas);
|
| + DrawText(pdfContext, obj, canvas);
|
| } else if ((*array)[i]->isNumber()) {
|
| double dx = (*array)[i]->numberValue();
|
| SkMatrix matrix;
|
| @@ -1562,7 +1708,9 @@
|
| }
|
|
|
| static SkPdfResult PdfOp_CS_cs(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
|
| - SkPdfNativeObject* name = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NAME(pdfContext, name);
|
| + CHECK_PARAMETERS();
|
|
|
| //Next, get the ColorSpace Dictionary from the Resource Dictionary:
|
| SkPdfDictionary* colorSpaceResource = pdfContext->fGraphicsState.fResources->ColorSpace(pdfContext->fPdfDoc);
|
| @@ -1630,13 +1778,16 @@
|
| printf("color space = %s, N = %i\n", colorOperator->fColorSpace.fBuffer, n);
|
| #endif
|
|
|
| + EXPECT_OPERANDS(pdfContext, n);
|
| +
|
| for (int i = n - 1; i >= 0 ; i--) {
|
| if (doubles) {
|
| - c[i] = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + POP_NUMBER_INTO(pdfContext, c[i]);
|
| // } else {
|
| // v[i] = pdfContext->fObjectStack.top()->intValue(); pdfContext->fObjectStack.pop();
|
| }
|
| }
|
| + CHECK_PARAMETERS();
|
|
|
| // TODO(edisonn): Now, set that color. Only DeviceRGB supported.
|
| // TODO(edisonn): do possible field values to enum at parsing time!
|
| @@ -1656,7 +1807,7 @@
|
| }
|
|
|
| static SkPdfResult PdfOp_SCN_scn(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
|
| - if (pdfContext->fObjectStack.top()->isName()) {
|
| + if (pdfContext->fObjectStack.count() > 0 && pdfContext->fObjectStack.top()->isName()) {
|
| SkPdfNativeObject* name = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
|
|
| //Next, get the ExtGState Dictionary from the Resource Dictionary:
|
| @@ -1687,8 +1838,14 @@
|
| }
|
|
|
| static SkPdfResult PdfOp_G_g(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
|
| - /*double gray = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - return kNYI_SkPdfResult;
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, gray);
|
| + CHECK_PARAMETERS();
|
| +
|
| + colorOperator->fColorSpace = strings_DeviceRGB; // TODO(edisonn): HACK - it should be device gray, but not suported right now
|
| + colorOperator->setRGBColor(SkColorSetRGB((U8CPU)(255*gray), (U8CPU)(255*gray), (U8CPU)(255*gray)));
|
| +
|
| + return kPartial_SkPdfResult;
|
| }
|
|
|
| static SkPdfResult PdfOp_G(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| @@ -1700,9 +1857,11 @@
|
| }
|
|
|
| static SkPdfResult PdfOp_RG_rg(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
|
| - double b = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double g = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - double r = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 3);
|
| + POP_NUMBER(pdfContext, b);
|
| + POP_NUMBER(pdfContext, g);
|
| + POP_NUMBER(pdfContext, r);
|
| + CHECK_PARAMETERS();
|
|
|
| colorOperator->fColorSpace = strings_DeviceRGB;
|
| colorOperator->setRGBColor(SkColorSetRGB((U8CPU)(255*r), (U8CPU)(255*g), (U8CPU)(255*b)));
|
| @@ -1719,12 +1878,19 @@
|
|
|
| static SkPdfResult PdfOp_K_k(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
|
| // TODO(edisonn): spec has some rules about overprint, implement them.
|
| - /*double k = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - /*double y = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - /*double m = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - /*double c = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 4);
|
| + POP_NUMBER(pdfContext, k);
|
| + POP_NUMBER(pdfContext, y);
|
| + POP_NUMBER(pdfContext, m);
|
| + POP_NUMBER(pdfContext, c);
|
| + CHECK_PARAMETERS();
|
|
|
| - colorOperator->fColorSpace = strings_DeviceCMYK;
|
| + // TODO(edisonn): silly way to remove compiler warning
|
| + if (k + y + m + c == 0) {
|
| + return kNYI_SkPdfResult;
|
| + }
|
| +
|
| + //colorOperator->fColorSpace = strings_DeviceCMYK;
|
| // TODO(edisonn): Set color.
|
| return kNYI_SkPdfResult;
|
| }
|
| @@ -1887,41 +2053,50 @@
|
|
|
| //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) {
|
| - double lw = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, lw);
|
| + CHECK_PARAMETERS();
|
| +
|
| return skpdfGraphicsStateApplyLW(pdfContext, lw);
|
| }
|
|
|
| //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?
|
| - int lc = (int)pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - return skpdfGraphicsStateApplyLC(pdfContext, lc);
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, lc);
|
| + CHECK_PARAMETERS();
|
| +
|
| + return skpdfGraphicsStateApplyLC(pdfContext, (int)lc);
|
| }
|
|
|
| //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?
|
| - int lj = (int)pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| - return skpdfGraphicsStateApplyLJ(pdfContext, lj);
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, lj);
|
| + CHECK_PARAMETERS();
|
| +
|
| + return skpdfGraphicsStateApplyLJ(pdfContext, (int)lj);
|
| }
|
|
|
| //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) {
|
| - double ml = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, ml);
|
| + CHECK_PARAMETERS();
|
| return skpdfGraphicsStateApplyML(pdfContext, ml);
|
| }
|
|
|
| //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) {
|
| - SkPdfNativeObject* phase = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
| - SkPdfNativeObject* array = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 2);
|
| + POP_OBJ(pdfContext, phase);
|
| + POP_ARRAY(pdfContext, array);
|
| + CHECK_PARAMETERS();
|
|
|
| - if (!array->isArray()) {
|
| - return kIgnoreError_SkPdfResult;
|
| - }
|
| -
|
| - return skpdfGraphicsStateApplyD(pdfContext, (SkPdfArray*)array, phase);
|
| + return skpdfGraphicsStateApplyD(pdfContext, array, phase);
|
| }
|
|
|
| //intent ri (PDF 1.1) Set the color rendering intent in the graphics state (see “Rendering Intents” on page 197).
|
| @@ -1935,8 +2110,14 @@
|
| //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) {
|
| - pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, flatness);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (flatness < 0 || flatness > 100) {
|
| + return kError_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
|
|
| @@ -2065,7 +2246,9 @@
|
| //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) {
|
| - SkPdfNativeObject* name = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NAME(pdfContext, name);
|
| + CHECK_PARAMETERS();
|
|
|
| #ifdef PDF_TRACE
|
| SkString str;
|
| @@ -2156,7 +2339,10 @@
|
| //, 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) {
|
| - double charSpace = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, charSpace);
|
| + CHECK_PARAMETERS();
|
| +
|
| pdfContext->fGraphicsState.fCharSpace = charSpace;
|
|
|
| return kOK_SkPdfResult;
|
| @@ -2168,7 +2354,10 @@
|
| //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) {
|
| - double wordSpace = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, wordSpace);
|
| + CHECK_PARAMETERS();
|
| +
|
| pdfContext->fGraphicsState.fWordSpace = wordSpace;
|
|
|
| return kOK_SkPdfResult;
|
| @@ -2178,56 +2367,94 @@
|
| //, 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) {
|
| - /*double scale = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, scale);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (scale < 0) {
|
| + return kError_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
|
|
| //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) {
|
| - /*double render = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_INTEGER(pdfContext, mode);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (mode < 0) { // TODO(edisonn): function/enums with supported modes
|
| + return kError_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
| //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) {
|
| - /*double rise = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NUMBER(pdfContext, rise);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (rise < 0) {
|
| + return kNYI_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
|
|
| //wx wy d0
|
| static SkPdfResult PdfOp_d0(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| - pdfContext->fObjectStack.pop();
|
| - pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 2);
|
| + POP_NUMBER(pdfContext, wy);
|
| + POP_NUMBER(pdfContext, wx);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (wx < 0 || wy < 0) {
|
| + return kError_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
|
|
| //wx wy llx lly urx ury d1
|
| static SkPdfResult PdfOp_d1(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| - pdfContext->fObjectStack.pop();
|
| - pdfContext->fObjectStack.pop();
|
| - pdfContext->fObjectStack.pop();
|
| - pdfContext->fObjectStack.pop();
|
| - pdfContext->fObjectStack.pop();
|
| - pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 6);
|
| + POP_NUMBER(pdfContext, ury);
|
| + POP_NUMBER(pdfContext, urx);
|
| + POP_NUMBER(pdfContext, lly);
|
| + POP_NUMBER(pdfContext, llx);
|
| + POP_NUMBER(pdfContext, wy);
|
| + POP_NUMBER(pdfContext, wx);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (wx + wy + llx + lly + urx + ury) {
|
| + return kNYI_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
|
|
| //name sh
|
| static SkPdfResult PdfOp_sh(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| - pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NAME(pdfContext, name);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (name == NULL) {
|
| + return kError_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
|
|
| //name Do
|
| static SkPdfResult PdfOp_Do(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| - SkPdfNativeObject* name = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_NAME(pdfContext, name);
|
| + CHECK_PARAMETERS();
|
|
|
| SkPdfDictionary* xObject = pdfContext->fGraphicsState.fResources->XObject(pdfContext->fPdfDoc);
|
|
|
| @@ -2252,8 +2479,14 @@
|
| //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) {
|
| - pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_OBJ(pdfContext, tag);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (tag == NULL) {
|
| + return kNYI_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
|
|
| @@ -2263,17 +2496,29 @@
|
| //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) {
|
| - pdfContext->fObjectStack.pop();
|
| - pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 2);
|
| + POP_OBJ(pdfContext, properties);
|
| + POP_OBJ(pdfContext, tag);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (tag == NULL || properties == NULL) {
|
| + return kNYI_SkPdfResult;
|
| + }
|
| +
|
| 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) {
|
| - pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 1);
|
| + POP_OBJ(pdfContext, tag);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (tag == NULL) {
|
| + return kNYI_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
|
|
| @@ -2281,9 +2526,15 @@
|
| //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) {
|
| - pdfContext->fObjectStack.pop();
|
| - pdfContext->fObjectStack.pop();
|
| + EXPECT_OPERANDS(pdfContext, 2);
|
| + POP_OBJ(pdfContext, properties);
|
| + POP_OBJ(pdfContext, tag);
|
| + CHECK_PARAMETERS();
|
|
|
| + if (tag == NULL || properties == NULL) {
|
| + return kNYI_SkPdfResult;
|
| + }
|
| +
|
| return kNYI_SkPdfResult;
|
| }
|
|
|
|
|