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