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