• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "tools/debugger/DrawCommand.h"
9 
10 #include <algorithm>
11 #include "include/core/SkColorFilter.h"
12 #include "include/core/SkDrawable.h"
13 #include "include/core/SkImageFilter.h"
14 #include "include/core/SkPathEffect.h"
15 #include "include/core/SkPicture.h"
16 #include "include/core/SkTypeface.h"
17 #include "include/effects/SkDashPathEffect.h"
18 #include "include/encode/SkPngEncoder.h"
19 #include "include/private/SkShadowFlags.h"
20 #include "include/private/SkTHash.h"
21 #include "src/core/SkAutoMalloc.h"
22 #include "src/core/SkCanvasPriv.h"
23 #include "src/core/SkClipOpPriv.h"
24 #include "src/core/SkLatticeIter.h"
25 #include "src/core/SkMaskFilterBase.h"
26 #include "src/core/SkPaintDefaults.h"
27 #include "src/core/SkReadBuffer.h"
28 #include "src/core/SkRectPriv.h"
29 #include "src/core/SkTextBlobPriv.h"
30 #include "src/core/SkWriteBuffer.h"
31 #include "tools/debugger/DebugLayerManager.h"
32 #include "tools/debugger/JsonWriteBuffer.h"
33 
34 #define DEBUGCANVAS_ATTRIBUTE_COMMAND "command"
35 #define DEBUGCANVAS_ATTRIBUTE_VISIBLE "visible"
36 #define DEBUGCANVAS_ATTRIBUTE_MATRIX "matrix"
37 #define DEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS "drawDepthTranslation"
38 #define DEBUGCANVAS_ATTRIBUTE_COORDS "coords"
39 #define DEBUGCANVAS_ATTRIBUTE_EDGING "edging"
40 #define DEBUGCANVAS_ATTRIBUTE_HINTING "hinting"
41 #define DEBUGCANVAS_ATTRIBUTE_BOUNDS "bounds"
42 #define DEBUGCANVAS_ATTRIBUTE_PAINT "paint"
43 #define DEBUGCANVAS_ATTRIBUTE_OUTER "outer"
44 #define DEBUGCANVAS_ATTRIBUTE_INNER "inner"
45 #define DEBUGCANVAS_ATTRIBUTE_MODE "mode"
46 #define DEBUGCANVAS_ATTRIBUTE_POINTS "points"
47 #define DEBUGCANVAS_ATTRIBUTE_PATH "path"
48 #define DEBUGCANVAS_ATTRIBUTE_TEXT "text"
49 #define DEBUGCANVAS_ATTRIBUTE_COLOR "color"
50 #define DEBUGCANVAS_ATTRIBUTE_ALPHA "alpha"
51 #define DEBUGCANVAS_ATTRIBUTE_BLENDMODE "blendMode"
52 #define DEBUGCANVAS_ATTRIBUTE_STYLE "style"
53 #define DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH "strokeWidth"
54 #define DEBUGCANVAS_ATTRIBUTE_STROKEMITER "strokeMiter"
55 #define DEBUGCANVAS_ATTRIBUTE_STROKEJOIN "strokeJoin"
56 #define DEBUGCANVAS_ATTRIBUTE_CAP "cap"
57 #define DEBUGCANVAS_ATTRIBUTE_ANTIALIAS "antiAlias"
58 #define DEBUGCANVAS_ATTRIBUTE_DITHER "dither"
59 #define DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT "fakeBoldText"
60 #define DEBUGCANVAS_ATTRIBUTE_LINEARTEXT "linearText"
61 #define DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT "subpixelText"
62 #define DEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT "devKernText"
63 #define DEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT "lcdRenderText"
64 #define DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT "embeddedBitmapText"
65 #define DEBUGCANVAS_ATTRIBUTE_AUTOHINTING "forceAutoHinting"
66 #define DEBUGCANVAS_ATTRIBUTE_REGION "region"
67 #define DEBUGCANVAS_ATTRIBUTE_REGIONOP "op"
68 #define DEBUGCANVAS_ATTRIBUTE_EDGESTYLE "edgeStyle"
69 #define DEBUGCANVAS_ATTRIBUTE_DEVICEREGION "deviceRegion"
70 #define DEBUGCANVAS_ATTRIBUTE_BLUR "blur"
71 #define DEBUGCANVAS_ATTRIBUTE_SIGMA "sigma"
72 #define DEBUGCANVAS_ATTRIBUTE_QUALITY "quality"
73 #define DEBUGCANVAS_ATTRIBUTE_TEXTSIZE "textSize"
74 #define DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX "textScaleX"
75 #define DEBUGCANVAS_ATTRIBUTE_TEXTSKEWX "textSkewX"
76 #define DEBUGCANVAS_ATTRIBUTE_DASHING "dashing"
77 #define DEBUGCANVAS_ATTRIBUTE_INTERVALS "intervals"
78 #define DEBUGCANVAS_ATTRIBUTE_PHASE "phase"
79 #define DEBUGCANVAS_ATTRIBUTE_FILLTYPE "fillType"
80 #define DEBUGCANVAS_ATTRIBUTE_VERBS "verbs"
81 #define DEBUGCANVAS_ATTRIBUTE_NAME "name"
82 #define DEBUGCANVAS_ATTRIBUTE_DATA "data"
83 #define DEBUGCANVAS_ATTRIBUTE_VALUES "values"
84 #define DEBUGCANVAS_ATTRIBUTE_SHADER "shader"
85 #define DEBUGCANVAS_ATTRIBUTE_PATHEFFECT "pathEffect"
86 #define DEBUGCANVAS_ATTRIBUTE_MASKFILTER "maskFilter"
87 #define DEBUGCANVAS_ATTRIBUTE_XFERMODE "xfermode"
88 #define DEBUGCANVAS_ATTRIBUTE_BACKDROP "backdrop"
89 #define DEBUGCANVAS_ATTRIBUTE_COLORFILTER "colorfilter"
90 #define DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER "imagefilter"
91 #define DEBUGCANVAS_ATTRIBUTE_IMAGE "image"
92 #define DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX "imageIndex"
93 #define DEBUGCANVAS_ATTRIBUTE_BITMAP "bitmap"
94 #define DEBUGCANVAS_ATTRIBUTE_SRC "src"
95 #define DEBUGCANVAS_ATTRIBUTE_DST "dst"
96 #define DEBUGCANVAS_ATTRIBUTE_CENTER "center"
97 #define DEBUGCANVAS_ATTRIBUTE_STRICT "strict"
98 #define DEBUGCANVAS_ATTRIBUTE_DESCRIPTION "description"
99 #define DEBUGCANVAS_ATTRIBUTE_X "x"
100 #define DEBUGCANVAS_ATTRIBUTE_Y "y"
101 #define DEBUGCANVAS_ATTRIBUTE_RUNS "runs"
102 #define DEBUGCANVAS_ATTRIBUTE_POSITIONS "positions"
103 #define DEBUGCANVAS_ATTRIBUTE_GLYPHS "glyphs"
104 #define DEBUGCANVAS_ATTRIBUTE_FONT "font"
105 #define DEBUGCANVAS_ATTRIBUTE_TYPEFACE "typeface"
106 #define DEBUGCANVAS_ATTRIBUTE_CUBICS "cubics"
107 #define DEBUGCANVAS_ATTRIBUTE_COLORS "colors"
108 #define DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS "textureCoords"
109 #define DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY "filterQuality"
110 #define DEBUGCANVAS_ATTRIBUTE_STARTANGLE "startAngle"
111 #define DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE "sweepAngle"
112 #define DEBUGCANVAS_ATTRIBUTE_USECENTER "useCenter"
113 #define DEBUGCANVAS_ATTRIBUTE_SHORTDESC "shortDesc"
114 #define DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID "uniqueID"
115 #define DEBUGCANVAS_ATTRIBUTE_WIDTH "width"
116 #define DEBUGCANVAS_ATTRIBUTE_HEIGHT "height"
117 #define DEBUGCANVAS_ATTRIBUTE_ALPHA "alpha"
118 #define DEBUGCANVAS_ATTRIBUTE_LATTICE "lattice"
119 #define DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT "xCount"
120 #define DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT "yCount"
121 #define DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS "xDivs"
122 #define DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS "yDivs"
123 #define DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS "flags"
124 #define DEBUGCANVAS_ATTRIBUTE_ZPLANE "zPlane"
125 #define DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION "lightPositions"
126 #define DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR "ambientColor"
127 #define DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR "spotColor"
128 #define DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS "lightRadius"
129 #define DEBUGCANVAS_ATTRIBUTE_LAYERNODEID "layerNodeId"
130 
131 #define DEBUGCANVAS_VERB_MOVE "move"
132 #define DEBUGCANVAS_VERB_LINE "line"
133 #define DEBUGCANVAS_VERB_QUAD "quad"
134 #define DEBUGCANVAS_VERB_CUBIC "cubic"
135 #define DEBUGCANVAS_VERB_CONIC "conic"
136 #define DEBUGCANVAS_VERB_CLOSE "close"
137 
138 #define DEBUGCANVAS_STYLE_FILL "fill"
139 #define DEBUGCANVAS_STYLE_STROKE "stroke"
140 #define DEBUGCANVAS_STYLE_STROKEANDFILL "strokeAndFill"
141 
142 #define DEBUGCANVAS_POINTMODE_POINTS "points"
143 #define DEBUGCANVAS_POINTMODE_LINES "lines"
144 #define DEBUGCANVAS_POINTMODE_POLYGON "polygon"
145 
146 #define DEBUGCANVAS_REGIONOP_DIFFERENCE "difference"
147 #define DEBUGCANVAS_REGIONOP_INTERSECT "intersect"
148 #define DEBUGCANVAS_REGIONOP_UNION "union"
149 #define DEBUGCANVAS_REGIONOP_XOR "xor"
150 #define DEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE "reverseDifference"
151 #define DEBUGCANVAS_REGIONOP_REPLACE "replace"
152 
153 #define DEBUGCANVAS_BLURSTYLE_NORMAL "normal"
154 #define DEBUGCANVAS_BLURSTYLE_SOLID "solid"
155 #define DEBUGCANVAS_BLURSTYLE_OUTER "outer"
156 #define DEBUGCANVAS_BLURSTYLE_INNER "inner"
157 
158 #define DEBUGCANVAS_BLURQUALITY_LOW "low"
159 #define DEBUGCANVAS_BLURQUALITY_HIGH "high"
160 
161 #define DEBUGCANVAS_FILLTYPE_WINDING "winding"
162 #define DEBUGCANVAS_FILLTYPE_EVENODD "evenOdd"
163 #define DEBUGCANVAS_FILLTYPE_INVERSEWINDING "inverseWinding"
164 #define DEBUGCANVAS_FILLTYPE_INVERSEEVENODD "inverseEvenOdd"
165 
166 #define DEBUGCANVAS_CAP_BUTT "butt"
167 #define DEBUGCANVAS_CAP_ROUND "round"
168 #define DEBUGCANVAS_CAP_SQUARE "square"
169 
170 #define DEBUGCANVAS_MITER_JOIN "miter"
171 #define DEBUGCANVAS_ROUND_JOIN "round"
172 #define DEBUGCANVAS_BEVEL_JOIN "bevel"
173 
174 #define DEBUGCANVAS_COLORTYPE_ARGB4444 "ARGB4444"
175 #define DEBUGCANVAS_COLORTYPE_RGBA8888 "RGBA8888"
176 #define DEBUGCANVAS_COLORTYPE_BGRA8888 "BGRA8888"
177 #define DEBUGCANVAS_COLORTYPE_565 "565"
178 #define DEBUGCANVAS_COLORTYPE_GRAY8 "Gray8"
179 #define DEBUGCANVAS_COLORTYPE_INDEX8 "Index8"
180 #define DEBUGCANVAS_COLORTYPE_ALPHA8 "Alpha8"
181 
182 #define DEBUGCANVAS_ALPHATYPE_OPAQUE "opaque"
183 #define DEBUGCANVAS_ALPHATYPE_PREMUL "premul"
184 #define DEBUGCANVAS_ALPHATYPE_UNPREMUL "unpremul"
185 #define DEBUGCANVAS_ALPHATYPE_UNKNOWN "unknown"
186 
187 #define DEBUGCANVAS_FILTERQUALITY_NONE "none"
188 #define DEBUGCANVAS_FILTERQUALITY_LOW "low"
189 #define DEBUGCANVAS_FILTERQUALITY_MEDIUM "medium"
190 #define DEBUGCANVAS_FILTERQUALITY_HIGH "high"
191 
192 #define DEBUGCANVAS_HINTING_NONE "none"
193 #define DEBUGCANVAS_HINTING_SLIGHT "slight"
194 #define DEBUGCANVAS_HINTING_NORMAL "normal"
195 #define DEBUGCANVAS_HINTING_FULL "full"
196 
197 #define DEBUGCANVAS_EDGING_ALIAS "alias"
198 #define DEBUGCANVAS_EDGING_ANTIALIAS "antialias"
199 #define DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS "subpixelantialias"
200 
201 #define DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC "transparentOccluder"
202 #define DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY "geometricOnly"
203 
str_append(SkString * str,const SkRect & r)204 static SkString* str_append(SkString* str, const SkRect& r) {
205     str->appendf(" [%g %g %g %g]", r.left(), r.top(), r.right(), r.bottom());
206     return str;
207 }
208 
DrawCommand(OpType type)209 DrawCommand::DrawCommand(OpType type) : fOpType(type), fVisible(true) {}
210 
GetCommandString(OpType type)211 const char* DrawCommand::GetCommandString(OpType type) {
212     switch (type) {
213         case kBeginDrawPicture_OpType: return "BeginDrawPicture";
214         case kClear_OpType: return "DrawClear";
215         case kClipPath_OpType: return "ClipPath";
216         case kClipRegion_OpType: return "ClipRegion";
217         case kClipRect_OpType: return "ClipRect";
218         case kClipRRect_OpType: return "ClipRRect";
219         case kConcat_OpType: return "Concat";
220         case kDrawAnnotation_OpType: return "DrawAnnotation";
221         case kDrawBitmap_OpType: return "DrawBitmap";
222         case kDrawBitmapLattice_OpType: return "DrawBitmapLattice";
223         case kDrawBitmapNine_OpType: return "DrawBitmapNine";
224         case kDrawBitmapRect_OpType: return "DrawBitmapRect";
225         case kDrawDRRect_OpType: return "DrawDRRect";
226         case kDrawImage_OpType: return "DrawImage";
227         case kDrawImageLattice_OpType: return "DrawImageLattice";
228         case kDrawImageNine_OpType: return "DrawImageNine";
229         case kDrawImageRect_OpType: return "DrawImageRect";
230         case kDrawImageRectLayer_OpType: return "DrawImageRectLayer";
231         case kDrawOval_OpType: return "DrawOval";
232         case kDrawPaint_OpType: return "DrawPaint";
233         case kDrawPatch_OpType: return "DrawPatch";
234         case kDrawPath_OpType: return "DrawPath";
235         case kDrawArc_OpType: return "DrawArc";
236         case kDrawPoints_OpType: return "DrawPoints";
237         case kDrawRect_OpType: return "DrawRect";
238         case kDrawRRect_OpType: return "DrawRRect";
239         case kDrawRegion_OpType: return "DrawRegion";
240         case kDrawShadow_OpType: return "DrawShadow";
241         case kDrawTextBlob_OpType: return "DrawTextBlob";
242         case kDrawVertices_OpType: return "DrawVertices";
243         case kDrawAtlas_OpType: return "DrawAtlas";
244         case kDrawDrawable_OpType: return "DrawDrawable";
245         case kDrawEdgeAAQuad_OpType: return "DrawEdgeAAQuad";
246         case kDrawEdgeAAImageSet_OpType: return "DrawEdgeAAImageSet";
247         case kEndDrawPicture_OpType: return "EndDrawPicture";
248         case kRestore_OpType: return "Restore";
249         case kSave_OpType: return "Save";
250         case kSaveLayer_OpType: return "SaveLayer";
251         case kSetMatrix_OpType: return "SetMatrix";
252         default:
253             SkDebugf("OpType error 0x%08x\n", type);
254             SkASSERT(0);
255             break;
256     }
257     SkDEBUGFAIL("DrawType UNUSED\n");
258     return nullptr;
259 }
260 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const261 void DrawCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
262     writer.appendString(DEBUGCANVAS_ATTRIBUTE_COMMAND, this->GetCommandString(fOpType));
263     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_VISIBLE, this->isVisible());
264 }
265 
266 namespace {
267 
xlate_and_scale_to_bounds(SkCanvas * canvas,const SkRect & bounds)268 void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
269     const SkISize& size = canvas->getBaseLayerSize();
270 
271     static const SkScalar kInsetFrac = 0.9f;  // Leave a border around object
272 
273     canvas->translate(size.fWidth / 2.0f, size.fHeight / 2.0f);
274     if (bounds.width() > bounds.height()) {
275         canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.width()),
276                       SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.width()));
277     } else {
278         canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.height()),
279                       SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.height()));
280     }
281     canvas->translate(-bounds.centerX(), -bounds.centerY());
282 }
283 
render_path(SkCanvas * canvas,const SkPath & path)284 void render_path(SkCanvas* canvas, const SkPath& path) {
285     canvas->clear(0xFFFFFFFF);
286 
287     const SkRect& bounds = path.getBounds();
288     if (bounds.isEmpty()) {
289         return;
290     }
291 
292     SkAutoCanvasRestore acr(canvas, true);
293     xlate_and_scale_to_bounds(canvas, bounds);
294 
295     SkPaint p;
296     p.setColor(SK_ColorBLACK);
297     p.setStyle(SkPaint::kStroke_Style);
298 
299     canvas->drawPath(path, p);
300 }
301 
render_region(SkCanvas * canvas,const SkRegion & region)302 void render_region(SkCanvas* canvas, const SkRegion& region) {
303     canvas->clear(0xFFFFFFFF);
304 
305     const SkIRect& bounds = region.getBounds();
306     if (bounds.isEmpty()) {
307         return;
308     }
309 
310     SkAutoCanvasRestore acr(canvas, true);
311     xlate_and_scale_to_bounds(canvas, SkRect::Make(bounds));
312 
313     SkPaint p;
314     p.setColor(SK_ColorBLACK);
315     p.setStyle(SkPaint::kStroke_Style);
316 
317     canvas->drawRegion(region, p);
318 }
319 
render_bitmap(SkCanvas * canvas,const SkBitmap & input,const SkRect * srcRect=nullptr)320 void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = nullptr) {
321     const SkISize& size = canvas->getBaseLayerSize();
322 
323     SkScalar xScale = SkIntToScalar(size.fWidth - 2) / input.width();
324     SkScalar yScale = SkIntToScalar(size.fHeight - 2) / input.height();
325 
326     if (input.width() > input.height()) {
327         yScale *= input.height() / (float)input.width();
328     } else {
329         xScale *= input.width() / (float)input.height();
330     }
331 
332     SkRect dst = SkRect::MakeXYWH(
333             SK_Scalar1, SK_Scalar1, xScale * input.width(), yScale * input.height());
334 
335     static const int kNumBlocks = 8;
336 
337     canvas->clear(0xFFFFFFFF);
338     SkISize block = {canvas->imageInfo().width() / kNumBlocks,
339                      canvas->imageInfo().height() / kNumBlocks};
340     for (int y = 0; y < kNumBlocks; ++y) {
341         for (int x = 0; x < kNumBlocks; ++x) {
342             SkPaint paint;
343             paint.setColor((x + y) % 2 ? SK_ColorLTGRAY : SK_ColorDKGRAY);
344             SkRect r = SkRect::MakeXYWH(SkIntToScalar(x * block.width()),
345                                         SkIntToScalar(y * block.height()),
346                                         SkIntToScalar(block.width()),
347                                         SkIntToScalar(block.height()));
348             canvas->drawRect(r, paint);
349         }
350     }
351 
352     canvas->drawBitmapRect(input, dst, nullptr);
353 
354     if (srcRect) {
355         SkRect  r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
356                                     srcRect->fTop * yScale + SK_Scalar1,
357                                     srcRect->fRight * xScale + SK_Scalar1,
358                                     srcRect->fBottom * yScale + SK_Scalar1);
359         SkPaint p;
360         p.setColor(SK_ColorRED);
361         p.setStyle(SkPaint::kStroke_Style);
362 
363         canvas->drawRect(r, p);
364     }
365 }
366 
render_rrect(SkCanvas * canvas,const SkRRect & rrect)367 void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
368     canvas->clear(0xFFFFFFFF);
369     canvas->save();
370 
371     const SkRect& bounds = rrect.getBounds();
372 
373     xlate_and_scale_to_bounds(canvas, bounds);
374 
375     SkPaint p;
376     p.setColor(SK_ColorBLACK);
377     p.setStyle(SkPaint::kStroke_Style);
378 
379     canvas->drawRRect(rrect, p);
380     canvas->restore();
381 }
382 
render_drrect(SkCanvas * canvas,const SkRRect & outer,const SkRRect & inner)383 void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
384     canvas->clear(0xFFFFFFFF);
385     canvas->save();
386 
387     const SkRect& bounds = outer.getBounds();
388 
389     xlate_and_scale_to_bounds(canvas, bounds);
390 
391     SkPaint p;
392     p.setColor(SK_ColorBLACK);
393     p.setStyle(SkPaint::kStroke_Style);
394 
395     canvas->drawDRRect(outer, inner, p);
396     canvas->restore();
397 }
398 
render_shadow(SkCanvas * canvas,const SkPath & path,SkDrawShadowRec rec)399 void render_shadow(SkCanvas* canvas, const SkPath& path, SkDrawShadowRec rec) {
400     canvas->clear(0xFFFFFFFF);
401 
402     const SkRect& bounds = path.getBounds();
403     if (bounds.isEmpty()) {
404         return;
405     }
406 
407     SkAutoCanvasRestore acr(canvas, true);
408     xlate_and_scale_to_bounds(canvas, bounds);
409 
410     rec.fAmbientColor = SK_ColorBLACK;
411     rec.fSpotColor    = SK_ColorBLACK;
412     canvas->private_draw_shadow_rec(path, rec);
413 }
414 
415 static const char* const gBlendModeMap[] = {
416         "clear",      "src",        "dst",      "srcOver",    "dstOver",   "srcIn",     "dstIn",
417         "srcOut",     "dstOut",     "srcATop",  "dstATop",    "xor",       "plus",      "modulate",
418 
419         "screen",
420 
421         "overlay",    "darken",     "lighten",  "colorDodge", "colorBurn", "hardLight", "softLight",
422         "difference", "exclusion",  "multiply",
423 
424         "hue",        "saturation", "color",    "luminosity",
425 };
426 
427 static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLastMode) + 1,
428               "blendMode mismatch");
429 static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLuminosity) + 1,
430               "blendMode mismatch");
431 
apply_paint_blend_mode(const SkPaint & paint,SkJSONWriter & writer)432 void apply_paint_blend_mode(const SkPaint& paint, SkJSONWriter& writer) {
433     const auto mode = paint.getBlendMode();
434     if (mode != SkBlendMode::kSrcOver) {
435         SkASSERT(static_cast<size_t>(mode) < SK_ARRAY_COUNT(gBlendModeMap));
436         writer.appendString(DEBUGCANVAS_ATTRIBUTE_BLENDMODE,
437                             gBlendModeMap[static_cast<size_t>(mode)]);
438     }
439 }
440 
441 };  // namespace
442 
MakeJsonColor(SkJSONWriter & writer,const SkColor color)443 void DrawCommand::MakeJsonColor(SkJSONWriter& writer, const SkColor color) {
444     writer.beginArray(nullptr, false);
445     writer.appendS32(SkColorGetA(color));
446     writer.appendS32(SkColorGetR(color));
447     writer.appendS32(SkColorGetG(color));
448     writer.appendS32(SkColorGetB(color));
449     writer.endArray();
450 }
451 
MakeJsonColor4f(SkJSONWriter & writer,const SkColor4f & color)452 void DrawCommand::MakeJsonColor4f(SkJSONWriter& writer, const SkColor4f& color) {
453     writer.beginArray(nullptr, false);
454     writer.appendFloat(color.fA);
455     writer.appendFloat(color.fR);
456     writer.appendFloat(color.fG);
457     writer.appendFloat(color.fB);
458     writer.endArray();
459 }
460 
MakeJsonPoint(SkJSONWriter & writer,const SkPoint & point)461 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, const SkPoint& point) {
462     writer.beginArray(nullptr, false);
463     writer.appendFloat(point.x());
464     writer.appendFloat(point.y());
465     writer.endArray();
466 }
467 
MakeJsonPoint(SkJSONWriter & writer,SkScalar x,SkScalar y)468 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, SkScalar x, SkScalar y) {
469     writer.beginArray(nullptr, false);
470     writer.appendFloat(x);
471     writer.appendFloat(y);
472     writer.endArray();
473 }
474 
MakeJsonPoint3(SkJSONWriter & writer,const SkPoint3 & point)475 void DrawCommand::MakeJsonPoint3(SkJSONWriter& writer, const SkPoint3& point) {
476     writer.beginArray(nullptr, false);
477     writer.appendFloat(point.x());
478     writer.appendFloat(point.y());
479     writer.appendFloat(point.z());
480     writer.endArray();
481 }
482 
MakeJsonRect(SkJSONWriter & writer,const SkRect & rect)483 void DrawCommand::MakeJsonRect(SkJSONWriter& writer, const SkRect& rect) {
484     writer.beginArray(nullptr, false);
485     writer.appendFloat(rect.left());
486     writer.appendFloat(rect.top());
487     writer.appendFloat(rect.right());
488     writer.appendFloat(rect.bottom());
489     writer.endArray();
490 }
491 
MakeJsonIRect(SkJSONWriter & writer,const SkIRect & rect)492 void DrawCommand::MakeJsonIRect(SkJSONWriter& writer, const SkIRect& rect) {
493     writer.beginArray(nullptr, false);
494     writer.appendS32(rect.left());
495     writer.appendS32(rect.top());
496     writer.appendS32(rect.right());
497     writer.appendS32(rect.bottom());
498     writer.endArray();
499 }
500 
make_json_rrect(SkJSONWriter & writer,const SkRRect & rrect)501 static void make_json_rrect(SkJSONWriter& writer, const SkRRect& rrect) {
502     writer.beginArray(nullptr, false);
503     DrawCommand::MakeJsonRect(writer, rrect.rect());
504     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperLeft_Corner));
505     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperRight_Corner));
506     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerRight_Corner));
507     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerLeft_Corner));
508     writer.endArray();
509 }
510 
MakeJsonMatrix(SkJSONWriter & writer,const SkMatrix & matrix)511 void DrawCommand::MakeJsonMatrix(SkJSONWriter& writer, const SkMatrix& matrix) {
512     writer.beginArray();
513     for (int r = 0; r < 3; ++r) {
514         writer.beginArray(nullptr, false);
515         for (int c = 0; c < 3; ++c) {
516             writer.appendFloat(matrix[r * 3 + c]);
517         }
518         writer.endArray();
519     }
520     writer.endArray();
521 }
522 
MakeJsonPath(SkJSONWriter & writer,const SkPath & path)523 void DrawCommand::MakeJsonPath(SkJSONWriter& writer, const SkPath& path) {
524     writer.beginObject();
525     switch (path.getFillType()) {
526         case SkPathFillType::kWinding:
527             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_WINDING);
528             break;
529         case SkPathFillType::kEvenOdd:
530             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_EVENODD);
531             break;
532         case SkPathFillType::kInverseWinding:
533             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
534                                 DEBUGCANVAS_FILLTYPE_INVERSEWINDING);
535             break;
536         case SkPathFillType::kInverseEvenOdd:
537             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
538                                 DEBUGCANVAS_FILLTYPE_INVERSEEVENODD);
539             break;
540     }
541     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_VERBS);
542     SkPath::Iter iter(path, false);
543     SkPoint      pts[4];
544     SkPath::Verb verb;
545     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
546         if (verb == SkPath::kClose_Verb) {
547             writer.appendString(DEBUGCANVAS_VERB_CLOSE);
548             continue;
549         }
550         writer.beginObject();  // verb
551         switch (verb) {
552             case SkPath::kLine_Verb: {
553                 writer.appendName(DEBUGCANVAS_VERB_LINE);
554                 MakeJsonPoint(writer, pts[1]);
555                 break;
556             }
557             case SkPath::kQuad_Verb: {
558                 writer.beginArray(DEBUGCANVAS_VERB_QUAD);
559                 MakeJsonPoint(writer, pts[1]);
560                 MakeJsonPoint(writer, pts[2]);
561                 writer.endArray();  // quad coords
562                 break;
563             }
564             case SkPath::kCubic_Verb: {
565                 writer.beginArray(DEBUGCANVAS_VERB_CUBIC);
566                 MakeJsonPoint(writer, pts[1]);
567                 MakeJsonPoint(writer, pts[2]);
568                 MakeJsonPoint(writer, pts[3]);
569                 writer.endArray();  // cubic coords
570                 break;
571             }
572             case SkPath::kConic_Verb: {
573                 writer.beginArray(DEBUGCANVAS_VERB_CONIC);
574                 MakeJsonPoint(writer, pts[1]);
575                 MakeJsonPoint(writer, pts[2]);
576                 writer.appendFloat(iter.conicWeight());
577                 writer.endArray();  // conic coords
578                 break;
579             }
580             case SkPath::kMove_Verb: {
581                 writer.appendName(DEBUGCANVAS_VERB_MOVE);
582                 MakeJsonPoint(writer, pts[0]);
583                 break;
584             }
585             case SkPath::kClose_Verb:
586             case SkPath::kDone_Verb:
587                 // Unreachable
588                 break;
589         }
590         writer.endObject();  // verb
591     }
592     writer.endArray();   // verbs
593     writer.endObject();  // path
594 }
595 
MakeJsonRegion(SkJSONWriter & writer,const SkRegion & region)596 void DrawCommand::MakeJsonRegion(SkJSONWriter& writer, const SkRegion& region) {
597     // TODO: Actually serialize the rectangles, rather than just devolving to path
598     SkPath path;
599     region.getBoundaryPath(&path);
600     MakeJsonPath(writer, path);
601 }
602 
regionop_name(SkClipOp op)603 static const char* regionop_name(SkClipOp op) {
604     switch (op) {
605         case kDifference_SkClipOp: return DEBUGCANVAS_REGIONOP_DIFFERENCE;
606         case kIntersect_SkClipOp: return DEBUGCANVAS_REGIONOP_INTERSECT;
607         case kUnion_SkClipOp: return DEBUGCANVAS_REGIONOP_UNION;
608         case kXOR_SkClipOp: return DEBUGCANVAS_REGIONOP_XOR;
609         case kReverseDifference_SkClipOp: return DEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE;
610         case kReplace_SkClipOp: return DEBUGCANVAS_REGIONOP_REPLACE;
611         default: SkASSERT(false); return "<invalid region op>";
612     }
613 }
614 
pointmode_name(SkCanvas::PointMode mode)615 static const char* pointmode_name(SkCanvas::PointMode mode) {
616     switch (mode) {
617         case SkCanvas::kPoints_PointMode: return DEBUGCANVAS_POINTMODE_POINTS;
618         case SkCanvas::kLines_PointMode: return DEBUGCANVAS_POINTMODE_LINES;
619         case SkCanvas::kPolygon_PointMode: return DEBUGCANVAS_POINTMODE_POLYGON;
620         default: SkASSERT(false); return "<invalid point mode>";
621     }
622 }
623 
store_scalar(SkJSONWriter & writer,const char * key,SkScalar value,SkScalar defaultValue)624 static void store_scalar(SkJSONWriter& writer,
625                          const char*   key,
626                          SkScalar      value,
627                          SkScalar      defaultValue) {
628     if (value != defaultValue) {
629         writer.appendFloat(key, value);
630     }
631 }
632 
store_bool(SkJSONWriter & writer,const char * key,bool value,bool defaultValue)633 static void store_bool(SkJSONWriter& writer, const char* key, bool value, bool defaultValue) {
634     if (value != defaultValue) {
635         writer.appendBool(key, value);
636     }
637 }
638 
encode_data(const void * bytes,size_t count,const char * contentType,UrlDataManager & urlDataManager)639 static SkString encode_data(const void*     bytes,
640                             size_t          count,
641                             const char*     contentType,
642                             UrlDataManager& urlDataManager) {
643     sk_sp<SkData> data(SkData::MakeWithCopy(bytes, count));
644     return urlDataManager.addData(data.get(), contentType);
645 }
646 
flatten(const SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)647 void DrawCommand::flatten(const SkFlattenable* flattenable,
648                           SkJSONWriter&        writer,
649                           UrlDataManager&      urlDataManager) {
650     SkBinaryWriteBuffer buffer;
651     flattenable->flatten(buffer);
652     void* data = sk_malloc_throw(buffer.bytesWritten());
653     buffer.writeToMemory(data);
654     SkString url =
655             encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
656     writer.appendString(DEBUGCANVAS_ATTRIBUTE_NAME, flattenable->getTypeName());
657     writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
658 
659     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_VALUES);
660     JsonWriteBuffer jsonBuffer(&writer, &urlDataManager);
661     flattenable->flatten(jsonBuffer);
662     writer.endObject();  // values
663 
664     sk_free(data);
665 }
666 
WritePNG(SkBitmap bitmap,SkWStream & out)667 void DrawCommand::WritePNG(SkBitmap bitmap, SkWStream& out) {
668     SkPixmap pm;
669     SkAssertResult(bitmap.peekPixels(&pm));
670 
671     SkPngEncoder::Options options;
672     options.fZLibLevel   = 1;
673     options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
674     SkPngEncoder::Encode(&out, pm, options);
675 }
676 
flatten(const SkImage & image,SkJSONWriter & writer,UrlDataManager & urlDataManager)677 bool DrawCommand::flatten(const SkImage&  image,
678                           SkJSONWriter&   writer,
679                           UrlDataManager& urlDataManager) {
680     size_t       rowBytes = 4 * image.width();
681     SkAutoMalloc buffer(rowBytes * image.height());
682     SkImageInfo  dstInfo =
683             SkImageInfo::Make(image.dimensions(), kN32_SkColorType, kPremul_SkAlphaType);
684     if (!image.readPixels(dstInfo, buffer.get(), rowBytes, 0, 0)) {
685         SkDebugf("readPixels failed\n");
686         return false;
687     }
688 
689     SkBitmap bm;
690     bm.installPixels(dstInfo, buffer.get(), rowBytes);
691 
692     SkDynamicMemoryWStream out;
693     DrawCommand::WritePNG(bm, out);
694     sk_sp<SkData> encoded = out.detachAsData();
695     SkString      url = encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager);
696     writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
697     return true;
698 }
699 
color_type_name(SkColorType colorType)700 static const char* color_type_name(SkColorType colorType) {
701     switch (colorType) {
702         case kARGB_4444_SkColorType: return DEBUGCANVAS_COLORTYPE_ARGB4444;
703         case kRGBA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_RGBA8888;
704         case kBGRA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_BGRA8888;
705         case kRGB_565_SkColorType: return DEBUGCANVAS_COLORTYPE_565;
706         case kGray_8_SkColorType: return DEBUGCANVAS_COLORTYPE_GRAY8;
707         case kAlpha_8_SkColorType: return DEBUGCANVAS_COLORTYPE_ALPHA8;
708         default: SkASSERT(false); return DEBUGCANVAS_COLORTYPE_RGBA8888;
709     }
710 }
711 
alpha_type_name(SkAlphaType alphaType)712 static const char* alpha_type_name(SkAlphaType alphaType) {
713     switch (alphaType) {
714         case kOpaque_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_OPAQUE;
715         case kPremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_PREMUL;
716         case kUnpremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_UNPREMUL;
717         default: SkASSERT(false); return DEBUGCANVAS_ALPHATYPE_OPAQUE;
718     }
719 }
720 
flatten(const SkBitmap & bitmap,SkJSONWriter & writer,UrlDataManager & urlDataManager)721 bool DrawCommand::flatten(const SkBitmap& bitmap,
722                           SkJSONWriter&   writer,
723                           UrlDataManager& urlDataManager) {
724     sk_sp<SkImage> image(SkImage::MakeFromBitmap(bitmap));
725     writer.appendString(DEBUGCANVAS_ATTRIBUTE_COLOR, color_type_name(bitmap.colorType()));
726     writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, alpha_type_name(bitmap.alphaType()));
727     bool success = flatten(*image, writer, urlDataManager);
728     return success;
729 }
730 
apply_font_hinting(const SkFont & font,SkJSONWriter & writer)731 static void apply_font_hinting(const SkFont& font, SkJSONWriter& writer) {
732     SkFontHinting hinting = font.getHinting();
733     if (hinting != SkPaintDefaults_Hinting) {
734         switch (hinting) {
735             case SkFontHinting::kNone:
736                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NONE);
737                 break;
738             case SkFontHinting::kSlight:
739                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_SLIGHT);
740                 break;
741             case SkFontHinting::kNormal:
742                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NORMAL);
743                 break;
744             case SkFontHinting::kFull:
745                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_FULL);
746                 break;
747         }
748     }
749 }
750 
apply_font_edging(const SkFont & font,SkJSONWriter & writer)751 static void apply_font_edging(const SkFont& font, SkJSONWriter& writer) {
752     switch (font.getEdging()) {
753         case SkFont::Edging::kAlias:
754             writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ALIAS);
755             break;
756         case SkFont::Edging::kAntiAlias:
757             writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ANTIALIAS);
758             break;
759         case SkFont::Edging::kSubpixelAntiAlias:
760             writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS);
761             break;
762     }
763 }
764 
apply_paint_color(const SkPaint & paint,SkJSONWriter & writer)765 static void apply_paint_color(const SkPaint& paint, SkJSONWriter& writer) {
766     SkColor color = paint.getColor();
767     if (color != SK_ColorBLACK) {
768         writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
769         DrawCommand::MakeJsonColor(writer, color);
770     }
771 }
772 
apply_paint_style(const SkPaint & paint,SkJSONWriter & writer)773 static void apply_paint_style(const SkPaint& paint, SkJSONWriter& writer) {
774     SkPaint::Style style = paint.getStyle();
775     if (style != SkPaint::kFill_Style) {
776         switch (style) {
777             case SkPaint::kStroke_Style: {
778                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKE);
779                 break;
780             }
781             case SkPaint::kStrokeAndFill_Style: {
782                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKEANDFILL);
783                 break;
784             }
785             default: SkASSERT(false);
786         }
787     }
788 }
789 
apply_paint_cap(const SkPaint & paint,SkJSONWriter & writer)790 static void apply_paint_cap(const SkPaint& paint, SkJSONWriter& writer) {
791     SkPaint::Cap cap = paint.getStrokeCap();
792     if (cap != SkPaint::kDefault_Cap) {
793         switch (cap) {
794             case SkPaint::kButt_Cap:
795                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_BUTT);
796                 break;
797             case SkPaint::kRound_Cap:
798                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_ROUND);
799                 break;
800             case SkPaint::kSquare_Cap:
801                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_SQUARE);
802                 break;
803             default: SkASSERT(false);
804         }
805     }
806 }
807 
apply_paint_join(const SkPaint & paint,SkJSONWriter & writer)808 static void apply_paint_join(const SkPaint& paint, SkJSONWriter& writer) {
809     SkPaint::Join join = paint.getStrokeJoin();
810     if (join != SkPaint::kDefault_Join) {
811         switch (join) {
812             case SkPaint::kMiter_Join:
813                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_MITER_JOIN);
814                 break;
815             case SkPaint::kRound_Join:
816                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_ROUND_JOIN);
817                 break;
818             case SkPaint::kBevel_Join:
819                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_BEVEL_JOIN);
820                 break;
821             default: SkASSERT(false);
822         }
823     }
824 }
825 
apply_paint_filterquality(const SkPaint & paint,SkJSONWriter & writer)826 static void apply_paint_filterquality(const SkPaint& paint, SkJSONWriter& writer) {
827     SkFilterQuality quality = paint.getFilterQuality();
828     switch (quality) {
829         case kNone_SkFilterQuality: break;
830         case kLow_SkFilterQuality:
831             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY, DEBUGCANVAS_FILTERQUALITY_LOW);
832             break;
833         case kMedium_SkFilterQuality:
834             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
835                                 DEBUGCANVAS_FILTERQUALITY_MEDIUM);
836             break;
837         case kHigh_SkFilterQuality:
838             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
839                                 DEBUGCANVAS_FILTERQUALITY_HIGH);
840             break;
841     }
842 }
843 
apply_paint_maskfilter(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)844 static void apply_paint_maskfilter(const SkPaint&  paint,
845                                    SkJSONWriter&   writer,
846                                    UrlDataManager& urlDataManager) {
847     SkMaskFilter* maskFilter = paint.getMaskFilter();
848     if (maskFilter != nullptr) {
849         SkMaskFilterBase::BlurRec blurRec;
850         if (as_MFB(maskFilter)->asABlur(&blurRec)) {
851             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BLUR);
852             writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SIGMA, blurRec.fSigma);
853             switch (blurRec.fStyle) {
854                 case SkBlurStyle::kNormal_SkBlurStyle:
855                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_NORMAL);
856                     break;
857                 case SkBlurStyle::kSolid_SkBlurStyle:
858                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_SOLID);
859                     break;
860                 case SkBlurStyle::kOuter_SkBlurStyle:
861                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_OUTER);
862                     break;
863                 case SkBlurStyle::kInner_SkBlurStyle:
864                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_INNER);
865                     break;
866                 default: SkASSERT(false);
867             }
868             writer.endObject();  // blur
869         } else {
870             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_MASKFILTER);
871             DrawCommand::flatten(maskFilter, writer, urlDataManager);
872             writer.endObject();  // maskFilter
873         }
874     }
875 }
876 
apply_paint_patheffect(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)877 static void apply_paint_patheffect(const SkPaint&  paint,
878                                    SkJSONWriter&   writer,
879                                    UrlDataManager& urlDataManager) {
880     SkPathEffect* pathEffect = paint.getPathEffect();
881     if (pathEffect != nullptr) {
882         SkPathEffect::DashInfo dashInfo;
883         SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
884         if (dashType == SkPathEffect::kDash_DashType) {
885             dashInfo.fIntervals = (SkScalar*)sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
886             pathEffect->asADash(&dashInfo);
887             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_DASHING);
888             writer.beginArray(DEBUGCANVAS_ATTRIBUTE_INTERVALS, false);
889             for (int32_t i = 0; i < dashInfo.fCount; i++) {
890                 writer.appendFloat(dashInfo.fIntervals[i]);
891             }
892             writer.endArray();  // intervals
893             sk_free(dashInfo.fIntervals);
894             writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_PHASE, dashInfo.fPhase);
895             writer.endObject();  // dashing
896         } else {
897             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_PATHEFFECT);
898             DrawCommand::flatten(pathEffect, writer, urlDataManager);
899             writer.endObject();  // pathEffect
900         }
901     }
902 }
903 
apply_font_typeface(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)904 static void apply_font_typeface(const SkFont&   font,
905                                 SkJSONWriter&   writer,
906                                 UrlDataManager& urlDataManager) {
907     SkTypeface* typeface = font.getTypefaceOrDefault();
908     if (typeface != nullptr) {
909         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_TYPEFACE);
910         SkDynamicMemoryWStream buffer;
911         typeface->serialize(&buffer);
912         void* data = sk_malloc_throw(buffer.bytesWritten());
913         buffer.copyTo(data);
914         SkString url = encode_data(
915                 data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
916         writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
917         sk_free(data);
918         writer.endObject();
919     }
920 }
921 
apply_flattenable(const char * key,SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)922 static void apply_flattenable(const char*     key,
923                               SkFlattenable*  flattenable,
924                               SkJSONWriter&   writer,
925                               UrlDataManager& urlDataManager) {
926     if (flattenable != nullptr) {
927         writer.beginObject(key);
928         DrawCommand::flatten(flattenable, writer, urlDataManager);
929         writer.endObject();
930     }
931 }
932 
MakeJsonPaint(SkJSONWriter & writer,const SkPaint & paint,UrlDataManager & urlDataManager)933 void DrawCommand::MakeJsonPaint(SkJSONWriter&   writer,
934                                 const SkPaint&  paint,
935                                 UrlDataManager& urlDataManager) {
936     writer.beginObject();
937     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
938     store_scalar(writer,
939                  DEBUGCANVAS_ATTRIBUTE_STROKEMITER,
940                  paint.getStrokeMiter(),
941                  SkPaintDefaults_MiterLimit);
942     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
943     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
944 
945     apply_paint_color(paint, writer);
946     apply_paint_style(paint, writer);
947     apply_paint_blend_mode(paint, writer);
948     apply_paint_cap(paint, writer);
949     apply_paint_join(paint, writer);
950     apply_paint_filterquality(paint, writer);
951     apply_paint_patheffect(paint, writer, urlDataManager);
952     apply_paint_maskfilter(paint, writer, urlDataManager);
953     apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, paint.getShader(), writer, urlDataManager);
954     apply_flattenable(
955             DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER, paint.getImageFilter(), writer, urlDataManager);
956     apply_flattenable(
957             DEBUGCANVAS_ATTRIBUTE_COLORFILTER, paint.getColorFilter(), writer, urlDataManager);
958     writer.endObject();  // paint
959 }
960 
MakeJsonFont(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)961 static void MakeJsonFont(const SkFont& font, SkJSONWriter& writer, UrlDataManager& urlDataManager) {
962     writer.beginObject();
963     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, font.isEmbolden(), false);
964     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_LINEARTEXT, font.isLinearMetrics(), false);
965     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, font.isSubpixel(), false);
966     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, font.isEmbeddedBitmaps(), false);
967     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_AUTOHINTING, font.isForceAutoHinting(), false);
968 
969     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSIZE, font.getSize(), SkPaintDefaults_TextSize);
970     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getScaleX(), SK_Scalar1);
971     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getSkewX(), 0.0f);
972     apply_font_edging(font, writer);
973     apply_font_hinting(font, writer);
974     apply_font_typeface(font, writer, urlDataManager);
975     writer.endObject();  // font
976 }
977 
MakeJsonLattice(SkJSONWriter & writer,const SkCanvas::Lattice & lattice)978 void DrawCommand::MakeJsonLattice(SkJSONWriter& writer, const SkCanvas::Lattice& lattice) {
979     writer.beginObject();
980     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT, lattice.fXCount);
981     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT, lattice.fYCount);
982     if (nullptr != lattice.fBounds) {
983         writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
984         MakeJsonIRect(writer, *lattice.fBounds);
985     }
986     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS);
987     for (int i = 0; i < lattice.fXCount; i++) {
988         writer.appendS32(lattice.fXDivs[i]);
989     }
990     writer.endArray();  // xdivs
991     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS);
992     for (int i = 0; i < lattice.fYCount; i++) {
993         writer.appendS32(lattice.fYDivs[i]);
994     }
995     writer.endArray();  // ydivs
996     if (nullptr != lattice.fRectTypes) {
997         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS);
998         int flagCount = 0;
999         for (int row = 0; row < lattice.fYCount + 1; row++) {
1000             writer.beginArray();
1001             for (int column = 0; column < lattice.fXCount + 1; column++) {
1002                 writer.appendS32(lattice.fRectTypes[flagCount++]);
1003             }
1004             writer.endArray();  // row
1005         }
1006         writer.endArray();
1007     }
1008     writer.endObject();
1009 }
1010 
ClearCommand(SkColor color)1011 ClearCommand::ClearCommand(SkColor color) : INHERITED(kClear_OpType) { fColor = color; }
1012 
execute(SkCanvas * canvas) const1013 void ClearCommand::execute(SkCanvas* canvas) const { canvas->clear(fColor); }
1014 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1015 void ClearCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1016     INHERITED::toJSON(writer, urlDataManager);
1017     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
1018     MakeJsonColor(writer, fColor);
1019 }
1020 
ClipPathCommand(const SkPath & path,SkClipOp op,bool doAA)1021 ClipPathCommand::ClipPathCommand(const SkPath& path, SkClipOp op, bool doAA)
1022         : INHERITED(kClipPath_OpType) {
1023     fPath = path;
1024     fOp   = op;
1025     fDoAA = doAA;
1026 }
1027 
execute(SkCanvas * canvas) const1028 void ClipPathCommand::execute(SkCanvas* canvas) const { canvas->clipPath(fPath, fOp, fDoAA); }
1029 
render(SkCanvas * canvas) const1030 bool ClipPathCommand::render(SkCanvas* canvas) const {
1031     render_path(canvas, fPath);
1032     return true;
1033 }
1034 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1035 void ClipPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1036     INHERITED::toJSON(writer, urlDataManager);
1037     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1038     MakeJsonPath(writer, fPath);
1039     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1040     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1041 }
1042 
ClipRegionCommand(const SkRegion & region,SkClipOp op)1043 ClipRegionCommand::ClipRegionCommand(const SkRegion& region, SkClipOp op)
1044         : INHERITED(kClipRegion_OpType) {
1045     fRegion = region;
1046     fOp     = op;
1047 }
1048 
execute(SkCanvas * canvas) const1049 void ClipRegionCommand::execute(SkCanvas* canvas) const { canvas->clipRegion(fRegion, fOp); }
1050 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1051 void ClipRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1052     INHERITED::toJSON(writer, urlDataManager);
1053     writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1054     MakeJsonRegion(writer, fRegion);
1055     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1056 }
1057 
ClipRectCommand(const SkRect & rect,SkClipOp op,bool doAA)1058 ClipRectCommand::ClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA)
1059         : INHERITED(kClipRect_OpType) {
1060     fRect = rect;
1061     fOp   = op;
1062     fDoAA = doAA;
1063 }
1064 
execute(SkCanvas * canvas) const1065 void ClipRectCommand::execute(SkCanvas* canvas) const { canvas->clipRect(fRect, fOp, fDoAA); }
1066 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1067 void ClipRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1068     INHERITED::toJSON(writer, urlDataManager);
1069     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1070     MakeJsonRect(writer, fRect);
1071     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1072     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1073 
1074     SkString desc;
1075     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1076 }
1077 
ClipRRectCommand(const SkRRect & rrect,SkClipOp op,bool doAA)1078 ClipRRectCommand::ClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA)
1079         : INHERITED(kClipRRect_OpType) {
1080     fRRect = rrect;
1081     fOp    = op;
1082     fDoAA  = doAA;
1083 }
1084 
execute(SkCanvas * canvas) const1085 void ClipRRectCommand::execute(SkCanvas* canvas) const { canvas->clipRRect(fRRect, fOp, fDoAA); }
1086 
render(SkCanvas * canvas) const1087 bool ClipRRectCommand::render(SkCanvas* canvas) const {
1088     render_rrect(canvas, fRRect);
1089     return true;
1090 }
1091 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1092 void ClipRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1093     INHERITED::toJSON(writer, urlDataManager);
1094     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1095     make_json_rrect(writer, fRRect);
1096     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1097     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1098 }
1099 
ConcatCommand(const SkMatrix & matrix)1100 ConcatCommand::ConcatCommand(const SkMatrix& matrix) : INHERITED(kConcat_OpType) {
1101     fMatrix = matrix;
1102 }
1103 
execute(SkCanvas * canvas) const1104 void ConcatCommand::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); }
1105 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1106 void ConcatCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1107     INHERITED::toJSON(writer, urlDataManager);
1108     writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
1109     MakeJsonMatrix(writer, fMatrix);
1110 }
1111 
1112 ////
1113 
DrawAnnotationCommand(const SkRect & rect,const char key[],sk_sp<SkData> value)1114 DrawAnnotationCommand::DrawAnnotationCommand(const SkRect& rect,
1115                                              const char    key[],
1116                                              sk_sp<SkData> value)
1117         : INHERITED(kDrawAnnotation_OpType), fRect(rect), fKey(key), fValue(std::move(value)) {}
1118 
execute(SkCanvas * canvas) const1119 void DrawAnnotationCommand::execute(SkCanvas* canvas) const {
1120     canvas->drawAnnotation(fRect, fKey.c_str(), fValue);
1121 }
1122 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1123 void DrawAnnotationCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1124     INHERITED::toJSON(writer, urlDataManager);
1125 
1126     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1127     MakeJsonRect(writer, fRect);
1128     writer.appendString("key", fKey.c_str());
1129     if (fValue.get()) {
1130         // TODO: dump out the "value"
1131     }
1132 
1133     SkString desc;
1134     str_append(&desc, fRect)->appendf(" %s", fKey.c_str());
1135     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, desc.c_str());
1136 }
1137 
1138 ////
1139 
DrawBitmapCommand(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)1140 DrawBitmapCommand::DrawBitmapCommand(const SkBitmap& bitmap,
1141                                      SkScalar        left,
1142                                      SkScalar        top,
1143                                      const SkPaint*  paint)
1144         : INHERITED(kDrawBitmap_OpType), fBitmap(bitmap), fLeft(left), fTop(top), fPaint(paint) {}
1145 
execute(SkCanvas * canvas) const1146 void DrawBitmapCommand::execute(SkCanvas* canvas) const {
1147     canvas->drawBitmap(fBitmap, fLeft, fTop, fPaint.getMaybeNull());
1148 }
1149 
render(SkCanvas * canvas) const1150 bool DrawBitmapCommand::render(SkCanvas* canvas) const {
1151     render_bitmap(canvas, fBitmap);
1152     return true;
1153 }
1154 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1155 void DrawBitmapCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1156     INHERITED::toJSON(writer, urlDataManager);
1157     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1158     flatten(fBitmap, writer, urlDataManager);
1159     writer.endObject();
1160     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1161     MakeJsonPoint(writer, fLeft, fTop);
1162     if (fPaint.isValid()) {
1163         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1164         MakeJsonPaint(writer, *fPaint, urlDataManager);
1165     }
1166 }
1167 
DrawBitmapLatticeCommand(const SkBitmap & bitmap,const SkCanvas::Lattice & lattice,const SkRect & dst,const SkPaint * paint)1168 DrawBitmapLatticeCommand::DrawBitmapLatticeCommand(const SkBitmap&          bitmap,
1169                                                    const SkCanvas::Lattice& lattice,
1170                                                    const SkRect&            dst,
1171                                                    const SkPaint*           paint)
1172         : INHERITED(kDrawBitmapLattice_OpType)
1173         , fBitmap(bitmap)
1174         , fLattice(lattice)
1175         , fDst(dst)
1176         , fPaint(paint) {}
1177 
execute(SkCanvas * canvas) const1178 void DrawBitmapLatticeCommand::execute(SkCanvas* canvas) const {
1179     canvas->drawBitmapLattice(fBitmap, fLattice, fDst, fPaint.getMaybeNull());
1180 }
1181 
render(SkCanvas * canvas) const1182 bool DrawBitmapLatticeCommand::render(SkCanvas* canvas) const {
1183     SkAutoCanvasRestore acr(canvas, true);
1184     canvas->clear(0xFFFFFFFF);
1185 
1186     xlate_and_scale_to_bounds(canvas, fDst);
1187 
1188     this->execute(canvas);
1189     return true;
1190 }
1191 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1192 void DrawBitmapLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1193     INHERITED::toJSON(writer, urlDataManager);
1194     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1195     flatten(fBitmap, writer, urlDataManager);
1196     writer.endObject();  // bitmap
1197 
1198     writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
1199     MakeJsonLattice(writer, fLattice);
1200     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1201     MakeJsonRect(writer, fDst);
1202     if (fPaint.isValid()) {
1203         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1204         MakeJsonPaint(writer, *fPaint, urlDataManager);
1205     }
1206 
1207     SkString desc;
1208     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1209 }
1210 
DrawBitmapNineCommand(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1211 DrawBitmapNineCommand::DrawBitmapNineCommand(const SkBitmap& bitmap,
1212                                              const SkIRect&  center,
1213                                              const SkRect&   dst,
1214                                              const SkPaint*  paint)
1215         : INHERITED(kDrawBitmapNine_OpType)
1216         , fBitmap(bitmap)
1217         , fCenter(center)
1218         , fDst(dst)
1219         , fPaint(paint) {}
1220 
execute(SkCanvas * canvas) const1221 void DrawBitmapNineCommand::execute(SkCanvas* canvas) const {
1222     canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaint.getMaybeNull());
1223 }
1224 
render(SkCanvas * canvas) const1225 bool DrawBitmapNineCommand::render(SkCanvas* canvas) const {
1226     SkRect tmp = SkRect::Make(fCenter);
1227     render_bitmap(canvas, fBitmap, &tmp);
1228     return true;
1229 }
1230 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1231 void DrawBitmapNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1232     INHERITED::toJSON(writer, urlDataManager);
1233     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1234     flatten(fBitmap, writer, urlDataManager);
1235     writer.endObject();  // bitmap
1236 
1237     writer.appendName(DEBUGCANVAS_ATTRIBUTE_CENTER);
1238     MakeJsonIRect(writer, fCenter);
1239     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1240     MakeJsonRect(writer, fDst);
1241     if (fPaint.isValid()) {
1242         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1243         MakeJsonPaint(writer, *fPaint, urlDataManager);
1244     }
1245 }
1246 
DrawBitmapRectCommand(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1247 DrawBitmapRectCommand::DrawBitmapRectCommand(const SkBitmap&             bitmap,
1248                                              const SkRect*               src,
1249                                              const SkRect&               dst,
1250                                              const SkPaint*              paint,
1251                                              SkCanvas::SrcRectConstraint constraint)
1252         : INHERITED(kDrawBitmapRect_OpType)
1253         , fBitmap(bitmap)
1254         , fSrc(src)
1255         , fDst(dst)
1256         , fPaint(paint)
1257         , fConstraint(constraint) {}
1258 
execute(SkCanvas * canvas) const1259 void DrawBitmapRectCommand::execute(SkCanvas* canvas) const {
1260     canvas->legacy_drawBitmapRect(
1261             fBitmap, fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
1262 }
1263 
render(SkCanvas * canvas) const1264 bool DrawBitmapRectCommand::render(SkCanvas* canvas) const {
1265     render_bitmap(canvas, fBitmap, fSrc.getMaybeNull());
1266     return true;
1267 }
1268 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1269 void DrawBitmapRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1270     INHERITED::toJSON(writer, urlDataManager);
1271     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1272     flatten(fBitmap, writer, urlDataManager);
1273     writer.endObject();  // bitmap
1274 
1275     if (fSrc.isValid()) {
1276         writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1277         MakeJsonRect(writer, *fSrc);
1278     }
1279     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1280     MakeJsonRect(writer, fDst);
1281     if (fPaint.isValid()) {
1282         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1283         MakeJsonPaint(writer, *fPaint, urlDataManager);
1284     }
1285     if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1286         writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1287     }
1288 
1289     SkString desc;
1290     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1291 }
1292 
DrawImageCommand(const SkImage * image,SkScalar left,SkScalar top,const SkPaint * paint)1293 DrawImageCommand::DrawImageCommand(const SkImage* image,
1294                                    SkScalar       left,
1295                                    SkScalar       top,
1296                                    const SkPaint* paint)
1297         : INHERITED(kDrawImage_OpType)
1298         , fImage(SkRef(image))
1299         , fLeft(left)
1300         , fTop(top)
1301         , fPaint(paint) {}
1302 
execute(SkCanvas * canvas) const1303 void DrawImageCommand::execute(SkCanvas* canvas) const {
1304     canvas->drawImage(fImage.get(), fLeft, fTop, fPaint.getMaybeNull());
1305 }
1306 
render(SkCanvas * canvas) const1307 bool DrawImageCommand::render(SkCanvas* canvas) const {
1308     SkAutoCanvasRestore acr(canvas, true);
1309     canvas->clear(0xFFFFFFFF);
1310 
1311     xlate_and_scale_to_bounds(
1312             canvas,
1313             SkRect::MakeXYWH(
1314                     fLeft, fTop, SkIntToScalar(fImage->width()), SkIntToScalar(fImage->height())));
1315     this->execute(canvas);
1316     return true;
1317 }
1318 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1319 void DrawImageCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1320     INHERITED::toJSON(writer, urlDataManager);
1321 
1322 
1323     if (urlDataManager.hasImageIndex()) {
1324         writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
1325         writer.appendU64((uint64_t)urlDataManager.lookupImage(fImage.get()));
1326     } else {
1327         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1328         flatten(*fImage, writer, urlDataManager);
1329         writer.endObject();  // image
1330     }
1331 
1332     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1333     MakeJsonPoint(writer, fLeft, fTop);
1334     if (fPaint.isValid()) {
1335         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1336         MakeJsonPaint(writer, *fPaint, urlDataManager);
1337     }
1338 
1339     writer.appendU32(DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID, fImage->uniqueID());
1340     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_WIDTH, fImage->width());
1341     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_HEIGHT, fImage->height());
1342     switch (fImage->alphaType()) {
1343         case kOpaque_SkAlphaType:
1344             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_OPAQUE);
1345             break;
1346         case kPremul_SkAlphaType:
1347             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_PREMUL);
1348             break;
1349         case kUnpremul_SkAlphaType:
1350             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNPREMUL);
1351             break;
1352         default:
1353             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNKNOWN);
1354             break;
1355     }
1356 }
1357 
DrawImageLatticeCommand(const SkImage * image,const SkCanvas::Lattice & lattice,const SkRect & dst,const SkPaint * paint)1358 DrawImageLatticeCommand::DrawImageLatticeCommand(const SkImage*           image,
1359                                                  const SkCanvas::Lattice& lattice,
1360                                                  const SkRect&            dst,
1361                                                  const SkPaint*           paint)
1362         : INHERITED(kDrawImageLattice_OpType)
1363         , fImage(SkRef(image))
1364         , fLattice(lattice)
1365         , fDst(dst)
1366         , fPaint(paint) {}
1367 
execute(SkCanvas * canvas) const1368 void DrawImageLatticeCommand::execute(SkCanvas* canvas) const {
1369     canvas->drawImageLattice(fImage.get(), fLattice, fDst, fPaint.getMaybeNull());
1370 }
1371 
render(SkCanvas * canvas) const1372 bool DrawImageLatticeCommand::render(SkCanvas* canvas) const {
1373     SkAutoCanvasRestore acr(canvas, true);
1374     canvas->clear(0xFFFFFFFF);
1375 
1376     xlate_and_scale_to_bounds(canvas, fDst);
1377 
1378     this->execute(canvas);
1379     return true;
1380 }
1381 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1382 void DrawImageLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1383     INHERITED::toJSON(writer, urlDataManager);
1384     if (urlDataManager.hasImageIndex()) {
1385         writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
1386         writer.appendU64((uint64_t)urlDataManager.lookupImage(fImage.get()));
1387     } else {
1388         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1389         flatten(*fImage, writer, urlDataManager);
1390         writer.endObject();  // image
1391     }
1392 
1393     writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
1394     MakeJsonLattice(writer, fLattice);
1395     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1396     MakeJsonRect(writer, fDst);
1397     if (fPaint.isValid()) {
1398         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1399         MakeJsonPaint(writer, *fPaint, urlDataManager);
1400     }
1401 
1402     SkString desc;
1403     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1404 }
1405 
DrawImageRectCommand(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1406 DrawImageRectCommand::DrawImageRectCommand(const SkImage*              image,
1407                                            const SkRect*               src,
1408                                            const SkRect&               dst,
1409                                            const SkPaint*              paint,
1410                                            SkCanvas::SrcRectConstraint constraint)
1411         : INHERITED(kDrawImageRect_OpType)
1412         , fImage(SkRef(image))
1413         , fSrc(src)
1414         , fDst(dst)
1415         , fPaint(paint)
1416         , fConstraint(constraint) {}
1417 
execute(SkCanvas * canvas) const1418 void DrawImageRectCommand::execute(SkCanvas* canvas) const {
1419     canvas->legacy_drawImageRect(
1420             fImage.get(), fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
1421 }
1422 
render(SkCanvas * canvas) const1423 bool DrawImageRectCommand::render(SkCanvas* canvas) const {
1424     SkAutoCanvasRestore acr(canvas, true);
1425     canvas->clear(0xFFFFFFFF);
1426 
1427     xlate_and_scale_to_bounds(canvas, fDst);
1428 
1429     this->execute(canvas);
1430     return true;
1431 }
1432 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1433 void DrawImageRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1434     INHERITED::toJSON(writer, urlDataManager);
1435     if (urlDataManager.hasImageIndex()) {
1436         writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
1437         writer.appendU64((uint64_t)urlDataManager.lookupImage(fImage.get()));
1438     } else {
1439         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1440         flatten(*fImage, writer, urlDataManager);
1441         writer.endObject();  // image
1442     }
1443 
1444     if (fSrc.isValid()) {
1445         writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1446         MakeJsonRect(writer, *fSrc);
1447     }
1448     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1449     MakeJsonRect(writer, fDst);
1450     if (fPaint.isValid()) {
1451         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1452         MakeJsonPaint(writer, *fPaint, urlDataManager);
1453     }
1454     if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1455         writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1456     }
1457 
1458     SkString desc;
1459     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1460 }
1461 
DrawImageRectLayerCommand(DebugLayerManager * layerManager,const int nodeId,const int frame,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1462 DrawImageRectLayerCommand::DrawImageRectLayerCommand(DebugLayerManager*    layerManager,
1463                                                      const int                   nodeId,
1464                                                      const int                   frame,
1465                                                      const SkRect*               src,
1466                                                      const SkRect&               dst,
1467                                                      const SkPaint*              paint,
1468                                                      SkCanvas::SrcRectConstraint constraint)
1469         : INHERITED(kDrawImageRectLayer_OpType)
1470         , fLayerManager(layerManager)
1471         , fNodeId(nodeId)
1472         , fFrame(frame)
1473         , fSrc(src)
1474         , fDst(dst)
1475         , fPaint(paint)
1476         , fConstraint(constraint) {}
1477 
execute(SkCanvas * canvas) const1478 void DrawImageRectLayerCommand::execute(SkCanvas* canvas) const {
1479     sk_sp<SkImage> snapshot = fLayerManager->getLayerAsImage(fNodeId, fFrame);
1480     canvas->legacy_drawImageRect(
1481             snapshot.get(), fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
1482 }
1483 
render(SkCanvas * canvas) const1484 bool DrawImageRectLayerCommand::render(SkCanvas* canvas) const {
1485     SkAutoCanvasRestore acr(canvas, true);
1486     canvas->clear(0xFFFFFFFF);
1487 
1488     xlate_and_scale_to_bounds(canvas, fDst);
1489 
1490     this->execute(canvas);
1491     return true;
1492 }
1493 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1494 void DrawImageRectLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1495     INHERITED::toJSON(writer, urlDataManager);
1496 
1497     // Don't append an image attribute here, the image can be rendered in as many different ways
1498     // as there are commands in the layer, at least. the urlDataManager would save each one under
1499     // a different URL.
1500     // Append the node id, and the layer inspector of the debugger will know what to do with it.
1501     writer.appendS64(DEBUGCANVAS_ATTRIBUTE_LAYERNODEID, fNodeId);
1502 
1503     if (fSrc.isValid()) {
1504         writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1505         MakeJsonRect(writer, *fSrc);
1506     }
1507     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1508     MakeJsonRect(writer, fDst);
1509     if (fPaint.isValid()) {
1510         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1511         MakeJsonPaint(writer, *fPaint, urlDataManager);
1512     }
1513     if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1514         writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1515     }
1516 
1517     SkString desc;
1518     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1519 }
1520 
DrawImageNineCommand(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1521 DrawImageNineCommand::DrawImageNineCommand(const SkImage* image,
1522                                            const SkIRect& center,
1523                                            const SkRect&  dst,
1524                                            const SkPaint* paint)
1525         : INHERITED(kDrawImageNine_OpType)
1526         , fImage(SkRef(image))
1527         , fCenter(center)
1528         , fDst(dst)
1529         , fPaint(paint) {}
1530 
execute(SkCanvas * canvas) const1531 void DrawImageNineCommand::execute(SkCanvas* canvas) const {
1532     canvas->drawImageNine(fImage.get(), fCenter, fDst, fPaint.getMaybeNull());
1533 }
1534 
render(SkCanvas * canvas) const1535 bool DrawImageNineCommand::render(SkCanvas* canvas) const {
1536     SkAutoCanvasRestore acr(canvas, true);
1537     canvas->clear(0xFFFFFFFF);
1538 
1539     xlate_and_scale_to_bounds(canvas, fDst);
1540 
1541     this->execute(canvas);
1542     return true;
1543 }
1544 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1545 void DrawImageNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1546     INHERITED::toJSON(writer, urlDataManager);
1547     if (urlDataManager.hasImageIndex()) {
1548         writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
1549         writer.appendU64((uint64_t)urlDataManager.lookupImage(fImage.get()));
1550     } else {
1551         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1552         flatten(*fImage, writer, urlDataManager);
1553         writer.endObject();  // image
1554     }
1555 
1556     writer.appendName(DEBUGCANVAS_ATTRIBUTE_CENTER);
1557     MakeJsonIRect(writer, fCenter);
1558     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1559     MakeJsonRect(writer, fDst);
1560     if (fPaint.isValid()) {
1561         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1562         MakeJsonPaint(writer, *fPaint, urlDataManager);
1563     }
1564 }
1565 
DrawOvalCommand(const SkRect & oval,const SkPaint & paint)1566 DrawOvalCommand::DrawOvalCommand(const SkRect& oval, const SkPaint& paint)
1567         : INHERITED(kDrawOval_OpType) {
1568     fOval  = oval;
1569     fPaint = paint;
1570 }
1571 
execute(SkCanvas * canvas) const1572 void DrawOvalCommand::execute(SkCanvas* canvas) const { canvas->drawOval(fOval, fPaint); }
1573 
render(SkCanvas * canvas) const1574 bool DrawOvalCommand::render(SkCanvas* canvas) const {
1575     canvas->clear(0xFFFFFFFF);
1576     canvas->save();
1577 
1578     xlate_and_scale_to_bounds(canvas, fOval);
1579 
1580     SkPaint p;
1581     p.setColor(SK_ColorBLACK);
1582     p.setStyle(SkPaint::kStroke_Style);
1583 
1584     canvas->drawOval(fOval, p);
1585     canvas->restore();
1586 
1587     return true;
1588 }
1589 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1590 void DrawOvalCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1591     INHERITED::toJSON(writer, urlDataManager);
1592     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1593     MakeJsonRect(writer, fOval);
1594     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1595     MakeJsonPaint(writer, fPaint, urlDataManager);
1596 }
1597 
DrawArcCommand(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)1598 DrawArcCommand::DrawArcCommand(const SkRect&  oval,
1599                                SkScalar       startAngle,
1600                                SkScalar       sweepAngle,
1601                                bool           useCenter,
1602                                const SkPaint& paint)
1603         : INHERITED(kDrawArc_OpType) {
1604     fOval       = oval;
1605     fStartAngle = startAngle;
1606     fSweepAngle = sweepAngle;
1607     fUseCenter  = useCenter;
1608     fPaint      = paint;
1609 }
1610 
execute(SkCanvas * canvas) const1611 void DrawArcCommand::execute(SkCanvas* canvas) const {
1612     canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, fPaint);
1613 }
1614 
render(SkCanvas * canvas) const1615 bool DrawArcCommand::render(SkCanvas* canvas) const {
1616     canvas->clear(0xFFFFFFFF);
1617     canvas->save();
1618 
1619     xlate_and_scale_to_bounds(canvas, fOval);
1620 
1621     SkPaint p;
1622     p.setColor(SK_ColorBLACK);
1623     p.setStyle(SkPaint::kStroke_Style);
1624 
1625     canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, p);
1626     canvas->restore();
1627 
1628     return true;
1629 }
1630 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1631 void DrawArcCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1632     INHERITED::toJSON(writer, urlDataManager);
1633     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1634     MakeJsonRect(writer, fOval);
1635     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_STARTANGLE, fStartAngle);
1636     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE, fSweepAngle);
1637     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_USECENTER, fUseCenter);
1638     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1639     MakeJsonPaint(writer, fPaint, urlDataManager);
1640 }
1641 
DrawPaintCommand(const SkPaint & paint)1642 DrawPaintCommand::DrawPaintCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1643     fPaint = paint;
1644 }
1645 
execute(SkCanvas * canvas) const1646 void DrawPaintCommand::execute(SkCanvas* canvas) const { canvas->drawPaint(fPaint); }
1647 
render(SkCanvas * canvas) const1648 bool DrawPaintCommand::render(SkCanvas* canvas) const {
1649     canvas->clear(0xFFFFFFFF);
1650     canvas->drawPaint(fPaint);
1651     return true;
1652 }
1653 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1654 void DrawPaintCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1655     INHERITED::toJSON(writer, urlDataManager);
1656     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1657     MakeJsonPaint(writer, fPaint, urlDataManager);
1658 }
1659 
DrawBehindCommand(const SkPaint & paint)1660 DrawBehindCommand::DrawBehindCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1661     fPaint = paint;
1662 }
1663 
execute(SkCanvas * canvas) const1664 void DrawBehindCommand::execute(SkCanvas* canvas) const {
1665     SkCanvasPriv::DrawBehind(canvas, fPaint);
1666 }
1667 
render(SkCanvas * canvas) const1668 bool DrawBehindCommand::render(SkCanvas* canvas) const {
1669     canvas->clear(0xFFFFFFFF);
1670     SkCanvasPriv::DrawBehind(canvas, fPaint);
1671     return true;
1672 }
1673 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1674 void DrawBehindCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1675     INHERITED::toJSON(writer, urlDataManager);
1676     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1677     MakeJsonPaint(writer, fPaint, urlDataManager);
1678 }
1679 
DrawPathCommand(const SkPath & path,const SkPaint & paint)1680 DrawPathCommand::DrawPathCommand(const SkPath& path, const SkPaint& paint)
1681         : INHERITED(kDrawPath_OpType) {
1682     fPath  = path;
1683     fPaint = paint;
1684 }
1685 
execute(SkCanvas * canvas) const1686 void DrawPathCommand::execute(SkCanvas* canvas) const { canvas->drawPath(fPath, fPaint); }
1687 
render(SkCanvas * canvas) const1688 bool DrawPathCommand::render(SkCanvas* canvas) const {
1689     render_path(canvas, fPath);
1690     return true;
1691 }
1692 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1693 void DrawPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1694     INHERITED::toJSON(writer, urlDataManager);
1695     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1696     MakeJsonPath(writer, fPath);
1697     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1698     MakeJsonPaint(writer, fPaint, urlDataManager);
1699 }
1700 
DrawRegionCommand(const SkRegion & region,const SkPaint & paint)1701 DrawRegionCommand::DrawRegionCommand(const SkRegion& region, const SkPaint& paint)
1702         : INHERITED(kDrawRegion_OpType) {
1703     fRegion = region;
1704     fPaint  = paint;
1705 }
1706 
execute(SkCanvas * canvas) const1707 void DrawRegionCommand::execute(SkCanvas* canvas) const { canvas->drawRegion(fRegion, fPaint); }
1708 
render(SkCanvas * canvas) const1709 bool DrawRegionCommand::render(SkCanvas* canvas) const {
1710     render_region(canvas, fRegion);
1711     return true;
1712 }
1713 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1714 void DrawRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1715     INHERITED::toJSON(writer, urlDataManager);
1716     writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1717     MakeJsonRegion(writer, fRegion);
1718     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1719     MakeJsonPaint(writer, fPaint, urlDataManager);
1720 }
1721 
BeginDrawPictureCommand(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)1722 BeginDrawPictureCommand::BeginDrawPictureCommand(const SkPicture* picture,
1723                                                  const SkMatrix*  matrix,
1724                                                  const SkPaint*   paint)
1725         : INHERITED(kBeginDrawPicture_OpType)
1726         , fPicture(SkRef(picture))
1727         , fMatrix(matrix)
1728         , fPaint(paint) {}
1729 
execute(SkCanvas * canvas) const1730 void BeginDrawPictureCommand::execute(SkCanvas* canvas) const {
1731     if (fPaint.isValid()) {
1732         SkRect bounds = fPicture->cullRect();
1733         if (fMatrix.isValid()) {
1734             fMatrix->mapRect(&bounds);
1735         }
1736         canvas->saveLayer(&bounds, fPaint.get());
1737     }
1738 
1739     if (fMatrix.isValid()) {
1740         if (!fPaint.isValid()) {
1741             canvas->save();
1742         }
1743         canvas->concat(*fMatrix);
1744     }
1745 }
1746 
render(SkCanvas * canvas) const1747 bool BeginDrawPictureCommand::render(SkCanvas* canvas) const {
1748     canvas->clear(0xFFFFFFFF);
1749     canvas->save();
1750 
1751     xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
1752 
1753     canvas->drawPicture(fPicture.get());
1754 
1755     canvas->restore();
1756 
1757     return true;
1758 }
1759 
EndDrawPictureCommand(bool restore)1760 EndDrawPictureCommand::EndDrawPictureCommand(bool restore)
1761         : INHERITED(kEndDrawPicture_OpType), fRestore(restore) {}
1762 
execute(SkCanvas * canvas) const1763 void EndDrawPictureCommand::execute(SkCanvas* canvas) const {
1764     if (fRestore) {
1765         canvas->restore();
1766     }
1767 }
1768 
DrawPointsCommand(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1769 DrawPointsCommand::DrawPointsCommand(SkCanvas::PointMode mode,
1770                                      size_t              count,
1771                                      const SkPoint       pts[],
1772                                      const SkPaint&      paint)
1773         : INHERITED(kDrawPoints_OpType), fMode(mode), fPts(pts, count), fPaint(paint) {}
1774 
execute(SkCanvas * canvas) const1775 void DrawPointsCommand::execute(SkCanvas* canvas) const {
1776     canvas->drawPoints(fMode, fPts.count(), fPts.begin(), fPaint);
1777 }
1778 
render(SkCanvas * canvas) const1779 bool DrawPointsCommand::render(SkCanvas* canvas) const {
1780     canvas->clear(0xFFFFFFFF);
1781     canvas->save();
1782 
1783     SkRect bounds;
1784 
1785     bounds.setEmpty();
1786     for (int i = 0; i < fPts.count(); ++i) {
1787         SkRectPriv::GrowToInclude(&bounds, fPts[i]);
1788     }
1789 
1790     xlate_and_scale_to_bounds(canvas, bounds);
1791 
1792     SkPaint p;
1793     p.setColor(SK_ColorBLACK);
1794     p.setStyle(SkPaint::kStroke_Style);
1795 
1796     canvas->drawPoints(fMode, fPts.count(), fPts.begin(), p);
1797     canvas->restore();
1798 
1799     return true;
1800 }
1801 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1802 void DrawPointsCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1803     INHERITED::toJSON(writer, urlDataManager);
1804     writer.appendString(DEBUGCANVAS_ATTRIBUTE_MODE, pointmode_name(fMode));
1805     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POINTS);
1806     for (int i = 0; i < fPts.count(); i++) {
1807         MakeJsonPoint(writer, fPts[i]);
1808     }
1809     writer.endArray();  // points
1810     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1811     MakeJsonPaint(writer, fPaint, urlDataManager);
1812 }
1813 
DrawTextBlobCommand(sk_sp<SkTextBlob> blob,SkScalar x,SkScalar y,const SkPaint & paint)1814 DrawTextBlobCommand::DrawTextBlobCommand(sk_sp<SkTextBlob> blob,
1815                                          SkScalar          x,
1816                                          SkScalar          y,
1817                                          const SkPaint&    paint)
1818         : INHERITED(kDrawTextBlob_OpType)
1819         , fBlob(std::move(blob))
1820         , fXPos(x)
1821         , fYPos(y)
1822         , fPaint(paint) {}
1823 
execute(SkCanvas * canvas) const1824 void DrawTextBlobCommand::execute(SkCanvas* canvas) const {
1825     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1826 }
1827 
render(SkCanvas * canvas) const1828 bool DrawTextBlobCommand::render(SkCanvas* canvas) const {
1829     canvas->clear(SK_ColorWHITE);
1830     canvas->save();
1831 
1832     SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
1833     xlate_and_scale_to_bounds(canvas, bounds);
1834 
1835     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1836 
1837     canvas->restore();
1838 
1839     return true;
1840 }
1841 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1842 void DrawTextBlobCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1843     INHERITED::toJSON(writer, urlDataManager);
1844     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_RUNS);
1845     SkTextBlobRunIterator iter(fBlob.get());
1846     while (!iter.done()) {
1847         writer.beginObject();  // run
1848         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_GLYPHS);
1849         for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1850             writer.appendU32(iter.glyphs()[i]);
1851         }
1852         writer.endArray();  // glyphs
1853         if (iter.positioning() != SkTextBlobRunIterator::kDefault_Positioning) {
1854             writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POSITIONS);
1855             const SkScalar* iterPositions = iter.pos();
1856             for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1857                 switch (iter.positioning()) {
1858                     case SkTextBlobRunIterator::kFull_Positioning:
1859                         MakeJsonPoint(writer, iterPositions[i * 2], iterPositions[i * 2 + 1]);
1860                         break;
1861                     case SkTextBlobRunIterator::kHorizontal_Positioning:
1862                         writer.appendFloat(iterPositions[i]);
1863                         break;
1864                     case SkTextBlobRunIterator::kDefault_Positioning: break;
1865                     case SkTextBlobRunIterator::kRSXform_Positioning:
1866                         // TODO_RSXFORM_BLOB
1867                         break;
1868                 }
1869             }
1870             writer.endArray();  // positions
1871         }
1872         writer.appendName(DEBUGCANVAS_ATTRIBUTE_FONT);
1873         MakeJsonFont(iter.font(), writer, urlDataManager);
1874         writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1875         MakeJsonPoint(writer, iter.offset());
1876 
1877         writer.endObject();  // run
1878         iter.next();
1879     }
1880     writer.endArray();  // runs
1881     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_X, fXPos);
1882     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_Y, fYPos);
1883     SkRect bounds = fBlob->bounds();
1884     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1885     MakeJsonRect(writer, bounds);
1886     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1887     MakeJsonPaint(writer, fPaint, urlDataManager);
1888 
1889     SkString desc;
1890     // make the bounds local by applying the x,y
1891     bounds.offset(fXPos, fYPos);
1892     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, bounds)->c_str());
1893 }
1894 
DrawPatchCommand(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)1895 DrawPatchCommand::DrawPatchCommand(const SkPoint  cubics[12],
1896                                    const SkColor  colors[4],
1897                                    const SkPoint  texCoords[4],
1898                                    SkBlendMode    bmode,
1899                                    const SkPaint& paint)
1900         : INHERITED(kDrawPatch_OpType), fBlendMode(bmode) {
1901     memcpy(fCubics, cubics, sizeof(fCubics));
1902     if (colors != nullptr) {
1903         memcpy(fColors, colors, sizeof(fColors));
1904         fColorsPtr = fColors;
1905     } else {
1906         fColorsPtr = nullptr;
1907     }
1908     if (texCoords != nullptr) {
1909         memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
1910         fTexCoordsPtr = fTexCoords;
1911     } else {
1912         fTexCoordsPtr = nullptr;
1913     }
1914     fPaint = paint;
1915 }
1916 
execute(SkCanvas * canvas) const1917 void DrawPatchCommand::execute(SkCanvas* canvas) const {
1918     canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fBlendMode, fPaint);
1919 }
1920 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1921 void DrawPatchCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1922     INHERITED::toJSON(writer, urlDataManager);
1923     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_CUBICS);
1924     for (int i = 0; i < 12; i++) {
1925         MakeJsonPoint(writer, fCubics[i]);
1926     }
1927     writer.endArray();  // cubics
1928     if (fColorsPtr != nullptr) {
1929         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_COLORS);
1930         for (int i = 0; i < 4; i++) {
1931             MakeJsonColor(writer, fColorsPtr[i]);
1932         }
1933         writer.endArray();  // colors
1934     }
1935     if (fTexCoordsPtr != nullptr) {
1936         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS);
1937         for (int i = 0; i < 4; i++) {
1938             MakeJsonPoint(writer, fTexCoords[i]);
1939         }
1940         writer.endArray();  // texCoords
1941     }
1942     // fBlendMode
1943 }
1944 
DrawRectCommand(const SkRect & rect,const SkPaint & paint)1945 DrawRectCommand::DrawRectCommand(const SkRect& rect, const SkPaint& paint)
1946         : INHERITED(kDrawRect_OpType) {
1947     fRect  = rect;
1948     fPaint = paint;
1949 }
1950 
execute(SkCanvas * canvas) const1951 void DrawRectCommand::execute(SkCanvas* canvas) const { canvas->drawRect(fRect, fPaint); }
1952 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1953 void DrawRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1954     INHERITED::toJSON(writer, urlDataManager);
1955     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1956     MakeJsonRect(writer, fRect);
1957     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1958     MakeJsonPaint(writer, fPaint, urlDataManager);
1959 
1960     SkString desc;
1961     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1962 }
1963 
DrawRRectCommand(const SkRRect & rrect,const SkPaint & paint)1964 DrawRRectCommand::DrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
1965         : INHERITED(kDrawRRect_OpType) {
1966     fRRect = rrect;
1967     fPaint = paint;
1968 }
1969 
execute(SkCanvas * canvas) const1970 void DrawRRectCommand::execute(SkCanvas* canvas) const { canvas->drawRRect(fRRect, fPaint); }
1971 
render(SkCanvas * canvas) const1972 bool DrawRRectCommand::render(SkCanvas* canvas) const {
1973     render_rrect(canvas, fRRect);
1974     return true;
1975 }
1976 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1977 void DrawRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1978     INHERITED::toJSON(writer, urlDataManager);
1979     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1980     make_json_rrect(writer, fRRect);
1981     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1982     MakeJsonPaint(writer, fPaint, urlDataManager);
1983 }
1984 
DrawDRRectCommand(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1985 DrawDRRectCommand::DrawDRRectCommand(const SkRRect& outer,
1986                                      const SkRRect& inner,
1987                                      const SkPaint& paint)
1988         : INHERITED(kDrawDRRect_OpType) {
1989     fOuter = outer;
1990     fInner = inner;
1991     fPaint = paint;
1992 }
1993 
execute(SkCanvas * canvas) const1994 void DrawDRRectCommand::execute(SkCanvas* canvas) const {
1995     canvas->drawDRRect(fOuter, fInner, fPaint);
1996 }
1997 
render(SkCanvas * canvas) const1998 bool DrawDRRectCommand::render(SkCanvas* canvas) const {
1999     render_drrect(canvas, fOuter, fInner);
2000     return true;
2001 }
2002 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2003 void DrawDRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2004     INHERITED::toJSON(writer, urlDataManager);
2005     writer.appendName(DEBUGCANVAS_ATTRIBUTE_OUTER);
2006     make_json_rrect(writer, fOuter);
2007     writer.appendName(DEBUGCANVAS_ATTRIBUTE_INNER);
2008     make_json_rrect(writer, fInner);
2009     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
2010     MakeJsonPaint(writer, fPaint, urlDataManager);
2011 }
2012 
DrawShadowCommand(const SkPath & path,const SkDrawShadowRec & rec)2013 DrawShadowCommand::DrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec)
2014         : INHERITED(kDrawShadow_OpType) {
2015     fPath      = path;
2016     fShadowRec = rec;
2017 }
2018 
execute(SkCanvas * canvas) const2019 void DrawShadowCommand::execute(SkCanvas* canvas) const {
2020     canvas->private_draw_shadow_rec(fPath, fShadowRec);
2021 }
2022 
render(SkCanvas * canvas) const2023 bool DrawShadowCommand::render(SkCanvas* canvas) const {
2024     render_shadow(canvas, fPath, fShadowRec);
2025     return true;
2026 }
2027 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2028 void DrawShadowCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2029     INHERITED::toJSON(writer, urlDataManager);
2030 
2031     bool geometricOnly = SkToBool(fShadowRec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
2032     bool transparentOccluder =
2033             SkToBool(fShadowRec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
2034 
2035     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
2036     MakeJsonPath(writer, fPath);
2037     writer.appendName(DEBUGCANVAS_ATTRIBUTE_ZPLANE);
2038     MakeJsonPoint3(writer, fShadowRec.fZPlaneParams);
2039     writer.appendName(DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION);
2040     MakeJsonPoint3(writer, fShadowRec.fLightPos);
2041     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS, fShadowRec.fLightRadius);
2042     writer.appendName(DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR);
2043     MakeJsonColor(writer, fShadowRec.fAmbientColor);
2044     writer.appendName(DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR);
2045     MakeJsonColor(writer, fShadowRec.fSpotColor);
2046     store_bool(writer, DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC, transparentOccluder, false);
2047     store_bool(writer, DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY, geometricOnly, false);
2048 }
2049 
2050 ///////////////////////////////////////////////////////////////////////////////////////////////////
2051 
DrawEdgeAAQuadCommand(const SkRect & rect,const SkPoint clip[],SkCanvas::QuadAAFlags aa,const SkColor4f & color,SkBlendMode mode)2052 DrawEdgeAAQuadCommand::DrawEdgeAAQuadCommand(const SkRect&         rect,
2053                                              const SkPoint         clip[],
2054                                              SkCanvas::QuadAAFlags aa,
2055                                              const SkColor4f&      color,
2056                                              SkBlendMode           mode)
2057         : INHERITED(kDrawEdgeAAQuad_OpType)
2058         , fRect(rect)
2059         , fHasClip(clip != nullptr)
2060         , fAA(aa)
2061         , fColor(color)
2062         , fMode(mode) {
2063     if (clip) {
2064         for (int i = 0; i < 4; ++i) {
2065             fClip[i] = clip[i];
2066         }
2067     }
2068 }
2069 
execute(SkCanvas * canvas) const2070 void DrawEdgeAAQuadCommand::execute(SkCanvas* canvas) const {
2071     canvas->experimental_DrawEdgeAAQuad(fRect, fHasClip ? fClip : nullptr, fAA, fColor, fMode);
2072 }
2073 
DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],int count,const SkPoint dstClips[],const SkMatrix preViewMatrices[],const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)2074 DrawEdgeAAImageSetCommand::DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],
2075                                                      int                           count,
2076                                                      const SkPoint                 dstClips[],
2077                                                      const SkMatrix              preViewMatrices[],
2078                                                      const SkPaint*              paint,
2079                                                      SkCanvas::SrcRectConstraint constraint)
2080         : INHERITED(kDrawEdgeAAImageSet_OpType)
2081         , fSet(count)
2082         , fCount(count)
2083         , fPaint(paint)
2084         , fConstraint(constraint) {
2085     int totalDstClipCount, totalMatrixCount;
2086     SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);
2087 
2088     std::copy_n(set, count, fSet.get());
2089     fDstClips.reset(totalDstClipCount);
2090     std::copy_n(dstClips, totalDstClipCount, fDstClips.get());
2091     fPreViewMatrices.reset(totalMatrixCount);
2092     std::copy_n(preViewMatrices, totalMatrixCount, fPreViewMatrices.get());
2093 }
2094 
execute(SkCanvas * canvas) const2095 void DrawEdgeAAImageSetCommand::execute(SkCanvas* canvas) const {
2096     canvas->experimental_DrawEdgeAAImageSet(fSet.get(),
2097                                             fCount,
2098                                             fDstClips.get(),
2099                                             fPreViewMatrices.get(),
2100                                             fPaint.getMaybeNull(),
2101                                             fConstraint);
2102 }
2103 
2104 ///////////////////////////////////////////////////////////////////////////////////////////////////
2105 
DrawDrawableCommand(SkDrawable * drawable,const SkMatrix * matrix)2106 DrawDrawableCommand::DrawDrawableCommand(SkDrawable* drawable, const SkMatrix* matrix)
2107         : INHERITED(kDrawDrawable_OpType), fDrawable(SkRef(drawable)), fMatrix(matrix) {}
2108 
execute(SkCanvas * canvas) const2109 void DrawDrawableCommand::execute(SkCanvas* canvas) const {
2110     canvas->drawDrawable(fDrawable.get(), fMatrix.getMaybeNull());
2111 }
2112 
2113 ///////////////////////////////////////////////////////////////////////////////////////////////////
2114 
DrawVerticesCommand(sk_sp<SkVertices> vertices,SkBlendMode bmode,const SkPaint & paint)2115 DrawVerticesCommand::DrawVerticesCommand(sk_sp<SkVertices> vertices,
2116                                          SkBlendMode       bmode,
2117                                          const SkPaint&    paint)
2118         : INHERITED(kDrawVertices_OpType)
2119         , fVertices(std::move(vertices))
2120         , fBlendMode(bmode)
2121         , fPaint(paint) {}
2122 
execute(SkCanvas * canvas) const2123 void DrawVerticesCommand::execute(SkCanvas* canvas) const {
2124     canvas->drawVertices(fVertices, fBlendMode, fPaint);
2125 }
2126 
2127 ///////////////////////////////////////////////////////////////////////////////////////////////////
2128 
DrawAtlasCommand(const SkImage * image,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)2129 DrawAtlasCommand::DrawAtlasCommand(const SkImage*  image,
2130                                    const SkRSXform xform[],
2131                                    const SkRect    tex[],
2132                                    const SkColor   colors[],
2133                                    int             count,
2134                                    SkBlendMode     bmode,
2135                                    const SkRect*   cull,
2136                                    const SkPaint*  paint)
2137         : INHERITED(kDrawAtlas_OpType)
2138         , fImage(SkRef(image))
2139         , fXform(xform, count)
2140         , fTex(tex, count)
2141         , fColors(colors, colors ? count : 0)
2142         , fBlendMode(bmode)
2143         , fCull(cull)
2144         , fPaint(paint) {}
2145 
execute(SkCanvas * canvas) const2146 void DrawAtlasCommand::execute(SkCanvas* canvas) const {
2147     canvas->drawAtlas(fImage.get(),
2148                       fXform.begin(),
2149                       fTex.begin(),
2150                       fColors.isEmpty() ? nullptr : fColors.begin(),
2151                       fXform.count(),
2152                       fBlendMode,
2153                       fCull.getMaybeNull(),
2154                       fPaint.getMaybeNull());
2155 }
2156 
2157 ///////////////////////////////////////////////////////////////////////////////////////////////////
2158 
RestoreCommand()2159 RestoreCommand::RestoreCommand() : INHERITED(kRestore_OpType) {}
2160 
execute(SkCanvas * canvas) const2161 void RestoreCommand::execute(SkCanvas* canvas) const { canvas->restore(); }
2162 
SaveCommand()2163 SaveCommand::SaveCommand() : INHERITED(kSave_OpType) {}
2164 
execute(SkCanvas * canvas) const2165 void SaveCommand::execute(SkCanvas* canvas) const { canvas->save(); }
2166 
SaveLayerCommand(const SkCanvas::SaveLayerRec & rec)2167 SaveLayerCommand::SaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
2168         : INHERITED(kSaveLayer_OpType)
2169         , fBounds(rec.fBounds)
2170         , fPaint(rec.fPaint)
2171         , fBackdrop(SkSafeRef(rec.fBackdrop))
2172         , fSaveLayerFlags(rec.fSaveLayerFlags) {}
2173 
execute(SkCanvas * canvas) const2174 void SaveLayerCommand::execute(SkCanvas* canvas) const {
2175     canvas->saveLayer(
2176             SkCanvas::SaveLayerRec(fBounds.getMaybeNull(), fPaint.getMaybeNull(), fSaveLayerFlags));
2177 }
2178 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2179 void SaveLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2180     INHERITED::toJSON(writer, urlDataManager);
2181     if (fBounds.isValid()) {
2182         writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
2183         MakeJsonRect(writer, *fBounds);
2184     }
2185     if (fPaint.isValid()) {
2186         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
2187         MakeJsonPaint(writer, *fPaint, urlDataManager);
2188     }
2189     if (fBackdrop != nullptr) {
2190         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BACKDROP);
2191         flatten(fBackdrop.get(), writer, urlDataManager);
2192         writer.endObject();  // backdrop
2193     }
2194     if (fSaveLayerFlags != 0) {
2195         SkDebugf("unsupported: saveLayer flags\n");
2196         SkASSERT(false);
2197     }
2198 }
2199 
SetMatrixCommand(const SkMatrix & matrix)2200 SetMatrixCommand::SetMatrixCommand(const SkMatrix& matrix) : INHERITED(kSetMatrix_OpType) {
2201     fMatrix = matrix;
2202 }
2203 
execute(SkCanvas * canvas) const2204 void SetMatrixCommand::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); }
2205 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2206 void SetMatrixCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2207     INHERITED::toJSON(writer, urlDataManager);
2208     writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
2209     MakeJsonMatrix(writer, fMatrix);
2210 }
2211