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