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