• 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 
apply_paint_blend_mode(const SkPaint & paint,SkJSONWriter & writer)365 void apply_paint_blend_mode(const SkPaint& paint, SkJSONWriter& writer) {
366     const auto mode = paint.getBlendMode_or(SkBlendMode::kSrcOver);
367     if (mode != SkBlendMode::kSrcOver) {
368         writer.appendString(DEBUGCANVAS_ATTRIBUTE_BLENDMODE, SkBlendMode_Name(mode));
369     }
370 }
371 
372 };  // namespace
373 
MakeJsonColor(SkJSONWriter & writer,const SkColor color)374 void DrawCommand::MakeJsonColor(SkJSONWriter& writer, const SkColor color) {
375     writer.beginArray(nullptr, false);
376     writer.appendS32(SkColorGetA(color));
377     writer.appendS32(SkColorGetR(color));
378     writer.appendS32(SkColorGetG(color));
379     writer.appendS32(SkColorGetB(color));
380     writer.endArray();
381 }
382 
MakeJsonColor4f(SkJSONWriter & writer,const SkColor4f & color)383 void DrawCommand::MakeJsonColor4f(SkJSONWriter& writer, const SkColor4f& color) {
384     writer.beginArray(nullptr, false);
385     writer.appendFloat(color.fA);
386     writer.appendFloat(color.fR);
387     writer.appendFloat(color.fG);
388     writer.appendFloat(color.fB);
389     writer.endArray();
390 }
391 
MakeJsonPoint(SkJSONWriter & writer,const SkPoint & point)392 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, const SkPoint& point) {
393     writer.beginArray(nullptr, false);
394     writer.appendFloat(point.x());
395     writer.appendFloat(point.y());
396     writer.endArray();
397 }
398 
MakeJsonPoint(SkJSONWriter & writer,SkScalar x,SkScalar y)399 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, SkScalar x, SkScalar y) {
400     writer.beginArray(nullptr, false);
401     writer.appendFloat(x);
402     writer.appendFloat(y);
403     writer.endArray();
404 }
405 
MakeJsonPoint3(SkJSONWriter & writer,const SkPoint3 & point)406 void DrawCommand::MakeJsonPoint3(SkJSONWriter& writer, const SkPoint3& point) {
407     writer.beginArray(nullptr, false);
408     writer.appendFloat(point.x());
409     writer.appendFloat(point.y());
410     writer.appendFloat(point.z());
411     writer.endArray();
412 }
413 
MakeJsonRect(SkJSONWriter & writer,const SkRect & rect)414 void DrawCommand::MakeJsonRect(SkJSONWriter& writer, const SkRect& rect) {
415     writer.beginArray(nullptr, false);
416     writer.appendFloat(rect.left());
417     writer.appendFloat(rect.top());
418     writer.appendFloat(rect.right());
419     writer.appendFloat(rect.bottom());
420     writer.endArray();
421 }
422 
MakeJsonIRect(SkJSONWriter & writer,const SkIRect & rect)423 void DrawCommand::MakeJsonIRect(SkJSONWriter& writer, const SkIRect& rect) {
424     writer.beginArray(nullptr, false);
425     writer.appendS32(rect.left());
426     writer.appendS32(rect.top());
427     writer.appendS32(rect.right());
428     writer.appendS32(rect.bottom());
429     writer.endArray();
430 }
431 
make_json_rrect(SkJSONWriter & writer,const SkRRect & rrect)432 static void make_json_rrect(SkJSONWriter& writer, const SkRRect& rrect) {
433     writer.beginArray(nullptr, false);
434     DrawCommand::MakeJsonRect(writer, rrect.rect());
435     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperLeft_Corner));
436     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperRight_Corner));
437     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerRight_Corner));
438     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerLeft_Corner));
439     writer.endArray();
440 }
441 
MakeJsonMatrix(SkJSONWriter & writer,const SkMatrix & matrix)442 void DrawCommand::MakeJsonMatrix(SkJSONWriter& writer, const SkMatrix& matrix) {
443     writer.beginArray();
444     for (int r = 0; r < 3; ++r) {
445         writer.beginArray(nullptr, false);
446         for (int c = 0; c < 3; ++c) {
447             writer.appendFloat(matrix[r * 3 + c]);
448         }
449         writer.endArray();
450     }
451     writer.endArray();
452 }
453 
MakeJsonMatrix44(SkJSONWriter & writer,const SkM44 & matrix)454 void DrawCommand::MakeJsonMatrix44(SkJSONWriter& writer, const SkM44& matrix) {
455     writer.beginArray();
456     for (int r = 0; r < 4; ++r) {
457         writer.beginArray(nullptr, false);
458         for (int c = 0; c < 4; ++c) {
459             writer.appendFloat(matrix.rc(r, c));
460         }
461         writer.endArray();
462     }
463     writer.endArray();
464 }
465 
MakeJsonPath(SkJSONWriter & writer,const SkPath & path)466 void DrawCommand::MakeJsonPath(SkJSONWriter& writer, const SkPath& path) {
467     writer.beginObject();
468     switch (path.getFillType()) {
469         case SkPathFillType::kWinding:
470             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_WINDING);
471             break;
472         case SkPathFillType::kEvenOdd:
473             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_EVENODD);
474             break;
475         case SkPathFillType::kInverseWinding:
476             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
477                                 DEBUGCANVAS_FILLTYPE_INVERSEWINDING);
478             break;
479         case SkPathFillType::kInverseEvenOdd:
480             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
481                                 DEBUGCANVAS_FILLTYPE_INVERSEEVENODD);
482             break;
483     }
484     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_VERBS);
485     SkPath::Iter iter(path, false);
486     SkPoint      pts[4];
487     SkPath::Verb verb;
488     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
489         if (verb == SkPath::kClose_Verb) {
490             writer.appendString(DEBUGCANVAS_VERB_CLOSE);
491             continue;
492         }
493         writer.beginObject();  // verb
494         switch (verb) {
495             case SkPath::kLine_Verb: {
496                 writer.appendName(DEBUGCANVAS_VERB_LINE);
497                 MakeJsonPoint(writer, pts[1]);
498                 break;
499             }
500             case SkPath::kQuad_Verb: {
501                 writer.beginArray(DEBUGCANVAS_VERB_QUAD);
502                 MakeJsonPoint(writer, pts[1]);
503                 MakeJsonPoint(writer, pts[2]);
504                 writer.endArray();  // quad coords
505                 break;
506             }
507             case SkPath::kCubic_Verb: {
508                 writer.beginArray(DEBUGCANVAS_VERB_CUBIC);
509                 MakeJsonPoint(writer, pts[1]);
510                 MakeJsonPoint(writer, pts[2]);
511                 MakeJsonPoint(writer, pts[3]);
512                 writer.endArray();  // cubic coords
513                 break;
514             }
515             case SkPath::kConic_Verb: {
516                 writer.beginArray(DEBUGCANVAS_VERB_CONIC);
517                 MakeJsonPoint(writer, pts[1]);
518                 MakeJsonPoint(writer, pts[2]);
519                 writer.appendFloat(iter.conicWeight());
520                 writer.endArray();  // conic coords
521                 break;
522             }
523             case SkPath::kMove_Verb: {
524                 writer.appendName(DEBUGCANVAS_VERB_MOVE);
525                 MakeJsonPoint(writer, pts[0]);
526                 break;
527             }
528             case SkPath::kClose_Verb:
529             case SkPath::kDone_Verb:
530                 // Unreachable
531                 break;
532         }
533         writer.endObject();  // verb
534     }
535     writer.endArray();   // verbs
536     writer.endObject();  // path
537 }
538 
MakeJsonRegion(SkJSONWriter & writer,const SkRegion & region)539 void DrawCommand::MakeJsonRegion(SkJSONWriter& writer, const SkRegion& region) {
540     // TODO: Actually serialize the rectangles, rather than just devolving to path
541     SkPath path;
542     region.getBoundaryPath(&path);
543     MakeJsonPath(writer, path);
544 }
545 
clipop_name(SkClipOp op)546 static const char* clipop_name(SkClipOp op) {
547     switch (op) {
548         case SkClipOp::kDifference: return DEBUGCANVAS_CLIPOP_DIFFERENCE;
549         case SkClipOp::kIntersect: return DEBUGCANVAS_CLIPOP_INTERSECT;
550         default: SkASSERT(false); return "<invalid region op>";
551     }
552 }
553 
pointmode_name(SkCanvas::PointMode mode)554 static const char* pointmode_name(SkCanvas::PointMode mode) {
555     switch (mode) {
556         case SkCanvas::kPoints_PointMode: return DEBUGCANVAS_POINTMODE_POINTS;
557         case SkCanvas::kLines_PointMode: return DEBUGCANVAS_POINTMODE_LINES;
558         case SkCanvas::kPolygon_PointMode: return DEBUGCANVAS_POINTMODE_POLYGON;
559         default: SkASSERT(false); return "<invalid point mode>";
560     }
561 }
562 
store_scalar(SkJSONWriter & writer,const char * key,SkScalar value,SkScalar defaultValue)563 static void store_scalar(SkJSONWriter& writer,
564                          const char*   key,
565                          SkScalar      value,
566                          SkScalar      defaultValue) {
567     if (value != defaultValue) {
568         writer.appendFloat(key, value);
569     }
570 }
571 
store_bool(SkJSONWriter & writer,const char * key,bool value,bool defaultValue)572 static void store_bool(SkJSONWriter& writer, const char* key, bool value, bool defaultValue) {
573     if (value != defaultValue) {
574         writer.appendBool(key, value);
575     }
576 }
577 
encode_data(const void * bytes,size_t count,const char * contentType,UrlDataManager & urlDataManager)578 static SkString encode_data(const void*     bytes,
579                             size_t          count,
580                             const char*     contentType,
581                             UrlDataManager& urlDataManager) {
582     sk_sp<SkData> data(SkData::MakeWithCopy(bytes, count));
583     return urlDataManager.addData(data.get(), contentType);
584 }
585 
flatten(const SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)586 void DrawCommand::flatten(const SkFlattenable* flattenable,
587                           SkJSONWriter&        writer,
588                           UrlDataManager&      urlDataManager) {
589     SkBinaryWriteBuffer buffer;
590     flattenable->flatten(buffer);
591     void* data = sk_malloc_throw(buffer.bytesWritten());
592     buffer.writeToMemory(data);
593     SkString url =
594             encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
595     writer.appendString(DEBUGCANVAS_ATTRIBUTE_NAME, flattenable->getTypeName());
596     writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
597 
598     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_VALUES);
599     JsonWriteBuffer jsonBuffer(&writer, &urlDataManager);
600     flattenable->flatten(jsonBuffer);
601     writer.endObject();  // values
602 
603     sk_free(data);
604 }
605 
WritePNG(SkBitmap bitmap,SkWStream & out)606 void DrawCommand::WritePNG(SkBitmap bitmap, SkWStream& out) {
607     SkPixmap pm;
608     SkAssertResult(bitmap.peekPixels(&pm));
609 
610     SkPngEncoder::Options options;
611     options.fZLibLevel   = 1;
612     options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
613     SkPngEncoder::Encode(&out, pm, options);
614 }
615 
616 // flattens an image to a Json stream, also called from shader flatten
flatten(const SkImage & image,SkJSONWriter & writer,UrlDataManager & urlDataManager)617 bool DrawCommand::flatten(const SkImage&  image,
618                           SkJSONWriter&   writer,
619                           UrlDataManager& urlDataManager) {
620     // For MSKP files, there is no need to encode the image,
621     // just report its id.
622     if (urlDataManager.hasImageIndex()) {
623         writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
624         writer.appendU64(urlDataManager.lookupImage(&image));
625         return true;
626     }
627 
628     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
629     size_t       rowBytes = 4 * image.width();
630     SkAutoMalloc buffer(rowBytes * image.height());
631     SkImageInfo  dstInfo =
632             SkImageInfo::Make(image.dimensions(), kN32_SkColorType, kPremul_SkAlphaType);
633     // "cheat" for this debug tool and use image's context
634     GrDirectContext* dContext = nullptr;
635 #if SK_SUPPORT_GPU
636     dContext = GrAsDirectContext(as_IB(&image)->context());
637 #endif
638     if (!image.readPixels(dContext, dstInfo, buffer.get(), rowBytes, 0, 0)) {
639         SkDebugf("DrawCommand::flatten SkImage: readPixels failed\n");
640         writer.endObject();
641         return false;
642     }
643 
644     SkBitmap bm;
645     bm.installPixels(dstInfo, buffer.get(), rowBytes);
646 
647     SkDynamicMemoryWStream out;
648     DrawCommand::WritePNG(bm, out);
649     sk_sp<SkData> encoded = out.detachAsData();
650     if (encoded == nullptr) {
651         SkDebugf("DrawCommand::flatten SkImage: could not encode image as PNG\n");
652         writer.endObject();
653         return false;
654     }
655     auto dataPtr = encoded->data();
656     if (!dataPtr) {
657       SkDebugf("DrawCommand::flatten SkImage: encoding as PNG produced zero length data\n");
658       writer.endObject();
659       return false;
660     }
661     SkString      url = encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager);
662     writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
663     writer.endObject();
664     return true;
665 }
666 
color_type_name(SkColorType colorType)667 static const char* color_type_name(SkColorType colorType) {
668     switch (colorType) {
669         case kARGB_4444_SkColorType: return DEBUGCANVAS_COLORTYPE_ARGB4444;
670         case kRGBA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_RGBA8888;
671         case kBGRA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_BGRA8888;
672         case kRGB_565_SkColorType: return DEBUGCANVAS_COLORTYPE_565;
673         case kGray_8_SkColorType: return DEBUGCANVAS_COLORTYPE_GRAY8;
674         case kAlpha_8_SkColorType: return DEBUGCANVAS_COLORTYPE_ALPHA8;
675         default: SkASSERT(false); return DEBUGCANVAS_COLORTYPE_RGBA8888;
676     }
677 }
678 
alpha_type_name(SkAlphaType alphaType)679 static const char* alpha_type_name(SkAlphaType alphaType) {
680     switch (alphaType) {
681         case kOpaque_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_OPAQUE;
682         case kPremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_PREMUL;
683         case kUnpremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_UNPREMUL;
684         default: SkASSERT(false); return DEBUGCANVAS_ALPHATYPE_OPAQUE;
685     }
686 }
687 
flatten(const SkBitmap & bitmap,SkJSONWriter & writer,UrlDataManager & urlDataManager)688 bool DrawCommand::flatten(const SkBitmap& bitmap,
689                           SkJSONWriter&   writer,
690                           UrlDataManager& urlDataManager) {
691     sk_sp<SkImage> image(bitmap.asImage());
692     writer.appendString(DEBUGCANVAS_ATTRIBUTE_COLOR, color_type_name(bitmap.colorType()));
693     writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, alpha_type_name(bitmap.alphaType()));
694     // Image will appear to have no uses, TODO(nifong): provide the user with a useful explanation
695     bool success = flatten(*image, writer, urlDataManager);
696     return success;
697 }
698 
apply_font_hinting(const SkFont & font,SkJSONWriter & writer)699 static void apply_font_hinting(const SkFont& font, SkJSONWriter& writer) {
700     SkFontHinting hinting = font.getHinting();
701     if (hinting != SkPaintDefaults_Hinting) {
702         switch (hinting) {
703             case SkFontHinting::kNone:
704                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NONE);
705                 break;
706             case SkFontHinting::kSlight:
707                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_SLIGHT);
708                 break;
709             case SkFontHinting::kNormal:
710                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NORMAL);
711                 break;
712             case SkFontHinting::kFull:
713                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_FULL);
714                 break;
715         }
716     }
717 }
718 
apply_font_edging(const SkFont & font,SkJSONWriter & writer)719 static void apply_font_edging(const SkFont& font, SkJSONWriter& writer) {
720     switch (font.getEdging()) {
721         case SkFont::Edging::kAlias:
722             writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ALIAS);
723             break;
724         case SkFont::Edging::kAntiAlias:
725             writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ANTIALIAS);
726             break;
727         case SkFont::Edging::kSubpixelAntiAlias:
728             writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS);
729             break;
730     }
731 }
732 
apply_paint_color(const SkPaint & paint,SkJSONWriter & writer)733 static void apply_paint_color(const SkPaint& paint, SkJSONWriter& writer) {
734     SkColor color = paint.getColor();
735     if (color != SK_ColorBLACK) {
736         writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
737         DrawCommand::MakeJsonColor(writer, color);
738     }
739 }
740 
apply_paint_style(const SkPaint & paint,SkJSONWriter & writer)741 static void apply_paint_style(const SkPaint& paint, SkJSONWriter& writer) {
742     SkPaint::Style style = paint.getStyle();
743     if (style != SkPaint::kFill_Style) {
744         switch (style) {
745             case SkPaint::kStroke_Style: {
746                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKE);
747                 break;
748             }
749             case SkPaint::kStrokeAndFill_Style: {
750                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKEANDFILL);
751                 break;
752             }
753             default: SkASSERT(false);
754         }
755     }
756 }
757 
apply_paint_cap(const SkPaint & paint,SkJSONWriter & writer)758 static void apply_paint_cap(const SkPaint& paint, SkJSONWriter& writer) {
759     SkPaint::Cap cap = paint.getStrokeCap();
760     if (cap != SkPaint::kDefault_Cap) {
761         switch (cap) {
762             case SkPaint::kButt_Cap:
763                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_BUTT);
764                 break;
765             case SkPaint::kRound_Cap:
766                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_ROUND);
767                 break;
768             case SkPaint::kSquare_Cap:
769                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_SQUARE);
770                 break;
771             default: SkASSERT(false);
772         }
773     }
774 }
775 
apply_paint_join(const SkPaint & paint,SkJSONWriter & writer)776 static void apply_paint_join(const SkPaint& paint, SkJSONWriter& writer) {
777     SkPaint::Join join = paint.getStrokeJoin();
778     if (join != SkPaint::kDefault_Join) {
779         switch (join) {
780             case SkPaint::kMiter_Join:
781                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_MITER_JOIN);
782                 break;
783             case SkPaint::kRound_Join:
784                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_ROUND_JOIN);
785                 break;
786             case SkPaint::kBevel_Join:
787                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_BEVEL_JOIN);
788                 break;
789             default: SkASSERT(false);
790         }
791     }
792 }
793 
apply_paint_maskfilter(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)794 static void apply_paint_maskfilter(const SkPaint&  paint,
795                                    SkJSONWriter&   writer,
796                                    UrlDataManager& urlDataManager) {
797     SkMaskFilter* maskFilter = paint.getMaskFilter();
798     if (maskFilter != nullptr) {
799         SkMaskFilterBase::BlurRec blurRec;
800         if (as_MFB(maskFilter)->asABlur(&blurRec)) {
801             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BLUR);
802             writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SIGMA, blurRec.fSigma);
803             switch (blurRec.fStyle) {
804                 case SkBlurStyle::kNormal_SkBlurStyle:
805                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_NORMAL);
806                     break;
807                 case SkBlurStyle::kSolid_SkBlurStyle:
808                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_SOLID);
809                     break;
810                 case SkBlurStyle::kOuter_SkBlurStyle:
811                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_OUTER);
812                     break;
813                 case SkBlurStyle::kInner_SkBlurStyle:
814                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_INNER);
815                     break;
816                 default: SkASSERT(false);
817             }
818             writer.endObject();  // blur
819         } else {
820             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_MASKFILTER);
821             DrawCommand::flatten(maskFilter, writer, urlDataManager);
822             writer.endObject();  // maskFilter
823         }
824     }
825 }
826 
apply_paint_patheffect(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)827 static void apply_paint_patheffect(const SkPaint&  paint,
828                                    SkJSONWriter&   writer,
829                                    UrlDataManager& urlDataManager) {
830     SkPathEffect* pathEffect = paint.getPathEffect();
831     if (pathEffect != nullptr) {
832         SkPathEffect::DashInfo dashInfo;
833         SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
834         if (dashType == SkPathEffect::kDash_DashType) {
835             dashInfo.fIntervals = (SkScalar*)sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
836             pathEffect->asADash(&dashInfo);
837             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_DASHING);
838             writer.beginArray(DEBUGCANVAS_ATTRIBUTE_INTERVALS, false);
839             for (int32_t i = 0; i < dashInfo.fCount; i++) {
840                 writer.appendFloat(dashInfo.fIntervals[i]);
841             }
842             writer.endArray();  // intervals
843             sk_free(dashInfo.fIntervals);
844             writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_PHASE, dashInfo.fPhase);
845             writer.endObject();  // dashing
846         } else {
847             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_PATHEFFECT);
848             DrawCommand::flatten(pathEffect, writer, urlDataManager);
849             writer.endObject();  // pathEffect
850         }
851     }
852 }
853 
apply_font_typeface(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)854 static void apply_font_typeface(const SkFont&   font,
855                                 SkJSONWriter&   writer,
856                                 UrlDataManager& urlDataManager) {
857     SkTypeface* typeface = font.getTypefaceOrDefault();
858     if (typeface != nullptr) {
859         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_TYPEFACE);
860         SkDynamicMemoryWStream buffer;
861         typeface->serialize(&buffer);
862         void* data = sk_malloc_throw(buffer.bytesWritten());
863         buffer.copyTo(data);
864         SkString url = encode_data(
865                 data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
866         writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
867         sk_free(data);
868         writer.endObject();
869     }
870 }
871 
apply_flattenable(const char * key,SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)872 static void apply_flattenable(const char*     key,
873                               SkFlattenable*  flattenable,
874                               SkJSONWriter&   writer,
875                               UrlDataManager& urlDataManager) {
876     if (flattenable != nullptr) {
877         writer.beginObject(key);
878         DrawCommand::flatten(flattenable, writer, urlDataManager);
879         writer.endObject();
880     }
881 }
882 
MakeJsonPaint(SkJSONWriter & writer,const SkPaint & paint,UrlDataManager & urlDataManager)883 void DrawCommand::MakeJsonPaint(SkJSONWriter&   writer,
884                                 const SkPaint&  paint,
885                                 UrlDataManager& urlDataManager) {
886     writer.beginObject();
887     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
888     store_scalar(writer,
889                  DEBUGCANVAS_ATTRIBUTE_STROKEMITER,
890                  paint.getStrokeMiter(),
891                  SkPaintDefaults_MiterLimit);
892     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
893     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
894 
895     apply_paint_color(paint, writer);
896     apply_paint_style(paint, writer);
897     apply_paint_blend_mode(paint, writer);
898     apply_paint_cap(paint, writer);
899     apply_paint_join(paint, writer);
900     apply_paint_patheffect(paint, writer, urlDataManager);
901     apply_paint_maskfilter(paint, writer, urlDataManager);
902     apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, paint.getShader(), writer, urlDataManager);
903     apply_flattenable(
904             DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER, paint.getImageFilter(), writer, urlDataManager);
905     apply_flattenable(
906             DEBUGCANVAS_ATTRIBUTE_COLORFILTER, paint.getColorFilter(), writer, urlDataManager);
907     writer.endObject();  // paint
908 }
909 
MakeJsonFont(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)910 static void MakeJsonFont(const SkFont& font, SkJSONWriter& writer, UrlDataManager& urlDataManager) {
911     writer.beginObject();
912     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, font.isEmbolden(), false);
913     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_LINEARTEXT, font.isLinearMetrics(), false);
914     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, font.isSubpixel(), false);
915     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, font.isEmbeddedBitmaps(), false);
916     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_AUTOHINTING, font.isForceAutoHinting(), false);
917 
918     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSIZE, font.getSize(), SkPaintDefaults_TextSize);
919     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getScaleX(), SK_Scalar1);
920     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getSkewX(), 0.0f);
921     apply_font_edging(font, writer);
922     apply_font_hinting(font, writer);
923     apply_font_typeface(font, writer, urlDataManager);
924     writer.endObject();  // font
925 }
926 
MakeJsonLattice(SkJSONWriter & writer,const SkCanvas::Lattice & lattice)927 void DrawCommand::MakeJsonLattice(SkJSONWriter& writer, const SkCanvas::Lattice& lattice) {
928     writer.beginObject();
929     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT, lattice.fXCount);
930     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT, lattice.fYCount);
931     if (nullptr != lattice.fBounds) {
932         writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
933         MakeJsonIRect(writer, *lattice.fBounds);
934     }
935     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS);
936     for (int i = 0; i < lattice.fXCount; i++) {
937         writer.appendS32(lattice.fXDivs[i]);
938     }
939     writer.endArray();  // xdivs
940     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS);
941     for (int i = 0; i < lattice.fYCount; i++) {
942         writer.appendS32(lattice.fYDivs[i]);
943     }
944     writer.endArray();  // ydivs
945     if (nullptr != lattice.fRectTypes) {
946         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS);
947         int flagCount = 0;
948         for (int row = 0; row < lattice.fYCount + 1; row++) {
949             writer.beginArray();
950             for (int column = 0; column < lattice.fXCount + 1; column++) {
951                 writer.appendS32(lattice.fRectTypes[flagCount++]);
952             }
953             writer.endArray();  // row
954         }
955         writer.endArray();
956     }
957     writer.endObject();
958 }
959 
ClearCommand(SkColor color)960 ClearCommand::ClearCommand(SkColor color) : INHERITED(kClear_OpType) { fColor = color; }
961 
execute(SkCanvas * canvas) const962 void ClearCommand::execute(SkCanvas* canvas) const { canvas->clear(fColor); }
963 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const964 void ClearCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
965     INHERITED::toJSON(writer, urlDataManager);
966     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
967     MakeJsonColor(writer, fColor);
968 }
969 
ClipPathCommand(const SkPath & path,SkClipOp op,bool doAA)970 ClipPathCommand::ClipPathCommand(const SkPath& path, SkClipOp op, bool doAA)
971         : INHERITED(kClipPath_OpType) {
972     fPath = path;
973     fOp   = op;
974     fDoAA = doAA;
975 }
976 
execute(SkCanvas * canvas) const977 void ClipPathCommand::execute(SkCanvas* canvas) const { canvas->clipPath(fPath, fOp, fDoAA); }
978 
render(SkCanvas * canvas) const979 bool ClipPathCommand::render(SkCanvas* canvas) const {
980     render_path(canvas, fPath);
981     return true;
982 }
983 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const984 void ClipPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
985     INHERITED::toJSON(writer, urlDataManager);
986     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
987     MakeJsonPath(writer, fPath);
988     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
989     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
990 }
991 
ClipRegionCommand(const SkRegion & region,SkClipOp op)992 ClipRegionCommand::ClipRegionCommand(const SkRegion& region, SkClipOp op)
993         : INHERITED(kClipRegion_OpType) {
994     fRegion = region;
995     fOp     = op;
996 }
997 
execute(SkCanvas * canvas) const998 void ClipRegionCommand::execute(SkCanvas* canvas) const { canvas->clipRegion(fRegion, fOp); }
999 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1000 void ClipRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1001     INHERITED::toJSON(writer, urlDataManager);
1002     writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1003     MakeJsonRegion(writer, fRegion);
1004     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
1005 }
1006 
ClipRectCommand(const SkRect & rect,SkClipOp op,bool doAA)1007 ClipRectCommand::ClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA)
1008         : INHERITED(kClipRect_OpType) {
1009     fRect = rect;
1010     fOp   = op;
1011     fDoAA = doAA;
1012 }
1013 
execute(SkCanvas * canvas) const1014 void ClipRectCommand::execute(SkCanvas* canvas) const { canvas->clipRect(fRect, fOp, fDoAA); }
1015 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1016 void ClipRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1017     INHERITED::toJSON(writer, urlDataManager);
1018     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1019     MakeJsonRect(writer, fRect);
1020     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
1021     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1022 
1023     SkString desc;
1024     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1025 }
1026 
ClipRRectCommand(const SkRRect & rrect,SkClipOp op,bool doAA)1027 ClipRRectCommand::ClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA)
1028         : INHERITED(kClipRRect_OpType) {
1029     fRRect = rrect;
1030     fOp    = op;
1031     fDoAA  = doAA;
1032 }
1033 
execute(SkCanvas * canvas) const1034 void ClipRRectCommand::execute(SkCanvas* canvas) const { canvas->clipRRect(fRRect, fOp, fDoAA); }
1035 
render(SkCanvas * canvas) const1036 bool ClipRRectCommand::render(SkCanvas* canvas) const {
1037     render_rrect(canvas, fRRect);
1038     return true;
1039 }
1040 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1041 void ClipRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1042     INHERITED::toJSON(writer, urlDataManager);
1043     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1044     make_json_rrect(writer, fRRect);
1045     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
1046     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1047 }
1048 
ClipShaderCommand(sk_sp<SkShader> cs,SkClipOp op)1049 ClipShaderCommand::ClipShaderCommand(sk_sp<SkShader> cs, SkClipOp op)
1050         : INHERITED(kClipShader_OpType) {
1051     fShader = cs;
1052     fOp     = op;
1053 }
1054 
execute(SkCanvas * canvas) const1055 void ClipShaderCommand::execute(SkCanvas* canvas) const { canvas->clipShader(fShader, fOp); }
1056 
render(SkCanvas * canvas) const1057 bool ClipShaderCommand::render(SkCanvas* canvas) const {
1058     SkPaint paint;
1059     paint.setShader(fShader);
1060     canvas->drawPaint(paint);
1061     return true;
1062 }
1063 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1064 void ClipShaderCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1065     INHERITED::toJSON(writer, urlDataManager);
1066     apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, fShader.get(), writer, urlDataManager);
1067     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
1068 }
1069 
ResetClipCommand()1070 ResetClipCommand::ResetClipCommand() : INHERITED(kResetClip_OpType) {}
1071 
execute(SkCanvas * canvas) const1072 void ResetClipCommand::execute(SkCanvas* canvas) const { SkCanvasPriv::ResetClip(canvas); }
1073 
ConcatCommand(const SkMatrix & matrix)1074 ConcatCommand::ConcatCommand(const SkMatrix& matrix) : INHERITED(kConcat_OpType) {
1075     fMatrix = matrix;
1076 }
1077 
execute(SkCanvas * canvas) const1078 void ConcatCommand::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); }
1079 
1080 namespace {
writeMatrixType(SkJSONWriter & writer,const SkMatrix & m)1081     void writeMatrixType(SkJSONWriter& writer, const SkMatrix& m) {
1082         switch (m.getType()) {
1083             case SkMatrix::kTranslate_Mask:
1084                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (translate)");
1085                 break;
1086             case SkMatrix::kScale_Mask:
1087                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (scale)");
1088                 break;
1089             case SkMatrix::kAffine_Mask:
1090                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (rotation or skew)");
1091                 break;
1092             case SkMatrix::kPerspective_Mask:
1093                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (perspective)");
1094                 break;
1095             default:
1096                 break;
1097         }
1098     }
1099 }
1100 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1101 void ConcatCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1102     INHERITED::toJSON(writer, urlDataManager);
1103     writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
1104     MakeJsonMatrix(writer, fMatrix);
1105     writeMatrixType(writer, fMatrix);
1106 }
1107 
Concat44Command(const SkM44 & matrix)1108 Concat44Command::Concat44Command(const SkM44& matrix) : INHERITED(kConcat44_OpType) {
1109     fMatrix = matrix;
1110 }
1111 
execute(SkCanvas * canvas) const1112 void Concat44Command::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); }
1113 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1114 void Concat44Command::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1115     INHERITED::toJSON(writer, urlDataManager);
1116     writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
1117     MakeJsonMatrix44(writer, fMatrix);
1118 }
1119 
1120 ////
1121 
DrawAnnotationCommand(const SkRect & rect,const char key[],sk_sp<SkData> value)1122 DrawAnnotationCommand::DrawAnnotationCommand(const SkRect& rect,
1123                                              const char    key[],
1124                                              sk_sp<SkData> value)
1125         : INHERITED(kDrawAnnotation_OpType), fRect(rect), fKey(key), fValue(std::move(value)) {}
1126 
execute(SkCanvas * canvas) const1127 void DrawAnnotationCommand::execute(SkCanvas* canvas) const {
1128     canvas->drawAnnotation(fRect, fKey.c_str(), fValue);
1129 }
1130 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1131 void DrawAnnotationCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1132     INHERITED::toJSON(writer, urlDataManager);
1133 
1134     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1135     MakeJsonRect(writer, fRect);
1136     writer.appendString("key", fKey.c_str());
1137     if (fValue) {
1138         writer.appendString("value", std::string(
1139             static_cast<const char*>(fValue->data()), fValue->size()
1140             ).c_str());
1141     }
1142 
1143     SkString desc;
1144     str_append(&desc, fRect)->appendf(" %s", fKey.c_str());
1145     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, desc.c_str());
1146 }
1147 
1148 ////
1149 
DrawImageCommand(const SkImage * image,SkScalar left,SkScalar top,const SkSamplingOptions & sampling,const SkPaint * paint)1150 DrawImageCommand::DrawImageCommand(const SkImage*           image,
1151                                    SkScalar                 left,
1152                                    SkScalar                 top,
1153                                    const SkSamplingOptions& sampling,
1154                                    const SkPaint*           paint)
1155         : INHERITED(kDrawImage_OpType)
1156         , fImage(SkRef(image))
1157         , fLeft(left)
1158         , fTop(top)
1159         , fSampling(sampling)
1160         , fPaint(paint) {}
1161 
execute(SkCanvas * canvas) const1162 void DrawImageCommand::execute(SkCanvas* canvas) const {
1163     canvas->drawImage(fImage.get(), fLeft, fTop, fSampling, fPaint.getMaybeNull());
1164 }
1165 
render(SkCanvas * canvas) const1166 bool DrawImageCommand::render(SkCanvas* canvas) const {
1167     SkAutoCanvasRestore acr(canvas, true);
1168     canvas->clear(0xFFFFFFFF);
1169 
1170     xlate_and_scale_to_bounds(
1171             canvas,
1172             SkRect::MakeXYWH(
1173                     fLeft, fTop, SkIntToScalar(fImage->width()), SkIntToScalar(fImage->height())));
1174     this->execute(canvas);
1175     return true;
1176 }
1177 
imageId(UrlDataManager & udm) const1178 uint64_t DrawImageCommand::imageId(UrlDataManager& udm) const {
1179     return udm.lookupImage(fImage.get());
1180 }
1181 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1182 void DrawImageCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1183     INHERITED::toJSON(writer, urlDataManager);
1184     flatten(*fImage, writer, urlDataManager);
1185     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1186     MakeJsonPoint(writer, fLeft, fTop);
1187     if (fPaint.isValid()) {
1188         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1189         MakeJsonPaint(writer, *fPaint, urlDataManager);
1190     }
1191 
1192     writer.appendU32(DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID, fImage->uniqueID());
1193     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_WIDTH, fImage->width());
1194     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_HEIGHT, fImage->height());
1195     switch (fImage->alphaType()) {
1196         case kOpaque_SkAlphaType:
1197             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_OPAQUE);
1198             break;
1199         case kPremul_SkAlphaType:
1200             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_PREMUL);
1201             break;
1202         case kUnpremul_SkAlphaType:
1203             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNPREMUL);
1204             break;
1205         default:
1206             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNKNOWN);
1207             break;
1208     }
1209 }
1210 
DrawImageLatticeCommand(const SkImage * image,const SkCanvas::Lattice & lattice,const SkRect & dst,SkFilterMode filter,const SkPaint * paint)1211 DrawImageLatticeCommand::DrawImageLatticeCommand(const SkImage*           image,
1212                                                  const SkCanvas::Lattice& lattice,
1213                                                  const SkRect&            dst,
1214                                                  SkFilterMode             filter,
1215                                                  const SkPaint*           paint)
1216         : INHERITED(kDrawImageLattice_OpType)
1217         , fImage(SkRef(image))
1218         , fLattice(lattice)
1219         , fDst(dst)
1220         , fFilter(filter)
1221         , fPaint(paint) {}
1222 
execute(SkCanvas * canvas) const1223 void DrawImageLatticeCommand::execute(SkCanvas* canvas) const {
1224     canvas->drawImageLattice(fImage.get(), fLattice, fDst, fFilter, fPaint.getMaybeNull());
1225 }
1226 
render(SkCanvas * canvas) const1227 bool DrawImageLatticeCommand::render(SkCanvas* canvas) const {
1228     SkAutoCanvasRestore acr(canvas, true);
1229     canvas->clear(0xFFFFFFFF);
1230 
1231     xlate_and_scale_to_bounds(canvas, fDst);
1232 
1233     this->execute(canvas);
1234     return true;
1235 }
1236 
imageId(UrlDataManager & udm) const1237 uint64_t DrawImageLatticeCommand::imageId(UrlDataManager& udm) const {
1238     return udm.lookupImage(fImage.get());
1239 }
1240 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1241 void DrawImageLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1242     INHERITED::toJSON(writer, urlDataManager);
1243     flatten(*fImage, writer, urlDataManager);
1244     writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
1245     MakeJsonLattice(writer, fLattice);
1246     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1247     MakeJsonRect(writer, fDst);
1248     if (fPaint.isValid()) {
1249         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1250         MakeJsonPaint(writer, *fPaint, urlDataManager);
1251     }
1252 
1253     SkString desc;
1254     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1255 }
1256 
DrawImageRectCommand(const SkImage * image,const SkRect & src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1257 DrawImageRectCommand::DrawImageRectCommand(const SkImage*              image,
1258                                            const SkRect&               src,
1259                                            const SkRect&               dst,
1260                                            const SkSamplingOptions&    sampling,
1261                                            const SkPaint*              paint,
1262                                            SkCanvas::SrcRectConstraint constraint)
1263         : INHERITED(kDrawImageRect_OpType)
1264         , fImage(SkRef(image))
1265         , fSrc(src)
1266         , fDst(dst)
1267         , fSampling(sampling)
1268         , fPaint(paint)
1269         , fConstraint(constraint) {}
1270 
execute(SkCanvas * canvas) const1271 void DrawImageRectCommand::execute(SkCanvas* canvas) const {
1272     canvas->drawImageRect(fImage.get(), fSrc, fDst, fSampling, fPaint.getMaybeNull(), fConstraint);
1273 }
1274 
render(SkCanvas * canvas) const1275 bool DrawImageRectCommand::render(SkCanvas* canvas) const {
1276     SkAutoCanvasRestore acr(canvas, true);
1277     canvas->clear(0xFFFFFFFF);
1278 
1279     xlate_and_scale_to_bounds(canvas, fDst);
1280 
1281     this->execute(canvas);
1282     return true;
1283 }
1284 
imageId(UrlDataManager & udm) const1285 uint64_t DrawImageRectCommand::imageId(UrlDataManager& udm) const {
1286     return udm.lookupImage(fImage.get());
1287 }
1288 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1289 void DrawImageRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1290     INHERITED::toJSON(writer, urlDataManager);
1291     flatten(*fImage, writer, urlDataManager);
1292     writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1293     MakeJsonRect(writer, fSrc);
1294     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1295     MakeJsonRect(writer, fDst);
1296     if (fPaint.isValid()) {
1297         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1298         MakeJsonPaint(writer, *fPaint, urlDataManager);
1299     }
1300     if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1301         writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1302     }
1303 
1304     SkString desc;
1305     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1306 }
1307 
DrawImageRectLayerCommand(DebugLayerManager * layerManager,const int nodeId,const int frame,const SkRect & src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1308 DrawImageRectLayerCommand::DrawImageRectLayerCommand(DebugLayerManager*    layerManager,
1309                                                      const int                   nodeId,
1310                                                      const int                   frame,
1311                                                      const SkRect&               src,
1312                                                      const SkRect&               dst,
1313                                                      const SkSamplingOptions&    sampling,
1314                                                      const SkPaint*              paint,
1315                                                      SkCanvas::SrcRectConstraint constraint)
1316         : INHERITED(kDrawImageRectLayer_OpType)
1317         , fLayerManager(layerManager)
1318         , fNodeId(nodeId)
1319         , fFrame(frame)
1320         , fSrc(src)
1321         , fDst(dst)
1322         , fSampling(sampling)
1323         , fPaint(paint)
1324         , fConstraint(constraint) {}
1325 
execute(SkCanvas * canvas) const1326 void DrawImageRectLayerCommand::execute(SkCanvas* canvas) const {
1327     sk_sp<SkImage> snapshot = fLayerManager->getLayerAsImage(fNodeId, fFrame);
1328     canvas->drawImageRect(snapshot.get(), fSrc, fDst, SkSamplingOptions(), fPaint.getMaybeNull(), fConstraint);
1329 }
1330 
render(SkCanvas * canvas) const1331 bool DrawImageRectLayerCommand::render(SkCanvas* canvas) const {
1332     SkAutoCanvasRestore acr(canvas, true);
1333     canvas->clear(0xFFFFFFFF);
1334 
1335     xlate_and_scale_to_bounds(canvas, fDst);
1336 
1337     this->execute(canvas);
1338     return true;
1339 }
1340 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1341 void DrawImageRectLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1342     INHERITED::toJSON(writer, urlDataManager);
1343 
1344     // Don't append an image attribute here, the image can be rendered in as many different ways
1345     // as there are commands in the layer, at least. the urlDataManager would save each one under
1346     // a different URL.
1347     // Append the node id, and the layer inspector of the debugger will know what to do with it.
1348     writer.appendS64(DEBUGCANVAS_ATTRIBUTE_LAYERNODEID, fNodeId);
1349 
1350     writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1351     MakeJsonRect(writer, fSrc);
1352 
1353     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1354     MakeJsonRect(writer, fDst);
1355     if (fPaint.isValid()) {
1356         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1357         MakeJsonPaint(writer, *fPaint, urlDataManager);
1358     }
1359     if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1360         writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1361     }
1362 
1363     SkString desc;
1364     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1365 }
1366 
DrawOvalCommand(const SkRect & oval,const SkPaint & paint)1367 DrawOvalCommand::DrawOvalCommand(const SkRect& oval, const SkPaint& paint)
1368         : INHERITED(kDrawOval_OpType) {
1369     fOval  = oval;
1370     fPaint = paint;
1371 }
1372 
execute(SkCanvas * canvas) const1373 void DrawOvalCommand::execute(SkCanvas* canvas) const { canvas->drawOval(fOval, fPaint); }
1374 
render(SkCanvas * canvas) const1375 bool DrawOvalCommand::render(SkCanvas* canvas) const {
1376     canvas->clear(0xFFFFFFFF);
1377     canvas->save();
1378 
1379     xlate_and_scale_to_bounds(canvas, fOval);
1380 
1381     SkPaint p;
1382     p.setColor(SK_ColorBLACK);
1383     p.setStyle(SkPaint::kStroke_Style);
1384 
1385     canvas->drawOval(fOval, p);
1386     canvas->restore();
1387 
1388     return true;
1389 }
1390 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1391 void DrawOvalCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1392     INHERITED::toJSON(writer, urlDataManager);
1393     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1394     MakeJsonRect(writer, fOval);
1395     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1396     MakeJsonPaint(writer, fPaint, urlDataManager);
1397 }
1398 
DrawArcCommand(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)1399 DrawArcCommand::DrawArcCommand(const SkRect&  oval,
1400                                SkScalar       startAngle,
1401                                SkScalar       sweepAngle,
1402                                bool           useCenter,
1403                                const SkPaint& paint)
1404         : INHERITED(kDrawArc_OpType) {
1405     fOval       = oval;
1406     fStartAngle = startAngle;
1407     fSweepAngle = sweepAngle;
1408     fUseCenter  = useCenter;
1409     fPaint      = paint;
1410 }
1411 
execute(SkCanvas * canvas) const1412 void DrawArcCommand::execute(SkCanvas* canvas) const {
1413     canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, fPaint);
1414 }
1415 
render(SkCanvas * canvas) const1416 bool DrawArcCommand::render(SkCanvas* canvas) const {
1417     canvas->clear(0xFFFFFFFF);
1418     canvas->save();
1419 
1420     xlate_and_scale_to_bounds(canvas, fOval);
1421 
1422     SkPaint p;
1423     p.setColor(SK_ColorBLACK);
1424     p.setStyle(SkPaint::kStroke_Style);
1425 
1426     canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, p);
1427     canvas->restore();
1428 
1429     return true;
1430 }
1431 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1432 void DrawArcCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1433     INHERITED::toJSON(writer, urlDataManager);
1434     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1435     MakeJsonRect(writer, fOval);
1436     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_STARTANGLE, fStartAngle);
1437     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE, fSweepAngle);
1438     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_USECENTER, fUseCenter);
1439     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1440     MakeJsonPaint(writer, fPaint, urlDataManager);
1441 }
1442 
DrawPaintCommand(const SkPaint & paint)1443 DrawPaintCommand::DrawPaintCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1444     fPaint = paint;
1445 }
1446 
execute(SkCanvas * canvas) const1447 void DrawPaintCommand::execute(SkCanvas* canvas) const { canvas->drawPaint(fPaint); }
1448 
render(SkCanvas * canvas) const1449 bool DrawPaintCommand::render(SkCanvas* canvas) const {
1450     canvas->clear(0xFFFFFFFF);
1451     canvas->drawPaint(fPaint);
1452     return true;
1453 }
1454 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1455 void DrawPaintCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1456     INHERITED::toJSON(writer, urlDataManager);
1457     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1458     MakeJsonPaint(writer, fPaint, urlDataManager);
1459 }
1460 
DrawBehindCommand(const SkPaint & paint)1461 DrawBehindCommand::DrawBehindCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1462     fPaint = paint;
1463 }
1464 
execute(SkCanvas * canvas) const1465 void DrawBehindCommand::execute(SkCanvas* canvas) const {
1466     SkCanvasPriv::DrawBehind(canvas, fPaint);
1467 }
1468 
render(SkCanvas * canvas) const1469 bool DrawBehindCommand::render(SkCanvas* canvas) const {
1470     canvas->clear(0xFFFFFFFF);
1471     SkCanvasPriv::DrawBehind(canvas, fPaint);
1472     return true;
1473 }
1474 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1475 void DrawBehindCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1476     INHERITED::toJSON(writer, urlDataManager);
1477     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1478     MakeJsonPaint(writer, fPaint, urlDataManager);
1479 }
1480 
DrawPathCommand(const SkPath & path,const SkPaint & paint)1481 DrawPathCommand::DrawPathCommand(const SkPath& path, const SkPaint& paint)
1482         : INHERITED(kDrawPath_OpType) {
1483     fPath  = path;
1484     fPaint = paint;
1485 }
1486 
execute(SkCanvas * canvas) const1487 void DrawPathCommand::execute(SkCanvas* canvas) const { canvas->drawPath(fPath, fPaint); }
1488 
render(SkCanvas * canvas) const1489 bool DrawPathCommand::render(SkCanvas* canvas) const {
1490     render_path(canvas, fPath);
1491     return true;
1492 }
1493 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1494 void DrawPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1495     INHERITED::toJSON(writer, urlDataManager);
1496     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1497     MakeJsonPath(writer, fPath);
1498     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1499     MakeJsonPaint(writer, fPaint, urlDataManager);
1500 }
1501 
DrawRegionCommand(const SkRegion & region,const SkPaint & paint)1502 DrawRegionCommand::DrawRegionCommand(const SkRegion& region, const SkPaint& paint)
1503         : INHERITED(kDrawRegion_OpType) {
1504     fRegion = region;
1505     fPaint  = paint;
1506 }
1507 
execute(SkCanvas * canvas) const1508 void DrawRegionCommand::execute(SkCanvas* canvas) const { canvas->drawRegion(fRegion, fPaint); }
1509 
render(SkCanvas * canvas) const1510 bool DrawRegionCommand::render(SkCanvas* canvas) const {
1511     render_region(canvas, fRegion);
1512     return true;
1513 }
1514 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1515 void DrawRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1516     INHERITED::toJSON(writer, urlDataManager);
1517     writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1518     MakeJsonRegion(writer, fRegion);
1519     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1520     MakeJsonPaint(writer, fPaint, urlDataManager);
1521 }
1522 
BeginDrawPictureCommand(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)1523 BeginDrawPictureCommand::BeginDrawPictureCommand(const SkPicture* picture,
1524                                                  const SkMatrix*  matrix,
1525                                                  const SkPaint*   paint)
1526         : INHERITED(kBeginDrawPicture_OpType)
1527         , fPicture(SkRef(picture))
1528         , fMatrix(matrix)
1529         , fPaint(paint) {}
1530 
execute(SkCanvas * canvas) const1531 void BeginDrawPictureCommand::execute(SkCanvas* canvas) const {
1532     if (fPaint.isValid()) {
1533         SkRect bounds = fPicture->cullRect();
1534         if (fMatrix.isValid()) {
1535             fMatrix->mapRect(&bounds);
1536         }
1537         canvas->saveLayer(&bounds, fPaint.get());
1538     }
1539 
1540     if (fMatrix.isValid()) {
1541         if (!fPaint.isValid()) {
1542             canvas->save();
1543         }
1544         canvas->concat(*fMatrix);
1545     }
1546 }
1547 
render(SkCanvas * canvas) const1548 bool BeginDrawPictureCommand::render(SkCanvas* canvas) const {
1549     canvas->clear(0xFFFFFFFF);
1550     canvas->save();
1551 
1552     xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
1553 
1554     canvas->drawPicture(fPicture.get());
1555 
1556     canvas->restore();
1557 
1558     return true;
1559 }
1560 
EndDrawPictureCommand(bool restore)1561 EndDrawPictureCommand::EndDrawPictureCommand(bool restore)
1562         : INHERITED(kEndDrawPicture_OpType), fRestore(restore) {}
1563 
execute(SkCanvas * canvas) const1564 void EndDrawPictureCommand::execute(SkCanvas* canvas) const {
1565     if (fRestore) {
1566         canvas->restore();
1567     }
1568 }
1569 
DrawPointsCommand(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1570 DrawPointsCommand::DrawPointsCommand(SkCanvas::PointMode mode,
1571                                      size_t              count,
1572                                      const SkPoint       pts[],
1573                                      const SkPaint&      paint)
1574         : INHERITED(kDrawPoints_OpType), fMode(mode), fPts(pts, count), fPaint(paint) {}
1575 
execute(SkCanvas * canvas) const1576 void DrawPointsCommand::execute(SkCanvas* canvas) const {
1577     canvas->drawPoints(fMode, fPts.count(), fPts.begin(), fPaint);
1578 }
1579 
render(SkCanvas * canvas) const1580 bool DrawPointsCommand::render(SkCanvas* canvas) const {
1581     canvas->clear(0xFFFFFFFF);
1582     canvas->save();
1583 
1584     SkRect bounds;
1585 
1586     bounds.setEmpty();
1587     for (int i = 0; i < fPts.count(); ++i) {
1588         SkRectPriv::GrowToInclude(&bounds, fPts[i]);
1589     }
1590 
1591     xlate_and_scale_to_bounds(canvas, bounds);
1592 
1593     SkPaint p;
1594     p.setColor(SK_ColorBLACK);
1595     p.setStyle(SkPaint::kStroke_Style);
1596 
1597     canvas->drawPoints(fMode, fPts.count(), fPts.begin(), p);
1598     canvas->restore();
1599 
1600     return true;
1601 }
1602 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1603 void DrawPointsCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1604     INHERITED::toJSON(writer, urlDataManager);
1605     writer.appendString(DEBUGCANVAS_ATTRIBUTE_MODE, pointmode_name(fMode));
1606     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POINTS);
1607     for (int i = 0; i < fPts.count(); i++) {
1608         MakeJsonPoint(writer, fPts[i]);
1609     }
1610     writer.endArray();  // points
1611     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1612     MakeJsonPaint(writer, fPaint, urlDataManager);
1613 }
1614 
DrawTextBlobCommand(sk_sp<SkTextBlob> blob,SkScalar x,SkScalar y,const SkPaint & paint)1615 DrawTextBlobCommand::DrawTextBlobCommand(sk_sp<SkTextBlob> blob,
1616                                          SkScalar          x,
1617                                          SkScalar          y,
1618                                          const SkPaint&    paint)
1619         : INHERITED(kDrawTextBlob_OpType)
1620         , fBlob(std::move(blob))
1621         , fXPos(x)
1622         , fYPos(y)
1623         , fPaint(paint) {}
1624 
execute(SkCanvas * canvas) const1625 void DrawTextBlobCommand::execute(SkCanvas* canvas) const {
1626     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1627 }
1628 
render(SkCanvas * canvas) const1629 bool DrawTextBlobCommand::render(SkCanvas* canvas) const {
1630     canvas->clear(SK_ColorWHITE);
1631     canvas->save();
1632 
1633     SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
1634     xlate_and_scale_to_bounds(canvas, bounds);
1635 
1636     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1637 
1638     canvas->restore();
1639 
1640     return true;
1641 }
1642 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1643 void DrawTextBlobCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1644     INHERITED::toJSON(writer, urlDataManager);
1645     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_RUNS);
1646     SkTextBlobRunIterator iter(fBlob.get());
1647     while (!iter.done()) {
1648         writer.beginObject();  // run
1649         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_GLYPHS);
1650         for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1651             writer.appendU32(iter.glyphs()[i]);
1652         }
1653         writer.endArray();  // glyphs
1654         if (iter.positioning() != SkTextBlobRunIterator::kDefault_Positioning) {
1655             writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POSITIONS);
1656             const SkScalar* iterPositions = iter.pos();
1657             for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1658                 switch (iter.positioning()) {
1659                     case SkTextBlobRunIterator::kFull_Positioning:
1660                         MakeJsonPoint(writer, iterPositions[i * 2], iterPositions[i * 2 + 1]);
1661                         break;
1662                     case SkTextBlobRunIterator::kHorizontal_Positioning:
1663                         writer.appendFloat(iterPositions[i]);
1664                         break;
1665                     case SkTextBlobRunIterator::kDefault_Positioning: break;
1666                     case SkTextBlobRunIterator::kRSXform_Positioning:
1667                         // TODO_RSXFORM_BLOB
1668                         break;
1669                 }
1670             }
1671             writer.endArray();  // positions
1672         }
1673         writer.appendName(DEBUGCANVAS_ATTRIBUTE_FONT);
1674         MakeJsonFont(iter.font(), writer, urlDataManager);
1675         writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1676         MakeJsonPoint(writer, iter.offset());
1677 
1678         writer.endObject();  // run
1679         iter.next();
1680     }
1681     writer.endArray();  // runs
1682     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_X, fXPos);
1683     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_Y, fYPos);
1684     SkRect bounds = fBlob->bounds();
1685     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1686     MakeJsonRect(writer, bounds);
1687     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1688     MakeJsonPaint(writer, fPaint, urlDataManager);
1689 
1690     SkString desc;
1691     // make the bounds local by applying the x,y
1692     bounds.offset(fXPos, fYPos);
1693     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, bounds)->c_str());
1694 }
1695 
DrawPatchCommand(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)1696 DrawPatchCommand::DrawPatchCommand(const SkPoint  cubics[12],
1697                                    const SkColor  colors[4],
1698                                    const SkPoint  texCoords[4],
1699                                    SkBlendMode    bmode,
1700                                    const SkPaint& paint)
1701         : INHERITED(kDrawPatch_OpType), fBlendMode(bmode) {
1702     memcpy(fCubics, cubics, sizeof(fCubics));
1703     if (colors != nullptr) {
1704         memcpy(fColors, colors, sizeof(fColors));
1705         fColorsPtr = fColors;
1706     } else {
1707         fColorsPtr = nullptr;
1708     }
1709     if (texCoords != nullptr) {
1710         memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
1711         fTexCoordsPtr = fTexCoords;
1712     } else {
1713         fTexCoordsPtr = nullptr;
1714     }
1715     fPaint = paint;
1716 }
1717 
execute(SkCanvas * canvas) const1718 void DrawPatchCommand::execute(SkCanvas* canvas) const {
1719     canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fBlendMode, fPaint);
1720 }
1721 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1722 void DrawPatchCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1723     INHERITED::toJSON(writer, urlDataManager);
1724     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_CUBICS);
1725     for (int i = 0; i < 12; i++) {
1726         MakeJsonPoint(writer, fCubics[i]);
1727     }
1728     writer.endArray();  // cubics
1729     if (fColorsPtr != nullptr) {
1730         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_COLORS);
1731         for (int i = 0; i < 4; i++) {
1732             MakeJsonColor(writer, fColorsPtr[i]);
1733         }
1734         writer.endArray();  // colors
1735     }
1736     if (fTexCoordsPtr != nullptr) {
1737         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS);
1738         for (int i = 0; i < 4; i++) {
1739             MakeJsonPoint(writer, fTexCoords[i]);
1740         }
1741         writer.endArray();  // texCoords
1742     }
1743     // fBlendMode
1744 }
1745 
DrawRectCommand(const SkRect & rect,const SkPaint & paint)1746 DrawRectCommand::DrawRectCommand(const SkRect& rect, const SkPaint& paint)
1747         : INHERITED(kDrawRect_OpType) {
1748     fRect  = rect;
1749     fPaint = paint;
1750 }
1751 
execute(SkCanvas * canvas) const1752 void DrawRectCommand::execute(SkCanvas* canvas) const { canvas->drawRect(fRect, fPaint); }
1753 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1754 void DrawRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1755     INHERITED::toJSON(writer, urlDataManager);
1756     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1757     MakeJsonRect(writer, fRect);
1758     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1759     MakeJsonPaint(writer, fPaint, urlDataManager);
1760 
1761     SkString desc;
1762     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1763 }
1764 
DrawRRectCommand(const SkRRect & rrect,const SkPaint & paint)1765 DrawRRectCommand::DrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
1766         : INHERITED(kDrawRRect_OpType) {
1767     fRRect = rrect;
1768     fPaint = paint;
1769 }
1770 
execute(SkCanvas * canvas) const1771 void DrawRRectCommand::execute(SkCanvas* canvas) const { canvas->drawRRect(fRRect, fPaint); }
1772 
render(SkCanvas * canvas) const1773 bool DrawRRectCommand::render(SkCanvas* canvas) const {
1774     render_rrect(canvas, fRRect);
1775     return true;
1776 }
1777 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1778 void DrawRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1779     INHERITED::toJSON(writer, urlDataManager);
1780     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1781     make_json_rrect(writer, fRRect);
1782     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1783     MakeJsonPaint(writer, fPaint, urlDataManager);
1784 }
1785 
DrawDRRectCommand(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1786 DrawDRRectCommand::DrawDRRectCommand(const SkRRect& outer,
1787                                      const SkRRect& inner,
1788                                      const SkPaint& paint)
1789         : INHERITED(kDrawDRRect_OpType) {
1790     fOuter = outer;
1791     fInner = inner;
1792     fPaint = paint;
1793 }
1794 
execute(SkCanvas * canvas) const1795 void DrawDRRectCommand::execute(SkCanvas* canvas) const {
1796     canvas->drawDRRect(fOuter, fInner, fPaint);
1797 }
1798 
render(SkCanvas * canvas) const1799 bool DrawDRRectCommand::render(SkCanvas* canvas) const {
1800     render_drrect(canvas, fOuter, fInner);
1801     return true;
1802 }
1803 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1804 void DrawDRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1805     INHERITED::toJSON(writer, urlDataManager);
1806     writer.appendName(DEBUGCANVAS_ATTRIBUTE_OUTER);
1807     make_json_rrect(writer, fOuter);
1808     writer.appendName(DEBUGCANVAS_ATTRIBUTE_INNER);
1809     make_json_rrect(writer, fInner);
1810     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1811     MakeJsonPaint(writer, fPaint, urlDataManager);
1812 }
1813 
DrawShadowCommand(const SkPath & path,const SkDrawShadowRec & rec)1814 DrawShadowCommand::DrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec)
1815         : INHERITED(kDrawShadow_OpType) {
1816     fPath      = path;
1817     fShadowRec = rec;
1818 }
1819 
execute(SkCanvas * canvas) const1820 void DrawShadowCommand::execute(SkCanvas* canvas) const {
1821     canvas->private_draw_shadow_rec(fPath, fShadowRec);
1822 }
1823 
render(SkCanvas * canvas) const1824 bool DrawShadowCommand::render(SkCanvas* canvas) const {
1825     render_shadow(canvas, fPath, fShadowRec);
1826     return true;
1827 }
1828 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1829 void DrawShadowCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1830     INHERITED::toJSON(writer, urlDataManager);
1831 
1832     bool geometricOnly = SkToBool(fShadowRec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
1833     bool transparentOccluder =
1834             SkToBool(fShadowRec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1835 
1836     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1837     MakeJsonPath(writer, fPath);
1838     writer.appendName(DEBUGCANVAS_ATTRIBUTE_ZPLANE);
1839     MakeJsonPoint3(writer, fShadowRec.fZPlaneParams);
1840     writer.appendName(DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION);
1841     MakeJsonPoint3(writer, fShadowRec.fLightPos);
1842     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS, fShadowRec.fLightRadius);
1843     writer.appendName(DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR);
1844     MakeJsonColor(writer, fShadowRec.fAmbientColor);
1845     writer.appendName(DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR);
1846     MakeJsonColor(writer, fShadowRec.fSpotColor);
1847     store_bool(writer, DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC, transparentOccluder, false);
1848     store_bool(writer, DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY, geometricOnly, false);
1849 }
1850 
1851 ///////////////////////////////////////////////////////////////////////////////////////////////////
1852 
DrawEdgeAAQuadCommand(const SkRect & rect,const SkPoint clip[],SkCanvas::QuadAAFlags aa,const SkColor4f & color,SkBlendMode mode)1853 DrawEdgeAAQuadCommand::DrawEdgeAAQuadCommand(const SkRect&         rect,
1854                                              const SkPoint         clip[],
1855                                              SkCanvas::QuadAAFlags aa,
1856                                              const SkColor4f&      color,
1857                                              SkBlendMode           mode)
1858         : INHERITED(kDrawEdgeAAQuad_OpType)
1859         , fRect(rect)
1860         , fHasClip(clip != nullptr)
1861         , fAA(aa)
1862         , fColor(color)
1863         , fMode(mode) {
1864     if (clip) {
1865         for (int i = 0; i < 4; ++i) {
1866             fClip[i] = clip[i];
1867         }
1868     }
1869 }
1870 
execute(SkCanvas * canvas) const1871 void DrawEdgeAAQuadCommand::execute(SkCanvas* canvas) const {
1872     canvas->experimental_DrawEdgeAAQuad(fRect, fHasClip ? fClip : nullptr, fAA, fColor, fMode);
1873 }
1874 
DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],int count,const SkPoint dstClips[],const SkMatrix preViewMatrices[],const SkSamplingOptions & sampling,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1875 DrawEdgeAAImageSetCommand::DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],
1876                                                      int                           count,
1877                                                      const SkPoint                 dstClips[],
1878                                                      const SkMatrix              preViewMatrices[],
1879                                                      const SkSamplingOptions&    sampling,
1880                                                      const SkPaint*              paint,
1881                                                      SkCanvas::SrcRectConstraint constraint)
1882         : INHERITED(kDrawEdgeAAImageSet_OpType)
1883         , fSet(count)
1884         , fCount(count)
1885         , fSampling(sampling)
1886         , fPaint(paint)
1887         , fConstraint(constraint) {
1888     int totalDstClipCount, totalMatrixCount;
1889     SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);
1890 
1891     std::copy_n(set, count, fSet.get());
1892     fDstClips.reset(totalDstClipCount);
1893     std::copy_n(dstClips, totalDstClipCount, fDstClips.get());
1894     fPreViewMatrices.reset(totalMatrixCount);
1895     std::copy_n(preViewMatrices, totalMatrixCount, fPreViewMatrices.get());
1896 }
1897 
execute(SkCanvas * canvas) const1898 void DrawEdgeAAImageSetCommand::execute(SkCanvas* canvas) const {
1899     canvas->experimental_DrawEdgeAAImageSet(fSet.get(),
1900                                             fCount,
1901                                             fDstClips.get(),
1902                                             fPreViewMatrices.get(),
1903                                             fSampling,
1904                                             fPaint.getMaybeNull(),
1905                                             fConstraint);
1906 }
1907 
1908 ///////////////////////////////////////////////////////////////////////////////////////////////////
1909 
DrawDrawableCommand(SkDrawable * drawable,const SkMatrix * matrix)1910 DrawDrawableCommand::DrawDrawableCommand(SkDrawable* drawable, const SkMatrix* matrix)
1911         : INHERITED(kDrawDrawable_OpType), fDrawable(SkRef(drawable)), fMatrix(matrix) {}
1912 
execute(SkCanvas * canvas) const1913 void DrawDrawableCommand::execute(SkCanvas* canvas) const {
1914     canvas->drawDrawable(fDrawable.get(), fMatrix.getMaybeNull());
1915 }
1916 
1917 ///////////////////////////////////////////////////////////////////////////////////////////////////
1918 
DrawVerticesCommand(sk_sp<SkVertices> vertices,SkBlendMode bmode,const SkPaint & paint)1919 DrawVerticesCommand::DrawVerticesCommand(sk_sp<SkVertices> vertices,
1920                                          SkBlendMode       bmode,
1921                                          const SkPaint&    paint)
1922         : INHERITED(kDrawVertices_OpType)
1923         , fVertices(std::move(vertices))
1924         , fBlendMode(bmode)
1925         , fPaint(paint) {}
1926 
execute(SkCanvas * canvas) const1927 void DrawVerticesCommand::execute(SkCanvas* canvas) const {
1928     canvas->drawVertices(fVertices, fBlendMode, fPaint);
1929 }
1930 
1931 ///////////////////////////////////////////////////////////////////////////////////////////////////
1932 
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)1933 DrawAtlasCommand::DrawAtlasCommand(const SkImage*  image,
1934                                    const SkRSXform xform[],
1935                                    const SkRect    tex[],
1936                                    const SkColor   colors[],
1937                                    int             count,
1938                                    SkBlendMode     bmode,
1939                                    const SkSamplingOptions& sampling,
1940                                    const SkRect*   cull,
1941                                    const SkPaint*  paint)
1942         : INHERITED(kDrawAtlas_OpType)
1943         , fImage(SkRef(image))
1944         , fXform(xform, count)
1945         , fTex(tex, count)
1946         , fColors(colors, colors ? count : 0)
1947         , fBlendMode(bmode)
1948         , fSampling(sampling)
1949         , fCull(cull)
1950         , fPaint(paint) {}
1951 
execute(SkCanvas * canvas) const1952 void DrawAtlasCommand::execute(SkCanvas* canvas) const {
1953     canvas->drawAtlas(fImage.get(),
1954                       fXform.begin(),
1955                       fTex.begin(),
1956                       fColors.isEmpty() ? nullptr : fColors.begin(),
1957                       fXform.count(),
1958                       fBlendMode,
1959                       fSampling,
1960                       fCull.getMaybeNull(),
1961                       fPaint.getMaybeNull());
1962 }
1963 
1964 ///////////////////////////////////////////////////////////////////////////////////////////////////
1965 
RestoreCommand()1966 RestoreCommand::RestoreCommand() : INHERITED(kRestore_OpType) {}
1967 
execute(SkCanvas * canvas) const1968 void RestoreCommand::execute(SkCanvas* canvas) const { canvas->restore(); }
1969 
SaveCommand()1970 SaveCommand::SaveCommand() : INHERITED(kSave_OpType) {}
1971 
execute(SkCanvas * canvas) const1972 void SaveCommand::execute(SkCanvas* canvas) const { canvas->save(); }
1973 
SaveLayerCommand(const SkCanvas::SaveLayerRec & rec)1974 SaveLayerCommand::SaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
1975         : INHERITED(kSaveLayer_OpType)
1976         , fBounds(rec.fBounds)
1977         , fPaint(rec.fPaint)
1978         , fBackdrop(SkSafeRef(rec.fBackdrop))
1979         , fSaveLayerFlags(rec.fSaveLayerFlags)
1980         , fBackdropScale(SkCanvasPriv::GetBackdropScaleFactor(rec)) {}
1981 
execute(SkCanvas * canvas) const1982 void SaveLayerCommand::execute(SkCanvas* canvas) const {
1983     // In the common case fBackdropScale == 1.f and then this is no different than a regular Rec
1984     canvas->saveLayer(SkCanvasPriv::ScaledBackdropLayer(fBounds.getMaybeNull(),
1985                                                         fPaint.getMaybeNull(),
1986                                                         fBackdrop.get(),
1987                                                         fBackdropScale,
1988                                                         fSaveLayerFlags));
1989 }
1990 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1991 void SaveLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1992     INHERITED::toJSON(writer, urlDataManager);
1993     if (fBounds.isValid()) {
1994         writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
1995         MakeJsonRect(writer, *fBounds);
1996     }
1997     if (fPaint.isValid()) {
1998         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1999         MakeJsonPaint(writer, *fPaint, urlDataManager);
2000     }
2001     if (fBackdrop != nullptr) {
2002         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BACKDROP);
2003         flatten(fBackdrop.get(), writer, urlDataManager);
2004         writer.endObject();  // backdrop
2005     }
2006     if (fSaveLayerFlags != 0) {
2007         SkDebugf("unsupported: saveLayer flags\n");
2008         SkASSERT(false);
2009     }
2010 }
2011 
SetMatrixCommand(const SkMatrix & matrix)2012 SetMatrixCommand::SetMatrixCommand(const SkMatrix& matrix) : INHERITED(kSetMatrix_OpType) {
2013     fMatrix = matrix;
2014 }
2015 
execute(SkCanvas * canvas) const2016 void SetMatrixCommand::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); }
2017 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2018 void SetMatrixCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2019     INHERITED::toJSON(writer, urlDataManager);
2020     writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
2021     MakeJsonMatrix(writer, fMatrix);
2022     writeMatrixType(writer, fMatrix);
2023 }
2024 
SetM44Command(const SkM44 & matrix)2025 SetM44Command::SetM44Command(const SkM44& matrix) : INHERITED(kSetM44_OpType) {
2026     fMatrix = matrix;
2027 }
2028 
execute(SkCanvas * canvas) const2029 void SetM44Command::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); }
2030 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2031 void SetM44Command::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2032     INHERITED::toJSON(writer, urlDataManager);
2033     writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
2034     MakeJsonMatrix44(writer, fMatrix);
2035 }
2036