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