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