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