Simplify SkPdfTokenLooper behavior.

Instead of passing a pointer to a pointer to a NULL looper, which can
then be set to point to a new looper (which then must be looped and
deleted), pass a pointer to the current looper. Each function can then
create a looper based on the parent (on the stack) and call loop()
itself.

Remove setUp(). Now that there is a pointer to the parent at creation
time, there is no need for this function.

Modify the constructors to only provide ones that are needed.

Add documentation.

Remove PdfInlineImageLooper::done(), which is never used.

R=mtklein@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@12447 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/PdfViewer/inc/SkPdfTokenLooper.h b/experimental/PdfViewer/inc/SkPdfTokenLooper.h
index 8deca17..f3897cc 100644
--- a/experimental/PdfViewer/inc/SkPdfTokenLooper.h
+++ b/experimental/PdfViewer/inc/SkPdfTokenLooper.h
@@ -15,31 +15,54 @@
 class SkCanvas;
 class SkPdfContext;
 
+/**
+ *  An object which reads tokens from a tokenizer and draws it to an SkCanvas.
+ *  FIXME (scroggo): Can this be an interface? See http://goo.gl/AXQtkH
+ */
 class SkPdfTokenLooper {
-protected:
-    SkPdfTokenLooper* fParent;
-    SkPdfNativeTokenizer* fTokenizer;
-    SkPdfContext* fPdfContext;
-    SkCanvas* fCanvas;
-
 public:
-    SkPdfTokenLooper(SkPdfTokenLooper* parent,
-                   SkPdfNativeTokenizer* tokenizer,
-                   SkPdfContext* pdfContext,
-                   SkCanvas* canvas)
-        : fParent(parent), fTokenizer(tokenizer), fPdfContext(pdfContext), fCanvas(canvas) {}
+    /**
+     *  Create a looper with no parent.
+     *  @param tokenizer SkPdfNativeTokenizer for reading tokens.
+     *  @param pdfContext Context for drawing state.
+     *  @param canvas Target SkCanvas for drawing.
+     */
+    SkPdfTokenLooper(SkPdfNativeTokenizer* tokenizer,
+                     SkPdfContext* pdfContext,
+                     SkCanvas* canvas)
+        : fParent(NULL)
+        , fTokenizer(tokenizer)
+        , fPdfContext(pdfContext)
+        , fCanvas(canvas) {}
+
+    /**
+     *  Create a looper as a child of parent. It will share the
+     *  SkPdfContext, SkPdfTokenizer, and SkCanvas with its parent.
+     */
+    explicit SkPdfTokenLooper(SkPdfTokenLooper* parent)
+        : fParent(parent)
+        , fTokenizer(parent->fTokenizer)
+        , fPdfContext(parent->fPdfContext)
+        , fCanvas(parent->fCanvas) {}
 
     virtual ~SkPdfTokenLooper() {}
 
+    /**
+     *  Consume a token, and draw to fCanvas as directed.
+     */
     virtual SkPdfResult consumeToken(PdfToken& token) = 0;
+
+    /**
+     *  Consume all the tokens this looper can handle.
+     */
     virtual void loop() = 0;
 
-    void setUp(SkPdfTokenLooper* parent) {
-        fParent = parent;
-        fTokenizer = parent->fTokenizer;
-        fPdfContext = parent->fPdfContext;
-        fCanvas = parent->fCanvas;
-    }
+protected:
+    // All are unowned pointers.
+    SkPdfTokenLooper*       fParent;
+    SkPdfNativeTokenizer*   fTokenizer;
+    SkPdfContext*           fPdfContext;
+    SkCanvas*               fCanvas;
 };
 
 #endif // SkPdfTokenLooper_DEFINED
diff --git a/experimental/PdfViewer/src/SkPdfContext.cpp b/experimental/PdfViewer/src/SkPdfContext.cpp
index f29afe5..b033e7a 100644
--- a/experimental/PdfViewer/src/SkPdfContext.cpp
+++ b/experimental/PdfViewer/src/SkPdfContext.cpp
@@ -14,14 +14,16 @@
 
 class PdfMainLooper : public SkPdfTokenLooper {
 public:
-    PdfMainLooper(SkPdfTokenLooper* parent,
-                  SkPdfNativeTokenizer* tokenizer,
+    PdfMainLooper(SkPdfNativeTokenizer* tokenizer,
                   SkPdfContext* pdfContext,
                   SkCanvas* canvas)
-        : SkPdfTokenLooper(parent, tokenizer, pdfContext, canvas) {}
+        : INHERITED(tokenizer, pdfContext, canvas) {}
 
-    virtual SkPdfResult consumeToken(PdfToken& token);
-    virtual void loop();
+    virtual SkPdfResult consumeToken(PdfToken& token) SK_OVERRIDE;
+    virtual void loop() SK_OVERRIDE;
+
+private:
+    typedef SkPdfTokenLooper INHERITED;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -38,7 +40,7 @@
         // Nothing to parse.
         return;
     }
-    PdfMainLooper looper(NULL, tokenizer, this, canvas);
+    PdfMainLooper looper(tokenizer, this, canvas);
     looper.loop();
     // FIXME (scroggo): Will restructure to put tokenizer on the stack.
     delete tokenizer;
@@ -87,19 +89,12 @@
         PdfOperatorRenderer pdfOperatorRenderer = NULL;
         if (gPdfOps.find(token.fKeyword, token.fKeywordLength, &pdfOperatorRenderer) &&
                     pdfOperatorRenderer) {
-            SkPdfTokenLooper* childLooper = NULL;
             // Main work is done by pdfOperatorRenderer(...)
-            SkPdfResult result = pdfOperatorRenderer(fPdfContext, fCanvas, &childLooper);
+            SkPdfResult result = pdfOperatorRenderer(fPdfContext, fCanvas, this);
 
             int cnt = 0;
             gRenderStats[result].find(token.fKeyword, token.fKeywordLength, &cnt);
             gRenderStats[result].set(token.fKeyword, token.fKeywordLength, cnt + 1);
-            if (childLooper) {
-                // FIXME (scroggo): Auto delete this.
-                childLooper->setUp(this);
-                childLooper->loop();
-                delete childLooper;
-            }
         } else {
             int cnt = 0;
             gRenderStats[kUnsupported_SkPdfResult].find(token.fKeyword,
diff --git a/experimental/PdfViewer/src/SkPdfOps.h b/experimental/PdfViewer/src/SkPdfOps.h
index 1712e20..c88d607 100644
--- a/experimental/PdfViewer/src/SkPdfOps.h
+++ b/experimental/PdfViewer/src/SkPdfOps.h
@@ -9,7 +9,7 @@
 #define SkPdfOps_DEFINED
 
 // Signature for all the operations available in pdf.
-typedef SkPdfResult (*PdfOperatorRenderer)(SkPdfContext*, SkCanvas*, SkPdfTokenLooper**);
+typedef SkPdfResult (*PdfOperatorRenderer)(SkPdfContext*, SkCanvas*, SkPdfTokenLooper*);
 
 // FIXME (scroggo): Make a cleaner interface for this, and avoid statics and globals.
 // Map of string to function pointer for all known draw operations.
diff --git a/experimental/PdfViewer/src/SkPdfRenderer.cpp b/experimental/PdfViewer/src/SkPdfRenderer.cpp
index 714da50..eea7c6e 100644
--- a/experimental/PdfViewer/src/SkPdfRenderer.cpp
+++ b/experimental/PdfViewer/src/SkPdfRenderer.cpp
@@ -208,21 +208,26 @@
 // TODO(edisonn): Document SkPdfTokenLooper and subclasses.
 class PdfInlineImageLooper : public SkPdfTokenLooper {
 public:
-    PdfInlineImageLooper()
-        : SkPdfTokenLooper(NULL, NULL, NULL, NULL) {}
+    explicit PdfInlineImageLooper(SkPdfTokenLooper* parent)
+        : INHERITED(parent) {}
 
-    virtual SkPdfResult consumeToken(PdfToken& token);
-    virtual void loop();
-    SkPdfResult done();
+    virtual SkPdfResult consumeToken(PdfToken& token) SK_OVERRIDE;
+    virtual void loop() SK_OVERRIDE;
+
+private:
+    typedef SkPdfTokenLooper INHERITED;
 };
 
 class PdfCompatibilitySectionLooper : public SkPdfTokenLooper {
 public:
-    PdfCompatibilitySectionLooper()
-        : SkPdfTokenLooper(NULL, NULL, NULL, NULL) {}
+    explicit PdfCompatibilitySectionLooper(SkPdfTokenLooper* parent)
+        : INHERITED (parent) {}
 
-    virtual SkPdfResult consumeToken(PdfToken& token);
-    virtual void loop();
+    virtual SkPdfResult consumeToken(PdfToken& token) SK_OVERRIDE;
+    virtual void loop() SK_OVERRIDE;
+
+private:
+    typedef SkPdfTokenLooper INHERITED;
 };
 
 // Utilities
@@ -347,10 +352,10 @@
 }
 
 // TODO(edisonn): create header files with declarations!
-SkPdfResult PdfOp_q(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper);
-SkPdfResult PdfOp_Q(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper);
-SkPdfResult PdfOp_Tw(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper);
-SkPdfResult PdfOp_Tc(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper);
+SkPdfResult PdfOp_q(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper* parentLooper);
+SkPdfResult PdfOp_Q(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper* parentLooper);
+SkPdfResult PdfOp_Tw(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper* parentLooper);
+SkPdfResult PdfOp_Tc(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper* parentLooper);
 
 // TODO(edisonn): perf!!!
 static SkColorTable* getGrayColortable() {
@@ -915,14 +920,14 @@
     return kPartial_SkPdfResult;
 }
 
-SkPdfResult PdfOp_q(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+SkPdfResult PdfOp_q(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     pdfContext->fStateStack.push(pdfContext->fGraphicsState);
     canvas->save();
     pdfContext->fObjectStack.nest();
     return kOK_SkPdfResult;
 }
 
-SkPdfResult PdfOp_Q(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+SkPdfResult PdfOp_Q(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     if (pdfContext->fStateStack.count() > 0) {
         pdfContext->fGraphicsState = pdfContext->fStateStack.top();
         pdfContext->fStateStack.pop();
@@ -944,7 +949,7 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_cm(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_cm(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("cm", pdfContext, 6);
     POP_NUMBER(pdfContext, f);
     POP_NUMBER(pdfContext, e);
@@ -985,7 +990,7 @@
 //leading TL Set the text leading, Tl
 //, 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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_TL(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("TL", pdfContext, 1);
     POP_NUMBER(pdfContext, ty);
     CHECK_PARAMETERS();
@@ -995,7 +1000,7 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_Td(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_Td(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Td", pdfContext, 2);
     POP_NUMBER(pdfContext, ty);
     POP_NUMBER(pdfContext, tx);
@@ -1010,7 +1015,8 @@
     return kPartial_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_TD(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_TD(SkPdfContext* pdfContext, SkCanvas* canvas,
+                            SkPdfTokenLooper* parentLooper) {
     EXPECT_OPERANDS("TD", pdfContext, 2)
     POP_NUMBER(pdfContext, ty);
     POP_NUMBER(pdfContext, tx);
@@ -1020,7 +1026,7 @@
     SkPdfReal* _ty = pdfContext->fPdfDoc->createReal(-ty);
     pdfContext->fObjectStack.push(_ty);
 
-    PdfOp_TL(pdfContext, canvas, looper);
+    PdfOp_TL(pdfContext, canvas, parentLooper);
 
     SkPdfReal* vtx = pdfContext->fPdfDoc->createReal(tx);
     pdfContext->fObjectStack.push(vtx);
@@ -1028,12 +1034,12 @@
     SkPdfReal* vty = pdfContext->fPdfDoc->createReal(ty);
     pdfContext->fObjectStack.push(vty);
 
-    SkPdfResult ret = PdfOp_Td(pdfContext, canvas, looper);
+    SkPdfResult ret = PdfOp_Td(pdfContext, canvas, parentLooper);
 
     return ret;
 }
 
-static SkPdfResult PdfOp_Tm(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_Tm(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Tm", pdfContext, 6);
     POP_NUMBER(pdfContext, f);
     POP_NUMBER(pdfContext, e);
@@ -1069,19 +1075,19 @@
 //0 Tl Td
 //where Tl is the current leading parameter in the text state
 static SkPdfResult PdfOp_T_star(SkPdfContext* pdfContext, SkCanvas* canvas,
-                                SkPdfTokenLooper** looper) {
+                                SkPdfTokenLooper* parentLooper) {
     SkPdfReal* zero = pdfContext->fPdfDoc->createReal(0.0);
     SkPdfReal* tl = pdfContext->fPdfDoc->createReal(pdfContext->fGraphicsState.fTextLeading);
 
     pdfContext->fObjectStack.push(zero);
     pdfContext->fObjectStack.push(tl);
 
-    SkPdfResult ret = PdfOp_Td(pdfContext, canvas, looper);
+    SkPdfResult ret = PdfOp_Td(pdfContext, canvas, parentLooper);
 
     return ret;
 }
 
-static SkPdfResult PdfOp_m(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_m(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     if (pdfContext->fGraphicsState.fPathClosed) {
         pdfContext->fGraphicsState.fPath.reset();
         pdfContext->fGraphicsState.fPathClosed = false;
@@ -1101,7 +1107,7 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_l(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_l(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     if (pdfContext->fGraphicsState.fPathClosed) {
         pdfContext->fGraphicsState.fPath.reset();
         pdfContext->fGraphicsState.fPathClosed = false;
@@ -1121,7 +1127,7 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_c(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_c(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     if (pdfContext->fGraphicsState.fPathClosed) {
         pdfContext->fGraphicsState.fPath.reset();
         pdfContext->fGraphicsState.fPathClosed = false;
@@ -1146,7 +1152,7 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_v(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_v(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     if (pdfContext->fGraphicsState.fPathClosed) {
         pdfContext->fGraphicsState.fPath.reset();
         pdfContext->fGraphicsState.fPathClosed = false;
@@ -1172,7 +1178,7 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_y(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_y(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     if (pdfContext->fGraphicsState.fPathClosed) {
         pdfContext->fGraphicsState.fPath.reset();
         pdfContext->fGraphicsState.fPathClosed = false;
@@ -1198,7 +1204,7 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_re(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_re(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     if (pdfContext->fGraphicsState.fPathClosed) {
         pdfContext->fGraphicsState.fPath.reset();
         pdfContext->fGraphicsState.fPathClosed = false;
@@ -1222,7 +1228,7 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_h(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_h(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     pdfContext->fGraphicsState.fPath.close();
     return kOK_SkPdfResult;
 }
@@ -1372,46 +1378,46 @@
 
 }
 
-static SkPdfResult PdfOp_S(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_S(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_fillAndStroke(pdfContext, canvas, false, true, false, false);
 }
 
-static SkPdfResult PdfOp_s(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_s(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_fillAndStroke(pdfContext, canvas, false, true, true, false);
 }
 
-static SkPdfResult PdfOp_F(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_F(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_fillAndStroke(pdfContext, canvas, true, false, false, false);
 }
 
-static SkPdfResult PdfOp_f(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_f(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_fillAndStroke(pdfContext, canvas, true, false, false, false);
 }
 
 static SkPdfResult PdfOp_f_star(SkPdfContext* pdfContext, SkCanvas* canvas,
-                                SkPdfTokenLooper** looper) {
+                                SkPdfTokenLooper*) {
     return PdfOp_fillAndStroke(pdfContext, canvas, true, false, false, true);
 }
 
-static SkPdfResult PdfOp_B(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_B(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_fillAndStroke(pdfContext, canvas, true, true, false, false);
 }
 
 static SkPdfResult PdfOp_B_star(SkPdfContext* pdfContext, SkCanvas* canvas,
-                                SkPdfTokenLooper** looper) {
+                                SkPdfTokenLooper*) {
     return PdfOp_fillAndStroke(pdfContext, canvas, true, true, false, true);
 }
 
-static SkPdfResult PdfOp_b(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_b(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_fillAndStroke(pdfContext, canvas, true, true, true, false);
 }
 
 static SkPdfResult PdfOp_b_star(SkPdfContext* pdfContext, SkCanvas* canvas,
-                                SkPdfTokenLooper** looper) {
+                                SkPdfTokenLooper*) {
     return PdfOp_fillAndStroke(pdfContext, canvas, true, true, true, true);
 }
 
-static SkPdfResult PdfOp_n(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_n(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     canvas->setMatrix(pdfContext->fGraphicsState.fCTM);
     if (pdfContext->fGraphicsState.fHasClipPathToApply) {
 #ifndef PDF_DEBUG_NO_CLIPING
@@ -1426,7 +1432,7 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_BT(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_BT(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     pdfContext->fGraphicsState.fTextBlock   = true;
     SkMatrix matrix = pdfContext->fGraphicsState.fCTM;
     matrix.preScale(SkDoubleToScalar(1), SkDoubleToScalar(-1));
@@ -1436,7 +1442,7 @@
     return kPartial_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_ET(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_ET(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     if (!pdfContext->fGraphicsState.fTextBlock) {
         SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingBT_SkPdfIssue, "ET without BT", NULL,
                     pdfContext);
@@ -1489,7 +1495,7 @@
 //font resource in the Fontsubdictionary of the current resource dictionary; size is
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_Tf(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Tf", pdfContext, 2);
     POP_NUMBER(pdfContext, fontSize);
     POP_NAME(pdfContext, fontName);
@@ -1498,7 +1504,7 @@
     return skpdfGraphicsStateApplyFontCore(pdfContext, fontName, fontSize);
 }
 
-static SkPdfResult PdfOp_Tj(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_Tj(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Tj", pdfContext, 1);
     POP_STRING(pdfContext, str);
     CHECK_PARAMETERS();
@@ -1516,7 +1522,7 @@
 }
 
 static SkPdfResult PdfOp_quote(SkPdfContext* pdfContext, SkCanvas* canvas,
-                               SkPdfTokenLooper** looper) {
+                               SkPdfTokenLooper* parentLooper) {
     if (!pdfContext->fGraphicsState.fTextBlock) {
         // TODO(edisonn): try to recover and draw it any way?
         SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingBT_SkPdfIssue,
@@ -1524,13 +1530,13 @@
         return kIgnoreError_SkPdfResult;
     }
 
-    PdfOp_T_star(pdfContext, canvas, looper);
+    PdfOp_T_star(pdfContext, canvas, parentLooper);
     // Do not pop, and push, just transfer the param to Tj
-    return PdfOp_Tj(pdfContext, canvas, looper);
+    return PdfOp_Tj(pdfContext, canvas, parentLooper);
 }
 
 static SkPdfResult PdfOp_doublequote(SkPdfContext* pdfContext, SkCanvas* canvas,
-                                     SkPdfTokenLooper** looper) {
+                                     SkPdfTokenLooper* parentLooper) {
     if (!pdfContext->fGraphicsState.fTextBlock) {
         // TODO(edisonn): try to recover and draw it any way?
         SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kMissingBT_SkPdfIssue,
@@ -1545,18 +1551,18 @@
     CHECK_PARAMETERS();
 
     pdfContext->fObjectStack.push(aw);
-    PdfOp_Tw(pdfContext, canvas, looper);
+    PdfOp_Tw(pdfContext, canvas, parentLooper);
 
     pdfContext->fObjectStack.push(ac);
-    PdfOp_Tc(pdfContext, canvas, looper);
+    PdfOp_Tc(pdfContext, canvas, parentLooper);
 
     pdfContext->fObjectStack.push(str);
-    PdfOp_quote(pdfContext, canvas, looper);
+    PdfOp_quote(pdfContext, canvas, parentLooper);
 
     return kPartial_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_TJ(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_TJ(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Tf", pdfContext, 1);
     POP_ARRAY(pdfContext, array);
     CHECK_PARAMETERS();
@@ -1670,11 +1676,11 @@
     return kPartial_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_CS(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_CS(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_CS_cs(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking);
 }
 
-static SkPdfResult PdfOp_cs(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_cs(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_CS_cs(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
@@ -1717,11 +1723,11 @@
     return kPartial_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_SC(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_SC(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking);
 }
 
-static SkPdfResult PdfOp_sc(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_sc(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
@@ -1750,11 +1756,11 @@
     return kPartial_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_SCN(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_SCN(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking);
 }
 
-static SkPdfResult PdfOp_scn(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_scn(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
@@ -1775,11 +1781,11 @@
     return kPartial_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_G(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_G(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_G_g(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking);
 }
 
-static SkPdfResult PdfOp_g(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_g(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_G_g(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
@@ -1796,11 +1802,11 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_RG(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_RG(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_RG_rg(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking);
 }
 
-static SkPdfResult PdfOp_rg(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_rg(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_RG_rg(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
@@ -1824,23 +1830,22 @@
     return kNYI_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_K(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_K(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_K_k(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking);
 }
 
-static SkPdfResult PdfOp_k(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_k(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     return PdfOp_K_k(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
-static SkPdfResult PdfOp_W(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_W(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     pdfContext->fGraphicsState.fClipPath = pdfContext->fGraphicsState.fPath;
     pdfContext->fGraphicsState.fHasClipPathToApply = true;
 
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_W_star(SkPdfContext* pdfContext, SkCanvas* canvas,
-                                SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_W_star(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     pdfContext->fGraphicsState.fClipPath = pdfContext->fGraphicsState.fPath;
 
     pdfContext->fGraphicsState.fClipPath.setFillType(SkPath::kEvenOdd_FillType);
@@ -1849,12 +1854,14 @@
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_BX(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
-    *looper = new PdfCompatibilitySectionLooper();
+static SkPdfResult PdfOp_BX(SkPdfContext* pdfContext, SkCanvas* canvas,
+                            SkPdfTokenLooper* parentLooper) {
+    PdfCompatibilitySectionLooper looper(parentLooper);
+    looper.loop();
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_EX(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_EX(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNullObject_SkPdfIssue,
                 "EX operator should not be called, it is handled in a looper, "
                         "unless the file is corrupted, we should assert",
@@ -1863,12 +1870,14 @@
     return kIgnoreError_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_BI(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
-    *looper = new PdfInlineImageLooper();
+static SkPdfResult PdfOp_BI(SkPdfContext* pdfContext, SkCanvas* canvas,
+                            SkPdfTokenLooper* parentLooper) {
+    PdfInlineImageLooper looper(parentLooper);
+    looper.loop();
     return kOK_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_ID(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_ID(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     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",
@@ -1876,7 +1885,7 @@
     return kIgnoreError_SkPdfResult;
 }
 
-static SkPdfResult PdfOp_EI(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_EI(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     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",
@@ -2041,7 +2050,7 @@
 
 
 //lineWidth w Set the line width in the graphics state (see “Line Width” on page 152).
-static SkPdfResult PdfOp_w(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_w(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("w", pdfContext, 1);
     POP_NUMBER(pdfContext, lw);
     CHECK_PARAMETERS();
@@ -2050,7 +2059,7 @@
 }
 
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_J(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     // TODO(edisonn): round/ceil to int?
     EXPECT_OPERANDS("J", pdfContext, 1);
     POP_NUMBER(pdfContext, lc);
@@ -2060,7 +2069,7 @@
 }
 
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_j(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     // TODO(edisonn): round/ceil to int?
     EXPECT_OPERANDS("j", pdfContext, 1);
     POP_NUMBER(pdfContext, lj);
@@ -2070,7 +2079,7 @@
 }
 
 //miterLimit M Set the miter limit in the graphics state (see “Miter Limit” on page 153).
-static SkPdfResult PdfOp_M(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_M(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("M", pdfContext, 1);
     POP_NUMBER(pdfContext, ml);
     CHECK_PARAMETERS();
@@ -2079,7 +2088,7 @@
 
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_d(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("d", pdfContext, 2);
     POP_OBJ(pdfContext, phase);
     POP_ARRAY(pdfContext, array);
@@ -2090,7 +2099,7 @@
 
 //intent ri (PDF 1.1) Set the color rendering intent in the graphics state (see “Rendering Intents”
 // on page 197).
-static SkPdfResult PdfOp_ri(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_ri(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     pdfContext->fObjectStack.pop();
 
     SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "render intent NYI", NULL,
@@ -2102,7 +2111,7 @@
 //flatness i Set the flatness tolerance in the graphics state (see Section 6.5.1, “Flatness
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_i(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("i", pdfContext, 1);
     POP_NUMBER(pdfContext, flatness);
     CHECK_PARAMETERS();
@@ -2259,7 +2268,7 @@
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_gs(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("gs", pdfContext, 1);
     POP_NAME(pdfContext, name);
     CHECK_PARAMETERS();
@@ -2361,7 +2370,7 @@
 //, 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, SkPdfTokenLooper** looper) {
+SkPdfResult PdfOp_Tc(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Tc", pdfContext, 1);
     POP_NUMBER(pdfContext, charSpace);
     CHECK_PARAMETERS();
@@ -2376,7 +2385,7 @@
 //, to wordSpace, which is a number expressed in unscaled
 //text space units. Word spacing is used by the Tj, TJ, and ' operators. Initial
 //value: 0.
-SkPdfResult PdfOp_Tw(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+SkPdfResult PdfOp_Tw(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Tw", pdfContext, 1);
     POP_NUMBER(pdfContext, wordSpace);
     CHECK_PARAMETERS();
@@ -2389,7 +2398,7 @@
 //scale Tz Set the horizontal scaling, Th
 //, 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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_Tz(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Tz", pdfContext, 1);
     POP_NUMBER(pdfContext, scale);
     CHECK_PARAMETERS();
@@ -2405,7 +2414,7 @@
 
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_Tr(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Tr", pdfContext, 1);
     POP_INTEGER(pdfContext, mode);
     CHECK_PARAMETERS();
@@ -2420,7 +2429,7 @@
 }
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_Ts(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Ts", pdfContext, 1);
     POP_NUMBER(pdfContext, rise);
     CHECK_PARAMETERS();
@@ -2435,7 +2444,7 @@
 }
 
 //wx wy d0
-static SkPdfResult PdfOp_d0(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_d0(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("d0", pdfContext, 2);
     POP_NUMBER(pdfContext, wy);
     POP_NUMBER(pdfContext, wx);
@@ -2457,7 +2466,7 @@
 }
 
 //wx wy llx lly urx ury d1
-static SkPdfResult PdfOp_d1(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_d1(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("d1", pdfContext, 6);
     POP_NUMBER(pdfContext, ury);
     POP_NUMBER(pdfContext, urx);
@@ -2476,7 +2485,7 @@
 }
 
 //name sh
-static SkPdfResult PdfOp_sh(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_sh(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("sh", pdfContext, 1);
     POP_NAME(pdfContext, name);
     CHECK_PARAMETERS();
@@ -2491,7 +2500,7 @@
 }
 
 //name Do
-static SkPdfResult PdfOp_Do(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_Do(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("Do", pdfContext, 1);
     POP_NAME(pdfContext, name);
     CHECK_PARAMETERS();
@@ -2512,7 +2521,7 @@
 
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_MP(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("MP", pdfContext, 1);
     POP_OBJ(pdfContext, tag);
     CHECK_PARAMETERS();
@@ -2532,7 +2541,7 @@
 //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_DP(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_DP(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("DP", pdfContext, 2);
     POP_OBJ(pdfContext, properties);
     POP_OBJ(pdfContext, tag);
@@ -2556,7 +2565,7 @@
 
 //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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_BMC(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("BMC", pdfContext, 1);
     POP_OBJ(pdfContext, tag);
     CHECK_PARAMETERS();
@@ -2576,7 +2585,7 @@
 // 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, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_BDC(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     EXPECT_OPERANDS("BDC", pdfContext, 2);
     POP_OBJ(pdfContext, properties);
     POP_OBJ(pdfContext, tag);
@@ -2599,7 +2608,7 @@
 }
 
 //— EMC End a marked-content sequence begun by a BMC or BDC operator.
-static SkPdfResult PdfOp_EMC(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper** looper) {
+static SkPdfResult PdfOp_EMC(SkPdfContext* pdfContext, SkCanvas* canvas, SkPdfTokenLooper*) {
     SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "EMC NYI", NULL, NULL);
     return kNYI_SkPdfResult;
 }
@@ -2721,13 +2730,12 @@
 }
 
 void PdfInlineImageLooper::loop() {
+    // FIXME (scroggo): Does this need to be looper? It does not consumeTokens,
+    // nor does it loop. The one thing it does is provide access to the
+    // protected members of SkPdfTokenLooper.
     doXObject_Image(fPdfContext, fCanvas, fTokenizer->readInlineImage());
 }
 
-SkPdfResult PdfInlineImageLooper::done() {
-    return kNYI_SkPdfResult;
-}
-
 SkPdfResult PdfCompatibilitySectionLooper::consumeToken(PdfToken& token) {
     return fParent->consumeToken(token);
 }
@@ -2738,12 +2746,12 @@
     PdfToken token;
     while (fTokenizer->readToken(&token)) {
         if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "BX") == 0) {
-            SkPdfTokenLooper* looper = new PdfCompatibilitySectionLooper();
-            looper->setUp(this);
-            looper->loop();
-            delete looper;
+            PdfCompatibilitySectionLooper looper(this);
+            looper.loop();
         } else {
-            if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "EX") == 0) break;
+            if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "EX") == 0) {
+                break;
+            }
             fParent->consumeToken(token);
         }
     }