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