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