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