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 kDrawBitmapLattice_OpType: return "DrawBitmapLattice";
223 case kDrawBitmapNine_OpType: return "DrawBitmapNine";
224 case kDrawBitmapRect_OpType: return "DrawBitmapRect";
225 case kDrawDRRect_OpType: return "DrawDRRect";
226 case kDrawImage_OpType: return "DrawImage";
227 case kDrawImageLattice_OpType: return "DrawImageLattice";
228 case kDrawImageNine_OpType: return "DrawImageNine";
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 default:
253 SkDebugf("OpType error 0x%08x\n", type);
254 SkASSERT(0);
255 break;
256 }
257 SkDEBUGFAIL("DrawType UNUSED\n");
258 return nullptr;
259 }
260
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const261 void DrawCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
262 writer.appendString(DEBUGCANVAS_ATTRIBUTE_COMMAND, this->GetCommandString(fOpType));
263 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_VISIBLE, this->isVisible());
264 }
265
266 namespace {
267
xlate_and_scale_to_bounds(SkCanvas * canvas,const SkRect & bounds)268 void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
269 const SkISize& size = canvas->getBaseLayerSize();
270
271 static const SkScalar kInsetFrac = 0.9f; // Leave a border around object
272
273 canvas->translate(size.fWidth / 2.0f, size.fHeight / 2.0f);
274 if (bounds.width() > bounds.height()) {
275 canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.width()),
276 SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.width()));
277 } else {
278 canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.height()),
279 SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.height()));
280 }
281 canvas->translate(-bounds.centerX(), -bounds.centerY());
282 }
283
render_path(SkCanvas * canvas,const SkPath & path)284 void render_path(SkCanvas* canvas, const SkPath& path) {
285 canvas->clear(0xFFFFFFFF);
286
287 const SkRect& bounds = path.getBounds();
288 if (bounds.isEmpty()) {
289 return;
290 }
291
292 SkAutoCanvasRestore acr(canvas, true);
293 xlate_and_scale_to_bounds(canvas, bounds);
294
295 SkPaint p;
296 p.setColor(SK_ColorBLACK);
297 p.setStyle(SkPaint::kStroke_Style);
298
299 canvas->drawPath(path, p);
300 }
301
render_region(SkCanvas * canvas,const SkRegion & region)302 void render_region(SkCanvas* canvas, const SkRegion& region) {
303 canvas->clear(0xFFFFFFFF);
304
305 const SkIRect& bounds = region.getBounds();
306 if (bounds.isEmpty()) {
307 return;
308 }
309
310 SkAutoCanvasRestore acr(canvas, true);
311 xlate_and_scale_to_bounds(canvas, SkRect::Make(bounds));
312
313 SkPaint p;
314 p.setColor(SK_ColorBLACK);
315 p.setStyle(SkPaint::kStroke_Style);
316
317 canvas->drawRegion(region, p);
318 }
319
render_bitmap(SkCanvas * canvas,const SkBitmap & input,const SkRect * srcRect=nullptr)320 void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = nullptr) {
321 const SkISize& size = canvas->getBaseLayerSize();
322
323 SkScalar xScale = SkIntToScalar(size.fWidth - 2) / input.width();
324 SkScalar yScale = SkIntToScalar(size.fHeight - 2) / input.height();
325
326 if (input.width() > input.height()) {
327 yScale *= input.height() / (float)input.width();
328 } else {
329 xScale *= input.width() / (float)input.height();
330 }
331
332 SkRect dst = SkRect::MakeXYWH(
333 SK_Scalar1, SK_Scalar1, xScale * input.width(), yScale * input.height());
334
335 static const int kNumBlocks = 8;
336
337 canvas->clear(0xFFFFFFFF);
338 SkISize block = {canvas->imageInfo().width() / kNumBlocks,
339 canvas->imageInfo().height() / kNumBlocks};
340 for (int y = 0; y < kNumBlocks; ++y) {
341 for (int x = 0; x < kNumBlocks; ++x) {
342 SkPaint paint;
343 paint.setColor((x + y) % 2 ? SK_ColorLTGRAY : SK_ColorDKGRAY);
344 SkRect r = SkRect::MakeXYWH(SkIntToScalar(x * block.width()),
345 SkIntToScalar(y * block.height()),
346 SkIntToScalar(block.width()),
347 SkIntToScalar(block.height()));
348 canvas->drawRect(r, paint);
349 }
350 }
351
352 canvas->drawBitmapRect(input, dst, nullptr);
353
354 if (srcRect) {
355 SkRect r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
356 srcRect->fTop * yScale + SK_Scalar1,
357 srcRect->fRight * xScale + SK_Scalar1,
358 srcRect->fBottom * yScale + SK_Scalar1);
359 SkPaint p;
360 p.setColor(SK_ColorRED);
361 p.setStyle(SkPaint::kStroke_Style);
362
363 canvas->drawRect(r, p);
364 }
365 }
366
render_rrect(SkCanvas * canvas,const SkRRect & rrect)367 void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
368 canvas->clear(0xFFFFFFFF);
369 canvas->save();
370
371 const SkRect& bounds = rrect.getBounds();
372
373 xlate_and_scale_to_bounds(canvas, bounds);
374
375 SkPaint p;
376 p.setColor(SK_ColorBLACK);
377 p.setStyle(SkPaint::kStroke_Style);
378
379 canvas->drawRRect(rrect, p);
380 canvas->restore();
381 }
382
render_drrect(SkCanvas * canvas,const SkRRect & outer,const SkRRect & inner)383 void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
384 canvas->clear(0xFFFFFFFF);
385 canvas->save();
386
387 const SkRect& bounds = outer.getBounds();
388
389 xlate_and_scale_to_bounds(canvas, bounds);
390
391 SkPaint p;
392 p.setColor(SK_ColorBLACK);
393 p.setStyle(SkPaint::kStroke_Style);
394
395 canvas->drawDRRect(outer, inner, p);
396 canvas->restore();
397 }
398
render_shadow(SkCanvas * canvas,const SkPath & path,SkDrawShadowRec rec)399 void render_shadow(SkCanvas* canvas, const SkPath& path, SkDrawShadowRec rec) {
400 canvas->clear(0xFFFFFFFF);
401
402 const SkRect& bounds = path.getBounds();
403 if (bounds.isEmpty()) {
404 return;
405 }
406
407 SkAutoCanvasRestore acr(canvas, true);
408 xlate_and_scale_to_bounds(canvas, bounds);
409
410 rec.fAmbientColor = SK_ColorBLACK;
411 rec.fSpotColor = SK_ColorBLACK;
412 canvas->private_draw_shadow_rec(path, rec);
413 }
414
415 static const char* const gBlendModeMap[] = {
416 "clear", "src", "dst", "srcOver", "dstOver", "srcIn", "dstIn",
417 "srcOut", "dstOut", "srcATop", "dstATop", "xor", "plus", "modulate",
418
419 "screen",
420
421 "overlay", "darken", "lighten", "colorDodge", "colorBurn", "hardLight", "softLight",
422 "difference", "exclusion", "multiply",
423
424 "hue", "saturation", "color", "luminosity",
425 };
426
427 static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLastMode) + 1,
428 "blendMode mismatch");
429 static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLuminosity) + 1,
430 "blendMode mismatch");
431
apply_paint_blend_mode(const SkPaint & paint,SkJSONWriter & writer)432 void apply_paint_blend_mode(const SkPaint& paint, SkJSONWriter& writer) {
433 const auto mode = paint.getBlendMode();
434 if (mode != SkBlendMode::kSrcOver) {
435 SkASSERT(static_cast<size_t>(mode) < SK_ARRAY_COUNT(gBlendModeMap));
436 writer.appendString(DEBUGCANVAS_ATTRIBUTE_BLENDMODE,
437 gBlendModeMap[static_cast<size_t>(mode)]);
438 }
439 }
440
441 }; // namespace
442
MakeJsonColor(SkJSONWriter & writer,const SkColor color)443 void DrawCommand::MakeJsonColor(SkJSONWriter& writer, const SkColor color) {
444 writer.beginArray(nullptr, false);
445 writer.appendS32(SkColorGetA(color));
446 writer.appendS32(SkColorGetR(color));
447 writer.appendS32(SkColorGetG(color));
448 writer.appendS32(SkColorGetB(color));
449 writer.endArray();
450 }
451
MakeJsonColor4f(SkJSONWriter & writer,const SkColor4f & color)452 void DrawCommand::MakeJsonColor4f(SkJSONWriter& writer, const SkColor4f& color) {
453 writer.beginArray(nullptr, false);
454 writer.appendFloat(color.fA);
455 writer.appendFloat(color.fR);
456 writer.appendFloat(color.fG);
457 writer.appendFloat(color.fB);
458 writer.endArray();
459 }
460
MakeJsonPoint(SkJSONWriter & writer,const SkPoint & point)461 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, const SkPoint& point) {
462 writer.beginArray(nullptr, false);
463 writer.appendFloat(point.x());
464 writer.appendFloat(point.y());
465 writer.endArray();
466 }
467
MakeJsonPoint(SkJSONWriter & writer,SkScalar x,SkScalar y)468 void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, SkScalar x, SkScalar y) {
469 writer.beginArray(nullptr, false);
470 writer.appendFloat(x);
471 writer.appendFloat(y);
472 writer.endArray();
473 }
474
MakeJsonPoint3(SkJSONWriter & writer,const SkPoint3 & point)475 void DrawCommand::MakeJsonPoint3(SkJSONWriter& writer, const SkPoint3& point) {
476 writer.beginArray(nullptr, false);
477 writer.appendFloat(point.x());
478 writer.appendFloat(point.y());
479 writer.appendFloat(point.z());
480 writer.endArray();
481 }
482
MakeJsonRect(SkJSONWriter & writer,const SkRect & rect)483 void DrawCommand::MakeJsonRect(SkJSONWriter& writer, const SkRect& rect) {
484 writer.beginArray(nullptr, false);
485 writer.appendFloat(rect.left());
486 writer.appendFloat(rect.top());
487 writer.appendFloat(rect.right());
488 writer.appendFloat(rect.bottom());
489 writer.endArray();
490 }
491
MakeJsonIRect(SkJSONWriter & writer,const SkIRect & rect)492 void DrawCommand::MakeJsonIRect(SkJSONWriter& writer, const SkIRect& rect) {
493 writer.beginArray(nullptr, false);
494 writer.appendS32(rect.left());
495 writer.appendS32(rect.top());
496 writer.appendS32(rect.right());
497 writer.appendS32(rect.bottom());
498 writer.endArray();
499 }
500
make_json_rrect(SkJSONWriter & writer,const SkRRect & rrect)501 static void make_json_rrect(SkJSONWriter& writer, const SkRRect& rrect) {
502 writer.beginArray(nullptr, false);
503 DrawCommand::MakeJsonRect(writer, rrect.rect());
504 DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperLeft_Corner));
505 DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperRight_Corner));
506 DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerRight_Corner));
507 DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerLeft_Corner));
508 writer.endArray();
509 }
510
MakeJsonMatrix(SkJSONWriter & writer,const SkMatrix & matrix)511 void DrawCommand::MakeJsonMatrix(SkJSONWriter& writer, const SkMatrix& matrix) {
512 writer.beginArray();
513 for (int r = 0; r < 3; ++r) {
514 writer.beginArray(nullptr, false);
515 for (int c = 0; c < 3; ++c) {
516 writer.appendFloat(matrix[r * 3 + c]);
517 }
518 writer.endArray();
519 }
520 writer.endArray();
521 }
522
MakeJsonPath(SkJSONWriter & writer,const SkPath & path)523 void DrawCommand::MakeJsonPath(SkJSONWriter& writer, const SkPath& path) {
524 writer.beginObject();
525 switch (path.getFillType()) {
526 case SkPathFillType::kWinding:
527 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_WINDING);
528 break;
529 case SkPathFillType::kEvenOdd:
530 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_EVENODD);
531 break;
532 case SkPathFillType::kInverseWinding:
533 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
534 DEBUGCANVAS_FILLTYPE_INVERSEWINDING);
535 break;
536 case SkPathFillType::kInverseEvenOdd:
537 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE,
538 DEBUGCANVAS_FILLTYPE_INVERSEEVENODD);
539 break;
540 }
541 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_VERBS);
542 SkPath::Iter iter(path, false);
543 SkPoint pts[4];
544 SkPath::Verb verb;
545 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
546 if (verb == SkPath::kClose_Verb) {
547 writer.appendString(DEBUGCANVAS_VERB_CLOSE);
548 continue;
549 }
550 writer.beginObject(); // verb
551 switch (verb) {
552 case SkPath::kLine_Verb: {
553 writer.appendName(DEBUGCANVAS_VERB_LINE);
554 MakeJsonPoint(writer, pts[1]);
555 break;
556 }
557 case SkPath::kQuad_Verb: {
558 writer.beginArray(DEBUGCANVAS_VERB_QUAD);
559 MakeJsonPoint(writer, pts[1]);
560 MakeJsonPoint(writer, pts[2]);
561 writer.endArray(); // quad coords
562 break;
563 }
564 case SkPath::kCubic_Verb: {
565 writer.beginArray(DEBUGCANVAS_VERB_CUBIC);
566 MakeJsonPoint(writer, pts[1]);
567 MakeJsonPoint(writer, pts[2]);
568 MakeJsonPoint(writer, pts[3]);
569 writer.endArray(); // cubic coords
570 break;
571 }
572 case SkPath::kConic_Verb: {
573 writer.beginArray(DEBUGCANVAS_VERB_CONIC);
574 MakeJsonPoint(writer, pts[1]);
575 MakeJsonPoint(writer, pts[2]);
576 writer.appendFloat(iter.conicWeight());
577 writer.endArray(); // conic coords
578 break;
579 }
580 case SkPath::kMove_Verb: {
581 writer.appendName(DEBUGCANVAS_VERB_MOVE);
582 MakeJsonPoint(writer, pts[0]);
583 break;
584 }
585 case SkPath::kClose_Verb:
586 case SkPath::kDone_Verb:
587 // Unreachable
588 break;
589 }
590 writer.endObject(); // verb
591 }
592 writer.endArray(); // verbs
593 writer.endObject(); // path
594 }
595
MakeJsonRegion(SkJSONWriter & writer,const SkRegion & region)596 void DrawCommand::MakeJsonRegion(SkJSONWriter& writer, const SkRegion& region) {
597 // TODO: Actually serialize the rectangles, rather than just devolving to path
598 SkPath path;
599 region.getBoundaryPath(&path);
600 MakeJsonPath(writer, path);
601 }
602
regionop_name(SkClipOp op)603 static const char* regionop_name(SkClipOp op) {
604 switch (op) {
605 case kDifference_SkClipOp: return DEBUGCANVAS_REGIONOP_DIFFERENCE;
606 case kIntersect_SkClipOp: return DEBUGCANVAS_REGIONOP_INTERSECT;
607 case kUnion_SkClipOp: return DEBUGCANVAS_REGIONOP_UNION;
608 case kXOR_SkClipOp: return DEBUGCANVAS_REGIONOP_XOR;
609 case kReverseDifference_SkClipOp: return DEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE;
610 case kReplace_SkClipOp: return DEBUGCANVAS_REGIONOP_REPLACE;
611 default: SkASSERT(false); return "<invalid region op>";
612 }
613 }
614
pointmode_name(SkCanvas::PointMode mode)615 static const char* pointmode_name(SkCanvas::PointMode mode) {
616 switch (mode) {
617 case SkCanvas::kPoints_PointMode: return DEBUGCANVAS_POINTMODE_POINTS;
618 case SkCanvas::kLines_PointMode: return DEBUGCANVAS_POINTMODE_LINES;
619 case SkCanvas::kPolygon_PointMode: return DEBUGCANVAS_POINTMODE_POLYGON;
620 default: SkASSERT(false); return "<invalid point mode>";
621 }
622 }
623
store_scalar(SkJSONWriter & writer,const char * key,SkScalar value,SkScalar defaultValue)624 static void store_scalar(SkJSONWriter& writer,
625 const char* key,
626 SkScalar value,
627 SkScalar defaultValue) {
628 if (value != defaultValue) {
629 writer.appendFloat(key, value);
630 }
631 }
632
store_bool(SkJSONWriter & writer,const char * key,bool value,bool defaultValue)633 static void store_bool(SkJSONWriter& writer, const char* key, bool value, bool defaultValue) {
634 if (value != defaultValue) {
635 writer.appendBool(key, value);
636 }
637 }
638
encode_data(const void * bytes,size_t count,const char * contentType,UrlDataManager & urlDataManager)639 static SkString encode_data(const void* bytes,
640 size_t count,
641 const char* contentType,
642 UrlDataManager& urlDataManager) {
643 sk_sp<SkData> data(SkData::MakeWithCopy(bytes, count));
644 return urlDataManager.addData(data.get(), contentType);
645 }
646
flatten(const SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)647 void DrawCommand::flatten(const SkFlattenable* flattenable,
648 SkJSONWriter& writer,
649 UrlDataManager& urlDataManager) {
650 SkBinaryWriteBuffer buffer;
651 flattenable->flatten(buffer);
652 void* data = sk_malloc_throw(buffer.bytesWritten());
653 buffer.writeToMemory(data);
654 SkString url =
655 encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
656 writer.appendString(DEBUGCANVAS_ATTRIBUTE_NAME, flattenable->getTypeName());
657 writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
658
659 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_VALUES);
660 JsonWriteBuffer jsonBuffer(&writer, &urlDataManager);
661 flattenable->flatten(jsonBuffer);
662 writer.endObject(); // values
663
664 sk_free(data);
665 }
666
WritePNG(SkBitmap bitmap,SkWStream & out)667 void DrawCommand::WritePNG(SkBitmap bitmap, SkWStream& out) {
668 SkPixmap pm;
669 SkAssertResult(bitmap.peekPixels(&pm));
670
671 SkPngEncoder::Options options;
672 options.fZLibLevel = 1;
673 options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
674 SkPngEncoder::Encode(&out, pm, options);
675 }
676
flatten(const SkImage & image,SkJSONWriter & writer,UrlDataManager & urlDataManager)677 bool DrawCommand::flatten(const SkImage& image,
678 SkJSONWriter& writer,
679 UrlDataManager& urlDataManager) {
680 size_t rowBytes = 4 * image.width();
681 SkAutoMalloc buffer(rowBytes * image.height());
682 SkImageInfo dstInfo =
683 SkImageInfo::Make(image.dimensions(), kN32_SkColorType, kPremul_SkAlphaType);
684 if (!image.readPixels(dstInfo, buffer.get(), rowBytes, 0, 0)) {
685 SkDebugf("readPixels failed\n");
686 return false;
687 }
688
689 SkBitmap bm;
690 bm.installPixels(dstInfo, buffer.get(), rowBytes);
691
692 SkDynamicMemoryWStream out;
693 DrawCommand::WritePNG(bm, out);
694 sk_sp<SkData> encoded = out.detachAsData();
695 SkString url = encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager);
696 writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
697 return true;
698 }
699
color_type_name(SkColorType colorType)700 static const char* color_type_name(SkColorType colorType) {
701 switch (colorType) {
702 case kARGB_4444_SkColorType: return DEBUGCANVAS_COLORTYPE_ARGB4444;
703 case kRGBA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_RGBA8888;
704 case kBGRA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_BGRA8888;
705 case kRGB_565_SkColorType: return DEBUGCANVAS_COLORTYPE_565;
706 case kGray_8_SkColorType: return DEBUGCANVAS_COLORTYPE_GRAY8;
707 case kAlpha_8_SkColorType: return DEBUGCANVAS_COLORTYPE_ALPHA8;
708 default: SkASSERT(false); return DEBUGCANVAS_COLORTYPE_RGBA8888;
709 }
710 }
711
alpha_type_name(SkAlphaType alphaType)712 static const char* alpha_type_name(SkAlphaType alphaType) {
713 switch (alphaType) {
714 case kOpaque_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_OPAQUE;
715 case kPremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_PREMUL;
716 case kUnpremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_UNPREMUL;
717 default: SkASSERT(false); return DEBUGCANVAS_ALPHATYPE_OPAQUE;
718 }
719 }
720
flatten(const SkBitmap & bitmap,SkJSONWriter & writer,UrlDataManager & urlDataManager)721 bool DrawCommand::flatten(const SkBitmap& bitmap,
722 SkJSONWriter& writer,
723 UrlDataManager& urlDataManager) {
724 sk_sp<SkImage> image(SkImage::MakeFromBitmap(bitmap));
725 writer.appendString(DEBUGCANVAS_ATTRIBUTE_COLOR, color_type_name(bitmap.colorType()));
726 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, alpha_type_name(bitmap.alphaType()));
727 bool success = flatten(*image, writer, urlDataManager);
728 return success;
729 }
730
apply_font_hinting(const SkFont & font,SkJSONWriter & writer)731 static void apply_font_hinting(const SkFont& font, SkJSONWriter& writer) {
732 SkFontHinting hinting = font.getHinting();
733 if (hinting != SkPaintDefaults_Hinting) {
734 switch (hinting) {
735 case SkFontHinting::kNone:
736 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NONE);
737 break;
738 case SkFontHinting::kSlight:
739 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_SLIGHT);
740 break;
741 case SkFontHinting::kNormal:
742 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NORMAL);
743 break;
744 case SkFontHinting::kFull:
745 writer.appendString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_FULL);
746 break;
747 }
748 }
749 }
750
apply_font_edging(const SkFont & font,SkJSONWriter & writer)751 static void apply_font_edging(const SkFont& font, SkJSONWriter& writer) {
752 switch (font.getEdging()) {
753 case SkFont::Edging::kAlias:
754 writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ALIAS);
755 break;
756 case SkFont::Edging::kAntiAlias:
757 writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ANTIALIAS);
758 break;
759 case SkFont::Edging::kSubpixelAntiAlias:
760 writer.appendString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS);
761 break;
762 }
763 }
764
apply_paint_color(const SkPaint & paint,SkJSONWriter & writer)765 static void apply_paint_color(const SkPaint& paint, SkJSONWriter& writer) {
766 SkColor color = paint.getColor();
767 if (color != SK_ColorBLACK) {
768 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
769 DrawCommand::MakeJsonColor(writer, color);
770 }
771 }
772
apply_paint_style(const SkPaint & paint,SkJSONWriter & writer)773 static void apply_paint_style(const SkPaint& paint, SkJSONWriter& writer) {
774 SkPaint::Style style = paint.getStyle();
775 if (style != SkPaint::kFill_Style) {
776 switch (style) {
777 case SkPaint::kStroke_Style: {
778 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKE);
779 break;
780 }
781 case SkPaint::kStrokeAndFill_Style: {
782 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKEANDFILL);
783 break;
784 }
785 default: SkASSERT(false);
786 }
787 }
788 }
789
apply_paint_cap(const SkPaint & paint,SkJSONWriter & writer)790 static void apply_paint_cap(const SkPaint& paint, SkJSONWriter& writer) {
791 SkPaint::Cap cap = paint.getStrokeCap();
792 if (cap != SkPaint::kDefault_Cap) {
793 switch (cap) {
794 case SkPaint::kButt_Cap:
795 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_BUTT);
796 break;
797 case SkPaint::kRound_Cap:
798 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_ROUND);
799 break;
800 case SkPaint::kSquare_Cap:
801 writer.appendString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_SQUARE);
802 break;
803 default: SkASSERT(false);
804 }
805 }
806 }
807
apply_paint_join(const SkPaint & paint,SkJSONWriter & writer)808 static void apply_paint_join(const SkPaint& paint, SkJSONWriter& writer) {
809 SkPaint::Join join = paint.getStrokeJoin();
810 if (join != SkPaint::kDefault_Join) {
811 switch (join) {
812 case SkPaint::kMiter_Join:
813 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_MITER_JOIN);
814 break;
815 case SkPaint::kRound_Join:
816 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_ROUND_JOIN);
817 break;
818 case SkPaint::kBevel_Join:
819 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_BEVEL_JOIN);
820 break;
821 default: SkASSERT(false);
822 }
823 }
824 }
825
apply_paint_filterquality(const SkPaint & paint,SkJSONWriter & writer)826 static void apply_paint_filterquality(const SkPaint& paint, SkJSONWriter& writer) {
827 SkFilterQuality quality = paint.getFilterQuality();
828 switch (quality) {
829 case kNone_SkFilterQuality: break;
830 case kLow_SkFilterQuality:
831 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY, DEBUGCANVAS_FILTERQUALITY_LOW);
832 break;
833 case kMedium_SkFilterQuality:
834 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
835 DEBUGCANVAS_FILTERQUALITY_MEDIUM);
836 break;
837 case kHigh_SkFilterQuality:
838 writer.appendString(DEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
839 DEBUGCANVAS_FILTERQUALITY_HIGH);
840 break;
841 }
842 }
843
apply_paint_maskfilter(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)844 static void apply_paint_maskfilter(const SkPaint& paint,
845 SkJSONWriter& writer,
846 UrlDataManager& urlDataManager) {
847 SkMaskFilter* maskFilter = paint.getMaskFilter();
848 if (maskFilter != nullptr) {
849 SkMaskFilterBase::BlurRec blurRec;
850 if (as_MFB(maskFilter)->asABlur(&blurRec)) {
851 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BLUR);
852 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SIGMA, blurRec.fSigma);
853 switch (blurRec.fStyle) {
854 case SkBlurStyle::kNormal_SkBlurStyle:
855 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_NORMAL);
856 break;
857 case SkBlurStyle::kSolid_SkBlurStyle:
858 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_SOLID);
859 break;
860 case SkBlurStyle::kOuter_SkBlurStyle:
861 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_OUTER);
862 break;
863 case SkBlurStyle::kInner_SkBlurStyle:
864 writer.appendString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_INNER);
865 break;
866 default: SkASSERT(false);
867 }
868 writer.endObject(); // blur
869 } else {
870 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_MASKFILTER);
871 DrawCommand::flatten(maskFilter, writer, urlDataManager);
872 writer.endObject(); // maskFilter
873 }
874 }
875 }
876
apply_paint_patheffect(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)877 static void apply_paint_patheffect(const SkPaint& paint,
878 SkJSONWriter& writer,
879 UrlDataManager& urlDataManager) {
880 SkPathEffect* pathEffect = paint.getPathEffect();
881 if (pathEffect != nullptr) {
882 SkPathEffect::DashInfo dashInfo;
883 SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
884 if (dashType == SkPathEffect::kDash_DashType) {
885 dashInfo.fIntervals = (SkScalar*)sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
886 pathEffect->asADash(&dashInfo);
887 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_DASHING);
888 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_INTERVALS, false);
889 for (int32_t i = 0; i < dashInfo.fCount; i++) {
890 writer.appendFloat(dashInfo.fIntervals[i]);
891 }
892 writer.endArray(); // intervals
893 sk_free(dashInfo.fIntervals);
894 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_PHASE, dashInfo.fPhase);
895 writer.endObject(); // dashing
896 } else {
897 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_PATHEFFECT);
898 DrawCommand::flatten(pathEffect, writer, urlDataManager);
899 writer.endObject(); // pathEffect
900 }
901 }
902 }
903
apply_font_typeface(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)904 static void apply_font_typeface(const SkFont& font,
905 SkJSONWriter& writer,
906 UrlDataManager& urlDataManager) {
907 SkTypeface* typeface = font.getTypefaceOrDefault();
908 if (typeface != nullptr) {
909 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_TYPEFACE);
910 SkDynamicMemoryWStream buffer;
911 typeface->serialize(&buffer);
912 void* data = sk_malloc_throw(buffer.bytesWritten());
913 buffer.copyTo(data);
914 SkString url = encode_data(
915 data, buffer.bytesWritten(), "application/octet-stream", urlDataManager);
916 writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
917 sk_free(data);
918 writer.endObject();
919 }
920 }
921
apply_flattenable(const char * key,SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)922 static void apply_flattenable(const char* key,
923 SkFlattenable* flattenable,
924 SkJSONWriter& writer,
925 UrlDataManager& urlDataManager) {
926 if (flattenable != nullptr) {
927 writer.beginObject(key);
928 DrawCommand::flatten(flattenable, writer, urlDataManager);
929 writer.endObject();
930 }
931 }
932
MakeJsonPaint(SkJSONWriter & writer,const SkPaint & paint,UrlDataManager & urlDataManager)933 void DrawCommand::MakeJsonPaint(SkJSONWriter& writer,
934 const SkPaint& paint,
935 UrlDataManager& urlDataManager) {
936 writer.beginObject();
937 store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
938 store_scalar(writer,
939 DEBUGCANVAS_ATTRIBUTE_STROKEMITER,
940 paint.getStrokeMiter(),
941 SkPaintDefaults_MiterLimit);
942 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
943 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
944
945 apply_paint_color(paint, writer);
946 apply_paint_style(paint, writer);
947 apply_paint_blend_mode(paint, writer);
948 apply_paint_cap(paint, writer);
949 apply_paint_join(paint, writer);
950 apply_paint_filterquality(paint, writer);
951 apply_paint_patheffect(paint, writer, urlDataManager);
952 apply_paint_maskfilter(paint, writer, urlDataManager);
953 apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, paint.getShader(), writer, urlDataManager);
954 apply_flattenable(
955 DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER, paint.getImageFilter(), writer, urlDataManager);
956 apply_flattenable(
957 DEBUGCANVAS_ATTRIBUTE_COLORFILTER, paint.getColorFilter(), writer, urlDataManager);
958 writer.endObject(); // paint
959 }
960
MakeJsonFont(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)961 static void MakeJsonFont(const SkFont& font, SkJSONWriter& writer, UrlDataManager& urlDataManager) {
962 writer.beginObject();
963 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, font.isEmbolden(), false);
964 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_LINEARTEXT, font.isLinearMetrics(), false);
965 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, font.isSubpixel(), false);
966 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, font.isEmbeddedBitmaps(), false);
967 store_bool(writer, DEBUGCANVAS_ATTRIBUTE_AUTOHINTING, font.isForceAutoHinting(), false);
968
969 store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSIZE, font.getSize(), SkPaintDefaults_TextSize);
970 store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getScaleX(), SK_Scalar1);
971 store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getSkewX(), 0.0f);
972 apply_font_edging(font, writer);
973 apply_font_hinting(font, writer);
974 apply_font_typeface(font, writer, urlDataManager);
975 writer.endObject(); // font
976 }
977
MakeJsonLattice(SkJSONWriter & writer,const SkCanvas::Lattice & lattice)978 void DrawCommand::MakeJsonLattice(SkJSONWriter& writer, const SkCanvas::Lattice& lattice) {
979 writer.beginObject();
980 writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT, lattice.fXCount);
981 writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT, lattice.fYCount);
982 if (nullptr != lattice.fBounds) {
983 writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
984 MakeJsonIRect(writer, *lattice.fBounds);
985 }
986 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS);
987 for (int i = 0; i < lattice.fXCount; i++) {
988 writer.appendS32(lattice.fXDivs[i]);
989 }
990 writer.endArray(); // xdivs
991 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS);
992 for (int i = 0; i < lattice.fYCount; i++) {
993 writer.appendS32(lattice.fYDivs[i]);
994 }
995 writer.endArray(); // ydivs
996 if (nullptr != lattice.fRectTypes) {
997 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS);
998 int flagCount = 0;
999 for (int row = 0; row < lattice.fYCount + 1; row++) {
1000 writer.beginArray();
1001 for (int column = 0; column < lattice.fXCount + 1; column++) {
1002 writer.appendS32(lattice.fRectTypes[flagCount++]);
1003 }
1004 writer.endArray(); // row
1005 }
1006 writer.endArray();
1007 }
1008 writer.endObject();
1009 }
1010
ClearCommand(SkColor color)1011 ClearCommand::ClearCommand(SkColor color) : INHERITED(kClear_OpType) { fColor = color; }
1012
execute(SkCanvas * canvas) const1013 void ClearCommand::execute(SkCanvas* canvas) const { canvas->clear(fColor); }
1014
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1015 void ClearCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1016 INHERITED::toJSON(writer, urlDataManager);
1017 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR);
1018 MakeJsonColor(writer, fColor);
1019 }
1020
ClipPathCommand(const SkPath & path,SkClipOp op,bool doAA)1021 ClipPathCommand::ClipPathCommand(const SkPath& path, SkClipOp op, bool doAA)
1022 : INHERITED(kClipPath_OpType) {
1023 fPath = path;
1024 fOp = op;
1025 fDoAA = doAA;
1026 }
1027
execute(SkCanvas * canvas) const1028 void ClipPathCommand::execute(SkCanvas* canvas) const { canvas->clipPath(fPath, fOp, fDoAA); }
1029
render(SkCanvas * canvas) const1030 bool ClipPathCommand::render(SkCanvas* canvas) const {
1031 render_path(canvas, fPath);
1032 return true;
1033 }
1034
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1035 void ClipPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1036 INHERITED::toJSON(writer, urlDataManager);
1037 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1038 MakeJsonPath(writer, fPath);
1039 writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1040 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1041 }
1042
ClipRegionCommand(const SkRegion & region,SkClipOp op)1043 ClipRegionCommand::ClipRegionCommand(const SkRegion& region, SkClipOp op)
1044 : INHERITED(kClipRegion_OpType) {
1045 fRegion = region;
1046 fOp = op;
1047 }
1048
execute(SkCanvas * canvas) const1049 void ClipRegionCommand::execute(SkCanvas* canvas) const { canvas->clipRegion(fRegion, fOp); }
1050
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1051 void ClipRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1052 INHERITED::toJSON(writer, urlDataManager);
1053 writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1054 MakeJsonRegion(writer, fRegion);
1055 writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1056 }
1057
ClipRectCommand(const SkRect & rect,SkClipOp op,bool doAA)1058 ClipRectCommand::ClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA)
1059 : INHERITED(kClipRect_OpType) {
1060 fRect = rect;
1061 fOp = op;
1062 fDoAA = doAA;
1063 }
1064
execute(SkCanvas * canvas) const1065 void ClipRectCommand::execute(SkCanvas* canvas) const { canvas->clipRect(fRect, fOp, fDoAA); }
1066
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1067 void ClipRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1068 INHERITED::toJSON(writer, urlDataManager);
1069 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1070 MakeJsonRect(writer, fRect);
1071 writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1072 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1073
1074 SkString desc;
1075 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1076 }
1077
ClipRRectCommand(const SkRRect & rrect,SkClipOp op,bool doAA)1078 ClipRRectCommand::ClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA)
1079 : INHERITED(kClipRRect_OpType) {
1080 fRRect = rrect;
1081 fOp = op;
1082 fDoAA = doAA;
1083 }
1084
execute(SkCanvas * canvas) const1085 void ClipRRectCommand::execute(SkCanvas* canvas) const { canvas->clipRRect(fRRect, fOp, fDoAA); }
1086
render(SkCanvas * canvas) const1087 bool ClipRRectCommand::render(SkCanvas* canvas) const {
1088 render_rrect(canvas, fRRect);
1089 return true;
1090 }
1091
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1092 void ClipRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1093 INHERITED::toJSON(writer, urlDataManager);
1094 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1095 make_json_rrect(writer, fRRect);
1096 writer.appendString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1097 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1098 }
1099
ConcatCommand(const SkMatrix & matrix)1100 ConcatCommand::ConcatCommand(const SkMatrix& matrix) : INHERITED(kConcat_OpType) {
1101 fMatrix = matrix;
1102 }
1103
execute(SkCanvas * canvas) const1104 void ConcatCommand::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); }
1105
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1106 void ConcatCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1107 INHERITED::toJSON(writer, urlDataManager);
1108 writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
1109 MakeJsonMatrix(writer, fMatrix);
1110 }
1111
1112 ////
1113
DrawAnnotationCommand(const SkRect & rect,const char key[],sk_sp<SkData> value)1114 DrawAnnotationCommand::DrawAnnotationCommand(const SkRect& rect,
1115 const char key[],
1116 sk_sp<SkData> value)
1117 : INHERITED(kDrawAnnotation_OpType), fRect(rect), fKey(key), fValue(std::move(value)) {}
1118
execute(SkCanvas * canvas) const1119 void DrawAnnotationCommand::execute(SkCanvas* canvas) const {
1120 canvas->drawAnnotation(fRect, fKey.c_str(), fValue);
1121 }
1122
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1123 void DrawAnnotationCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1124 INHERITED::toJSON(writer, urlDataManager);
1125
1126 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1127 MakeJsonRect(writer, fRect);
1128 writer.appendString("key", fKey.c_str());
1129 if (fValue.get()) {
1130 // TODO: dump out the "value"
1131 }
1132
1133 SkString desc;
1134 str_append(&desc, fRect)->appendf(" %s", fKey.c_str());
1135 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, desc.c_str());
1136 }
1137
1138 ////
1139
DrawBitmapCommand(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)1140 DrawBitmapCommand::DrawBitmapCommand(const SkBitmap& bitmap,
1141 SkScalar left,
1142 SkScalar top,
1143 const SkPaint* paint)
1144 : INHERITED(kDrawBitmap_OpType), fBitmap(bitmap), fLeft(left), fTop(top), fPaint(paint) {}
1145
execute(SkCanvas * canvas) const1146 void DrawBitmapCommand::execute(SkCanvas* canvas) const {
1147 canvas->drawBitmap(fBitmap, fLeft, fTop, fPaint.getMaybeNull());
1148 }
1149
render(SkCanvas * canvas) const1150 bool DrawBitmapCommand::render(SkCanvas* canvas) const {
1151 render_bitmap(canvas, fBitmap);
1152 return true;
1153 }
1154
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1155 void DrawBitmapCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1156 INHERITED::toJSON(writer, urlDataManager);
1157 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1158 flatten(fBitmap, writer, urlDataManager);
1159 writer.endObject();
1160 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1161 MakeJsonPoint(writer, fLeft, fTop);
1162 if (fPaint.isValid()) {
1163 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1164 MakeJsonPaint(writer, *fPaint, urlDataManager);
1165 }
1166 }
1167
DrawBitmapLatticeCommand(const SkBitmap & bitmap,const SkCanvas::Lattice & lattice,const SkRect & dst,const SkPaint * paint)1168 DrawBitmapLatticeCommand::DrawBitmapLatticeCommand(const SkBitmap& bitmap,
1169 const SkCanvas::Lattice& lattice,
1170 const SkRect& dst,
1171 const SkPaint* paint)
1172 : INHERITED(kDrawBitmapLattice_OpType)
1173 , fBitmap(bitmap)
1174 , fLattice(lattice)
1175 , fDst(dst)
1176 , fPaint(paint) {}
1177
execute(SkCanvas * canvas) const1178 void DrawBitmapLatticeCommand::execute(SkCanvas* canvas) const {
1179 canvas->drawBitmapLattice(fBitmap, fLattice, fDst, fPaint.getMaybeNull());
1180 }
1181
render(SkCanvas * canvas) const1182 bool DrawBitmapLatticeCommand::render(SkCanvas* canvas) const {
1183 SkAutoCanvasRestore acr(canvas, true);
1184 canvas->clear(0xFFFFFFFF);
1185
1186 xlate_and_scale_to_bounds(canvas, fDst);
1187
1188 this->execute(canvas);
1189 return true;
1190 }
1191
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1192 void DrawBitmapLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1193 INHERITED::toJSON(writer, urlDataManager);
1194 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1195 flatten(fBitmap, writer, urlDataManager);
1196 writer.endObject(); // bitmap
1197
1198 writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
1199 MakeJsonLattice(writer, fLattice);
1200 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1201 MakeJsonRect(writer, fDst);
1202 if (fPaint.isValid()) {
1203 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1204 MakeJsonPaint(writer, *fPaint, urlDataManager);
1205 }
1206
1207 SkString desc;
1208 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1209 }
1210
DrawBitmapNineCommand(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1211 DrawBitmapNineCommand::DrawBitmapNineCommand(const SkBitmap& bitmap,
1212 const SkIRect& center,
1213 const SkRect& dst,
1214 const SkPaint* paint)
1215 : INHERITED(kDrawBitmapNine_OpType)
1216 , fBitmap(bitmap)
1217 , fCenter(center)
1218 , fDst(dst)
1219 , fPaint(paint) {}
1220
execute(SkCanvas * canvas) const1221 void DrawBitmapNineCommand::execute(SkCanvas* canvas) const {
1222 canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaint.getMaybeNull());
1223 }
1224
render(SkCanvas * canvas) const1225 bool DrawBitmapNineCommand::render(SkCanvas* canvas) const {
1226 SkRect tmp = SkRect::Make(fCenter);
1227 render_bitmap(canvas, fBitmap, &tmp);
1228 return true;
1229 }
1230
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1231 void DrawBitmapNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1232 INHERITED::toJSON(writer, urlDataManager);
1233 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1234 flatten(fBitmap, writer, urlDataManager);
1235 writer.endObject(); // bitmap
1236
1237 writer.appendName(DEBUGCANVAS_ATTRIBUTE_CENTER);
1238 MakeJsonIRect(writer, fCenter);
1239 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1240 MakeJsonRect(writer, fDst);
1241 if (fPaint.isValid()) {
1242 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1243 MakeJsonPaint(writer, *fPaint, urlDataManager);
1244 }
1245 }
1246
DrawBitmapRectCommand(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1247 DrawBitmapRectCommand::DrawBitmapRectCommand(const SkBitmap& bitmap,
1248 const SkRect* src,
1249 const SkRect& dst,
1250 const SkPaint* paint,
1251 SkCanvas::SrcRectConstraint constraint)
1252 : INHERITED(kDrawBitmapRect_OpType)
1253 , fBitmap(bitmap)
1254 , fSrc(src)
1255 , fDst(dst)
1256 , fPaint(paint)
1257 , fConstraint(constraint) {}
1258
execute(SkCanvas * canvas) const1259 void DrawBitmapRectCommand::execute(SkCanvas* canvas) const {
1260 canvas->legacy_drawBitmapRect(
1261 fBitmap, fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
1262 }
1263
render(SkCanvas * canvas) const1264 bool DrawBitmapRectCommand::render(SkCanvas* canvas) const {
1265 render_bitmap(canvas, fBitmap, fSrc.getMaybeNull());
1266 return true;
1267 }
1268
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1269 void DrawBitmapRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1270 INHERITED::toJSON(writer, urlDataManager);
1271 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BITMAP);
1272 flatten(fBitmap, writer, urlDataManager);
1273 writer.endObject(); // bitmap
1274
1275 if (fSrc.isValid()) {
1276 writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1277 MakeJsonRect(writer, *fSrc);
1278 }
1279 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1280 MakeJsonRect(writer, fDst);
1281 if (fPaint.isValid()) {
1282 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1283 MakeJsonPaint(writer, *fPaint, urlDataManager);
1284 }
1285 if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1286 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1287 }
1288
1289 SkString desc;
1290 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1291 }
1292
DrawImageCommand(const SkImage * image,SkScalar left,SkScalar top,const SkPaint * paint)1293 DrawImageCommand::DrawImageCommand(const SkImage* image,
1294 SkScalar left,
1295 SkScalar top,
1296 const SkPaint* paint)
1297 : INHERITED(kDrawImage_OpType)
1298 , fImage(SkRef(image))
1299 , fLeft(left)
1300 , fTop(top)
1301 , fPaint(paint) {}
1302
execute(SkCanvas * canvas) const1303 void DrawImageCommand::execute(SkCanvas* canvas) const {
1304 canvas->drawImage(fImage.get(), fLeft, fTop, fPaint.getMaybeNull());
1305 }
1306
render(SkCanvas * canvas) const1307 bool DrawImageCommand::render(SkCanvas* canvas) const {
1308 SkAutoCanvasRestore acr(canvas, true);
1309 canvas->clear(0xFFFFFFFF);
1310
1311 xlate_and_scale_to_bounds(
1312 canvas,
1313 SkRect::MakeXYWH(
1314 fLeft, fTop, SkIntToScalar(fImage->width()), SkIntToScalar(fImage->height())));
1315 this->execute(canvas);
1316 return true;
1317 }
1318
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1319 void DrawImageCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1320 INHERITED::toJSON(writer, urlDataManager);
1321
1322
1323 if (urlDataManager.hasImageIndex()) {
1324 writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
1325 writer.appendU64((uint64_t)urlDataManager.lookupImage(fImage.get()));
1326 } else {
1327 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1328 flatten(*fImage, writer, urlDataManager);
1329 writer.endObject(); // image
1330 }
1331
1332 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1333 MakeJsonPoint(writer, fLeft, fTop);
1334 if (fPaint.isValid()) {
1335 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1336 MakeJsonPaint(writer, *fPaint, urlDataManager);
1337 }
1338
1339 writer.appendU32(DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID, fImage->uniqueID());
1340 writer.appendS32(DEBUGCANVAS_ATTRIBUTE_WIDTH, fImage->width());
1341 writer.appendS32(DEBUGCANVAS_ATTRIBUTE_HEIGHT, fImage->height());
1342 switch (fImage->alphaType()) {
1343 case kOpaque_SkAlphaType:
1344 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_OPAQUE);
1345 break;
1346 case kPremul_SkAlphaType:
1347 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_PREMUL);
1348 break;
1349 case kUnpremul_SkAlphaType:
1350 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNPREMUL);
1351 break;
1352 default:
1353 writer.appendString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNKNOWN);
1354 break;
1355 }
1356 }
1357
DrawImageLatticeCommand(const SkImage * image,const SkCanvas::Lattice & lattice,const SkRect & dst,const SkPaint * paint)1358 DrawImageLatticeCommand::DrawImageLatticeCommand(const SkImage* image,
1359 const SkCanvas::Lattice& lattice,
1360 const SkRect& dst,
1361 const SkPaint* paint)
1362 : INHERITED(kDrawImageLattice_OpType)
1363 , fImage(SkRef(image))
1364 , fLattice(lattice)
1365 , fDst(dst)
1366 , fPaint(paint) {}
1367
execute(SkCanvas * canvas) const1368 void DrawImageLatticeCommand::execute(SkCanvas* canvas) const {
1369 canvas->drawImageLattice(fImage.get(), fLattice, fDst, fPaint.getMaybeNull());
1370 }
1371
render(SkCanvas * canvas) const1372 bool DrawImageLatticeCommand::render(SkCanvas* canvas) const {
1373 SkAutoCanvasRestore acr(canvas, true);
1374 canvas->clear(0xFFFFFFFF);
1375
1376 xlate_and_scale_to_bounds(canvas, fDst);
1377
1378 this->execute(canvas);
1379 return true;
1380 }
1381
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1382 void DrawImageLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1383 INHERITED::toJSON(writer, urlDataManager);
1384 if (urlDataManager.hasImageIndex()) {
1385 writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
1386 writer.appendU64((uint64_t)urlDataManager.lookupImage(fImage.get()));
1387 } else {
1388 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1389 flatten(*fImage, writer, urlDataManager);
1390 writer.endObject(); // image
1391 }
1392
1393 writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE);
1394 MakeJsonLattice(writer, fLattice);
1395 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1396 MakeJsonRect(writer, fDst);
1397 if (fPaint.isValid()) {
1398 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1399 MakeJsonPaint(writer, *fPaint, urlDataManager);
1400 }
1401
1402 SkString desc;
1403 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1404 }
1405
DrawImageRectCommand(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1406 DrawImageRectCommand::DrawImageRectCommand(const SkImage* image,
1407 const SkRect* src,
1408 const SkRect& dst,
1409 const SkPaint* paint,
1410 SkCanvas::SrcRectConstraint constraint)
1411 : INHERITED(kDrawImageRect_OpType)
1412 , fImage(SkRef(image))
1413 , fSrc(src)
1414 , fDst(dst)
1415 , fPaint(paint)
1416 , fConstraint(constraint) {}
1417
execute(SkCanvas * canvas) const1418 void DrawImageRectCommand::execute(SkCanvas* canvas) const {
1419 canvas->legacy_drawImageRect(
1420 fImage.get(), fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
1421 }
1422
render(SkCanvas * canvas) const1423 bool DrawImageRectCommand::render(SkCanvas* canvas) const {
1424 SkAutoCanvasRestore acr(canvas, true);
1425 canvas->clear(0xFFFFFFFF);
1426
1427 xlate_and_scale_to_bounds(canvas, fDst);
1428
1429 this->execute(canvas);
1430 return true;
1431 }
1432
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1433 void DrawImageRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1434 INHERITED::toJSON(writer, urlDataManager);
1435 if (urlDataManager.hasImageIndex()) {
1436 writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
1437 writer.appendU64((uint64_t)urlDataManager.lookupImage(fImage.get()));
1438 } else {
1439 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1440 flatten(*fImage, writer, urlDataManager);
1441 writer.endObject(); // image
1442 }
1443
1444 if (fSrc.isValid()) {
1445 writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1446 MakeJsonRect(writer, *fSrc);
1447 }
1448 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1449 MakeJsonRect(writer, fDst);
1450 if (fPaint.isValid()) {
1451 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1452 MakeJsonPaint(writer, *fPaint, urlDataManager);
1453 }
1454 if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1455 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1456 }
1457
1458 SkString desc;
1459 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1460 }
1461
DrawImageRectLayerCommand(DebugLayerManager * layerManager,const int nodeId,const int frame,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1462 DrawImageRectLayerCommand::DrawImageRectLayerCommand(DebugLayerManager* layerManager,
1463 const int nodeId,
1464 const int frame,
1465 const SkRect* src,
1466 const SkRect& dst,
1467 const SkPaint* paint,
1468 SkCanvas::SrcRectConstraint constraint)
1469 : INHERITED(kDrawImageRectLayer_OpType)
1470 , fLayerManager(layerManager)
1471 , fNodeId(nodeId)
1472 , fFrame(frame)
1473 , fSrc(src)
1474 , fDst(dst)
1475 , fPaint(paint)
1476 , fConstraint(constraint) {}
1477
execute(SkCanvas * canvas) const1478 void DrawImageRectLayerCommand::execute(SkCanvas* canvas) const {
1479 sk_sp<SkImage> snapshot = fLayerManager->getLayerAsImage(fNodeId, fFrame);
1480 canvas->legacy_drawImageRect(
1481 snapshot.get(), fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
1482 }
1483
render(SkCanvas * canvas) const1484 bool DrawImageRectLayerCommand::render(SkCanvas* canvas) const {
1485 SkAutoCanvasRestore acr(canvas, true);
1486 canvas->clear(0xFFFFFFFF);
1487
1488 xlate_and_scale_to_bounds(canvas, fDst);
1489
1490 this->execute(canvas);
1491 return true;
1492 }
1493
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1494 void DrawImageRectLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1495 INHERITED::toJSON(writer, urlDataManager);
1496
1497 // Don't append an image attribute here, the image can be rendered in as many different ways
1498 // as there are commands in the layer, at least. the urlDataManager would save each one under
1499 // a different URL.
1500 // Append the node id, and the layer inspector of the debugger will know what to do with it.
1501 writer.appendS64(DEBUGCANVAS_ATTRIBUTE_LAYERNODEID, fNodeId);
1502
1503 if (fSrc.isValid()) {
1504 writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
1505 MakeJsonRect(writer, *fSrc);
1506 }
1507 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1508 MakeJsonRect(writer, fDst);
1509 if (fPaint.isValid()) {
1510 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1511 MakeJsonPaint(writer, *fPaint, urlDataManager);
1512 }
1513 if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1514 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true);
1515 }
1516
1517 SkString desc;
1518 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1519 }
1520
DrawImageNineCommand(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1521 DrawImageNineCommand::DrawImageNineCommand(const SkImage* image,
1522 const SkIRect& center,
1523 const SkRect& dst,
1524 const SkPaint* paint)
1525 : INHERITED(kDrawImageNine_OpType)
1526 , fImage(SkRef(image))
1527 , fCenter(center)
1528 , fDst(dst)
1529 , fPaint(paint) {}
1530
execute(SkCanvas * canvas) const1531 void DrawImageNineCommand::execute(SkCanvas* canvas) const {
1532 canvas->drawImageNine(fImage.get(), fCenter, fDst, fPaint.getMaybeNull());
1533 }
1534
render(SkCanvas * canvas) const1535 bool DrawImageNineCommand::render(SkCanvas* canvas) const {
1536 SkAutoCanvasRestore acr(canvas, true);
1537 canvas->clear(0xFFFFFFFF);
1538
1539 xlate_and_scale_to_bounds(canvas, fDst);
1540
1541 this->execute(canvas);
1542 return true;
1543 }
1544
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1545 void DrawImageNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1546 INHERITED::toJSON(writer, urlDataManager);
1547 if (urlDataManager.hasImageIndex()) {
1548 writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX);
1549 writer.appendU64((uint64_t)urlDataManager.lookupImage(fImage.get()));
1550 } else {
1551 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE);
1552 flatten(*fImage, writer, urlDataManager);
1553 writer.endObject(); // image
1554 }
1555
1556 writer.appendName(DEBUGCANVAS_ATTRIBUTE_CENTER);
1557 MakeJsonIRect(writer, fCenter);
1558 writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
1559 MakeJsonRect(writer, fDst);
1560 if (fPaint.isValid()) {
1561 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1562 MakeJsonPaint(writer, *fPaint, urlDataManager);
1563 }
1564 }
1565
DrawOvalCommand(const SkRect & oval,const SkPaint & paint)1566 DrawOvalCommand::DrawOvalCommand(const SkRect& oval, const SkPaint& paint)
1567 : INHERITED(kDrawOval_OpType) {
1568 fOval = oval;
1569 fPaint = paint;
1570 }
1571
execute(SkCanvas * canvas) const1572 void DrawOvalCommand::execute(SkCanvas* canvas) const { canvas->drawOval(fOval, fPaint); }
1573
render(SkCanvas * canvas) const1574 bool DrawOvalCommand::render(SkCanvas* canvas) const {
1575 canvas->clear(0xFFFFFFFF);
1576 canvas->save();
1577
1578 xlate_and_scale_to_bounds(canvas, fOval);
1579
1580 SkPaint p;
1581 p.setColor(SK_ColorBLACK);
1582 p.setStyle(SkPaint::kStroke_Style);
1583
1584 canvas->drawOval(fOval, p);
1585 canvas->restore();
1586
1587 return true;
1588 }
1589
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1590 void DrawOvalCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1591 INHERITED::toJSON(writer, urlDataManager);
1592 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1593 MakeJsonRect(writer, fOval);
1594 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1595 MakeJsonPaint(writer, fPaint, urlDataManager);
1596 }
1597
DrawArcCommand(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)1598 DrawArcCommand::DrawArcCommand(const SkRect& oval,
1599 SkScalar startAngle,
1600 SkScalar sweepAngle,
1601 bool useCenter,
1602 const SkPaint& paint)
1603 : INHERITED(kDrawArc_OpType) {
1604 fOval = oval;
1605 fStartAngle = startAngle;
1606 fSweepAngle = sweepAngle;
1607 fUseCenter = useCenter;
1608 fPaint = paint;
1609 }
1610
execute(SkCanvas * canvas) const1611 void DrawArcCommand::execute(SkCanvas* canvas) const {
1612 canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, fPaint);
1613 }
1614
render(SkCanvas * canvas) const1615 bool DrawArcCommand::render(SkCanvas* canvas) const {
1616 canvas->clear(0xFFFFFFFF);
1617 canvas->save();
1618
1619 xlate_and_scale_to_bounds(canvas, fOval);
1620
1621 SkPaint p;
1622 p.setColor(SK_ColorBLACK);
1623 p.setStyle(SkPaint::kStroke_Style);
1624
1625 canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, p);
1626 canvas->restore();
1627
1628 return true;
1629 }
1630
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1631 void DrawArcCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1632 INHERITED::toJSON(writer, urlDataManager);
1633 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1634 MakeJsonRect(writer, fOval);
1635 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_STARTANGLE, fStartAngle);
1636 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE, fSweepAngle);
1637 writer.appendBool(DEBUGCANVAS_ATTRIBUTE_USECENTER, fUseCenter);
1638 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1639 MakeJsonPaint(writer, fPaint, urlDataManager);
1640 }
1641
DrawPaintCommand(const SkPaint & paint)1642 DrawPaintCommand::DrawPaintCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1643 fPaint = paint;
1644 }
1645
execute(SkCanvas * canvas) const1646 void DrawPaintCommand::execute(SkCanvas* canvas) const { canvas->drawPaint(fPaint); }
1647
render(SkCanvas * canvas) const1648 bool DrawPaintCommand::render(SkCanvas* canvas) const {
1649 canvas->clear(0xFFFFFFFF);
1650 canvas->drawPaint(fPaint);
1651 return true;
1652 }
1653
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1654 void DrawPaintCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1655 INHERITED::toJSON(writer, urlDataManager);
1656 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1657 MakeJsonPaint(writer, fPaint, urlDataManager);
1658 }
1659
DrawBehindCommand(const SkPaint & paint)1660 DrawBehindCommand::DrawBehindCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1661 fPaint = paint;
1662 }
1663
execute(SkCanvas * canvas) const1664 void DrawBehindCommand::execute(SkCanvas* canvas) const {
1665 SkCanvasPriv::DrawBehind(canvas, fPaint);
1666 }
1667
render(SkCanvas * canvas) const1668 bool DrawBehindCommand::render(SkCanvas* canvas) const {
1669 canvas->clear(0xFFFFFFFF);
1670 SkCanvasPriv::DrawBehind(canvas, fPaint);
1671 return true;
1672 }
1673
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1674 void DrawBehindCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1675 INHERITED::toJSON(writer, urlDataManager);
1676 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1677 MakeJsonPaint(writer, fPaint, urlDataManager);
1678 }
1679
DrawPathCommand(const SkPath & path,const SkPaint & paint)1680 DrawPathCommand::DrawPathCommand(const SkPath& path, const SkPaint& paint)
1681 : INHERITED(kDrawPath_OpType) {
1682 fPath = path;
1683 fPaint = paint;
1684 }
1685
execute(SkCanvas * canvas) const1686 void DrawPathCommand::execute(SkCanvas* canvas) const { canvas->drawPath(fPath, fPaint); }
1687
render(SkCanvas * canvas) const1688 bool DrawPathCommand::render(SkCanvas* canvas) const {
1689 render_path(canvas, fPath);
1690 return true;
1691 }
1692
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1693 void DrawPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1694 INHERITED::toJSON(writer, urlDataManager);
1695 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
1696 MakeJsonPath(writer, fPath);
1697 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1698 MakeJsonPaint(writer, fPaint, urlDataManager);
1699 }
1700
DrawRegionCommand(const SkRegion & region,const SkPaint & paint)1701 DrawRegionCommand::DrawRegionCommand(const SkRegion& region, const SkPaint& paint)
1702 : INHERITED(kDrawRegion_OpType) {
1703 fRegion = region;
1704 fPaint = paint;
1705 }
1706
execute(SkCanvas * canvas) const1707 void DrawRegionCommand::execute(SkCanvas* canvas) const { canvas->drawRegion(fRegion, fPaint); }
1708
render(SkCanvas * canvas) const1709 bool DrawRegionCommand::render(SkCanvas* canvas) const {
1710 render_region(canvas, fRegion);
1711 return true;
1712 }
1713
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1714 void DrawRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1715 INHERITED::toJSON(writer, urlDataManager);
1716 writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION);
1717 MakeJsonRegion(writer, fRegion);
1718 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1719 MakeJsonPaint(writer, fPaint, urlDataManager);
1720 }
1721
BeginDrawPictureCommand(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)1722 BeginDrawPictureCommand::BeginDrawPictureCommand(const SkPicture* picture,
1723 const SkMatrix* matrix,
1724 const SkPaint* paint)
1725 : INHERITED(kBeginDrawPicture_OpType)
1726 , fPicture(SkRef(picture))
1727 , fMatrix(matrix)
1728 , fPaint(paint) {}
1729
execute(SkCanvas * canvas) const1730 void BeginDrawPictureCommand::execute(SkCanvas* canvas) const {
1731 if (fPaint.isValid()) {
1732 SkRect bounds = fPicture->cullRect();
1733 if (fMatrix.isValid()) {
1734 fMatrix->mapRect(&bounds);
1735 }
1736 canvas->saveLayer(&bounds, fPaint.get());
1737 }
1738
1739 if (fMatrix.isValid()) {
1740 if (!fPaint.isValid()) {
1741 canvas->save();
1742 }
1743 canvas->concat(*fMatrix);
1744 }
1745 }
1746
render(SkCanvas * canvas) const1747 bool BeginDrawPictureCommand::render(SkCanvas* canvas) const {
1748 canvas->clear(0xFFFFFFFF);
1749 canvas->save();
1750
1751 xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
1752
1753 canvas->drawPicture(fPicture.get());
1754
1755 canvas->restore();
1756
1757 return true;
1758 }
1759
EndDrawPictureCommand(bool restore)1760 EndDrawPictureCommand::EndDrawPictureCommand(bool restore)
1761 : INHERITED(kEndDrawPicture_OpType), fRestore(restore) {}
1762
execute(SkCanvas * canvas) const1763 void EndDrawPictureCommand::execute(SkCanvas* canvas) const {
1764 if (fRestore) {
1765 canvas->restore();
1766 }
1767 }
1768
DrawPointsCommand(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1769 DrawPointsCommand::DrawPointsCommand(SkCanvas::PointMode mode,
1770 size_t count,
1771 const SkPoint pts[],
1772 const SkPaint& paint)
1773 : INHERITED(kDrawPoints_OpType), fMode(mode), fPts(pts, count), fPaint(paint) {}
1774
execute(SkCanvas * canvas) const1775 void DrawPointsCommand::execute(SkCanvas* canvas) const {
1776 canvas->drawPoints(fMode, fPts.count(), fPts.begin(), fPaint);
1777 }
1778
render(SkCanvas * canvas) const1779 bool DrawPointsCommand::render(SkCanvas* canvas) const {
1780 canvas->clear(0xFFFFFFFF);
1781 canvas->save();
1782
1783 SkRect bounds;
1784
1785 bounds.setEmpty();
1786 for (int i = 0; i < fPts.count(); ++i) {
1787 SkRectPriv::GrowToInclude(&bounds, fPts[i]);
1788 }
1789
1790 xlate_and_scale_to_bounds(canvas, bounds);
1791
1792 SkPaint p;
1793 p.setColor(SK_ColorBLACK);
1794 p.setStyle(SkPaint::kStroke_Style);
1795
1796 canvas->drawPoints(fMode, fPts.count(), fPts.begin(), p);
1797 canvas->restore();
1798
1799 return true;
1800 }
1801
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1802 void DrawPointsCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1803 INHERITED::toJSON(writer, urlDataManager);
1804 writer.appendString(DEBUGCANVAS_ATTRIBUTE_MODE, pointmode_name(fMode));
1805 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POINTS);
1806 for (int i = 0; i < fPts.count(); i++) {
1807 MakeJsonPoint(writer, fPts[i]);
1808 }
1809 writer.endArray(); // points
1810 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1811 MakeJsonPaint(writer, fPaint, urlDataManager);
1812 }
1813
DrawTextBlobCommand(sk_sp<SkTextBlob> blob,SkScalar x,SkScalar y,const SkPaint & paint)1814 DrawTextBlobCommand::DrawTextBlobCommand(sk_sp<SkTextBlob> blob,
1815 SkScalar x,
1816 SkScalar y,
1817 const SkPaint& paint)
1818 : INHERITED(kDrawTextBlob_OpType)
1819 , fBlob(std::move(blob))
1820 , fXPos(x)
1821 , fYPos(y)
1822 , fPaint(paint) {}
1823
execute(SkCanvas * canvas) const1824 void DrawTextBlobCommand::execute(SkCanvas* canvas) const {
1825 canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1826 }
1827
render(SkCanvas * canvas) const1828 bool DrawTextBlobCommand::render(SkCanvas* canvas) const {
1829 canvas->clear(SK_ColorWHITE);
1830 canvas->save();
1831
1832 SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
1833 xlate_and_scale_to_bounds(canvas, bounds);
1834
1835 canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1836
1837 canvas->restore();
1838
1839 return true;
1840 }
1841
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1842 void DrawTextBlobCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1843 INHERITED::toJSON(writer, urlDataManager);
1844 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_RUNS);
1845 SkTextBlobRunIterator iter(fBlob.get());
1846 while (!iter.done()) {
1847 writer.beginObject(); // run
1848 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_GLYPHS);
1849 for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1850 writer.appendU32(iter.glyphs()[i]);
1851 }
1852 writer.endArray(); // glyphs
1853 if (iter.positioning() != SkTextBlobRunIterator::kDefault_Positioning) {
1854 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POSITIONS);
1855 const SkScalar* iterPositions = iter.pos();
1856 for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1857 switch (iter.positioning()) {
1858 case SkTextBlobRunIterator::kFull_Positioning:
1859 MakeJsonPoint(writer, iterPositions[i * 2], iterPositions[i * 2 + 1]);
1860 break;
1861 case SkTextBlobRunIterator::kHorizontal_Positioning:
1862 writer.appendFloat(iterPositions[i]);
1863 break;
1864 case SkTextBlobRunIterator::kDefault_Positioning: break;
1865 case SkTextBlobRunIterator::kRSXform_Positioning:
1866 // TODO_RSXFORM_BLOB
1867 break;
1868 }
1869 }
1870 writer.endArray(); // positions
1871 }
1872 writer.appendName(DEBUGCANVAS_ATTRIBUTE_FONT);
1873 MakeJsonFont(iter.font(), writer, urlDataManager);
1874 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1875 MakeJsonPoint(writer, iter.offset());
1876
1877 writer.endObject(); // run
1878 iter.next();
1879 }
1880 writer.endArray(); // runs
1881 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_X, fXPos);
1882 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_Y, fYPos);
1883 SkRect bounds = fBlob->bounds();
1884 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1885 MakeJsonRect(writer, bounds);
1886 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1887 MakeJsonPaint(writer, fPaint, urlDataManager);
1888
1889 SkString desc;
1890 // make the bounds local by applying the x,y
1891 bounds.offset(fXPos, fYPos);
1892 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, bounds)->c_str());
1893 }
1894
DrawPatchCommand(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)1895 DrawPatchCommand::DrawPatchCommand(const SkPoint cubics[12],
1896 const SkColor colors[4],
1897 const SkPoint texCoords[4],
1898 SkBlendMode bmode,
1899 const SkPaint& paint)
1900 : INHERITED(kDrawPatch_OpType), fBlendMode(bmode) {
1901 memcpy(fCubics, cubics, sizeof(fCubics));
1902 if (colors != nullptr) {
1903 memcpy(fColors, colors, sizeof(fColors));
1904 fColorsPtr = fColors;
1905 } else {
1906 fColorsPtr = nullptr;
1907 }
1908 if (texCoords != nullptr) {
1909 memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
1910 fTexCoordsPtr = fTexCoords;
1911 } else {
1912 fTexCoordsPtr = nullptr;
1913 }
1914 fPaint = paint;
1915 }
1916
execute(SkCanvas * canvas) const1917 void DrawPatchCommand::execute(SkCanvas* canvas) const {
1918 canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fBlendMode, fPaint);
1919 }
1920
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1921 void DrawPatchCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1922 INHERITED::toJSON(writer, urlDataManager);
1923 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_CUBICS);
1924 for (int i = 0; i < 12; i++) {
1925 MakeJsonPoint(writer, fCubics[i]);
1926 }
1927 writer.endArray(); // cubics
1928 if (fColorsPtr != nullptr) {
1929 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_COLORS);
1930 for (int i = 0; i < 4; i++) {
1931 MakeJsonColor(writer, fColorsPtr[i]);
1932 }
1933 writer.endArray(); // colors
1934 }
1935 if (fTexCoordsPtr != nullptr) {
1936 writer.beginArray(DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS);
1937 for (int i = 0; i < 4; i++) {
1938 MakeJsonPoint(writer, fTexCoords[i]);
1939 }
1940 writer.endArray(); // texCoords
1941 }
1942 // fBlendMode
1943 }
1944
DrawRectCommand(const SkRect & rect,const SkPaint & paint)1945 DrawRectCommand::DrawRectCommand(const SkRect& rect, const SkPaint& paint)
1946 : INHERITED(kDrawRect_OpType) {
1947 fRect = rect;
1948 fPaint = paint;
1949 }
1950
execute(SkCanvas * canvas) const1951 void DrawRectCommand::execute(SkCanvas* canvas) const { canvas->drawRect(fRect, fPaint); }
1952
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1953 void DrawRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1954 INHERITED::toJSON(writer, urlDataManager);
1955 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1956 MakeJsonRect(writer, fRect);
1957 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1958 MakeJsonPaint(writer, fPaint, urlDataManager);
1959
1960 SkString desc;
1961 writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1962 }
1963
DrawRRectCommand(const SkRRect & rrect,const SkPaint & paint)1964 DrawRRectCommand::DrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
1965 : INHERITED(kDrawRRect_OpType) {
1966 fRRect = rrect;
1967 fPaint = paint;
1968 }
1969
execute(SkCanvas * canvas) const1970 void DrawRRectCommand::execute(SkCanvas* canvas) const { canvas->drawRRect(fRRect, fPaint); }
1971
render(SkCanvas * canvas) const1972 bool DrawRRectCommand::render(SkCanvas* canvas) const {
1973 render_rrect(canvas, fRRect);
1974 return true;
1975 }
1976
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1977 void DrawRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1978 INHERITED::toJSON(writer, urlDataManager);
1979 writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS);
1980 make_json_rrect(writer, fRRect);
1981 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
1982 MakeJsonPaint(writer, fPaint, urlDataManager);
1983 }
1984
DrawDRRectCommand(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1985 DrawDRRectCommand::DrawDRRectCommand(const SkRRect& outer,
1986 const SkRRect& inner,
1987 const SkPaint& paint)
1988 : INHERITED(kDrawDRRect_OpType) {
1989 fOuter = outer;
1990 fInner = inner;
1991 fPaint = paint;
1992 }
1993
execute(SkCanvas * canvas) const1994 void DrawDRRectCommand::execute(SkCanvas* canvas) const {
1995 canvas->drawDRRect(fOuter, fInner, fPaint);
1996 }
1997
render(SkCanvas * canvas) const1998 bool DrawDRRectCommand::render(SkCanvas* canvas) const {
1999 render_drrect(canvas, fOuter, fInner);
2000 return true;
2001 }
2002
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2003 void DrawDRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2004 INHERITED::toJSON(writer, urlDataManager);
2005 writer.appendName(DEBUGCANVAS_ATTRIBUTE_OUTER);
2006 make_json_rrect(writer, fOuter);
2007 writer.appendName(DEBUGCANVAS_ATTRIBUTE_INNER);
2008 make_json_rrect(writer, fInner);
2009 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
2010 MakeJsonPaint(writer, fPaint, urlDataManager);
2011 }
2012
DrawShadowCommand(const SkPath & path,const SkDrawShadowRec & rec)2013 DrawShadowCommand::DrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec)
2014 : INHERITED(kDrawShadow_OpType) {
2015 fPath = path;
2016 fShadowRec = rec;
2017 }
2018
execute(SkCanvas * canvas) const2019 void DrawShadowCommand::execute(SkCanvas* canvas) const {
2020 canvas->private_draw_shadow_rec(fPath, fShadowRec);
2021 }
2022
render(SkCanvas * canvas) const2023 bool DrawShadowCommand::render(SkCanvas* canvas) const {
2024 render_shadow(canvas, fPath, fShadowRec);
2025 return true;
2026 }
2027
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2028 void DrawShadowCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2029 INHERITED::toJSON(writer, urlDataManager);
2030
2031 bool geometricOnly = SkToBool(fShadowRec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
2032 bool transparentOccluder =
2033 SkToBool(fShadowRec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
2034
2035 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH);
2036 MakeJsonPath(writer, fPath);
2037 writer.appendName(DEBUGCANVAS_ATTRIBUTE_ZPLANE);
2038 MakeJsonPoint3(writer, fShadowRec.fZPlaneParams);
2039 writer.appendName(DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION);
2040 MakeJsonPoint3(writer, fShadowRec.fLightPos);
2041 writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS, fShadowRec.fLightRadius);
2042 writer.appendName(DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR);
2043 MakeJsonColor(writer, fShadowRec.fAmbientColor);
2044 writer.appendName(DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR);
2045 MakeJsonColor(writer, fShadowRec.fSpotColor);
2046 store_bool(writer, DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC, transparentOccluder, false);
2047 store_bool(writer, DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY, geometricOnly, false);
2048 }
2049
2050 ///////////////////////////////////////////////////////////////////////////////////////////////////
2051
DrawEdgeAAQuadCommand(const SkRect & rect,const SkPoint clip[],SkCanvas::QuadAAFlags aa,const SkColor4f & color,SkBlendMode mode)2052 DrawEdgeAAQuadCommand::DrawEdgeAAQuadCommand(const SkRect& rect,
2053 const SkPoint clip[],
2054 SkCanvas::QuadAAFlags aa,
2055 const SkColor4f& color,
2056 SkBlendMode mode)
2057 : INHERITED(kDrawEdgeAAQuad_OpType)
2058 , fRect(rect)
2059 , fHasClip(clip != nullptr)
2060 , fAA(aa)
2061 , fColor(color)
2062 , fMode(mode) {
2063 if (clip) {
2064 for (int i = 0; i < 4; ++i) {
2065 fClip[i] = clip[i];
2066 }
2067 }
2068 }
2069
execute(SkCanvas * canvas) const2070 void DrawEdgeAAQuadCommand::execute(SkCanvas* canvas) const {
2071 canvas->experimental_DrawEdgeAAQuad(fRect, fHasClip ? fClip : nullptr, fAA, fColor, fMode);
2072 }
2073
DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],int count,const SkPoint dstClips[],const SkMatrix preViewMatrices[],const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)2074 DrawEdgeAAImageSetCommand::DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[],
2075 int count,
2076 const SkPoint dstClips[],
2077 const SkMatrix preViewMatrices[],
2078 const SkPaint* paint,
2079 SkCanvas::SrcRectConstraint constraint)
2080 : INHERITED(kDrawEdgeAAImageSet_OpType)
2081 , fSet(count)
2082 , fCount(count)
2083 , fPaint(paint)
2084 , fConstraint(constraint) {
2085 int totalDstClipCount, totalMatrixCount;
2086 SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);
2087
2088 std::copy_n(set, count, fSet.get());
2089 fDstClips.reset(totalDstClipCount);
2090 std::copy_n(dstClips, totalDstClipCount, fDstClips.get());
2091 fPreViewMatrices.reset(totalMatrixCount);
2092 std::copy_n(preViewMatrices, totalMatrixCount, fPreViewMatrices.get());
2093 }
2094
execute(SkCanvas * canvas) const2095 void DrawEdgeAAImageSetCommand::execute(SkCanvas* canvas) const {
2096 canvas->experimental_DrawEdgeAAImageSet(fSet.get(),
2097 fCount,
2098 fDstClips.get(),
2099 fPreViewMatrices.get(),
2100 fPaint.getMaybeNull(),
2101 fConstraint);
2102 }
2103
2104 ///////////////////////////////////////////////////////////////////////////////////////////////////
2105
DrawDrawableCommand(SkDrawable * drawable,const SkMatrix * matrix)2106 DrawDrawableCommand::DrawDrawableCommand(SkDrawable* drawable, const SkMatrix* matrix)
2107 : INHERITED(kDrawDrawable_OpType), fDrawable(SkRef(drawable)), fMatrix(matrix) {}
2108
execute(SkCanvas * canvas) const2109 void DrawDrawableCommand::execute(SkCanvas* canvas) const {
2110 canvas->drawDrawable(fDrawable.get(), fMatrix.getMaybeNull());
2111 }
2112
2113 ///////////////////////////////////////////////////////////////////////////////////////////////////
2114
DrawVerticesCommand(sk_sp<SkVertices> vertices,SkBlendMode bmode,const SkPaint & paint)2115 DrawVerticesCommand::DrawVerticesCommand(sk_sp<SkVertices> vertices,
2116 SkBlendMode bmode,
2117 const SkPaint& paint)
2118 : INHERITED(kDrawVertices_OpType)
2119 , fVertices(std::move(vertices))
2120 , fBlendMode(bmode)
2121 , fPaint(paint) {}
2122
execute(SkCanvas * canvas) const2123 void DrawVerticesCommand::execute(SkCanvas* canvas) const {
2124 canvas->drawVertices(fVertices, fBlendMode, fPaint);
2125 }
2126
2127 ///////////////////////////////////////////////////////////////////////////////////////////////////
2128
DrawAtlasCommand(const SkImage * image,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)2129 DrawAtlasCommand::DrawAtlasCommand(const SkImage* image,
2130 const SkRSXform xform[],
2131 const SkRect tex[],
2132 const SkColor colors[],
2133 int count,
2134 SkBlendMode bmode,
2135 const SkRect* cull,
2136 const SkPaint* paint)
2137 : INHERITED(kDrawAtlas_OpType)
2138 , fImage(SkRef(image))
2139 , fXform(xform, count)
2140 , fTex(tex, count)
2141 , fColors(colors, colors ? count : 0)
2142 , fBlendMode(bmode)
2143 , fCull(cull)
2144 , fPaint(paint) {}
2145
execute(SkCanvas * canvas) const2146 void DrawAtlasCommand::execute(SkCanvas* canvas) const {
2147 canvas->drawAtlas(fImage.get(),
2148 fXform.begin(),
2149 fTex.begin(),
2150 fColors.isEmpty() ? nullptr : fColors.begin(),
2151 fXform.count(),
2152 fBlendMode,
2153 fCull.getMaybeNull(),
2154 fPaint.getMaybeNull());
2155 }
2156
2157 ///////////////////////////////////////////////////////////////////////////////////////////////////
2158
RestoreCommand()2159 RestoreCommand::RestoreCommand() : INHERITED(kRestore_OpType) {}
2160
execute(SkCanvas * canvas) const2161 void RestoreCommand::execute(SkCanvas* canvas) const { canvas->restore(); }
2162
SaveCommand()2163 SaveCommand::SaveCommand() : INHERITED(kSave_OpType) {}
2164
execute(SkCanvas * canvas) const2165 void SaveCommand::execute(SkCanvas* canvas) const { canvas->save(); }
2166
SaveLayerCommand(const SkCanvas::SaveLayerRec & rec)2167 SaveLayerCommand::SaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
2168 : INHERITED(kSaveLayer_OpType)
2169 , fBounds(rec.fBounds)
2170 , fPaint(rec.fPaint)
2171 , fBackdrop(SkSafeRef(rec.fBackdrop))
2172 , fSaveLayerFlags(rec.fSaveLayerFlags) {}
2173
execute(SkCanvas * canvas) const2174 void SaveLayerCommand::execute(SkCanvas* canvas) const {
2175 canvas->saveLayer(
2176 SkCanvas::SaveLayerRec(fBounds.getMaybeNull(), fPaint.getMaybeNull(), fSaveLayerFlags));
2177 }
2178
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2179 void SaveLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2180 INHERITED::toJSON(writer, urlDataManager);
2181 if (fBounds.isValid()) {
2182 writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS);
2183 MakeJsonRect(writer, *fBounds);
2184 }
2185 if (fPaint.isValid()) {
2186 writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT);
2187 MakeJsonPaint(writer, *fPaint, urlDataManager);
2188 }
2189 if (fBackdrop != nullptr) {
2190 writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BACKDROP);
2191 flatten(fBackdrop.get(), writer, urlDataManager);
2192 writer.endObject(); // backdrop
2193 }
2194 if (fSaveLayerFlags != 0) {
2195 SkDebugf("unsupported: saveLayer flags\n");
2196 SkASSERT(false);
2197 }
2198 }
2199
SetMatrixCommand(const SkMatrix & matrix)2200 SetMatrixCommand::SetMatrixCommand(const SkMatrix& matrix) : INHERITED(kSetMatrix_OpType) {
2201 fMatrix = matrix;
2202 }
2203
execute(SkCanvas * canvas) const2204 void SetMatrixCommand::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); }
2205
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2206 void SetMatrixCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2207 INHERITED::toJSON(writer, urlDataManager);
2208 writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX);
2209 MakeJsonMatrix(writer, fMatrix);
2210 }
2211