Home | History | Annotate | Download | only in debugger
      1 
      2 /*
      3  * Copyright 2012 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkDrawCommand.h"
     11 
     12 #include "SkBlurMaskFilter.h"
     13 #include "SkColorFilter.h"
     14 #include "SkDashPathEffect.h"
     15 #include "SkImageFilter.h"
     16 #include "SkMaskFilter.h"
     17 #include "SkObjectParser.h"
     18 #include "SkPaintDefaults.h"
     19 #include "SkPathEffect.h"
     20 #include "SkPicture.h"
     21 #include "SkTextBlob.h"
     22 #include "SkTextBlobRunIterator.h"
     23 #include "SkTHash.h"
     24 #include "SkTypeface.h"
     25 #include "SkValidatingReadBuffer.h"
     26 #include "SkWriteBuffer.h"
     27 
     28 #if SK_SUPPORT_GPU
     29 #include "GrContext.h"
     30 #include "GrRenderTarget.h"
     31 #endif
     32 
     33 #define SKDEBUGCANVAS_ATTRIBUTE_COMMAND           "command"
     34 #define SKDEBUGCANVAS_ATTRIBUTE_VISIBLE           "visible"
     35 #define SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL        "auditTrail"
     36 #define SKDEBUGCANVAS_ATTRIBUTE_MATRIX            "matrix"
     37 #define SKDEBUGCANVAS_ATTRIBUTE_COORDS            "coords"
     38 #define SKDEBUGCANVAS_ATTRIBUTE_BOUNDS            "bounds"
     39 #define SKDEBUGCANVAS_ATTRIBUTE_PAINT             "paint"
     40 #define SKDEBUGCANVAS_ATTRIBUTE_OUTER             "outer"
     41 #define SKDEBUGCANVAS_ATTRIBUTE_INNER             "inner"
     42 #define SKDEBUGCANVAS_ATTRIBUTE_MODE              "mode"
     43 #define SKDEBUGCANVAS_ATTRIBUTE_POINTS            "points"
     44 #define SKDEBUGCANVAS_ATTRIBUTE_PATH              "path"
     45 #define SKDEBUGCANVAS_ATTRIBUTE_TEXT              "text"
     46 #define SKDEBUGCANVAS_ATTRIBUTE_COLOR             "color"
     47 #define SKDEBUGCANVAS_ATTRIBUTE_ALPHA             "alpha"
     48 #define SKDEBUGCANVAS_ATTRIBUTE_STYLE             "style"
     49 #define SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH       "strokeWidth"
     50 #define SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER       "strokeMiter"
     51 #define SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN        "strokeJoin"
     52 #define SKDEBUGCANVAS_ATTRIBUTE_CAP               "cap"
     53 #define SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS         "antiAlias"
     54 #define SKDEBUGCANVAS_ATTRIBUTE_DITHER            "dither"
     55 #define SKDEBUGCANVAS_ATTRIBUTE_REGION            "region"
     56 #define SKDEBUGCANVAS_ATTRIBUTE_REGIONOP          "op"
     57 #define SKDEBUGCANVAS_ATTRIBUTE_EDGESTYLE         "edgeStyle"
     58 #define SKDEBUGCANVAS_ATTRIBUTE_DEVICEREGION      "deviceRegion"
     59 #define SKDEBUGCANVAS_ATTRIBUTE_BLUR              "blur"
     60 #define SKDEBUGCANVAS_ATTRIBUTE_SIGMA             "sigma"
     61 #define SKDEBUGCANVAS_ATTRIBUTE_QUALITY           "quality"
     62 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN         "textAlign"
     63 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE          "textSize"
     64 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX        "textScaleX"
     65 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX         "textSkewX"
     66 #define SKDEBUGCANVAS_ATTRIBUTE_DASHING           "dashing"
     67 #define SKDEBUGCANVAS_ATTRIBUTE_INTERVALS         "intervals"
     68 #define SKDEBUGCANVAS_ATTRIBUTE_PHASE             "phase"
     69 #define SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE          "fillType"
     70 #define SKDEBUGCANVAS_ATTRIBUTE_VERBS             "verbs"
     71 #define SKDEBUGCANVAS_ATTRIBUTE_NAME              "name"
     72 #define SKDEBUGCANVAS_ATTRIBUTE_DATA              "data"
     73 #define SKDEBUGCANVAS_ATTRIBUTE_SHADER            "shader"
     74 #define SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT        "pathEffect"
     75 #define SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER        "maskFilter"
     76 #define SKDEBUGCANVAS_ATTRIBUTE_XFERMODE          "xfermode"
     77 #define SKDEBUGCANVAS_ATTRIBUTE_LOOPER            "looper"
     78 #define SKDEBUGCANVAS_ATTRIBUTE_BACKDROP          "backdrop"
     79 #define SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER       "colorfilter"
     80 #define SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER       "imagefilter"
     81 #define SKDEBUGCANVAS_ATTRIBUTE_IMAGE             "image"
     82 #define SKDEBUGCANVAS_ATTRIBUTE_BITMAP            "bitmap"
     83 #define SKDEBUGCANVAS_ATTRIBUTE_SRC               "src"
     84 #define SKDEBUGCANVAS_ATTRIBUTE_DST               "dst"
     85 #define SKDEBUGCANVAS_ATTRIBUTE_CENTER            "center"
     86 #define SKDEBUGCANVAS_ATTRIBUTE_STRICT            "strict"
     87 #define SKDEBUGCANVAS_ATTRIBUTE_DESCRIPTION       "description"
     88 #define SKDEBUGCANVAS_ATTRIBUTE_X                 "x"
     89 #define SKDEBUGCANVAS_ATTRIBUTE_Y                 "y"
     90 #define SKDEBUGCANVAS_ATTRIBUTE_RUNS              "runs"
     91 #define SKDEBUGCANVAS_ATTRIBUTE_POSITIONS         "positions"
     92 #define SKDEBUGCANVAS_ATTRIBUTE_GLYPHS            "glyphs"
     93 #define SKDEBUGCANVAS_ATTRIBUTE_FONT              "font"
     94 #define SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE          "typeface"
     95 #define SKDEBUGCANVAS_ATTRIBUTE_CUBICS            "cubics"
     96 #define SKDEBUGCANVAS_ATTRIBUTE_COLORS            "colors"
     97 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS     "textureCoords"
     98 #define SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY     "filterQuality"
     99 
    100 #define SKDEBUGCANVAS_VERB_MOVE                   "move"
    101 #define SKDEBUGCANVAS_VERB_LINE                   "line"
    102 #define SKDEBUGCANVAS_VERB_QUAD                   "quad"
    103 #define SKDEBUGCANVAS_VERB_CUBIC                  "cubic"
    104 #define SKDEBUGCANVAS_VERB_CONIC                  "conic"
    105 #define SKDEBUGCANVAS_VERB_CLOSE                  "close"
    106 
    107 #define SKDEBUGCANVAS_STYLE_FILL                  "fill"
    108 #define SKDEBUGCANVAS_STYLE_STROKE                "stroke"
    109 #define SKDEBUGCANVAS_STYLE_STROKEANDFILL         "strokeAndFill"
    110 
    111 #define SKDEBUGCANVAS_POINTMODE_POINTS            "points"
    112 #define SKDEBUGCANVAS_POINTMODE_LINES             "lines"
    113 #define SKDEBUGCANVAS_POINTMODE_POLYGON           "polygon"
    114 
    115 #define SKDEBUGCANVAS_REGIONOP_DIFFERENCE         "difference"
    116 #define SKDEBUGCANVAS_REGIONOP_INTERSECT          "intersect"
    117 #define SKDEBUGCANVAS_REGIONOP_UNION              "union"
    118 #define SKDEBUGCANVAS_REGIONOP_XOR                "xor"
    119 #define SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE "reverseDifference"
    120 #define SKDEBUGCANVAS_REGIONOP_REPLACE            "replace"
    121 
    122 #define SKDEBUGCANVAS_BLURSTYLE_NORMAL            "normal"
    123 #define SKDEBUGCANVAS_BLURSTYLE_SOLID             "solid"
    124 #define SKDEBUGCANVAS_BLURSTYLE_OUTER             "outer"
    125 #define SKDEBUGCANVAS_BLURSTYLE_INNER             "inner"
    126 
    127 #define SKDEBUGCANVAS_BLURQUALITY_LOW             "low"
    128 #define SKDEBUGCANVAS_BLURQUALITY_HIGH            "high"
    129 
    130 #define SKDEBUGCANVAS_ALIGN_LEFT                  "left"
    131 #define SKDEBUGCANVAS_ALIGN_CENTER                "center"
    132 #define SKDEBUGCANVAS_ALIGN_RIGHT                 "right"
    133 
    134 #define SKDEBUGCANVAS_FILLTYPE_WINDING            "winding"
    135 #define SKDEBUGCANVAS_FILLTYPE_EVENODD            "evenOdd"
    136 #define SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING     "inverseWinding"
    137 #define SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD     "inverseEvenOdd"
    138 
    139 #define SKDEBUGCANVAS_CAP_BUTT                    "butt"
    140 #define SKDEBUGCANVAS_CAP_ROUND                   "round"
    141 #define SKDEBUGCANVAS_CAP_SQUARE                  "square"
    142 
    143 #define SKDEBUGCANVAS_MITER_JOIN                  "miter"
    144 #define SKDEBUGCANVAS_ROUND_JOIN                  "round"
    145 #define SKDEBUGCANVAS_BEVEL_JOIN                  "bevel"
    146 
    147 #define SKDEBUGCANVAS_COLORTYPE_ARGB4444          "ARGB4444"
    148 #define SKDEBUGCANVAS_COLORTYPE_RGBA8888          "RGBA8888"
    149 #define SKDEBUGCANVAS_COLORTYPE_BGRA8888          "BGRA8888"
    150 #define SKDEBUGCANVAS_COLORTYPE_565               "565"
    151 #define SKDEBUGCANVAS_COLORTYPE_GRAY8             "Gray8"
    152 #define SKDEBUGCANVAS_COLORTYPE_INDEX8            "Index8"
    153 #define SKDEBUGCANVAS_COLORTYPE_ALPHA8            "Alpha8"
    154 
    155 #define SKDEBUGCANVAS_ALPHATYPE_OPAQUE            "opaque"
    156 #define SKDEBUGCANVAS_ALPHATYPE_PREMUL            "premul"
    157 #define SKDEBUGCANVAS_ALPHATYPE_UNPREMUL          "unpremul"
    158 
    159 #define SKDEBUGCANVAS_FILTERQUALITY_NONE          "none"
    160 #define SKDEBUGCANVAS_FILTERQUALITY_LOW           "low"
    161 #define SKDEBUGCANVAS_FILTERQUALITY_MEDIUM        "medium"
    162 #define SKDEBUGCANVAS_FILTERQUALITY_HIGH          "high"
    163 
    164 typedef SkDrawCommand* (*FROM_JSON)(Json::Value&, UrlDataManager&);
    165 
    166 // TODO(chudy): Refactor into non subclass model.
    167 
    168 SkDrawCommand::SkDrawCommand(OpType type)
    169     : fOpType(type)
    170     , fVisible(true) {
    171 }
    172 
    173 SkDrawCommand::~SkDrawCommand() {
    174     fInfo.deleteAll();
    175 }
    176 
    177 const char* SkDrawCommand::GetCommandString(OpType type) {
    178     switch (type) {
    179         case kBeginDrawPicture_OpType: return "BeginDrawPicture";
    180         case kClipPath_OpType: return "ClipPath";
    181         case kClipRegion_OpType: return "ClipRegion";
    182         case kClipRect_OpType: return "ClipRect";
    183         case kClipRRect_OpType: return "ClipRRect";
    184         case kConcat_OpType: return "Concat";
    185         case kDrawBitmap_OpType: return "DrawBitmap";
    186         case kDrawBitmapNine_OpType: return "DrawBitmapNine";
    187         case kDrawBitmapRect_OpType: return "DrawBitmapRect";
    188         case kDrawClear_OpType: return "DrawClear";
    189         case kDrawDRRect_OpType: return "DrawDRRect";
    190         case kDrawImage_OpType: return "DrawImage";
    191         case kDrawImageRect_OpType: return "DrawImageRect";
    192         case kDrawOval_OpType: return "DrawOval";
    193         case kDrawPaint_OpType: return "DrawPaint";
    194         case kDrawPatch_OpType: return "DrawPatch";
    195         case kDrawPath_OpType: return "DrawPath";
    196         case kDrawPoints_OpType: return "DrawPoints";
    197         case kDrawPosText_OpType: return "DrawPosText";
    198         case kDrawPosTextH_OpType: return "DrawPosTextH";
    199         case kDrawRect_OpType: return "DrawRect";
    200         case kDrawRRect_OpType: return "DrawRRect";
    201         case kDrawText_OpType: return "DrawText";
    202         case kDrawTextBlob_OpType: return "DrawTextBlob";
    203         case kDrawTextOnPath_OpType: return "DrawTextOnPath";
    204         case kDrawVertices_OpType: return "DrawVertices";
    205         case kEndDrawPicture_OpType: return "EndDrawPicture";
    206         case kRestore_OpType: return "Restore";
    207         case kSave_OpType: return "Save";
    208         case kSaveLayer_OpType: return "SaveLayer";
    209         case kSetMatrix_OpType: return "SetMatrix";
    210         default:
    211             SkDebugf("OpType error 0x%08x\n", type);
    212             SkASSERT(0);
    213             break;
    214     }
    215     SkDEBUGFAIL("DrawType UNUSED\n");
    216     return nullptr;
    217 }
    218 
    219 SkString SkDrawCommand::toString() const {
    220     return SkString(GetCommandString(fOpType));
    221 }
    222 
    223 Json::Value SkDrawCommand::toJSON(UrlDataManager& urlDataManager) const {
    224     Json::Value result;
    225     result[SKDEBUGCANVAS_ATTRIBUTE_COMMAND] = this->GetCommandString(fOpType);
    226     result[SKDEBUGCANVAS_ATTRIBUTE_VISIBLE] = Json::Value(this->isVisible());
    227     return result;
    228 }
    229 
    230 Json::Value SkDrawCommand::drawToAndCollectJSON(SkCanvas* canvas,
    231                                                 UrlDataManager& urlDataManager) const {
    232     Json::Value result = this->toJSON(urlDataManager);
    233 
    234     SkASSERT(canvas);
    235 
    236 #if SK_SUPPORT_GPU
    237     GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
    238     if (rt) {
    239         GrContext* ctx = rt->getContext();
    240         if(ctx) {
    241             GrAuditTrail* at = ctx->getAuditTrail();
    242             GrAuditTrail::AutoEnable enable(at);
    243             this->execute(canvas);
    244 
    245             // TODO if this is inefficient we could add a method to GrAuditTrail which takes
    246             // a Json::Value and is only compiled in this file
    247             Json::Value parsedFromString;
    248             Json::Reader reader;
    249             SkDEBUGCODE(bool parsingSuccessful = )reader.parse(at->toJson().c_str(),
    250                                                                parsedFromString);
    251             SkASSERT(parsingSuccessful);
    252 
    253             result[SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL] = parsedFromString;
    254             at->reset();
    255         }
    256     }
    257 #endif
    258     return result;
    259 }
    260 
    261 #define INSTALL_FACTORY(name) factories.set(SkString(GetCommandString(k ## name ##_OpType)), \
    262                                             (FROM_JSON) Sk ## name ## Command::fromJSON)
    263 SkDrawCommand* SkDrawCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
    264     static SkTHashMap<SkString, FROM_JSON> factories;
    265     static bool initialized = false;
    266     if (!initialized) {
    267         initialized = true;
    268         INSTALL_FACTORY(Restore);
    269         INSTALL_FACTORY(ClipPath);
    270         INSTALL_FACTORY(ClipRegion);
    271         INSTALL_FACTORY(ClipRect);
    272         INSTALL_FACTORY(ClipRRect);
    273         INSTALL_FACTORY(Concat);
    274         INSTALL_FACTORY(DrawBitmap);
    275         INSTALL_FACTORY(DrawBitmapRect);
    276         INSTALL_FACTORY(DrawBitmapNine);
    277         INSTALL_FACTORY(DrawImage);
    278         INSTALL_FACTORY(DrawImageRect);
    279         INSTALL_FACTORY(DrawOval);
    280         INSTALL_FACTORY(DrawPaint);
    281         INSTALL_FACTORY(DrawPath);
    282         INSTALL_FACTORY(DrawPoints);
    283         INSTALL_FACTORY(DrawText);
    284         INSTALL_FACTORY(DrawPosText);
    285         INSTALL_FACTORY(DrawTextOnPath);
    286         INSTALL_FACTORY(DrawTextBlob);
    287 
    288         INSTALL_FACTORY(DrawRect);
    289         INSTALL_FACTORY(DrawRRect);
    290         INSTALL_FACTORY(DrawDRRect);
    291         INSTALL_FACTORY(DrawPatch);
    292         INSTALL_FACTORY(Save);
    293         INSTALL_FACTORY(SaveLayer);
    294         INSTALL_FACTORY(SetMatrix);
    295     }
    296     SkString name = SkString(command[SKDEBUGCANVAS_ATTRIBUTE_COMMAND].asCString());
    297     FROM_JSON* factory = factories.find(name);
    298     if (factory == nullptr) {
    299         SkDebugf("no JSON factory for '%s'\n", name.c_str());
    300         return nullptr;
    301     }
    302     return (*factory)(command, urlDataManager);
    303 }
    304 
    305 namespace {
    306 
    307 void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
    308     const SkISize& size = canvas->getDeviceSize();
    309 
    310     static const SkScalar kInsetFrac = 0.9f; // Leave a border around object
    311 
    312     canvas->translate(size.fWidth/2.0f, size.fHeight/2.0f);
    313     if (bounds.width() > bounds.height()) {
    314         canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.width()),
    315                       SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.width()));
    316     } else {
    317         canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.height()),
    318                       SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.height()));
    319     }
    320     canvas->translate(-bounds.centerX(), -bounds.centerY());
    321 }
    322 
    323 
    324 void render_path(SkCanvas* canvas, const SkPath& path) {
    325     canvas->clear(0xFFFFFFFF);
    326 
    327     const SkRect& bounds = path.getBounds();
    328     if (bounds.isEmpty()) {
    329         return;
    330     }
    331 
    332     SkAutoCanvasRestore acr(canvas, true);
    333     xlate_and_scale_to_bounds(canvas, bounds);
    334 
    335     SkPaint p;
    336     p.setColor(SK_ColorBLACK);
    337     p.setStyle(SkPaint::kStroke_Style);
    338 
    339     canvas->drawPath(path, p);
    340 }
    341 
    342 void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = nullptr) {
    343     const SkISize& size = canvas->getDeviceSize();
    344 
    345     SkScalar xScale = SkIntToScalar(size.fWidth-2) / input.width();
    346     SkScalar yScale = SkIntToScalar(size.fHeight-2) / input.height();
    347 
    348     if (input.width() > input.height()) {
    349         yScale *= input.height() / (float) input.width();
    350     } else {
    351         xScale *= input.width() / (float) input.height();
    352     }
    353 
    354     SkRect dst = SkRect::MakeXYWH(SK_Scalar1, SK_Scalar1,
    355                                   xScale * input.width(),
    356                                   yScale * input.height());
    357 
    358     static const int kNumBlocks = 8;
    359 
    360     canvas->clear(0xFFFFFFFF);
    361     SkISize block = {
    362         canvas->imageInfo().width()/kNumBlocks,
    363         canvas->imageInfo().height()/kNumBlocks
    364     };
    365     for (int y = 0; y < kNumBlocks; ++y) {
    366         for (int x = 0; x < kNumBlocks; ++x) {
    367             SkPaint paint;
    368             paint.setColor((x+y)%2 ? SK_ColorLTGRAY : SK_ColorDKGRAY);
    369             SkRect r = SkRect::MakeXYWH(SkIntToScalar(x*block.width()),
    370                                         SkIntToScalar(y*block.height()),
    371                                         SkIntToScalar(block.width()),
    372                                         SkIntToScalar(block.height()));
    373             canvas->drawRect(r, paint);
    374         }
    375     }
    376 
    377     canvas->drawBitmapRect(input, dst, nullptr);
    378 
    379     if (srcRect) {
    380         SkRect r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
    381                                     srcRect->fTop * yScale + SK_Scalar1,
    382                                     srcRect->fRight * xScale + SK_Scalar1,
    383                                     srcRect->fBottom * yScale + SK_Scalar1);
    384         SkPaint p;
    385         p.setColor(SK_ColorRED);
    386         p.setStyle(SkPaint::kStroke_Style);
    387 
    388         canvas->drawRect(r, p);
    389     }
    390 }
    391 
    392 void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
    393     canvas->clear(0xFFFFFFFF);
    394     canvas->save();
    395 
    396     const SkRect& bounds = rrect.getBounds();
    397 
    398     xlate_and_scale_to_bounds(canvas, bounds);
    399 
    400     SkPaint p;
    401     p.setColor(SK_ColorBLACK);
    402     p.setStyle(SkPaint::kStroke_Style);
    403 
    404     canvas->drawRRect(rrect, p);
    405     canvas->restore();
    406 }
    407 
    408 void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
    409     canvas->clear(0xFFFFFFFF);
    410     canvas->save();
    411 
    412     const SkRect& bounds = outer.getBounds();
    413 
    414     xlate_and_scale_to_bounds(canvas, bounds);
    415 
    416     SkPaint p;
    417     p.setColor(SK_ColorBLACK);
    418     p.setStyle(SkPaint::kStroke_Style);
    419 
    420     canvas->drawDRRect(outer, inner, p);
    421     canvas->restore();
    422 }
    423 
    424 };
    425 
    426 static Json::Value make_json_color(const SkColor color) {
    427     Json::Value result(Json::arrayValue);
    428     result.append(Json::Value(SkColorGetA(color)));
    429     result.append(Json::Value(SkColorGetR(color)));
    430     result.append(Json::Value(SkColorGetG(color)));
    431     result.append(Json::Value(SkColorGetB(color)));
    432     return result;
    433 }
    434 
    435 
    436 static Json::Value make_json_point(const SkPoint& point) {
    437     Json::Value result(Json::arrayValue);
    438     result.append(Json::Value(point.x()));
    439     result.append(Json::Value(point.y()));
    440     return result;
    441 }
    442 
    443 static Json::Value make_json_point(SkScalar x, SkScalar y) {
    444     Json::Value result(Json::arrayValue);
    445     result.append(Json::Value(x));
    446     result.append(Json::Value(y));
    447     return result;
    448 }
    449 
    450 static Json::Value make_json_rect(const SkRect& rect) {
    451     Json::Value result(Json::arrayValue);
    452     result.append(Json::Value(rect.left()));
    453     result.append(Json::Value(rect.top()));
    454     result.append(Json::Value(rect.right()));
    455     result.append(Json::Value(rect.bottom()));
    456     return result;
    457 }
    458 
    459 static Json::Value make_json_irect(const SkIRect& rect) {
    460     Json::Value result(Json::arrayValue);
    461     result.append(Json::Value(rect.left()));
    462     result.append(Json::Value(rect.top()));
    463     result.append(Json::Value(rect.right()));
    464     result.append(Json::Value(rect.bottom()));
    465     return result;
    466 }
    467 
    468 static Json::Value make_json_rrect(const SkRRect& rrect) {
    469     Json::Value result(Json::arrayValue);
    470     result.append(make_json_rect(rrect.rect()));
    471     result.append(make_json_point(rrect.radii(SkRRect::kUpperLeft_Corner)));
    472     result.append(make_json_point(rrect.radii(SkRRect::kUpperRight_Corner)));
    473     result.append(make_json_point(rrect.radii(SkRRect::kLowerRight_Corner)));
    474     result.append(make_json_point(rrect.radii(SkRRect::kLowerLeft_Corner)));
    475     return result;
    476 }
    477 
    478 static Json::Value make_json_matrix(const SkMatrix& matrix) {
    479     Json::Value result(Json::arrayValue);
    480     Json::Value row1(Json::arrayValue);
    481     row1.append(Json::Value(matrix[0]));
    482     row1.append(Json::Value(matrix[1]));
    483     row1.append(Json::Value(matrix[2]));
    484     result.append(row1);
    485     Json::Value row2(Json::arrayValue);
    486     row2.append(Json::Value(matrix[3]));
    487     row2.append(Json::Value(matrix[4]));
    488     row2.append(Json::Value(matrix[5]));
    489     result.append(row2);
    490     Json::Value row3(Json::arrayValue);
    491     row3.append(Json::Value(matrix[6]));
    492     row3.append(Json::Value(matrix[7]));
    493     row3.append(Json::Value(matrix[8]));
    494     result.append(row3);
    495     return result;
    496 }
    497 
    498 static Json::Value make_json_path(const SkPath& path) {
    499     Json::Value result(Json::objectValue);
    500     switch (path.getFillType()) {
    501         case SkPath::kWinding_FillType:
    502             result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_WINDING;
    503             break;
    504         case SkPath::kEvenOdd_FillType:
    505             result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_EVENODD;
    506             break;
    507         case SkPath::kInverseWinding_FillType:
    508             result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING;
    509             break;
    510         case SkPath::kInverseEvenOdd_FillType:
    511             result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD;
    512             break;
    513     }
    514     Json::Value verbs(Json::arrayValue);
    515     SkPath::Iter iter(path, false);
    516     SkPoint pts[4];
    517     SkPath::Verb verb;
    518     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
    519         switch (verb) {
    520             case SkPath::kLine_Verb: {
    521                 Json::Value line(Json::objectValue);
    522                 line[SKDEBUGCANVAS_VERB_LINE] = make_json_point(pts[1]);
    523                 verbs.append(line);
    524                 break;
    525             }
    526             case SkPath::kQuad_Verb: {
    527                 Json::Value quad(Json::objectValue);
    528                 Json::Value coords(Json::arrayValue);
    529                 coords.append(make_json_point(pts[1]));
    530                 coords.append(make_json_point(pts[2]));
    531                 quad[SKDEBUGCANVAS_VERB_QUAD] = coords;
    532                 verbs.append(quad);
    533                 break;
    534             }
    535             case SkPath::kCubic_Verb: {
    536                 Json::Value cubic(Json::objectValue);
    537                 Json::Value coords(Json::arrayValue);
    538                 coords.append(make_json_point(pts[1]));
    539                 coords.append(make_json_point(pts[2]));
    540                 coords.append(make_json_point(pts[3]));
    541                 cubic[SKDEBUGCANVAS_VERB_CUBIC] = coords;
    542                 verbs.append(cubic);
    543                 break;
    544             }
    545             case SkPath::kConic_Verb: {
    546                 Json::Value conic(Json::objectValue);
    547                 Json::Value coords(Json::arrayValue);
    548                 coords.append(make_json_point(pts[1]));
    549                 coords.append(make_json_point(pts[2]));
    550                 coords.append(Json::Value(iter.conicWeight()));
    551                 conic[SKDEBUGCANVAS_VERB_CONIC] = coords;
    552                 verbs.append(conic);
    553                 break;
    554             }
    555             case SkPath::kMove_Verb: {
    556                 Json::Value move(Json::objectValue);
    557                 move[SKDEBUGCANVAS_VERB_MOVE] = make_json_point(pts[0]);
    558                 verbs.append(move);
    559                 break;
    560             }
    561             case SkPath::kClose_Verb:
    562                 verbs.append(Json::Value(SKDEBUGCANVAS_VERB_CLOSE));
    563                 break;
    564             case SkPath::kDone_Verb:
    565                 break;
    566         }
    567     }
    568     result[SKDEBUGCANVAS_ATTRIBUTE_VERBS] = verbs;
    569     return result;
    570 }
    571 
    572 static Json::Value make_json_region(const SkRegion& region) {
    573     return Json::Value("<unimplemented>");
    574 }
    575 
    576 static Json::Value make_json_regionop(SkRegion::Op op) {
    577     switch (op) {
    578         case SkRegion::kDifference_Op:
    579             return Json::Value(SKDEBUGCANVAS_REGIONOP_DIFFERENCE);
    580         case SkRegion::kIntersect_Op:
    581             return Json::Value(SKDEBUGCANVAS_REGIONOP_INTERSECT);
    582         case SkRegion::kUnion_Op:
    583             return Json::Value(SKDEBUGCANVAS_REGIONOP_UNION);
    584         case SkRegion::kXOR_Op:
    585             return Json::Value(SKDEBUGCANVAS_REGIONOP_XOR);
    586         case SkRegion::kReverseDifference_Op:
    587             return Json::Value(SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE);
    588         case SkRegion::kReplace_Op:
    589             return Json::Value(SKDEBUGCANVAS_REGIONOP_REPLACE);
    590         default:
    591             SkASSERT(false);
    592             return Json::Value("<invalid region op>");
    593     };
    594 }
    595 
    596 static Json::Value make_json_pointmode(SkCanvas::PointMode mode) {
    597     switch (mode) {
    598         case SkCanvas::kPoints_PointMode:
    599             return Json::Value(SKDEBUGCANVAS_POINTMODE_POINTS);
    600         case SkCanvas::kLines_PointMode:
    601             return Json::Value(SKDEBUGCANVAS_POINTMODE_LINES);
    602         case SkCanvas::kPolygon_PointMode:
    603             return Json::Value(SKDEBUGCANVAS_POINTMODE_POLYGON);
    604         default:
    605             SkASSERT(false);
    606             return Json::Value("<invalid point mode>");
    607     };
    608 }
    609 
    610 static void store_scalar(Json::Value* target, const char* key, SkScalar value,
    611                          SkScalar defaultValue) {
    612     if (value != defaultValue) {
    613         (*target)[key] = Json::Value(value);
    614     }
    615 }
    616 
    617 static void store_bool(Json::Value* target, const char* key, bool value, bool defaultValue) {
    618     if (value != defaultValue) {
    619         (*target)[key] = Json::Value(value);
    620     }
    621 }
    622 
    623 static void encode_data(const void* bytes, size_t count, const char* contentType,
    624                         UrlDataManager& urlDataManager, Json::Value* target) {
    625     SkAutoTUnref<SkData> data(SkData::NewWithCopy(bytes, count));
    626     SkString url = urlDataManager.addData(data, contentType);
    627     *target = Json::Value(url.c_str());
    628 }
    629 
    630 static void flatten(const SkFlattenable* flattenable, Json::Value* target,
    631                     UrlDataManager& urlDataManager) {
    632     SkWriteBuffer buffer;
    633     flattenable->flatten(buffer);
    634     void* data = sk_malloc_throw(buffer.bytesWritten());
    635     buffer.writeToMemory(data);
    636     Json::Value jsonData;
    637     encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager, &jsonData);
    638     Json::Value jsonFlattenable;
    639     jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_NAME] = Json::Value(flattenable->getTypeName());
    640     jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_DATA] = jsonData;
    641     (*target) = jsonFlattenable;
    642     sk_free(data);
    643 }
    644 
    645 static bool SK_WARN_UNUSED_RESULT flatten(const SkImage& image, Json::Value* target,
    646                                           UrlDataManager& urlDataManager) {
    647     SkData* encoded = image.encode(SkImageEncoder::kPNG_Type, 100);
    648     if (encoded == nullptr) {
    649         // PNG encode doesn't necessarily support all color formats, convert to a different
    650         // format
    651         size_t rowBytes = 4 * image.width();
    652         void* buffer = sk_malloc_throw(rowBytes * image.height());
    653         SkImageInfo dstInfo = SkImageInfo::Make(image.width(), image.height(),
    654                                                 kN32_SkColorType, kPremul_SkAlphaType);
    655         if (!image.readPixels(dstInfo, buffer, rowBytes, 0, 0)) {
    656             SkDebugf("readPixels failed\n");
    657             return false;
    658         }
    659         SkImage* converted = SkImage::NewRasterCopy(dstInfo, buffer, rowBytes);
    660         encoded = converted->encode(SkImageEncoder::kPNG_Type, 100);
    661         if (encoded == nullptr) {
    662             SkDebugf("image encode failed\n");
    663             return false;
    664         }
    665         sk_free(converted);
    666         sk_free(buffer);
    667     }
    668     Json::Value jsonData;
    669     encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager, &jsonData);
    670     (*target)[SKDEBUGCANVAS_ATTRIBUTE_DATA] = jsonData;
    671     encoded->unref();
    672     return true;
    673 }
    674 
    675 static const char* color_type_name(SkColorType colorType) {
    676     switch (colorType) {
    677         case kARGB_4444_SkColorType:
    678             return SKDEBUGCANVAS_COLORTYPE_ARGB4444;
    679         case kRGBA_8888_SkColorType:
    680             return SKDEBUGCANVAS_COLORTYPE_RGBA8888;
    681         case kBGRA_8888_SkColorType:
    682             return SKDEBUGCANVAS_COLORTYPE_BGRA8888;
    683         case kRGB_565_SkColorType:
    684             return SKDEBUGCANVAS_COLORTYPE_565;
    685         case kGray_8_SkColorType:
    686             return SKDEBUGCANVAS_COLORTYPE_GRAY8;
    687         case kIndex_8_SkColorType:
    688             return SKDEBUGCANVAS_COLORTYPE_INDEX8;
    689         case kAlpha_8_SkColorType:
    690             return SKDEBUGCANVAS_COLORTYPE_ALPHA8;
    691         default:
    692             SkASSERT(false);
    693             return SKDEBUGCANVAS_COLORTYPE_RGBA8888;
    694     }
    695 }
    696 
    697 static const char* alpha_type_name(SkAlphaType alphaType) {
    698     switch (alphaType) {
    699         case kOpaque_SkAlphaType:
    700             return SKDEBUGCANVAS_ALPHATYPE_OPAQUE;
    701         case kPremul_SkAlphaType:
    702             return SKDEBUGCANVAS_ALPHATYPE_PREMUL;
    703         case kUnpremul_SkAlphaType:
    704             return SKDEBUGCANVAS_ALPHATYPE_UNPREMUL;
    705         default:
    706             SkASSERT(false);
    707             return SKDEBUGCANVAS_ALPHATYPE_OPAQUE;
    708     }
    709 }
    710 
    711 static Json::ArrayIndex decode_data(Json::Value data, UrlDataManager& urlDataManager,
    712                                     const void** target) {
    713     UrlDataManager::UrlData* urlData = urlDataManager.getDataFromUrl(SkString(data.asCString()));
    714     if (urlData == nullptr) {
    715         SkASSERT(false);
    716         *target = nullptr;
    717         return 0;
    718     }
    719     *target = urlData->fData->data();
    720     // cast should be safe for any reasonably-sized object...
    721     return (Json::ArrayIndex) urlData->fData->size();
    722 }
    723 
    724 static SkFlattenable* load_flattenable(Json::Value jsonFlattenable,
    725                                        UrlDataManager& urlDataManager) {
    726     if (!jsonFlattenable.isMember(SKDEBUGCANVAS_ATTRIBUTE_NAME)) {
    727         return nullptr;
    728     }
    729     const char* name = jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_NAME].asCString();
    730     SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name);
    731     if (factory == nullptr) {
    732         SkDebugf("no factory for loading '%s'\n", name);
    733         return nullptr;
    734     }
    735     const void* data;
    736     int size = decode_data(jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_DATA], urlDataManager, &data);
    737     SkValidatingReadBuffer buffer(data, size);
    738     SkFlattenable* result = factory(buffer);
    739     if (!buffer.isValid()) {
    740         SkDebugf("invalid buffer loading flattenable\n");
    741         return nullptr;
    742     }
    743     return result;
    744 }
    745 
    746 static SkColorType colortype_from_name(const char* name) {
    747     if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_ARGB4444)) {
    748         return kARGB_4444_SkColorType;
    749     }
    750     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_RGBA8888)) {
    751         return kRGBA_8888_SkColorType;
    752     }
    753     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_BGRA8888)) {
    754         return kBGRA_8888_SkColorType;
    755     }
    756     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_565)) {
    757         return kRGB_565_SkColorType;
    758     }
    759     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_GRAY8)) {
    760         return kGray_8_SkColorType;
    761     }
    762     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_INDEX8)) {
    763         return kIndex_8_SkColorType;
    764     }
    765     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_ALPHA8)) {
    766         return kAlpha_8_SkColorType;
    767     }
    768     SkASSERT(false);
    769     return kN32_SkColorType;
    770 }
    771 
    772 static SkBitmap* convert_colortype(SkBitmap* bitmap, SkColorType colorType) {
    773     if (bitmap->colorType() == colorType  ) {
    774         return bitmap;
    775     }
    776     SkBitmap* dst = new SkBitmap();
    777     if (bitmap->copyTo(dst, colorType)) {
    778         delete bitmap;
    779         return dst;
    780     }
    781     SkASSERT(false);
    782     delete dst;
    783     return bitmap;
    784 }
    785 
    786 // caller is responsible for freeing return value
    787 static SkBitmap* load_bitmap(const Json::Value& jsonBitmap, UrlDataManager& urlDataManager) {
    788     if (!jsonBitmap.isMember(SKDEBUGCANVAS_ATTRIBUTE_DATA)) {
    789         SkDebugf("invalid bitmap\n");
    790         return nullptr;
    791     }
    792     const void* data;
    793     int size = decode_data(jsonBitmap[SKDEBUGCANVAS_ATTRIBUTE_DATA], urlDataManager, &data);
    794     SkMemoryStream stream(data, size);
    795     SkImageDecoder* decoder = SkImageDecoder::Factory(&stream);
    796     SkBitmap* bitmap = new SkBitmap();
    797     SkImageDecoder::Result result = decoder->decode(&stream, bitmap,
    798                                                     SkImageDecoder::kDecodePixels_Mode);
    799     sk_free(decoder);
    800     if (result != SkImageDecoder::kFailure) {
    801         if (jsonBitmap.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLOR)) {
    802             const char* ctName = jsonBitmap[SKDEBUGCANVAS_ATTRIBUTE_COLOR].asCString();
    803             SkColorType ct = colortype_from_name(ctName);
    804             if (ct != kIndex_8_SkColorType) {
    805                 bitmap = convert_colortype(bitmap, ct);
    806             }
    807         }
    808         return bitmap;
    809     }
    810     SkDebugf("image decode failed\n");
    811     return nullptr;
    812 }
    813 
    814 static SkImage* load_image(const Json::Value& jsonImage, UrlDataManager& urlDataManager) {
    815     SkBitmap* bitmap = load_bitmap(jsonImage, urlDataManager);
    816     if (bitmap == nullptr) {
    817         return nullptr;
    818     }
    819     SkImage* result = SkImage::NewFromBitmap(*bitmap);
    820     delete bitmap;
    821     return result;
    822 }
    823 
    824 static bool SK_WARN_UNUSED_RESULT flatten(const SkBitmap& bitmap, Json::Value* target,
    825                                           UrlDataManager& urlDataManager) {
    826     bitmap.lockPixels();
    827     SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bitmap));
    828     bitmap.unlockPixels();
    829     (*target)[SKDEBUGCANVAS_ATTRIBUTE_COLOR] = Json::Value(color_type_name(bitmap.colorType()));
    830     (*target)[SKDEBUGCANVAS_ATTRIBUTE_ALPHA] = Json::Value(alpha_type_name(bitmap.alphaType()));
    831     bool success = flatten(*image, target, urlDataManager);
    832     return success;
    833 }
    834 
    835 static void apply_paint_color(const SkPaint& paint, Json::Value* target) {
    836     SkColor color = paint.getColor();
    837     if (color != SK_ColorBLACK) {
    838         Json::Value colorValue(Json::arrayValue);
    839         colorValue.append(Json::Value(SkColorGetA(color)));
    840         colorValue.append(Json::Value(SkColorGetR(color)));
    841         colorValue.append(Json::Value(SkColorGetG(color)));
    842         colorValue.append(Json::Value(SkColorGetB(color)));
    843         (*target)[SKDEBUGCANVAS_ATTRIBUTE_COLOR] = colorValue;;
    844     }
    845 }
    846 
    847 static void apply_paint_style(const SkPaint& paint, Json::Value* target) {
    848     SkPaint::Style style = paint.getStyle();
    849     if (style != SkPaint::kFill_Style) {
    850         switch (style) {
    851             case SkPaint::kStroke_Style: {
    852                 Json::Value stroke(SKDEBUGCANVAS_STYLE_STROKE);
    853                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = stroke;
    854                 break;
    855             }
    856             case SkPaint::kStrokeAndFill_Style: {
    857                 Json::Value strokeAndFill(SKDEBUGCANVAS_STYLE_STROKEANDFILL);
    858                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = strokeAndFill;
    859                 break;
    860             }
    861             default: SkASSERT(false);
    862         }
    863     }
    864 }
    865 
    866 static void apply_paint_cap(const SkPaint& paint, Json::Value* target) {
    867     SkPaint::Cap cap = paint.getStrokeCap();
    868     if (cap != SkPaint::kDefault_Cap) {
    869         switch (cap) {
    870             case SkPaint::kButt_Cap:
    871                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_CAP] = Json::Value(SKDEBUGCANVAS_CAP_BUTT);
    872                 break;
    873             case SkPaint::kRound_Cap:
    874                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_CAP] = Json::Value(SKDEBUGCANVAS_CAP_ROUND);
    875                 break;
    876             case SkPaint::kSquare_Cap:
    877                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_CAP] = Json::Value(SKDEBUGCANVAS_CAP_SQUARE);
    878                 break;
    879             default: SkASSERT(false);
    880         }
    881     }
    882 }
    883 
    884 static void apply_paint_join(const SkPaint& paint, Json::Value* target) {
    885     SkPaint::Join join = paint.getStrokeJoin();
    886     if (join != SkPaint::kDefault_Join) {
    887         switch (join) {
    888             case SkPaint::kMiter_Join:
    889                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN] = Json::Value(
    890                                                                           SKDEBUGCANVAS_MITER_JOIN);
    891                 break;
    892             case SkPaint::kRound_Join:
    893                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN] = Json::Value(
    894                                                                           SKDEBUGCANVAS_ROUND_JOIN);
    895                 break;
    896             case SkPaint::kBevel_Join:
    897                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN] = Json::Value(
    898                                                                         SKDEBUGCANVAS_BEVEL_JOIN);
    899                 break;
    900             default: SkASSERT(false);
    901         }
    902     }
    903 }
    904 
    905 static void apply_paint_filterquality(const SkPaint& paint, Json::Value* target) {
    906     SkFilterQuality quality = paint.getFilterQuality();
    907     switch (quality) {
    908         case kNone_SkFilterQuality:
    909             break;
    910         case kLow_SkFilterQuality:
    911             (*target)[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY] = Json::Value(
    912                                                                    SKDEBUGCANVAS_FILTERQUALITY_LOW);
    913             break;
    914         case kMedium_SkFilterQuality:
    915             (*target)[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY] = Json::Value(
    916                                                                 SKDEBUGCANVAS_FILTERQUALITY_MEDIUM);
    917             break;
    918         case kHigh_SkFilterQuality:
    919             (*target)[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY] = Json::Value(
    920                                                                   SKDEBUGCANVAS_FILTERQUALITY_HIGH);
    921             break;
    922     }
    923 }
    924 
    925 static void apply_paint_maskfilter(const SkPaint& paint, Json::Value* target,
    926                                    UrlDataManager& urlDataManager) {
    927     SkMaskFilter* maskFilter = paint.getMaskFilter();
    928     if (maskFilter != nullptr) {
    929         SkMaskFilter::BlurRec blurRec;
    930         if (maskFilter->asABlur(&blurRec)) {
    931             Json::Value blur(Json::objectValue);
    932             blur[SKDEBUGCANVAS_ATTRIBUTE_SIGMA] = Json::Value(blurRec.fSigma);
    933             switch (blurRec.fStyle) {
    934                 case SkBlurStyle::kNormal_SkBlurStyle:
    935                     blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
    936                                                                     SKDEBUGCANVAS_BLURSTYLE_NORMAL);
    937                     break;
    938                 case SkBlurStyle::kSolid_SkBlurStyle:
    939                     blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
    940                                                                      SKDEBUGCANVAS_BLURSTYLE_SOLID);
    941                     break;
    942                 case SkBlurStyle::kOuter_SkBlurStyle:
    943                     blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
    944                                                                      SKDEBUGCANVAS_BLURSTYLE_OUTER);
    945                     break;
    946                 case SkBlurStyle::kInner_SkBlurStyle:
    947                     blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
    948                                                                      SKDEBUGCANVAS_BLURSTYLE_INNER);
    949                     break;
    950                 default:
    951                     SkASSERT(false);
    952             }
    953             switch (blurRec.fQuality) {
    954                 case SkBlurQuality::kLow_SkBlurQuality:
    955                     blur[SKDEBUGCANVAS_ATTRIBUTE_QUALITY] = Json::Value(
    956                                                                      SKDEBUGCANVAS_BLURQUALITY_LOW);
    957                     break;
    958                 case SkBlurQuality::kHigh_SkBlurQuality:
    959                     blur[SKDEBUGCANVAS_ATTRIBUTE_QUALITY] = Json::Value(
    960                                                                     SKDEBUGCANVAS_BLURQUALITY_HIGH);
    961                     break;
    962                 default:
    963                     SkASSERT(false);
    964             }
    965             (*target)[SKDEBUGCANVAS_ATTRIBUTE_BLUR] = blur;
    966         } else {
    967             Json::Value jsonMaskFilter;
    968             flatten(maskFilter, &jsonMaskFilter, urlDataManager);
    969             (*target)[SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER] = jsonMaskFilter;
    970         }
    971     }
    972 }
    973 
    974 static void apply_paint_patheffect(const SkPaint& paint, Json::Value* target,
    975                                    UrlDataManager& urlDataManager) {
    976     SkPathEffect* pathEffect = paint.getPathEffect();
    977     if (pathEffect != nullptr) {
    978         SkPathEffect::DashInfo dashInfo;
    979         SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
    980         if (dashType == SkPathEffect::kDash_DashType) {
    981             dashInfo.fIntervals = (SkScalar*) sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
    982             pathEffect->asADash(&dashInfo);
    983             Json::Value dashing(Json::objectValue);
    984             Json::Value intervals(Json::arrayValue);
    985             for (int32_t i = 0; i < dashInfo.fCount; i++) {
    986                 intervals.append(Json::Value(dashInfo.fIntervals[i]));
    987             }
    988             sk_free(dashInfo.fIntervals);
    989             dashing[SKDEBUGCANVAS_ATTRIBUTE_INTERVALS] = intervals;
    990             dashing[SKDEBUGCANVAS_ATTRIBUTE_PHASE] = dashInfo.fPhase;
    991             (*target)[SKDEBUGCANVAS_ATTRIBUTE_DASHING] = dashing;
    992         } else {
    993             Json::Value jsonPathEffect;
    994             flatten(pathEffect, &jsonPathEffect, urlDataManager);
    995             (*target)[SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT] = jsonPathEffect;
    996         }
    997     }
    998 }
    999 
   1000 static void apply_paint_textalign(const SkPaint& paint, Json::Value* target) {
   1001     SkPaint::Align textAlign = paint.getTextAlign();
   1002     if (textAlign != SkPaint::kLeft_Align) {
   1003         switch (textAlign) {
   1004             case SkPaint::kCenter_Align: {
   1005                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN] = SKDEBUGCANVAS_ALIGN_CENTER;
   1006                 break;
   1007             }
   1008             case SkPaint::kRight_Align: {
   1009                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN] = SKDEBUGCANVAS_ALIGN_RIGHT;
   1010                 break;
   1011             }
   1012             default: SkASSERT(false);
   1013         }
   1014     }
   1015 }
   1016 
   1017 static void apply_paint_typeface(const SkPaint& paint, Json::Value* target,
   1018                                  UrlDataManager& urlDataManager) {
   1019     SkTypeface* typeface = paint.getTypeface();
   1020     if (typeface != nullptr) {
   1021         Json::Value jsonTypeface;
   1022         SkDynamicMemoryWStream buffer;
   1023         typeface->serialize(&buffer);
   1024         void* data = sk_malloc_throw(buffer.bytesWritten());
   1025         buffer.copyTo(data);
   1026         Json::Value jsonData;
   1027         encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager,
   1028                     &jsonData);
   1029         jsonTypeface[SKDEBUGCANVAS_ATTRIBUTE_DATA] = jsonData;
   1030         sk_free(data);
   1031         (*target)[SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE] = jsonTypeface;
   1032     }
   1033 }
   1034 
   1035 static void apply_paint_shader(const SkPaint& paint, Json::Value* target,
   1036                                UrlDataManager& urlDataManager) {
   1037     SkFlattenable* shader = paint.getShader();
   1038     if (shader != nullptr) {
   1039         Json::Value jsonShader;
   1040         flatten(shader, &jsonShader, urlDataManager);
   1041         (*target)[SKDEBUGCANVAS_ATTRIBUTE_SHADER] = jsonShader;
   1042     }
   1043 }
   1044 
   1045 static void apply_paint_xfermode(const SkPaint& paint, Json::Value* target,
   1046                                  UrlDataManager& urlDataManager) {
   1047     SkFlattenable* xfermode = paint.getXfermode();
   1048     if (xfermode != nullptr) {
   1049         Json::Value jsonXfermode;
   1050         flatten(xfermode, &jsonXfermode, urlDataManager);
   1051         (*target)[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE] = jsonXfermode;
   1052     }
   1053 }
   1054 
   1055 static void apply_paint_imagefilter(const SkPaint& paint, Json::Value* target,
   1056                                     UrlDataManager& urlDataManager) {
   1057     SkFlattenable* imageFilter = paint.getImageFilter();
   1058     if (imageFilter != nullptr) {
   1059         Json::Value jsonImageFilter;
   1060         flatten(imageFilter, &jsonImageFilter, urlDataManager);
   1061         (*target)[SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER] = jsonImageFilter;
   1062     }
   1063 }
   1064 
   1065 static void apply_paint_colorfilter(const SkPaint& paint, Json::Value* target,
   1066                                     UrlDataManager& urlDataManager) {
   1067     SkFlattenable* colorFilter = paint.getColorFilter();
   1068     if (colorFilter != nullptr) {
   1069         Json::Value jsonColorFilter;
   1070         flatten(colorFilter, &jsonColorFilter, urlDataManager);
   1071         (*target)[SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER] = jsonColorFilter;
   1072     }
   1073 }
   1074 
   1075 static void apply_paint_looper(const SkPaint& paint, Json::Value* target,
   1076                                UrlDataManager& urlDataManager) {
   1077     SkFlattenable* looper = paint.getLooper();
   1078     if (looper != nullptr) {
   1079         Json::Value jsonLooper;
   1080         flatten(looper, &jsonLooper, urlDataManager);
   1081         (*target)[SKDEBUGCANVAS_ATTRIBUTE_LOOPER] = jsonLooper;
   1082     }
   1083 }
   1084 
   1085 Json::Value make_json_paint(const SkPaint& paint, UrlDataManager& urlDataManager) {
   1086     Json::Value result(Json::objectValue);
   1087     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
   1088     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER, paint.getStrokeMiter(),
   1089                  SkPaintDefaults_MiterLimit);
   1090     store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
   1091     store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
   1092     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE, paint.getTextSize(),
   1093                  SkPaintDefaults_TextSize);
   1094     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextScaleX(), SK_Scalar1);
   1095     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextSkewX(), 0.0f);
   1096     apply_paint_color(paint, &result);
   1097     apply_paint_style(paint, &result);
   1098     apply_paint_cap(paint, &result);
   1099     apply_paint_join(paint, &result);
   1100     apply_paint_filterquality(paint, &result);
   1101     apply_paint_textalign(paint, &result);
   1102     apply_paint_patheffect(paint, &result, urlDataManager);
   1103     apply_paint_maskfilter(paint, &result, urlDataManager);
   1104     apply_paint_shader(paint, &result, urlDataManager);
   1105     apply_paint_xfermode(paint, &result, urlDataManager);
   1106     apply_paint_looper(paint, &result, urlDataManager);
   1107     apply_paint_imagefilter(paint, &result, urlDataManager);
   1108     apply_paint_colorfilter(paint, &result, urlDataManager);
   1109     apply_paint_typeface(paint, &result, urlDataManager);
   1110     return result;
   1111 }
   1112 
   1113 static SkPoint get_json_point(Json::Value point) {
   1114     return SkPoint::Make(point[0].asFloat(), point[1].asFloat());
   1115 }
   1116 
   1117 static SkColor get_json_color(Json::Value color) {
   1118     return SkColorSetARGB(color[0].asInt(), color[1].asInt(), color[2].asInt(), color[3].asInt());
   1119 }
   1120 
   1121 static void extract_json_paint_color(Json::Value& jsonPaint, SkPaint* target) {
   1122     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLOR)) {
   1123         target->setColor(get_json_color(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_COLOR]));
   1124     }
   1125 }
   1126 
   1127 static void extract_json_paint_shader(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
   1128                                       SkPaint* target) {
   1129     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_SHADER)) {
   1130         Json::Value jsonShader = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_SHADER];
   1131         SkShader* shader = (SkShader*) load_flattenable(jsonShader, urlDataManager);
   1132         if (shader != nullptr) {
   1133             target->setShader(shader);
   1134             shader->unref();
   1135         }
   1136     }
   1137 }
   1138 
   1139 static void extract_json_paint_patheffect(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
   1140                                           SkPaint* target) {
   1141     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT)) {
   1142         Json::Value jsonPathEffect = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT];
   1143         SkPathEffect* pathEffect = (SkPathEffect*) load_flattenable(jsonPathEffect, urlDataManager);
   1144         if (pathEffect != nullptr) {
   1145             target->setPathEffect(pathEffect);
   1146             pathEffect->unref();
   1147         }
   1148     }
   1149 }
   1150 
   1151 static void extract_json_paint_maskfilter(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
   1152                                           SkPaint* target) {
   1153     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER)) {
   1154         Json::Value jsonMaskFilter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER];
   1155         SkMaskFilter* maskFilter = (SkMaskFilter*) load_flattenable(jsonMaskFilter, urlDataManager);
   1156         if (maskFilter != nullptr) {
   1157             target->setMaskFilter(maskFilter);
   1158             maskFilter->unref();
   1159         }
   1160     }
   1161 }
   1162 
   1163 static void extract_json_paint_colorfilter(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
   1164                                            SkPaint* target) {
   1165     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER)) {
   1166         Json::Value jsonColorFilter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER];
   1167         SkColorFilter* colorFilter = (SkColorFilter*) load_flattenable(jsonColorFilter,
   1168                                                                        urlDataManager);
   1169         if (colorFilter != nullptr) {
   1170             target->setColorFilter(colorFilter);
   1171             colorFilter->unref();
   1172         }
   1173     }
   1174 }
   1175 
   1176 static void extract_json_paint_xfermode(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
   1177                                         SkPaint* target) {
   1178     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_XFERMODE)) {
   1179         Json::Value jsonXfermode = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE];
   1180         SkXfermode* xfermode = (SkXfermode*) load_flattenable(jsonXfermode, urlDataManager);
   1181         if (xfermode != nullptr) {
   1182             target->setXfermode(xfermode);
   1183             xfermode->unref();
   1184         }
   1185     }
   1186 }
   1187 
   1188 static void extract_json_paint_looper(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
   1189                                       SkPaint* target) {
   1190     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_LOOPER)) {
   1191         Json::Value jsonLooper = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_LOOPER];
   1192         SkDrawLooper* looper = (SkDrawLooper*) load_flattenable(jsonLooper, urlDataManager);
   1193         if (looper != nullptr) {
   1194             target->setLooper(looper);
   1195             looper->unref();
   1196         }
   1197     }
   1198 }
   1199 
   1200 static void extract_json_paint_imagefilter(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
   1201                                            SkPaint* target) {
   1202     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER)) {
   1203         Json::Value jsonImageFilter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER];
   1204         SkImageFilter* imageFilter = (SkImageFilter*) load_flattenable(jsonImageFilter,
   1205                                                                        urlDataManager);
   1206         if (imageFilter != nullptr) {
   1207             target->setImageFilter(imageFilter);
   1208             imageFilter->unref();
   1209         }
   1210     }
   1211 }
   1212 
   1213 static void extract_json_paint_typeface(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
   1214                                         SkPaint* target) {
   1215     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE)) {
   1216         Json::Value jsonTypeface = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE];
   1217         Json::Value jsonData = jsonTypeface[SKDEBUGCANVAS_ATTRIBUTE_DATA];
   1218         const void* data;
   1219         Json::ArrayIndex length = decode_data(jsonData, urlDataManager, &data);
   1220         SkMemoryStream buffer(data, length);
   1221         SkTypeface* typeface = SkTypeface::Deserialize(&buffer);
   1222         target->setTypeface(typeface);
   1223     }
   1224 }
   1225 
   1226 static void extract_json_paint_style(Json::Value& jsonPaint, SkPaint* target) {
   1227     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STYLE)) {
   1228         const char* style = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STYLE].asCString();
   1229         if (!strcmp(style, SKDEBUGCANVAS_STYLE_FILL)) {
   1230             target->setStyle(SkPaint::kFill_Style);
   1231         }
   1232         else if (!strcmp(style, SKDEBUGCANVAS_STYLE_STROKE)) {
   1233             target->setStyle(SkPaint::kStroke_Style);
   1234         }
   1235         else if (!strcmp(style, SKDEBUGCANVAS_STYLE_STROKEANDFILL)) {
   1236             target->setStyle(SkPaint::kStrokeAndFill_Style);
   1237         }
   1238     }
   1239 }
   1240 
   1241 static void extract_json_paint_strokewidth(Json::Value& jsonPaint, SkPaint* target) {
   1242     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH)) {
   1243         float strokeWidth = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH].asFloat();
   1244         target->setStrokeWidth(strokeWidth);
   1245     }
   1246 }
   1247 
   1248 static void extract_json_paint_strokemiter(Json::Value& jsonPaint, SkPaint* target) {
   1249     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER)) {
   1250         float strokeMiter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER].asFloat();
   1251         target->setStrokeMiter(strokeMiter);
   1252     }
   1253 }
   1254 
   1255 static void extract_json_paint_strokejoin(Json::Value& jsonPaint, SkPaint* target) {
   1256     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN)) {
   1257         const char* join = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN].asCString();
   1258         if (!strcmp(join, SKDEBUGCANVAS_MITER_JOIN)) {
   1259             target->setStrokeJoin(SkPaint::kMiter_Join);
   1260         }
   1261         else if (!strcmp(join, SKDEBUGCANVAS_ROUND_JOIN)) {
   1262             target->setStrokeJoin(SkPaint::kRound_Join);
   1263         }
   1264         else if (!strcmp(join, SKDEBUGCANVAS_BEVEL_JOIN)) {
   1265             target->setStrokeJoin(SkPaint::kBevel_Join);
   1266         }
   1267         else {
   1268             SkASSERT(false);
   1269         }
   1270     }
   1271 }
   1272 
   1273 static void extract_json_paint_cap(Json::Value& jsonPaint, SkPaint* target) {
   1274     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_CAP)) {
   1275         const char* cap = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_CAP].asCString();
   1276         if (!strcmp(cap, SKDEBUGCANVAS_CAP_BUTT)) {
   1277             target->setStrokeCap(SkPaint::kButt_Cap);
   1278         }
   1279         else if (!strcmp(cap, SKDEBUGCANVAS_CAP_ROUND)) {
   1280             target->setStrokeCap(SkPaint::kRound_Cap);
   1281         }
   1282         else if (!strcmp(cap, SKDEBUGCANVAS_CAP_SQUARE)) {
   1283             target->setStrokeCap(SkPaint::kSquare_Cap);
   1284         }
   1285     }
   1286 }
   1287 
   1288 static void extract_json_paint_filterquality(Json::Value& jsonPaint, SkPaint* target) {
   1289     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY)) {
   1290         const char* quality = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY].asCString();
   1291         if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_NONE)) {
   1292             target->setFilterQuality(kNone_SkFilterQuality);
   1293         }
   1294         else if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_LOW)) {
   1295             target->setFilterQuality(kLow_SkFilterQuality);
   1296         }
   1297         else if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_MEDIUM)) {
   1298             target->setFilterQuality(kMedium_SkFilterQuality);
   1299         }
   1300         else if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_HIGH)) {
   1301             target->setFilterQuality(kHigh_SkFilterQuality);
   1302         }
   1303     }
   1304 }
   1305 
   1306 static void extract_json_paint_antialias(Json::Value& jsonPaint, SkPaint* target) {
   1307     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS)) {
   1308         target->setAntiAlias(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
   1309     }
   1310 }
   1311 
   1312 static void extract_json_paint_dither(Json::Value& jsonPaint, SkPaint* target) {
   1313     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_DITHER)) {
   1314         target->setDither(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_DITHER].asBool());
   1315     }
   1316 }
   1317 
   1318 static void extract_json_paint_blur(Json::Value& jsonPaint, SkPaint* target) {
   1319     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_BLUR)) {
   1320         Json::Value blur = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_BLUR];
   1321         SkScalar sigma = blur[SKDEBUGCANVAS_ATTRIBUTE_SIGMA].asFloat();
   1322         SkBlurStyle style;
   1323         const char* jsonStyle = blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE].asCString();
   1324         if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_NORMAL)) {
   1325             style = SkBlurStyle::kNormal_SkBlurStyle;
   1326         }
   1327         else if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_SOLID)) {
   1328             style = SkBlurStyle::kSolid_SkBlurStyle;
   1329         }
   1330         else if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_OUTER)) {
   1331             style = SkBlurStyle::kOuter_SkBlurStyle;
   1332         }
   1333         else if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_INNER)) {
   1334             style = SkBlurStyle::kInner_SkBlurStyle;
   1335         }
   1336         else {
   1337             SkASSERT(false);
   1338             style = SkBlurStyle::kNormal_SkBlurStyle;
   1339         }
   1340         SkBlurMaskFilter::BlurFlags flags;
   1341         const char* jsonQuality = blur[SKDEBUGCANVAS_ATTRIBUTE_QUALITY].asCString();
   1342         if (!strcmp(jsonQuality, SKDEBUGCANVAS_BLURQUALITY_LOW)) {
   1343             flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
   1344         }
   1345         else if (!strcmp(jsonQuality, SKDEBUGCANVAS_BLURQUALITY_HIGH)) {
   1346             flags = SkBlurMaskFilter::BlurFlags::kHighQuality_BlurFlag;
   1347         }
   1348         else {
   1349             SkASSERT(false);
   1350             flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
   1351         }
   1352         target->setMaskFilter(SkBlurMaskFilter::Create(style, sigma, flags));
   1353     }
   1354 }
   1355 
   1356 static void extract_json_paint_dashing(Json::Value& jsonPaint, SkPaint* target) {
   1357     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_DASHING)) {
   1358         Json::Value dash = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_DASHING];
   1359         Json::Value jsonIntervals = dash[SKDEBUGCANVAS_ATTRIBUTE_INTERVALS];
   1360         Json::ArrayIndex count = jsonIntervals.size();
   1361         SkScalar* intervals = (SkScalar*) sk_malloc_throw(count * sizeof(SkScalar));
   1362         for (Json::ArrayIndex i = 0; i < count; i++) {
   1363             intervals[i] = jsonIntervals[i].asFloat();
   1364         }
   1365         SkScalar phase = dash[SKDEBUGCANVAS_ATTRIBUTE_PHASE].asFloat();
   1366         target->setPathEffect(SkDashPathEffect::Create(intervals, count, phase));
   1367         sk_free(intervals);
   1368     }
   1369 }
   1370 
   1371 static void extract_json_paint_textalign(Json::Value& jsonPaint, SkPaint* target) {
   1372     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN)) {
   1373         SkPaint::Align textAlign;
   1374         const char* jsonAlign = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN].asCString();
   1375         if (!strcmp(jsonAlign, SKDEBUGCANVAS_ALIGN_LEFT)) {
   1376             textAlign = SkPaint::kLeft_Align;
   1377         }
   1378         else if (!strcmp(jsonAlign, SKDEBUGCANVAS_ALIGN_CENTER)) {
   1379             textAlign = SkPaint::kCenter_Align;
   1380         }
   1381         else if (!strcmp(jsonAlign, SKDEBUGCANVAS_ALIGN_RIGHT)) {
   1382             textAlign = SkPaint::kRight_Align;
   1383         }
   1384         else {
   1385             SkASSERT(false);
   1386             textAlign = SkPaint::kLeft_Align;
   1387         }
   1388         target->setTextAlign(textAlign);
   1389     }
   1390 }
   1391 
   1392 static void extract_json_paint_textsize(Json::Value& jsonPaint, SkPaint* target) {
   1393     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE)) {
   1394         float textSize = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE].asFloat();
   1395         target->setTextSize(textSize);
   1396     }
   1397 }
   1398 
   1399 static void extract_json_paint_textscalex(Json::Value& jsonPaint, SkPaint* target) {
   1400     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX)) {
   1401         float textScaleX = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX].asFloat();
   1402         target->setTextScaleX(textScaleX);
   1403     }
   1404 }
   1405 
   1406 static void extract_json_paint_textskewx(Json::Value& jsonPaint, SkPaint* target) {
   1407     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX)) {
   1408         float textSkewX = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX].asFloat();
   1409         target->setTextSkewX(textSkewX);
   1410     }
   1411 }
   1412 
   1413 static void extract_json_paint(Json::Value& paint, UrlDataManager& urlDataManager,
   1414                                SkPaint* result) {
   1415     extract_json_paint_color(paint, result);
   1416     extract_json_paint_shader(paint, urlDataManager, result);
   1417     extract_json_paint_patheffect(paint, urlDataManager, result);
   1418     extract_json_paint_maskfilter(paint, urlDataManager, result);
   1419     extract_json_paint_colorfilter(paint, urlDataManager, result);
   1420     extract_json_paint_xfermode(paint, urlDataManager, result);
   1421     extract_json_paint_looper(paint, urlDataManager, result);
   1422     extract_json_paint_imagefilter(paint, urlDataManager, result);
   1423     extract_json_paint_typeface(paint, urlDataManager, result);
   1424     extract_json_paint_style(paint, result);
   1425     extract_json_paint_strokewidth(paint, result);
   1426     extract_json_paint_strokemiter(paint, result);
   1427     extract_json_paint_strokejoin(paint, result);
   1428     extract_json_paint_cap(paint, result);
   1429     extract_json_paint_filterquality(paint, result);
   1430     extract_json_paint_antialias(paint, result);
   1431     extract_json_paint_dither(paint, result);
   1432     extract_json_paint_blur(paint, result);
   1433     extract_json_paint_dashing(paint, result);
   1434     extract_json_paint_textalign(paint, result);
   1435     extract_json_paint_textsize(paint, result);
   1436     extract_json_paint_textscalex(paint, result);
   1437     extract_json_paint_textskewx(paint, result);
   1438 }
   1439 
   1440 static void extract_json_rect(Json::Value& rect, SkRect* result) {
   1441     result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3].asFloat());
   1442 }
   1443 
   1444 static void extract_json_irect(Json::Value& rect, SkIRect* result) {
   1445     result->set(rect[0].asInt(), rect[1].asInt(), rect[2].asInt(), rect[3].asInt());
   1446 }
   1447 
   1448 static void extract_json_rrect(Json::Value& rrect, SkRRect* result) {
   1449     SkVector radii[4] = {
   1450                             { rrect[1][0].asFloat(), rrect[1][1].asFloat() },
   1451                             { rrect[2][0].asFloat(), rrect[2][1].asFloat() },
   1452                             { rrect[3][0].asFloat(), rrect[3][1].asFloat() },
   1453                             { rrect[4][0].asFloat(), rrect[4][1].asFloat() }
   1454                         };
   1455     result->setRectRadii(SkRect::MakeLTRB(rrect[0][0].asFloat(), rrect[0][1].asFloat(),
   1456                                           rrect[0][2].asFloat(), rrect[0][3].asFloat()),
   1457                                           radii);
   1458 }
   1459 
   1460 static void extract_json_matrix(Json::Value& matrix, SkMatrix* result) {
   1461     SkScalar values[] = {
   1462         matrix[0][0].asFloat(), matrix[0][1].asFloat(), matrix[0][2].asFloat(),
   1463         matrix[1][0].asFloat(), matrix[1][1].asFloat(), matrix[1][2].asFloat(),
   1464         matrix[2][0].asFloat(), matrix[2][1].asFloat(), matrix[2][2].asFloat()
   1465     };
   1466     result->set9(values);
   1467 }
   1468 
   1469 static void extract_json_path(Json::Value& path, SkPath* result) {
   1470     const char* fillType = path[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE].asCString();
   1471     if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_WINDING)) {
   1472         result->setFillType(SkPath::kWinding_FillType);
   1473     }
   1474     else if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_EVENODD)) {
   1475         result->setFillType(SkPath::kEvenOdd_FillType);
   1476     }
   1477     else if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING)) {
   1478         result->setFillType(SkPath::kInverseWinding_FillType);
   1479     }
   1480     else if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD)) {
   1481         result->setFillType(SkPath::kInverseEvenOdd_FillType);
   1482     }
   1483     Json::Value verbs = path[SKDEBUGCANVAS_ATTRIBUTE_VERBS];
   1484     for (Json::ArrayIndex i = 0; i < verbs.size(); i++) {
   1485         Json::Value verb = verbs[i];
   1486         if (verb.isString()) {
   1487             SkASSERT(!strcmp(verb.asCString(), SKDEBUGCANVAS_VERB_CLOSE));
   1488             result->close();
   1489         }
   1490         else {
   1491             if (verb.isMember(SKDEBUGCANVAS_VERB_MOVE)) {
   1492                 Json::Value move = verb[SKDEBUGCANVAS_VERB_MOVE];
   1493                 result->moveTo(move[0].asFloat(), move[1].asFloat());
   1494             }
   1495             else if (verb.isMember(SKDEBUGCANVAS_VERB_LINE)) {
   1496                 Json::Value line = verb[SKDEBUGCANVAS_VERB_LINE];
   1497                 result->lineTo(line[0].asFloat(), line[1].asFloat());
   1498             }
   1499             else if (verb.isMember(SKDEBUGCANVAS_VERB_QUAD)) {
   1500                 Json::Value quad = verb[SKDEBUGCANVAS_VERB_QUAD];
   1501                 result->quadTo(quad[0][0].asFloat(), quad[0][1].asFloat(),
   1502                                quad[1][0].asFloat(), quad[1][1].asFloat());
   1503             }
   1504             else if (verb.isMember(SKDEBUGCANVAS_VERB_CUBIC)) {
   1505                 Json::Value cubic = verb[SKDEBUGCANVAS_VERB_CUBIC];
   1506                 result->cubicTo(cubic[0][0].asFloat(), cubic[0][1].asFloat(),
   1507                                 cubic[1][0].asFloat(), cubic[1][1].asFloat(),
   1508                                 cubic[2][0].asFloat(), cubic[2][1].asFloat());
   1509             }
   1510             else if (verb.isMember(SKDEBUGCANVAS_VERB_CONIC)) {
   1511                 Json::Value conic = verb[SKDEBUGCANVAS_VERB_CONIC];
   1512                 result->conicTo(conic[0][0].asFloat(), conic[0][1].asFloat(),
   1513                                 conic[1][0].asFloat(), conic[1][1].asFloat(),
   1514                                 conic[2].asFloat());
   1515             }
   1516             else {
   1517                 SkASSERT(false);
   1518             }
   1519         }
   1520     }
   1521 }
   1522 
   1523 SkRegion::Op get_json_regionop(Json::Value& jsonOp) {
   1524     const char* op = jsonOp.asCString();
   1525     if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_DIFFERENCE)) {
   1526         return SkRegion::kDifference_Op;
   1527     }
   1528     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_INTERSECT)) {
   1529         return SkRegion::kIntersect_Op;
   1530     }
   1531     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_UNION)) {
   1532         return SkRegion::kUnion_Op;
   1533     }
   1534     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_XOR)) {
   1535         return SkRegion::kXOR_Op;
   1536     }
   1537     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE)) {
   1538         return SkRegion::kReverseDifference_Op;
   1539     }
   1540     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_REPLACE)) {
   1541         return SkRegion::kReplace_Op;
   1542     }
   1543     SkASSERT(false);
   1544     return SkRegion::kIntersect_Op;
   1545 }
   1546 
   1547 SkClearCommand::SkClearCommand(SkColor color) : INHERITED(kDrawClear_OpType) {
   1548     fColor = color;
   1549     fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
   1550 }
   1551 
   1552 void SkClearCommand::execute(SkCanvas* canvas) const {
   1553     canvas->clear(fColor);
   1554 }
   1555 
   1556 Json::Value SkClearCommand::toJSON(UrlDataManager& urlDataManager) const {
   1557     Json::Value result = INHERITED::toJSON(urlDataManager);
   1558     result[SKDEBUGCANVAS_ATTRIBUTE_COLOR] = make_json_color(fColor);
   1559     return result;
   1560 }
   1561 
   1562  SkClearCommand* SkClearCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
   1563     Json::Value color = command[SKDEBUGCANVAS_ATTRIBUTE_COLOR];
   1564     return new SkClearCommand(get_json_color(color));
   1565 }
   1566 
   1567 SkClipPathCommand::SkClipPathCommand(const SkPath& path, SkRegion::Op op, bool doAA)
   1568     : INHERITED(kClipPath_OpType) {
   1569     fPath = path;
   1570     fOp = op;
   1571     fDoAA = doAA;
   1572 
   1573     fInfo.push(SkObjectParser::PathToString(path));
   1574     fInfo.push(SkObjectParser::RegionOpToString(op));
   1575     fInfo.push(SkObjectParser::BoolToString(doAA));
   1576 }
   1577 
   1578 void SkClipPathCommand::execute(SkCanvas* canvas) const {
   1579     canvas->clipPath(fPath, fOp, fDoAA);
   1580 }
   1581 
   1582 bool SkClipPathCommand::render(SkCanvas* canvas) const {
   1583     render_path(canvas, fPath);
   1584     return true;
   1585 }
   1586 
   1587 Json::Value SkClipPathCommand::toJSON(UrlDataManager& urlDataManager) const {
   1588     Json::Value result = INHERITED::toJSON(urlDataManager);
   1589     result[SKDEBUGCANVAS_ATTRIBUTE_PATH] = make_json_path(fPath);
   1590     result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
   1591     result[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS] = fDoAA;
   1592     return result;
   1593 }
   1594 
   1595 SkClipPathCommand* SkClipPathCommand::fromJSON(Json::Value& command,
   1596                                                UrlDataManager& urlDataManager) {
   1597     SkPath path;
   1598     extract_json_path(command[SKDEBUGCANVAS_ATTRIBUTE_PATH], &path);
   1599     return new SkClipPathCommand(path, get_json_regionop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]),
   1600                                  command[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
   1601 }
   1602 
   1603 SkClipRegionCommand::SkClipRegionCommand(const SkRegion& region, SkRegion::Op op)
   1604     : INHERITED(kClipRegion_OpType) {
   1605     fRegion = region;
   1606     fOp = op;
   1607 
   1608     fInfo.push(SkObjectParser::RegionToString(region));
   1609     fInfo.push(SkObjectParser::RegionOpToString(op));
   1610 }
   1611 
   1612 void SkClipRegionCommand::execute(SkCanvas* canvas) const {
   1613     canvas->clipRegion(fRegion, fOp);
   1614 }
   1615 
   1616 Json::Value SkClipRegionCommand::toJSON(UrlDataManager& urlDataManager) const {
   1617     Json::Value result = INHERITED::toJSON(urlDataManager);
   1618     result[SKDEBUGCANVAS_ATTRIBUTE_REGION] = make_json_region(fRegion);
   1619     result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
   1620     return result;
   1621 }
   1622 
   1623 SkClipRegionCommand* SkClipRegionCommand::fromJSON(Json::Value& command,
   1624                                                    UrlDataManager& urlDataManager) {
   1625     SkASSERT(false);
   1626     return nullptr;
   1627 }
   1628 
   1629 SkClipRectCommand::SkClipRectCommand(const SkRect& rect, SkRegion::Op op, bool doAA)
   1630     : INHERITED(kClipRect_OpType) {
   1631     fRect = rect;
   1632     fOp = op;
   1633     fDoAA = doAA;
   1634 
   1635     fInfo.push(SkObjectParser::RectToString(rect));
   1636     fInfo.push(SkObjectParser::RegionOpToString(op));
   1637     fInfo.push(SkObjectParser::BoolToString(doAA));
   1638 }
   1639 
   1640 void SkClipRectCommand::execute(SkCanvas* canvas) const {
   1641     canvas->clipRect(fRect, fOp, fDoAA);
   1642 }
   1643 
   1644 Json::Value SkClipRectCommand::toJSON(UrlDataManager& urlDataManager) const {
   1645     Json::Value result = INHERITED::toJSON(urlDataManager);
   1646     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rect(fRect);
   1647     result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
   1648     result[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS] = Json::Value(fDoAA);
   1649     return result;
   1650 }
   1651 
   1652 SkClipRectCommand* SkClipRectCommand::fromJSON(Json::Value& command,
   1653                                                UrlDataManager& urlDataManager) {
   1654     SkRect rect;
   1655     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &rect);
   1656     return new SkClipRectCommand(rect, get_json_regionop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]),
   1657                                  command[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
   1658 }
   1659 
   1660 SkClipRRectCommand::SkClipRRectCommand(const SkRRect& rrect, SkRegion::Op op, bool doAA)
   1661     : INHERITED(kClipRRect_OpType) {
   1662     fRRect = rrect;
   1663     fOp = op;
   1664     fDoAA = doAA;
   1665 
   1666     fInfo.push(SkObjectParser::RRectToString(rrect));
   1667     fInfo.push(SkObjectParser::RegionOpToString(op));
   1668     fInfo.push(SkObjectParser::BoolToString(doAA));
   1669 }
   1670 
   1671 void SkClipRRectCommand::execute(SkCanvas* canvas) const {
   1672     canvas->clipRRect(fRRect, fOp, fDoAA);
   1673 }
   1674 
   1675 bool SkClipRRectCommand::render(SkCanvas* canvas) const {
   1676     render_rrect(canvas, fRRect);
   1677     return true;
   1678 }
   1679 
   1680 Json::Value SkClipRRectCommand::toJSON(UrlDataManager& urlDataManager) const {
   1681     Json::Value result = INHERITED::toJSON(urlDataManager);
   1682     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rrect(fRRect);
   1683     result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
   1684     result[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS] = Json::Value(fDoAA);
   1685     return result;
   1686 }
   1687 
   1688 SkClipRRectCommand* SkClipRRectCommand::fromJSON(Json::Value& command,
   1689                                                  UrlDataManager& urlDataManager) {
   1690     SkRRect rrect;
   1691     extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &rrect);
   1692     return new SkClipRRectCommand(rrect,
   1693                                   get_json_regionop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]),
   1694                                   command[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
   1695 }
   1696 
   1697 SkConcatCommand::SkConcatCommand(const SkMatrix& matrix)
   1698     : INHERITED(kConcat_OpType) {
   1699     fMatrix = matrix;
   1700 
   1701     fInfo.push(SkObjectParser::MatrixToString(matrix));
   1702 }
   1703 
   1704 void SkConcatCommand::execute(SkCanvas* canvas) const {
   1705     canvas->concat(fMatrix);
   1706 }
   1707 
   1708 Json::Value SkConcatCommand::toJSON(UrlDataManager& urlDataManager) const {
   1709     Json::Value result = INHERITED::toJSON(urlDataManager);
   1710     result[SKDEBUGCANVAS_ATTRIBUTE_MATRIX] = make_json_matrix(fMatrix);
   1711     return result;
   1712 }
   1713 
   1714 SkConcatCommand* SkConcatCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
   1715     SkMatrix matrix;
   1716     extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
   1717     return new SkConcatCommand(matrix);
   1718 }
   1719 
   1720 SkDrawBitmapCommand::SkDrawBitmapCommand(const SkBitmap& bitmap, SkScalar left, SkScalar top,
   1721                                          const SkPaint* paint)
   1722     : INHERITED(kDrawBitmap_OpType) {
   1723     fBitmap = bitmap;
   1724     fLeft = left;
   1725     fTop = top;
   1726     if (paint) {
   1727         fPaint = *paint;
   1728         fPaintPtr = &fPaint;
   1729     } else {
   1730         fPaintPtr = nullptr;
   1731     }
   1732 
   1733     fInfo.push(SkObjectParser::BitmapToString(bitmap));
   1734     fInfo.push(SkObjectParser::ScalarToString(left, "SkScalar left: "));
   1735     fInfo.push(SkObjectParser::ScalarToString(top, "SkScalar top: "));
   1736     if (paint) {
   1737         fInfo.push(SkObjectParser::PaintToString(*paint));
   1738     }
   1739 }
   1740 
   1741 void SkDrawBitmapCommand::execute(SkCanvas* canvas) const {
   1742     canvas->drawBitmap(fBitmap, fLeft, fTop, fPaintPtr);
   1743 }
   1744 
   1745 bool SkDrawBitmapCommand::render(SkCanvas* canvas) const {
   1746     render_bitmap(canvas, fBitmap);
   1747     return true;
   1748 }
   1749 
   1750 Json::Value SkDrawBitmapCommand::toJSON(UrlDataManager& urlDataManager) const {
   1751     Json::Value result = INHERITED::toJSON(urlDataManager);
   1752     Json::Value encoded;
   1753     if (flatten(fBitmap, &encoded, urlDataManager)) {
   1754         Json::Value command(Json::objectValue);
   1755         result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
   1756         result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_point(fLeft, fTop);
   1757         if (fPaintPtr != nullptr) {
   1758             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaintPtr, urlDataManager);
   1759         }
   1760     }
   1761     return result;
   1762 }
   1763 
   1764 SkDrawBitmapCommand* SkDrawBitmapCommand::fromJSON(Json::Value& command,
   1765                                                    UrlDataManager& urlDataManager) {
   1766     SkBitmap* bitmap = load_bitmap(command[SKDEBUGCANVAS_ATTRIBUTE_BITMAP], urlDataManager);
   1767     if (bitmap == nullptr) {
   1768         return nullptr;
   1769     }
   1770     Json::Value point = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
   1771     SkPaint* paintPtr;
   1772     SkPaint paint;
   1773     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
   1774         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   1775         paintPtr = &paint;
   1776     }
   1777     else {
   1778         paintPtr = nullptr;
   1779     }
   1780     SkDrawBitmapCommand* result = new SkDrawBitmapCommand(*bitmap, point[0].asFloat(),
   1781                                                           point[1].asFloat(), paintPtr);
   1782     delete bitmap;
   1783     return result;
   1784 }
   1785 
   1786 SkDrawBitmapNineCommand::SkDrawBitmapNineCommand(const SkBitmap& bitmap, const SkIRect& center,
   1787                                                  const SkRect& dst, const SkPaint* paint)
   1788     : INHERITED(kDrawBitmapNine_OpType) {
   1789     fBitmap = bitmap;
   1790     fCenter = center;
   1791     fDst = dst;
   1792     if (paint) {
   1793         fPaint = *paint;
   1794         fPaintPtr = &fPaint;
   1795     } else {
   1796         fPaintPtr = nullptr;
   1797     }
   1798 
   1799     fInfo.push(SkObjectParser::BitmapToString(bitmap));
   1800     fInfo.push(SkObjectParser::IRectToString(center));
   1801     fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
   1802     if (paint) {
   1803         fInfo.push(SkObjectParser::PaintToString(*paint));
   1804     }
   1805 }
   1806 
   1807 void SkDrawBitmapNineCommand::execute(SkCanvas* canvas) const {
   1808     canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaintPtr);
   1809 }
   1810 
   1811 bool SkDrawBitmapNineCommand::render(SkCanvas* canvas) const {
   1812     SkRect tmp = SkRect::Make(fCenter);
   1813     render_bitmap(canvas, fBitmap, &tmp);
   1814     return true;
   1815 }
   1816 
   1817 Json::Value SkDrawBitmapNineCommand::toJSON(UrlDataManager& urlDataManager) const {
   1818     Json::Value result = INHERITED::toJSON(urlDataManager);
   1819     Json::Value encoded;
   1820     if (flatten(fBitmap, &encoded, urlDataManager)) {
   1821         result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
   1822         result[SKDEBUGCANVAS_ATTRIBUTE_CENTER] = make_json_irect(fCenter);
   1823         result[SKDEBUGCANVAS_ATTRIBUTE_DST] = make_json_rect(fDst);
   1824         if (fPaintPtr != nullptr) {
   1825             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaintPtr, urlDataManager);
   1826         }
   1827     }
   1828     return result;
   1829 }
   1830 
   1831 SkDrawBitmapNineCommand* SkDrawBitmapNineCommand::fromJSON(Json::Value& command,
   1832                                                            UrlDataManager& urlDataManager) {
   1833     SkBitmap* bitmap = load_bitmap(command[SKDEBUGCANVAS_ATTRIBUTE_BITMAP], urlDataManager);
   1834     if (bitmap == nullptr) {
   1835         return nullptr;
   1836     }
   1837     SkIRect center;
   1838     extract_json_irect(command[SKDEBUGCANVAS_ATTRIBUTE_CENTER], &center);
   1839     SkRect dst;
   1840     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
   1841     SkPaint* paintPtr;
   1842     SkPaint paint;
   1843     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
   1844         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   1845         paintPtr = &paint;
   1846     }
   1847     else {
   1848         paintPtr = nullptr;
   1849     }
   1850     SkDrawBitmapNineCommand* result = new SkDrawBitmapNineCommand(*bitmap, center, dst, paintPtr);
   1851     delete bitmap;
   1852     return result;
   1853 }
   1854 
   1855 SkDrawBitmapRectCommand::SkDrawBitmapRectCommand(const SkBitmap& bitmap, const SkRect* src,
   1856                                                  const SkRect& dst, const SkPaint* paint,
   1857                                                  SkCanvas::SrcRectConstraint constraint)
   1858     : INHERITED(kDrawBitmapRect_OpType) {
   1859     fBitmap = bitmap;
   1860     if (src) {
   1861         fSrc = *src;
   1862     } else {
   1863         fSrc.setEmpty();
   1864     }
   1865     fDst = dst;
   1866 
   1867     if (paint) {
   1868         fPaint = *paint;
   1869         fPaintPtr = &fPaint;
   1870     } else {
   1871         fPaintPtr = nullptr;
   1872     }
   1873     fConstraint = constraint;
   1874 
   1875     fInfo.push(SkObjectParser::BitmapToString(bitmap));
   1876     if (src) {
   1877         fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
   1878     }
   1879     fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
   1880     if (paint) {
   1881         fInfo.push(SkObjectParser::PaintToString(*paint));
   1882     }
   1883     fInfo.push(SkObjectParser::IntToString(fConstraint, "Constraint: "));
   1884 }
   1885 
   1886 void SkDrawBitmapRectCommand::execute(SkCanvas* canvas) const {
   1887     canvas->legacy_drawBitmapRect(fBitmap, this->srcRect(), fDst, fPaintPtr, fConstraint);
   1888 }
   1889 
   1890 bool SkDrawBitmapRectCommand::render(SkCanvas* canvas) const {
   1891     render_bitmap(canvas, fBitmap, this->srcRect());
   1892     return true;
   1893 }
   1894 
   1895 Json::Value SkDrawBitmapRectCommand::toJSON(UrlDataManager& urlDataManager) const {
   1896     Json::Value result = INHERITED::toJSON(urlDataManager);
   1897     Json::Value encoded;
   1898     if (flatten(fBitmap, &encoded, urlDataManager)) {
   1899         result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
   1900         if (!fSrc.isEmpty()) {
   1901             result[SKDEBUGCANVAS_ATTRIBUTE_SRC] = make_json_rect(fSrc);
   1902         }
   1903         result[SKDEBUGCANVAS_ATTRIBUTE_DST] = make_json_rect(fDst);
   1904         if (fPaintPtr != nullptr) {
   1905             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaintPtr, urlDataManager);
   1906         }
   1907         if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
   1908             result[SKDEBUGCANVAS_ATTRIBUTE_STRICT] = Json::Value(true);
   1909         }
   1910     }
   1911     return result;
   1912 }
   1913 
   1914 SkDrawBitmapRectCommand* SkDrawBitmapRectCommand::fromJSON(Json::Value& command,
   1915                                                            UrlDataManager& urlDataManager) {
   1916     SkBitmap* bitmap = load_bitmap(command[SKDEBUGCANVAS_ATTRIBUTE_BITMAP], urlDataManager);
   1917     if (bitmap == nullptr) {
   1918         return nullptr;
   1919     }
   1920     SkRect dst;
   1921     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
   1922     SkPaint* paintPtr;
   1923     SkPaint paint;
   1924     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
   1925         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   1926         paintPtr = &paint;
   1927     }
   1928     else {
   1929         paintPtr = nullptr;
   1930     }
   1931     SkCanvas::SrcRectConstraint constraint;
   1932     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_STRICT) &&
   1933         command[SKDEBUGCANVAS_ATTRIBUTE_STRICT].asBool()) {
   1934         constraint = SkCanvas::kStrict_SrcRectConstraint;
   1935     }
   1936     else {
   1937         constraint = SkCanvas::kFast_SrcRectConstraint;
   1938     }
   1939     SkRect* srcPtr;
   1940     SkRect src;
   1941     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_SRC)) {
   1942         extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_SRC], &src);
   1943         srcPtr = &src;
   1944     }
   1945     else {
   1946         srcPtr = nullptr;
   1947     }
   1948     SkDrawBitmapRectCommand* result = new SkDrawBitmapRectCommand(*bitmap, srcPtr, dst, paintPtr,
   1949                                                                   constraint);
   1950     delete bitmap;
   1951     return result;
   1952 }
   1953 
   1954 SkDrawImageCommand::SkDrawImageCommand(const SkImage* image, SkScalar left, SkScalar top,
   1955                                        const SkPaint* paint)
   1956     : INHERITED(kDrawImage_OpType)
   1957     , fImage(SkRef(image))
   1958     , fLeft(left)
   1959     , fTop(top) {
   1960 
   1961     fInfo.push(SkObjectParser::ImageToString(image));
   1962     fInfo.push(SkObjectParser::ScalarToString(left, "Left: "));
   1963     fInfo.push(SkObjectParser::ScalarToString(top, "Top: "));
   1964 
   1965     if (paint) {
   1966         fPaint.set(*paint);
   1967         fInfo.push(SkObjectParser::PaintToString(*paint));
   1968     }
   1969 }
   1970 
   1971 void SkDrawImageCommand::execute(SkCanvas* canvas) const {
   1972     canvas->drawImage(fImage, fLeft, fTop, fPaint.getMaybeNull());
   1973 }
   1974 
   1975 bool SkDrawImageCommand::render(SkCanvas* canvas) const {
   1976     SkAutoCanvasRestore acr(canvas, true);
   1977     canvas->clear(0xFFFFFFFF);
   1978 
   1979     xlate_and_scale_to_bounds(canvas, SkRect::MakeXYWH(fLeft, fTop,
   1980                                                        SkIntToScalar(fImage->width()),
   1981                                                        SkIntToScalar(fImage->height())));
   1982     this->execute(canvas);
   1983     return true;
   1984 }
   1985 
   1986 Json::Value SkDrawImageCommand::toJSON(UrlDataManager& urlDataManager) const {
   1987     Json::Value result = INHERITED::toJSON(urlDataManager);
   1988     Json::Value encoded;
   1989     if (flatten(*fImage, &encoded, urlDataManager)) {
   1990         result[SKDEBUGCANVAS_ATTRIBUTE_IMAGE] = encoded;
   1991         result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_point(fLeft, fTop);
   1992         if (fPaint.isValid()) {
   1993             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaint.get(), urlDataManager);
   1994         }
   1995     }
   1996     return result;
   1997 }
   1998 
   1999 SkDrawImageCommand* SkDrawImageCommand::fromJSON(Json::Value& command,
   2000                                                  UrlDataManager& urlDataManager) {
   2001     SkImage* image = load_image(command[SKDEBUGCANVAS_ATTRIBUTE_IMAGE], urlDataManager);
   2002     if (image == nullptr) {
   2003         return nullptr;
   2004     }
   2005     Json::Value point = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
   2006     SkPaint* paintPtr;
   2007     SkPaint paint;
   2008     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
   2009         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2010         paintPtr = &paint;
   2011     }
   2012     else {
   2013         paintPtr = nullptr;
   2014     }
   2015     SkDrawImageCommand* result = new SkDrawImageCommand(image, point[0].asFloat(),
   2016                                                         point[1].asFloat(), paintPtr);
   2017     image->unref();
   2018     return result;
   2019 }
   2020 
   2021 SkDrawImageRectCommand::SkDrawImageRectCommand(const SkImage* image, const SkRect* src,
   2022                                                const SkRect& dst, const SkPaint* paint,
   2023                                                SkCanvas::SrcRectConstraint constraint)
   2024     : INHERITED(kDrawImageRect_OpType)
   2025     , fImage(SkRef(image))
   2026     , fDst(dst)
   2027     , fConstraint(constraint) {
   2028 
   2029     if (src) {
   2030         fSrc.set(*src);
   2031     }
   2032 
   2033     if (paint) {
   2034         fPaint.set(*paint);
   2035     }
   2036 
   2037     fInfo.push(SkObjectParser::ImageToString(image));
   2038     if (src) {
   2039         fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
   2040     }
   2041     fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
   2042     if (paint) {
   2043         fInfo.push(SkObjectParser::PaintToString(*paint));
   2044     }
   2045     fInfo.push(SkObjectParser::IntToString(fConstraint, "Constraint: "));
   2046 }
   2047 
   2048 void SkDrawImageRectCommand::execute(SkCanvas* canvas) const {
   2049     canvas->legacy_drawImageRect(fImage, fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(),
   2050                                  fConstraint);
   2051 }
   2052 
   2053 bool SkDrawImageRectCommand::render(SkCanvas* canvas) const {
   2054     SkAutoCanvasRestore acr(canvas, true);
   2055     canvas->clear(0xFFFFFFFF);
   2056 
   2057     xlate_and_scale_to_bounds(canvas, fDst);
   2058 
   2059     this->execute(canvas);
   2060     return true;
   2061 }
   2062 
   2063 Json::Value SkDrawImageRectCommand::toJSON(UrlDataManager& urlDataManager) const {
   2064     Json::Value result = INHERITED::toJSON(urlDataManager);
   2065     Json::Value encoded;
   2066     if (flatten(*fImage.get(), &encoded, urlDataManager)) {
   2067         result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
   2068         if (fSrc.isValid()) {
   2069             result[SKDEBUGCANVAS_ATTRIBUTE_SRC] = make_json_rect(*fSrc.get());
   2070         }
   2071         result[SKDEBUGCANVAS_ATTRIBUTE_DST] = make_json_rect(fDst);
   2072         if (fPaint.isValid()) {
   2073             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaint.get(), urlDataManager);
   2074         }
   2075         if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
   2076             result[SKDEBUGCANVAS_ATTRIBUTE_STRICT] = Json::Value(true);
   2077         }
   2078     }
   2079     return result;
   2080 }
   2081 
   2082 SkDrawImageRectCommand* SkDrawImageRectCommand::fromJSON(Json::Value& command,
   2083                                                          UrlDataManager& urlDataManager) {
   2084     SkImage* image = load_image(command[SKDEBUGCANVAS_ATTRIBUTE_IMAGE], urlDataManager);
   2085     if (image == nullptr) {
   2086         return nullptr;
   2087     }
   2088     SkRect dst;
   2089     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
   2090     SkPaint* paintPtr;
   2091     SkPaint paint;
   2092     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
   2093         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2094         paintPtr = &paint;
   2095     }
   2096     else {
   2097         paintPtr = nullptr;
   2098     }
   2099     SkCanvas::SrcRectConstraint constraint;
   2100     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_STRICT) &&
   2101         command[SKDEBUGCANVAS_ATTRIBUTE_STRICT].asBool()) {
   2102         constraint = SkCanvas::kStrict_SrcRectConstraint;
   2103     }
   2104     else {
   2105         constraint = SkCanvas::kFast_SrcRectConstraint;
   2106     }
   2107     SkRect* srcPtr;
   2108     SkRect src;
   2109     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_SRC)) {
   2110         extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_SRC], &src);
   2111         srcPtr = &src;
   2112     }
   2113     else {
   2114         srcPtr = nullptr;
   2115     }
   2116     SkDrawImageRectCommand* result = new SkDrawImageRectCommand(image, srcPtr, dst, paintPtr,
   2117                                                                 constraint);
   2118     image->unref();
   2119     return result;
   2120 }
   2121 
   2122 SkDrawOvalCommand::SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint)
   2123     : INHERITED(kDrawOval_OpType) {
   2124     fOval = oval;
   2125     fPaint = paint;
   2126 
   2127     fInfo.push(SkObjectParser::RectToString(oval));
   2128     fInfo.push(SkObjectParser::PaintToString(paint));
   2129 }
   2130 
   2131 void SkDrawOvalCommand::execute(SkCanvas* canvas) const {
   2132     canvas->drawOval(fOval, fPaint);
   2133 }
   2134 
   2135 bool SkDrawOvalCommand::render(SkCanvas* canvas) const {
   2136     canvas->clear(0xFFFFFFFF);
   2137     canvas->save();
   2138 
   2139     xlate_and_scale_to_bounds(canvas, fOval);
   2140 
   2141     SkPaint p;
   2142     p.setColor(SK_ColorBLACK);
   2143     p.setStyle(SkPaint::kStroke_Style);
   2144 
   2145     canvas->drawOval(fOval, p);
   2146     canvas->restore();
   2147 
   2148     return true;
   2149 }
   2150 
   2151 Json::Value SkDrawOvalCommand::toJSON(UrlDataManager& urlDataManager) const {
   2152     Json::Value result = INHERITED::toJSON(urlDataManager);
   2153     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rect(fOval);
   2154     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2155     return result;
   2156 }
   2157 
   2158 SkDrawOvalCommand* SkDrawOvalCommand::fromJSON(Json::Value& command,
   2159                                                UrlDataManager& urlDataManager) {
   2160     SkRect coords;
   2161     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
   2162     SkPaint paint;
   2163     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2164     return new SkDrawOvalCommand(coords, paint);
   2165 }
   2166 
   2167 SkDrawPaintCommand::SkDrawPaintCommand(const SkPaint& paint)
   2168     : INHERITED(kDrawPaint_OpType) {
   2169     fPaint = paint;
   2170 
   2171     fInfo.push(SkObjectParser::PaintToString(paint));
   2172 }
   2173 
   2174 void SkDrawPaintCommand::execute(SkCanvas* canvas) const {
   2175     canvas->drawPaint(fPaint);
   2176 }
   2177 
   2178 bool SkDrawPaintCommand::render(SkCanvas* canvas) const {
   2179     canvas->clear(0xFFFFFFFF);
   2180     canvas->drawPaint(fPaint);
   2181     return true;
   2182 }
   2183 
   2184 Json::Value SkDrawPaintCommand::toJSON(UrlDataManager& urlDataManager) const {
   2185     Json::Value result = INHERITED::toJSON(urlDataManager);
   2186     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2187     return result;
   2188 }
   2189 
   2190 SkDrawPaintCommand* SkDrawPaintCommand::fromJSON(Json::Value& command,
   2191                                                  UrlDataManager& urlDataManager) {
   2192     SkPaint paint;
   2193     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2194     return new SkDrawPaintCommand(paint);
   2195 }
   2196 
   2197 SkDrawPathCommand::SkDrawPathCommand(const SkPath& path, const SkPaint& paint)
   2198     : INHERITED(kDrawPath_OpType) {
   2199     fPath = path;
   2200     fPaint = paint;
   2201 
   2202     fInfo.push(SkObjectParser::PathToString(path));
   2203     fInfo.push(SkObjectParser::PaintToString(paint));
   2204 }
   2205 
   2206 void SkDrawPathCommand::execute(SkCanvas* canvas) const {
   2207     canvas->drawPath(fPath, fPaint);
   2208 }
   2209 
   2210 bool SkDrawPathCommand::render(SkCanvas* canvas) const {
   2211     render_path(canvas, fPath);
   2212     return true;
   2213 }
   2214 
   2215 Json::Value SkDrawPathCommand::toJSON(UrlDataManager& urlDataManager) const {
   2216     Json::Value result = INHERITED::toJSON(urlDataManager);
   2217     result[SKDEBUGCANVAS_ATTRIBUTE_PATH] = make_json_path(fPath);
   2218     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2219     return result;
   2220 }
   2221 
   2222 SkDrawPathCommand* SkDrawPathCommand::fromJSON(Json::Value& command,
   2223                                                UrlDataManager& urlDataManager) {
   2224     SkPath path;
   2225     extract_json_path(command[SKDEBUGCANVAS_ATTRIBUTE_PATH], &path);
   2226     SkPaint paint;
   2227     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2228     return new SkDrawPathCommand(path, paint);
   2229 }
   2230 
   2231 SkBeginDrawPictureCommand::SkBeginDrawPictureCommand(const SkPicture* picture,
   2232                                                      const SkMatrix* matrix,
   2233                                                      const SkPaint* paint)
   2234     : INHERITED(kBeginDrawPicture_OpType)
   2235     , fPicture(SkRef(picture)) {
   2236 
   2237     SkString* str = new SkString;
   2238     str->appendf("SkPicture: L: %f T: %f R: %f B: %f",
   2239                  picture->cullRect().fLeft, picture->cullRect().fTop,
   2240                  picture->cullRect().fRight, picture->cullRect().fBottom);
   2241     fInfo.push(str);
   2242 
   2243     if (matrix) {
   2244         fMatrix.set(*matrix);
   2245         fInfo.push(SkObjectParser::MatrixToString(*matrix));
   2246     }
   2247 
   2248     if (paint) {
   2249         fPaint.set(*paint);
   2250         fInfo.push(SkObjectParser::PaintToString(*paint));
   2251     }
   2252 
   2253 }
   2254 
   2255 void SkBeginDrawPictureCommand::execute(SkCanvas* canvas) const {
   2256     if (fPaint.isValid()) {
   2257         SkRect bounds = fPicture->cullRect();
   2258         if (fMatrix.isValid()) {
   2259             fMatrix.get()->mapRect(&bounds);
   2260         }
   2261         canvas->saveLayer(&bounds, fPaint.get());
   2262     }
   2263 
   2264     if (fMatrix.isValid()) {
   2265         if (!fPaint.isValid()) {
   2266             canvas->save();
   2267         }
   2268         canvas->concat(*fMatrix.get());
   2269     }
   2270 }
   2271 
   2272 bool SkBeginDrawPictureCommand::render(SkCanvas* canvas) const {
   2273     canvas->clear(0xFFFFFFFF);
   2274     canvas->save();
   2275 
   2276     xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
   2277 
   2278     canvas->drawPicture(fPicture.get());
   2279 
   2280     canvas->restore();
   2281 
   2282     return true;
   2283 }
   2284 
   2285 SkEndDrawPictureCommand::SkEndDrawPictureCommand(bool restore)
   2286     : INHERITED(kEndDrawPicture_OpType) , fRestore(restore) { }
   2287 
   2288 void SkEndDrawPictureCommand::execute(SkCanvas* canvas) const {
   2289     if (fRestore) {
   2290         canvas->restore();
   2291     }
   2292 }
   2293 
   2294 SkDrawPointsCommand::SkDrawPointsCommand(SkCanvas::PointMode mode, size_t count,
   2295                                          const SkPoint pts[], const SkPaint& paint)
   2296     : INHERITED(kDrawPoints_OpType) {
   2297     fMode = mode;
   2298     fCount = count;
   2299     fPts = new SkPoint[count];
   2300     memcpy(fPts, pts, count * sizeof(SkPoint));
   2301     fPaint = paint;
   2302 
   2303     fInfo.push(SkObjectParser::PointsToString(pts, count));
   2304     fInfo.push(SkObjectParser::ScalarToString(SkIntToScalar((unsigned int)count),
   2305                                               "Points: "));
   2306     fInfo.push(SkObjectParser::PointModeToString(mode));
   2307     fInfo.push(SkObjectParser::PaintToString(paint));
   2308 }
   2309 
   2310 void SkDrawPointsCommand::execute(SkCanvas* canvas) const {
   2311     canvas->drawPoints(fMode, fCount, fPts, fPaint);
   2312 }
   2313 
   2314 bool SkDrawPointsCommand::render(SkCanvas* canvas) const {
   2315     canvas->clear(0xFFFFFFFF);
   2316     canvas->save();
   2317 
   2318     SkRect bounds;
   2319 
   2320     bounds.setEmpty();
   2321     for (unsigned int i = 0; i < fCount; ++i) {
   2322         bounds.growToInclude(fPts[i].fX, fPts[i].fY);
   2323     }
   2324 
   2325     xlate_and_scale_to_bounds(canvas, bounds);
   2326 
   2327     SkPaint p;
   2328     p.setColor(SK_ColorBLACK);
   2329     p.setStyle(SkPaint::kStroke_Style);
   2330 
   2331     canvas->drawPoints(fMode, fCount, fPts, p);
   2332     canvas->restore();
   2333 
   2334     return true;
   2335 }
   2336 
   2337 Json::Value SkDrawPointsCommand::toJSON(UrlDataManager& urlDataManager) const {
   2338     Json::Value result = INHERITED::toJSON(urlDataManager);
   2339     result[SKDEBUGCANVAS_ATTRIBUTE_MODE] = make_json_pointmode(fMode);
   2340     Json::Value points(Json::arrayValue);
   2341     for (size_t i = 0; i < fCount; i++) {
   2342         points.append(make_json_point(fPts[i]));
   2343     }
   2344     result[SKDEBUGCANVAS_ATTRIBUTE_POINTS] = points;
   2345     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2346     return result;
   2347 }
   2348 
   2349 SkDrawPointsCommand* SkDrawPointsCommand::fromJSON(Json::Value& command,
   2350                                                    UrlDataManager& urlDataManager) {
   2351     SkCanvas::PointMode mode;
   2352     const char* jsonMode = command[SKDEBUGCANVAS_ATTRIBUTE_MODE].asCString();
   2353     if (!strcmp(jsonMode, SKDEBUGCANVAS_POINTMODE_POINTS)) {
   2354         mode = SkCanvas::kPoints_PointMode;
   2355     }
   2356     else if (!strcmp(jsonMode, SKDEBUGCANVAS_POINTMODE_LINES)) {
   2357         mode = SkCanvas::kLines_PointMode;
   2358     }
   2359     else if (!strcmp(jsonMode, SKDEBUGCANVAS_POINTMODE_POLYGON)) {
   2360         mode = SkCanvas::kPolygon_PointMode;
   2361     }
   2362     else {
   2363         SkASSERT(false);
   2364         return nullptr;
   2365     }
   2366     Json::Value jsonPoints = command[SKDEBUGCANVAS_ATTRIBUTE_POINTS];
   2367     int count = (int) jsonPoints.size();
   2368     SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
   2369     for (int i = 0; i < count; i++) {
   2370         points[i] = SkPoint::Make(jsonPoints[i][0].asFloat(), jsonPoints[i][1].asFloat());
   2371     }
   2372     SkPaint paint;
   2373     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2374     SkDrawPointsCommand* result = new SkDrawPointsCommand(mode, count, points, paint);
   2375     sk_free(points);
   2376     return result;
   2377 }
   2378 
   2379 SkDrawPosTextCommand::SkDrawPosTextCommand(const void* text, size_t byteLength,
   2380                                            const SkPoint pos[], const SkPaint& paint)
   2381     : INHERITED(kDrawPosText_OpType) {
   2382     size_t numPts = paint.countText(text, byteLength);
   2383 
   2384     fText = new char[byteLength];
   2385     memcpy(fText, text, byteLength);
   2386     fByteLength = byteLength;
   2387 
   2388     fPos = new SkPoint[numPts];
   2389     memcpy(fPos, pos, numPts * sizeof(SkPoint));
   2390 
   2391     fPaint = paint;
   2392 
   2393     fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
   2394     // TODO(chudy): Test that this works.
   2395     fInfo.push(SkObjectParser::PointsToString(pos, 1));
   2396     fInfo.push(SkObjectParser::PaintToString(paint));
   2397 }
   2398 
   2399 void SkDrawPosTextCommand::execute(SkCanvas* canvas) const {
   2400     canvas->drawPosText(fText, fByteLength, fPos, fPaint);
   2401 }
   2402 
   2403 Json::Value SkDrawPosTextCommand::toJSON(UrlDataManager& urlDataManager) const {
   2404     Json::Value result = INHERITED::toJSON(urlDataManager);
   2405     result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
   2406                                                        ((const char*) fText) + fByteLength);
   2407     Json::Value coords(Json::arrayValue);
   2408     for (size_t i = 0; i < fByteLength; i++) {
   2409         coords.append(make_json_point(fPos[i]));
   2410     }
   2411     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = coords;
   2412     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2413     return result;
   2414 }
   2415 
   2416 SkDrawPosTextCommand* SkDrawPosTextCommand::fromJSON(Json::Value& command,
   2417                                                      UrlDataManager& urlDataManager) {
   2418     const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
   2419     SkPaint paint;
   2420     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2421     Json::Value coords = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
   2422     int count = (int) coords.size();
   2423     SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
   2424     for (int i = 0; i < count; i++) {
   2425         points[i] = SkPoint::Make(coords[i][0].asFloat(), coords[i][1].asFloat());
   2426     }
   2427     return new SkDrawPosTextCommand(text, strlen(text), points, paint);
   2428 }
   2429 
   2430 SkDrawPosTextHCommand::SkDrawPosTextHCommand(const void* text, size_t byteLength,
   2431                                              const SkScalar xpos[], SkScalar constY,
   2432                                              const SkPaint& paint)
   2433     : INHERITED(kDrawPosTextH_OpType) {
   2434     size_t numPts = paint.countText(text, byteLength);
   2435 
   2436     fText = new char[byteLength];
   2437     memcpy(fText, text, byteLength);
   2438     fByteLength = byteLength;
   2439 
   2440     fXpos = new SkScalar[numPts];
   2441     memcpy(fXpos, xpos, numPts * sizeof(SkScalar));
   2442 
   2443     fConstY = constY;
   2444     fPaint = paint;
   2445 
   2446     fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
   2447     fInfo.push(SkObjectParser::ScalarToString(xpos[0], "XPOS: "));
   2448     fInfo.push(SkObjectParser::ScalarToString(constY, "SkScalar constY: "));
   2449     fInfo.push(SkObjectParser::PaintToString(paint));
   2450 }
   2451 
   2452 void SkDrawPosTextHCommand::execute(SkCanvas* canvas) const {
   2453     canvas->drawPosTextH(fText, fByteLength, fXpos, fConstY, fPaint);
   2454 }
   2455 
   2456 static const char* gPositioningLabels[] = {
   2457     "kDefault_Positioning",
   2458     "kHorizontal_Positioning",
   2459     "kFull_Positioning",
   2460 };
   2461 
   2462 SkDrawTextBlobCommand::SkDrawTextBlobCommand(const SkTextBlob* blob, SkScalar x, SkScalar y,
   2463                                              const SkPaint& paint)
   2464     : INHERITED(kDrawTextBlob_OpType)
   2465     , fBlob(SkRef(blob))
   2466     , fXPos(x)
   2467     , fYPos(y)
   2468     , fPaint(paint) {
   2469 
   2470     SkAutoTDelete<SkString> runsStr(new SkString);
   2471     fInfo.push(SkObjectParser::ScalarToString(x, "XPOS: "));
   2472     fInfo.push(SkObjectParser::ScalarToString(y, "YPOS: "));
   2473     fInfo.push(SkObjectParser::RectToString(fBlob->bounds(), "Bounds: "));
   2474     fInfo.push(runsStr);
   2475     fInfo.push(SkObjectParser::PaintToString(paint));
   2476 
   2477     unsigned runs = 0;
   2478     SkPaint runPaint(paint);
   2479     SkTextBlobRunIterator iter(blob);
   2480     while (!iter.done()) {
   2481         SkAutoTDelete<SkString> tmpStr(new SkString);
   2482         tmpStr->printf("==== Run [%d] ====", runs++);
   2483         fInfo.push(tmpStr.release());
   2484 
   2485         fInfo.push(SkObjectParser::IntToString(iter.glyphCount(), "GlyphCount: "));
   2486         tmpStr.reset(new SkString("GlyphPositioning: "));
   2487         tmpStr->append(gPositioningLabels[iter.positioning()]);
   2488         fInfo.push(tmpStr.release());
   2489 
   2490         iter.applyFontToPaint(&runPaint);
   2491         fInfo.push(SkObjectParser::PaintToString(runPaint));
   2492 
   2493         iter.next();
   2494     }
   2495 
   2496     runsStr->printf("Runs: %d", runs);
   2497     // runStr is owned by fInfo at this point.
   2498     runsStr.release();
   2499 }
   2500 
   2501 void SkDrawTextBlobCommand::execute(SkCanvas* canvas) const {
   2502     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
   2503 }
   2504 
   2505 bool SkDrawTextBlobCommand::render(SkCanvas* canvas) const {
   2506     canvas->clear(SK_ColorWHITE);
   2507     canvas->save();
   2508 
   2509     SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
   2510     xlate_and_scale_to_bounds(canvas, bounds);
   2511 
   2512     canvas->drawTextBlob(fBlob.get(), fXPos, fYPos, fPaint);
   2513 
   2514     canvas->restore();
   2515 
   2516     return true;
   2517 }
   2518 
   2519 Json::Value SkDrawTextBlobCommand::toJSON(UrlDataManager& urlDataManager) const {
   2520     Json::Value result = INHERITED::toJSON(urlDataManager);
   2521     Json::Value runs(Json::arrayValue);
   2522     SkTextBlobRunIterator iter(fBlob.get());
   2523     while (!iter.done()) {
   2524         Json::Value run(Json::objectValue);
   2525         Json::Value jsonPositions(Json::arrayValue);
   2526         Json::Value jsonGlyphs(Json::arrayValue);
   2527         const SkScalar* iterPositions = iter.pos();
   2528         const uint16_t* iterGlyphs = iter.glyphs();
   2529         for (uint32_t i = 0; i < iter.glyphCount(); i++) {
   2530             switch (iter.positioning()) {
   2531                 case SkTextBlob::kFull_Positioning:
   2532                     jsonPositions.append(make_json_point(iterPositions[i * 2],
   2533                                                          iterPositions[i * 2 + 1]));
   2534                     break;
   2535                 case SkTextBlob::kHorizontal_Positioning:
   2536                     jsonPositions.append(Json::Value(iterPositions[i]));
   2537                     break;
   2538                 case SkTextBlob::kDefault_Positioning:
   2539                     break;
   2540             }
   2541             jsonGlyphs.append(Json::Value(iterGlyphs[i]));
   2542         }
   2543         if (iter.positioning() != SkTextBlob::kDefault_Positioning) {
   2544             run[SKDEBUGCANVAS_ATTRIBUTE_POSITIONS] = jsonPositions;
   2545         }
   2546         run[SKDEBUGCANVAS_ATTRIBUTE_GLYPHS] = jsonGlyphs;
   2547         SkPaint fontPaint;
   2548         iter.applyFontToPaint(&fontPaint);
   2549         run[SKDEBUGCANVAS_ATTRIBUTE_FONT] = make_json_paint(fontPaint, urlDataManager);
   2550         run[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_point(iter.offset());
   2551         runs.append(run);
   2552         iter.next();
   2553     }
   2554     result[SKDEBUGCANVAS_ATTRIBUTE_RUNS] = runs;
   2555     result[SKDEBUGCANVAS_ATTRIBUTE_X] = Json::Value(fXPos);
   2556     result[SKDEBUGCANVAS_ATTRIBUTE_Y] = Json::Value(fYPos);
   2557     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2558     return result;
   2559 }
   2560 
   2561 SkDrawTextBlobCommand* SkDrawTextBlobCommand::fromJSON(Json::Value& command,
   2562                                                        UrlDataManager& urlDataManager) {
   2563     SkTextBlobBuilder builder;
   2564     Json::Value runs = command[SKDEBUGCANVAS_ATTRIBUTE_RUNS];
   2565     for (Json::ArrayIndex i = 0 ; i < runs.size(); i++) {
   2566         Json::Value run = runs[i];
   2567         SkPaint font;
   2568         font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
   2569         extract_json_paint(run[SKDEBUGCANVAS_ATTRIBUTE_FONT], urlDataManager, &font);
   2570         Json::Value glyphs = run[SKDEBUGCANVAS_ATTRIBUTE_GLYPHS];
   2571         int count = glyphs.size();
   2572         Json::Value coords = run[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
   2573         SkScalar x = coords[0].asFloat();
   2574         SkScalar y = coords[1].asFloat();
   2575         if (run.isMember(SKDEBUGCANVAS_ATTRIBUTE_POSITIONS)) {
   2576             Json::Value positions = run[SKDEBUGCANVAS_ATTRIBUTE_POSITIONS];
   2577             if (positions.size() > 0 && positions[0].isNumeric()) {
   2578                 SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPosH(font, count, y);
   2579                 for (int j = 0; j < count; j++) {
   2580                     buffer.glyphs[j] = glyphs[j].asUInt();
   2581                     buffer.pos[j] = positions[j].asFloat();
   2582                 }
   2583             }
   2584             else {
   2585                 SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPos(font, count);
   2586                 for (int j = 0; j < count; j++) {
   2587                     buffer.glyphs[j] = glyphs[j].asUInt();
   2588                     buffer.pos[j * 2] = positions[j][0].asFloat();
   2589                     buffer.pos[j * 2 + 1] = positions[j][1].asFloat();
   2590                 }
   2591             }
   2592         }
   2593         else {
   2594             SkTextBlobBuilder::RunBuffer buffer = builder.allocRun(font, count, x, y);
   2595             for (int j = 0; j < count; j++) {
   2596                 buffer.glyphs[j] = glyphs[j].asUInt();
   2597             }
   2598         }
   2599     }
   2600     SkScalar x = command[SKDEBUGCANVAS_ATTRIBUTE_X].asFloat();
   2601     SkScalar y = command[SKDEBUGCANVAS_ATTRIBUTE_Y].asFloat();
   2602     SkPaint paint;
   2603     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2604     return new SkDrawTextBlobCommand(builder.build(), x, y, paint);
   2605 }
   2606 
   2607 SkDrawPatchCommand::SkDrawPatchCommand(const SkPoint cubics[12], const SkColor colors[4],
   2608                                        const SkPoint texCoords[4], SkXfermode* xfermode,
   2609                                        const SkPaint& paint)
   2610     : INHERITED(kDrawPatch_OpType) {
   2611     memcpy(fCubics, cubics, sizeof(fCubics));
   2612     if (colors != nullptr) {
   2613         memcpy(fColors, colors, sizeof(fColors));
   2614         fColorsPtr = fColors;
   2615     } else {
   2616         fColorsPtr = nullptr;
   2617     }
   2618     if (texCoords != nullptr) {
   2619         memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
   2620         fTexCoordsPtr = fTexCoords;
   2621     } else {
   2622         fTexCoordsPtr = nullptr;
   2623     }
   2624     if (xfermode != nullptr) {
   2625         fXfermode.reset(SkRef(xfermode));
   2626     }
   2627     fPaint = paint;
   2628 
   2629     fInfo.push(SkObjectParser::PaintToString(paint));
   2630 }
   2631 
   2632 void SkDrawPatchCommand::execute(SkCanvas* canvas) const {
   2633     canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fXfermode, fPaint);
   2634 }
   2635 
   2636 Json::Value SkDrawPatchCommand::toJSON(UrlDataManager& urlDataManager) const {
   2637     Json::Value result = INHERITED::toJSON(urlDataManager);
   2638     Json::Value cubics = Json::Value(Json::arrayValue);
   2639     for (int i = 0; i < 12; i++) {
   2640         cubics.append(make_json_point(fCubics[i]));
   2641     }
   2642     result[SKDEBUGCANVAS_ATTRIBUTE_CUBICS] = cubics;
   2643     if (fColorsPtr != nullptr) {
   2644         Json::Value colors = Json::Value(Json::arrayValue);
   2645         for (int i = 0; i < 4; i++) {
   2646             colors.append(make_json_color(fColorsPtr[i]));
   2647         }
   2648         result[SKDEBUGCANVAS_ATTRIBUTE_COLORS] = colors;
   2649     }
   2650     if (fTexCoordsPtr != nullptr) {
   2651         Json::Value texCoords = Json::Value(Json::arrayValue);
   2652         for (int i = 0; i < 4; i++) {
   2653             texCoords.append(make_json_point(fTexCoords[i]));
   2654         }
   2655         result[SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS] = texCoords;
   2656     }
   2657     if (fXfermode.get() != nullptr) {
   2658         Json::Value jsonXfermode;
   2659         flatten(fXfermode, &jsonXfermode, urlDataManager);
   2660         result[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE] = jsonXfermode;
   2661     }
   2662     return result;
   2663 }
   2664 
   2665 SkDrawPatchCommand* SkDrawPatchCommand::fromJSON(Json::Value& command,
   2666                                                  UrlDataManager& urlDataManager) {
   2667     Json::Value jsonCubics = command[SKDEBUGCANVAS_ATTRIBUTE_CUBICS];
   2668     SkPoint cubics[12];
   2669     for (int i = 0; i < 12; i++) {
   2670         cubics[i] = get_json_point(jsonCubics[i]);
   2671     }
   2672     SkColor* colorsPtr;
   2673     SkColor colors[4];
   2674     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLORS)) {
   2675         Json::Value jsonColors = command[SKDEBUGCANVAS_ATTRIBUTE_COLORS];
   2676         for (int i = 0; i < 4; i++) {
   2677             colors[i] = get_json_color(jsonColors[i]);
   2678         }
   2679         colorsPtr = colors;
   2680     }
   2681     else {
   2682         colorsPtr = nullptr;
   2683     }
   2684     SkPoint* texCoordsPtr;
   2685     SkPoint texCoords[4];
   2686     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS)) {
   2687         Json::Value jsonTexCoords = command[SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS];
   2688         for (int i = 0; i < 4; i++) {
   2689             texCoords[i] = get_json_point(jsonTexCoords[i]);
   2690         }
   2691         texCoordsPtr = texCoords;
   2692     }
   2693     else {
   2694         texCoordsPtr = nullptr;
   2695     }
   2696     SkAutoTUnref<SkXfermode> xfermode;
   2697     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_XFERMODE)) {
   2698         Json::Value jsonXfermode = command[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE];
   2699         xfermode.reset((SkXfermode*) load_flattenable(jsonXfermode, urlDataManager));
   2700     }
   2701     SkPaint paint;
   2702     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2703     return new SkDrawPatchCommand(cubics, colorsPtr, texCoordsPtr, xfermode, paint);
   2704 }
   2705 
   2706 SkDrawRectCommand::SkDrawRectCommand(const SkRect& rect, const SkPaint& paint)
   2707     : INHERITED(kDrawRect_OpType) {
   2708     fRect = rect;
   2709     fPaint = paint;
   2710 
   2711     fInfo.push(SkObjectParser::RectToString(rect));
   2712     fInfo.push(SkObjectParser::PaintToString(paint));
   2713 }
   2714 
   2715 void SkDrawRectCommand::execute(SkCanvas* canvas) const {
   2716     canvas->drawRect(fRect, fPaint);
   2717 }
   2718 
   2719 Json::Value SkDrawRectCommand::toJSON(UrlDataManager& urlDataManager) const {
   2720     Json::Value result = INHERITED::toJSON(urlDataManager);
   2721     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rect(fRect);
   2722     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2723     return result;
   2724 }
   2725 
   2726 SkDrawRectCommand* SkDrawRectCommand::fromJSON(Json::Value& command,
   2727                                                UrlDataManager& urlDataManager) {
   2728     SkRect coords;
   2729     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
   2730     SkPaint paint;
   2731     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2732     return new SkDrawRectCommand(coords, paint);
   2733 }
   2734 
   2735 SkDrawRRectCommand::SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
   2736     : INHERITED(kDrawRRect_OpType) {
   2737     fRRect = rrect;
   2738     fPaint = paint;
   2739 
   2740     fInfo.push(SkObjectParser::RRectToString(rrect));
   2741     fInfo.push(SkObjectParser::PaintToString(paint));
   2742 }
   2743 
   2744 void SkDrawRRectCommand::execute(SkCanvas* canvas) const {
   2745     canvas->drawRRect(fRRect, fPaint);
   2746 }
   2747 
   2748 bool SkDrawRRectCommand::render(SkCanvas* canvas) const {
   2749     render_rrect(canvas, fRRect);
   2750     return true;
   2751 }
   2752 
   2753 Json::Value SkDrawRRectCommand::toJSON(UrlDataManager& urlDataManager) const {
   2754     Json::Value result = INHERITED::toJSON(urlDataManager);
   2755     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rrect(fRRect);
   2756     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2757     return result;
   2758 }
   2759 
   2760 SkDrawRRectCommand* SkDrawRRectCommand::fromJSON(Json::Value& command,
   2761                                                  UrlDataManager& urlDataManager) {
   2762     SkRRect coords;
   2763     extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
   2764     SkPaint paint;
   2765     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2766     return new SkDrawRRectCommand(coords, paint);
   2767 }
   2768 
   2769 SkDrawDRRectCommand::SkDrawDRRectCommand(const SkRRect& outer,
   2770                                          const SkRRect& inner,
   2771                                          const SkPaint& paint)
   2772     : INHERITED(kDrawDRRect_OpType) {
   2773     fOuter = outer;
   2774     fInner = inner;
   2775     fPaint = paint;
   2776 
   2777     fInfo.push(SkObjectParser::RRectToString(outer));
   2778     fInfo.push(SkObjectParser::RRectToString(inner));
   2779     fInfo.push(SkObjectParser::PaintToString(paint));
   2780 }
   2781 
   2782 void SkDrawDRRectCommand::execute(SkCanvas* canvas) const {
   2783     canvas->drawDRRect(fOuter, fInner, fPaint);
   2784 }
   2785 
   2786 bool SkDrawDRRectCommand::render(SkCanvas* canvas) const {
   2787     render_drrect(canvas, fOuter, fInner);
   2788     return true;
   2789 }
   2790 
   2791 Json::Value SkDrawDRRectCommand::toJSON(UrlDataManager& urlDataManager) const {
   2792     Json::Value result = INHERITED::toJSON(urlDataManager);
   2793     result[SKDEBUGCANVAS_ATTRIBUTE_OUTER] = make_json_rrect(fOuter);
   2794     result[SKDEBUGCANVAS_ATTRIBUTE_INNER] = make_json_rrect(fInner);
   2795     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2796     return result;
   2797 }
   2798 
   2799 SkDrawDRRectCommand* SkDrawDRRectCommand::fromJSON(Json::Value& command,
   2800                                                    UrlDataManager& urlDataManager) {
   2801     SkRRect outer;
   2802     extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_INNER], &outer);
   2803     SkRRect inner;
   2804     extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_INNER], &inner);
   2805     SkPaint paint;
   2806     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2807     return new SkDrawDRRectCommand(outer, inner, paint);
   2808 }
   2809 
   2810 SkDrawTextCommand::SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y,
   2811                                      const SkPaint& paint)
   2812     : INHERITED(kDrawText_OpType) {
   2813     fText = new char[byteLength];
   2814     memcpy(fText, text, byteLength);
   2815     fByteLength = byteLength;
   2816     fX = x;
   2817     fY = y;
   2818     fPaint = paint;
   2819 
   2820     fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
   2821     fInfo.push(SkObjectParser::ScalarToString(x, "SkScalar x: "));
   2822     fInfo.push(SkObjectParser::ScalarToString(y, "SkScalar y: "));
   2823     fInfo.push(SkObjectParser::PaintToString(paint));
   2824 }
   2825 
   2826 void SkDrawTextCommand::execute(SkCanvas* canvas) const {
   2827     canvas->drawText(fText, fByteLength, fX, fY, fPaint);
   2828 }
   2829 
   2830 Json::Value SkDrawTextCommand::toJSON(UrlDataManager& urlDataManager) const {
   2831     Json::Value result = INHERITED::toJSON(urlDataManager);
   2832     result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
   2833                                                        ((const char*) fText) + fByteLength);
   2834     Json::Value coords(Json::arrayValue);
   2835     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_point(fX, fY);
   2836     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2837     return result;
   2838 }
   2839 
   2840 SkDrawTextCommand* SkDrawTextCommand::fromJSON(Json::Value& command,
   2841                                                UrlDataManager& urlDataManager) {
   2842     const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
   2843     SkPaint paint;
   2844     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2845     Json::Value coords = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
   2846     return new SkDrawTextCommand(text, strlen(text), coords[0].asFloat(), coords[1].asFloat(),
   2847                                  paint);
   2848 }
   2849 
   2850 SkDrawTextOnPathCommand::SkDrawTextOnPathCommand(const void* text, size_t byteLength,
   2851                                                  const SkPath& path, const SkMatrix* matrix,
   2852                                                  const SkPaint& paint)
   2853     : INHERITED(kDrawTextOnPath_OpType) {
   2854     fText = new char[byteLength];
   2855     memcpy(fText, text, byteLength);
   2856     fByteLength = byteLength;
   2857     fPath = path;
   2858     if (matrix) {
   2859         fMatrix = *matrix;
   2860     } else {
   2861         fMatrix.setIdentity();
   2862     }
   2863     fPaint = paint;
   2864 
   2865     fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
   2866     fInfo.push(SkObjectParser::PathToString(path));
   2867     if (matrix) {
   2868         fInfo.push(SkObjectParser::MatrixToString(*matrix));
   2869     }
   2870     fInfo.push(SkObjectParser::PaintToString(paint));
   2871 }
   2872 
   2873 void SkDrawTextOnPathCommand::execute(SkCanvas* canvas) const {
   2874     canvas->drawTextOnPath(fText, fByteLength, fPath,
   2875                            fMatrix.isIdentity() ? nullptr : &fMatrix,
   2876                            fPaint);
   2877 }
   2878 
   2879 Json::Value SkDrawTextOnPathCommand::toJSON(UrlDataManager& urlDataManager) const {
   2880     Json::Value result = INHERITED::toJSON(urlDataManager);
   2881     result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
   2882                                                        ((const char*) fText) + fByteLength);
   2883     Json::Value coords(Json::arrayValue);
   2884     result[SKDEBUGCANVAS_ATTRIBUTE_PATH] = make_json_path(fPath);
   2885     if (!fMatrix.isIdentity()) {
   2886         result[SKDEBUGCANVAS_ATTRIBUTE_MATRIX] = make_json_matrix(fMatrix);
   2887     }
   2888     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
   2889     return result;
   2890 }
   2891 
   2892 SkDrawTextOnPathCommand* SkDrawTextOnPathCommand::fromJSON(Json::Value& command,
   2893                                                            UrlDataManager& urlDataManager) {
   2894     const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
   2895     SkPaint paint;
   2896     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   2897     SkPath path;
   2898     extract_json_path(command[SKDEBUGCANVAS_ATTRIBUTE_PATH], &path);
   2899     SkMatrix* matrixPtr;
   2900     SkMatrix matrix;
   2901     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_MATRIX)) {
   2902         extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
   2903         matrixPtr = &matrix;
   2904     }
   2905     else {
   2906         matrixPtr = nullptr;
   2907     }
   2908     return new SkDrawTextOnPathCommand(text, strlen(text), path, matrixPtr, paint);
   2909 }
   2910 
   2911 SkDrawVerticesCommand::SkDrawVerticesCommand(SkCanvas::VertexMode vmode, int vertexCount,
   2912                                              const SkPoint vertices[], const SkPoint texs[],
   2913                                              const SkColor colors[], SkXfermode* xfermode,
   2914                                              const uint16_t indices[], int indexCount,
   2915                                              const SkPaint& paint)
   2916     : INHERITED(kDrawVertices_OpType) {
   2917     fVmode = vmode;
   2918 
   2919     fVertexCount = vertexCount;
   2920 
   2921     fVertices = new SkPoint[vertexCount];
   2922     memcpy(fVertices, vertices, vertexCount * sizeof(SkPoint));
   2923 
   2924     if (texs) {
   2925         fTexs = new SkPoint[vertexCount];
   2926         memcpy(fTexs, texs, vertexCount * sizeof(SkPoint));
   2927     } else {
   2928         fTexs = nullptr;
   2929     }
   2930 
   2931     if (colors) {
   2932         fColors = new SkColor[vertexCount];
   2933         memcpy(fColors, colors, vertexCount * sizeof(SkColor));
   2934     } else {
   2935         fColors = nullptr;
   2936     }
   2937 
   2938     fXfermode = xfermode;
   2939     if (fXfermode) {
   2940         fXfermode->ref();
   2941     }
   2942 
   2943     if (indexCount > 0) {
   2944         fIndices = new uint16_t[indexCount];
   2945         memcpy(fIndices, indices, indexCount * sizeof(uint16_t));
   2946     } else {
   2947         fIndices = nullptr;
   2948     }
   2949 
   2950     fIndexCount = indexCount;
   2951     fPaint = paint;
   2952 
   2953     // TODO(chudy)
   2954     fInfo.push(SkObjectParser::CustomTextToString("To be implemented."));
   2955     fInfo.push(SkObjectParser::PaintToString(paint));
   2956 }
   2957 
   2958 SkDrawVerticesCommand::~SkDrawVerticesCommand() {
   2959     delete [] fVertices;
   2960     delete [] fTexs;
   2961     delete [] fColors;
   2962     SkSafeUnref(fXfermode);
   2963     delete [] fIndices;
   2964 }
   2965 
   2966 void SkDrawVerticesCommand::execute(SkCanvas* canvas) const {
   2967     canvas->drawVertices(fVmode, fVertexCount, fVertices,
   2968                          fTexs, fColors, fXfermode, fIndices,
   2969                          fIndexCount, fPaint);
   2970 }
   2971 
   2972 SkRestoreCommand::SkRestoreCommand()
   2973     : INHERITED(kRestore_OpType) {
   2974     fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
   2975 }
   2976 
   2977 void SkRestoreCommand::execute(SkCanvas* canvas) const {
   2978     canvas->restore();
   2979 }
   2980 
   2981 SkRestoreCommand* SkRestoreCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
   2982     return new SkRestoreCommand();
   2983 }
   2984 
   2985 SkSaveCommand::SkSaveCommand()
   2986     : INHERITED(kSave_OpType) {
   2987 }
   2988 
   2989 void SkSaveCommand::execute(SkCanvas* canvas) const {
   2990     canvas->save();
   2991 }
   2992 
   2993 SkSaveCommand* SkSaveCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
   2994     return new SkSaveCommand();
   2995 }
   2996 
   2997 SkSaveLayerCommand::SkSaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
   2998     : INHERITED(kSaveLayer_OpType) {
   2999     if (rec.fBounds) {
   3000         fBounds = *rec.fBounds;
   3001     } else {
   3002         fBounds.setEmpty();
   3003     }
   3004 
   3005     if (rec.fPaint) {
   3006         fPaint = *rec.fPaint;
   3007         fPaintPtr = &fPaint;
   3008     } else {
   3009         fPaintPtr = nullptr;
   3010     }
   3011     fSaveLayerFlags = rec.fSaveLayerFlags;
   3012 
   3013     if (rec.fBackdrop) {
   3014         fBackdrop = rec.fBackdrop;
   3015         fBackdrop->ref();
   3016     } else {
   3017         fBackdrop = nullptr;
   3018     }
   3019 
   3020     if (rec.fBounds) {
   3021         fInfo.push(SkObjectParser::RectToString(*rec.fBounds, "Bounds: "));
   3022     }
   3023     if (rec.fPaint) {
   3024         fInfo.push(SkObjectParser::PaintToString(*rec.fPaint));
   3025     }
   3026     fInfo.push(SkObjectParser::SaveLayerFlagsToString(fSaveLayerFlags));
   3027 }
   3028 
   3029 SkSaveLayerCommand::~SkSaveLayerCommand() {
   3030     if (fBackdrop != nullptr) {
   3031         fBackdrop->unref();
   3032     }
   3033 }
   3034 
   3035 void SkSaveLayerCommand::execute(SkCanvas* canvas) const {
   3036     canvas->saveLayer(SkCanvas::SaveLayerRec(fBounds.isEmpty() ? nullptr : &fBounds,
   3037                                              fPaintPtr,
   3038                                              fSaveLayerFlags));
   3039 }
   3040 
   3041 void SkSaveLayerCommand::vizExecute(SkCanvas* canvas) const {
   3042     canvas->save();
   3043 }
   3044 
   3045 Json::Value SkSaveLayerCommand::toJSON(UrlDataManager& urlDataManager) const {
   3046     Json::Value result = INHERITED::toJSON(urlDataManager);
   3047     if (!fBounds.isEmpty()) {
   3048         result[SKDEBUGCANVAS_ATTRIBUTE_BOUNDS] = make_json_rect(fBounds);
   3049     }
   3050     if (fPaintPtr != nullptr) {
   3051         result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaintPtr,
   3052                                                                 urlDataManager);
   3053     }
   3054     if (fBackdrop != nullptr) {
   3055         Json::Value jsonBackdrop;
   3056         flatten(fBackdrop, &jsonBackdrop, urlDataManager);
   3057         result[SKDEBUGCANVAS_ATTRIBUTE_BACKDROP] = jsonBackdrop;
   3058     }
   3059     if (fSaveLayerFlags != 0) {
   3060         SkDebugf("unsupported: saveLayer flags\n");
   3061         SkASSERT(false);
   3062     }
   3063     return result;
   3064 }
   3065 
   3066 SkSaveLayerCommand* SkSaveLayerCommand::fromJSON(Json::Value& command,
   3067                                                  UrlDataManager& urlDataManager) {
   3068     SkCanvas::SaveLayerRec rec;
   3069     SkRect bounds;
   3070     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_BOUNDS)) {
   3071         extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_BOUNDS], &bounds);
   3072         rec.fBounds = &bounds;
   3073     }
   3074     SkPaint paint;
   3075     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
   3076         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
   3077         rec.fPaint = &paint;
   3078     }
   3079     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_BACKDROP)) {
   3080         Json::Value backdrop = command[SKDEBUGCANVAS_ATTRIBUTE_BACKDROP];
   3081         rec.fBackdrop = (SkImageFilter*) load_flattenable(backdrop, urlDataManager);
   3082     }
   3083     SkSaveLayerCommand* result = new SkSaveLayerCommand(rec);
   3084     if (rec.fBackdrop != nullptr) {
   3085         rec.fBackdrop->unref();
   3086     }
   3087     return result;
   3088 }
   3089 
   3090 SkSetMatrixCommand::SkSetMatrixCommand(const SkMatrix& matrix)
   3091     : INHERITED(kSetMatrix_OpType) {
   3092     fUserMatrix.reset();
   3093     fMatrix = matrix;
   3094     fInfo.push(SkObjectParser::MatrixToString(matrix));
   3095 }
   3096 
   3097 void SkSetMatrixCommand::setUserMatrix(const SkMatrix& userMatrix) {
   3098     fUserMatrix = userMatrix;
   3099 }
   3100 
   3101 void SkSetMatrixCommand::execute(SkCanvas* canvas) const {
   3102     SkMatrix temp = SkMatrix::Concat(fUserMatrix, fMatrix);
   3103     canvas->setMatrix(temp);
   3104 }
   3105 
   3106 Json::Value SkSetMatrixCommand::toJSON(UrlDataManager& urlDataManager) const {
   3107     Json::Value result = INHERITED::toJSON(urlDataManager);
   3108     result[SKDEBUGCANVAS_ATTRIBUTE_MATRIX] = make_json_matrix(fMatrix);
   3109     return result;
   3110 }
   3111 
   3112 SkSetMatrixCommand* SkSetMatrixCommand::fromJSON(Json::Value& command,
   3113                                                  UrlDataManager& urlDataManager) {
   3114     SkMatrix matrix;
   3115     extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
   3116     return new SkSetMatrixCommand(matrix);
   3117 }
   3118