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