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 "SkDrawCommand.h"
9 
10 #include <algorithm>
11 #include "SkAutoMalloc.h"
12 #include "SkCanvasPriv.h"
13 #include "SkClipOpPriv.h"
14 #include "SkColorFilter.h"
15 #include "SkDashPathEffect.h"
16 #include "SkDrawable.h"
17 #include "SkImageFilter.h"
18 #include "SkJsonWriteBuffer.h"
19 #include "SkLatticeIter.h"
20 #include "SkMaskFilterBase.h"
21 #include "SkPaintDefaults.h"
22 #include "SkPathEffect.h"
23 #include "SkPicture.h"
24 #include "SkPngEncoder.h"
25 #include "SkReadBuffer.h"
26 #include "SkRectPriv.h"
27 #include "SkShadowFlags.h"
28 #include "SkTHash.h"
29 #include "SkTextBlobPriv.h"
30 #include "SkTypeface.h"
31 #include "SkWriteBuffer.h"
32 
33 #define SKDEBUGCANVAS_ATTRIBUTE_COMMAND           "command"
34 #define SKDEBUGCANVAS_ATTRIBUTE_VISIBLE           "visible"
35 #define SKDEBUGCANVAS_ATTRIBUTE_MATRIX            "matrix"
36 #define SKDEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS    "drawDepthTranslation"
37 #define SKDEBUGCANVAS_ATTRIBUTE_COORDS            "coords"
38 #define SKDEBUGCANVAS_ATTRIBUTE_EDGING            "edging"
39 #define SKDEBUGCANVAS_ATTRIBUTE_HINTING           "hinting"
40 #define SKDEBUGCANVAS_ATTRIBUTE_BOUNDS            "bounds"
41 #define SKDEBUGCANVAS_ATTRIBUTE_PAINT             "paint"
42 #define SKDEBUGCANVAS_ATTRIBUTE_OUTER             "outer"
43 #define SKDEBUGCANVAS_ATTRIBUTE_INNER             "inner"
44 #define SKDEBUGCANVAS_ATTRIBUTE_MODE              "mode"
45 #define SKDEBUGCANVAS_ATTRIBUTE_POINTS            "points"
46 #define SKDEBUGCANVAS_ATTRIBUTE_PATH              "path"
47 #define SKDEBUGCANVAS_ATTRIBUTE_TEXT              "text"
48 #define SKDEBUGCANVAS_ATTRIBUTE_COLOR             "color"
49 #define SKDEBUGCANVAS_ATTRIBUTE_ALPHA             "alpha"
50 #define SKDEBUGCANVAS_ATTRIBUTE_BLENDMODE         "blendMode"
51 #define SKDEBUGCANVAS_ATTRIBUTE_STYLE             "style"
52 #define SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH       "strokeWidth"
53 #define SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER       "strokeMiter"
54 #define SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN        "strokeJoin"
55 #define SKDEBUGCANVAS_ATTRIBUTE_CAP               "cap"
56 #define SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS         "antiAlias"
57 #define SKDEBUGCANVAS_ATTRIBUTE_DITHER            "dither"
58 #define SKDEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT      "fakeBoldText"
59 #define SKDEBUGCANVAS_ATTRIBUTE_LINEARTEXT        "linearText"
60 #define SKDEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT      "subpixelText"
61 #define SKDEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT       "devKernText"
62 #define SKDEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT     "lcdRenderText"
63 #define SKDEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT "embeddedBitmapText"
64 #define SKDEBUGCANVAS_ATTRIBUTE_AUTOHINTING       "forceAutoHinting"
65 #define SKDEBUGCANVAS_ATTRIBUTE_REGION            "region"
66 #define SKDEBUGCANVAS_ATTRIBUTE_REGIONOP          "op"
67 #define SKDEBUGCANVAS_ATTRIBUTE_EDGESTYLE         "edgeStyle"
68 #define SKDEBUGCANVAS_ATTRIBUTE_DEVICEREGION      "deviceRegion"
69 #define SKDEBUGCANVAS_ATTRIBUTE_BLUR              "blur"
70 #define SKDEBUGCANVAS_ATTRIBUTE_SIGMA             "sigma"
71 #define SKDEBUGCANVAS_ATTRIBUTE_QUALITY           "quality"
72 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE          "textSize"
73 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX        "textScaleX"
74 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX         "textSkewX"
75 #define SKDEBUGCANVAS_ATTRIBUTE_DASHING           "dashing"
76 #define SKDEBUGCANVAS_ATTRIBUTE_INTERVALS         "intervals"
77 #define SKDEBUGCANVAS_ATTRIBUTE_PHASE             "phase"
78 #define SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE          "fillType"
79 #define SKDEBUGCANVAS_ATTRIBUTE_VERBS             "verbs"
80 #define SKDEBUGCANVAS_ATTRIBUTE_NAME              "name"
81 #define SKDEBUGCANVAS_ATTRIBUTE_DATA              "data"
82 #define SKDEBUGCANVAS_ATTRIBUTE_VALUES            "values"
83 #define SKDEBUGCANVAS_ATTRIBUTE_SHADER            "shader"
84 #define SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT        "pathEffect"
85 #define SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER        "maskFilter"
86 #define SKDEBUGCANVAS_ATTRIBUTE_XFERMODE          "xfermode"
87 #define SKDEBUGCANVAS_ATTRIBUTE_LOOPER            "looper"
88 #define SKDEBUGCANVAS_ATTRIBUTE_BACKDROP          "backdrop"
89 #define SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER       "colorfilter"
90 #define SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER       "imagefilter"
91 #define SKDEBUGCANVAS_ATTRIBUTE_IMAGE             "image"
92 #define SKDEBUGCANVAS_ATTRIBUTE_BITMAP            "bitmap"
93 #define SKDEBUGCANVAS_ATTRIBUTE_SRC               "src"
94 #define SKDEBUGCANVAS_ATTRIBUTE_DST               "dst"
95 #define SKDEBUGCANVAS_ATTRIBUTE_CENTER            "center"
96 #define SKDEBUGCANVAS_ATTRIBUTE_STRICT            "strict"
97 #define SKDEBUGCANVAS_ATTRIBUTE_DESCRIPTION       "description"
98 #define SKDEBUGCANVAS_ATTRIBUTE_X                 "x"
99 #define SKDEBUGCANVAS_ATTRIBUTE_Y                 "y"
100 #define SKDEBUGCANVAS_ATTRIBUTE_RUNS              "runs"
101 #define SKDEBUGCANVAS_ATTRIBUTE_POSITIONS         "positions"
102 #define SKDEBUGCANVAS_ATTRIBUTE_GLYPHS            "glyphs"
103 #define SKDEBUGCANVAS_ATTRIBUTE_FONT              "font"
104 #define SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE          "typeface"
105 #define SKDEBUGCANVAS_ATTRIBUTE_CUBICS            "cubics"
106 #define SKDEBUGCANVAS_ATTRIBUTE_COLORS            "colors"
107 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS     "textureCoords"
108 #define SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY     "filterQuality"
109 #define SKDEBUGCANVAS_ATTRIBUTE_STARTANGLE        "startAngle"
110 #define SKDEBUGCANVAS_ATTRIBUTE_SWEEPANGLE        "sweepAngle"
111 #define SKDEBUGCANVAS_ATTRIBUTE_USECENTER         "useCenter"
112 #define SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC         "shortDesc"
113 #define SKDEBUGCANVAS_ATTRIBUTE_UNIQUE_ID         "uniqueID"
114 #define SKDEBUGCANVAS_ATTRIBUTE_WIDTH             "width"
115 #define SKDEBUGCANVAS_ATTRIBUTE_HEIGHT            "height"
116 #define SKDEBUGCANVAS_ATTRIBUTE_ALPHA             "alpha"
117 #define SKDEBUGCANVAS_ATTRIBUTE_LATTICE           "lattice"
118 #define SKDEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT     "xCount"
119 #define SKDEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT     "yCount"
120 #define SKDEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS      "xDivs"
121 #define SKDEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS      "yDivs"
122 #define SKDEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS      "flags"
123 #define SKDEBUGCANVAS_ATTRIBUTE_ZPLANE            "zPlane"
124 #define SKDEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION     "lightPositions"
125 #define SKDEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR      "ambientColor"
126 #define SKDEBUGCANVAS_ATTRIBUTE_SPOTCOLOR         "spotColor"
127 #define SKDEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS       "lightRadius"
128 
129 #define SKDEBUGCANVAS_VERB_MOVE                   "move"
130 #define SKDEBUGCANVAS_VERB_LINE                   "line"
131 #define SKDEBUGCANVAS_VERB_QUAD                   "quad"
132 #define SKDEBUGCANVAS_VERB_CUBIC                  "cubic"
133 #define SKDEBUGCANVAS_VERB_CONIC                  "conic"
134 #define SKDEBUGCANVAS_VERB_CLOSE                  "close"
135 
136 #define SKDEBUGCANVAS_STYLE_FILL                  "fill"
137 #define SKDEBUGCANVAS_STYLE_STROKE                "stroke"
138 #define SKDEBUGCANVAS_STYLE_STROKEANDFILL         "strokeAndFill"
139 
140 #define SKDEBUGCANVAS_POINTMODE_POINTS            "points"
141 #define SKDEBUGCANVAS_POINTMODE_LINES             "lines"
142 #define SKDEBUGCANVAS_POINTMODE_POLYGON           "polygon"
143 
144 #define SKDEBUGCANVAS_REGIONOP_DIFFERENCE         "difference"
145 #define SKDEBUGCANVAS_REGIONOP_INTERSECT          "intersect"
146 #define SKDEBUGCANVAS_REGIONOP_UNION              "union"
147 #define SKDEBUGCANVAS_REGIONOP_XOR                "xor"
148 #define SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE "reverseDifference"
149 #define SKDEBUGCANVAS_REGIONOP_REPLACE            "replace"
150 
151 #define SKDEBUGCANVAS_BLURSTYLE_NORMAL            "normal"
152 #define SKDEBUGCANVAS_BLURSTYLE_SOLID             "solid"
153 #define SKDEBUGCANVAS_BLURSTYLE_OUTER             "outer"
154 #define SKDEBUGCANVAS_BLURSTYLE_INNER             "inner"
155 
156 #define SKDEBUGCANVAS_BLURQUALITY_LOW             "low"
157 #define SKDEBUGCANVAS_BLURQUALITY_HIGH            "high"
158 
159 #define SKDEBUGCANVAS_FILLTYPE_WINDING            "winding"
160 #define SKDEBUGCANVAS_FILLTYPE_EVENODD            "evenOdd"
161 #define SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING     "inverseWinding"
162 #define SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD     "inverseEvenOdd"
163 
164 #define SKDEBUGCANVAS_CAP_BUTT                    "butt"
165 #define SKDEBUGCANVAS_CAP_ROUND                   "round"
166 #define SKDEBUGCANVAS_CAP_SQUARE                  "square"
167 
168 #define SKDEBUGCANVAS_MITER_JOIN                  "miter"
169 #define SKDEBUGCANVAS_ROUND_JOIN                  "round"
170 #define SKDEBUGCANVAS_BEVEL_JOIN                  "bevel"
171 
172 #define SKDEBUGCANVAS_COLORTYPE_ARGB4444          "ARGB4444"
173 #define SKDEBUGCANVAS_COLORTYPE_RGBA8888          "RGBA8888"
174 #define SKDEBUGCANVAS_COLORTYPE_BGRA8888          "BGRA8888"
175 #define SKDEBUGCANVAS_COLORTYPE_565               "565"
176 #define SKDEBUGCANVAS_COLORTYPE_GRAY8             "Gray8"
177 #define SKDEBUGCANVAS_COLORTYPE_INDEX8            "Index8"
178 #define SKDEBUGCANVAS_COLORTYPE_ALPHA8            "Alpha8"
179 
180 #define SKDEBUGCANVAS_ALPHATYPE_OPAQUE            "opaque"
181 #define SKDEBUGCANVAS_ALPHATYPE_PREMUL            "premul"
182 #define SKDEBUGCANVAS_ALPHATYPE_UNPREMUL          "unpremul"
183 #define SKDEBUGCANVAS_ALPHATYPE_UNKNOWN           "unknown"
184 
185 #define SKDEBUGCANVAS_FILTERQUALITY_NONE          "none"
186 #define SKDEBUGCANVAS_FILTERQUALITY_LOW           "low"
187 #define SKDEBUGCANVAS_FILTERQUALITY_MEDIUM        "medium"
188 #define SKDEBUGCANVAS_FILTERQUALITY_HIGH          "high"
189 
190 #define SKDEBUGCANVAS_HINTING_NONE                "none"
191 #define SKDEBUGCANVAS_HINTING_SLIGHT              "slight"
192 #define SKDEBUGCANVAS_HINTING_NORMAL              "normal"
193 #define SKDEBUGCANVAS_HINTING_FULL                "full"
194 
195 #define SKDEBUGCANVAS_EDGING_ALIAS                "alias"
196 #define SKDEBUGCANVAS_EDGING_ANTIALIAS            "antialias"
197 #define SKDEBUGCANVAS_EDGING_SUBPIXELANTIALIAS    "subpixelantialias"
198 
199 #define SKDEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC  "transparentOccluder"
200 #define SKDEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY   "geometricOnly"
201 
str_append(SkString * str,const SkRect & r)202 static SkString* str_append(SkString* str, const SkRect& r) {
203     str->appendf(" [%g %g %g %g]", r.left(), r.top(), r.right(), r.bottom());
204     return str;
205 }
206 
SkDrawCommand(OpType type)207 SkDrawCommand::SkDrawCommand(OpType type)
208     : fOpType(type)
209     , fVisible(true) {
210 }
211 
GetCommandString(OpType type)212 const char* SkDrawCommand::GetCommandString(OpType type) {
213     switch (type) {
214         case kBeginDrawPicture_OpType: return "BeginDrawPicture";
215         case kClear_OpType: return "DrawClear";
216         case kClipPath_OpType: return "ClipPath";
217         case kClipRegion_OpType: return "ClipRegion";
218         case kClipRect_OpType: return "ClipRect";
219         case kClipRRect_OpType: return "ClipRRect";
220         case kConcat_OpType: return "Concat";
221         case kDrawAnnotation_OpType: return "DrawAnnotation";
222         case kDrawBitmap_OpType: return "DrawBitmap";
223         case kDrawBitmapLattice_OpType: return "DrawBitmapLattice";
224         case kDrawBitmapNine_OpType: return "DrawBitmapNine";
225         case kDrawBitmapRect_OpType: return "DrawBitmapRect";
226         case kDrawDRRect_OpType: return "DrawDRRect";
227         case kDrawImage_OpType: return "DrawImage";
228         case kDrawImageLattice_OpType: return "DrawImageLattice";
229         case kDrawImageNine_OpType: return "DrawImageNine";
230         case kDrawImageRect_OpType: return "DrawImageRect";
231         case kDrawImageSet_OpType: return "DrawImageSet";
232         case kDrawOval_OpType: return "DrawOval";
233         case kDrawPaint_OpType: return "DrawPaint";
234         case kDrawPatch_OpType: return "DrawPatch";
235         case kDrawPath_OpType: return "DrawPath";
236         case kDrawArc_OpType: return "DrawArc";
237         case kDrawPoints_OpType: return "DrawPoints";
238         case kDrawRect_OpType: return "DrawRect";
239         case kDrawRRect_OpType: return "DrawRRect";
240         case kDrawRegion_OpType: return "DrawRegion";
241         case kDrawShadow_OpType: return "DrawShadow";
242         case kDrawTextBlob_OpType: return "DrawTextBlob";
243         case kDrawVertices_OpType: return "DrawVertices";
244         case kDrawAtlas_OpType: return "DrawAtlas";
245         case kDrawDrawable_OpType: return "DrawDrawable";
246         case kEndDrawPicture_OpType: return "EndDrawPicture";
247         case kRestore_OpType: return "Restore";
248         case kSave_OpType: return "Save";
249         case kSaveLayer_OpType: return "SaveLayer";
250         case kSetMatrix_OpType: return "SetMatrix";
251         default:
252             SkDebugf("OpType error 0x%08x\n", type);
253             SkASSERT(0);
254             break;
255     }
256     SkDEBUGFAIL("DrawType UNUSED\n");
257     return nullptr;
258 }
259 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const260 void SkDrawCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
261     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_COMMAND, this->GetCommandString(fOpType));
262     writer.appendBool(SKDEBUGCANVAS_ATTRIBUTE_VISIBLE, this->isVisible());
263 }
264 
265 namespace {
266 
xlate_and_scale_to_bounds(SkCanvas * canvas,const SkRect & bounds)267 void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
268     const SkISize& size = canvas->getBaseLayerSize();
269 
270     static const SkScalar kInsetFrac = 0.9f; // Leave a border around object
271 
272     canvas->translate(size.fWidth/2.0f, size.fHeight/2.0f);
273     if (bounds.width() > bounds.height()) {
274         canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.width()),
275                       SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.width()));
276     } else {
277         canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.height()),
278                       SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.height()));
279     }
280     canvas->translate(-bounds.centerX(), -bounds.centerY());
281 }
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(SK_Scalar1, SK_Scalar1,
333                                   xScale * input.width(),
334                                   yScale * input.height());
335 
336     static const int kNumBlocks = 8;
337 
338     canvas->clear(0xFFFFFFFF);
339     SkISize block = {
340         canvas->imageInfo().width()/kNumBlocks,
341         canvas->imageInfo().height()/kNumBlocks
342     };
343     for (int y = 0; y < kNumBlocks; ++y) {
344         for (int x = 0; x < kNumBlocks; ++x) {
345             SkPaint paint;
346             paint.setColor((x+y)%2 ? SK_ColorLTGRAY : SK_ColorDKGRAY);
347             SkRect r = SkRect::MakeXYWH(SkIntToScalar(x*block.width()),
348                                         SkIntToScalar(y*block.height()),
349                                         SkIntToScalar(block.width()),
350                                         SkIntToScalar(block.height()));
351             canvas->drawRect(r, paint);
352         }
353     }
354 
355     canvas->drawBitmapRect(input, dst, nullptr);
356 
357     if (srcRect) {
358         SkRect r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
359                                     srcRect->fTop * yScale + SK_Scalar1,
360                                     srcRect->fRight * xScale + SK_Scalar1,
361                                     srcRect->fBottom * yScale + SK_Scalar1);
362         SkPaint p;
363         p.setColor(SK_ColorRED);
364         p.setStyle(SkPaint::kStroke_Style);
365 
366         canvas->drawRect(r, p);
367     }
368 }
369 
render_rrect(SkCanvas * canvas,const SkRRect & rrect)370 void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
371     canvas->clear(0xFFFFFFFF);
372     canvas->save();
373 
374     const SkRect& bounds = rrect.getBounds();
375 
376     xlate_and_scale_to_bounds(canvas, bounds);
377 
378     SkPaint p;
379     p.setColor(SK_ColorBLACK);
380     p.setStyle(SkPaint::kStroke_Style);
381 
382     canvas->drawRRect(rrect, p);
383     canvas->restore();
384 }
385 
render_drrect(SkCanvas * canvas,const SkRRect & outer,const SkRRect & inner)386 void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
387     canvas->clear(0xFFFFFFFF);
388     canvas->save();
389 
390     const SkRect& bounds = outer.getBounds();
391 
392     xlate_and_scale_to_bounds(canvas, bounds);
393 
394     SkPaint p;
395     p.setColor(SK_ColorBLACK);
396     p.setStyle(SkPaint::kStroke_Style);
397 
398     canvas->drawDRRect(outer, inner, p);
399     canvas->restore();
400 }
401 
render_shadow(SkCanvas * canvas,const SkPath & path,SkDrawShadowRec rec)402 void render_shadow(SkCanvas* canvas, const SkPath& path, SkDrawShadowRec rec) {
403     canvas->clear(0xFFFFFFFF);
404 
405     const SkRect& bounds = path.getBounds();
406     if (bounds.isEmpty()) {
407         return;
408     }
409 
410     SkAutoCanvasRestore acr(canvas, true);
411     xlate_and_scale_to_bounds(canvas, bounds);
412 
413     rec.fAmbientColor = SK_ColorBLACK;
414     rec.fSpotColor = SK_ColorBLACK;
415     canvas->private_draw_shadow_rec(path, rec);
416 }
417 
418 static const char* const gBlendModeMap[] = {
419     "clear",
420     "src",
421     "dst",
422     "srcOver",
423     "dstOver",
424     "srcIn",
425     "dstIn",
426     "srcOut",
427     "dstOut",
428     "srcATop",
429     "dstATop",
430     "xor",
431     "plus",
432     "modulate",
433 
434     "screen",
435 
436     "overlay",
437     "darken",
438     "lighten",
439     "colorDodge",
440     "colorBurn",
441     "hardLight",
442     "softLight",
443     "difference",
444     "exclusion",
445     "multiply",
446 
447     "hue",
448     "saturation",
449     "color",
450     "luminosity",
451 };
452 
453 static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLastMode) + 1,
454               "blendMode mismatch");
455 static_assert(SK_ARRAY_COUNT(gBlendModeMap) == static_cast<size_t>(SkBlendMode::kLuminosity) + 1,
456               "blendMode mismatch");
457 
apply_paint_blend_mode(const SkPaint & paint,SkJSONWriter & writer)458 void apply_paint_blend_mode(const SkPaint& paint, SkJSONWriter& writer) {
459     const auto mode = paint.getBlendMode();
460     if (mode != SkBlendMode::kSrcOver) {
461         SkASSERT(static_cast<size_t>(mode) < SK_ARRAY_COUNT(gBlendModeMap));
462         writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_BLENDMODE,
463                             gBlendModeMap[static_cast<size_t>(mode)]);
464     }
465 }
466 
467 };
468 
MakeJsonColor(SkJSONWriter & writer,const SkColor color)469 void SkDrawCommand::MakeJsonColor(SkJSONWriter& writer, const SkColor color) {
470     writer.beginArray(nullptr, false);
471     writer.appendS32(SkColorGetA(color));
472     writer.appendS32(SkColorGetR(color));
473     writer.appendS32(SkColorGetG(color));
474     writer.appendS32(SkColorGetB(color));
475     writer.endArray();
476 }
477 
MakeJsonColor4f(SkJSONWriter & writer,const SkColor4f & color)478 void SkDrawCommand::MakeJsonColor4f(SkJSONWriter& writer, const SkColor4f& color) {
479     writer.beginArray(nullptr, false);
480     writer.appendFloat(color.fA);
481     writer.appendFloat(color.fR);
482     writer.appendFloat(color.fG);
483     writer.appendFloat(color.fB);
484     writer.endArray();
485 }
486 
MakeJsonPoint(SkJSONWriter & writer,const SkPoint & point)487 void SkDrawCommand::MakeJsonPoint(SkJSONWriter& writer, const SkPoint& point) {
488     writer.beginArray(nullptr, false);
489     writer.appendFloat(point.x());
490     writer.appendFloat(point.y());
491     writer.endArray();
492 }
493 
MakeJsonPoint(SkJSONWriter & writer,SkScalar x,SkScalar y)494 void SkDrawCommand::MakeJsonPoint(SkJSONWriter& writer, SkScalar x, SkScalar y) {
495     writer.beginArray(nullptr, false);
496     writer.appendFloat(x);
497     writer.appendFloat(y);
498     writer.endArray();
499 }
500 
MakeJsonPoint3(SkJSONWriter & writer,const SkPoint3 & point)501 void SkDrawCommand::MakeJsonPoint3(SkJSONWriter& writer, const SkPoint3& point) {
502     writer.beginArray(nullptr, false);
503     writer.appendFloat(point.x());
504     writer.appendFloat(point.y());
505     writer.appendFloat(point.z());
506     writer.endArray();
507 }
508 
MakeJsonRect(SkJSONWriter & writer,const SkRect & rect)509 void SkDrawCommand::MakeJsonRect(SkJSONWriter& writer, const SkRect& rect) {
510     writer.beginArray(nullptr, false);
511     writer.appendFloat(rect.left());
512     writer.appendFloat(rect.top());
513     writer.appendFloat(rect.right());
514     writer.appendFloat(rect.bottom());
515     writer.endArray();
516 }
517 
MakeJsonIRect(SkJSONWriter & writer,const SkIRect & rect)518 void SkDrawCommand::MakeJsonIRect(SkJSONWriter& writer, const SkIRect& rect) {
519     writer.beginArray(nullptr, false);
520     writer.appendS32(rect.left());
521     writer.appendS32(rect.top());
522     writer.appendS32(rect.right());
523     writer.appendS32(rect.bottom());
524     writer.endArray();
525 }
526 
make_json_rrect(SkJSONWriter & writer,const SkRRect & rrect)527 static void make_json_rrect(SkJSONWriter& writer, const SkRRect& rrect) {
528     writer.beginArray(nullptr, false);
529     SkDrawCommand::MakeJsonRect(writer, rrect.rect());
530     SkDrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperLeft_Corner));
531     SkDrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperRight_Corner));
532     SkDrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerRight_Corner));
533     SkDrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerLeft_Corner));
534     writer.endArray();
535 }
536 
MakeJsonMatrix(SkJSONWriter & writer,const SkMatrix & matrix)537 void SkDrawCommand::MakeJsonMatrix(SkJSONWriter& writer, const SkMatrix& matrix) {
538     writer.beginArray();
539     for (int r = 0; r < 3; ++r) {
540         writer.beginArray(nullptr, false);
541         for (int c = 0; c < 3; ++c) {
542             writer.appendFloat(matrix[r * 3 + c]);
543         }
544         writer.endArray();
545     }
546     writer.endArray();
547 }
548 
MakeJsonPath(SkJSONWriter & writer,const SkPath & path)549 void SkDrawCommand::MakeJsonPath(SkJSONWriter& writer, const SkPath& path) {
550     writer.beginObject();
551     switch (path.getFillType()) {
552         case SkPath::kWinding_FillType:
553             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE, SKDEBUGCANVAS_FILLTYPE_WINDING);
554             break;
555         case SkPath::kEvenOdd_FillType:
556             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE, SKDEBUGCANVAS_FILLTYPE_EVENODD);
557             break;
558         case SkPath::kInverseWinding_FillType:
559             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE, SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING);
560             break;
561         case SkPath::kInverseEvenOdd_FillType:
562             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE, SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD);
563             break;
564     }
565     writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_VERBS);
566     SkPath::Iter iter(path, false);
567     SkPoint pts[4];
568     SkPath::Verb verb;
569     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
570         if (verb == SkPath::kClose_Verb) {
571             writer.appendString(SKDEBUGCANVAS_VERB_CLOSE);
572             continue;
573         }
574         writer.beginObject(); // verb
575         switch (verb) {
576             case SkPath::kLine_Verb: {
577                 writer.appendName(SKDEBUGCANVAS_VERB_LINE);
578                 MakeJsonPoint(writer, pts[1]);
579                 break;
580             }
581             case SkPath::kQuad_Verb: {
582                 writer.beginArray(SKDEBUGCANVAS_VERB_QUAD);
583                 MakeJsonPoint(writer, pts[1]);
584                 MakeJsonPoint(writer, pts[2]);
585                 writer.endArray(); // quad coords
586                 break;
587             }
588             case SkPath::kCubic_Verb: {
589                 writer.beginArray(SKDEBUGCANVAS_VERB_CUBIC);
590                 MakeJsonPoint(writer, pts[1]);
591                 MakeJsonPoint(writer, pts[2]);
592                 MakeJsonPoint(writer, pts[3]);
593                 writer.endArray(); // cubic coords
594                 break;
595             }
596             case SkPath::kConic_Verb: {
597                 writer.beginArray(SKDEBUGCANVAS_VERB_CONIC);
598                 MakeJsonPoint(writer, pts[1]);
599                 MakeJsonPoint(writer, pts[2]);
600                 writer.appendFloat(iter.conicWeight());
601                 writer.endArray(); // conic coords
602                 break;
603             }
604             case SkPath::kMove_Verb: {
605                 writer.appendName(SKDEBUGCANVAS_VERB_MOVE);
606                 MakeJsonPoint(writer, pts[0]);
607                 break;
608             }
609             case SkPath::kClose_Verb:
610             case SkPath::kDone_Verb:
611                 // Unreachable
612                 break;
613         }
614         writer.endObject(); // verb
615     }
616     writer.endArray(); // verbs
617     writer.endObject(); // path
618 }
619 
MakeJsonRegion(SkJSONWriter & writer,const SkRegion & region)620 void SkDrawCommand::MakeJsonRegion(SkJSONWriter& writer, const SkRegion& region) {
621     // TODO: Actually serialize the rectangles, rather than just devolving to path
622     SkPath path;
623     region.getBoundaryPath(&path);
624     MakeJsonPath(writer, path);
625 }
626 
regionop_name(SkClipOp op)627 static const char* regionop_name(SkClipOp op) {
628     switch (op) {
629         case kDifference_SkClipOp:
630             return SKDEBUGCANVAS_REGIONOP_DIFFERENCE;
631         case kIntersect_SkClipOp:
632             return SKDEBUGCANVAS_REGIONOP_INTERSECT;
633         case kUnion_SkClipOp:
634             return SKDEBUGCANVAS_REGIONOP_UNION;
635         case kXOR_SkClipOp:
636             return SKDEBUGCANVAS_REGIONOP_XOR;
637         case kReverseDifference_SkClipOp:
638             return SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE;
639         case kReplace_SkClipOp:
640             return SKDEBUGCANVAS_REGIONOP_REPLACE;
641         default:
642             SkASSERT(false);
643             return "<invalid region op>";
644     }
645 }
646 
pointmode_name(SkCanvas::PointMode mode)647 static const char* pointmode_name(SkCanvas::PointMode mode) {
648     switch (mode) {
649         case SkCanvas::kPoints_PointMode:
650             return SKDEBUGCANVAS_POINTMODE_POINTS;
651         case SkCanvas::kLines_PointMode:
652             return SKDEBUGCANVAS_POINTMODE_LINES;
653         case SkCanvas::kPolygon_PointMode:
654             return SKDEBUGCANVAS_POINTMODE_POLYGON;
655         default:
656             SkASSERT(false);
657             return "<invalid point mode>";
658     }
659 }
660 
store_scalar(SkJSONWriter & writer,const char * key,SkScalar value,SkScalar defaultValue)661 static void store_scalar(SkJSONWriter& writer, const char* key, SkScalar value,
662                          SkScalar defaultValue) {
663     if (value != defaultValue) {
664         writer.appendFloat(key, value);
665     }
666 }
667 
store_bool(SkJSONWriter & writer,const char * key,bool value,bool defaultValue)668 static void store_bool(SkJSONWriter& writer,const char* key, bool value, bool defaultValue) {
669     if (value != defaultValue) {
670         writer.appendBool(key, value);
671     }
672 }
673 
encode_data(const void * bytes,size_t count,const char * contentType,UrlDataManager & urlDataManager)674 static SkString encode_data(const void* bytes, size_t count, const char* contentType,
675                             UrlDataManager& urlDataManager) {
676     sk_sp<SkData> data(SkData::MakeWithCopy(bytes, count));
677     return urlDataManager.addData(data.get(), contentType);
678 }
679 
flatten(const SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)680 void SkDrawCommand::flatten(const SkFlattenable* flattenable, SkJSONWriter& writer,
681                             UrlDataManager& urlDataManager) {
682     SkBinaryWriteBuffer buffer;
683     flattenable->flatten(buffer);
684     void* data = sk_malloc_throw(buffer.bytesWritten());
685     buffer.writeToMemory(data);
686     SkString url = encode_data(data, buffer.bytesWritten(), "application/octet-stream",
687                                urlDataManager);
688     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_NAME, flattenable->getTypeName());
689     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
690 
691     writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_VALUES);
692     SkJsonWriteBuffer jsonBuffer(&writer, &urlDataManager);
693     flattenable->flatten(jsonBuffer);
694     writer.endObject(); // values
695 
696     sk_free(data);
697 }
698 
WritePNG(SkBitmap bitmap,SkWStream & out)699 void SkDrawCommand::WritePNG(SkBitmap bitmap, SkWStream& out) {
700     SkPixmap pm;
701     SkAssertResult(bitmap.peekPixels(&pm));
702 
703     SkPngEncoder::Options options;
704     options.fZLibLevel = 1;
705     options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
706     SkPngEncoder::Encode(&out, pm, options);
707 }
708 
flatten(const SkImage & image,SkJSONWriter & writer,UrlDataManager & urlDataManager)709 bool SkDrawCommand::flatten(const SkImage& image, SkJSONWriter& writer,
710                             UrlDataManager& urlDataManager) {
711     size_t rowBytes = 4 * image.width();
712     SkAutoMalloc buffer(rowBytes * image.height());
713     SkImageInfo dstInfo = SkImageInfo::Make(image.width(), image.height(),
714                                             kN32_SkColorType, kPremul_SkAlphaType);
715     if (!image.readPixels(dstInfo, buffer.get(), rowBytes, 0, 0)) {
716         SkDebugf("readPixels failed\n");
717         return false;
718     }
719 
720     SkBitmap bm;
721     bm.installPixels(dstInfo, buffer.get(), rowBytes);
722 
723     SkDynamicMemoryWStream out;
724     SkDrawCommand::WritePNG(bm, out);
725     sk_sp<SkData> encoded = out.detachAsData();
726     SkString url = encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager);
727     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
728     return true;
729 }
730 
color_type_name(SkColorType colorType)731 static const char* color_type_name(SkColorType colorType) {
732     switch (colorType) {
733         case kARGB_4444_SkColorType:
734             return SKDEBUGCANVAS_COLORTYPE_ARGB4444;
735         case kRGBA_8888_SkColorType:
736             return SKDEBUGCANVAS_COLORTYPE_RGBA8888;
737         case kBGRA_8888_SkColorType:
738             return SKDEBUGCANVAS_COLORTYPE_BGRA8888;
739         case kRGB_565_SkColorType:
740             return SKDEBUGCANVAS_COLORTYPE_565;
741         case kGray_8_SkColorType:
742             return SKDEBUGCANVAS_COLORTYPE_GRAY8;
743         case kAlpha_8_SkColorType:
744             return SKDEBUGCANVAS_COLORTYPE_ALPHA8;
745         default:
746             SkASSERT(false);
747             return SKDEBUGCANVAS_COLORTYPE_RGBA8888;
748     }
749 }
750 
alpha_type_name(SkAlphaType alphaType)751 static const char* alpha_type_name(SkAlphaType alphaType) {
752     switch (alphaType) {
753         case kOpaque_SkAlphaType:
754             return SKDEBUGCANVAS_ALPHATYPE_OPAQUE;
755         case kPremul_SkAlphaType:
756             return SKDEBUGCANVAS_ALPHATYPE_PREMUL;
757         case kUnpremul_SkAlphaType:
758             return SKDEBUGCANVAS_ALPHATYPE_UNPREMUL;
759         default:
760             SkASSERT(false);
761             return SKDEBUGCANVAS_ALPHATYPE_OPAQUE;
762     }
763 }
764 
flatten(const SkBitmap & bitmap,SkJSONWriter & writer,UrlDataManager & urlDataManager)765 bool SkDrawCommand::flatten(const SkBitmap& bitmap, SkJSONWriter& writer,
766                             UrlDataManager& urlDataManager) {
767     sk_sp<SkImage> image(SkImage::MakeFromBitmap(bitmap));
768     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_COLOR, color_type_name(bitmap.colorType()));
769     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_ALPHA, alpha_type_name(bitmap.alphaType()));
770     bool success = flatten(*image, writer, urlDataManager);
771     return success;
772 }
773 
apply_font_hinting(const SkFont & font,SkJSONWriter & writer)774 static void apply_font_hinting(const SkFont& font, SkJSONWriter& writer) {
775     SkFontHinting hinting = font.getHinting();
776     if (hinting != SkPaintDefaults_Hinting) {
777         switch (hinting) {
778             case kNo_SkFontHinting:
779                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_HINTING, SKDEBUGCANVAS_HINTING_NONE);
780                 break;
781             case kSlight_SkFontHinting:
782                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_HINTING, SKDEBUGCANVAS_HINTING_SLIGHT);
783                 break;
784             case kNormal_SkFontHinting:
785                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_HINTING, SKDEBUGCANVAS_HINTING_NORMAL);
786                 break;
787             case kFull_SkFontHinting:
788                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_HINTING, SKDEBUGCANVAS_HINTING_FULL);
789                 break;
790         }
791     }
792 }
793 
apply_font_edging(const SkFont & font,SkJSONWriter & writer)794 static void apply_font_edging(const SkFont& font, SkJSONWriter& writer) {
795     switch (font.getEdging()) {
796         case SkFont::Edging::kAlias:
797             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_EDGING, SKDEBUGCANVAS_EDGING_ALIAS);
798             break;
799         case SkFont::Edging::kAntiAlias:
800             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_EDGING, SKDEBUGCANVAS_EDGING_ANTIALIAS);
801             break;
802         case SkFont::Edging::kSubpixelAntiAlias:
803             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_EDGING, SKDEBUGCANVAS_EDGING_SUBPIXELANTIALIAS);
804             break;
805     }
806 }
807 
apply_paint_color(const SkPaint & paint,SkJSONWriter & writer)808 static void apply_paint_color(const SkPaint& paint, SkJSONWriter& writer) {
809     SkColor color = paint.getColor();
810     if (color != SK_ColorBLACK) {
811         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COLOR);
812         SkDrawCommand::MakeJsonColor(writer, color);
813     }
814 }
815 
apply_paint_style(const SkPaint & paint,SkJSONWriter & writer)816 static void apply_paint_style(const SkPaint& paint, SkJSONWriter& writer) {
817     SkPaint::Style style = paint.getStyle();
818     if (style != SkPaint::kFill_Style) {
819         switch (style) {
820             case SkPaint::kStroke_Style: {
821                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_STYLE, SKDEBUGCANVAS_STYLE_STROKE);
822                 break;
823             }
824             case SkPaint::kStrokeAndFill_Style: {
825                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_STYLE, SKDEBUGCANVAS_STYLE_STROKEANDFILL);
826                 break;
827             }
828             default: SkASSERT(false);
829         }
830     }
831 }
832 
apply_paint_cap(const SkPaint & paint,SkJSONWriter & writer)833 static void apply_paint_cap(const SkPaint& paint, SkJSONWriter& writer) {
834     SkPaint::Cap cap = paint.getStrokeCap();
835     if (cap != SkPaint::kDefault_Cap) {
836         switch (cap) {
837             case SkPaint::kButt_Cap:
838                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_CAP, SKDEBUGCANVAS_CAP_BUTT);
839                 break;
840             case SkPaint::kRound_Cap:
841                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_CAP, SKDEBUGCANVAS_CAP_ROUND);
842                 break;
843             case SkPaint::kSquare_Cap:
844                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_CAP, SKDEBUGCANVAS_CAP_SQUARE);
845                 break;
846             default: SkASSERT(false);
847         }
848     }
849 }
850 
apply_paint_join(const SkPaint & paint,SkJSONWriter & writer)851 static void apply_paint_join(const SkPaint& paint, SkJSONWriter& writer) {
852     SkPaint::Join join = paint.getStrokeJoin();
853     if (join != SkPaint::kDefault_Join) {
854         switch (join) {
855             case SkPaint::kMiter_Join:
856                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN, SKDEBUGCANVAS_MITER_JOIN);
857                 break;
858             case SkPaint::kRound_Join:
859                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN, SKDEBUGCANVAS_ROUND_JOIN);
860                 break;
861             case SkPaint::kBevel_Join:
862                 writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN, SKDEBUGCANVAS_BEVEL_JOIN);
863                 break;
864             default: SkASSERT(false);
865         }
866     }
867 }
868 
apply_paint_filterquality(const SkPaint & paint,SkJSONWriter & writer)869 static void apply_paint_filterquality(const SkPaint& paint, SkJSONWriter& writer) {
870     SkFilterQuality quality = paint.getFilterQuality();
871     switch (quality) {
872         case kNone_SkFilterQuality:
873             break;
874         case kLow_SkFilterQuality:
875             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
876                                 SKDEBUGCANVAS_FILTERQUALITY_LOW);
877             break;
878         case kMedium_SkFilterQuality:
879             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
880                                 SKDEBUGCANVAS_FILTERQUALITY_MEDIUM);
881             break;
882         case kHigh_SkFilterQuality:
883             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY,
884                                 SKDEBUGCANVAS_FILTERQUALITY_HIGH);
885             break;
886     }
887 }
888 
apply_paint_maskfilter(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)889 static void apply_paint_maskfilter(const SkPaint& paint, SkJSONWriter& writer,
890                                    UrlDataManager& urlDataManager) {
891     SkMaskFilter* maskFilter = paint.getMaskFilter();
892     if (maskFilter != nullptr) {
893         SkMaskFilterBase::BlurRec blurRec;
894         if (as_MFB(maskFilter)->asABlur(&blurRec)) {
895             writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_BLUR);
896             writer.appendFloat(SKDEBUGCANVAS_ATTRIBUTE_SIGMA, blurRec.fSigma);
897             switch (blurRec.fStyle) {
898                 case SkBlurStyle::kNormal_SkBlurStyle:
899                     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_STYLE,
900                                         SKDEBUGCANVAS_BLURSTYLE_NORMAL);
901                     break;
902                 case SkBlurStyle::kSolid_SkBlurStyle:
903                     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_STYLE,
904                                         SKDEBUGCANVAS_BLURSTYLE_SOLID);
905                     break;
906                 case SkBlurStyle::kOuter_SkBlurStyle:
907                     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_STYLE,
908                                         SKDEBUGCANVAS_BLURSTYLE_OUTER);
909                     break;
910                 case SkBlurStyle::kInner_SkBlurStyle:
911                     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_STYLE,
912                                         SKDEBUGCANVAS_BLURSTYLE_INNER);
913                     break;
914                 default:
915                     SkASSERT(false);
916             }
917             writer.endObject(); // blur
918         } else {
919             writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER);
920             SkDrawCommand::flatten(maskFilter, writer, urlDataManager);
921             writer.endObject(); // maskFilter
922         }
923     }
924 }
925 
apply_paint_patheffect(const SkPaint & paint,SkJSONWriter & writer,UrlDataManager & urlDataManager)926 static void apply_paint_patheffect(const SkPaint& paint, SkJSONWriter& writer,
927                                    UrlDataManager& urlDataManager) {
928     SkPathEffect* pathEffect = paint.getPathEffect();
929     if (pathEffect != nullptr) {
930         SkPathEffect::DashInfo dashInfo;
931         SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
932         if (dashType == SkPathEffect::kDash_DashType) {
933             dashInfo.fIntervals = (SkScalar*) sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
934             pathEffect->asADash(&dashInfo);
935             writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_DASHING);
936             writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_INTERVALS, false);
937             for (int32_t i = 0; i < dashInfo.fCount; i++) {
938                 writer.appendFloat(dashInfo.fIntervals[i]);
939             }
940             writer.endArray(); // intervals
941             sk_free(dashInfo.fIntervals);
942             writer.appendFloat(SKDEBUGCANVAS_ATTRIBUTE_PHASE, dashInfo.fPhase);
943             writer.endObject(); // dashing
944         } else {
945             writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT);
946             SkDrawCommand::flatten(pathEffect, writer, urlDataManager);
947             writer.endObject(); // pathEffect
948         }
949     }
950 }
951 
apply_font_typeface(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)952 static void apply_font_typeface(const SkFont& font, SkJSONWriter& writer,
953                                  UrlDataManager& urlDataManager) {
954     SkTypeface* typeface = font.getTypefaceOrDefault();
955     if (typeface != nullptr) {
956         writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE);
957         SkDynamicMemoryWStream buffer;
958         typeface->serialize(&buffer);
959         void* data = sk_malloc_throw(buffer.bytesWritten());
960         buffer.copyTo(data);
961         SkString url = encode_data(data, buffer.bytesWritten(), "application/octet-stream",
962                                    urlDataManager);
963         writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_DATA, url.c_str());
964         sk_free(data);
965         writer.endObject();
966     }
967 }
968 
apply_flattenable(const char * key,SkFlattenable * flattenable,SkJSONWriter & writer,UrlDataManager & urlDataManager)969 static void apply_flattenable(const char* key, SkFlattenable* flattenable, SkJSONWriter& writer,
970                               UrlDataManager& urlDataManager) {
971     if (flattenable != nullptr) {
972         writer.beginObject(key);
973         SkDrawCommand::flatten(flattenable, writer, urlDataManager);
974         writer.endObject();
975     }
976 }
977 
MakeJsonPaint(SkJSONWriter & writer,const SkPaint & paint,UrlDataManager & urlDataManager)978 void SkDrawCommand::MakeJsonPaint(SkJSONWriter& writer, const SkPaint& paint,
979                                   UrlDataManager& urlDataManager) {
980     writer.beginObject();
981     store_scalar(writer, SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
982     store_scalar(writer, SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER, paint.getStrokeMiter(),
983                  SkPaintDefaults_MiterLimit);
984     store_bool(writer, SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
985     store_bool(writer, SKDEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
986 
987     apply_paint_color(paint, writer);
988     apply_paint_style(paint, writer);
989     apply_paint_blend_mode(paint, writer);
990     apply_paint_cap(paint, writer);
991     apply_paint_join(paint, writer);
992     apply_paint_filterquality(paint, writer);
993     apply_paint_patheffect(paint, writer, urlDataManager);
994     apply_paint_maskfilter(paint, writer, urlDataManager);
995     apply_flattenable(SKDEBUGCANVAS_ATTRIBUTE_SHADER, paint.getShader(), writer, urlDataManager);
996     apply_flattenable(SKDEBUGCANVAS_ATTRIBUTE_LOOPER, paint.getLooper(), writer, urlDataManager);
997     apply_flattenable(SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER, paint.getImageFilter(), writer,
998                       urlDataManager);
999     apply_flattenable(SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER, paint.getColorFilter(), writer,
1000                       urlDataManager);
1001     writer.endObject(); // paint
1002 }
1003 
MakeJsonFont(const SkFont & font,SkJSONWriter & writer,UrlDataManager & urlDataManager)1004 static void MakeJsonFont(const SkFont& font, SkJSONWriter& writer, UrlDataManager& urlDataManager) {
1005     writer.beginObject();
1006     store_bool(writer, SKDEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, font.isEmbolden(), false);
1007     store_bool(writer, SKDEBUGCANVAS_ATTRIBUTE_LINEARTEXT, font.isLinearMetrics(), false);
1008     store_bool(writer, SKDEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, font.isSubpixel(), false);
1009     store_bool(writer, SKDEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, font.isEmbeddedBitmaps(), false);
1010     store_bool(writer, SKDEBUGCANVAS_ATTRIBUTE_AUTOHINTING, font.isForceAutoHinting(), false);
1011 
1012     store_scalar(writer, SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE, font.getSize(),
1013                  SkPaintDefaults_TextSize);
1014     store_scalar(writer, SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getScaleX(), SK_Scalar1);
1015     store_scalar(writer, SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getSkewX(), 0.0f);
1016     apply_font_edging(font, writer);
1017     apply_font_hinting(font, writer);
1018     apply_font_typeface(font, writer, urlDataManager);
1019     writer.endObject(); // font
1020 }
1021 
MakeJsonLattice(SkJSONWriter & writer,const SkCanvas::Lattice & lattice)1022 void SkDrawCommand::MakeJsonLattice(SkJSONWriter& writer, const SkCanvas::Lattice& lattice) {
1023     writer.beginObject();
1024     writer.appendS32(SKDEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT, lattice.fXCount);
1025     writer.appendS32(SKDEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT, lattice.fYCount);
1026     if (nullptr != lattice.fBounds) {
1027         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_BOUNDS);
1028         MakeJsonIRect(writer, *lattice.fBounds);
1029     }
1030     writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS);
1031     for (int i = 0; i < lattice.fXCount; i++) {
1032         writer.appendS32(lattice.fXDivs[i]);
1033     }
1034     writer.endArray(); // xdivs
1035     writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS);
1036     for (int i = 0; i < lattice.fYCount; i++) {
1037         writer.appendS32(lattice.fYDivs[i]);
1038     }
1039     writer.endArray(); // ydivs
1040     if (nullptr != lattice.fRectTypes) {
1041         writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS);
1042         int flagCount = 0;
1043         for (int row = 0; row < lattice.fYCount+1; row++) {
1044             writer.beginArray();
1045             for (int column = 0; column < lattice.fXCount+1; column++) {
1046                 writer.appendS32(lattice.fRectTypes[flagCount++]);
1047             }
1048             writer.endArray(); // row
1049         }
1050         writer.endArray();
1051     }
1052     writer.endObject();
1053 }
1054 
SkClearCommand(SkColor color)1055 SkClearCommand::SkClearCommand(SkColor color) : INHERITED(kClear_OpType) {
1056     fColor = color;
1057 }
1058 
execute(SkCanvas * canvas) const1059 void SkClearCommand::execute(SkCanvas* canvas) const {
1060     canvas->clear(fColor);
1061 }
1062 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1063 void SkClearCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1064     INHERITED::toJSON(writer, urlDataManager);
1065     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COLOR);
1066     MakeJsonColor(writer, fColor);
1067 }
1068 
SkClipPathCommand(const SkPath & path,SkClipOp op,bool doAA)1069 SkClipPathCommand::SkClipPathCommand(const SkPath& path, SkClipOp op, bool doAA)
1070     : INHERITED(kClipPath_OpType) {
1071     fPath = path;
1072     fOp = op;
1073     fDoAA = doAA;
1074 }
1075 
execute(SkCanvas * canvas) const1076 void SkClipPathCommand::execute(SkCanvas* canvas) const {
1077     canvas->clipPath(fPath, fOp, fDoAA);
1078 }
1079 
render(SkCanvas * canvas) const1080 bool SkClipPathCommand::render(SkCanvas* canvas) const {
1081     render_path(canvas, fPath);
1082     return true;
1083 }
1084 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1085 void SkClipPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1086     INHERITED::toJSON(writer, urlDataManager);
1087     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PATH); MakeJsonPath(writer, fPath);
1088     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1089     writer.appendBool(SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1090 }
1091 
SkClipRegionCommand(const SkRegion & region,SkClipOp op)1092 SkClipRegionCommand::SkClipRegionCommand(const SkRegion& region, SkClipOp op)
1093     : INHERITED(kClipRegion_OpType) {
1094     fRegion = region;
1095     fOp = op;
1096 }
1097 
execute(SkCanvas * canvas) const1098 void SkClipRegionCommand::execute(SkCanvas* canvas) const {
1099     canvas->clipRegion(fRegion, fOp);
1100 }
1101 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1102 void SkClipRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1103     INHERITED::toJSON(writer, urlDataManager);
1104     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_REGION); MakeJsonRegion(writer, fRegion);
1105     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1106 }
1107 
SkClipRectCommand(const SkRect & rect,SkClipOp op,bool doAA)1108 SkClipRectCommand::SkClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA)
1109     : INHERITED(kClipRect_OpType) {
1110     fRect = rect;
1111     fOp = op;
1112     fDoAA = doAA;
1113 }
1114 
execute(SkCanvas * canvas) const1115 void SkClipRectCommand::execute(SkCanvas* canvas) const {
1116     canvas->clipRect(fRect, fOp, fDoAA);
1117 }
1118 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1119 void SkClipRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1120     INHERITED::toJSON(writer, urlDataManager);
1121     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); MakeJsonRect(writer, fRect);
1122     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1123     writer.appendBool(SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1124 
1125     SkString desc;
1126     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1127 }
1128 
SkClipRRectCommand(const SkRRect & rrect,SkClipOp op,bool doAA)1129 SkClipRRectCommand::SkClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA)
1130     : INHERITED(kClipRRect_OpType) {
1131     fRRect = rrect;
1132     fOp = op;
1133     fDoAA = doAA;
1134 }
1135 
execute(SkCanvas * canvas) const1136 void SkClipRRectCommand::execute(SkCanvas* canvas) const {
1137     canvas->clipRRect(fRRect, fOp, fDoAA);
1138 }
1139 
render(SkCanvas * canvas) const1140 bool SkClipRRectCommand::render(SkCanvas* canvas) const {
1141     render_rrect(canvas, fRRect);
1142     return true;
1143 }
1144 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1145 void SkClipRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1146     INHERITED::toJSON(writer, urlDataManager);
1147     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); make_json_rrect(writer, fRRect);
1148     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_REGIONOP, regionop_name(fOp));
1149     writer.appendBool(SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA);
1150 }
1151 
SkConcatCommand(const SkMatrix & matrix)1152 SkConcatCommand::SkConcatCommand(const SkMatrix& matrix)
1153     : INHERITED(kConcat_OpType) {
1154     fMatrix = matrix;
1155 }
1156 
execute(SkCanvas * canvas) const1157 void SkConcatCommand::execute(SkCanvas* canvas) const {
1158     canvas->concat(fMatrix);
1159 }
1160 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1161 void SkConcatCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1162     INHERITED::toJSON(writer, urlDataManager);
1163     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_MATRIX); MakeJsonMatrix(writer, fMatrix);
1164 }
1165 
1166 ////
1167 
SkDrawAnnotationCommand(const SkRect & rect,const char key[],sk_sp<SkData> value)1168 SkDrawAnnotationCommand::SkDrawAnnotationCommand(const SkRect& rect, const char key[],
1169                                                  sk_sp<SkData> value)
1170     : INHERITED(kDrawAnnotation_OpType)
1171     , fRect(rect)
1172     , fKey(key)
1173     , fValue(std::move(value))
1174 {
1175 }
1176 
execute(SkCanvas * canvas) const1177 void SkDrawAnnotationCommand::execute(SkCanvas* canvas) const {
1178     canvas->drawAnnotation(fRect, fKey.c_str(), fValue);
1179 }
1180 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1181 void SkDrawAnnotationCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1182     INHERITED::toJSON(writer, urlDataManager);
1183 
1184     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); MakeJsonRect(writer, fRect);
1185     writer.appendString("key", fKey.c_str());
1186     if (fValue.get()) {
1187         // TODO: dump out the "value"
1188     }
1189 
1190     SkString desc;
1191     str_append(&desc, fRect)->appendf(" %s", fKey.c_str());
1192     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC, desc.c_str());
1193 }
1194 
1195 ////
1196 
SkDrawBitmapCommand(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)1197 SkDrawBitmapCommand::SkDrawBitmapCommand(const SkBitmap& bitmap, SkScalar left, SkScalar top,
1198                                          const SkPaint* paint)
1199     : INHERITED(kDrawBitmap_OpType)
1200     , fBitmap(bitmap)
1201     , fLeft(left)
1202     , fTop(top)
1203     , fPaint(paint) {}
1204 
execute(SkCanvas * canvas) const1205 void SkDrawBitmapCommand::execute(SkCanvas* canvas) const {
1206     canvas->drawBitmap(fBitmap, fLeft, fTop, fPaint.getMaybeNull());
1207 }
1208 
render(SkCanvas * canvas) const1209 bool SkDrawBitmapCommand::render(SkCanvas* canvas) const {
1210     render_bitmap(canvas, fBitmap);
1211     return true;
1212 }
1213 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1214 void SkDrawBitmapCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1215     INHERITED::toJSON(writer, urlDataManager);
1216     writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_BITMAP);
1217     flatten(fBitmap, writer, urlDataManager);
1218     writer.endObject();
1219     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); MakeJsonPoint(writer, fLeft, fTop);
1220     if (fPaint.isValid()) {
1221         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
1222         MakeJsonPaint(writer, *fPaint, urlDataManager);
1223     }
1224 }
1225 
SkDrawBitmapLatticeCommand(const SkBitmap & bitmap,const SkCanvas::Lattice & lattice,const SkRect & dst,const SkPaint * paint)1226 SkDrawBitmapLatticeCommand::SkDrawBitmapLatticeCommand(const SkBitmap& bitmap,
1227                                                        const SkCanvas::Lattice& lattice,
1228                                                        const SkRect& dst, const SkPaint* paint)
1229     : INHERITED(kDrawBitmapLattice_OpType)
1230     , fBitmap(bitmap)
1231     , fLattice(lattice)
1232     , fDst(dst)
1233     , fPaint(paint) {}
1234 
execute(SkCanvas * canvas) const1235 void SkDrawBitmapLatticeCommand::execute(SkCanvas* canvas) const {
1236     canvas->drawBitmapLattice(fBitmap, fLattice, fDst, fPaint.getMaybeNull());
1237 }
1238 
render(SkCanvas * canvas) const1239 bool SkDrawBitmapLatticeCommand::render(SkCanvas* canvas) const {
1240     SkAutoCanvasRestore acr(canvas, true);
1241     canvas->clear(0xFFFFFFFF);
1242 
1243     xlate_and_scale_to_bounds(canvas, fDst);
1244 
1245     this->execute(canvas);
1246     return true;
1247 }
1248 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1249 void SkDrawBitmapLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1250     INHERITED::toJSON(writer, urlDataManager);
1251     writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_BITMAP);
1252     flatten(fBitmap, writer, urlDataManager);
1253     writer.endObject(); // bitmap
1254 
1255     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_LATTICE); MakeJsonLattice(writer, fLattice);
1256     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_DST); MakeJsonRect(writer, fDst);
1257     if (fPaint.isValid()) {
1258         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
1259         MakeJsonPaint(writer, *fPaint, urlDataManager);
1260     }
1261 
1262     SkString desc;
1263     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1264 }
1265 
SkDrawBitmapNineCommand(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1266 SkDrawBitmapNineCommand::SkDrawBitmapNineCommand(const SkBitmap& bitmap, const SkIRect& center,
1267                                                  const SkRect& dst, const SkPaint* paint)
1268     : INHERITED(kDrawBitmapNine_OpType)
1269     , fBitmap(bitmap)
1270     , fCenter(center)
1271     , fDst(dst)
1272     , fPaint(paint) {}
1273 
execute(SkCanvas * canvas) const1274 void SkDrawBitmapNineCommand::execute(SkCanvas* canvas) const {
1275     canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaint.getMaybeNull());
1276 }
1277 
render(SkCanvas * canvas) const1278 bool SkDrawBitmapNineCommand::render(SkCanvas* canvas) const {
1279     SkRect tmp = SkRect::Make(fCenter);
1280     render_bitmap(canvas, fBitmap, &tmp);
1281     return true;
1282 }
1283 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1284 void SkDrawBitmapNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1285     INHERITED::toJSON(writer, urlDataManager);
1286     writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_BITMAP);
1287     flatten(fBitmap, writer, urlDataManager);
1288     writer.endObject(); // bitmap
1289 
1290     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_CENTER); MakeJsonIRect(writer, fCenter);
1291     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_DST); MakeJsonRect(writer, fDst);
1292     if (fPaint.isValid()) {
1293         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
1294         MakeJsonPaint(writer, *fPaint, urlDataManager);
1295     }
1296 }
1297 
SkDrawBitmapRectCommand(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1298 SkDrawBitmapRectCommand::SkDrawBitmapRectCommand(const SkBitmap& bitmap, const SkRect* src,
1299                                                  const SkRect& dst, const SkPaint* paint,
1300                                                  SkCanvas::SrcRectConstraint constraint)
1301     : INHERITED(kDrawBitmapRect_OpType)
1302     , fBitmap(bitmap)
1303     , fSrc(src)
1304     , fDst(dst)
1305     , fPaint(paint)
1306     , fConstraint(constraint) {}
1307 
execute(SkCanvas * canvas) const1308 void SkDrawBitmapRectCommand::execute(SkCanvas* canvas) const {
1309     canvas->legacy_drawBitmapRect(fBitmap, fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(),
1310                                   fConstraint);
1311 }
1312 
render(SkCanvas * canvas) const1313 bool SkDrawBitmapRectCommand::render(SkCanvas* canvas) const {
1314     render_bitmap(canvas, fBitmap, fSrc.getMaybeNull());
1315     return true;
1316 }
1317 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1318 void SkDrawBitmapRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1319     INHERITED::toJSON(writer, urlDataManager);
1320     writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_BITMAP);
1321     flatten(fBitmap, writer, urlDataManager);
1322     writer.endObject(); // bitmap
1323 
1324     if (fSrc.isValid()) {
1325         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_SRC); MakeJsonRect(writer, *fSrc);
1326     }
1327     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_DST); MakeJsonRect(writer, fDst);
1328     if (fPaint.isValid()) {
1329         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
1330         MakeJsonPaint(writer, *fPaint, urlDataManager);
1331     }
1332     if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1333         writer.appendBool(SKDEBUGCANVAS_ATTRIBUTE_STRICT, true);
1334     }
1335 
1336     SkString desc;
1337     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1338 }
1339 
SkDrawImageCommand(const SkImage * image,SkScalar left,SkScalar top,const SkPaint * paint)1340 SkDrawImageCommand::SkDrawImageCommand(const SkImage* image, SkScalar left, SkScalar top,
1341                                        const SkPaint* paint)
1342     : INHERITED(kDrawImage_OpType)
1343     , fImage(SkRef(image))
1344     , fLeft(left)
1345     , fTop(top)
1346     , fPaint(paint) {}
1347 
execute(SkCanvas * canvas) const1348 void SkDrawImageCommand::execute(SkCanvas* canvas) const {
1349     canvas->drawImage(fImage.get(), fLeft, fTop, fPaint.getMaybeNull());
1350 }
1351 
render(SkCanvas * canvas) const1352 bool SkDrawImageCommand::render(SkCanvas* canvas) const {
1353     SkAutoCanvasRestore acr(canvas, true);
1354     canvas->clear(0xFFFFFFFF);
1355 
1356     xlate_and_scale_to_bounds(canvas, SkRect::MakeXYWH(fLeft, fTop,
1357                                                        SkIntToScalar(fImage->width()),
1358                                                        SkIntToScalar(fImage->height())));
1359     this->execute(canvas);
1360     return true;
1361 }
1362 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1363 void SkDrawImageCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1364     INHERITED::toJSON(writer, urlDataManager);
1365     writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_IMAGE);
1366     flatten(*fImage, writer, urlDataManager);
1367     writer.endObject(); // image
1368 
1369     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); MakeJsonPoint(writer, fLeft, fTop);
1370     if (fPaint.isValid()) {
1371         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
1372         MakeJsonPaint(writer, *fPaint, urlDataManager);
1373     }
1374 
1375     writer.appendU32(SKDEBUGCANVAS_ATTRIBUTE_UNIQUE_ID, fImage->uniqueID());
1376     writer.appendS32(SKDEBUGCANVAS_ATTRIBUTE_WIDTH, fImage->width());
1377     writer.appendS32(SKDEBUGCANVAS_ATTRIBUTE_HEIGHT, fImage->height());
1378     switch (fImage->alphaType()) {
1379         case kOpaque_SkAlphaType:
1380             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_ALPHA, SKDEBUGCANVAS_ALPHATYPE_OPAQUE);
1381             break;
1382         case kPremul_SkAlphaType:
1383             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_ALPHA, SKDEBUGCANVAS_ALPHATYPE_PREMUL);
1384             break;
1385         case kUnpremul_SkAlphaType:
1386             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_ALPHA, SKDEBUGCANVAS_ALPHATYPE_UNPREMUL);
1387             break;
1388         default:
1389             writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_ALPHA, SKDEBUGCANVAS_ALPHATYPE_UNKNOWN);
1390             break;
1391     }
1392 }
1393 
SkDrawImageLatticeCommand(const SkImage * image,const SkCanvas::Lattice & lattice,const SkRect & dst,const SkPaint * paint)1394 SkDrawImageLatticeCommand::SkDrawImageLatticeCommand(const SkImage* image,
1395                                                      const SkCanvas::Lattice& lattice,
1396                                                      const SkRect& dst, const SkPaint* paint)
1397     : INHERITED(kDrawImageLattice_OpType)
1398     , fImage(SkRef(image))
1399     , fLattice(lattice)
1400     , fDst(dst)
1401     , fPaint(paint) {}
1402 
execute(SkCanvas * canvas) const1403 void SkDrawImageLatticeCommand::execute(SkCanvas* canvas) const {
1404     canvas->drawImageLattice(fImage.get(), fLattice, fDst, fPaint.getMaybeNull());
1405 }
1406 
render(SkCanvas * canvas) const1407 bool SkDrawImageLatticeCommand::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 SkDrawImageLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1418     INHERITED::toJSON(writer, urlDataManager);
1419     writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_IMAGE);
1420     flatten(*fImage, writer, urlDataManager);
1421     writer.endObject(); // image
1422 
1423     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_LATTICE); MakeJsonLattice(writer, fLattice);
1424     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_DST); MakeJsonRect(writer, fDst);
1425     if (fPaint.isValid()) {
1426         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
1427         MakeJsonPaint(writer, *fPaint, urlDataManager);
1428     }
1429 
1430     SkString desc;
1431     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1432 }
1433 
SkDrawImageRectCommand(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1434 SkDrawImageRectCommand::SkDrawImageRectCommand(const SkImage* image, const SkRect* src,
1435                                                const SkRect& dst, const SkPaint* paint,
1436                                                SkCanvas::SrcRectConstraint constraint)
1437     : INHERITED(kDrawImageRect_OpType)
1438     , fImage(SkRef(image))
1439     , fSrc(src)
1440     , fDst(dst)
1441     , fPaint(paint)
1442     , fConstraint(constraint) {}
1443 
execute(SkCanvas * canvas) const1444 void SkDrawImageRectCommand::execute(SkCanvas* canvas) const {
1445     canvas->legacy_drawImageRect(fImage.get(), fSrc.getMaybeNull(), fDst,
1446                                  fPaint.getMaybeNull(), fConstraint);
1447 }
1448 
render(SkCanvas * canvas) const1449 bool SkDrawImageRectCommand::render(SkCanvas* canvas) const {
1450     SkAutoCanvasRestore acr(canvas, true);
1451     canvas->clear(0xFFFFFFFF);
1452 
1453     xlate_and_scale_to_bounds(canvas, fDst);
1454 
1455     this->execute(canvas);
1456     return true;
1457 }
1458 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1459 void SkDrawImageRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1460     INHERITED::toJSON(writer, urlDataManager);
1461     writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_IMAGE);
1462     flatten(*fImage, writer, urlDataManager);
1463     writer.endObject(); // image
1464 
1465     if (fSrc.isValid()) {
1466         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_SRC); MakeJsonRect(writer, *fSrc);
1467     }
1468     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_DST); MakeJsonRect(writer, fDst);
1469     if (fPaint.isValid()) {
1470         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
1471         MakeJsonPaint(writer, *fPaint, urlDataManager);
1472     }
1473     if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1474         writer.appendBool(SKDEBUGCANVAS_ATTRIBUTE_STRICT, true);
1475     }
1476 
1477     SkString desc;
1478     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fDst)->c_str());
1479 }
1480 
SkDrawImageSetCommand(const SkCanvas::ImageSetEntry set[],int count,SkFilterQuality filterQuality,SkBlendMode mode)1481 SkDrawImageSetCommand::SkDrawImageSetCommand(const SkCanvas::ImageSetEntry set[], int count,
1482                                              SkFilterQuality filterQuality, SkBlendMode mode)
1483         : INHERITED(kDrawImageSet_OpType)
1484         , fSet(count)
1485         , fCount(count)
1486         , fFilterQuality(filterQuality)
1487         , fMode(mode) {
1488     std::copy_n(set, count, fSet.get());
1489 }
1490 
execute(SkCanvas * canvas) const1491 void SkDrawImageSetCommand::execute(SkCanvas* canvas) const {
1492     canvas->experimental_DrawImageSetV1(fSet.get(), fCount, fFilterQuality, fMode);
1493 }
1494 
SkDrawImageNineCommand(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1495 SkDrawImageNineCommand::SkDrawImageNineCommand(const SkImage* image, const SkIRect& center,
1496                                                const SkRect& dst, const SkPaint* paint)
1497     : INHERITED(kDrawImageNine_OpType)
1498     , fImage(SkRef(image))
1499     , fCenter(center)
1500     , fDst(dst)
1501     , fPaint(paint) {}
1502 
execute(SkCanvas * canvas) const1503 void SkDrawImageNineCommand::execute(SkCanvas* canvas) const {
1504     canvas->drawImageNine(fImage.get(), fCenter, fDst, fPaint.getMaybeNull());
1505 }
1506 
render(SkCanvas * canvas) const1507 bool SkDrawImageNineCommand::render(SkCanvas* canvas) const {
1508     SkAutoCanvasRestore acr(canvas, true);
1509     canvas->clear(0xFFFFFFFF);
1510 
1511     xlate_and_scale_to_bounds(canvas, fDst);
1512 
1513     this->execute(canvas);
1514     return true;
1515 }
1516 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1517 void SkDrawImageNineCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1518     INHERITED::toJSON(writer, urlDataManager);
1519     writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_IMAGE);
1520     flatten(*fImage, writer, urlDataManager);
1521     writer.endObject(); // image
1522 
1523     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_CENTER); MakeJsonIRect(writer, fCenter);
1524     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_DST); MakeJsonRect(writer, fDst);
1525     if (fPaint.isValid()) {
1526         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
1527         MakeJsonPaint(writer, *fPaint, urlDataManager);
1528     }
1529 }
1530 
SkDrawOvalCommand(const SkRect & oval,const SkPaint & paint)1531 SkDrawOvalCommand::SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint)
1532     : INHERITED(kDrawOval_OpType) {
1533     fOval = oval;
1534     fPaint = paint;
1535 }
1536 
execute(SkCanvas * canvas) const1537 void SkDrawOvalCommand::execute(SkCanvas* canvas) const {
1538     canvas->drawOval(fOval, fPaint);
1539 }
1540 
render(SkCanvas * canvas) const1541 bool SkDrawOvalCommand::render(SkCanvas* canvas) const {
1542     canvas->clear(0xFFFFFFFF);
1543     canvas->save();
1544 
1545     xlate_and_scale_to_bounds(canvas, fOval);
1546 
1547     SkPaint p;
1548     p.setColor(SK_ColorBLACK);
1549     p.setStyle(SkPaint::kStroke_Style);
1550 
1551     canvas->drawOval(fOval, p);
1552     canvas->restore();
1553 
1554     return true;
1555 }
1556 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1557 void SkDrawOvalCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1558     INHERITED::toJSON(writer, urlDataManager);
1559     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); MakeJsonRect(writer, fOval);
1560     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1561 }
1562 
SkDrawArcCommand(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)1563 SkDrawArcCommand::SkDrawArcCommand(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
1564                                    bool useCenter, const SkPaint& paint)
1565         : INHERITED(kDrawArc_OpType) {
1566     fOval = oval;
1567     fStartAngle = startAngle;
1568     fSweepAngle = sweepAngle;
1569     fUseCenter = useCenter;
1570     fPaint = paint;
1571 }
1572 
execute(SkCanvas * canvas) const1573 void SkDrawArcCommand::execute(SkCanvas* canvas) const {
1574     canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, fPaint);
1575 }
1576 
render(SkCanvas * canvas) const1577 bool SkDrawArcCommand::render(SkCanvas* canvas) const {
1578     canvas->clear(0xFFFFFFFF);
1579     canvas->save();
1580 
1581     xlate_and_scale_to_bounds(canvas, fOval);
1582 
1583     SkPaint p;
1584     p.setColor(SK_ColorBLACK);
1585     p.setStyle(SkPaint::kStroke_Style);
1586 
1587     canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, p);
1588     canvas->restore();
1589 
1590     return true;
1591 }
1592 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1593 void SkDrawArcCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1594     INHERITED::toJSON(writer, urlDataManager);
1595     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); MakeJsonRect(writer, fOval);
1596     writer.appendFloat(SKDEBUGCANVAS_ATTRIBUTE_STARTANGLE, fStartAngle);
1597     writer.appendFloat(SKDEBUGCANVAS_ATTRIBUTE_SWEEPANGLE, fSweepAngle);
1598     writer.appendBool(SKDEBUGCANVAS_ATTRIBUTE_USECENTER, fUseCenter);
1599     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1600 }
1601 
SkDrawPaintCommand(const SkPaint & paint)1602 SkDrawPaintCommand::SkDrawPaintCommand(const SkPaint& paint)
1603     : INHERITED(kDrawPaint_OpType) {
1604     fPaint = paint;
1605 }
1606 
execute(SkCanvas * canvas) const1607 void SkDrawPaintCommand::execute(SkCanvas* canvas) const {
1608     canvas->drawPaint(fPaint);
1609 }
1610 
render(SkCanvas * canvas) const1611 bool SkDrawPaintCommand::render(SkCanvas* canvas) const {
1612     canvas->clear(0xFFFFFFFF);
1613     canvas->drawPaint(fPaint);
1614     return true;
1615 }
1616 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1617 void SkDrawPaintCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1618     INHERITED::toJSON(writer, urlDataManager);
1619     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1620 }
1621 
SkDrawPathCommand(const SkPath & path,const SkPaint & paint)1622 SkDrawPathCommand::SkDrawPathCommand(const SkPath& path, const SkPaint& paint)
1623     : INHERITED(kDrawPath_OpType) {
1624     fPath = path;
1625     fPaint = paint;
1626 }
1627 
execute(SkCanvas * canvas) const1628 void SkDrawPathCommand::execute(SkCanvas* canvas) const {
1629     canvas->drawPath(fPath, fPaint);
1630 }
1631 
render(SkCanvas * canvas) const1632 bool SkDrawPathCommand::render(SkCanvas* canvas) const {
1633     render_path(canvas, fPath);
1634     return true;
1635 }
1636 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1637 void SkDrawPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1638     INHERITED::toJSON(writer, urlDataManager);
1639     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PATH); MakeJsonPath(writer, fPath);
1640     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1641 }
1642 
SkDrawBehindCommand(const SkPaint & paint)1643 SkDrawBehindCommand::SkDrawBehindCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) {
1644     fPaint = paint;
1645 }
1646 
execute(SkCanvas * canvas) const1647 void SkDrawBehindCommand::execute(SkCanvas* canvas) const {
1648     SkCanvasPriv::DrawBehind(canvas, fPaint);
1649 }
1650 
render(SkCanvas * canvas) const1651 bool SkDrawBehindCommand::render(SkCanvas* canvas) const {
1652     canvas->clear(0xFFFFFFFF);
1653     SkCanvasPriv::DrawBehind(canvas, fPaint);
1654     return true;
1655 }
1656 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1657 void SkDrawBehindCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1658     INHERITED::toJSON(writer, urlDataManager);
1659     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
1660     MakeJsonPaint(writer, fPaint, urlDataManager);
1661 }
1662 
1663 
SkDrawRegionCommand(const SkRegion & region,const SkPaint & paint)1664 SkDrawRegionCommand::SkDrawRegionCommand(const SkRegion& region, const SkPaint& paint)
1665     : INHERITED(kDrawRegion_OpType) {
1666     fRegion = region;
1667     fPaint = paint;
1668 }
1669 
execute(SkCanvas * canvas) const1670 void SkDrawRegionCommand::execute(SkCanvas* canvas) const {
1671     canvas->drawRegion(fRegion, fPaint);
1672 }
1673 
render(SkCanvas * canvas) const1674 bool SkDrawRegionCommand::render(SkCanvas* canvas) const {
1675     render_region(canvas, fRegion);
1676     return true;
1677 }
1678 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1679 void SkDrawRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1680     INHERITED::toJSON(writer, urlDataManager);
1681     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_REGION); MakeJsonRegion(writer, fRegion);
1682     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1683 }
1684 
SkBeginDrawPictureCommand(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)1685 SkBeginDrawPictureCommand::SkBeginDrawPictureCommand(const SkPicture* picture,
1686                                                      const SkMatrix* matrix,
1687                                                      const SkPaint* paint)
1688     : INHERITED(kBeginDrawPicture_OpType)
1689     , fPicture(SkRef(picture))
1690     , fMatrix(matrix)
1691     , fPaint(paint) {}
1692 
execute(SkCanvas * canvas) const1693 void SkBeginDrawPictureCommand::execute(SkCanvas* canvas) const {
1694     if (fPaint.isValid()) {
1695         SkRect bounds = fPicture->cullRect();
1696         if (fMatrix.isValid()) {
1697             fMatrix->mapRect(&bounds);
1698         }
1699         canvas->saveLayer(&bounds, fPaint.get());
1700     }
1701 
1702     if (fMatrix.isValid()) {
1703         if (!fPaint.isValid()) {
1704             canvas->save();
1705         }
1706         canvas->concat(*fMatrix);
1707     }
1708 }
1709 
render(SkCanvas * canvas) const1710 bool SkBeginDrawPictureCommand::render(SkCanvas* canvas) const {
1711     canvas->clear(0xFFFFFFFF);
1712     canvas->save();
1713 
1714     xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
1715 
1716     canvas->drawPicture(fPicture.get());
1717 
1718     canvas->restore();
1719 
1720     return true;
1721 }
1722 
SkEndDrawPictureCommand(bool restore)1723 SkEndDrawPictureCommand::SkEndDrawPictureCommand(bool restore)
1724     : INHERITED(kEndDrawPicture_OpType) , fRestore(restore) { }
1725 
execute(SkCanvas * canvas) const1726 void SkEndDrawPictureCommand::execute(SkCanvas* canvas) const {
1727     if (fRestore) {
1728         canvas->restore();
1729     }
1730 }
1731 
SkDrawPointsCommand(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1732 SkDrawPointsCommand::SkDrawPointsCommand(SkCanvas::PointMode mode, size_t count,
1733                                          const SkPoint pts[], const SkPaint& paint)
1734     : INHERITED(kDrawPoints_OpType)
1735     , fMode(mode)
1736     , fPts(pts, count)
1737     , fPaint(paint) {}
1738 
execute(SkCanvas * canvas) const1739 void SkDrawPointsCommand::execute(SkCanvas* canvas) const {
1740     canvas->drawPoints(fMode, fPts.count(), fPts.begin(), fPaint);
1741 }
1742 
render(SkCanvas * canvas) const1743 bool SkDrawPointsCommand::render(SkCanvas* canvas) const {
1744     canvas->clear(0xFFFFFFFF);
1745     canvas->save();
1746 
1747     SkRect bounds;
1748 
1749     bounds.setEmpty();
1750     for (int i = 0; i < fPts.count(); ++i) {
1751         SkRectPriv::GrowToInclude(&bounds, fPts[i]);
1752     }
1753 
1754     xlate_and_scale_to_bounds(canvas, bounds);
1755 
1756     SkPaint p;
1757     p.setColor(SK_ColorBLACK);
1758     p.setStyle(SkPaint::kStroke_Style);
1759 
1760     canvas->drawPoints(fMode, fPts.count(), fPts.begin(), p);
1761     canvas->restore();
1762 
1763     return true;
1764 }
1765 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1766 void SkDrawPointsCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1767     INHERITED::toJSON(writer, urlDataManager);
1768     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_MODE, pointmode_name(fMode));
1769     writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_POINTS);
1770     for (int i = 0; i < fPts.count(); i++) {
1771         MakeJsonPoint(writer, fPts[i]);
1772     }
1773     writer.endArray(); // points
1774     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1775 }
1776 
SkDrawTextBlobCommand(sk_sp<SkTextBlob> blob,SkScalar x,SkScalar y,const SkPaint & paint)1777 SkDrawTextBlobCommand::SkDrawTextBlobCommand(sk_sp<SkTextBlob> blob, SkScalar x, SkScalar y,
1778                                              const SkPaint& paint)
1779     : INHERITED(kDrawTextBlob_OpType)
1780     , fBlob(std::move(blob))
1781     , fXPos(x)
1782     , fYPos(y)
1783     , fPaint(paint) {}
1784 
execute(SkCanvas * canvas) const1785 void SkDrawTextBlobCommand::execute(SkCanvas* canvas) const {
1786     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1787 }
1788 
render(SkCanvas * canvas) const1789 bool SkDrawTextBlobCommand::render(SkCanvas* canvas) const {
1790     canvas->clear(SK_ColorWHITE);
1791     canvas->save();
1792 
1793     SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
1794     xlate_and_scale_to_bounds(canvas, bounds);
1795 
1796     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
1797 
1798     canvas->restore();
1799 
1800     return true;
1801 }
1802 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1803 void SkDrawTextBlobCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1804     INHERITED::toJSON(writer, urlDataManager);
1805     writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_RUNS);
1806     SkTextBlobRunIterator iter(fBlob.get());
1807     while (!iter.done()) {
1808         writer.beginObject(); // run
1809         writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_GLYPHS);
1810         for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1811             writer.appendU32(iter.glyphs()[i]);
1812         }
1813         writer.endArray(); // glyphs
1814         if (iter.positioning() != SkTextBlobRunIterator::kDefault_Positioning) {
1815             writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_POSITIONS);
1816             const SkScalar* iterPositions = iter.pos();
1817             for (uint32_t i = 0; i < iter.glyphCount(); i++) {
1818                 switch (iter.positioning()) {
1819                 case SkTextBlobRunIterator::kFull_Positioning:
1820                     MakeJsonPoint(writer, iterPositions[i * 2], iterPositions[i * 2 + 1]);
1821                     break;
1822                 case SkTextBlobRunIterator::kHorizontal_Positioning:
1823                     writer.appendFloat(iterPositions[i]);
1824                     break;
1825                 case SkTextBlobRunIterator::kDefault_Positioning:
1826                     break;
1827                 case SkTextBlobRunIterator::kRSXform_Positioning:
1828                     // TODO_RSXFORM_BLOB
1829                     break;
1830                 }
1831             }
1832             writer.endArray(); // positions
1833         }
1834         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_FONT);
1835             MakeJsonFont(iter.font(), writer, urlDataManager);
1836         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS);
1837             MakeJsonPoint(writer, iter.offset());
1838 
1839         writer.endObject(); // run
1840         iter.next();
1841     }
1842     writer.endArray(); // runs
1843     writer.appendFloat(SKDEBUGCANVAS_ATTRIBUTE_X, fXPos);
1844     writer.appendFloat(SKDEBUGCANVAS_ATTRIBUTE_Y, fYPos);
1845     SkRect bounds = fBlob->bounds();
1846     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); MakeJsonRect(writer, bounds);
1847     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1848 
1849     SkString desc;
1850     // make the bounds local by applying the x,y
1851     bounds.offset(fXPos, fYPos);
1852     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, bounds)->c_str());
1853 }
1854 
SkDrawPatchCommand(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)1855 SkDrawPatchCommand::SkDrawPatchCommand(const SkPoint cubics[12], const SkColor colors[4],
1856                                        const SkPoint texCoords[4], SkBlendMode bmode,
1857                                        const SkPaint& paint)
1858     : INHERITED(kDrawPatch_OpType)
1859     , fBlendMode(bmode)
1860 {
1861     memcpy(fCubics, cubics, sizeof(fCubics));
1862     if (colors != nullptr) {
1863         memcpy(fColors, colors, sizeof(fColors));
1864         fColorsPtr = fColors;
1865     } else {
1866         fColorsPtr = nullptr;
1867     }
1868     if (texCoords != nullptr) {
1869         memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
1870         fTexCoordsPtr = fTexCoords;
1871     } else {
1872         fTexCoordsPtr = nullptr;
1873     }
1874     fPaint = paint;
1875 }
1876 
execute(SkCanvas * canvas) const1877 void SkDrawPatchCommand::execute(SkCanvas* canvas) const {
1878     canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fBlendMode, fPaint);
1879 }
1880 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1881 void SkDrawPatchCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1882     INHERITED::toJSON(writer, urlDataManager);
1883     writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_CUBICS);
1884     for (int i = 0; i < 12; i++) {
1885         MakeJsonPoint(writer, fCubics[i]);
1886     }
1887     writer.endArray(); // cubics
1888     if (fColorsPtr != nullptr) {
1889         writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_COLORS);
1890         for (int i = 0; i < 4; i++) {
1891             MakeJsonColor(writer, fColorsPtr[i]);
1892         }
1893         writer.endArray(); // colors
1894     }
1895     if (fTexCoordsPtr != nullptr) {
1896         writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS);
1897         for (int i = 0; i < 4; i++) {
1898             MakeJsonPoint(writer, fTexCoords[i]);
1899         }
1900         writer.endArray(); // texCoords
1901     }
1902     // fBlendMode
1903 }
1904 
SkDrawRectCommand(const SkRect & rect,const SkPaint & paint)1905 SkDrawRectCommand::SkDrawRectCommand(const SkRect& rect, const SkPaint& paint)
1906     : INHERITED(kDrawRect_OpType) {
1907     fRect = rect;
1908     fPaint = paint;
1909 }
1910 
execute(SkCanvas * canvas) const1911 void SkDrawRectCommand::execute(SkCanvas* canvas) const {
1912     canvas->drawRect(fRect, fPaint);
1913 }
1914 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1915 void SkDrawRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1916     INHERITED::toJSON(writer, urlDataManager);
1917     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); MakeJsonRect(writer, fRect);
1918     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1919 
1920     SkString desc;
1921     writer.appendString(SKDEBUGCANVAS_ATTRIBUTE_SHORTDESC, str_append(&desc, fRect)->c_str());
1922 }
1923 
SkDrawEdgeAARectCommand(const SkRect & rect,SkCanvas::QuadAAFlags aa,SkColor color,SkBlendMode mode)1924 SkDrawEdgeAARectCommand::SkDrawEdgeAARectCommand(const SkRect& rect, SkCanvas::QuadAAFlags aa,
1925                                                  SkColor color, SkBlendMode mode)
1926     : INHERITED(kDrawEdgeAARect_OpType) {
1927     fRect = rect;
1928     fAA = aa;
1929     fColor = color;
1930     fMode = mode;
1931 }
1932 
execute(SkCanvas * canvas) const1933 void SkDrawEdgeAARectCommand::execute(SkCanvas* canvas) const {
1934     canvas->experimental_DrawEdgeAARectV1(fRect, fAA, fColor, fMode);
1935 }
1936 
SkDrawRRectCommand(const SkRRect & rrect,const SkPaint & paint)1937 SkDrawRRectCommand::SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
1938     : INHERITED(kDrawRRect_OpType) {
1939     fRRect = rrect;
1940     fPaint = paint;
1941 }
1942 
execute(SkCanvas * canvas) const1943 void SkDrawRRectCommand::execute(SkCanvas* canvas) const {
1944     canvas->drawRRect(fRRect, fPaint);
1945 }
1946 
render(SkCanvas * canvas) const1947 bool SkDrawRRectCommand::render(SkCanvas* canvas) const {
1948     render_rrect(canvas, fRRect);
1949     return true;
1950 }
1951 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1952 void SkDrawRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1953     INHERITED::toJSON(writer, urlDataManager);
1954     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_COORDS); make_json_rrect(writer, fRRect);
1955     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1956 }
1957 
SkDrawDRRectCommand(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1958 SkDrawDRRectCommand::SkDrawDRRectCommand(const SkRRect& outer,
1959                                          const SkRRect& inner,
1960                                          const SkPaint& paint)
1961     : INHERITED(kDrawDRRect_OpType) {
1962     fOuter = outer;
1963     fInner = inner;
1964     fPaint = paint;
1965 }
1966 
execute(SkCanvas * canvas) const1967 void SkDrawDRRectCommand::execute(SkCanvas* canvas) const {
1968     canvas->drawDRRect(fOuter, fInner, fPaint);
1969 }
1970 
render(SkCanvas * canvas) const1971 bool SkDrawDRRectCommand::render(SkCanvas* canvas) const {
1972     render_drrect(canvas, fOuter, fInner);
1973     return true;
1974 }
1975 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1976 void SkDrawDRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1977     INHERITED::toJSON(writer, urlDataManager);
1978     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_OUTER); make_json_rrect(writer, fOuter);
1979     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_INNER); make_json_rrect(writer, fInner);
1980     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager);
1981 }
1982 
SkDrawShadowCommand(const SkPath & path,const SkDrawShadowRec & rec)1983 SkDrawShadowCommand::SkDrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec)
1984         : INHERITED(kDrawShadow_OpType) {
1985     fPath = path;
1986     fShadowRec = rec;
1987 }
1988 
execute(SkCanvas * canvas) const1989 void SkDrawShadowCommand::execute(SkCanvas* canvas) const {
1990     canvas->private_draw_shadow_rec(fPath, fShadowRec);
1991 }
1992 
render(SkCanvas * canvas) const1993 bool SkDrawShadowCommand::render(SkCanvas* canvas) const {
1994     render_shadow(canvas, fPath, fShadowRec);
1995     return true;
1996 }
1997 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const1998 void SkDrawShadowCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
1999     INHERITED::toJSON(writer, urlDataManager);
2000 
2001     bool geometricOnly = SkToBool(fShadowRec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
2002     bool transparentOccluder =
2003             SkToBool(fShadowRec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
2004 
2005     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PATH); MakeJsonPath(writer, fPath);
2006     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_ZPLANE);
2007         MakeJsonPoint3(writer, fShadowRec.fZPlaneParams);
2008     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION);
2009         MakeJsonPoint3(writer, fShadowRec.fLightPos);
2010     writer.appendFloat(SKDEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS, fShadowRec.fLightRadius);
2011     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR);
2012         MakeJsonColor(writer, fShadowRec.fAmbientColor);
2013     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_SPOTCOLOR);
2014         MakeJsonColor(writer, fShadowRec.fSpotColor);
2015     store_bool(writer, SKDEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC, transparentOccluder, false);
2016     store_bool(writer, SKDEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY, geometricOnly, false);
2017 }
2018 
2019 ///////////////////////////////////////////////////////////////////////////////////////////////////
2020 
SkDrawDrawableCommand(SkDrawable * drawable,const SkMatrix * matrix)2021 SkDrawDrawableCommand::SkDrawDrawableCommand(SkDrawable* drawable, const SkMatrix* matrix)
2022     : INHERITED(kDrawDrawable_OpType)
2023     , fDrawable(SkRef(drawable))
2024     , fMatrix(matrix) {}
2025 
execute(SkCanvas * canvas) const2026 void SkDrawDrawableCommand::execute(SkCanvas* canvas) const {
2027     canvas->drawDrawable(fDrawable.get(), fMatrix.getMaybeNull());
2028 }
2029 
2030 ///////////////////////////////////////////////////////////////////////////////////////////////////
2031 
SkDrawVerticesCommand(sk_sp<SkVertices> vertices,SkBlendMode bmode,const SkPaint & paint)2032 SkDrawVerticesCommand::SkDrawVerticesCommand(sk_sp<SkVertices> vertices, SkBlendMode bmode,
2033                                              const SkPaint& paint)
2034     : INHERITED(kDrawVertices_OpType)
2035     , fVertices(std::move(vertices))
2036     , fBlendMode(bmode)
2037     , fPaint(paint) {}
2038 
execute(SkCanvas * canvas) const2039 void SkDrawVerticesCommand::execute(SkCanvas* canvas) const {
2040     canvas->drawVertices(fVertices, fBlendMode, fPaint);
2041 }
2042 
2043 ///////////////////////////////////////////////////////////////////////////////////////////////////
2044 
SkDrawAtlasCommand(const SkImage * image,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)2045 SkDrawAtlasCommand::SkDrawAtlasCommand(const SkImage* image, const SkRSXform xform[],
2046                                        const SkRect tex[], const SkColor colors[], int count,
2047                                        SkBlendMode bmode, const SkRect* cull,
2048                                        const SkPaint* paint)
2049     : INHERITED(kDrawAtlas_OpType)
2050     , fImage(SkRef(image))
2051     , fXform(xform, count)
2052     , fTex(tex, count)
2053     , fColors(colors, colors ? count : 0)
2054     , fBlendMode(bmode)
2055     , fCull(cull)
2056     , fPaint(paint) {}
2057 
execute(SkCanvas * canvas) const2058 void SkDrawAtlasCommand::execute(SkCanvas* canvas) const {
2059     canvas->drawAtlas(fImage.get(), fXform.begin(), fTex.begin(),
2060                       fColors.isEmpty() ? nullptr : fColors.begin(), fXform.count(), fBlendMode,
2061                       fCull.getMaybeNull(), fPaint.getMaybeNull());
2062 }
2063 
2064 ///////////////////////////////////////////////////////////////////////////////////////////////////
2065 
SkRestoreCommand()2066 SkRestoreCommand::SkRestoreCommand()
2067     : INHERITED(kRestore_OpType) {}
2068 
execute(SkCanvas * canvas) const2069 void SkRestoreCommand::execute(SkCanvas* canvas) const {
2070     canvas->restore();
2071 }
2072 
SkSaveCommand()2073 SkSaveCommand::SkSaveCommand()
2074     : INHERITED(kSave_OpType) {
2075 }
2076 
execute(SkCanvas * canvas) const2077 void SkSaveCommand::execute(SkCanvas* canvas) const {
2078     canvas->save();
2079 }
2080 
SkSaveLayerCommand(const SkCanvas::SaveLayerRec & rec)2081 SkSaveLayerCommand::SkSaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
2082     : INHERITED(kSaveLayer_OpType)
2083     , fBounds(rec.fBounds)
2084     , fPaint(rec.fPaint)
2085     , fBackdrop(SkSafeRef(rec.fBackdrop))
2086     , fSaveLayerFlags(rec.fSaveLayerFlags) {}
2087 
execute(SkCanvas * canvas) const2088 void SkSaveLayerCommand::execute(SkCanvas* canvas) const {
2089     canvas->saveLayer(SkCanvas::SaveLayerRec(fBounds.getMaybeNull(), fPaint.getMaybeNull(),
2090                                              fSaveLayerFlags));
2091 }
2092 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2093 void SkSaveLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2094     INHERITED::toJSON(writer, urlDataManager);
2095     if (fBounds.isValid()) {
2096         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_BOUNDS); MakeJsonRect(writer, *fBounds);
2097     }
2098     if (fPaint.isValid()) {
2099         writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT);
2100         MakeJsonPaint(writer, *fPaint, urlDataManager);
2101     }
2102     if (fBackdrop != nullptr) {
2103         writer.beginObject(SKDEBUGCANVAS_ATTRIBUTE_BACKDROP);
2104         flatten(fBackdrop.get(), writer, urlDataManager);
2105         writer.endObject(); // backdrop
2106     }
2107     if (fSaveLayerFlags != 0) {
2108         SkDebugf("unsupported: saveLayer flags\n");
2109         SkASSERT(false);
2110     }
2111 }
2112 
SkSetMatrixCommand(const SkMatrix & matrix)2113 SkSetMatrixCommand::SkSetMatrixCommand(const SkMatrix& matrix)
2114     : INHERITED(kSetMatrix_OpType) {
2115     fMatrix = matrix;
2116 }
2117 
execute(SkCanvas * canvas) const2118 void SkSetMatrixCommand::execute(SkCanvas* canvas) const {
2119     canvas->setMatrix(fMatrix);
2120 }
2121 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager) const2122 void SkSetMatrixCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
2123     INHERITED::toJSON(writer, urlDataManager);
2124     writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_MATRIX); MakeJsonMatrix(writer, fMatrix);
2125 }
2126