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