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