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