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
apply_paint_blend_mode(const SkPaint & paint,SkJSONWriter & writer)365 void apply_paint_blend_mode(const SkPaint& paint, SkJSONWriter& writer) {
366 const auto mode = paint.getBlendMode_or(SkBlendMode::kSrcOver);
367 if (mode != SkBlendMode::kSrcOver) {
368 writer.appendString(DEBUGCANVAS_ATTRIBUTE_BLENDMODE, SkBlendMode_Name(mode));
369 }
370 }
371
372 }; // namespace
373
MakeJsonColor(SkJSONWriter & writer,const SkColor color)374 void DrawCommand::MakeJsonColor(SkJSONWriter& writer, const SkColor color) {
375 writer.beginArray(nullptr, false);
376 writer.appendS32(SkColorGetA(color));
377 writer.appendS32(SkColorGetR(color));
378 writer.appendS32(SkColorGetG(color));
379 writer.appendS32(SkColorGetB(color));
380 writer.endArray();
381 }
382
MakeJsonColor4f(SkJSONWriter & writer,const SkColor4f & color)383 void DrawCommand::MakeJsonColor4f(SkJSONWriter& writer, const SkColor4f& color) {
384 writer.beginArray(nullptr, false);
385 writer.appendFloat(color.fA);
386 writer.appendFloat(color.fR);
387 writer.appendFloat(color.fG);
388 writer.appendFloat(color.fB);
389 writer.endArray();
390 }
391
MakeJsonPoint(SkJSONWriter & writer,const SkPoint & point)392 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, const SkPoint& point) {
393 writer.beginArray(nullptr, false);
394 writer.appendFloat(point.x());
395 writer.appendFloat(point.y());
396 writer.endArray();
397 }
398
MakeJsonPoint(SkJSONWriter & writer,SkScalar x,SkScalar y)399 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, SkScalar x, SkScalar y) {
400 writer.beginArray(nullptr, false);
401 writer.appendFloat(x);
402 writer.appendFloat(y);
403 writer.endArray();
404 }
405
MakeJsonPoint3(SkJSONWriter & writer,const SkPoint3 & point)406 void DrawCommand::MakeJsonPoint3(SkJSONWriter& writer, const SkPoint3& point) {
407 writer.beginArray(nullptr, false);
408 writer.appendFloat(point.x());
409 writer.appendFloat(point.y());
410 writer.appendFloat(point.z());
411 writer.endArray();
412 }
413
MakeJsonRect(SkJSONWriter & writer,const SkRect & rect)414 void DrawCommand::MakeJsonRect(SkJSONWriter& writer, const SkRect& rect) {
415 writer.beginArray(nullptr, false);
416 writer.appendFloat(rect.left());
417 writer.appendFloat(rect.top());
418 writer.appendFloat(rect.right());
419 writer.appendFloat(rect.bottom());
420 writer.endArray();
421 }
422
MakeJsonIRect(SkJSONWriter & writer,const SkIRect & rect)423 void DrawCommand::MakeJsonIRect(SkJSONWriter& writer, const SkIRect& rect) {
424 writer.beginArray(nullptr, false);
425 writer.appendS32(rect.left());
426 writer.appendS32(rect.top());
427 writer.appendS32(rect.right());
428 writer.appendS32(rect.bottom());
429 writer.endArray();
430 }
431
make_json_rrect(SkJSONWriter & writer,const SkRRect & rrect)432 static void make_json_rrect(SkJSONWriter& writer, const SkRRect& rrect) {
433 writer.beginArray(nullptr, false);
434 DrawCommand::MakeJsonRect(writer, rrect.rect());
435 DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperLeft_Corner));
436 DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperRight_Corner));
437 DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerRight_Corner));
438 DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerLeft_Corner));
439 writer.endArray();
440 }
441
MakeJsonMatrix(SkJSONWriter & writer,const SkMatrix & matrix)442 void DrawCommand::MakeJsonMatrix(SkJSONWriter& writer, const SkMatrix& matrix) {
443 writer.beginArray();
444 for (int r = 0; r < 3; ++r) {
445 writer.beginArray(nullptr, false);
446 for (int c = 0; c < 3; ++c) {
447 writer.appendFloat(matrix[r * 3 + c]);
448 }
449 writer.endArray();
450 }
451 writer.endArray();
452 }
453
MakeJsonMatrix44(SkJSONWriter & writer,const SkM44 & matrix)454 void DrawCommand::MakeJsonMatrix44(SkJSONWriter& writer, const SkM44& matrix) {
455 writer.beginArray();
456 for (int r = 0; r < 4; ++r) {
457 writer.beginArray(nullptr, false);
458 for (int c = 0; c < 4; ++c) {
459 writer.appendFloat(matrix.rc(r, c));
460 }
461 writer.endArray();
462 }
463 writer.endArray();
464 }
465
MakeJsonPath(SkJSONWriter & writer,const SkPath & path)466 void DrawCommand::MakeJsonPath(SkJSONWriter& writer, const SkPath& path) {
467 writer.beginObject();
468 switch (path.getFillType()) {
469 case SkPathFillType::kWinding:
470 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_WINDING);
471 break;
472 case SkPathFillType::kEvenOdd:
473 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_EVENODD);
474 break;
475 case SkPathFillType::kInverseWinding:
476 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
477 DEBUGCANVAS_FILLTYPE_INVERSEWINDING);
478 break;
479 case SkPathFillType::kInverseEvenOdd:
480 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
481 DEBUGCANVAS_FILLTYPE_INVERSEEVENODD);
482 break;
483 }
484 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_VERBS);
485 SkPath::Iter iter(path, false);
486 SkPoint pts[4];
487 SkPath::Verb verb;
488 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
489 if (verb == SkPath::kClose_Verb) {
490 writer.appendString(DEBUGCANVAS_VERB_CLOSE);
491 continue;
492 }
493 writer.beginObject(); // verb
494 switch (verb) {
495 case SkPath::kLine_Verb: {
496 writer.appendName(DEBUGCANVAS_VERB_LINE);
497 MakeJsonPoint(writer, pts[1]);
498 break;
499 }
500 case SkPath::kQuad_Verb: {
501 writer.beginArray(DEBUGCANVAS_VERB_QUAD);
502 MakeJsonPoint(writer, pts[1]);
503 MakeJsonPoint(writer, pts[2]);
504 writer.endArray(); // quad coords
505 break;
506 }
507 case SkPath::kCubic_Verb: {
508 writer.beginArray(DEBUGCANVAS_VERB_CUBIC);
509 MakeJsonPoint(writer, pts[1]);
510 MakeJsonPoint(writer, pts[2]);
511 MakeJsonPoint(writer, pts[3]);
512 writer.endArray(); // cubic coords
513 break;
514 }
515 case SkPath::kConic_Verb: {
516 writer.beginArray(DEBUGCANVAS_VERB_CONIC);
517 MakeJsonPoint(writer, pts[1]);
518 MakeJsonPoint(writer, pts[2]);
519 writer.appendFloat(iter.conicWeight());
520 writer.endArray(); // conic coords
521 break;
522 }
523 case SkPath::kMove_Verb: {
524 writer.appendName(DEBUGCANVAS_VERB_MOVE);
525 MakeJsonPoint(writer, pts[0]);
526 break;
527 }
528 case SkPath::kClose_Verb:
529 case SkPath::kDone_Verb:
530 // Unreachable
531 break;
532 }
533 writer.endObject(); // verb
534 }
535 writer.endArray(); // verbs
536 writer.endObject(); // path
537 }
538
MakeJsonRegion(SkJSONWriter & writer,const SkRegion & region)539 void DrawCommand::MakeJsonRegion(SkJSONWriter& writer, const SkRegion& region) {
540 // TODO: Actually serialize the rectangles, rather than just devolving to path
541 SkPath path;
542 region.getBoundaryPath(&path);
543 MakeJsonPath(writer, path);
544 }
545
clipop_name(SkClipOp op)546 static const char* clipop_name(SkClipOp op) {
547 switch (op) {
548 case SkClipOp::kDifference: return DEBUGCANVAS_CLIPOP_DIFFERENCE;
549 case SkClipOp::kIntersect: return DEBUGCANVAS_CLIPOP_INTERSECT;
550 default: SkASSERT(false); return "<invalid region op>";
551 }
552 }
553
pointmode_name(SkCanvas::PointMode mode)554 static const char* pointmode_name(SkCanvas::PointMode mode) {
555 switch (mode) {
556 case SkCanvas::kPoints_PointMode: return DEBUGCANVAS_POINTMODE_POINTS;
557 case SkCanvas::kLines_PointMode: return DEBUGCANVAS_POINTMODE_LINES;
558 case SkCanvas::kPolygon_PointMode: return DEBUGCANVAS_POINTMODE_POLYGON;
559 default: SkASSERT(false); return "<invalid point mode>";
560 }
561 }
562
store_scalar(SkJSONWriter & writer,const char * key,SkScalar value,SkScalar defaultValue)563 static void store_scalar(SkJSONWriter& writer,
564 const char* key,
565 SkScalar value,
566 SkScalar defaultValue) {
567 if (value != defaultValue) {
568 writer.appendFloat(key, value);
569 }
570 }
571
store_bool(SkJSONWriter & writer,const char * key,bool value,bool defaultValue)572 static void store_bool(SkJSONWriter& writer, const char* key, bool value, bool defaultValue) {
573 if (value != defaultValue) {
574 writer.appendBool(key, value);
575 }
576 }
577
encode_data(const void * bytes,size_t count,const char * contentType,UrlDataManager & urlDataManager)578 static SkString encode_data(const void* bytes,
579 size_t count,
580 const char* contentType,
581 UrlDataManager& urlDataManager) {
582 sk_sp<SkData> data(SkData::MakeWithCopy(bytes, count));
583 return urlDataManager.addData(data.get(), contentType);
584 }
585
flatten(const SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)586 void DrawCommand::flatten(const SkFlattenable* flattenable,
587 SkJSONWriter& writer,
588 UrlDataManager& urlDataManager) {
589 SkBinaryWriteBuffer buffer;
590 flattenable->flatten(buffer);
591 void* data = sk_malloc_throw(buffer.bytesWritten());
592 buffer.writeToMemory(data);
593 SkString url =
594 encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
595 writer.appendString(DEBUGCANVAS_ATTRIBUTE_NAME, flattenable->getTypeName());
596 writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
597
598 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_VALUES);
599 JsonWriteBuffer jsonBuffer(&writer, &urlDataManager);
600 flattenable->flatten(jsonBuffer);
601 writer.endObject(); // values
602
603 sk_free(data);
604 }
605
WritePNG(SkBitmap bitmap,SkWStream & out)606 void DrawCommand::WritePNG(SkBitmap bitmap, SkWStream& out) {
607 SkPixmap pm;
608 SkAssertResult(bitmap.peekPixels(&pm));
609
610 SkPngEncoder::Options options;
611 options.fZLibLevel = 1;
612 options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
613 SkPngEncoder::Encode(&out, pm, options);
614 }
615
616 // flattens an image to a Json stream, also called from shader flatten
flatten(const SkImage & image,SkJSONWriter & writer,UrlDataManager & urlDataManager)617 bool DrawCommand::flatten(const SkImage& image,
618 SkJSONWriter& writer,
619 UrlDataManager& urlDataManager) {
620 // For MSKP files, there is no need to encode the image,
621 // just report its id.
622 if (urlDataManager.hasImageIndex()) {
623 writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
624 writer.appendU64(urlDataManager.lookupImage(&image));
625 return true;
626 }
627
628 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
629 size_t rowBytes = 4 * image.width();
630 SkAutoMalloc buffer(rowBytes * image.height());
631 SkImageInfo dstInfo =
632 SkImageInfo::Make(image.dimensions(), kN32_SkColorType, kPremul_SkAlphaType);
633 // "cheat" for this debug tool and use image's context
634 GrDirectContext* dContext = nullptr;
635 #if SK_SUPPORT_GPU
636 dContext = GrAsDirectContext(as_IB(&image)->context());
637 #endif
638 if (!image.readPixels(dContext, dstInfo, buffer.get(), rowBytes, 0, 0)) {
639 SkDebugf("DrawCommand::flatten SkImage: readPixels failed\n");
640 writer.endObject();
641 return false;
642 }
643
644 SkBitmap bm;
645 bm.installPixels(dstInfo, buffer.get(), rowBytes);
646
647 SkDynamicMemoryWStream out;
648 DrawCommand::WritePNG(bm, out);
649 sk_sp<SkData> encoded = out.detachAsData();
650 if (encoded == nullptr) {
651 SkDebugf("DrawCommand::flatten SkImage: could not encode image as PNG\n");
652 writer.endObject();
653 return false;
654 }
655 auto dataPtr = encoded->data();
656 if (!dataPtr) {
657 SkDebugf("DrawCommand::flatten SkImage: encoding as PNG produced zero length data\n");
658 writer.endObject();
659 return false;
660 }
661 SkString url = encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager);
662 writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
663 writer.endObject();
664 return true;
665 }
666
color_type_name(SkColorType colorType)667 static const char* color_type_name(SkColorType colorType) {
668 switch (colorType) {
669 case kARGB_4444_SkColorType: return DEBUGCANVAS_COLORTYPE_ARGB4444;
670 case kRGBA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_RGBA8888;
671 case kBGRA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_BGRA8888;
672 case kRGB_565_SkColorType: return DEBUGCANVAS_COLORTYPE_565;
673 case kGray_8_SkColorType: return DEBUGCANVAS_COLORTYPE_GRAY8;
674 case kAlpha_8_SkColorType: return DEBUGCANVAS_COLORTYPE_ALPHA8;
675 default: SkASSERT(false); return DEBUGCANVAS_COLORTYPE_RGBA8888;
676 }
677 }
678
alpha_type_name(SkAlphaType alphaType)679 static const char* alpha_type_name(SkAlphaType alphaType) {
680 switch (alphaType) {
681 case kOpaque_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_OPAQUE;
682 case kPremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_PREMUL;
683 case kUnpremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_UNPREMUL;
684 default: SkASSERT(false); return DEBUGCANVAS_ALPHATYPE_OPAQUE;
685 }
686 }
687
flatten(const SkBitmap & bitmap,SkJSONWriter & writer,UrlDataManager & urlDataManager)688 bool DrawCommand::flatten(const SkBitmap& bitmap,
689 SkJSONWriter& writer,
690 UrlDataManager& urlDataManager) {
691 sk_sp<SkImage> image(bitmap.asImage());
692 writer.appendString(DEBUGCANVAS_ATTRIBUTE_COLOR, color_type_name(bitmap.colorType()));
693 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, alpha_type_name(bitmap.alphaType()));
694 // Image will appear to have no uses, TODO(nifong): provide the user with a useful explanation
695 bool success = flatten(*image, writer, urlDataManager);
696 return success;
697 }
698
apply_font_hinting(const SkFont & font,SkJSONWriter & writer)699 static void apply_font_hinting(const SkFont& font, SkJSONWriter& writer) {
700 SkFontHinting hinting = font.getHinting();
701 if (hinting != SkPaintDefaults_Hinting) {
702 switch (hinting) {
703 case SkFontHinting::kNone:
704 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NONE);
705 break;
706 case SkFontHinting::kSlight:
707 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_SLIGHT);
708 break;
709 case SkFontHinting::kNormal:
710 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NORMAL);
711 break;
712 case SkFontHinting::kFull:
713 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_FULL);
714 break;
715 }
716 }
717 }
718
apply_font_edging(const SkFont & font,SkJSONWriter & writer)719 static void apply_font_edging(const SkFont& font, SkJSONWriter& writer) {
720 switch (font.getEdging()) {
721 case SkFont::Edging::kAlias:
722 writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ALIAS);
723 break;
724 case SkFont::Edging::kAntiAlias:
725 writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ANTIALIAS);
726 break;
727 case SkFont::Edging::kSubpixelAntiAlias:
728 writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS);
729 break;
730 }
731 }
732
apply_paint_color(const SkPaint & paint,SkJSONWriter & writer)733 static void apply_paint_color(const SkPaint& paint, SkJSONWriter& writer) {
734 SkColor color = paint.getColor();
735 if (color != SK_ColorBLACK) {
736 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
737 DrawCommand::MakeJsonColor(writer, color);
738 }
739 }
740
apply_paint_style(const SkPaint & paint,SkJSONWriter & writer)741 static void apply_paint_style(const SkPaint& paint, SkJSONWriter& writer) {
742 SkPaint::Style style = paint.getStyle();
743 if (style != SkPaint::kFill_Style) {
744 switch (style) {
745 case SkPaint::kStroke_Style: {
746 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKE);
747 break;
748 }
749 case SkPaint::kStrokeAndFill_Style: {
750 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKEANDFILL);
751 break;
752 }
753 default: SkASSERT(false);
754 }
755 }
756 }
757
apply_paint_cap(const SkPaint & paint,SkJSONWriter & writer)758 static void apply_paint_cap(const SkPaint& paint, SkJSONWriter& writer) {
759 SkPaint::Cap cap = paint.getStrokeCap();
760 if (cap != SkPaint::kDefault_Cap) {
761 switch (cap) {
762 case SkPaint::kButt_Cap:
763 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_BUTT);
764 break;
765 case SkPaint::kRound_Cap:
766 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_ROUND);
767 break;
768 case SkPaint::kSquare_Cap:
769 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_SQUARE);
770 break;
771 default: SkASSERT(false);
772 }
773 }
774 }
775
apply_paint_join(const SkPaint & paint,SkJSONWriter & writer)776 static void apply_paint_join(const SkPaint& paint, SkJSONWriter& writer) {
777 SkPaint::Join join = paint.getStrokeJoin();
778 if (join != SkPaint::kDefault_Join) {
779 switch (join) {
780 case SkPaint::kMiter_Join:
781 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_MITER_JOIN);
782 break;
783 case SkPaint::kRound_Join:
784 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_ROUND_JOIN);
785 break;
786 case SkPaint::kBevel_Join:
787 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_BEVEL_JOIN);
788 break;
789 default: SkASSERT(false);
790 }
791 }
792 }
793
apply_paint_maskfilter(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)794 static void apply_paint_maskfilter(const SkPaint& paint,
795 SkJSONWriter& writer,
796 UrlDataManager& urlDataManager) {
797 SkMaskFilter* maskFilter = paint.getMaskFilter();
798 if (maskFilter != nullptr) {
799 SkMaskFilterBase::BlurRec blurRec;
800 if (as_MFB(maskFilter)->asABlur(&blurRec)) {
801 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BLUR);
802 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SIGMA, blurRec.fSigma);
803 switch (blurRec.fStyle) {
804 case SkBlurStyle::kNormal_SkBlurStyle:
805 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_NORMAL);
806 break;
807 case SkBlurStyle::kSolid_SkBlurStyle:
808 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_SOLID);
809 break;
810 case SkBlurStyle::kOuter_SkBlurStyle:
811 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_OUTER);
812 break;
813 case SkBlurStyle::kInner_SkBlurStyle:
814 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_INNER);
815 break;
816 default: SkASSERT(false);
817 }
818 writer.endObject(); // blur
819 } else {
820 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_MASKFILTER);
821 DrawCommand::flatten(maskFilter, writer, urlDataManager);
822 writer.endObject(); // maskFilter
823 }
824 }
825 }
826
apply_paint_patheffect(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)827 static void apply_paint_patheffect(const SkPaint& paint,
828 SkJSONWriter& writer,
829 UrlDataManager& urlDataManager) {
830 SkPathEffect* pathEffect = paint.getPathEffect();
831 if (pathEffect != nullptr) {
832 SkPathEffect::DashInfo dashInfo;
833 SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
834 if (dashType == SkPathEffect::kDash_DashType) {
835 dashInfo.fIntervals = (SkScalar*)sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
836 pathEffect->asADash(&dashInfo);
837 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_DASHING);
838 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_INTERVALS, false);
839 for (int32_t i = 0; i < dashInfo.fCount; i++) {
840 writer.appendFloat(dashInfo.fIntervals[i]);
841 }
842 writer.endArray(); // intervals
843 sk_free(dashInfo.fIntervals);
844 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_PHASE, dashInfo.fPhase);
845 writer.endObject(); // dashing
846 } else {
847 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_PATHEFFECT);
848 DrawCommand::flatten(pathEffect, writer, urlDataManager);
849 writer.endObject(); // pathEffect
850 }
851 }
852 }
853
apply_font_typeface(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)854 static void apply_font_typeface(const SkFont& font,
855 SkJSONWriter& writer,
856 UrlDataManager& urlDataManager) {
857 SkTypeface* typeface = font.getTypefaceOrDefault();
858 if (typeface != nullptr) {
859 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_TYPEFACE);
860 SkDynamicMemoryWStream buffer;
861 typeface->serialize(&buffer);
862 void* data = sk_malloc_throw(buffer.bytesWritten());
863 buffer.copyTo(data);
864 SkString url = encode_data(
865 data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
866 writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
867 sk_free(data);
868 writer.endObject();
869 }
870 }
871
apply_flattenable(const char * key,SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)872 static void apply_flattenable(const char* key,
873 SkFlattenable* flattenable,
874 SkJSONWriter& writer,
875 UrlDataManager& urlDataManager) {
876 if (flattenable != nullptr) {
877 writer.beginObject(key);
878 DrawCommand::flatten(flattenable, writer, urlDataManager);
879 writer.endObject();
880 }
881 }
882
MakeJsonPaint(SkJSONWriter & writer,const SkPaint & paint,UrlDataManager & urlDataManager)883 void DrawCommand::MakeJsonPaint(SkJSONWriter& writer,
884 const SkPaint& paint,
885 UrlDataManager& urlDataManager) {
886 writer.beginObject();
887 store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
888 store_scalar(writer,
889 DEBUGCANVAS_ATTRIBUTE_STROKEMITER,
890 paint.getStrokeMiter(),
891 SkPaintDefaults_MiterLimit);
892 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
893 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
894
895 apply_paint_color(paint, writer);
896 apply_paint_style(paint, writer);
897 apply_paint_blend_mode(paint, writer);
898 apply_paint_cap(paint, writer);
899 apply_paint_join(paint, writer);
900 apply_paint_patheffect(paint, writer, urlDataManager);
901 apply_paint_maskfilter(paint, writer, urlDataManager);
902 apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, paint.getShader(), writer, urlDataManager);
903 apply_flattenable(
904 DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER, paint.getImageFilter(), writer, urlDataManager);
905 apply_flattenable(
906 DEBUGCANVAS_ATTRIBUTE_COLORFILTER, paint.getColorFilter(), writer, urlDataManager);
907 writer.endObject(); // paint
908 }
909
MakeJsonFont(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)910 static void MakeJsonFont(const SkFont& font, SkJSONWriter& writer, UrlDataManager& urlDataManager) {
911 writer.beginObject();
912 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, font.isEmbolden(), false);
913 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_LINEARTEXT, font.isLinearMetrics(), false);
914 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, font.isSubpixel(), false);
915 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, font.isEmbeddedBitmaps(), false);
916 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_AUTOHINTING, font.isForceAutoHinting(), false);
917
918 store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSIZE, font.getSize(), SkPaintDefaults_TextSize);
919 store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getScaleX(), SK_Scalar1);
920 store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getSkewX(), 0.0f);
921 apply_font_edging(font, writer);
922 apply_font_hinting(font, writer);
923 apply_font_typeface(font, writer, urlDataManager);
924 writer.endObject(); // font
925 }
926
MakeJsonLattice(SkJSONWriter & writer,const SkCanvas::Lattice & lattice)927 void DrawCommand::MakeJsonLattice(SkJSONWriter& writer, const SkCanvas::Lattice& lattice) {
928 writer.beginObject();
929 writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT, lattice.fXCount);
930 writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT, lattice.fYCount);
931 if (nullptr != lattice.fBounds) {
932 writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
933 MakeJsonIRect(writer, *lattice.fBounds);
934 }
935 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS);
936 for (int i = 0; i < lattice.fXCount; i++) {
937 writer.appendS32(lattice.fXDivs[i]);
938 }
939 writer.endArray(); // xdivs
940 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS);
941 for (int i = 0; i < lattice.fYCount; i++) {
942 writer.appendS32(lattice.fYDivs[i]);
943 }
944 writer.endArray(); // ydivs
945 if (nullptr != lattice.fRectTypes) {
946 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS);
947 int flagCount = 0;
948 for (int row = 0; row < lattice.fYCount + 1; row++) {
949 writer.beginArray();
950 for (int column = 0; column < lattice.fXCount + 1; column++) {
951 writer.appendS32(lattice.fRectTypes[flagCount++]);
952 }
953 writer.endArray(); // row
954 }
955 writer.endArray();
956 }
957 writer.endObject();
958 }
959
ClearCommand(SkColor color)960 ClearCommand::ClearCommand(SkColor color) : INHERITED(kClear_OpType) { fColor = color; }
961
execute(SkCanvas * canvas) const962 void ClearCommand::execute(SkCanvas* canvas) const { canvas->clear(fColor); }
963
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const964 void ClearCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
965 INHERITED::toJSON(writer, urlDataManager);
966 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
967 MakeJsonColor(writer, fColor);
968 }
969
ClipPathCommand(const SkPath & path,SkClipOp op,bool doAA)970 ClipPathCommand::ClipPathCommand(const SkPath& path, SkClipOp op, bool doAA)
971 : INHERITED(kClipPath_OpType) {
972 fPath = path;
973 fOp = op;
974 fDoAA = doAA;
975 }
976
execute(SkCanvas * canvas) const977 void ClipPathCommand::execute(SkCanvas* canvas) const { canvas->clipPath(fPath, fOp, fDoAA); }
978
render(SkCanvas * canvas) const979 bool ClipPathCommand::render(SkCanvas* canvas) const {
980 render_path(canvas, fPath);
981 return true;
982 }
983
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const984 void ClipPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
985 INHERITED::toJSON(writer, urlDataManager);
986 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
987 MakeJsonPath(writer, fPath);
988 writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
989 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
990 }
991
ClipRegionCommand(const SkRegion & region,SkClipOp op)992 ClipRegionCommand::ClipRegionCommand(const SkRegion& region, SkClipOp op)
993 : INHERITED(kClipRegion_OpType) {
994 fRegion = region;
995 fOp = op;
996 }
997
execute(SkCanvas * canvas) const998 void ClipRegionCommand::execute(SkCanvas* canvas) const { canvas->clipRegion(fRegion, fOp); }
999
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1000 void ClipRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1001 INHERITED::toJSON(writer, urlDataManager);
1002 writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1003 MakeJsonRegion(writer, fRegion);
1004 writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
1005 }
1006
ClipRectCommand(const SkRect & rect,SkClipOp op,bool doAA)1007 ClipRectCommand::ClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA)
1008 : INHERITED(kClipRect_OpType) {
1009 fRect = rect;
1010 fOp = op;
1011 fDoAA = doAA;
1012 }
1013
execute(SkCanvas * canvas) const1014 void ClipRectCommand::execute(SkCanvas* canvas) const { canvas->clipRect(fRect, fOp, fDoAA); }
1015
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1016 void ClipRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1017 INHERITED::toJSON(writer, urlDataManager);
1018 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1019 MakeJsonRect(writer, fRect);
1020 writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
1021 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1022
1023 SkString desc;
1024 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1025 }
1026
ClipRRectCommand(const SkRRect & rrect,SkClipOp op,bool doAA)1027 ClipRRectCommand::ClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA)
1028 : INHERITED(kClipRRect_OpType) {
1029 fRRect = rrect;
1030 fOp = op;
1031 fDoAA = doAA;
1032 }
1033
execute(SkCanvas * canvas) const1034 void ClipRRectCommand::execute(SkCanvas* canvas) const { canvas->clipRRect(fRRect, fOp, fDoAA); }
1035
render(SkCanvas * canvas) const1036 bool ClipRRectCommand::render(SkCanvas* canvas) const {
1037 render_rrect(canvas, fRRect);
1038 return true;
1039 }
1040
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1041 void ClipRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1042 INHERITED::toJSON(writer, urlDataManager);
1043 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1044 make_json_rrect(writer, fRRect);
1045 writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
1046 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1047 }
1048
ClipShaderCommand(sk_sp<SkShader> cs,SkClipOp op)1049 ClipShaderCommand::ClipShaderCommand(sk_sp<SkShader> cs, SkClipOp op)
1050 : INHERITED(kClipShader_OpType) {
1051 fShader = cs;
1052 fOp = op;
1053 }
1054
execute(SkCanvas * canvas) const1055 void ClipShaderCommand::execute(SkCanvas* canvas) const { canvas->clipShader(fShader, fOp); }
1056
render(SkCanvas * canvas) const1057 bool ClipShaderCommand::render(SkCanvas* canvas) const {
1058 SkPaint paint;
1059 paint.setShader(fShader);
1060 canvas->drawPaint(paint);
1061 return true;
1062 }
1063
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1064 void ClipShaderCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1065 INHERITED::toJSON(writer, urlDataManager);
1066 apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, fShader.get(), writer, urlDataManager);
1067 writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp));
1068 }
1069
ResetClipCommand()1070 ResetClipCommand::ResetClipCommand() : INHERITED(kResetClip_OpType) {}
1071
execute(SkCanvas * canvas) const1072 void ResetClipCommand::execute(SkCanvas* canvas) const { SkCanvasPriv::ResetClip(canvas); }
1073
ConcatCommand(const SkMatrix & matrix)1074 ConcatCommand::ConcatCommand(const SkMatrix& matrix) : INHERITED(kConcat_OpType) {
1075 fMatrix = matrix;
1076 }
1077
execute(SkCanvas * canvas) const1078 void ConcatCommand::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); }
1079
1080 namespace {
writeMatrixType(SkJSONWriter & writer,const SkMatrix & m)1081 void writeMatrixType(SkJSONWriter& writer, const SkMatrix& m) {
1082 switch (m.getType()) {
1083 case SkMatrix::kTranslate_Mask:
1084 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (translate)");
1085 break;
1086 case SkMatrix::kScale_Mask:
1087 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (scale)");
1088 break;
1089 case SkMatrix::kAffine_Mask:
1090 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (rotation or skew)");
1091 break;
1092 case SkMatrix::kPerspective_Mask:
1093 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (perspective)");
1094 break;
1095 default:
1096 break;
1097 }
1098 }
1099 }
1100
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1101 void ConcatCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1102 INHERITED::toJSON(writer, urlDataManager);
1103 writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
1104 MakeJsonMatrix(writer, fMatrix);
1105 writeMatrixType(writer, fMatrix);
1106 }
1107
Concat44Command(const SkM44 & matrix)1108 Concat44Command::Concat44Command(const SkM44& matrix) : INHERITED(kConcat44_OpType) {
1109 fMatrix = matrix;
1110 }
1111
execute(SkCanvas * canvas) const1112 void Concat44Command::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); }
1113
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1114 void Concat44Command::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1115 INHERITED::toJSON(writer, urlDataManager);
1116 writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
1117 MakeJsonMatrix44(writer, fMatrix);
1118 }
1119
1120 ////
1121
DrawAnnotationCommand(const SkRect & rect,const char key[],sk_sp<SkData> value)1122 DrawAnnotationCommand::DrawAnnotationCommand(const SkRect& rect,
1123 const char key[],
1124 sk_sp<SkData> value)
1125 : INHERITED(kDrawAnnotation_OpType), fRect(rect), fKey(key), fValue(std::move(value)) {}
1126
execute(SkCanvas * canvas) const1127 void DrawAnnotationCommand::execute(SkCanvas* canvas) const {
1128 canvas->drawAnnotation(fRect, fKey.c_str(), fValue);
1129 }
1130
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1131 void DrawAnnotationCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1132 INHERITED::toJSON(writer, urlDataManager);
1133
1134 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1135 MakeJsonRect(writer, fRect);
1136 writer.appendString("key", fKey.c_str());
1137 if (fValue) {
1138 writer.appendString("value", std::string(
1139 static_cast<const char*>(fValue->data()), fValue->size()
1140 ).c_str());
1141 }
1142
1143 SkString desc;
1144 str_append(&desc, fRect)->appendf(" %s", fKey.c_str());
1145 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, desc.c_str());
1146 }
1147
1148 ////
1149
DrawImageCommand(const SkImage * image,SkScalar left,SkScalar top,const SkSamplingOptions & sampling,const SkPaint * paint)1150 DrawImageCommand::DrawImageCommand(const SkImage* image,
1151 SkScalar left,
1152 SkScalar top,
1153 const SkSamplingOptions& sampling,
1154 const SkPaint* paint)
1155 : INHERITED(kDrawImage_OpType)
1156 , fImage(SkRef(image))
1157 , fLeft(left)
1158 , fTop(top)
1159 , fSampling(sampling)
1160 , fPaint(paint) {}
1161
execute(SkCanvas * canvas) const1162 void DrawImageCommand::execute(SkCanvas* canvas) const {
1163 canvas->drawImage(fImage.get(), fLeft, fTop, fSampling, fPaint.getMaybeNull());
1164 }
1165
render(SkCanvas * canvas) const1166 bool DrawImageCommand::render(SkCanvas* canvas) const {
1167 SkAutoCanvasRestore acr(canvas, true);
1168 canvas->clear(0xFFFFFFFF);
1169
1170 xlate_and_scale_to_bounds(
1171 canvas,
1172 SkRect::MakeXYWH(
1173 fLeft, fTop, SkIntToScalar(fImage->width()), SkIntToScalar(fImage->height())));
1174 this->execute(canvas);
1175 return true;
1176 }
1177
imageId(UrlDataManager & udm) const1178 uint64_t DrawImageCommand::imageId(UrlDataManager& udm) const {
1179 return udm.lookupImage(fImage.get());
1180 }
1181
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1182 void DrawImageCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1183 INHERITED::toJSON(writer, urlDataManager);
1184 flatten(*fImage, writer, urlDataManager);
1185 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1186 MakeJsonPoint(writer, fLeft, fTop);
1187 if (fPaint.isValid()) {
1188 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1189 MakeJsonPaint(writer, *fPaint, urlDataManager);
1190 }
1191
1192 writer.appendU32(DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID, fImage->uniqueID());
1193 writer.appendS32(DEBUGCANVAS_ATTRIBUTE_WIDTH, fImage->width());
1194 writer.appendS32(DEBUGCANVAS_ATTRIBUTE_HEIGHT, fImage->height());
1195 switch (fImage->alphaType()) {
1196 case kOpaque_SkAlphaType:
1197 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_OPAQUE);
1198 break;
1199 case kPremul_SkAlphaType:
1200 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_PREMUL);
1201 break;
1202 case kUnpremul_SkAlphaType:
1203 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNPREMUL);
1204 break;
1205 default:
1206 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNKNOWN);
1207 break;
1208 }
1209 }
1210
DrawImageLatticeCommand(const SkImage * image,const SkCanvas::Lattice & lattice,const SkRect & dst,SkFilterMode filter,const SkPaint * paint)1211 DrawImageLatticeCommand::DrawImageLatticeCommand(const SkImage* image,
1212 const SkCanvas::Lattice& lattice,
1213 const SkRect& dst,
1214 SkFilterMode filter,
1215 const SkPaint* paint)
1216 : INHERITED(kDrawImageLattice_OpType)
1217 , fImage(SkRef(image))
1218 , fLattice(lattice)
1219 , fDst(dst)
1220 , fFilter(filter)
1221 , fPaint(paint) {}
1222
execute(SkCanvas * canvas) const1223 void DrawImageLatticeCommand::execute(SkCanvas* canvas) const {
1224 canvas->drawImageLattice(fImage.get(), fLattice, fDst, fFilter, fPaint.getMaybeNull());
1225 }
1226
render(SkCanvas * canvas) const1227 bool DrawImageLatticeCommand::render(SkCanvas* canvas) const {
1228 SkAutoCanvasRestore acr(canvas, true);
1229 canvas->clear(0xFFFFFFFF);
1230
1231 xlate_and_scale_to_bounds(canvas, fDst);
1232
1233 this->execute(canvas);
1234 return true;
1235 }
1236
imageId(UrlDataManager & udm) const1237 uint64_t DrawImageLatticeCommand::imageId(UrlDataManager& udm) const {
1238 return udm.lookupImage(fImage.get());
1239 }
1240
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1241 void DrawImageLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1242 INHERITED::toJSON(writer, urlDataManager);
1243 flatten(*fImage, writer, urlDataManager);
1244 writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
1245 MakeJsonLattice(writer, fLattice);
1246 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1247 MakeJsonRect(writer, fDst);
1248 if (fPaint.isValid()) {
1249 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1250 MakeJsonPaint(writer, *fPaint, urlDataManager);
1251 }
1252
1253 SkString desc;
1254 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1255 }
1256
DrawImageRectCommand(const SkImage * image,const SkRect & src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1257 DrawImageRectCommand::DrawImageRectCommand(const SkImage* image,
1258 const SkRect& src,
1259 const SkRect& dst,
1260 const SkSamplingOptions& sampling,
1261 const SkPaint* paint,
1262 SkCanvas::SrcRectConstraint constraint)
1263 : INHERITED(kDrawImageRect_OpType)
1264 , fImage(SkRef(image))
1265 , fSrc(src)
1266 , fDst(dst)
1267 , fSampling(sampling)
1268 , fPaint(paint)
1269 , fConstraint(constraint) {}
1270
execute(SkCanvas * canvas) const1271 void DrawImageRectCommand::execute(SkCanvas* canvas) const {
1272 canvas->drawImageRect(fImage.get(), fSrc, fDst, fSampling, fPaint.getMaybeNull(), fConstraint);
1273 }
1274
render(SkCanvas * canvas) const1275 bool DrawImageRectCommand::render(SkCanvas* canvas) const {
1276 SkAutoCanvasRestore acr(canvas, true);
1277 canvas->clear(0xFFFFFFFF);
1278
1279 xlate_and_scale_to_bounds(canvas, fDst);
1280
1281 this->execute(canvas);
1282 return true;
1283 }
1284
imageId(UrlDataManager & udm) const1285 uint64_t DrawImageRectCommand::imageId(UrlDataManager& udm) const {
1286 return udm.lookupImage(fImage.get());
1287 }
1288
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1289 void DrawImageRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1290 INHERITED::toJSON(writer, urlDataManager);
1291 flatten(*fImage, writer, urlDataManager);
1292 writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1293 MakeJsonRect(writer, fSrc);
1294 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1295 MakeJsonRect(writer, fDst);
1296 if (fPaint.isValid()) {
1297 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1298 MakeJsonPaint(writer, *fPaint, urlDataManager);
1299 }
1300 if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1301 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1302 }
1303
1304 SkString desc;
1305 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1306 }
1307
DrawImageRectLayerCommand(DebugLayerManager * layerManager,const int nodeId,const int frame,const SkRect & src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1308 DrawImageRectLayerCommand::DrawImageRectLayerCommand(DebugLayerManager* layerManager,
1309 const int nodeId,
1310 const int frame,
1311 const SkRect& src,
1312 const SkRect& dst,
1313 const SkSamplingOptions& sampling,
1314 const SkPaint* paint,
1315 SkCanvas::SrcRectConstraint constraint)
1316 : INHERITED(kDrawImageRectLayer_OpType)
1317 , fLayerManager(layerManager)
1318 , fNodeId(nodeId)
1319 , fFrame(frame)
1320 , fSrc(src)
1321 , fDst(dst)
1322 , fSampling(sampling)
1323 , fPaint(paint)
1324 , fConstraint(constraint) {}
1325
execute(SkCanvas * canvas) const1326 void DrawImageRectLayerCommand::execute(SkCanvas* canvas) const {
1327 sk_sp<SkImage> snapshot = fLayerManager->getLayerAsImage(fNodeId, fFrame);
1328 canvas->drawImageRect(snapshot.get(), fSrc, fDst, SkSamplingOptions(), fPaint.getMaybeNull(), fConstraint);
1329 }
1330
render(SkCanvas * canvas) const1331 bool DrawImageRectLayerCommand::render(SkCanvas* canvas) const {
1332 SkAutoCanvasRestore acr(canvas, true);
1333 canvas->clear(0xFFFFFFFF);
1334
1335 xlate_and_scale_to_bounds(canvas, fDst);
1336
1337 this->execute(canvas);
1338 return true;
1339 }
1340
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1341 void DrawImageRectLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1342 INHERITED::toJSON(writer, urlDataManager);
1343
1344 // Don't append an image attribute here, the image can be rendered in as many different ways
1345 // as there are commands in the layer, at least. the urlDataManager would save each one under
1346 // a different URL.
1347 // Append the node id, and the layer inspector of the debugger will know what to do with it.
1348 writer.appendS64(DEBUGCANVAS_ATTRIBUTE_LAYERNODEID, fNodeId);
1349
1350 writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1351 MakeJsonRect(writer, fSrc);
1352
1353 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1354 MakeJsonRect(writer, fDst);
1355 if (fPaint.isValid()) {
1356 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1357 MakeJsonPaint(writer, *fPaint, urlDataManager);
1358 }
1359 if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1360 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1361 }
1362
1363 SkString desc;
1364 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1365 }
1366
DrawOvalCommand(const SkRect & oval,const SkPaint & paint)1367 DrawOvalCommand::DrawOvalCommand(const SkRect& oval, const SkPaint& paint)
1368 : INHERITED(kDrawOval_OpType) {
1369 fOval = oval;
1370 fPaint = paint;
1371 }
1372
execute(SkCanvas * canvas) const1373 void DrawOvalCommand::execute(SkCanvas* canvas) const { canvas->drawOval(fOval, fPaint); }
1374
render(SkCanvas * canvas) const1375 bool DrawOvalCommand::render(SkCanvas* canvas) const {
1376 canvas->clear(0xFFFFFFFF);
1377 canvas->save();
1378
1379 xlate_and_scale_to_bounds(canvas, fOval);
1380
1381 SkPaint p;
1382 p.setColor(SK_ColorBLACK);
1383 p.setStyle(SkPaint::kStroke_Style);
1384
1385 canvas->drawOval(fOval, p);
1386 canvas->restore();
1387
1388 return true;
1389 }
1390
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1391 void DrawOvalCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1392 INHERITED::toJSON(writer, urlDataManager);
1393 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1394 MakeJsonRect(writer, fOval);
1395 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1396 MakeJsonPaint(writer, fPaint, urlDataManager);
1397 }
1398
DrawArcCommand(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)1399 DrawArcCommand::DrawArcCommand(const SkRect& oval,
1400 SkScalar startAngle,
1401 SkScalar sweepAngle,
1402 bool useCenter,
1403 const SkPaint& paint)
1404 : INHERITED(kDrawArc_OpType) {
1405 fOval = oval;
1406 fStartAngle = startAngle;
1407 fSweepAngle = sweepAngle;
1408 fUseCenter = useCenter;
1409 fPaint = paint;
1410 }
1411
execute(SkCanvas * canvas) const1412 void DrawArcCommand::execute(SkCanvas* canvas) const {
1413 canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, fPaint);
1414 }
1415
render(SkCanvas * canvas) const1416 bool DrawArcCommand::render(SkCanvas* canvas) const {
1417 canvas->clear(0xFFFFFFFF);
1418 canvas->save();
1419
1420 xlate_and_scale_to_bounds(canvas, fOval);
1421
1422 SkPaint p;
1423 p.setColor(SK_ColorBLACK);
1424 p.setStyle(SkPaint::kStroke_Style);
1425
1426 canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, p);
1427 canvas->restore();
1428
1429 return true;
1430 }
1431
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1432 void DrawArcCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1433 INHERITED::toJSON(writer, urlDataManager);
1434 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1435 MakeJsonRect(writer, fOval);
1436 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_STARTANGLE, fStartAngle);
1437 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE, fSweepAngle);
1438 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_USECENTER, fUseCenter);
1439 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1440 MakeJsonPaint(writer, fPaint, urlDataManager);
1441 }
1442
DrawPaintCommand(const SkPaint & paint)1443 DrawPaintCommand::DrawPaintCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1444 fPaint = paint;
1445 }
1446
execute(SkCanvas * canvas) const1447 void DrawPaintCommand::execute(SkCanvas* canvas) const { canvas->drawPaint(fPaint); }
1448
render(SkCanvas * canvas) const1449 bool DrawPaintCommand::render(SkCanvas* canvas) const {
1450 canvas->clear(0xFFFFFFFF);
1451 canvas->drawPaint(fPaint);
1452 return true;
1453 }
1454
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1455 void DrawPaintCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1456 INHERITED::toJSON(writer, urlDataManager);
1457 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1458 MakeJsonPaint(writer, fPaint, urlDataManager);
1459 }
1460
DrawBehindCommand(const SkPaint & paint)1461 DrawBehindCommand::DrawBehindCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1462 fPaint = paint;
1463 }
1464
execute(SkCanvas * canvas) const1465 void DrawBehindCommand::execute(SkCanvas* canvas) const {
1466 SkCanvasPriv::DrawBehind(canvas, fPaint);
1467 }
1468
render(SkCanvas * canvas) const1469 bool DrawBehindCommand::render(SkCanvas* canvas) const {
1470 canvas->clear(0xFFFFFFFF);
1471 SkCanvasPriv::DrawBehind(canvas, fPaint);
1472 return true;
1473 }
1474
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1475 void DrawBehindCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1476 INHERITED::toJSON(writer, urlDataManager);
1477 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1478 MakeJsonPaint(writer, fPaint, urlDataManager);
1479 }
1480
DrawPathCommand(const SkPath & path,const SkPaint & paint)1481 DrawPathCommand::DrawPathCommand(const SkPath& path, const SkPaint& paint)
1482 : INHERITED(kDrawPath_OpType) {
1483 fPath = path;
1484 fPaint = paint;
1485 }
1486
execute(SkCanvas * canvas) const1487 void DrawPathCommand::execute(SkCanvas* canvas) const { canvas->drawPath(fPath, fPaint); }
1488
render(SkCanvas * canvas) const1489 bool DrawPathCommand::render(SkCanvas* canvas) const {
1490 render_path(canvas, fPath);
1491 return true;
1492 }
1493
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1494 void DrawPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1495 INHERITED::toJSON(writer, urlDataManager);
1496 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1497 MakeJsonPath(writer, fPath);
1498 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1499 MakeJsonPaint(writer, fPaint, urlDataManager);
1500 }
1501
DrawRegionCommand(const SkRegion & region,const SkPaint & paint)1502 DrawRegionCommand::DrawRegionCommand(const SkRegion& region, const SkPaint& paint)
1503 : INHERITED(kDrawRegion_OpType) {
1504 fRegion = region;
1505 fPaint = paint;
1506 }
1507
execute(SkCanvas * canvas) const1508 void DrawRegionCommand::execute(SkCanvas* canvas) const { canvas->drawRegion(fRegion, fPaint); }
1509
render(SkCanvas * canvas) const1510 bool DrawRegionCommand::render(SkCanvas* canvas) const {
1511 render_region(canvas, fRegion);
1512 return true;
1513 }
1514
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1515 void DrawRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1516 INHERITED::toJSON(writer, urlDataManager);
1517 writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1518 MakeJsonRegion(writer, fRegion);
1519 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1520 MakeJsonPaint(writer, fPaint, urlDataManager);
1521 }
1522
BeginDrawPictureCommand(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)1523 BeginDrawPictureCommand::BeginDrawPictureCommand(const SkPicture* picture,
1524 const SkMatrix* matrix,
1525 const SkPaint* paint)
1526 : INHERITED(kBeginDrawPicture_OpType)
1527 , fPicture(SkRef(picture))
1528 , fMatrix(matrix)
1529 , fPaint(paint) {}
1530
execute(SkCanvas * canvas) const1531 void BeginDrawPictureCommand::execute(SkCanvas* canvas) const {
1532 if (fPaint.isValid()) {
1533 SkRect bounds = fPicture->cullRect();
1534 if (fMatrix.isValid()) {
1535 fMatrix->mapRect(&bounds);
1536 }
1537 canvas->saveLayer(&bounds, fPaint.get());
1538 }
1539
1540 if (fMatrix.isValid()) {
1541 if (!fPaint.isValid()) {
1542 canvas->save();
1543 }
1544 canvas->concat(*fMatrix);
1545 }
1546 }
1547
render(SkCanvas * canvas) const1548 bool BeginDrawPictureCommand::render(SkCanvas* canvas) const {
1549 canvas->clear(0xFFFFFFFF);
1550 canvas->save();
1551
1552 xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
1553
1554 canvas->drawPicture(fPicture.get());
1555
1556 canvas->restore();
1557
1558 return true;
1559 }
1560
EndDrawPictureCommand(bool restore)1561 EndDrawPictureCommand::EndDrawPictureCommand(bool restore)
1562 : INHERITED(kEndDrawPicture_OpType), fRestore(restore) {}
1563
execute(SkCanvas * canvas) const1564 void EndDrawPictureCommand::execute(SkCanvas* canvas) const {
1565 if (fRestore) {
1566 canvas->restore();
1567 }
1568 }
1569
DrawPointsCommand(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1570 DrawPointsCommand::DrawPointsCommand(SkCanvas::PointMode mode,
1571 size_t count,
1572 const SkPoint pts[],
1573 const SkPaint& paint)
1574 : INHERITED(kDrawPoints_OpType), fMode(mode), fPts(pts, count), fPaint(paint) {}
1575
execute(SkCanvas * canvas) const1576 void DrawPointsCommand::execute(SkCanvas* canvas) const {
1577 canvas->drawPoints(fMode, fPts.count(), fPts.begin(), fPaint);
1578 }
1579
render(SkCanvas * canvas) const1580 bool DrawPointsCommand::render(SkCanvas* canvas) const {
1581 canvas->clear(0xFFFFFFFF);
1582 canvas->save();
1583
1584 SkRect bounds;
1585
1586 bounds.setEmpty();
1587 for (int i = 0; i < fPts.count(); ++i) {
1588 SkRectPriv::GrowToInclude(&bounds, fPts[i]);
1589 }
1590
1591 xlate_and_scale_to_bounds(canvas, bounds);
1592
1593 SkPaint p;
1594 p.setColor(SK_ColorBLACK);
1595 p.setStyle(SkPaint::kStroke_Style);
1596
1597 canvas->drawPoints(fMode, fPts.count(), fPts.begin(), p);
1598 canvas->restore();
1599
1600 return true;
1601 }
1602
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1603 void DrawPointsCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1604 INHERITED::toJSON(writer, urlDataManager);
1605 writer.appendString(DEBUGCANVAS_ATTRIBUTE_MODE, pointmode_name(fMode));
1606 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POINTS);
1607 for (int i = 0; i < fPts.count(); i++) {
1608 MakeJsonPoint(writer, fPts[i]);
1609 }
1610 writer.endArray(); // points
1611 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1612 MakeJsonPaint(writer, fPaint, urlDataManager);
1613 }
1614
DrawTextBlobCommand(sk_sp<SkTextBlob> blob,SkScalar x,SkScalar y,const SkPaint & paint)1615 DrawTextBlobCommand::DrawTextBlobCommand(sk_sp<SkTextBlob> blob,
1616 SkScalar x,
1617 SkScalar y,
1618 const SkPaint& paint)
1619 : INHERITED(kDrawTextBlob_OpType)
1620 , fBlob(std::move(blob))
1621 , fXPos(x)
1622 , fYPos(y)
1623 , fPaint(paint) {}
1624
execute(SkCanvas * canvas) const1625 void DrawTextBlobCommand::execute(SkCanvas* canvas) const {
1626 canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1627 }
1628
render(SkCanvas * canvas) const1629 bool DrawTextBlobCommand::render(SkCanvas* canvas) const {
1630 canvas->clear(SK_ColorWHITE);
1631 canvas->save();
1632
1633 SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
1634 xlate_and_scale_to_bounds(canvas, bounds);
1635
1636 canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1637
1638 canvas->restore();
1639
1640 return true;
1641 }
1642
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1643 void DrawTextBlobCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1644 INHERITED::toJSON(writer, urlDataManager);
1645 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_RUNS);
1646 SkTextBlobRunIterator iter(fBlob.get());
1647 while (!iter.done()) {
1648 writer.beginObject(); // run
1649 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_GLYPHS);
1650 for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1651 writer.appendU32(iter.glyphs()[i]);
1652 }
1653 writer.endArray(); // glyphs
1654 if (iter.positioning() != SkTextBlobRunIterator::kDefault_Positioning) {
1655 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POSITIONS);
1656 const SkScalar* iterPositions = iter.pos();
1657 for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1658 switch (iter.positioning()) {
1659 case SkTextBlobRunIterator::kFull_Positioning:
1660 MakeJsonPoint(writer, iterPositions[i * 2], iterPositions[i * 2 + 1]);
1661 break;
1662 case SkTextBlobRunIterator::kHorizontal_Positioning:
1663 writer.appendFloat(iterPositions[i]);
1664 break;
1665 case SkTextBlobRunIterator::kDefault_Positioning: break;
1666 case SkTextBlobRunIterator::kRSXform_Positioning:
1667 // TODO_RSXFORM_BLOB
1668 break;
1669 }
1670 }
1671 writer.endArray(); // positions
1672 }
1673 writer.appendName(DEBUGCANVAS_ATTRIBUTE_FONT);
1674 MakeJsonFont(iter.font(), writer, urlDataManager);
1675 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1676 MakeJsonPoint(writer, iter.offset());
1677
1678 writer.endObject(); // run
1679 iter.next();
1680 }
1681 writer.endArray(); // runs
1682 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_X, fXPos);
1683 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_Y, fYPos);
1684 SkRect bounds = fBlob->bounds();
1685 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1686 MakeJsonRect(writer, bounds);
1687 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1688 MakeJsonPaint(writer, fPaint, urlDataManager);
1689
1690 SkString desc;
1691 // make the bounds local by applying the x,y
1692 bounds.offset(fXPos, fYPos);
1693 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, bounds)->c_str());
1694 }
1695
DrawPatchCommand(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)1696 DrawPatchCommand::DrawPatchCommand(const SkPoint cubics[12],
1697 const SkColor colors[4],
1698 const SkPoint texCoords[4],
1699 SkBlendMode bmode,
1700 const SkPaint& paint)
1701 : INHERITED(kDrawPatch_OpType), fBlendMode(bmode) {
1702 memcpy(fCubics, cubics, sizeof(fCubics));
1703 if (colors != nullptr) {
1704 memcpy(fColors, colors, sizeof(fColors));
1705 fColorsPtr = fColors;
1706 } else {
1707 fColorsPtr = nullptr;
1708 }
1709 if (texCoords != nullptr) {
1710 memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
1711 fTexCoordsPtr = fTexCoords;
1712 } else {
1713 fTexCoordsPtr = nullptr;
1714 }
1715 fPaint = paint;
1716 }
1717
execute(SkCanvas * canvas) const1718 void DrawPatchCommand::execute(SkCanvas* canvas) const {
1719 canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fBlendMode, fPaint);
1720 }
1721
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1722 void DrawPatchCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1723 INHERITED::toJSON(writer, urlDataManager);
1724 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_CUBICS);
1725 for (int i = 0; i < 12; i++) {
1726 MakeJsonPoint(writer, fCubics[i]);
1727 }
1728 writer.endArray(); // cubics
1729 if (fColorsPtr != nullptr) {
1730 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_COLORS);
1731 for (int i = 0; i < 4; i++) {
1732 MakeJsonColor(writer, fColorsPtr[i]);
1733 }
1734 writer.endArray(); // colors
1735 }
1736 if (fTexCoordsPtr != nullptr) {
1737 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS);
1738 for (int i = 0; i < 4; i++) {
1739 MakeJsonPoint(writer, fTexCoords[i]);
1740 }
1741 writer.endArray(); // texCoords
1742 }
1743 // fBlendMode
1744 }
1745
DrawRectCommand(const SkRect & rect,const SkPaint & paint)1746 DrawRectCommand::DrawRectCommand(const SkRect& rect, const SkPaint& paint)
1747 : INHERITED(kDrawRect_OpType) {
1748 fRect = rect;
1749 fPaint = paint;
1750 }
1751
execute(SkCanvas * canvas) const1752 void DrawRectCommand::execute(SkCanvas* canvas) const { canvas->drawRect(fRect, fPaint); }
1753
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1754 void DrawRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1755 INHERITED::toJSON(writer, urlDataManager);
1756 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1757 MakeJsonRect(writer, fRect);
1758 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1759 MakeJsonPaint(writer, fPaint, urlDataManager);
1760
1761 SkString desc;
1762 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1763 }
1764
DrawRRectCommand(const SkRRect & rrect,const SkPaint & paint)1765 DrawRRectCommand::DrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
1766 : INHERITED(kDrawRRect_OpType) {
1767 fRRect = rrect;
1768 fPaint = paint;
1769 }
1770
execute(SkCanvas * canvas) const1771 void DrawRRectCommand::execute(SkCanvas* canvas) const { canvas->drawRRect(fRRect, fPaint); }
1772
render(SkCanvas * canvas) const1773 bool DrawRRectCommand::render(SkCanvas* canvas) const {
1774 render_rrect(canvas, fRRect);
1775 return true;
1776 }
1777
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1778 void DrawRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1779 INHERITED::toJSON(writer, urlDataManager);
1780 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1781 make_json_rrect(writer, fRRect);
1782 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1783 MakeJsonPaint(writer, fPaint, urlDataManager);
1784 }
1785
DrawDRRectCommand(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1786 DrawDRRectCommand::DrawDRRectCommand(const SkRRect& outer,
1787 const SkRRect& inner,
1788 const SkPaint& paint)
1789 : INHERITED(kDrawDRRect_OpType) {
1790 fOuter = outer;
1791 fInner = inner;
1792 fPaint = paint;
1793 }
1794
execute(SkCanvas * canvas) const1795 void DrawDRRectCommand::execute(SkCanvas* canvas) const {
1796 canvas->drawDRRect(fOuter, fInner, fPaint);
1797 }
1798
render(SkCanvas * canvas) const1799 bool DrawDRRectCommand::render(SkCanvas* canvas) const {
1800 render_drrect(canvas, fOuter, fInner);
1801 return true;
1802 }
1803
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1804 void DrawDRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1805 INHERITED::toJSON(writer, urlDataManager);
1806 writer.appendName(DEBUGCANVAS_ATTRIBUTE_OUTER);
1807 make_json_rrect(writer, fOuter);
1808 writer.appendName(DEBUGCANVAS_ATTRIBUTE_INNER);
1809 make_json_rrect(writer, fInner);
1810 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1811 MakeJsonPaint(writer, fPaint, urlDataManager);
1812 }
1813
DrawShadowCommand(const SkPath & path,const SkDrawShadowRec & rec)1814 DrawShadowCommand::DrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec)
1815 : INHERITED(kDrawShadow_OpType) {
1816 fPath = path;
1817 fShadowRec = rec;
1818 }
1819
execute(SkCanvas * canvas) const1820 void DrawShadowCommand::execute(SkCanvas* canvas) const {
1821 canvas->private_draw_shadow_rec(fPath, fShadowRec);
1822 }
1823
render(SkCanvas * canvas) const1824 bool DrawShadowCommand::render(SkCanvas* canvas) const {
1825 render_shadow(canvas, fPath, fShadowRec);
1826 return true;
1827 }
1828
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1829 void DrawShadowCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1830 INHERITED::toJSON(writer, urlDataManager);
1831
1832 bool geometricOnly = SkToBool(fShadowRec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
1833 bool transparentOccluder =
1834 SkToBool(fShadowRec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1835
1836 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1837 MakeJsonPath(writer, fPath);
1838 writer.appendName(DEBUGCANVAS_ATTRIBUTE_ZPLANE);
1839 MakeJsonPoint3(writer, fShadowRec.fZPlaneParams);
1840 writer.appendName(DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION);
1841 MakeJsonPoint3(writer, fShadowRec.fLightPos);
1842 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS, fShadowRec.fLightRadius);
1843 writer.appendName(DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR);
1844 MakeJsonColor(writer, fShadowRec.fAmbientColor);
1845 writer.appendName(DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR);
1846 MakeJsonColor(writer, fShadowRec.fSpotColor);
1847 store_bool(writer, DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC, transparentOccluder, false);
1848 store_bool(writer, DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY, geometricOnly, false);
1849 }
1850
1851 ///////////////////////////////////////////////////////////////////////////////////////////////////
1852
DrawEdgeAAQuadCommand(const SkRect & rect,const SkPoint clip[],SkCanvas::QuadAAFlags aa,const SkColor4f & color,SkBlendMode mode)1853 DrawEdgeAAQuadCommand::DrawEdgeAAQuadCommand(const SkRect& rect,
1854 const SkPoint clip[],
1855 SkCanvas::QuadAAFlags aa,
1856 const SkColor4f& color,
1857 SkBlendMode mode)
1858 : INHERITED(kDrawEdgeAAQuad_OpType)
1859 , fRect(rect)
1860 , fHasClip(clip != nullptr)
1861 , fAA(aa)
1862 , fColor(color)
1863 , fMode(mode) {
1864 if (clip) {
1865 for (int i = 0; i < 4; ++i) {
1866 fClip[i] = clip[i];
1867 }
1868 }
1869 }
1870
execute(SkCanvas * canvas) const1871 void DrawEdgeAAQuadCommand::execute(SkCanvas* canvas) const {
1872 canvas->experimental_DrawEdgeAAQuad(fRect, fHasClip ? fClip : nullptr, fAA, fColor, fMode);
1873 }
1874
DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],int count,const SkPoint dstClips[],const SkMatrix preViewMatrices[],const SkSamplingOptions & sampling,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1875 DrawEdgeAAImageSetCommand::DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],
1876 int count,
1877 const SkPoint dstClips[],
1878 const SkMatrix preViewMatrices[],
1879 const SkSamplingOptions& sampling,
1880 const SkPaint* paint,
1881 SkCanvas::SrcRectConstraint constraint)
1882 : INHERITED(kDrawEdgeAAImageSet_OpType)
1883 , fSet(count)
1884 , fCount(count)
1885 , fSampling(sampling)
1886 , fPaint(paint)
1887 , fConstraint(constraint) {
1888 int totalDstClipCount, totalMatrixCount;
1889 SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);
1890
1891 std::copy_n(set, count, fSet.get());
1892 fDstClips.reset(totalDstClipCount);
1893 std::copy_n(dstClips, totalDstClipCount, fDstClips.get());
1894 fPreViewMatrices.reset(totalMatrixCount);
1895 std::copy_n(preViewMatrices, totalMatrixCount, fPreViewMatrices.get());
1896 }
1897
execute(SkCanvas * canvas) const1898 void DrawEdgeAAImageSetCommand::execute(SkCanvas* canvas) const {
1899 canvas->experimental_DrawEdgeAAImageSet(fSet.get(),
1900 fCount,
1901 fDstClips.get(),
1902 fPreViewMatrices.get(),
1903 fSampling,
1904 fPaint.getMaybeNull(),
1905 fConstraint);
1906 }
1907
1908 ///////////////////////////////////////////////////////////////////////////////////////////////////
1909
DrawDrawableCommand(SkDrawable * drawable,const SkMatrix * matrix)1910 DrawDrawableCommand::DrawDrawableCommand(SkDrawable* drawable, const SkMatrix* matrix)
1911 : INHERITED(kDrawDrawable_OpType), fDrawable(SkRef(drawable)), fMatrix(matrix) {}
1912
execute(SkCanvas * canvas) const1913 void DrawDrawableCommand::execute(SkCanvas* canvas) const {
1914 canvas->drawDrawable(fDrawable.get(), fMatrix.getMaybeNull());
1915 }
1916
1917 ///////////////////////////////////////////////////////////////////////////////////////////////////
1918
DrawVerticesCommand(sk_sp<SkVertices> vertices,SkBlendMode bmode,const SkPaint & paint)1919 DrawVerticesCommand::DrawVerticesCommand(sk_sp<SkVertices> vertices,
1920 SkBlendMode bmode,
1921 const SkPaint& paint)
1922 : INHERITED(kDrawVertices_OpType)
1923 , fVertices(std::move(vertices))
1924 , fBlendMode(bmode)
1925 , fPaint(paint) {}
1926
execute(SkCanvas * canvas) const1927 void DrawVerticesCommand::execute(SkCanvas* canvas) const {
1928 canvas->drawVertices(fVertices, fBlendMode, fPaint);
1929 }
1930
1931 ///////////////////////////////////////////////////////////////////////////////////////////////////
1932
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)1933 DrawAtlasCommand::DrawAtlasCommand(const SkImage* image,
1934 const SkRSXform xform[],
1935 const SkRect tex[],
1936 const SkColor colors[],
1937 int count,
1938 SkBlendMode bmode,
1939 const SkSamplingOptions& sampling,
1940 const SkRect* cull,
1941 const SkPaint* paint)
1942 : INHERITED(kDrawAtlas_OpType)
1943 , fImage(SkRef(image))
1944 , fXform(xform, count)
1945 , fTex(tex, count)
1946 , fColors(colors, colors ? count : 0)
1947 , fBlendMode(bmode)
1948 , fSampling(sampling)
1949 , fCull(cull)
1950 , fPaint(paint) {}
1951
execute(SkCanvas * canvas) const1952 void DrawAtlasCommand::execute(SkCanvas* canvas) const {
1953 canvas->drawAtlas(fImage.get(),
1954 fXform.begin(),
1955 fTex.begin(),
1956 fColors.isEmpty() ? nullptr : fColors.begin(),
1957 fXform.count(),
1958 fBlendMode,
1959 fSampling,
1960 fCull.getMaybeNull(),
1961 fPaint.getMaybeNull());
1962 }
1963
1964 ///////////////////////////////////////////////////////////////////////////////////////////////////
1965
RestoreCommand()1966 RestoreCommand::RestoreCommand() : INHERITED(kRestore_OpType) {}
1967
execute(SkCanvas * canvas) const1968 void RestoreCommand::execute(SkCanvas* canvas) const { canvas->restore(); }
1969
SaveCommand()1970 SaveCommand::SaveCommand() : INHERITED(kSave_OpType) {}
1971
execute(SkCanvas * canvas) const1972 void SaveCommand::execute(SkCanvas* canvas) const { canvas->save(); }
1973
SaveLayerCommand(const SkCanvas::SaveLayerRec & rec)1974 SaveLayerCommand::SaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
1975 : INHERITED(kSaveLayer_OpType)
1976 , fBounds(rec.fBounds)
1977 , fPaint(rec.fPaint)
1978 , fBackdrop(SkSafeRef(rec.fBackdrop))
1979 , fSaveLayerFlags(rec.fSaveLayerFlags)
1980 , fBackdropScale(SkCanvasPriv::GetBackdropScaleFactor(rec)) {}
1981
execute(SkCanvas * canvas) const1982 void SaveLayerCommand::execute(SkCanvas* canvas) const {
1983 // In the common case fBackdropScale == 1.f and then this is no different than a regular Rec
1984 canvas->saveLayer(SkCanvasPriv::ScaledBackdropLayer(fBounds.getMaybeNull(),
1985 fPaint.getMaybeNull(),
1986 fBackdrop.get(),
1987 fBackdropScale,
1988 fSaveLayerFlags));
1989 }
1990
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1991 void SaveLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1992 INHERITED::toJSON(writer, urlDataManager);
1993 if (fBounds.isValid()) {
1994 writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
1995 MakeJsonRect(writer, *fBounds);
1996 }
1997 if (fPaint.isValid()) {
1998 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1999 MakeJsonPaint(writer, *fPaint, urlDataManager);
2000 }
2001 if (fBackdrop != nullptr) {
2002 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BACKDROP);
2003 flatten(fBackdrop.get(), writer, urlDataManager);
2004 writer.endObject(); // backdrop
2005 }
2006 if (fSaveLayerFlags != 0) {
2007 SkDebugf("unsupported: saveLayer flags\n");
2008 SkASSERT(false);
2009 }
2010 }
2011
SetMatrixCommand(const SkMatrix & matrix)2012 SetMatrixCommand::SetMatrixCommand(const SkMatrix& matrix) : INHERITED(kSetMatrix_OpType) {
2013 fMatrix = matrix;
2014 }
2015
execute(SkCanvas * canvas) const2016 void SetMatrixCommand::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); }
2017
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2018 void SetMatrixCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2019 INHERITED::toJSON(writer, urlDataManager);
2020 writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
2021 MakeJsonMatrix(writer, fMatrix);
2022 writeMatrixType(writer, fMatrix);
2023 }
2024
SetM44Command(const SkM44 & matrix)2025 SetM44Command::SetM44Command(const SkM44& matrix) : INHERITED(kSetM44_OpType) {
2026 fMatrix = matrix;
2027 }
2028
execute(SkCanvas * canvas) const2029 void SetM44Command::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); }
2030
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2031 void SetM44Command::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2032 INHERITED::toJSON(writer, urlDataManager);
2033 writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
2034 MakeJsonMatrix44(writer, fMatrix);
2035 }
2036