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