Deal with ca and CA transparency operators in pdf. add comments to generated classes.

Review URL: https://codereview.chromium.org/16975013

git-svn-id: http://skia.googlecode.com/svn/trunk@9685 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/PdfViewer/pdf_viewer_main.cpp b/experimental/PdfViewer/pdf_viewer_main.cpp
index 2c6c423..d2d0ff3 100644
--- a/experimental/PdfViewer/pdf_viewer_main.cpp
+++ b/experimental/PdfViewer/pdf_viewer_main.cpp
@@ -7,6 +7,7 @@
 
 #include "SkCanvas.h"
 #include "SkDevice.h"
+#include "SkForceLinking.h"
 #include "SkGraphics.h"
 #include "SkImageDecoder.h"
 #include "SkImageEncoder.h"
@@ -24,6 +25,8 @@
 #include "podofo.h"
 using namespace PoDoFo;
 
+__SK_FORCE_IMAGE_DECODER_LINKING;
+
 const PdfObject* resolveReferenceObject(const PdfMemDocument* pdfDoc,
                                   const PdfObject* obj,
                                   bool resolveOneElementArrays = false);
@@ -176,14 +179,20 @@
 
 /*
  * TODO(edisonn):
- * - encapsulate podofo in the pdf api so the skpdf does not know anything about podofo
+ * - encapsulate podofo in the pdf api so the skpdf does not know anything about podofo ... in progress
  * - ASAP so skp -> pdf -> png looks great
- * - load gs/ especially smask and already known prop (skp)
- * - use transparency (I think ca and CA ops) (skp)
- * - all font types
- * - word spacing
- * - load font for baidu.pdf
- * - load font for youtube.pdf
+ * - load gs/ especially smask and already known prop (skp)...
+ * - all font types and all ppdf font features
+ *      - word spacing
+ *      - load font for baidu.pdf
+ *      - load font for youtube.pdf
+ *      - parser for pdf from the definition already available in pdfspec_autogen.py
+ * - wrapper on classes for customizations? e.g.
+ * SkPdfPageObjectVanila - has only the basic loaders/getters
+ * SkPdfPageObject : public SkPdfPageObjectVanila, extends, and I can add customizations here
+ * need to find a nice object model for all this with constructors and factories
+ * - deal with inheritable automatically ?
+ * - deal with specific type in spec directly, add all dictionary types to known types
 */
 
 //#define PDF_TRACE
@@ -270,6 +279,7 @@
 struct PdfColorOperator {
     std::string fColorSpace;  // TODO(edisonn): use SkString
     SkColor fColor;
+    double fOpacity;  // ca or CA
     // TODO(edisonn): add here other color space options.
 
     void setRGBColor(SkColor color) {
@@ -277,7 +287,12 @@
         fColor = color;
     }
     // TODO(edisonn): double check the default values for all fields.
-    PdfColorOperator() : fColor(SK_ColorBLACK) {}
+    PdfColorOperator() : fColor(SK_ColorBLACK), fOpacity(1) {}
+
+    void applyGraphicsState(SkPaint* paint) {
+        paint->setColor(SkColorSetA(fColor, fOpacity * 255));
+    }
+
 };
 
 // TODO(edisonn): better class design.
@@ -326,7 +341,22 @@
         fWordSpace    = 0;
         fCharSpace    = 0;
         fHasClipPathToApply = false;
-        fResources = NULL;
+        fResources    = NULL;
+    }
+
+    void applyGraphicsState(SkPaint* paint, bool stroking) {
+        if (stroking) {
+            fStroking.applyGraphicsState(paint);
+        } else {
+            fNonStroking.applyGraphicsState(paint);
+        }
+
+        // TODO(edisonn): get this from pdfContext->options,
+        // or pdfContext->addPaintOptions(&paint);
+        paint->setAntiAlias(true);
+
+        // TODO(edisonn): dashing, miter, ...
+        paint->setStrokeWidth(SkDoubleToScalar(fLineWidth));
     }
 };
 
@@ -763,7 +793,8 @@
     if (fCurFont->GetFontScale() != 0) {
         paint.setTextScaleX(SkFloatToScalar(fCurFont->GetFontScale() / 100.0));
     }
-    paint.setColor(pdfContext->fGraphicsState.fNonStroking.fColor);
+
+    pdfContext->fGraphicsState.applyGraphicsState(&paint, false);
 
     paint.setTypeface(SkTypefaceFromPdfFont(fCurFont));
 
@@ -883,6 +914,9 @@
     if (value == NULL || !value->IsNumber()) {
         return false;
     }
+    if (data == NULL) {
+        return true;
+    }
 
     *data = value->GetNumber();
     return true;
@@ -905,9 +939,12 @@
     const PdfObject* value = resolveReferenceObject(pdfDoc,
                                               dict.GetKey(PdfName(key)));
 
-    if (value == NULL || !value->IsReal()) {
+    if (value == NULL || (!value->IsReal() && !value->IsNumber())) {
         return false;
     }
+    if (data == NULL) {
+        return true;
+    }
 
     *data = value->GetReal();
     return true;
@@ -934,6 +971,9 @@
     if (value == NULL || !value->IsBool()) {
         return false;
     }
+    if (data == NULL) {
+        return true;
+    }
 
     *data = value->GetBool();
     return true;
@@ -959,6 +999,9 @@
     if (value == NULL || !value->IsName()) {
         return false;
     }
+    if (data == NULL) {
+        return true;
+    }
 
     *data = value->GetName().GetName();
     return true;
@@ -984,6 +1027,9 @@
     if (value == NULL || (!value->IsString() && !value->IsHexString())) {
         return false;
     }
+    if (data == NULL) {
+        return true;
+    }
 
     *data = value->GetString().GetString();
     return true;
@@ -1009,6 +1055,9 @@
     if (value == NULL || !value->IsDictionary()) {
         return false;
     }
+    if (data == NULL) {
+        return true;
+    }
 
     return PodofoMapper::map(*pdfDoc, *value, (SkPdfObject**)data);
 }
@@ -1035,6 +1084,10 @@
         return false;
     }
 
+    if (data == NULL) {
+        return true;
+    }
+
     return PodofoMapper::map(*pdfDoc, *value, (T**)data);
 }
 
@@ -1059,6 +1112,9 @@
     if (value == NULL) {
         return false;
     }
+    if (data == NULL) {
+        return true;
+    }
     return PodofoMapper::map(*pdfDoc, *value, data);
 }
 
@@ -1311,6 +1367,7 @@
         canvas->saveLayer(&dst, NULL);
         canvas->drawBitmapRect(image, dst, NULL);
         SkPaint xfer;
+        pdfContext->fGraphicsState.applyGraphicsState(&xfer, false);
         xfer.setXfermodeMode(SkXfermode::kSrcOut_Mode); // SkXfermode::kSdtOut_Mode
         canvas->drawBitmapRect(sMask, dst, &xfer);
         canvas->restore();
@@ -1597,12 +1654,13 @@
     double ty = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop();
     double tx = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop();
 
+    // TODO(edisonn): Create factory methods or constructors so podofo is hidden
     PdfObject _ty(PdfVariant(-ty));
     pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc.podofo(), &_ty));
 
     PdfOp_TL(pdfContext, canvas, looper);
 
-    PdfObject vtx(PdfVariant(-(-tx)));  // TODO(edisonn) Hmm, the compiler thinks I have here a function pointer if we use (tx), but not -(-tx)
+    PdfObject vtx(PdfVariant(-(-tx)));  // TODO(edisonn): Hmm, the compiler thinks I have here a function pointer if we use (tx), but not -(-tx)
     pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc.podofo(), &vtx));
 
     PdfObject vty(PdfVariant(-(-ty)));
@@ -1785,20 +1843,13 @@
 
     SkPaint paint;
 
-    // TODO(edisonn): get this from pdfContext->options,
-    // or pdfContext->addPaintOptions(&paint);
-    paint.setAntiAlias(true);
-
-    // TODO(edisonn): dashing, miter, ...
-
-//    path.transform(pdfContext->fGraphicsState.fMatrix);
-//    path.transform(pdfContext->fOriginalMatrix);
-
     SkPoint line[2];
     if (fill && !stroke && path.isLine(line)) {
         paint.setStyle(SkPaint::kStroke_Style);
-        paint.setColor(pdfContext->fGraphicsState.fNonStroking.fColor);
+
+        pdfContext->fGraphicsState.applyGraphicsState(&paint, false);
         paint.setStrokeWidth(SkDoubleToScalar(0));
+
         canvas->drawPath(path, paint);
     } else {
         if (fill) {
@@ -1806,14 +1857,17 @@
             if (evenOdd) {
                 path.setFillType(SkPath::kEvenOdd_FillType);
             }
-            paint.setColor(pdfContext->fGraphicsState.fNonStroking.fColor);
+
+            pdfContext->fGraphicsState.applyGraphicsState(&paint, false);
+
             canvas->drawPath(path, paint);
         }
 
         if (stroke) {
             paint.setStyle(SkPaint::kStroke_Style);
-            paint.setColor(pdfContext->fGraphicsState.fStroking.fColor);
-            paint.setStrokeWidth(SkDoubleToScalar(pdfContext->fGraphicsState.fLineWidth));
+
+            pdfContext->fGraphicsState.applyGraphicsState(&paint, true);
+
             path.setFillType(SkPath::kWinding_FillType);  // reset it, just in case it messes up the stroke
             canvas->drawPath(path, paint);
         }
@@ -2290,6 +2344,23 @@
     PodofoMapper::map(value, &gs);
 
     // TODO(edisonn): now load all those properties in graphic state.
+    if (gs == NULL) {
+        return kIgnoreError_PdfResult;
+    }
+
+    if (gs->has_CA()) {
+        pdfContext->fGraphicsState.fStroking.fOpacity = gs->CA();
+    }
+
+    if (gs->has_ca()) {
+        pdfContext->fGraphicsState.fNonStroking.fOpacity = gs->ca();
+    }
+
+    if (gs->has_LW()) {
+        pdfContext->fGraphicsState.fLineWidth = gs->LW();
+    }
+
+
 
     return kNYI_PdfResult;
 }