• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "tools/debugger/DrawCommand.h"
9 
10 #include <algorithm>
11 #include "include/core/SkColorFilter.h"
12 #include "include/core/SkDrawable.h"
13 #include "include/core/SkImageFilter.h"
14 #include "include/core/SkPathEffect.h"
15 #include "include/core/SkPicture.h"
16 #include "include/core/SkTypeface.h"
17 #include "include/effects/SkDashPathEffect.h"
18 #include "include/encode/SkPngEncoder.h"
19 #include "include/private/SkShadowFlags.h"
20 #include "include/private/SkTHash.h"
21 #include "src/core/SkAutoMalloc.h"
22 #include "src/core/SkCanvasPriv.h"
23 #include "src/core/SkClipOpPriv.h"
24 #include "src/core/SkLatticeIter.h"
25 #include "src/core/SkMaskFilterBase.h"
26 #include "src/core/SkPaintDefaults.h"
27 #include "src/core/SkReadBuffer.h"
28 #include "src/core/SkRectPriv.h"
29 #include "src/core/SkTextBlobPriv.h"
30 #include "src/core/SkWriteBuffer.h"
31 #include "tools/debugger/JsonWriteBuffer.h"
32 
33 #define DEBUGCANVAS_ATTRIBUTE_COMMAND "command"
34 #define DEBUGCANVAS_ATTRIBUTE_VISIBLE "visible"
35 #define DEBUGCANVAS_ATTRIBUTE_MATRIX "matrix"
36 #define DEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS "drawDepthTranslation"
37 #define DEBUGCANVAS_ATTRIBUTE_COORDS "coords"
38 #define DEBUGCANVAS_ATTRIBUTE_EDGING "edging"
39 #define DEBUGCANVAS_ATTRIBUTE_HINTING "hinting"
40 #define DEBUGCANVAS_ATTRIBUTE_BOUNDS "bounds"
41 #define DEBUGCANVAS_ATTRIBUTE_PAINT "paint"
42 #define DEBUGCANVAS_ATTRIBUTE_OUTER "outer"
43 #define DEBUGCANVAS_ATTRIBUTE_INNER "inner"
44 #define DEBUGCANVAS_ATTRIBUTE_MODE "mode"
45 #define DEBUGCANVAS_ATTRIBUTE_POINTS "points"
46 #define DEBUGCANVAS_ATTRIBUTE_PATH "path"
47 #define DEBUGCANVAS_ATTRIBUTE_TEXT "text"
48 #define DEBUGCANVAS_ATTRIBUTE_COLOR "color"
49 #define DEBUGCANVAS_ATTRIBUTE_ALPHA "alpha"
50 #define DEBUGCANVAS_ATTRIBUTE_BLENDMODE "blendMode"
51 #define DEBUGCANVAS_ATTRIBUTE_STYLE "style"
52 #define DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH "strokeWidth"
53 #define DEBUGCANVAS_ATTRIBUTE_STROKEMITER "strokeMiter"
54 #define DEBUGCANVAS_ATTRIBUTE_STROKEJOIN "strokeJoin"
55 #define DEBUGCANVAS_ATTRIBUTE_CAP "cap"
56 #define DEBUGCANVAS_ATTRIBUTE_ANTIALIAS "antiAlias"
57 #define DEBUGCANVAS_ATTRIBUTE_DITHER "dither"
58 #define DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT "fakeBoldText"
59 #define DEBUGCANVAS_ATTRIBUTE_LINEARTEXT "linearText"
60 #define DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT "subpixelText"
61 #define DEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT "devKernText"
62 #define DEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT "lcdRenderText"
63 #define DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT "embeddedBitmapText"
64 #define DEBUGCANVAS_ATTRIBUTE_AUTOHINTING "forceAutoHinting"
65 #define DEBUGCANVAS_ATTRIBUTE_REGION "region"
66 #define DEBUGCANVAS_ATTRIBUTE_REGIONOP "op"
67 #define DEBUGCANVAS_ATTRIBUTE_EDGESTYLE "edgeStyle"
68 #define DEBUGCANVAS_ATTRIBUTE_DEVICEREGION "deviceRegion"
69 #define DEBUGCANVAS_ATTRIBUTE_BLUR "blur"
70 #define DEBUGCANVAS_ATTRIBUTE_SIGMA "sigma"
71 #define DEBUGCANVAS_ATTRIBUTE_QUALITY "quality"
72 #define DEBUGCANVAS_ATTRIBUTE_TEXTSIZE "textSize"
73 #define DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX "textScaleX"
74 #define DEBUGCANVAS_ATTRIBUTE_TEXTSKEWX "textSkewX"
75 #define DEBUGCANVAS_ATTRIBUTE_DASHING "dashing"
76 #define DEBUGCANVAS_ATTRIBUTE_INTERVALS "intervals"
77 #define DEBUGCANVAS_ATTRIBUTE_PHASE "phase"
78 #define DEBUGCANVAS_ATTRIBUTE_FILLTYPE "fillType"
79 #define DEBUGCANVAS_ATTRIBUTE_VERBS "verbs"
80 #define DEBUGCANVAS_ATTRIBUTE_NAME "name"
81 #define DEBUGCANVAS_ATTRIBUTE_DATA "data"
82 #define DEBUGCANVAS_ATTRIBUTE_VALUES "values"
83 #define DEBUGCANVAS_ATTRIBUTE_SHADER "shader"
84 #define DEBUGCANVAS_ATTRIBUTE_PATHEFFECT "pathEffect"
85 #define DEBUGCANVAS_ATTRIBUTE_MASKFILTER "maskFilter"
86 #define DEBUGCANVAS_ATTRIBUTE_XFERMODE "xfermode"
87 #define DEBUGCANVAS_ATTRIBUTE_BACKDROP "backdrop"
88 #define DEBUGCANVAS_ATTRIBUTE_COLORFILTER "colorfilter"
89 #define DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER "imagefilter"
90 #define DEBUGCANVAS_ATTRIBUTE_IMAGE "image"
91 #define DEBUGCANVAS_ATTRIBUTE_BITMAP "bitmap"
92 #define DEBUGCANVAS_ATTRIBUTE_SRC "src"
93 #define DEBUGCANVAS_ATTRIBUTE_DST "dst"
94 #define DEBUGCANVAS_ATTRIBUTE_CENTER "center"
95 #define DEBUGCANVAS_ATTRIBUTE_STRICT "strict"
96 #define DEBUGCANVAS_ATTRIBUTE_DESCRIPTION "description"
97 #define DEBUGCANVAS_ATTRIBUTE_X "x"
98 #define DEBUGCANVAS_ATTRIBUTE_Y "y"
99 #define DEBUGCANVAS_ATTRIBUTE_RUNS "runs"
100 #define DEBUGCANVAS_ATTRIBUTE_POSITIONS "positions"
101 #define DEBUGCANVAS_ATTRIBUTE_GLYPHS "glyphs"
102 #define DEBUGCANVAS_ATTRIBUTE_FONT "font"
103 #define DEBUGCANVAS_ATTRIBUTE_TYPEFACE "typeface"
104 #define DEBUGCANVAS_ATTRIBUTE_CUBICS "cubics"
105 #define DEBUGCANVAS_ATTRIBUTE_COLORS "colors"
106 #define DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS "textureCoords"
107 #define DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY "filterQuality"
108 #define DEBUGCANVAS_ATTRIBUTE_STARTANGLE "startAngle"
109 #define DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE "sweepAngle"
110 #define DEBUGCANVAS_ATTRIBUTE_USECENTER "useCenter"
111 #define DEBUGCANVAS_ATTRIBUTE_SHORTDESC "shortDesc"
112 #define DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID "uniqueID"
113 #define DEBUGCANVAS_ATTRIBUTE_WIDTH "width"
114 #define DEBUGCANVAS_ATTRIBUTE_HEIGHT "height"
115 #define DEBUGCANVAS_ATTRIBUTE_ALPHA "alpha"
116 #define DEBUGCANVAS_ATTRIBUTE_LATTICE "lattice"
117 #define DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT "xCount"
118 #define DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT "yCount"
119 #define DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS "xDivs"
120 #define DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS "yDivs"
121 #define DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS "flags"
122 #define DEBUGCANVAS_ATTRIBUTE_ZPLANE "zPlane"
123 #define DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION "lightPositions"
124 #define DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR "ambientColor"
125 #define DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR "spotColor"
126 #define DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS "lightRadius"
127 
128 #define DEBUGCANVAS_VERB_MOVE "move"
129 #define DEBUGCANVAS_VERB_LINE "line"
130 #define DEBUGCANVAS_VERB_QUAD "quad"
131 #define DEBUGCANVAS_VERB_CUBIC "cubic"
132 #define DEBUGCANVAS_VERB_CONIC "conic"
133 #define DEBUGCANVAS_VERB_CLOSE "close"
134 
135 #define DEBUGCANVAS_STYLE_FILL "fill"
136 #define DEBUGCANVAS_STYLE_STROKE "stroke"
137 #define DEBUGCANVAS_STYLE_STROKEANDFILL "strokeAndFill"
138 
139 #define DEBUGCANVAS_POINTMODE_POINTS "points"
140 #define DEBUGCANVAS_POINTMODE_LINES "lines"
141 #define DEBUGCANVAS_POINTMODE_POLYGON "polygon"
142 
143 #define DEBUGCANVAS_REGIONOP_DIFFERENCE "difference"
144 #define DEBUGCANVAS_REGIONOP_INTERSECT "intersect"
145 #define DEBUGCANVAS_REGIONOP_UNION "union"
146 #define DEBUGCANVAS_REGIONOP_XOR "xor"
147 #define DEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE "reverseDifference"
148 #define DEBUGCANVAS_REGIONOP_REPLACE "replace"
149 
150 #define DEBUGCANVAS_BLURSTYLE_NORMAL "normal"
151 #define DEBUGCANVAS_BLURSTYLE_SOLID "solid"
152 #define DEBUGCANVAS_BLURSTYLE_OUTER "outer"
153 #define DEBUGCANVAS_BLURSTYLE_INNER "inner"
154 
155 #define DEBUGCANVAS_BLURQUALITY_LOW "low"
156 #define DEBUGCANVAS_BLURQUALITY_HIGH "high"
157 
158 #define DEBUGCANVAS_FILLTYPE_WINDING "winding"
159 #define DEBUGCANVAS_FILLTYPE_EVENODD "evenOdd"
160 #define DEBUGCANVAS_FILLTYPE_INVERSEWINDING "inverseWinding"
161 #define DEBUGCANVAS_FILLTYPE_INVERSEEVENODD "inverseEvenOdd"
162 
163 #define DEBUGCANVAS_CAP_BUTT "butt"
164 #define DEBUGCANVAS_CAP_ROUND "round"
165 #define DEBUGCANVAS_CAP_SQUARE "square"
166 
167 #define DEBUGCANVAS_MITER_JOIN "miter"
168 #define DEBUGCANVAS_ROUND_JOIN "round"
169 #define DEBUGCANVAS_BEVEL_JOIN "bevel"
170 
171 #define DEBUGCANVAS_COLORTYPE_ARGB4444 "ARGB4444"
172 #define DEBUGCANVAS_COLORTYPE_RGBA8888 "RGBA8888"
173 #define DEBUGCANVAS_COLORTYPE_BGRA8888 "BGRA8888"
174 #define DEBUGCANVAS_COLORTYPE_565 "565"
175 #define DEBUGCANVAS_COLORTYPE_GRAY8 "Gray8"
176 #define DEBUGCANVAS_COLORTYPE_INDEX8 "Index8"
177 #define DEBUGCANVAS_COLORTYPE_ALPHA8 "Alpha8"
178 
179 #define DEBUGCANVAS_ALPHATYPE_OPAQUE "opaque"
180 #define DEBUGCANVAS_ALPHATYPE_PREMUL "premul"
181 #define DEBUGCANVAS_ALPHATYPE_UNPREMUL "unpremul"
182 #define DEBUGCANVAS_ALPHATYPE_UNKNOWN "unknown"
183 
184 #define DEBUGCANVAS_FILTERQUALITY_NONE "none"
185 #define DEBUGCANVAS_FILTERQUALITY_LOW "low"
186 #define DEBUGCANVAS_FILTERQUALITY_MEDIUM "medium"
187 #define DEBUGCANVAS_FILTERQUALITY_HIGH "high"
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 kConcat_OpType: return "Concat";
217         case kDrawAnnotation_OpType: return "DrawAnnotation";
218         case kDrawBitmap_OpType: return "DrawBitmap";
219         case kDrawBitmapLattice_OpType: return "DrawBitmapLattice";
220         case kDrawBitmapNine_OpType: return "DrawBitmapNine";
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 kDrawImageNine_OpType: return "DrawImageNine";
226         case kDrawImageRect_OpType: return "DrawImageRect";
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         default:
249             SkDebugf("OpType error 0x%08x\n", type);
250             SkASSERT(0);
251             break;
252     }
253     SkDEBUGFAIL("DrawType UNUSED\n");
254     return nullptr;
255 }
256 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const257 void DrawCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
258     writer.appendString(DEBUGCANVAS_ATTRIBUTE_COMMAND, this->GetCommandString(fOpType));
259     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_VISIBLE, this->isVisible());
260 }
261 
262 namespace {
263 
xlate_and_scale_to_bounds(SkCanvas * canvas,const SkRect & bounds)264 void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
265     const SkISize& size = canvas->getBaseLayerSize();
266 
267     static const SkScalar kInsetFrac = 0.9f;  // Leave a border around object
268 
269     canvas->translate(size.fWidth / 2.0f, size.fHeight / 2.0f);
270     if (bounds.width() > bounds.height()) {
271         canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.width()),
272                       SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.width()));
273     } else {
274         canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.height()),
275                       SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.height()));
276     }
277     canvas->translate(-bounds.centerX(), -bounds.centerY());
278 }
279 
render_path(SkCanvas * canvas,const SkPath & path)280 void render_path(SkCanvas* canvas, const SkPath& path) {
281     canvas->clear(0xFFFFFFFF);
282 
283     const SkRect& bounds = path.getBounds();
284     if (bounds.isEmpty()) {
285         return;
286     }
287 
288     SkAutoCanvasRestore acr(canvas, true);
289     xlate_and_scale_to_bounds(canvas, bounds);
290 
291     SkPaint p;
292     p.setColor(SK_ColorBLACK);
293     p.setStyle(SkPaint::kStroke_Style);
294 
295     canvas->drawPath(path, p);
296 }
297 
render_region(SkCanvas * canvas,const SkRegion & region)298 void render_region(SkCanvas* canvas, const SkRegion& region) {
299     canvas->clear(0xFFFFFFFF);
300 
301     const SkIRect& bounds = region.getBounds();
302     if (bounds.isEmpty()) {
303         return;
304     }
305 
306     SkAutoCanvasRestore acr(canvas, true);
307     xlate_and_scale_to_bounds(canvas, SkRect::Make(bounds));
308 
309     SkPaint p;
310     p.setColor(SK_ColorBLACK);
311     p.setStyle(SkPaint::kStroke_Style);
312 
313     canvas->drawRegion(region, p);
314 }
315 
render_bitmap(SkCanvas * canvas,const SkBitmap & input,const SkRect * srcRect=nullptr)316 void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = nullptr) {
317     const SkISize& size = canvas->getBaseLayerSize();
318 
319     SkScalar xScale = SkIntToScalar(size.fWidth - 2) / input.width();
320     SkScalar yScale = SkIntToScalar(size.fHeight - 2) / input.height();
321 
322     if (input.width() > input.height()) {
323         yScale *= input.height() / (float)input.width();
324     } else {
325         xScale *= input.width() / (float)input.height();
326     }
327 
328     SkRect dst = SkRect::MakeXYWH(
329             SK_Scalar1, SK_Scalar1, xScale * input.width(), yScale * input.height());
330 
331     static const int kNumBlocks = 8;
332 
333     canvas->clear(0xFFFFFFFF);
334     SkISize block = {canvas->imageInfo().width() / kNumBlocks,
335                      canvas->imageInfo().height() / kNumBlocks};
336     for (int y = 0; y < kNumBlocks; ++y) {
337         for (int x = 0; x < kNumBlocks; ++x) {
338             SkPaint paint;
339             paint.setColor((x + y) % 2 ? SK_ColorLTGRAY : SK_ColorDKGRAY);
340             SkRect r = SkRect::MakeXYWH(SkIntToScalar(x * block.width()),
341                                         SkIntToScalar(y * block.height()),
342                                         SkIntToScalar(block.width()),
343                                         SkIntToScalar(block.height()));
344             canvas->drawRect(r, paint);
345         }
346     }
347 
348     canvas->drawBitmapRect(input, dst, nullptr);
349 
350     if (srcRect) {
351         SkRect  r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
352                                     srcRect->fTop * yScale + SK_Scalar1,
353                                     srcRect->fRight * xScale + SK_Scalar1,
354                                     srcRect->fBottom * yScale + SK_Scalar1);
355         SkPaint p;
356         p.setColor(SK_ColorRED);
357         p.setStyle(SkPaint::kStroke_Style);
358 
359         canvas->drawRect(r, p);
360     }
361 }
362 
render_rrect(SkCanvas * canvas,const SkRRect & rrect)363 void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
364     canvas->clear(0xFFFFFFFF);
365     canvas->save();
366 
367     const SkRect& bounds = rrect.getBounds();
368 
369     xlate_and_scale_to_bounds(canvas, bounds);
370 
371     SkPaint p;
372     p.setColor(SK_ColorBLACK);
373     p.setStyle(SkPaint::kStroke_Style);
374 
375     canvas->drawRRect(rrect, p);
376     canvas->restore();
377 }
378 
render_drrect(SkCanvas * canvas,const SkRRect & outer,const SkRRect & inner)379 void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
380     canvas->clear(0xFFFFFFFF);
381     canvas->save();
382 
383     const SkRect& bounds = outer.getBounds();
384 
385     xlate_and_scale_to_bounds(canvas, bounds);
386 
387     SkPaint p;
388     p.setColor(SK_ColorBLACK);
389     p.setStyle(SkPaint::kStroke_Style);
390 
391     canvas->drawDRRect(outer, inner, p);
392     canvas->restore();
393 }
394 
render_shadow(SkCanvas * canvas,const SkPath & path,SkDrawShadowRec rec)395 void render_shadow(SkCanvas* canvas, const SkPath& path, SkDrawShadowRec rec) {
396     canvas->clear(0xFFFFFFFF);
397 
398     const SkRect& bounds = path.getBounds();
399     if (bounds.isEmpty()) {
400         return;
401     }
402 
403     SkAutoCanvasRestore acr(canvas, true);
404     xlate_and_scale_to_bounds(canvas, bounds);
405 
406     rec.fAmbientColor = SK_ColorBLACK;
407     rec.fSpotColor    = SK_ColorBLACK;
408     canvas->private_draw_shadow_rec(path, rec);
409 }
410 
411 static const char* const gBlendModeMap[] = {
412         "clear",      "src",        "dst",      "srcOver",    "dstOver",   "srcIn",     "dstIn",
413         "srcOut",     "dstOut",     "srcATop",  "dstATop",    "xor",       "plus",      "modulate",
414 
415         "screen",
416 
417         "overlay",    "darken",     "lighten",  "colorDodge", "colorBurn", "hardLight", "softLight",
418         "difference", "exclusion",  "multiply",
419 
420         "hue",        "saturation", "color",    "luminosity",
421 };
422 
423 static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLastMode) + 1,
424               "blendMode mismatch");
425 static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLuminosity) + 1,
426               "blendMode mismatch");
427 
apply_paint_blend_mode(const SkPaint & paint,SkJSONWriter & writer)428 void apply_paint_blend_mode(const SkPaint& paint, SkJSONWriter& writer) {
429     const auto mode = paint.getBlendMode();
430     if (mode != SkBlendMode::kSrcOver) {
431         SkASSERT(static_cast<size_t>(mode) < SK_ARRAY_COUNT(gBlendModeMap));
432         writer.appendString(DEBUGCANVAS_ATTRIBUTE_BLENDMODE,
433                             gBlendModeMap[static_cast<size_t>(mode)]);
434     }
435 }
436 
437 };  // namespace
438 
MakeJsonColor(SkJSONWriter & writer,const SkColor color)439 void DrawCommand::MakeJsonColor(SkJSONWriter& writer, const SkColor color) {
440     writer.beginArray(nullptr, false);
441     writer.appendS32(SkColorGetA(color));
442     writer.appendS32(SkColorGetR(color));
443     writer.appendS32(SkColorGetG(color));
444     writer.appendS32(SkColorGetB(color));
445     writer.endArray();
446 }
447 
MakeJsonColor4f(SkJSONWriter & writer,const SkColor4f & color)448 void DrawCommand::MakeJsonColor4f(SkJSONWriter& writer, const SkColor4f& color) {
449     writer.beginArray(nullptr, false);
450     writer.appendFloat(color.fA);
451     writer.appendFloat(color.fR);
452     writer.appendFloat(color.fG);
453     writer.appendFloat(color.fB);
454     writer.endArray();
455 }
456 
MakeJsonPoint(SkJSONWriter & writer,const SkPoint & point)457 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, const SkPoint& point) {
458     writer.beginArray(nullptr, false);
459     writer.appendFloat(point.x());
460     writer.appendFloat(point.y());
461     writer.endArray();
462 }
463 
MakeJsonPoint(SkJSONWriter & writer,SkScalar x,SkScalar y)464 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, SkScalar x, SkScalar y) {
465     writer.beginArray(nullptr, false);
466     writer.appendFloat(x);
467     writer.appendFloat(y);
468     writer.endArray();
469 }
470 
MakeJsonPoint3(SkJSONWriter & writer,const SkPoint3 & point)471 void DrawCommand::MakeJsonPoint3(SkJSONWriter& writer, const SkPoint3& point) {
472     writer.beginArray(nullptr, false);
473     writer.appendFloat(point.x());
474     writer.appendFloat(point.y());
475     writer.appendFloat(point.z());
476     writer.endArray();
477 }
478 
MakeJsonRect(SkJSONWriter & writer,const SkRect & rect)479 void DrawCommand::MakeJsonRect(SkJSONWriter& writer, const SkRect& rect) {
480     writer.beginArray(nullptr, false);
481     writer.appendFloat(rect.left());
482     writer.appendFloat(rect.top());
483     writer.appendFloat(rect.right());
484     writer.appendFloat(rect.bottom());
485     writer.endArray();
486 }
487 
MakeJsonIRect(SkJSONWriter & writer,const SkIRect & rect)488 void DrawCommand::MakeJsonIRect(SkJSONWriter& writer, const SkIRect& rect) {
489     writer.beginArray(nullptr, false);
490     writer.appendS32(rect.left());
491     writer.appendS32(rect.top());
492     writer.appendS32(rect.right());
493     writer.appendS32(rect.bottom());
494     writer.endArray();
495 }
496 
make_json_rrect(SkJSONWriter & writer,const SkRRect & rrect)497 static void make_json_rrect(SkJSONWriter& writer, const SkRRect& rrect) {
498     writer.beginArray(nullptr, false);
499     DrawCommand::MakeJsonRect(writer, rrect.rect());
500     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperLeft_Corner));
501     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperRight_Corner));
502     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerRight_Corner));
503     DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerLeft_Corner));
504     writer.endArray();
505 }
506 
MakeJsonMatrix(SkJSONWriter & writer,const SkMatrix & matrix)507 void DrawCommand::MakeJsonMatrix(SkJSONWriter& writer, const SkMatrix& matrix) {
508     writer.beginArray();
509     for (int r = 0; r < 3; ++r) {
510         writer.beginArray(nullptr, false);
511         for (int c = 0; c < 3; ++c) {
512             writer.appendFloat(matrix[r * 3 + c]);
513         }
514         writer.endArray();
515     }
516     writer.endArray();
517 }
518 
MakeJsonPath(SkJSONWriter & writer,const SkPath & path)519 void DrawCommand::MakeJsonPath(SkJSONWriter& writer, const SkPath& path) {
520     writer.beginObject();
521     switch (path.getFillType()) {
522         case SkPath::kWinding_FillType:
523             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_WINDING);
524             break;
525         case SkPath::kEvenOdd_FillType:
526             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_EVENODD);
527             break;
528         case SkPath::kInverseWinding_FillType:
529             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
530                                 DEBUGCANVAS_FILLTYPE_INVERSEWINDING);
531             break;
532         case SkPath::kInverseEvenOdd_FillType:
533             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
534                                 DEBUGCANVAS_FILLTYPE_INVERSEEVENODD);
535             break;
536     }
537     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_VERBS);
538     SkPath::Iter iter(path, false);
539     SkPoint      pts[4];
540     SkPath::Verb verb;
541     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
542         if (verb == SkPath::kClose_Verb) {
543             writer.appendString(DEBUGCANVAS_VERB_CLOSE);
544             continue;
545         }
546         writer.beginObject();  // verb
547         switch (verb) {
548             case SkPath::kLine_Verb: {
549                 writer.appendName(DEBUGCANVAS_VERB_LINE);
550                 MakeJsonPoint(writer, pts[1]);
551                 break;
552             }
553             case SkPath::kQuad_Verb: {
554                 writer.beginArray(DEBUGCANVAS_VERB_QUAD);
555                 MakeJsonPoint(writer, pts[1]);
556                 MakeJsonPoint(writer, pts[2]);
557                 writer.endArray();  // quad coords
558                 break;
559             }
560             case SkPath::kCubic_Verb: {
561                 writer.beginArray(DEBUGCANVAS_VERB_CUBIC);
562                 MakeJsonPoint(writer, pts[1]);
563                 MakeJsonPoint(writer, pts[2]);
564                 MakeJsonPoint(writer, pts[3]);
565                 writer.endArray();  // cubic coords
566                 break;
567             }
568             case SkPath::kConic_Verb: {
569                 writer.beginArray(DEBUGCANVAS_VERB_CONIC);
570                 MakeJsonPoint(writer, pts[1]);
571                 MakeJsonPoint(writer, pts[2]);
572                 writer.appendFloat(iter.conicWeight());
573                 writer.endArray();  // conic coords
574                 break;
575             }
576             case SkPath::kMove_Verb: {
577                 writer.appendName(DEBUGCANVAS_VERB_MOVE);
578                 MakeJsonPoint(writer, pts[0]);
579                 break;
580             }
581             case SkPath::kClose_Verb:
582             case SkPath::kDone_Verb:
583                 // Unreachable
584                 break;
585         }
586         writer.endObject();  // verb
587     }
588     writer.endArray();   // verbs
589     writer.endObject();  // path
590 }
591 
MakeJsonRegion(SkJSONWriter & writer,const SkRegion & region)592 void DrawCommand::MakeJsonRegion(SkJSONWriter& writer, const SkRegion& region) {
593     // TODO: Actually serialize the rectangles, rather than just devolving to path
594     SkPath path;
595     region.getBoundaryPath(&path);
596     MakeJsonPath(writer, path);
597 }
598 
regionop_name(SkClipOp op)599 static const char* regionop_name(SkClipOp op) {
600     switch (op) {
601         case kDifference_SkClipOp: return DEBUGCANVAS_REGIONOP_DIFFERENCE;
602         case kIntersect_SkClipOp: return DEBUGCANVAS_REGIONOP_INTERSECT;
603         case kUnion_SkClipOp: return DEBUGCANVAS_REGIONOP_UNION;
604         case kXOR_SkClipOp: return DEBUGCANVAS_REGIONOP_XOR;
605         case kReverseDifference_SkClipOp: return DEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE;
606         case kReplace_SkClipOp: return DEBUGCANVAS_REGIONOP_REPLACE;
607         default: SkASSERT(false); return "<invalid region op>";
608     }
609 }
610 
pointmode_name(SkCanvas::PointMode mode)611 static const char* pointmode_name(SkCanvas::PointMode mode) {
612     switch (mode) {
613         case SkCanvas::kPoints_PointMode: return DEBUGCANVAS_POINTMODE_POINTS;
614         case SkCanvas::kLines_PointMode: return DEBUGCANVAS_POINTMODE_LINES;
615         case SkCanvas::kPolygon_PointMode: return DEBUGCANVAS_POINTMODE_POLYGON;
616         default: SkASSERT(false); return "<invalid point mode>";
617     }
618 }
619 
store_scalar(SkJSONWriter & writer,const char * key,SkScalar value,SkScalar defaultValue)620 static void store_scalar(SkJSONWriter& writer,
621                          const char*   key,
622                          SkScalar      value,
623                          SkScalar      defaultValue) {
624     if (value != defaultValue) {
625         writer.appendFloat(key, value);
626     }
627 }
628 
store_bool(SkJSONWriter & writer,const char * key,bool value,bool defaultValue)629 static void store_bool(SkJSONWriter& writer, const char* key, bool value, bool defaultValue) {
630     if (value != defaultValue) {
631         writer.appendBool(key, value);
632     }
633 }
634 
encode_data(const void * bytes,size_t count,const char * contentType,UrlDataManager & urlDataManager)635 static SkString encode_data(const void*     bytes,
636                             size_t          count,
637                             const char*     contentType,
638                             UrlDataManager& urlDataManager) {
639     sk_sp<SkData> data(SkData::MakeWithCopy(bytes, count));
640     return urlDataManager.addData(data.get(), contentType);
641 }
642 
flatten(const SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)643 void DrawCommand::flatten(const SkFlattenable* flattenable,
644                           SkJSONWriter&        writer,
645                           UrlDataManager&      urlDataManager) {
646     SkBinaryWriteBuffer buffer;
647     flattenable->flatten(buffer);
648     void* data = sk_malloc_throw(buffer.bytesWritten());
649     buffer.writeToMemory(data);
650     SkString url =
651             encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
652     writer.appendString(DEBUGCANVAS_ATTRIBUTE_NAME, flattenable->getTypeName());
653     writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
654 
655     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_VALUES);
656     JsonWriteBuffer jsonBuffer(&writer, &urlDataManager);
657     flattenable->flatten(jsonBuffer);
658     writer.endObject();  // values
659 
660     sk_free(data);
661 }
662 
WritePNG(SkBitmap bitmap,SkWStream & out)663 void DrawCommand::WritePNG(SkBitmap bitmap, SkWStream& out) {
664     SkPixmap pm;
665     SkAssertResult(bitmap.peekPixels(&pm));
666 
667     SkPngEncoder::Options options;
668     options.fZLibLevel   = 1;
669     options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
670     SkPngEncoder::Encode(&out, pm, options);
671 }
672 
flatten(const SkImage & image,SkJSONWriter & writer,UrlDataManager & urlDataManager)673 bool DrawCommand::flatten(const SkImage&  image,
674                           SkJSONWriter&   writer,
675                           UrlDataManager& urlDataManager) {
676     size_t       rowBytes = 4 * image.width();
677     SkAutoMalloc buffer(rowBytes * image.height());
678     SkImageInfo  dstInfo =
679             SkImageInfo::Make(image.width(), image.height(), kN32_SkColorType, kPremul_SkAlphaType);
680     if (!image.readPixels(dstInfo, buffer.get(), rowBytes, 0, 0)) {
681         SkDebugf("readPixels failed\n");
682         return false;
683     }
684 
685     SkBitmap bm;
686     bm.installPixels(dstInfo, buffer.get(), rowBytes);
687 
688     SkDynamicMemoryWStream out;
689     DrawCommand::WritePNG(bm, out);
690     sk_sp<SkData> encoded = out.detachAsData();
691     SkString      url = encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager);
692     writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
693     return true;
694 }
695 
color_type_name(SkColorType colorType)696 static const char* color_type_name(SkColorType colorType) {
697     switch (colorType) {
698         case kARGB_4444_SkColorType: return DEBUGCANVAS_COLORTYPE_ARGB4444;
699         case kRGBA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_RGBA8888;
700         case kBGRA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_BGRA8888;
701         case kRGB_565_SkColorType: return DEBUGCANVAS_COLORTYPE_565;
702         case kGray_8_SkColorType: return DEBUGCANVAS_COLORTYPE_GRAY8;
703         case kAlpha_8_SkColorType: return DEBUGCANVAS_COLORTYPE_ALPHA8;
704         default: SkASSERT(false); return DEBUGCANVAS_COLORTYPE_RGBA8888;
705     }
706 }
707 
alpha_type_name(SkAlphaType alphaType)708 static const char* alpha_type_name(SkAlphaType alphaType) {
709     switch (alphaType) {
710         case kOpaque_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_OPAQUE;
711         case kPremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_PREMUL;
712         case kUnpremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_UNPREMUL;
713         default: SkASSERT(false); return DEBUGCANVAS_ALPHATYPE_OPAQUE;
714     }
715 }
716 
flatten(const SkBitmap & bitmap,SkJSONWriter & writer,UrlDataManager & urlDataManager)717 bool DrawCommand::flatten(const SkBitmap& bitmap,
718                           SkJSONWriter&   writer,
719                           UrlDataManager& urlDataManager) {
720     sk_sp<SkImage> image(SkImage::MakeFromBitmap(bitmap));
721     writer.appendString(DEBUGCANVAS_ATTRIBUTE_COLOR, color_type_name(bitmap.colorType()));
722     writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, alpha_type_name(bitmap.alphaType()));
723     bool success = flatten(*image, writer, urlDataManager);
724     return success;
725 }
726 
apply_font_hinting(const SkFont & font,SkJSONWriter & writer)727 static void apply_font_hinting(const SkFont& font, SkJSONWriter& writer) {
728     SkFontHinting hinting = font.getHinting();
729     if (hinting != SkPaintDefaults_Hinting) {
730         switch (hinting) {
731             case SkFontHinting::kNone:
732                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NONE);
733                 break;
734             case SkFontHinting::kSlight:
735                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_SLIGHT);
736                 break;
737             case SkFontHinting::kNormal:
738                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NORMAL);
739                 break;
740             case SkFontHinting::kFull:
741                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_FULL);
742                 break;
743         }
744     }
745 }
746 
apply_font_edging(const SkFont & font,SkJSONWriter & writer)747 static void apply_font_edging(const SkFont& font, SkJSONWriter& writer) {
748     switch (font.getEdging()) {
749         case SkFont::Edging::kAlias:
750             writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ALIAS);
751             break;
752         case SkFont::Edging::kAntiAlias:
753             writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ANTIALIAS);
754             break;
755         case SkFont::Edging::kSubpixelAntiAlias:
756             writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS);
757             break;
758     }
759 }
760 
apply_paint_color(const SkPaint & paint,SkJSONWriter & writer)761 static void apply_paint_color(const SkPaint& paint, SkJSONWriter& writer) {
762     SkColor color = paint.getColor();
763     if (color != SK_ColorBLACK) {
764         writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
765         DrawCommand::MakeJsonColor(writer, color);
766     }
767 }
768 
apply_paint_style(const SkPaint & paint,SkJSONWriter & writer)769 static void apply_paint_style(const SkPaint& paint, SkJSONWriter& writer) {
770     SkPaint::Style style = paint.getStyle();
771     if (style != SkPaint::kFill_Style) {
772         switch (style) {
773             case SkPaint::kStroke_Style: {
774                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKE);
775                 break;
776             }
777             case SkPaint::kStrokeAndFill_Style: {
778                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKEANDFILL);
779                 break;
780             }
781             default: SkASSERT(false);
782         }
783     }
784 }
785 
apply_paint_cap(const SkPaint & paint,SkJSONWriter & writer)786 static void apply_paint_cap(const SkPaint& paint, SkJSONWriter& writer) {
787     SkPaint::Cap cap = paint.getStrokeCap();
788     if (cap != SkPaint::kDefault_Cap) {
789         switch (cap) {
790             case SkPaint::kButt_Cap:
791                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_BUTT);
792                 break;
793             case SkPaint::kRound_Cap:
794                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_ROUND);
795                 break;
796             case SkPaint::kSquare_Cap:
797                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_SQUARE);
798                 break;
799             default: SkASSERT(false);
800         }
801     }
802 }
803 
apply_paint_join(const SkPaint & paint,SkJSONWriter & writer)804 static void apply_paint_join(const SkPaint& paint, SkJSONWriter& writer) {
805     SkPaint::Join join = paint.getStrokeJoin();
806     if (join != SkPaint::kDefault_Join) {
807         switch (join) {
808             case SkPaint::kMiter_Join:
809                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_MITER_JOIN);
810                 break;
811             case SkPaint::kRound_Join:
812                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_ROUND_JOIN);
813                 break;
814             case SkPaint::kBevel_Join:
815                 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_BEVEL_JOIN);
816                 break;
817             default: SkASSERT(false);
818         }
819     }
820 }
821 
apply_paint_filterquality(const SkPaint & paint,SkJSONWriter & writer)822 static void apply_paint_filterquality(const SkPaint& paint, SkJSONWriter& writer) {
823     SkFilterQuality quality = paint.getFilterQuality();
824     switch (quality) {
825         case kNone_SkFilterQuality: break;
826         case kLow_SkFilterQuality:
827             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY, DEBUGCANVAS_FILTERQUALITY_LOW);
828             break;
829         case kMedium_SkFilterQuality:
830             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
831                                 DEBUGCANVAS_FILTERQUALITY_MEDIUM);
832             break;
833         case kHigh_SkFilterQuality:
834             writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
835                                 DEBUGCANVAS_FILTERQUALITY_HIGH);
836             break;
837     }
838 }
839 
apply_paint_maskfilter(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)840 static void apply_paint_maskfilter(const SkPaint&  paint,
841                                    SkJSONWriter&   writer,
842                                    UrlDataManager& urlDataManager) {
843     SkMaskFilter* maskFilter = paint.getMaskFilter();
844     if (maskFilter != nullptr) {
845         SkMaskFilterBase::BlurRec blurRec;
846         if (as_MFB(maskFilter)->asABlur(&blurRec)) {
847             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BLUR);
848             writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SIGMA, blurRec.fSigma);
849             switch (blurRec.fStyle) {
850                 case SkBlurStyle::kNormal_SkBlurStyle:
851                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_NORMAL);
852                     break;
853                 case SkBlurStyle::kSolid_SkBlurStyle:
854                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_SOLID);
855                     break;
856                 case SkBlurStyle::kOuter_SkBlurStyle:
857                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_OUTER);
858                     break;
859                 case SkBlurStyle::kInner_SkBlurStyle:
860                     writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_INNER);
861                     break;
862                 default: SkASSERT(false);
863             }
864             writer.endObject();  // blur
865         } else {
866             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_MASKFILTER);
867             DrawCommand::flatten(maskFilter, writer, urlDataManager);
868             writer.endObject();  // maskFilter
869         }
870     }
871 }
872 
apply_paint_patheffect(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)873 static void apply_paint_patheffect(const SkPaint&  paint,
874                                    SkJSONWriter&   writer,
875                                    UrlDataManager& urlDataManager) {
876     SkPathEffect* pathEffect = paint.getPathEffect();
877     if (pathEffect != nullptr) {
878         SkPathEffect::DashInfo dashInfo;
879         SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
880         if (dashType == SkPathEffect::kDash_DashType) {
881             dashInfo.fIntervals = (SkScalar*)sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
882             pathEffect->asADash(&dashInfo);
883             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_DASHING);
884             writer.beginArray(DEBUGCANVAS_ATTRIBUTE_INTERVALS, false);
885             for (int32_t i = 0; i < dashInfo.fCount; i++) {
886                 writer.appendFloat(dashInfo.fIntervals[i]);
887             }
888             writer.endArray();  // intervals
889             sk_free(dashInfo.fIntervals);
890             writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_PHASE, dashInfo.fPhase);
891             writer.endObject();  // dashing
892         } else {
893             writer.beginObject(DEBUGCANVAS_ATTRIBUTE_PATHEFFECT);
894             DrawCommand::flatten(pathEffect, writer, urlDataManager);
895             writer.endObject();  // pathEffect
896         }
897     }
898 }
899 
apply_font_typeface(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)900 static void apply_font_typeface(const SkFont&   font,
901                                 SkJSONWriter&   writer,
902                                 UrlDataManager& urlDataManager) {
903     SkTypeface* typeface = font.getTypefaceOrDefault();
904     if (typeface != nullptr) {
905         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_TYPEFACE);
906         SkDynamicMemoryWStream buffer;
907         typeface->serialize(&buffer);
908         void* data = sk_malloc_throw(buffer.bytesWritten());
909         buffer.copyTo(data);
910         SkString url = encode_data(
911                 data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
912         writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
913         sk_free(data);
914         writer.endObject();
915     }
916 }
917 
apply_flattenable(const char * key,SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)918 static void apply_flattenable(const char*     key,
919                               SkFlattenable*  flattenable,
920                               SkJSONWriter&   writer,
921                               UrlDataManager& urlDataManager) {
922     if (flattenable != nullptr) {
923         writer.beginObject(key);
924         DrawCommand::flatten(flattenable, writer, urlDataManager);
925         writer.endObject();
926     }
927 }
928 
MakeJsonPaint(SkJSONWriter & writer,const SkPaint & paint,UrlDataManager & urlDataManager)929 void DrawCommand::MakeJsonPaint(SkJSONWriter&   writer,
930                                 const SkPaint&  paint,
931                                 UrlDataManager& urlDataManager) {
932     writer.beginObject();
933     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
934     store_scalar(writer,
935                  DEBUGCANVAS_ATTRIBUTE_STROKEMITER,
936                  paint.getStrokeMiter(),
937                  SkPaintDefaults_MiterLimit);
938     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
939     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
940 
941     apply_paint_color(paint, writer);
942     apply_paint_style(paint, writer);
943     apply_paint_blend_mode(paint, writer);
944     apply_paint_cap(paint, writer);
945     apply_paint_join(paint, writer);
946     apply_paint_filterquality(paint, writer);
947     apply_paint_patheffect(paint, writer, urlDataManager);
948     apply_paint_maskfilter(paint, writer, urlDataManager);
949     apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, paint.getShader(), writer, urlDataManager);
950     apply_flattenable(
951             DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER, paint.getImageFilter(), writer, urlDataManager);
952     apply_flattenable(
953             DEBUGCANVAS_ATTRIBUTE_COLORFILTER, paint.getColorFilter(), writer, urlDataManager);
954     writer.endObject();  // paint
955 }
956 
MakeJsonFont(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)957 static void MakeJsonFont(const SkFont& font, SkJSONWriter& writer, UrlDataManager& urlDataManager) {
958     writer.beginObject();
959     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, font.isEmbolden(), false);
960     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_LINEARTEXT, font.isLinearMetrics(), false);
961     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, font.isSubpixel(), false);
962     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, font.isEmbeddedBitmaps(), false);
963     store_bool(writer, DEBUGCANVAS_ATTRIBUTE_AUTOHINTING, font.isForceAutoHinting(), false);
964 
965     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSIZE, font.getSize(), SkPaintDefaults_TextSize);
966     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getScaleX(), SK_Scalar1);
967     store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getSkewX(), 0.0f);
968     apply_font_edging(font, writer);
969     apply_font_hinting(font, writer);
970     apply_font_typeface(font, writer, urlDataManager);
971     writer.endObject();  // font
972 }
973 
MakeJsonLattice(SkJSONWriter & writer,const SkCanvas::Lattice & lattice)974 void DrawCommand::MakeJsonLattice(SkJSONWriter& writer, const SkCanvas::Lattice& lattice) {
975     writer.beginObject();
976     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT, lattice.fXCount);
977     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT, lattice.fYCount);
978     if (nullptr != lattice.fBounds) {
979         writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
980         MakeJsonIRect(writer, *lattice.fBounds);
981     }
982     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS);
983     for (int i = 0; i < lattice.fXCount; i++) {
984         writer.appendS32(lattice.fXDivs[i]);
985     }
986     writer.endArray();  // xdivs
987     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS);
988     for (int i = 0; i < lattice.fYCount; i++) {
989         writer.appendS32(lattice.fYDivs[i]);
990     }
991     writer.endArray();  // ydivs
992     if (nullptr != lattice.fRectTypes) {
993         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS);
994         int flagCount = 0;
995         for (int row = 0; row < lattice.fYCount + 1; row++) {
996             writer.beginArray();
997             for (int column = 0; column < lattice.fXCount + 1; column++) {
998                 writer.appendS32(lattice.fRectTypes[flagCount++]);
999             }
1000             writer.endArray();  // row
1001         }
1002         writer.endArray();
1003     }
1004     writer.endObject();
1005 }
1006 
ClearCommand(SkColor color)1007 ClearCommand::ClearCommand(SkColor color) : INHERITED(kClear_OpType) { fColor = color; }
1008 
execute(SkCanvas * canvas) const1009 void ClearCommand::execute(SkCanvas* canvas) const { canvas->clear(fColor); }
1010 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1011 void ClearCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1012     INHERITED::toJSON(writer, urlDataManager);
1013     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
1014     MakeJsonColor(writer, fColor);
1015 }
1016 
ClipPathCommand(const SkPath & path,SkClipOp op,bool doAA)1017 ClipPathCommand::ClipPathCommand(const SkPath& path, SkClipOp op, bool doAA)
1018         : INHERITED(kClipPath_OpType) {
1019     fPath = path;
1020     fOp   = op;
1021     fDoAA = doAA;
1022 }
1023 
execute(SkCanvas * canvas) const1024 void ClipPathCommand::execute(SkCanvas* canvas) const { canvas->clipPath(fPath, fOp, fDoAA); }
1025 
render(SkCanvas * canvas) const1026 bool ClipPathCommand::render(SkCanvas* canvas) const {
1027     render_path(canvas, fPath);
1028     return true;
1029 }
1030 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1031 void ClipPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1032     INHERITED::toJSON(writer, urlDataManager);
1033     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1034     MakeJsonPath(writer, fPath);
1035     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1036     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1037 }
1038 
ClipRegionCommand(const SkRegion & region,SkClipOp op)1039 ClipRegionCommand::ClipRegionCommand(const SkRegion& region, SkClipOp op)
1040         : INHERITED(kClipRegion_OpType) {
1041     fRegion = region;
1042     fOp     = op;
1043 }
1044 
execute(SkCanvas * canvas) const1045 void ClipRegionCommand::execute(SkCanvas* canvas) const { canvas->clipRegion(fRegion, fOp); }
1046 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1047 void ClipRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1048     INHERITED::toJSON(writer, urlDataManager);
1049     writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1050     MakeJsonRegion(writer, fRegion);
1051     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1052 }
1053 
ClipRectCommand(const SkRect & rect,SkClipOp op,bool doAA)1054 ClipRectCommand::ClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA)
1055         : INHERITED(kClipRect_OpType) {
1056     fRect = rect;
1057     fOp   = op;
1058     fDoAA = doAA;
1059 }
1060 
execute(SkCanvas * canvas) const1061 void ClipRectCommand::execute(SkCanvas* canvas) const { canvas->clipRect(fRect, fOp, fDoAA); }
1062 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1063 void ClipRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1064     INHERITED::toJSON(writer, urlDataManager);
1065     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1066     MakeJsonRect(writer, fRect);
1067     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1068     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1069 
1070     SkString desc;
1071     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1072 }
1073 
ClipRRectCommand(const SkRRect & rrect,SkClipOp op,bool doAA)1074 ClipRRectCommand::ClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA)
1075         : INHERITED(kClipRRect_OpType) {
1076     fRRect = rrect;
1077     fOp    = op;
1078     fDoAA  = doAA;
1079 }
1080 
execute(SkCanvas * canvas) const1081 void ClipRRectCommand::execute(SkCanvas* canvas) const { canvas->clipRRect(fRRect, fOp, fDoAA); }
1082 
render(SkCanvas * canvas) const1083 bool ClipRRectCommand::render(SkCanvas* canvas) const {
1084     render_rrect(canvas, fRRect);
1085     return true;
1086 }
1087 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1088 void ClipRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1089     INHERITED::toJSON(writer, urlDataManager);
1090     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1091     make_json_rrect(writer, fRRect);
1092     writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1093     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1094 }
1095 
ConcatCommand(const SkMatrix & matrix)1096 ConcatCommand::ConcatCommand(const SkMatrix& matrix) : INHERITED(kConcat_OpType) {
1097     fMatrix = matrix;
1098 }
1099 
execute(SkCanvas * canvas) const1100 void ConcatCommand::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); }
1101 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1102 void ConcatCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1103     INHERITED::toJSON(writer, urlDataManager);
1104     writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
1105     MakeJsonMatrix(writer, fMatrix);
1106 }
1107 
1108 ////
1109 
DrawAnnotationCommand(const SkRect & rect,const char key[],sk_sp<SkData> value)1110 DrawAnnotationCommand::DrawAnnotationCommand(const SkRect& rect,
1111                                              const char    key[],
1112                                              sk_sp<SkData> value)
1113         : INHERITED(kDrawAnnotation_OpType), fRect(rect), fKey(key), fValue(std::move(value)) {}
1114 
execute(SkCanvas * canvas) const1115 void DrawAnnotationCommand::execute(SkCanvas* canvas) const {
1116     canvas->drawAnnotation(fRect, fKey.c_str(), fValue);
1117 }
1118 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1119 void DrawAnnotationCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1120     INHERITED::toJSON(writer, urlDataManager);
1121 
1122     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1123     MakeJsonRect(writer, fRect);
1124     writer.appendString("key", fKey.c_str());
1125     if (fValue.get()) {
1126         // TODO: dump out the "value"
1127     }
1128 
1129     SkString desc;
1130     str_append(&desc, fRect)->appendf(" %s", fKey.c_str());
1131     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, desc.c_str());
1132 }
1133 
1134 ////
1135 
DrawBitmapCommand(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)1136 DrawBitmapCommand::DrawBitmapCommand(const SkBitmap& bitmap,
1137                                      SkScalar        left,
1138                                      SkScalar        top,
1139                                      const SkPaint*  paint)
1140         : INHERITED(kDrawBitmap_OpType), fBitmap(bitmap), fLeft(left), fTop(top), fPaint(paint) {}
1141 
execute(SkCanvas * canvas) const1142 void DrawBitmapCommand::execute(SkCanvas* canvas) const {
1143     canvas->drawBitmap(fBitmap, fLeft, fTop, fPaint.getMaybeNull());
1144 }
1145 
render(SkCanvas * canvas) const1146 bool DrawBitmapCommand::render(SkCanvas* canvas) const {
1147     render_bitmap(canvas, fBitmap);
1148     return true;
1149 }
1150 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1151 void DrawBitmapCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1152     INHERITED::toJSON(writer, urlDataManager);
1153     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1154     flatten(fBitmap, writer, urlDataManager);
1155     writer.endObject();
1156     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1157     MakeJsonPoint(writer, fLeft, fTop);
1158     if (fPaint.isValid()) {
1159         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1160         MakeJsonPaint(writer, *fPaint, urlDataManager);
1161     }
1162 }
1163 
DrawBitmapLatticeCommand(const SkBitmap & bitmap,const SkCanvas::Lattice & lattice,const SkRect & dst,const SkPaint * paint)1164 DrawBitmapLatticeCommand::DrawBitmapLatticeCommand(const SkBitmap&          bitmap,
1165                                                    const SkCanvas::Lattice& lattice,
1166                                                    const SkRect&            dst,
1167                                                    const SkPaint*           paint)
1168         : INHERITED(kDrawBitmapLattice_OpType)
1169         , fBitmap(bitmap)
1170         , fLattice(lattice)
1171         , fDst(dst)
1172         , fPaint(paint) {}
1173 
execute(SkCanvas * canvas) const1174 void DrawBitmapLatticeCommand::execute(SkCanvas* canvas) const {
1175     canvas->drawBitmapLattice(fBitmap, fLattice, fDst, fPaint.getMaybeNull());
1176 }
1177 
render(SkCanvas * canvas) const1178 bool DrawBitmapLatticeCommand::render(SkCanvas* canvas) const {
1179     SkAutoCanvasRestore acr(canvas, true);
1180     canvas->clear(0xFFFFFFFF);
1181 
1182     xlate_and_scale_to_bounds(canvas, fDst);
1183 
1184     this->execute(canvas);
1185     return true;
1186 }
1187 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1188 void DrawBitmapLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1189     INHERITED::toJSON(writer, urlDataManager);
1190     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1191     flatten(fBitmap, writer, urlDataManager);
1192     writer.endObject();  // bitmap
1193 
1194     writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
1195     MakeJsonLattice(writer, fLattice);
1196     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1197     MakeJsonRect(writer, fDst);
1198     if (fPaint.isValid()) {
1199         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1200         MakeJsonPaint(writer, *fPaint, urlDataManager);
1201     }
1202 
1203     SkString desc;
1204     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1205 }
1206 
DrawBitmapNineCommand(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1207 DrawBitmapNineCommand::DrawBitmapNineCommand(const SkBitmap& bitmap,
1208                                              const SkIRect&  center,
1209                                              const SkRect&   dst,
1210                                              const SkPaint*  paint)
1211         : INHERITED(kDrawBitmapNine_OpType)
1212         , fBitmap(bitmap)
1213         , fCenter(center)
1214         , fDst(dst)
1215         , fPaint(paint) {}
1216 
execute(SkCanvas * canvas) const1217 void DrawBitmapNineCommand::execute(SkCanvas* canvas) const {
1218     canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaint.getMaybeNull());
1219 }
1220 
render(SkCanvas * canvas) const1221 bool DrawBitmapNineCommand::render(SkCanvas* canvas) const {
1222     SkRect tmp = SkRect::Make(fCenter);
1223     render_bitmap(canvas, fBitmap, &tmp);
1224     return true;
1225 }
1226 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1227 void DrawBitmapNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1228     INHERITED::toJSON(writer, urlDataManager);
1229     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1230     flatten(fBitmap, writer, urlDataManager);
1231     writer.endObject();  // bitmap
1232 
1233     writer.appendName(DEBUGCANVAS_ATTRIBUTE_CENTER);
1234     MakeJsonIRect(writer, fCenter);
1235     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1236     MakeJsonRect(writer, fDst);
1237     if (fPaint.isValid()) {
1238         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1239         MakeJsonPaint(writer, *fPaint, urlDataManager);
1240     }
1241 }
1242 
DrawBitmapRectCommand(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1243 DrawBitmapRectCommand::DrawBitmapRectCommand(const SkBitmap&             bitmap,
1244                                              const SkRect*               src,
1245                                              const SkRect&               dst,
1246                                              const SkPaint*              paint,
1247                                              SkCanvas::SrcRectConstraint constraint)
1248         : INHERITED(kDrawBitmapRect_OpType)
1249         , fBitmap(bitmap)
1250         , fSrc(src)
1251         , fDst(dst)
1252         , fPaint(paint)
1253         , fConstraint(constraint) {}
1254 
execute(SkCanvas * canvas) const1255 void DrawBitmapRectCommand::execute(SkCanvas* canvas) const {
1256     canvas->legacy_drawBitmapRect(
1257             fBitmap, fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
1258 }
1259 
render(SkCanvas * canvas) const1260 bool DrawBitmapRectCommand::render(SkCanvas* canvas) const {
1261     render_bitmap(canvas, fBitmap, fSrc.getMaybeNull());
1262     return true;
1263 }
1264 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1265 void DrawBitmapRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1266     INHERITED::toJSON(writer, urlDataManager);
1267     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1268     flatten(fBitmap, writer, urlDataManager);
1269     writer.endObject();  // bitmap
1270 
1271     if (fSrc.isValid()) {
1272         writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1273         MakeJsonRect(writer, *fSrc);
1274     }
1275     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1276     MakeJsonRect(writer, fDst);
1277     if (fPaint.isValid()) {
1278         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1279         MakeJsonPaint(writer, *fPaint, urlDataManager);
1280     }
1281     if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1282         writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1283     }
1284 
1285     SkString desc;
1286     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1287 }
1288 
DrawImageCommand(const SkImage * image,SkScalar left,SkScalar top,const SkPaint * paint)1289 DrawImageCommand::DrawImageCommand(const SkImage* image,
1290                                    SkScalar       left,
1291                                    SkScalar       top,
1292                                    const SkPaint* paint)
1293         : INHERITED(kDrawImage_OpType)
1294         , fImage(SkRef(image))
1295         , fLeft(left)
1296         , fTop(top)
1297         , fPaint(paint) {}
1298 
execute(SkCanvas * canvas) const1299 void DrawImageCommand::execute(SkCanvas* canvas) const {
1300     canvas->drawImage(fImage.get(), fLeft, fTop, fPaint.getMaybeNull());
1301 }
1302 
render(SkCanvas * canvas) const1303 bool DrawImageCommand::render(SkCanvas* canvas) const {
1304     SkAutoCanvasRestore acr(canvas, true);
1305     canvas->clear(0xFFFFFFFF);
1306 
1307     xlate_and_scale_to_bounds(
1308             canvas,
1309             SkRect::MakeXYWH(
1310                     fLeft, fTop, SkIntToScalar(fImage->width()), SkIntToScalar(fImage->height())));
1311     this->execute(canvas);
1312     return true;
1313 }
1314 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1315 void DrawImageCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1316     INHERITED::toJSON(writer, urlDataManager);
1317     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1318     flatten(*fImage, writer, urlDataManager);
1319     writer.endObject();  // image
1320 
1321     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1322     MakeJsonPoint(writer, fLeft, fTop);
1323     if (fPaint.isValid()) {
1324         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1325         MakeJsonPaint(writer, *fPaint, urlDataManager);
1326     }
1327 
1328     writer.appendU32(DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID, fImage->uniqueID());
1329     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_WIDTH, fImage->width());
1330     writer.appendS32(DEBUGCANVAS_ATTRIBUTE_HEIGHT, fImage->height());
1331     switch (fImage->alphaType()) {
1332         case kOpaque_SkAlphaType:
1333             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_OPAQUE);
1334             break;
1335         case kPremul_SkAlphaType:
1336             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_PREMUL);
1337             break;
1338         case kUnpremul_SkAlphaType:
1339             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNPREMUL);
1340             break;
1341         default:
1342             writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNKNOWN);
1343             break;
1344     }
1345 }
1346 
DrawImageLatticeCommand(const SkImage * image,const SkCanvas::Lattice & lattice,const SkRect & dst,const SkPaint * paint)1347 DrawImageLatticeCommand::DrawImageLatticeCommand(const SkImage*           image,
1348                                                  const SkCanvas::Lattice& lattice,
1349                                                  const SkRect&            dst,
1350                                                  const SkPaint*           paint)
1351         : INHERITED(kDrawImageLattice_OpType)
1352         , fImage(SkRef(image))
1353         , fLattice(lattice)
1354         , fDst(dst)
1355         , fPaint(paint) {}
1356 
execute(SkCanvas * canvas) const1357 void DrawImageLatticeCommand::execute(SkCanvas* canvas) const {
1358     canvas->drawImageLattice(fImage.get(), fLattice, fDst, fPaint.getMaybeNull());
1359 }
1360 
render(SkCanvas * canvas) const1361 bool DrawImageLatticeCommand::render(SkCanvas* canvas) const {
1362     SkAutoCanvasRestore acr(canvas, true);
1363     canvas->clear(0xFFFFFFFF);
1364 
1365     xlate_and_scale_to_bounds(canvas, fDst);
1366 
1367     this->execute(canvas);
1368     return true;
1369 }
1370 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1371 void DrawImageLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1372     INHERITED::toJSON(writer, urlDataManager);
1373     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1374     flatten(*fImage, writer, urlDataManager);
1375     writer.endObject();  // image
1376 
1377     writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
1378     MakeJsonLattice(writer, fLattice);
1379     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1380     MakeJsonRect(writer, fDst);
1381     if (fPaint.isValid()) {
1382         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1383         MakeJsonPaint(writer, *fPaint, urlDataManager);
1384     }
1385 
1386     SkString desc;
1387     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1388 }
1389 
DrawImageRectCommand(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1390 DrawImageRectCommand::DrawImageRectCommand(const SkImage*              image,
1391                                            const SkRect*               src,
1392                                            const SkRect&               dst,
1393                                            const SkPaint*              paint,
1394                                            SkCanvas::SrcRectConstraint constraint)
1395         : INHERITED(kDrawImageRect_OpType)
1396         , fImage(SkRef(image))
1397         , fSrc(src)
1398         , fDst(dst)
1399         , fPaint(paint)
1400         , fConstraint(constraint) {}
1401 
execute(SkCanvas * canvas) const1402 void DrawImageRectCommand::execute(SkCanvas* canvas) const {
1403     canvas->legacy_drawImageRect(
1404             fImage.get(), fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
1405 }
1406 
render(SkCanvas * canvas) const1407 bool DrawImageRectCommand::render(SkCanvas* canvas) const {
1408     SkAutoCanvasRestore acr(canvas, true);
1409     canvas->clear(0xFFFFFFFF);
1410 
1411     xlate_and_scale_to_bounds(canvas, fDst);
1412 
1413     this->execute(canvas);
1414     return true;
1415 }
1416 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1417 void DrawImageRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1418     INHERITED::toJSON(writer, urlDataManager);
1419     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1420     flatten(*fImage, writer, urlDataManager);
1421     writer.endObject();  // image
1422 
1423     if (fSrc.isValid()) {
1424         writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1425         MakeJsonRect(writer, *fSrc);
1426     }
1427     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1428     MakeJsonRect(writer, fDst);
1429     if (fPaint.isValid()) {
1430         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1431         MakeJsonPaint(writer, *fPaint, urlDataManager);
1432     }
1433     if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1434         writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1435     }
1436 
1437     SkString desc;
1438     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1439 }
1440 
DrawImageNineCommand(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1441 DrawImageNineCommand::DrawImageNineCommand(const SkImage* image,
1442                                            const SkIRect& center,
1443                                            const SkRect&  dst,
1444                                            const SkPaint* paint)
1445         : INHERITED(kDrawImageNine_OpType)
1446         , fImage(SkRef(image))
1447         , fCenter(center)
1448         , fDst(dst)
1449         , fPaint(paint) {}
1450 
execute(SkCanvas * canvas) const1451 void DrawImageNineCommand::execute(SkCanvas* canvas) const {
1452     canvas->drawImageNine(fImage.get(), fCenter, fDst, fPaint.getMaybeNull());
1453 }
1454 
render(SkCanvas * canvas) const1455 bool DrawImageNineCommand::render(SkCanvas* canvas) const {
1456     SkAutoCanvasRestore acr(canvas, true);
1457     canvas->clear(0xFFFFFFFF);
1458 
1459     xlate_and_scale_to_bounds(canvas, fDst);
1460 
1461     this->execute(canvas);
1462     return true;
1463 }
1464 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1465 void DrawImageNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1466     INHERITED::toJSON(writer, urlDataManager);
1467     writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1468     flatten(*fImage, writer, urlDataManager);
1469     writer.endObject();  // image
1470 
1471     writer.appendName(DEBUGCANVAS_ATTRIBUTE_CENTER);
1472     MakeJsonIRect(writer, fCenter);
1473     writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1474     MakeJsonRect(writer, fDst);
1475     if (fPaint.isValid()) {
1476         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1477         MakeJsonPaint(writer, *fPaint, urlDataManager);
1478     }
1479 }
1480 
DrawOvalCommand(const SkRect & oval,const SkPaint & paint)1481 DrawOvalCommand::DrawOvalCommand(const SkRect& oval, const SkPaint& paint)
1482         : INHERITED(kDrawOval_OpType) {
1483     fOval  = oval;
1484     fPaint = paint;
1485 }
1486 
execute(SkCanvas * canvas) const1487 void DrawOvalCommand::execute(SkCanvas* canvas) const { canvas->drawOval(fOval, fPaint); }
1488 
render(SkCanvas * canvas) const1489 bool DrawOvalCommand::render(SkCanvas* canvas) const {
1490     canvas->clear(0xFFFFFFFF);
1491     canvas->save();
1492 
1493     xlate_and_scale_to_bounds(canvas, fOval);
1494 
1495     SkPaint p;
1496     p.setColor(SK_ColorBLACK);
1497     p.setStyle(SkPaint::kStroke_Style);
1498 
1499     canvas->drawOval(fOval, p);
1500     canvas->restore();
1501 
1502     return true;
1503 }
1504 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1505 void DrawOvalCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1506     INHERITED::toJSON(writer, urlDataManager);
1507     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1508     MakeJsonRect(writer, fOval);
1509     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1510     MakeJsonPaint(writer, fPaint, urlDataManager);
1511 }
1512 
DrawArcCommand(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)1513 DrawArcCommand::DrawArcCommand(const SkRect&  oval,
1514                                SkScalar       startAngle,
1515                                SkScalar       sweepAngle,
1516                                bool           useCenter,
1517                                const SkPaint& paint)
1518         : INHERITED(kDrawArc_OpType) {
1519     fOval       = oval;
1520     fStartAngle = startAngle;
1521     fSweepAngle = sweepAngle;
1522     fUseCenter  = useCenter;
1523     fPaint      = paint;
1524 }
1525 
execute(SkCanvas * canvas) const1526 void DrawArcCommand::execute(SkCanvas* canvas) const {
1527     canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, fPaint);
1528 }
1529 
render(SkCanvas * canvas) const1530 bool DrawArcCommand::render(SkCanvas* canvas) const {
1531     canvas->clear(0xFFFFFFFF);
1532     canvas->save();
1533 
1534     xlate_and_scale_to_bounds(canvas, fOval);
1535 
1536     SkPaint p;
1537     p.setColor(SK_ColorBLACK);
1538     p.setStyle(SkPaint::kStroke_Style);
1539 
1540     canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, p);
1541     canvas->restore();
1542 
1543     return true;
1544 }
1545 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1546 void DrawArcCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1547     INHERITED::toJSON(writer, urlDataManager);
1548     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1549     MakeJsonRect(writer, fOval);
1550     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_STARTANGLE, fStartAngle);
1551     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE, fSweepAngle);
1552     writer.appendBool(DEBUGCANVAS_ATTRIBUTE_USECENTER, fUseCenter);
1553     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1554     MakeJsonPaint(writer, fPaint, urlDataManager);
1555 }
1556 
DrawPaintCommand(const SkPaint & paint)1557 DrawPaintCommand::DrawPaintCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1558     fPaint = paint;
1559 }
1560 
execute(SkCanvas * canvas) const1561 void DrawPaintCommand::execute(SkCanvas* canvas) const { canvas->drawPaint(fPaint); }
1562 
render(SkCanvas * canvas) const1563 bool DrawPaintCommand::render(SkCanvas* canvas) const {
1564     canvas->clear(0xFFFFFFFF);
1565     canvas->drawPaint(fPaint);
1566     return true;
1567 }
1568 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1569 void DrawPaintCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1570     INHERITED::toJSON(writer, urlDataManager);
1571     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1572     MakeJsonPaint(writer, fPaint, urlDataManager);
1573 }
1574 
DrawBehindCommand(const SkPaint & paint)1575 DrawBehindCommand::DrawBehindCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1576     fPaint = paint;
1577 }
1578 
execute(SkCanvas * canvas) const1579 void DrawBehindCommand::execute(SkCanvas* canvas) const {
1580     SkCanvasPriv::DrawBehind(canvas, fPaint);
1581 }
1582 
render(SkCanvas * canvas) const1583 bool DrawBehindCommand::render(SkCanvas* canvas) const {
1584     canvas->clear(0xFFFFFFFF);
1585     SkCanvasPriv::DrawBehind(canvas, fPaint);
1586     return true;
1587 }
1588 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1589 void DrawBehindCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1590     INHERITED::toJSON(writer, urlDataManager);
1591     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1592     MakeJsonPaint(writer, fPaint, urlDataManager);
1593 }
1594 
DrawPathCommand(const SkPath & path,const SkPaint & paint)1595 DrawPathCommand::DrawPathCommand(const SkPath& path, const SkPaint& paint)
1596         : INHERITED(kDrawPath_OpType) {
1597     fPath  = path;
1598     fPaint = paint;
1599 }
1600 
execute(SkCanvas * canvas) const1601 void DrawPathCommand::execute(SkCanvas* canvas) const { canvas->drawPath(fPath, fPaint); }
1602 
render(SkCanvas * canvas) const1603 bool DrawPathCommand::render(SkCanvas* canvas) const {
1604     render_path(canvas, fPath);
1605     return true;
1606 }
1607 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1608 void DrawPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1609     INHERITED::toJSON(writer, urlDataManager);
1610     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1611     MakeJsonPath(writer, fPath);
1612     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1613     MakeJsonPaint(writer, fPaint, urlDataManager);
1614 }
1615 
DrawRegionCommand(const SkRegion & region,const SkPaint & paint)1616 DrawRegionCommand::DrawRegionCommand(const SkRegion& region, const SkPaint& paint)
1617         : INHERITED(kDrawRegion_OpType) {
1618     fRegion = region;
1619     fPaint  = paint;
1620 }
1621 
execute(SkCanvas * canvas) const1622 void DrawRegionCommand::execute(SkCanvas* canvas) const { canvas->drawRegion(fRegion, fPaint); }
1623 
render(SkCanvas * canvas) const1624 bool DrawRegionCommand::render(SkCanvas* canvas) const {
1625     render_region(canvas, fRegion);
1626     return true;
1627 }
1628 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1629 void DrawRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1630     INHERITED::toJSON(writer, urlDataManager);
1631     writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1632     MakeJsonRegion(writer, fRegion);
1633     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1634     MakeJsonPaint(writer, fPaint, urlDataManager);
1635 }
1636 
BeginDrawPictureCommand(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)1637 BeginDrawPictureCommand::BeginDrawPictureCommand(const SkPicture* picture,
1638                                                  const SkMatrix*  matrix,
1639                                                  const SkPaint*   paint)
1640         : INHERITED(kBeginDrawPicture_OpType)
1641         , fPicture(SkRef(picture))
1642         , fMatrix(matrix)
1643         , fPaint(paint) {}
1644 
execute(SkCanvas * canvas) const1645 void BeginDrawPictureCommand::execute(SkCanvas* canvas) const {
1646     if (fPaint.isValid()) {
1647         SkRect bounds = fPicture->cullRect();
1648         if (fMatrix.isValid()) {
1649             fMatrix->mapRect(&bounds);
1650         }
1651         canvas->saveLayer(&bounds, fPaint.get());
1652     }
1653 
1654     if (fMatrix.isValid()) {
1655         if (!fPaint.isValid()) {
1656             canvas->save();
1657         }
1658         canvas->concat(*fMatrix);
1659     }
1660 }
1661 
render(SkCanvas * canvas) const1662 bool BeginDrawPictureCommand::render(SkCanvas* canvas) const {
1663     canvas->clear(0xFFFFFFFF);
1664     canvas->save();
1665 
1666     xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
1667 
1668     canvas->drawPicture(fPicture.get());
1669 
1670     canvas->restore();
1671 
1672     return true;
1673 }
1674 
EndDrawPictureCommand(bool restore)1675 EndDrawPictureCommand::EndDrawPictureCommand(bool restore)
1676         : INHERITED(kEndDrawPicture_OpType), fRestore(restore) {}
1677 
execute(SkCanvas * canvas) const1678 void EndDrawPictureCommand::execute(SkCanvas* canvas) const {
1679     if (fRestore) {
1680         canvas->restore();
1681     }
1682 }
1683 
DrawPointsCommand(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1684 DrawPointsCommand::DrawPointsCommand(SkCanvas::PointMode mode,
1685                                      size_t              count,
1686                                      const SkPoint       pts[],
1687                                      const SkPaint&      paint)
1688         : INHERITED(kDrawPoints_OpType), fMode(mode), fPts(pts, count), fPaint(paint) {}
1689 
execute(SkCanvas * canvas) const1690 void DrawPointsCommand::execute(SkCanvas* canvas) const {
1691     canvas->drawPoints(fMode, fPts.count(), fPts.begin(), fPaint);
1692 }
1693 
render(SkCanvas * canvas) const1694 bool DrawPointsCommand::render(SkCanvas* canvas) const {
1695     canvas->clear(0xFFFFFFFF);
1696     canvas->save();
1697 
1698     SkRect bounds;
1699 
1700     bounds.setEmpty();
1701     for (int i = 0; i < fPts.count(); ++i) {
1702         SkRectPriv::GrowToInclude(&bounds, fPts[i]);
1703     }
1704 
1705     xlate_and_scale_to_bounds(canvas, bounds);
1706 
1707     SkPaint p;
1708     p.setColor(SK_ColorBLACK);
1709     p.setStyle(SkPaint::kStroke_Style);
1710 
1711     canvas->drawPoints(fMode, fPts.count(), fPts.begin(), p);
1712     canvas->restore();
1713 
1714     return true;
1715 }
1716 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1717 void DrawPointsCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1718     INHERITED::toJSON(writer, urlDataManager);
1719     writer.appendString(DEBUGCANVAS_ATTRIBUTE_MODE, pointmode_name(fMode));
1720     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POINTS);
1721     for (int i = 0; i < fPts.count(); i++) {
1722         MakeJsonPoint(writer, fPts[i]);
1723     }
1724     writer.endArray();  // points
1725     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1726     MakeJsonPaint(writer, fPaint, urlDataManager);
1727 }
1728 
DrawTextBlobCommand(sk_sp<SkTextBlob> blob,SkScalar x,SkScalar y,const SkPaint & paint)1729 DrawTextBlobCommand::DrawTextBlobCommand(sk_sp<SkTextBlob> blob,
1730                                          SkScalar          x,
1731                                          SkScalar          y,
1732                                          const SkPaint&    paint)
1733         : INHERITED(kDrawTextBlob_OpType)
1734         , fBlob(std::move(blob))
1735         , fXPos(x)
1736         , fYPos(y)
1737         , fPaint(paint) {}
1738 
execute(SkCanvas * canvas) const1739 void DrawTextBlobCommand::execute(SkCanvas* canvas) const {
1740     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1741 }
1742 
render(SkCanvas * canvas) const1743 bool DrawTextBlobCommand::render(SkCanvas* canvas) const {
1744     canvas->clear(SK_ColorWHITE);
1745     canvas->save();
1746 
1747     SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
1748     xlate_and_scale_to_bounds(canvas, bounds);
1749 
1750     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1751 
1752     canvas->restore();
1753 
1754     return true;
1755 }
1756 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1757 void DrawTextBlobCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1758     INHERITED::toJSON(writer, urlDataManager);
1759     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_RUNS);
1760     SkTextBlobRunIterator iter(fBlob.get());
1761     while (!iter.done()) {
1762         writer.beginObject();  // run
1763         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_GLYPHS);
1764         for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1765             writer.appendU32(iter.glyphs()[i]);
1766         }
1767         writer.endArray();  // glyphs
1768         if (iter.positioning() != SkTextBlobRunIterator::kDefault_Positioning) {
1769             writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POSITIONS);
1770             const SkScalar* iterPositions = iter.pos();
1771             for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1772                 switch (iter.positioning()) {
1773                     case SkTextBlobRunIterator::kFull_Positioning:
1774                         MakeJsonPoint(writer, iterPositions[i * 2], iterPositions[i * 2 + 1]);
1775                         break;
1776                     case SkTextBlobRunIterator::kHorizontal_Positioning:
1777                         writer.appendFloat(iterPositions[i]);
1778                         break;
1779                     case SkTextBlobRunIterator::kDefault_Positioning: break;
1780                     case SkTextBlobRunIterator::kRSXform_Positioning:
1781                         // TODO_RSXFORM_BLOB
1782                         break;
1783                 }
1784             }
1785             writer.endArray();  // positions
1786         }
1787         writer.appendName(DEBUGCANVAS_ATTRIBUTE_FONT);
1788         MakeJsonFont(iter.font(), writer, urlDataManager);
1789         writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1790         MakeJsonPoint(writer, iter.offset());
1791 
1792         writer.endObject();  // run
1793         iter.next();
1794     }
1795     writer.endArray();  // runs
1796     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_X, fXPos);
1797     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_Y, fYPos);
1798     SkRect bounds = fBlob->bounds();
1799     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1800     MakeJsonRect(writer, bounds);
1801     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1802     MakeJsonPaint(writer, fPaint, urlDataManager);
1803 
1804     SkString desc;
1805     // make the bounds local by applying the x,y
1806     bounds.offset(fXPos, fYPos);
1807     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, bounds)->c_str());
1808 }
1809 
DrawPatchCommand(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)1810 DrawPatchCommand::DrawPatchCommand(const SkPoint  cubics[12],
1811                                    const SkColor  colors[4],
1812                                    const SkPoint  texCoords[4],
1813                                    SkBlendMode    bmode,
1814                                    const SkPaint& paint)
1815         : INHERITED(kDrawPatch_OpType), fBlendMode(bmode) {
1816     memcpy(fCubics, cubics, sizeof(fCubics));
1817     if (colors != nullptr) {
1818         memcpy(fColors, colors, sizeof(fColors));
1819         fColorsPtr = fColors;
1820     } else {
1821         fColorsPtr = nullptr;
1822     }
1823     if (texCoords != nullptr) {
1824         memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
1825         fTexCoordsPtr = fTexCoords;
1826     } else {
1827         fTexCoordsPtr = nullptr;
1828     }
1829     fPaint = paint;
1830 }
1831 
execute(SkCanvas * canvas) const1832 void DrawPatchCommand::execute(SkCanvas* canvas) const {
1833     canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fBlendMode, fPaint);
1834 }
1835 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1836 void DrawPatchCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1837     INHERITED::toJSON(writer, urlDataManager);
1838     writer.beginArray(DEBUGCANVAS_ATTRIBUTE_CUBICS);
1839     for (int i = 0; i < 12; i++) {
1840         MakeJsonPoint(writer, fCubics[i]);
1841     }
1842     writer.endArray();  // cubics
1843     if (fColorsPtr != nullptr) {
1844         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_COLORS);
1845         for (int i = 0; i < 4; i++) {
1846             MakeJsonColor(writer, fColorsPtr[i]);
1847         }
1848         writer.endArray();  // colors
1849     }
1850     if (fTexCoordsPtr != nullptr) {
1851         writer.beginArray(DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS);
1852         for (int i = 0; i < 4; i++) {
1853             MakeJsonPoint(writer, fTexCoords[i]);
1854         }
1855         writer.endArray();  // texCoords
1856     }
1857     // fBlendMode
1858 }
1859 
DrawRectCommand(const SkRect & rect,const SkPaint & paint)1860 DrawRectCommand::DrawRectCommand(const SkRect& rect, const SkPaint& paint)
1861         : INHERITED(kDrawRect_OpType) {
1862     fRect  = rect;
1863     fPaint = paint;
1864 }
1865 
execute(SkCanvas * canvas) const1866 void DrawRectCommand::execute(SkCanvas* canvas) const { canvas->drawRect(fRect, fPaint); }
1867 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1868 void DrawRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1869     INHERITED::toJSON(writer, urlDataManager);
1870     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1871     MakeJsonRect(writer, fRect);
1872     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1873     MakeJsonPaint(writer, fPaint, urlDataManager);
1874 
1875     SkString desc;
1876     writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1877 }
1878 
DrawRRectCommand(const SkRRect & rrect,const SkPaint & paint)1879 DrawRRectCommand::DrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
1880         : INHERITED(kDrawRRect_OpType) {
1881     fRRect = rrect;
1882     fPaint = paint;
1883 }
1884 
execute(SkCanvas * canvas) const1885 void DrawRRectCommand::execute(SkCanvas* canvas) const { canvas->drawRRect(fRRect, fPaint); }
1886 
render(SkCanvas * canvas) const1887 bool DrawRRectCommand::render(SkCanvas* canvas) const {
1888     render_rrect(canvas, fRRect);
1889     return true;
1890 }
1891 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1892 void DrawRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1893     INHERITED::toJSON(writer, urlDataManager);
1894     writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1895     make_json_rrect(writer, fRRect);
1896     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1897     MakeJsonPaint(writer, fPaint, urlDataManager);
1898 }
1899 
DrawDRRectCommand(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1900 DrawDRRectCommand::DrawDRRectCommand(const SkRRect& outer,
1901                                      const SkRRect& inner,
1902                                      const SkPaint& paint)
1903         : INHERITED(kDrawDRRect_OpType) {
1904     fOuter = outer;
1905     fInner = inner;
1906     fPaint = paint;
1907 }
1908 
execute(SkCanvas * canvas) const1909 void DrawDRRectCommand::execute(SkCanvas* canvas) const {
1910     canvas->drawDRRect(fOuter, fInner, fPaint);
1911 }
1912 
render(SkCanvas * canvas) const1913 bool DrawDRRectCommand::render(SkCanvas* canvas) const {
1914     render_drrect(canvas, fOuter, fInner);
1915     return true;
1916 }
1917 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1918 void DrawDRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1919     INHERITED::toJSON(writer, urlDataManager);
1920     writer.appendName(DEBUGCANVAS_ATTRIBUTE_OUTER);
1921     make_json_rrect(writer, fOuter);
1922     writer.appendName(DEBUGCANVAS_ATTRIBUTE_INNER);
1923     make_json_rrect(writer, fInner);
1924     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1925     MakeJsonPaint(writer, fPaint, urlDataManager);
1926 }
1927 
DrawShadowCommand(const SkPath & path,const SkDrawShadowRec & rec)1928 DrawShadowCommand::DrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec)
1929         : INHERITED(kDrawShadow_OpType) {
1930     fPath      = path;
1931     fShadowRec = rec;
1932 }
1933 
execute(SkCanvas * canvas) const1934 void DrawShadowCommand::execute(SkCanvas* canvas) const {
1935     canvas->private_draw_shadow_rec(fPath, fShadowRec);
1936 }
1937 
render(SkCanvas * canvas) const1938 bool DrawShadowCommand::render(SkCanvas* canvas) const {
1939     render_shadow(canvas, fPath, fShadowRec);
1940     return true;
1941 }
1942 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1943 void DrawShadowCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1944     INHERITED::toJSON(writer, urlDataManager);
1945 
1946     bool geometricOnly = SkToBool(fShadowRec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
1947     bool transparentOccluder =
1948             SkToBool(fShadowRec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1949 
1950     writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1951     MakeJsonPath(writer, fPath);
1952     writer.appendName(DEBUGCANVAS_ATTRIBUTE_ZPLANE);
1953     MakeJsonPoint3(writer, fShadowRec.fZPlaneParams);
1954     writer.appendName(DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION);
1955     MakeJsonPoint3(writer, fShadowRec.fLightPos);
1956     writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS, fShadowRec.fLightRadius);
1957     writer.appendName(DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR);
1958     MakeJsonColor(writer, fShadowRec.fAmbientColor);
1959     writer.appendName(DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR);
1960     MakeJsonColor(writer, fShadowRec.fSpotColor);
1961     store_bool(writer, DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC, transparentOccluder, false);
1962     store_bool(writer, DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY, geometricOnly, false);
1963 }
1964 
1965 ///////////////////////////////////////////////////////////////////////////////////////////////////
1966 
DrawEdgeAAQuadCommand(const SkRect & rect,const SkPoint clip[],SkCanvas::QuadAAFlags aa,SkColor color,SkBlendMode mode)1967 DrawEdgeAAQuadCommand::DrawEdgeAAQuadCommand(const SkRect&         rect,
1968                                              const SkPoint         clip[],
1969                                              SkCanvas::QuadAAFlags aa,
1970                                              SkColor               color,
1971                                              SkBlendMode           mode)
1972         : INHERITED(kDrawEdgeAAQuad_OpType)
1973         , fRect(rect)
1974         , fHasClip(clip != nullptr)
1975         , fAA(aa)
1976         , fColor(color)
1977         , fMode(mode) {
1978     if (clip) {
1979         for (int i = 0; i < 4; ++i) {
1980             fClip[i] = clip[i];
1981         }
1982     }
1983 }
1984 
execute(SkCanvas * canvas) const1985 void DrawEdgeAAQuadCommand::execute(SkCanvas* canvas) const {
1986     canvas->experimental_DrawEdgeAAQuad(fRect, fHasClip ? fClip : nullptr, fAA, fColor, fMode);
1987 }
1988 
DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],int count,const SkPoint dstClips[],const SkMatrix preViewMatrices[],const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1989 DrawEdgeAAImageSetCommand::DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],
1990                                                      int                           count,
1991                                                      const SkPoint                 dstClips[],
1992                                                      const SkMatrix              preViewMatrices[],
1993                                                      const SkPaint*              paint,
1994                                                      SkCanvas::SrcRectConstraint constraint)
1995         : INHERITED(kDrawEdgeAAImageSet_OpType)
1996         , fSet(count)
1997         , fCount(count)
1998         , fPaint(paint)
1999         , fConstraint(constraint) {
2000     int totalDstClipCount, totalMatrixCount;
2001     SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);
2002 
2003     std::copy_n(set, count, fSet.get());
2004     fDstClips.reset(totalDstClipCount);
2005     std::copy_n(dstClips, totalDstClipCount, fDstClips.get());
2006     fPreViewMatrices.reset(totalMatrixCount);
2007     std::copy_n(preViewMatrices, totalMatrixCount, fPreViewMatrices.get());
2008 }
2009 
execute(SkCanvas * canvas) const2010 void DrawEdgeAAImageSetCommand::execute(SkCanvas* canvas) const {
2011     canvas->experimental_DrawEdgeAAImageSet(fSet.get(),
2012                                             fCount,
2013                                             fDstClips.get(),
2014                                             fPreViewMatrices.get(),
2015                                             fPaint.getMaybeNull(),
2016                                             fConstraint);
2017 }
2018 
2019 ///////////////////////////////////////////////////////////////////////////////////////////////////
2020 
DrawDrawableCommand(SkDrawable * drawable,const SkMatrix * matrix)2021 DrawDrawableCommand::DrawDrawableCommand(SkDrawable* drawable, const SkMatrix* matrix)
2022         : INHERITED(kDrawDrawable_OpType), fDrawable(SkRef(drawable)), fMatrix(matrix) {}
2023 
execute(SkCanvas * canvas) const2024 void DrawDrawableCommand::execute(SkCanvas* canvas) const {
2025     canvas->drawDrawable(fDrawable.get(), fMatrix.getMaybeNull());
2026 }
2027 
2028 ///////////////////////////////////////////////////////////////////////////////////////////////////
2029 
DrawVerticesCommand(sk_sp<SkVertices> vertices,SkBlendMode bmode,const SkPaint & paint)2030 DrawVerticesCommand::DrawVerticesCommand(sk_sp<SkVertices> vertices,
2031                                          SkBlendMode       bmode,
2032                                          const SkPaint&    paint)
2033         : INHERITED(kDrawVertices_OpType)
2034         , fVertices(std::move(vertices))
2035         , fBlendMode(bmode)
2036         , fPaint(paint) {}
2037 
execute(SkCanvas * canvas) const2038 void DrawVerticesCommand::execute(SkCanvas* canvas) const {
2039     canvas->drawVertices(fVertices, fBlendMode, fPaint);
2040 }
2041 
2042 ///////////////////////////////////////////////////////////////////////////////////////////////////
2043 
DrawAtlasCommand(const SkImage * image,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)2044 DrawAtlasCommand::DrawAtlasCommand(const SkImage*  image,
2045                                    const SkRSXform xform[],
2046                                    const SkRect    tex[],
2047                                    const SkColor   colors[],
2048                                    int             count,
2049                                    SkBlendMode     bmode,
2050                                    const SkRect*   cull,
2051                                    const SkPaint*  paint)
2052         : INHERITED(kDrawAtlas_OpType)
2053         , fImage(SkRef(image))
2054         , fXform(xform, count)
2055         , fTex(tex, count)
2056         , fColors(colors, colors ? count : 0)
2057         , fBlendMode(bmode)
2058         , fCull(cull)
2059         , fPaint(paint) {}
2060 
execute(SkCanvas * canvas) const2061 void DrawAtlasCommand::execute(SkCanvas* canvas) const {
2062     canvas->drawAtlas(fImage.get(),
2063                       fXform.begin(),
2064                       fTex.begin(),
2065                       fColors.isEmpty() ? nullptr : fColors.begin(),
2066                       fXform.count(),
2067                       fBlendMode,
2068                       fCull.getMaybeNull(),
2069                       fPaint.getMaybeNull());
2070 }
2071 
2072 ///////////////////////////////////////////////////////////////////////////////////////////////////
2073 
RestoreCommand()2074 RestoreCommand::RestoreCommand() : INHERITED(kRestore_OpType) {}
2075 
execute(SkCanvas * canvas) const2076 void RestoreCommand::execute(SkCanvas* canvas) const { canvas->restore(); }
2077 
SaveCommand()2078 SaveCommand::SaveCommand() : INHERITED(kSave_OpType) {}
2079 
execute(SkCanvas * canvas) const2080 void SaveCommand::execute(SkCanvas* canvas) const { canvas->save(); }
2081 
SaveLayerCommand(const SkCanvas::SaveLayerRec & rec)2082 SaveLayerCommand::SaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
2083         : INHERITED(kSaveLayer_OpType)
2084         , fBounds(rec.fBounds)
2085         , fPaint(rec.fPaint)
2086         , fBackdrop(SkSafeRef(rec.fBackdrop))
2087         , fSaveLayerFlags(rec.fSaveLayerFlags) {}
2088 
execute(SkCanvas * canvas) const2089 void SaveLayerCommand::execute(SkCanvas* canvas) const {
2090     canvas->saveLayer(
2091             SkCanvas::SaveLayerRec(fBounds.getMaybeNull(), fPaint.getMaybeNull(), fSaveLayerFlags));
2092 }
2093 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2094 void SaveLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2095     INHERITED::toJSON(writer, urlDataManager);
2096     if (fBounds.isValid()) {
2097         writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
2098         MakeJsonRect(writer, *fBounds);
2099     }
2100     if (fPaint.isValid()) {
2101         writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
2102         MakeJsonPaint(writer, *fPaint, urlDataManager);
2103     }
2104     if (fBackdrop != nullptr) {
2105         writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BACKDROP);
2106         flatten(fBackdrop.get(), writer, urlDataManager);
2107         writer.endObject();  // backdrop
2108     }
2109     if (fSaveLayerFlags != 0) {
2110         SkDebugf("unsupported: saveLayer flags\n");
2111         SkASSERT(false);
2112     }
2113 }
2114 
SetMatrixCommand(const SkMatrix & matrix)2115 SetMatrixCommand::SetMatrixCommand(const SkMatrix& matrix) : INHERITED(kSetMatrix_OpType) {
2116     fMatrix = matrix;
2117 }
2118 
execute(SkCanvas * canvas) const2119 void SetMatrixCommand::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); }
2120 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2121 void SetMatrixCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2122     INHERITED::toJSON(writer, urlDataManager);
2123     writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
2124     MakeJsonMatrix(writer, fMatrix);
2125 }
2126