1 
2 /*
3  * Copyright 2012 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #include "SkDrawCommand.h"
11 
12 #include "SkBlurMaskFilter.h"
13 #include "SkColorFilter.h"
14 #include "SkDashPathEffect.h"
15 #include "SkImageFilter.h"
16 #include "SkMaskFilter.h"
17 #include "SkObjectParser.h"
18 #include "SkPaintDefaults.h"
19 #include "SkPathEffect.h"
20 #include "SkPicture.h"
21 #include "SkTextBlob.h"
22 #include "SkTextBlobRunIterator.h"
23 #include "SkTHash.h"
24 #include "SkTypeface.h"
25 #include "SkValidatingReadBuffer.h"
26 #include "SkWriteBuffer.h"
27 
28 #if SK_SUPPORT_GPU
29 #include "GrContext.h"
30 #include "GrRenderTarget.h"
31 #endif
32 
33 #define SKDEBUGCANVAS_ATTRIBUTE_COMMAND           "command"
34 #define SKDEBUGCANVAS_ATTRIBUTE_VISIBLE           "visible"
35 #define SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL        "auditTrail"
36 #define SKDEBUGCANVAS_ATTRIBUTE_MATRIX            "matrix"
37 #define SKDEBUGCANVAS_ATTRIBUTE_COORDS            "coords"
38 #define SKDEBUGCANVAS_ATTRIBUTE_BOUNDS            "bounds"
39 #define SKDEBUGCANVAS_ATTRIBUTE_PAINT             "paint"
40 #define SKDEBUGCANVAS_ATTRIBUTE_OUTER             "outer"
41 #define SKDEBUGCANVAS_ATTRIBUTE_INNER             "inner"
42 #define SKDEBUGCANVAS_ATTRIBUTE_MODE              "mode"
43 #define SKDEBUGCANVAS_ATTRIBUTE_POINTS            "points"
44 #define SKDEBUGCANVAS_ATTRIBUTE_PATH              "path"
45 #define SKDEBUGCANVAS_ATTRIBUTE_TEXT              "text"
46 #define SKDEBUGCANVAS_ATTRIBUTE_COLOR             "color"
47 #define SKDEBUGCANVAS_ATTRIBUTE_ALPHA             "alpha"
48 #define SKDEBUGCANVAS_ATTRIBUTE_STYLE             "style"
49 #define SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH       "strokeWidth"
50 #define SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER       "strokeMiter"
51 #define SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN        "strokeJoin"
52 #define SKDEBUGCANVAS_ATTRIBUTE_CAP               "cap"
53 #define SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS         "antiAlias"
54 #define SKDEBUGCANVAS_ATTRIBUTE_DITHER            "dither"
55 #define SKDEBUGCANVAS_ATTRIBUTE_REGION            "region"
56 #define SKDEBUGCANVAS_ATTRIBUTE_REGIONOP          "op"
57 #define SKDEBUGCANVAS_ATTRIBUTE_EDGESTYLE         "edgeStyle"
58 #define SKDEBUGCANVAS_ATTRIBUTE_DEVICEREGION      "deviceRegion"
59 #define SKDEBUGCANVAS_ATTRIBUTE_BLUR              "blur"
60 #define SKDEBUGCANVAS_ATTRIBUTE_SIGMA             "sigma"
61 #define SKDEBUGCANVAS_ATTRIBUTE_QUALITY           "quality"
62 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN         "textAlign"
63 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE          "textSize"
64 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX        "textScaleX"
65 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX         "textSkewX"
66 #define SKDEBUGCANVAS_ATTRIBUTE_DASHING           "dashing"
67 #define SKDEBUGCANVAS_ATTRIBUTE_INTERVALS         "intervals"
68 #define SKDEBUGCANVAS_ATTRIBUTE_PHASE             "phase"
69 #define SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE          "fillType"
70 #define SKDEBUGCANVAS_ATTRIBUTE_VERBS             "verbs"
71 #define SKDEBUGCANVAS_ATTRIBUTE_NAME              "name"
72 #define SKDEBUGCANVAS_ATTRIBUTE_DATA              "data"
73 #define SKDEBUGCANVAS_ATTRIBUTE_SHADER            "shader"
74 #define SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT        "pathEffect"
75 #define SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER        "maskFilter"
76 #define SKDEBUGCANVAS_ATTRIBUTE_XFERMODE          "xfermode"
77 #define SKDEBUGCANVAS_ATTRIBUTE_LOOPER            "looper"
78 #define SKDEBUGCANVAS_ATTRIBUTE_BACKDROP          "backdrop"
79 #define SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER       "colorfilter"
80 #define SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER       "imagefilter"
81 #define SKDEBUGCANVAS_ATTRIBUTE_IMAGE             "image"
82 #define SKDEBUGCANVAS_ATTRIBUTE_BITMAP            "bitmap"
83 #define SKDEBUGCANVAS_ATTRIBUTE_SRC               "src"
84 #define SKDEBUGCANVAS_ATTRIBUTE_DST               "dst"
85 #define SKDEBUGCANVAS_ATTRIBUTE_CENTER            "center"
86 #define SKDEBUGCANVAS_ATTRIBUTE_STRICT            "strict"
87 #define SKDEBUGCANVAS_ATTRIBUTE_DESCRIPTION       "description"
88 #define SKDEBUGCANVAS_ATTRIBUTE_X                 "x"
89 #define SKDEBUGCANVAS_ATTRIBUTE_Y                 "y"
90 #define SKDEBUGCANVAS_ATTRIBUTE_RUNS              "runs"
91 #define SKDEBUGCANVAS_ATTRIBUTE_POSITIONS         "positions"
92 #define SKDEBUGCANVAS_ATTRIBUTE_GLYPHS            "glyphs"
93 #define SKDEBUGCANVAS_ATTRIBUTE_FONT              "font"
94 #define SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE          "typeface"
95 #define SKDEBUGCANVAS_ATTRIBUTE_CUBICS            "cubics"
96 #define SKDEBUGCANVAS_ATTRIBUTE_COLORS            "colors"
97 #define SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS     "textureCoords"
98 #define SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY     "filterQuality"
99 
100 #define SKDEBUGCANVAS_VERB_MOVE                   "move"
101 #define SKDEBUGCANVAS_VERB_LINE                   "line"
102 #define SKDEBUGCANVAS_VERB_QUAD                   "quad"
103 #define SKDEBUGCANVAS_VERB_CUBIC                  "cubic"
104 #define SKDEBUGCANVAS_VERB_CONIC                  "conic"
105 #define SKDEBUGCANVAS_VERB_CLOSE                  "close"
106 
107 #define SKDEBUGCANVAS_STYLE_FILL                  "fill"
108 #define SKDEBUGCANVAS_STYLE_STROKE                "stroke"
109 #define SKDEBUGCANVAS_STYLE_STROKEANDFILL         "strokeAndFill"
110 
111 #define SKDEBUGCANVAS_POINTMODE_POINTS            "points"
112 #define SKDEBUGCANVAS_POINTMODE_LINES             "lines"
113 #define SKDEBUGCANVAS_POINTMODE_POLYGON           "polygon"
114 
115 #define SKDEBUGCANVAS_REGIONOP_DIFFERENCE         "difference"
116 #define SKDEBUGCANVAS_REGIONOP_INTERSECT          "intersect"
117 #define SKDEBUGCANVAS_REGIONOP_UNION              "union"
118 #define SKDEBUGCANVAS_REGIONOP_XOR                "xor"
119 #define SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE "reverseDifference"
120 #define SKDEBUGCANVAS_REGIONOP_REPLACE            "replace"
121 
122 #define SKDEBUGCANVAS_BLURSTYLE_NORMAL            "normal"
123 #define SKDEBUGCANVAS_BLURSTYLE_SOLID             "solid"
124 #define SKDEBUGCANVAS_BLURSTYLE_OUTER             "outer"
125 #define SKDEBUGCANVAS_BLURSTYLE_INNER             "inner"
126 
127 #define SKDEBUGCANVAS_BLURQUALITY_LOW             "low"
128 #define SKDEBUGCANVAS_BLURQUALITY_HIGH            "high"
129 
130 #define SKDEBUGCANVAS_ALIGN_LEFT                  "left"
131 #define SKDEBUGCANVAS_ALIGN_CENTER                "center"
132 #define SKDEBUGCANVAS_ALIGN_RIGHT                 "right"
133 
134 #define SKDEBUGCANVAS_FILLTYPE_WINDING            "winding"
135 #define SKDEBUGCANVAS_FILLTYPE_EVENODD            "evenOdd"
136 #define SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING     "inverseWinding"
137 #define SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD     "inverseEvenOdd"
138 
139 #define SKDEBUGCANVAS_CAP_BUTT                    "butt"
140 #define SKDEBUGCANVAS_CAP_ROUND                   "round"
141 #define SKDEBUGCANVAS_CAP_SQUARE                  "square"
142 
143 #define SKDEBUGCANVAS_MITER_JOIN                  "miter"
144 #define SKDEBUGCANVAS_ROUND_JOIN                  "round"
145 #define SKDEBUGCANVAS_BEVEL_JOIN                  "bevel"
146 
147 #define SKDEBUGCANVAS_COLORTYPE_ARGB4444          "ARGB4444"
148 #define SKDEBUGCANVAS_COLORTYPE_RGBA8888          "RGBA8888"
149 #define SKDEBUGCANVAS_COLORTYPE_BGRA8888          "BGRA8888"
150 #define SKDEBUGCANVAS_COLORTYPE_565               "565"
151 #define SKDEBUGCANVAS_COLORTYPE_GRAY8             "Gray8"
152 #define SKDEBUGCANVAS_COLORTYPE_INDEX8            "Index8"
153 #define SKDEBUGCANVAS_COLORTYPE_ALPHA8            "Alpha8"
154 
155 #define SKDEBUGCANVAS_ALPHATYPE_OPAQUE            "opaque"
156 #define SKDEBUGCANVAS_ALPHATYPE_PREMUL            "premul"
157 #define SKDEBUGCANVAS_ALPHATYPE_UNPREMUL          "unpremul"
158 
159 #define SKDEBUGCANVAS_FILTERQUALITY_NONE          "none"
160 #define SKDEBUGCANVAS_FILTERQUALITY_LOW           "low"
161 #define SKDEBUGCANVAS_FILTERQUALITY_MEDIUM        "medium"
162 #define SKDEBUGCANVAS_FILTERQUALITY_HIGH          "high"
163 
164 typedef SkDrawCommand* (*FROM_JSON)(Json::Value&, UrlDataManager&);
165 
166 // TODO(chudy): Refactor into non subclass model.
167 
SkDrawCommand(OpType type)168 SkDrawCommand::SkDrawCommand(OpType type)
169     : fOpType(type)
170     , fVisible(true) {
171 }
172 
~SkDrawCommand()173 SkDrawCommand::~SkDrawCommand() {
174     fInfo.deleteAll();
175 }
176 
GetCommandString(OpType type)177 const char* SkDrawCommand::GetCommandString(OpType type) {
178     switch (type) {
179         case kBeginDrawPicture_OpType: return "BeginDrawPicture";
180         case kClipPath_OpType: return "ClipPath";
181         case kClipRegion_OpType: return "ClipRegion";
182         case kClipRect_OpType: return "ClipRect";
183         case kClipRRect_OpType: return "ClipRRect";
184         case kConcat_OpType: return "Concat";
185         case kDrawBitmap_OpType: return "DrawBitmap";
186         case kDrawBitmapNine_OpType: return "DrawBitmapNine";
187         case kDrawBitmapRect_OpType: return "DrawBitmapRect";
188         case kDrawClear_OpType: return "DrawClear";
189         case kDrawDRRect_OpType: return "DrawDRRect";
190         case kDrawImage_OpType: return "DrawImage";
191         case kDrawImageRect_OpType: return "DrawImageRect";
192         case kDrawOval_OpType: return "DrawOval";
193         case kDrawPaint_OpType: return "DrawPaint";
194         case kDrawPatch_OpType: return "DrawPatch";
195         case kDrawPath_OpType: return "DrawPath";
196         case kDrawPoints_OpType: return "DrawPoints";
197         case kDrawPosText_OpType: return "DrawPosText";
198         case kDrawPosTextH_OpType: return "DrawPosTextH";
199         case kDrawRect_OpType: return "DrawRect";
200         case kDrawRRect_OpType: return "DrawRRect";
201         case kDrawText_OpType: return "DrawText";
202         case kDrawTextBlob_OpType: return "DrawTextBlob";
203         case kDrawTextOnPath_OpType: return "DrawTextOnPath";
204         case kDrawVertices_OpType: return "DrawVertices";
205         case kEndDrawPicture_OpType: return "EndDrawPicture";
206         case kRestore_OpType: return "Restore";
207         case kSave_OpType: return "Save";
208         case kSaveLayer_OpType: return "SaveLayer";
209         case kSetMatrix_OpType: return "SetMatrix";
210         default:
211             SkDebugf("OpType error 0x%08x\n", type);
212             SkASSERT(0);
213             break;
214     }
215     SkDEBUGFAIL("DrawType UNUSED\n");
216     return nullptr;
217 }
218 
toString() const219 SkString SkDrawCommand::toString() const {
220     return SkString(GetCommandString(fOpType));
221 }
222 
toJSON(UrlDataManager & urlDataManager) const223 Json::Value SkDrawCommand::toJSON(UrlDataManager& urlDataManager) const {
224     Json::Value result;
225     result[SKDEBUGCANVAS_ATTRIBUTE_COMMAND] = this->GetCommandString(fOpType);
226     result[SKDEBUGCANVAS_ATTRIBUTE_VISIBLE] = Json::Value(this->isVisible());
227     return result;
228 }
229 
drawToAndCollectJSON(SkCanvas * canvas,UrlDataManager & urlDataManager) const230 Json::Value SkDrawCommand::drawToAndCollectJSON(SkCanvas* canvas,
231                                                 UrlDataManager& urlDataManager) const {
232     Json::Value result = this->toJSON(urlDataManager);
233 
234     SkASSERT(canvas);
235 
236 #if SK_SUPPORT_GPU
237     GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
238     if (rt) {
239         GrContext* ctx = rt->getContext();
240         if(ctx) {
241             GrAuditTrail* at = ctx->getAuditTrail();
242             GrAuditTrail::AutoEnable enable(at);
243             this->execute(canvas);
244 
245             // TODO if this is inefficient we could add a method to GrAuditTrail which takes
246             // a Json::Value and is only compiled in this file
247             Json::Value parsedFromString;
248             Json::Reader reader;
249             SkDEBUGCODE(bool parsingSuccessful = )reader.parse(at->toJson().c_str(),
250                                                                parsedFromString);
251             SkASSERT(parsingSuccessful);
252 
253             result[SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL] = parsedFromString;
254             at->reset();
255         }
256     }
257 #endif
258     return result;
259 }
260 
261 #define INSTALL_FACTORY(name) factories.set(SkString(GetCommandString(k ## name ##_OpType)), \
262                                             (FROM_JSON) Sk ## name ## Command::fromJSON)
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)263 SkDrawCommand* SkDrawCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
264     static SkTHashMap<SkString, FROM_JSON> factories;
265     static bool initialized = false;
266     if (!initialized) {
267         initialized = true;
268         INSTALL_FACTORY(Restore);
269         INSTALL_FACTORY(ClipPath);
270         INSTALL_FACTORY(ClipRegion);
271         INSTALL_FACTORY(ClipRect);
272         INSTALL_FACTORY(ClipRRect);
273         INSTALL_FACTORY(Concat);
274         INSTALL_FACTORY(DrawBitmap);
275         INSTALL_FACTORY(DrawBitmapRect);
276         INSTALL_FACTORY(DrawBitmapNine);
277         INSTALL_FACTORY(DrawImage);
278         INSTALL_FACTORY(DrawImageRect);
279         INSTALL_FACTORY(DrawOval);
280         INSTALL_FACTORY(DrawPaint);
281         INSTALL_FACTORY(DrawPath);
282         INSTALL_FACTORY(DrawPoints);
283         INSTALL_FACTORY(DrawText);
284         INSTALL_FACTORY(DrawPosText);
285         INSTALL_FACTORY(DrawTextOnPath);
286         INSTALL_FACTORY(DrawTextBlob);
287 
288         INSTALL_FACTORY(DrawRect);
289         INSTALL_FACTORY(DrawRRect);
290         INSTALL_FACTORY(DrawDRRect);
291         INSTALL_FACTORY(DrawPatch);
292         INSTALL_FACTORY(Save);
293         INSTALL_FACTORY(SaveLayer);
294         INSTALL_FACTORY(SetMatrix);
295     }
296     SkString name = SkString(command[SKDEBUGCANVAS_ATTRIBUTE_COMMAND].asCString());
297     FROM_JSON* factory = factories.find(name);
298     if (factory == nullptr) {
299         SkDebugf("no JSON factory for '%s'\n", name.c_str());
300         return nullptr;
301     }
302     return (*factory)(command, urlDataManager);
303 }
304 
305 namespace {
306 
xlate_and_scale_to_bounds(SkCanvas * canvas,const SkRect & bounds)307 void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
308     const SkISize& size = canvas->getDeviceSize();
309 
310     static const SkScalar kInsetFrac = 0.9f; // Leave a border around object
311 
312     canvas->translate(size.fWidth/2.0f, size.fHeight/2.0f);
313     if (bounds.width() > bounds.height()) {
314         canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.width()),
315                       SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.width()));
316     } else {
317         canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.height()),
318                       SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.height()));
319     }
320     canvas->translate(-bounds.centerX(), -bounds.centerY());
321 }
322 
323 
render_path(SkCanvas * canvas,const SkPath & path)324 void render_path(SkCanvas* canvas, const SkPath& path) {
325     canvas->clear(0xFFFFFFFF);
326 
327     const SkRect& bounds = path.getBounds();
328     if (bounds.isEmpty()) {
329         return;
330     }
331 
332     SkAutoCanvasRestore acr(canvas, true);
333     xlate_and_scale_to_bounds(canvas, bounds);
334 
335     SkPaint p;
336     p.setColor(SK_ColorBLACK);
337     p.setStyle(SkPaint::kStroke_Style);
338 
339     canvas->drawPath(path, p);
340 }
341 
render_bitmap(SkCanvas * canvas,const SkBitmap & input,const SkRect * srcRect=nullptr)342 void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = nullptr) {
343     const SkISize& size = canvas->getDeviceSize();
344 
345     SkScalar xScale = SkIntToScalar(size.fWidth-2) / input.width();
346     SkScalar yScale = SkIntToScalar(size.fHeight-2) / input.height();
347 
348     if (input.width() > input.height()) {
349         yScale *= input.height() / (float) input.width();
350     } else {
351         xScale *= input.width() / (float) input.height();
352     }
353 
354     SkRect dst = SkRect::MakeXYWH(SK_Scalar1, SK_Scalar1,
355                                   xScale * input.width(),
356                                   yScale * input.height());
357 
358     static const int kNumBlocks = 8;
359 
360     canvas->clear(0xFFFFFFFF);
361     SkISize block = {
362         canvas->imageInfo().width()/kNumBlocks,
363         canvas->imageInfo().height()/kNumBlocks
364     };
365     for (int y = 0; y < kNumBlocks; ++y) {
366         for (int x = 0; x < kNumBlocks; ++x) {
367             SkPaint paint;
368             paint.setColor((x+y)%2 ? SK_ColorLTGRAY : SK_ColorDKGRAY);
369             SkRect r = SkRect::MakeXYWH(SkIntToScalar(x*block.width()),
370                                         SkIntToScalar(y*block.height()),
371                                         SkIntToScalar(block.width()),
372                                         SkIntToScalar(block.height()));
373             canvas->drawRect(r, paint);
374         }
375     }
376 
377     canvas->drawBitmapRect(input, dst, nullptr);
378 
379     if (srcRect) {
380         SkRect r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
381                                     srcRect->fTop * yScale + SK_Scalar1,
382                                     srcRect->fRight * xScale + SK_Scalar1,
383                                     srcRect->fBottom * yScale + SK_Scalar1);
384         SkPaint p;
385         p.setColor(SK_ColorRED);
386         p.setStyle(SkPaint::kStroke_Style);
387 
388         canvas->drawRect(r, p);
389     }
390 }
391 
render_rrect(SkCanvas * canvas,const SkRRect & rrect)392 void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
393     canvas->clear(0xFFFFFFFF);
394     canvas->save();
395 
396     const SkRect& bounds = rrect.getBounds();
397 
398     xlate_and_scale_to_bounds(canvas, bounds);
399 
400     SkPaint p;
401     p.setColor(SK_ColorBLACK);
402     p.setStyle(SkPaint::kStroke_Style);
403 
404     canvas->drawRRect(rrect, p);
405     canvas->restore();
406 }
407 
render_drrect(SkCanvas * canvas,const SkRRect & outer,const SkRRect & inner)408 void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
409     canvas->clear(0xFFFFFFFF);
410     canvas->save();
411 
412     const SkRect& bounds = outer.getBounds();
413 
414     xlate_and_scale_to_bounds(canvas, bounds);
415 
416     SkPaint p;
417     p.setColor(SK_ColorBLACK);
418     p.setStyle(SkPaint::kStroke_Style);
419 
420     canvas->drawDRRect(outer, inner, p);
421     canvas->restore();
422 }
423 
424 };
425 
make_json_color(const SkColor color)426 static Json::Value make_json_color(const SkColor color) {
427     Json::Value result(Json::arrayValue);
428     result.append(Json::Value(SkColorGetA(color)));
429     result.append(Json::Value(SkColorGetR(color)));
430     result.append(Json::Value(SkColorGetG(color)));
431     result.append(Json::Value(SkColorGetB(color)));
432     return result;
433 }
434 
435 
make_json_point(const SkPoint & point)436 static Json::Value make_json_point(const SkPoint& point) {
437     Json::Value result(Json::arrayValue);
438     result.append(Json::Value(point.x()));
439     result.append(Json::Value(point.y()));
440     return result;
441 }
442 
make_json_point(SkScalar x,SkScalar y)443 static Json::Value make_json_point(SkScalar x, SkScalar y) {
444     Json::Value result(Json::arrayValue);
445     result.append(Json::Value(x));
446     result.append(Json::Value(y));
447     return result;
448 }
449 
make_json_rect(const SkRect & rect)450 static Json::Value make_json_rect(const SkRect& rect) {
451     Json::Value result(Json::arrayValue);
452     result.append(Json::Value(rect.left()));
453     result.append(Json::Value(rect.top()));
454     result.append(Json::Value(rect.right()));
455     result.append(Json::Value(rect.bottom()));
456     return result;
457 }
458 
make_json_irect(const SkIRect & rect)459 static Json::Value make_json_irect(const SkIRect& rect) {
460     Json::Value result(Json::arrayValue);
461     result.append(Json::Value(rect.left()));
462     result.append(Json::Value(rect.top()));
463     result.append(Json::Value(rect.right()));
464     result.append(Json::Value(rect.bottom()));
465     return result;
466 }
467 
make_json_rrect(const SkRRect & rrect)468 static Json::Value make_json_rrect(const SkRRect& rrect) {
469     Json::Value result(Json::arrayValue);
470     result.append(make_json_rect(rrect.rect()));
471     result.append(make_json_point(rrect.radii(SkRRect::kUpperLeft_Corner)));
472     result.append(make_json_point(rrect.radii(SkRRect::kUpperRight_Corner)));
473     result.append(make_json_point(rrect.radii(SkRRect::kLowerRight_Corner)));
474     result.append(make_json_point(rrect.radii(SkRRect::kLowerLeft_Corner)));
475     return result;
476 }
477 
make_json_matrix(const SkMatrix & matrix)478 static Json::Value make_json_matrix(const SkMatrix& matrix) {
479     Json::Value result(Json::arrayValue);
480     Json::Value row1(Json::arrayValue);
481     row1.append(Json::Value(matrix[0]));
482     row1.append(Json::Value(matrix[1]));
483     row1.append(Json::Value(matrix[2]));
484     result.append(row1);
485     Json::Value row2(Json::arrayValue);
486     row2.append(Json::Value(matrix[3]));
487     row2.append(Json::Value(matrix[4]));
488     row2.append(Json::Value(matrix[5]));
489     result.append(row2);
490     Json::Value row3(Json::arrayValue);
491     row3.append(Json::Value(matrix[6]));
492     row3.append(Json::Value(matrix[7]));
493     row3.append(Json::Value(matrix[8]));
494     result.append(row3);
495     return result;
496 }
497 
make_json_path(const SkPath & path)498 static Json::Value make_json_path(const SkPath& path) {
499     Json::Value result(Json::objectValue);
500     switch (path.getFillType()) {
501         case SkPath::kWinding_FillType:
502             result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_WINDING;
503             break;
504         case SkPath::kEvenOdd_FillType:
505             result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_EVENODD;
506             break;
507         case SkPath::kInverseWinding_FillType:
508             result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING;
509             break;
510         case SkPath::kInverseEvenOdd_FillType:
511             result[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE] = SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD;
512             break;
513     }
514     Json::Value verbs(Json::arrayValue);
515     SkPath::Iter iter(path, false);
516     SkPoint pts[4];
517     SkPath::Verb verb;
518     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
519         switch (verb) {
520             case SkPath::kLine_Verb: {
521                 Json::Value line(Json::objectValue);
522                 line[SKDEBUGCANVAS_VERB_LINE] = make_json_point(pts[1]);
523                 verbs.append(line);
524                 break;
525             }
526             case SkPath::kQuad_Verb: {
527                 Json::Value quad(Json::objectValue);
528                 Json::Value coords(Json::arrayValue);
529                 coords.append(make_json_point(pts[1]));
530                 coords.append(make_json_point(pts[2]));
531                 quad[SKDEBUGCANVAS_VERB_QUAD] = coords;
532                 verbs.append(quad);
533                 break;
534             }
535             case SkPath::kCubic_Verb: {
536                 Json::Value cubic(Json::objectValue);
537                 Json::Value coords(Json::arrayValue);
538                 coords.append(make_json_point(pts[1]));
539                 coords.append(make_json_point(pts[2]));
540                 coords.append(make_json_point(pts[3]));
541                 cubic[SKDEBUGCANVAS_VERB_CUBIC] = coords;
542                 verbs.append(cubic);
543                 break;
544             }
545             case SkPath::kConic_Verb: {
546                 Json::Value conic(Json::objectValue);
547                 Json::Value coords(Json::arrayValue);
548                 coords.append(make_json_point(pts[1]));
549                 coords.append(make_json_point(pts[2]));
550                 coords.append(Json::Value(iter.conicWeight()));
551                 conic[SKDEBUGCANVAS_VERB_CONIC] = coords;
552                 verbs.append(conic);
553                 break;
554             }
555             case SkPath::kMove_Verb: {
556                 Json::Value move(Json::objectValue);
557                 move[SKDEBUGCANVAS_VERB_MOVE] = make_json_point(pts[0]);
558                 verbs.append(move);
559                 break;
560             }
561             case SkPath::kClose_Verb:
562                 verbs.append(Json::Value(SKDEBUGCANVAS_VERB_CLOSE));
563                 break;
564             case SkPath::kDone_Verb:
565                 break;
566         }
567     }
568     result[SKDEBUGCANVAS_ATTRIBUTE_VERBS] = verbs;
569     return result;
570 }
571 
make_json_region(const SkRegion & region)572 static Json::Value make_json_region(const SkRegion& region) {
573     return Json::Value("<unimplemented>");
574 }
575 
make_json_regionop(SkRegion::Op op)576 static Json::Value make_json_regionop(SkRegion::Op op) {
577     switch (op) {
578         case SkRegion::kDifference_Op:
579             return Json::Value(SKDEBUGCANVAS_REGIONOP_DIFFERENCE);
580         case SkRegion::kIntersect_Op:
581             return Json::Value(SKDEBUGCANVAS_REGIONOP_INTERSECT);
582         case SkRegion::kUnion_Op:
583             return Json::Value(SKDEBUGCANVAS_REGIONOP_UNION);
584         case SkRegion::kXOR_Op:
585             return Json::Value(SKDEBUGCANVAS_REGIONOP_XOR);
586         case SkRegion::kReverseDifference_Op:
587             return Json::Value(SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE);
588         case SkRegion::kReplace_Op:
589             return Json::Value(SKDEBUGCANVAS_REGIONOP_REPLACE);
590         default:
591             SkASSERT(false);
592             return Json::Value("<invalid region op>");
593     };
594 }
595 
make_json_pointmode(SkCanvas::PointMode mode)596 static Json::Value make_json_pointmode(SkCanvas::PointMode mode) {
597     switch (mode) {
598         case SkCanvas::kPoints_PointMode:
599             return Json::Value(SKDEBUGCANVAS_POINTMODE_POINTS);
600         case SkCanvas::kLines_PointMode:
601             return Json::Value(SKDEBUGCANVAS_POINTMODE_LINES);
602         case SkCanvas::kPolygon_PointMode:
603             return Json::Value(SKDEBUGCANVAS_POINTMODE_POLYGON);
604         default:
605             SkASSERT(false);
606             return Json::Value("<invalid point mode>");
607     };
608 }
609 
store_scalar(Json::Value * target,const char * key,SkScalar value,SkScalar defaultValue)610 static void store_scalar(Json::Value* target, const char* key, SkScalar value,
611                          SkScalar defaultValue) {
612     if (value != defaultValue) {
613         (*target)[key] = Json::Value(value);
614     }
615 }
616 
store_bool(Json::Value * target,const char * key,bool value,bool defaultValue)617 static void store_bool(Json::Value* target, const char* key, bool value, bool defaultValue) {
618     if (value != defaultValue) {
619         (*target)[key] = Json::Value(value);
620     }
621 }
622 
encode_data(const void * bytes,size_t count,const char * contentType,UrlDataManager & urlDataManager,Json::Value * target)623 static void encode_data(const void* bytes, size_t count, const char* contentType,
624                         UrlDataManager& urlDataManager, Json::Value* target) {
625     SkAutoTUnref<SkData> data(SkData::NewWithCopy(bytes, count));
626     SkString url = urlDataManager.addData(data, contentType);
627     *target = Json::Value(url.c_str());
628 }
629 
flatten(const SkFlattenable * flattenable,Json::Value * target,UrlDataManager & urlDataManager)630 static void flatten(const SkFlattenable* flattenable, Json::Value* target,
631                     UrlDataManager& urlDataManager) {
632     SkWriteBuffer buffer;
633     flattenable->flatten(buffer);
634     void* data = sk_malloc_throw(buffer.bytesWritten());
635     buffer.writeToMemory(data);
636     Json::Value jsonData;
637     encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager, &jsonData);
638     Json::Value jsonFlattenable;
639     jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_NAME] = Json::Value(flattenable->getTypeName());
640     jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_DATA] = jsonData;
641     (*target) = jsonFlattenable;
642     sk_free(data);
643 }
644 
flatten(const SkImage & image,Json::Value * target,UrlDataManager & urlDataManager)645 static bool SK_WARN_UNUSED_RESULT flatten(const SkImage& image, Json::Value* target,
646                                           UrlDataManager& urlDataManager) {
647     SkData* encoded = image.encode(SkImageEncoder::kPNG_Type, 100);
648     if (encoded == nullptr) {
649         // PNG encode doesn't necessarily support all color formats, convert to a different
650         // format
651         size_t rowBytes = 4 * image.width();
652         void* buffer = sk_malloc_throw(rowBytes * image.height());
653         SkImageInfo dstInfo = SkImageInfo::Make(image.width(), image.height(),
654                                                 kN32_SkColorType, kPremul_SkAlphaType);
655         if (!image.readPixels(dstInfo, buffer, rowBytes, 0, 0)) {
656             SkDebugf("readPixels failed\n");
657             return false;
658         }
659         SkImage* converted = SkImage::NewRasterCopy(dstInfo, buffer, rowBytes);
660         encoded = converted->encode(SkImageEncoder::kPNG_Type, 100);
661         if (encoded == nullptr) {
662             SkDebugf("image encode failed\n");
663             return false;
664         }
665         sk_free(converted);
666         sk_free(buffer);
667     }
668     Json::Value jsonData;
669     encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager, &jsonData);
670     (*target)[SKDEBUGCANVAS_ATTRIBUTE_DATA] = jsonData;
671     encoded->unref();
672     return true;
673 }
674 
color_type_name(SkColorType colorType)675 static const char* color_type_name(SkColorType colorType) {
676     switch (colorType) {
677         case kARGB_4444_SkColorType:
678             return SKDEBUGCANVAS_COLORTYPE_ARGB4444;
679         case kRGBA_8888_SkColorType:
680             return SKDEBUGCANVAS_COLORTYPE_RGBA8888;
681         case kBGRA_8888_SkColorType:
682             return SKDEBUGCANVAS_COLORTYPE_BGRA8888;
683         case kRGB_565_SkColorType:
684             return SKDEBUGCANVAS_COLORTYPE_565;
685         case kGray_8_SkColorType:
686             return SKDEBUGCANVAS_COLORTYPE_GRAY8;
687         case kIndex_8_SkColorType:
688             return SKDEBUGCANVAS_COLORTYPE_INDEX8;
689         case kAlpha_8_SkColorType:
690             return SKDEBUGCANVAS_COLORTYPE_ALPHA8;
691         default:
692             SkASSERT(false);
693             return SKDEBUGCANVAS_COLORTYPE_RGBA8888;
694     }
695 }
696 
alpha_type_name(SkAlphaType alphaType)697 static const char* alpha_type_name(SkAlphaType alphaType) {
698     switch (alphaType) {
699         case kOpaque_SkAlphaType:
700             return SKDEBUGCANVAS_ALPHATYPE_OPAQUE;
701         case kPremul_SkAlphaType:
702             return SKDEBUGCANVAS_ALPHATYPE_PREMUL;
703         case kUnpremul_SkAlphaType:
704             return SKDEBUGCANVAS_ALPHATYPE_UNPREMUL;
705         default:
706             SkASSERT(false);
707             return SKDEBUGCANVAS_ALPHATYPE_OPAQUE;
708     }
709 }
710 
decode_data(Json::Value data,UrlDataManager & urlDataManager,const void ** target)711 static Json::ArrayIndex decode_data(Json::Value data, UrlDataManager& urlDataManager,
712                                     const void** target) {
713     UrlDataManager::UrlData* urlData = urlDataManager.getDataFromUrl(SkString(data.asCString()));
714     if (urlData == nullptr) {
715         SkASSERT(false);
716         *target = nullptr;
717         return 0;
718     }
719     *target = urlData->fData->data();
720     // cast should be safe for any reasonably-sized object...
721     return (Json::ArrayIndex) urlData->fData->size();
722 }
723 
load_flattenable(Json::Value jsonFlattenable,UrlDataManager & urlDataManager)724 static SkFlattenable* load_flattenable(Json::Value jsonFlattenable,
725                                        UrlDataManager& urlDataManager) {
726     if (!jsonFlattenable.isMember(SKDEBUGCANVAS_ATTRIBUTE_NAME)) {
727         return nullptr;
728     }
729     const char* name = jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_NAME].asCString();
730     SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name);
731     if (factory == nullptr) {
732         SkDebugf("no factory for loading '%s'\n", name);
733         return nullptr;
734     }
735     const void* data;
736     int size = decode_data(jsonFlattenable[SKDEBUGCANVAS_ATTRIBUTE_DATA], urlDataManager, &data);
737     SkValidatingReadBuffer buffer(data, size);
738     SkFlattenable* result = factory(buffer);
739     if (!buffer.isValid()) {
740         SkDebugf("invalid buffer loading flattenable\n");
741         return nullptr;
742     }
743     return result;
744 }
745 
colortype_from_name(const char * name)746 static SkColorType colortype_from_name(const char* name) {
747     if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_ARGB4444)) {
748         return kARGB_4444_SkColorType;
749     }
750     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_RGBA8888)) {
751         return kRGBA_8888_SkColorType;
752     }
753     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_BGRA8888)) {
754         return kBGRA_8888_SkColorType;
755     }
756     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_565)) {
757         return kRGB_565_SkColorType;
758     }
759     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_GRAY8)) {
760         return kGray_8_SkColorType;
761     }
762     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_INDEX8)) {
763         return kIndex_8_SkColorType;
764     }
765     else if (!strcmp(name, SKDEBUGCANVAS_COLORTYPE_ALPHA8)) {
766         return kAlpha_8_SkColorType;
767     }
768     SkASSERT(false);
769     return kN32_SkColorType;
770 }
771 
convert_colortype(SkBitmap * bitmap,SkColorType colorType)772 static SkBitmap* convert_colortype(SkBitmap* bitmap, SkColorType colorType) {
773     if (bitmap->colorType() == colorType  ) {
774         return bitmap;
775     }
776     SkBitmap* dst = new SkBitmap();
777     if (bitmap->copyTo(dst, colorType)) {
778         delete bitmap;
779         return dst;
780     }
781     SkASSERT(false);
782     delete dst;
783     return bitmap;
784 }
785 
786 // caller is responsible for freeing return value
load_bitmap(const Json::Value & jsonBitmap,UrlDataManager & urlDataManager)787 static SkBitmap* load_bitmap(const Json::Value& jsonBitmap, UrlDataManager& urlDataManager) {
788     if (!jsonBitmap.isMember(SKDEBUGCANVAS_ATTRIBUTE_DATA)) {
789         SkDebugf("invalid bitmap\n");
790         return nullptr;
791     }
792     const void* data;
793     int size = decode_data(jsonBitmap[SKDEBUGCANVAS_ATTRIBUTE_DATA], urlDataManager, &data);
794     SkMemoryStream stream(data, size);
795     SkImageDecoder* decoder = SkImageDecoder::Factory(&stream);
796     SkBitmap* bitmap = new SkBitmap();
797     SkImageDecoder::Result result = decoder->decode(&stream, bitmap,
798                                                     SkImageDecoder::kDecodePixels_Mode);
799     sk_free(decoder);
800     if (result != SkImageDecoder::kFailure) {
801         if (jsonBitmap.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLOR)) {
802             const char* ctName = jsonBitmap[SKDEBUGCANVAS_ATTRIBUTE_COLOR].asCString();
803             SkColorType ct = colortype_from_name(ctName);
804             if (ct != kIndex_8_SkColorType) {
805                 bitmap = convert_colortype(bitmap, ct);
806             }
807         }
808         return bitmap;
809     }
810     SkDebugf("image decode failed\n");
811     return nullptr;
812 }
813 
load_image(const Json::Value & jsonImage,UrlDataManager & urlDataManager)814 static SkImage* load_image(const Json::Value& jsonImage, UrlDataManager& urlDataManager) {
815     SkBitmap* bitmap = load_bitmap(jsonImage, urlDataManager);
816     if (bitmap == nullptr) {
817         return nullptr;
818     }
819     SkImage* result = SkImage::NewFromBitmap(*bitmap);
820     delete bitmap;
821     return result;
822 }
823 
flatten(const SkBitmap & bitmap,Json::Value * target,UrlDataManager & urlDataManager)824 static bool SK_WARN_UNUSED_RESULT flatten(const SkBitmap& bitmap, Json::Value* target,
825                                           UrlDataManager& urlDataManager) {
826     bitmap.lockPixels();
827     SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bitmap));
828     bitmap.unlockPixels();
829     (*target)[SKDEBUGCANVAS_ATTRIBUTE_COLOR] = Json::Value(color_type_name(bitmap.colorType()));
830     (*target)[SKDEBUGCANVAS_ATTRIBUTE_ALPHA] = Json::Value(alpha_type_name(bitmap.alphaType()));
831     bool success = flatten(*image, target, urlDataManager);
832     return success;
833 }
834 
apply_paint_color(const SkPaint & paint,Json::Value * target)835 static void apply_paint_color(const SkPaint& paint, Json::Value* target) {
836     SkColor color = paint.getColor();
837     if (color != SK_ColorBLACK) {
838         Json::Value colorValue(Json::arrayValue);
839         colorValue.append(Json::Value(SkColorGetA(color)));
840         colorValue.append(Json::Value(SkColorGetR(color)));
841         colorValue.append(Json::Value(SkColorGetG(color)));
842         colorValue.append(Json::Value(SkColorGetB(color)));
843         (*target)[SKDEBUGCANVAS_ATTRIBUTE_COLOR] = colorValue;;
844     }
845 }
846 
apply_paint_style(const SkPaint & paint,Json::Value * target)847 static void apply_paint_style(const SkPaint& paint, Json::Value* target) {
848     SkPaint::Style style = paint.getStyle();
849     if (style != SkPaint::kFill_Style) {
850         switch (style) {
851             case SkPaint::kStroke_Style: {
852                 Json::Value stroke(SKDEBUGCANVAS_STYLE_STROKE);
853                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = stroke;
854                 break;
855             }
856             case SkPaint::kStrokeAndFill_Style: {
857                 Json::Value strokeAndFill(SKDEBUGCANVAS_STYLE_STROKEANDFILL);
858                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = strokeAndFill;
859                 break;
860             }
861             default: SkASSERT(false);
862         }
863     }
864 }
865 
apply_paint_cap(const SkPaint & paint,Json::Value * target)866 static void apply_paint_cap(const SkPaint& paint, Json::Value* target) {
867     SkPaint::Cap cap = paint.getStrokeCap();
868     if (cap != SkPaint::kDefault_Cap) {
869         switch (cap) {
870             case SkPaint::kButt_Cap:
871                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_CAP] = Json::Value(SKDEBUGCANVAS_CAP_BUTT);
872                 break;
873             case SkPaint::kRound_Cap:
874                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_CAP] = Json::Value(SKDEBUGCANVAS_CAP_ROUND);
875                 break;
876             case SkPaint::kSquare_Cap:
877                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_CAP] = Json::Value(SKDEBUGCANVAS_CAP_SQUARE);
878                 break;
879             default: SkASSERT(false);
880         }
881     }
882 }
883 
apply_paint_join(const SkPaint & paint,Json::Value * target)884 static void apply_paint_join(const SkPaint& paint, Json::Value* target) {
885     SkPaint::Join join = paint.getStrokeJoin();
886     if (join != SkPaint::kDefault_Join) {
887         switch (join) {
888             case SkPaint::kMiter_Join:
889                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN] = Json::Value(
890                                                                           SKDEBUGCANVAS_MITER_JOIN);
891                 break;
892             case SkPaint::kRound_Join:
893                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN] = Json::Value(
894                                                                           SKDEBUGCANVAS_ROUND_JOIN);
895                 break;
896             case SkPaint::kBevel_Join:
897                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN] = Json::Value(
898                                                                         SKDEBUGCANVAS_BEVEL_JOIN);
899                 break;
900             default: SkASSERT(false);
901         }
902     }
903 }
904 
apply_paint_filterquality(const SkPaint & paint,Json::Value * target)905 static void apply_paint_filterquality(const SkPaint& paint, Json::Value* target) {
906     SkFilterQuality quality = paint.getFilterQuality();
907     switch (quality) {
908         case kNone_SkFilterQuality:
909             break;
910         case kLow_SkFilterQuality:
911             (*target)[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY] = Json::Value(
912                                                                    SKDEBUGCANVAS_FILTERQUALITY_LOW);
913             break;
914         case kMedium_SkFilterQuality:
915             (*target)[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY] = Json::Value(
916                                                                 SKDEBUGCANVAS_FILTERQUALITY_MEDIUM);
917             break;
918         case kHigh_SkFilterQuality:
919             (*target)[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY] = Json::Value(
920                                                                   SKDEBUGCANVAS_FILTERQUALITY_HIGH);
921             break;
922     }
923 }
924 
apply_paint_maskfilter(const SkPaint & paint,Json::Value * target,UrlDataManager & urlDataManager)925 static void apply_paint_maskfilter(const SkPaint& paint, Json::Value* target,
926                                    UrlDataManager& urlDataManager) {
927     SkMaskFilter* maskFilter = paint.getMaskFilter();
928     if (maskFilter != nullptr) {
929         SkMaskFilter::BlurRec blurRec;
930         if (maskFilter->asABlur(&blurRec)) {
931             Json::Value blur(Json::objectValue);
932             blur[SKDEBUGCANVAS_ATTRIBUTE_SIGMA] = Json::Value(blurRec.fSigma);
933             switch (blurRec.fStyle) {
934                 case SkBlurStyle::kNormal_SkBlurStyle:
935                     blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
936                                                                     SKDEBUGCANVAS_BLURSTYLE_NORMAL);
937                     break;
938                 case SkBlurStyle::kSolid_SkBlurStyle:
939                     blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
940                                                                      SKDEBUGCANVAS_BLURSTYLE_SOLID);
941                     break;
942                 case SkBlurStyle::kOuter_SkBlurStyle:
943                     blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
944                                                                      SKDEBUGCANVAS_BLURSTYLE_OUTER);
945                     break;
946                 case SkBlurStyle::kInner_SkBlurStyle:
947                     blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE] = Json::Value(
948                                                                      SKDEBUGCANVAS_BLURSTYLE_INNER);
949                     break;
950                 default:
951                     SkASSERT(false);
952             }
953             switch (blurRec.fQuality) {
954                 case SkBlurQuality::kLow_SkBlurQuality:
955                     blur[SKDEBUGCANVAS_ATTRIBUTE_QUALITY] = Json::Value(
956                                                                      SKDEBUGCANVAS_BLURQUALITY_LOW);
957                     break;
958                 case SkBlurQuality::kHigh_SkBlurQuality:
959                     blur[SKDEBUGCANVAS_ATTRIBUTE_QUALITY] = Json::Value(
960                                                                     SKDEBUGCANVAS_BLURQUALITY_HIGH);
961                     break;
962                 default:
963                     SkASSERT(false);
964             }
965             (*target)[SKDEBUGCANVAS_ATTRIBUTE_BLUR] = blur;
966         } else {
967             Json::Value jsonMaskFilter;
968             flatten(maskFilter, &jsonMaskFilter, urlDataManager);
969             (*target)[SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER] = jsonMaskFilter;
970         }
971     }
972 }
973 
apply_paint_patheffect(const SkPaint & paint,Json::Value * target,UrlDataManager & urlDataManager)974 static void apply_paint_patheffect(const SkPaint& paint, Json::Value* target,
975                                    UrlDataManager& urlDataManager) {
976     SkPathEffect* pathEffect = paint.getPathEffect();
977     if (pathEffect != nullptr) {
978         SkPathEffect::DashInfo dashInfo;
979         SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
980         if (dashType == SkPathEffect::kDash_DashType) {
981             dashInfo.fIntervals = (SkScalar*) sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
982             pathEffect->asADash(&dashInfo);
983             Json::Value dashing(Json::objectValue);
984             Json::Value intervals(Json::arrayValue);
985             for (int32_t i = 0; i < dashInfo.fCount; i++) {
986                 intervals.append(Json::Value(dashInfo.fIntervals[i]));
987             }
988             sk_free(dashInfo.fIntervals);
989             dashing[SKDEBUGCANVAS_ATTRIBUTE_INTERVALS] = intervals;
990             dashing[SKDEBUGCANVAS_ATTRIBUTE_PHASE] = dashInfo.fPhase;
991             (*target)[SKDEBUGCANVAS_ATTRIBUTE_DASHING] = dashing;
992         } else {
993             Json::Value jsonPathEffect;
994             flatten(pathEffect, &jsonPathEffect, urlDataManager);
995             (*target)[SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT] = jsonPathEffect;
996         }
997     }
998 }
999 
apply_paint_textalign(const SkPaint & paint,Json::Value * target)1000 static void apply_paint_textalign(const SkPaint& paint, Json::Value* target) {
1001     SkPaint::Align textAlign = paint.getTextAlign();
1002     if (textAlign != SkPaint::kLeft_Align) {
1003         switch (textAlign) {
1004             case SkPaint::kCenter_Align: {
1005                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN] = SKDEBUGCANVAS_ALIGN_CENTER;
1006                 break;
1007             }
1008             case SkPaint::kRight_Align: {
1009                 (*target)[SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN] = SKDEBUGCANVAS_ALIGN_RIGHT;
1010                 break;
1011             }
1012             default: SkASSERT(false);
1013         }
1014     }
1015 }
1016 
apply_paint_typeface(const SkPaint & paint,Json::Value * target,UrlDataManager & urlDataManager)1017 static void apply_paint_typeface(const SkPaint& paint, Json::Value* target,
1018                                  UrlDataManager& urlDataManager) {
1019     SkTypeface* typeface = paint.getTypeface();
1020     if (typeface != nullptr) {
1021         Json::Value jsonTypeface;
1022         SkDynamicMemoryWStream buffer;
1023         typeface->serialize(&buffer);
1024         void* data = sk_malloc_throw(buffer.bytesWritten());
1025         buffer.copyTo(data);
1026         Json::Value jsonData;
1027         encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager,
1028                     &jsonData);
1029         jsonTypeface[SKDEBUGCANVAS_ATTRIBUTE_DATA] = jsonData;
1030         sk_free(data);
1031         (*target)[SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE] = jsonTypeface;
1032     }
1033 }
1034 
apply_paint_shader(const SkPaint & paint,Json::Value * target,UrlDataManager & urlDataManager)1035 static void apply_paint_shader(const SkPaint& paint, Json::Value* target,
1036                                UrlDataManager& urlDataManager) {
1037     SkFlattenable* shader = paint.getShader();
1038     if (shader != nullptr) {
1039         Json::Value jsonShader;
1040         flatten(shader, &jsonShader, urlDataManager);
1041         (*target)[SKDEBUGCANVAS_ATTRIBUTE_SHADER] = jsonShader;
1042     }
1043 }
1044 
apply_paint_xfermode(const SkPaint & paint,Json::Value * target,UrlDataManager & urlDataManager)1045 static void apply_paint_xfermode(const SkPaint& paint, Json::Value* target,
1046                                  UrlDataManager& urlDataManager) {
1047     SkFlattenable* xfermode = paint.getXfermode();
1048     if (xfermode != nullptr) {
1049         Json::Value jsonXfermode;
1050         flatten(xfermode, &jsonXfermode, urlDataManager);
1051         (*target)[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE] = jsonXfermode;
1052     }
1053 }
1054 
apply_paint_imagefilter(const SkPaint & paint,Json::Value * target,UrlDataManager & urlDataManager)1055 static void apply_paint_imagefilter(const SkPaint& paint, Json::Value* target,
1056                                     UrlDataManager& urlDataManager) {
1057     SkFlattenable* imageFilter = paint.getImageFilter();
1058     if (imageFilter != nullptr) {
1059         Json::Value jsonImageFilter;
1060         flatten(imageFilter, &jsonImageFilter, urlDataManager);
1061         (*target)[SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER] = jsonImageFilter;
1062     }
1063 }
1064 
apply_paint_colorfilter(const SkPaint & paint,Json::Value * target,UrlDataManager & urlDataManager)1065 static void apply_paint_colorfilter(const SkPaint& paint, Json::Value* target,
1066                                     UrlDataManager& urlDataManager) {
1067     SkFlattenable* colorFilter = paint.getColorFilter();
1068     if (colorFilter != nullptr) {
1069         Json::Value jsonColorFilter;
1070         flatten(colorFilter, &jsonColorFilter, urlDataManager);
1071         (*target)[SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER] = jsonColorFilter;
1072     }
1073 }
1074 
apply_paint_looper(const SkPaint & paint,Json::Value * target,UrlDataManager & urlDataManager)1075 static void apply_paint_looper(const SkPaint& paint, Json::Value* target,
1076                                UrlDataManager& urlDataManager) {
1077     SkFlattenable* looper = paint.getLooper();
1078     if (looper != nullptr) {
1079         Json::Value jsonLooper;
1080         flatten(looper, &jsonLooper, urlDataManager);
1081         (*target)[SKDEBUGCANVAS_ATTRIBUTE_LOOPER] = jsonLooper;
1082     }
1083 }
1084 
make_json_paint(const SkPaint & paint,UrlDataManager & urlDataManager)1085 Json::Value make_json_paint(const SkPaint& paint, UrlDataManager& urlDataManager) {
1086     Json::Value result(Json::objectValue);
1087     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
1088     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER, paint.getStrokeMiter(),
1089                  SkPaintDefaults_MiterLimit);
1090     store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
1091     store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false);
1092     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE, paint.getTextSize(),
1093                  SkPaintDefaults_TextSize);
1094     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextScaleX(), SK_Scalar1);
1095     store_scalar(&result, SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextSkewX(), 0.0f);
1096     apply_paint_color(paint, &result);
1097     apply_paint_style(paint, &result);
1098     apply_paint_cap(paint, &result);
1099     apply_paint_join(paint, &result);
1100     apply_paint_filterquality(paint, &result);
1101     apply_paint_textalign(paint, &result);
1102     apply_paint_patheffect(paint, &result, urlDataManager);
1103     apply_paint_maskfilter(paint, &result, urlDataManager);
1104     apply_paint_shader(paint, &result, urlDataManager);
1105     apply_paint_xfermode(paint, &result, urlDataManager);
1106     apply_paint_looper(paint, &result, urlDataManager);
1107     apply_paint_imagefilter(paint, &result, urlDataManager);
1108     apply_paint_colorfilter(paint, &result, urlDataManager);
1109     apply_paint_typeface(paint, &result, urlDataManager);
1110     return result;
1111 }
1112 
get_json_point(Json::Value point)1113 static SkPoint get_json_point(Json::Value point) {
1114     return SkPoint::Make(point[0].asFloat(), point[1].asFloat());
1115 }
1116 
get_json_color(Json::Value color)1117 static SkColor get_json_color(Json::Value color) {
1118     return SkColorSetARGB(color[0].asInt(), color[1].asInt(), color[2].asInt(), color[3].asInt());
1119 }
1120 
extract_json_paint_color(Json::Value & jsonPaint,SkPaint * target)1121 static void extract_json_paint_color(Json::Value& jsonPaint, SkPaint* target) {
1122     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLOR)) {
1123         target->setColor(get_json_color(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_COLOR]));
1124     }
1125 }
1126 
extract_json_paint_shader(Json::Value & jsonPaint,UrlDataManager & urlDataManager,SkPaint * target)1127 static void extract_json_paint_shader(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
1128                                       SkPaint* target) {
1129     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_SHADER)) {
1130         Json::Value jsonShader = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_SHADER];
1131         SkShader* shader = (SkShader*) load_flattenable(jsonShader, urlDataManager);
1132         if (shader != nullptr) {
1133             target->setShader(shader);
1134             shader->unref();
1135         }
1136     }
1137 }
1138 
extract_json_paint_patheffect(Json::Value & jsonPaint,UrlDataManager & urlDataManager,SkPaint * target)1139 static void extract_json_paint_patheffect(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
1140                                           SkPaint* target) {
1141     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT)) {
1142         Json::Value jsonPathEffect = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_PATHEFFECT];
1143         SkPathEffect* pathEffect = (SkPathEffect*) load_flattenable(jsonPathEffect, urlDataManager);
1144         if (pathEffect != nullptr) {
1145             target->setPathEffect(pathEffect);
1146             pathEffect->unref();
1147         }
1148     }
1149 }
1150 
extract_json_paint_maskfilter(Json::Value & jsonPaint,UrlDataManager & urlDataManager,SkPaint * target)1151 static void extract_json_paint_maskfilter(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
1152                                           SkPaint* target) {
1153     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER)) {
1154         Json::Value jsonMaskFilter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_MASKFILTER];
1155         SkMaskFilter* maskFilter = (SkMaskFilter*) load_flattenable(jsonMaskFilter, urlDataManager);
1156         if (maskFilter != nullptr) {
1157             target->setMaskFilter(maskFilter);
1158             maskFilter->unref();
1159         }
1160     }
1161 }
1162 
extract_json_paint_colorfilter(Json::Value & jsonPaint,UrlDataManager & urlDataManager,SkPaint * target)1163 static void extract_json_paint_colorfilter(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
1164                                            SkPaint* target) {
1165     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER)) {
1166         Json::Value jsonColorFilter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_COLORFILTER];
1167         SkColorFilter* colorFilter = (SkColorFilter*) load_flattenable(jsonColorFilter,
1168                                                                        urlDataManager);
1169         if (colorFilter != nullptr) {
1170             target->setColorFilter(colorFilter);
1171             colorFilter->unref();
1172         }
1173     }
1174 }
1175 
extract_json_paint_xfermode(Json::Value & jsonPaint,UrlDataManager & urlDataManager,SkPaint * target)1176 static void extract_json_paint_xfermode(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
1177                                         SkPaint* target) {
1178     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_XFERMODE)) {
1179         Json::Value jsonXfermode = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE];
1180         SkXfermode* xfermode = (SkXfermode*) load_flattenable(jsonXfermode, urlDataManager);
1181         if (xfermode != nullptr) {
1182             target->setXfermode(xfermode);
1183             xfermode->unref();
1184         }
1185     }
1186 }
1187 
extract_json_paint_looper(Json::Value & jsonPaint,UrlDataManager & urlDataManager,SkPaint * target)1188 static void extract_json_paint_looper(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
1189                                       SkPaint* target) {
1190     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_LOOPER)) {
1191         Json::Value jsonLooper = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_LOOPER];
1192         SkDrawLooper* looper = (SkDrawLooper*) load_flattenable(jsonLooper, urlDataManager);
1193         if (looper != nullptr) {
1194             target->setLooper(looper);
1195             looper->unref();
1196         }
1197     }
1198 }
1199 
extract_json_paint_imagefilter(Json::Value & jsonPaint,UrlDataManager & urlDataManager,SkPaint * target)1200 static void extract_json_paint_imagefilter(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
1201                                            SkPaint* target) {
1202     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER)) {
1203         Json::Value jsonImageFilter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_IMAGEFILTER];
1204         SkImageFilter* imageFilter = (SkImageFilter*) load_flattenable(jsonImageFilter,
1205                                                                        urlDataManager);
1206         if (imageFilter != nullptr) {
1207             target->setImageFilter(imageFilter);
1208             imageFilter->unref();
1209         }
1210     }
1211 }
1212 
extract_json_paint_typeface(Json::Value & jsonPaint,UrlDataManager & urlDataManager,SkPaint * target)1213 static void extract_json_paint_typeface(Json::Value& jsonPaint, UrlDataManager& urlDataManager,
1214                                         SkPaint* target) {
1215     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE)) {
1216         Json::Value jsonTypeface = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TYPEFACE];
1217         Json::Value jsonData = jsonTypeface[SKDEBUGCANVAS_ATTRIBUTE_DATA];
1218         const void* data;
1219         Json::ArrayIndex length = decode_data(jsonData, urlDataManager, &data);
1220         SkMemoryStream buffer(data, length);
1221         SkTypeface* typeface = SkTypeface::Deserialize(&buffer);
1222         target->setTypeface(typeface);
1223     }
1224 }
1225 
extract_json_paint_style(Json::Value & jsonPaint,SkPaint * target)1226 static void extract_json_paint_style(Json::Value& jsonPaint, SkPaint* target) {
1227     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STYLE)) {
1228         const char* style = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STYLE].asCString();
1229         if (!strcmp(style, SKDEBUGCANVAS_STYLE_FILL)) {
1230             target->setStyle(SkPaint::kFill_Style);
1231         }
1232         else if (!strcmp(style, SKDEBUGCANVAS_STYLE_STROKE)) {
1233             target->setStyle(SkPaint::kStroke_Style);
1234         }
1235         else if (!strcmp(style, SKDEBUGCANVAS_STYLE_STROKEANDFILL)) {
1236             target->setStyle(SkPaint::kStrokeAndFill_Style);
1237         }
1238     }
1239 }
1240 
extract_json_paint_strokewidth(Json::Value & jsonPaint,SkPaint * target)1241 static void extract_json_paint_strokewidth(Json::Value& jsonPaint, SkPaint* target) {
1242     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH)) {
1243         float strokeWidth = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STROKEWIDTH].asFloat();
1244         target->setStrokeWidth(strokeWidth);
1245     }
1246 }
1247 
extract_json_paint_strokemiter(Json::Value & jsonPaint,SkPaint * target)1248 static void extract_json_paint_strokemiter(Json::Value& jsonPaint, SkPaint* target) {
1249     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER)) {
1250         float strokeMiter = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STROKEMITER].asFloat();
1251         target->setStrokeMiter(strokeMiter);
1252     }
1253 }
1254 
extract_json_paint_strokejoin(Json::Value & jsonPaint,SkPaint * target)1255 static void extract_json_paint_strokejoin(Json::Value& jsonPaint, SkPaint* target) {
1256     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN)) {
1257         const char* join = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_STROKEJOIN].asCString();
1258         if (!strcmp(join, SKDEBUGCANVAS_MITER_JOIN)) {
1259             target->setStrokeJoin(SkPaint::kMiter_Join);
1260         }
1261         else if (!strcmp(join, SKDEBUGCANVAS_ROUND_JOIN)) {
1262             target->setStrokeJoin(SkPaint::kRound_Join);
1263         }
1264         else if (!strcmp(join, SKDEBUGCANVAS_BEVEL_JOIN)) {
1265             target->setStrokeJoin(SkPaint::kBevel_Join);
1266         }
1267         else {
1268             SkASSERT(false);
1269         }
1270     }
1271 }
1272 
extract_json_paint_cap(Json::Value & jsonPaint,SkPaint * target)1273 static void extract_json_paint_cap(Json::Value& jsonPaint, SkPaint* target) {
1274     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_CAP)) {
1275         const char* cap = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_CAP].asCString();
1276         if (!strcmp(cap, SKDEBUGCANVAS_CAP_BUTT)) {
1277             target->setStrokeCap(SkPaint::kButt_Cap);
1278         }
1279         else if (!strcmp(cap, SKDEBUGCANVAS_CAP_ROUND)) {
1280             target->setStrokeCap(SkPaint::kRound_Cap);
1281         }
1282         else if (!strcmp(cap, SKDEBUGCANVAS_CAP_SQUARE)) {
1283             target->setStrokeCap(SkPaint::kSquare_Cap);
1284         }
1285     }
1286 }
1287 
extract_json_paint_filterquality(Json::Value & jsonPaint,SkPaint * target)1288 static void extract_json_paint_filterquality(Json::Value& jsonPaint, SkPaint* target) {
1289     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY)) {
1290         const char* quality = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_FILTERQUALITY].asCString();
1291         if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_NONE)) {
1292             target->setFilterQuality(kNone_SkFilterQuality);
1293         }
1294         else if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_LOW)) {
1295             target->setFilterQuality(kLow_SkFilterQuality);
1296         }
1297         else if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_MEDIUM)) {
1298             target->setFilterQuality(kMedium_SkFilterQuality);
1299         }
1300         else if (!strcmp(quality, SKDEBUGCANVAS_FILTERQUALITY_HIGH)) {
1301             target->setFilterQuality(kHigh_SkFilterQuality);
1302         }
1303     }
1304 }
1305 
extract_json_paint_antialias(Json::Value & jsonPaint,SkPaint * target)1306 static void extract_json_paint_antialias(Json::Value& jsonPaint, SkPaint* target) {
1307     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS)) {
1308         target->setAntiAlias(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
1309     }
1310 }
1311 
extract_json_paint_dither(Json::Value & jsonPaint,SkPaint * target)1312 static void extract_json_paint_dither(Json::Value& jsonPaint, SkPaint* target) {
1313     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_DITHER)) {
1314         target->setDither(jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_DITHER].asBool());
1315     }
1316 }
1317 
extract_json_paint_blur(Json::Value & jsonPaint,SkPaint * target)1318 static void extract_json_paint_blur(Json::Value& jsonPaint, SkPaint* target) {
1319     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_BLUR)) {
1320         Json::Value blur = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_BLUR];
1321         SkScalar sigma = blur[SKDEBUGCANVAS_ATTRIBUTE_SIGMA].asFloat();
1322         SkBlurStyle style;
1323         const char* jsonStyle = blur[SKDEBUGCANVAS_ATTRIBUTE_STYLE].asCString();
1324         if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_NORMAL)) {
1325             style = SkBlurStyle::kNormal_SkBlurStyle;
1326         }
1327         else if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_SOLID)) {
1328             style = SkBlurStyle::kSolid_SkBlurStyle;
1329         }
1330         else if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_OUTER)) {
1331             style = SkBlurStyle::kOuter_SkBlurStyle;
1332         }
1333         else if (!strcmp(jsonStyle, SKDEBUGCANVAS_BLURSTYLE_INNER)) {
1334             style = SkBlurStyle::kInner_SkBlurStyle;
1335         }
1336         else {
1337             SkASSERT(false);
1338             style = SkBlurStyle::kNormal_SkBlurStyle;
1339         }
1340         SkBlurMaskFilter::BlurFlags flags;
1341         const char* jsonQuality = blur[SKDEBUGCANVAS_ATTRIBUTE_QUALITY].asCString();
1342         if (!strcmp(jsonQuality, SKDEBUGCANVAS_BLURQUALITY_LOW)) {
1343             flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
1344         }
1345         else if (!strcmp(jsonQuality, SKDEBUGCANVAS_BLURQUALITY_HIGH)) {
1346             flags = SkBlurMaskFilter::BlurFlags::kHighQuality_BlurFlag;
1347         }
1348         else {
1349             SkASSERT(false);
1350             flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
1351         }
1352         target->setMaskFilter(SkBlurMaskFilter::Create(style, sigma, flags));
1353     }
1354 }
1355 
extract_json_paint_dashing(Json::Value & jsonPaint,SkPaint * target)1356 static void extract_json_paint_dashing(Json::Value& jsonPaint, SkPaint* target) {
1357     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_DASHING)) {
1358         Json::Value dash = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_DASHING];
1359         Json::Value jsonIntervals = dash[SKDEBUGCANVAS_ATTRIBUTE_INTERVALS];
1360         Json::ArrayIndex count = jsonIntervals.size();
1361         SkScalar* intervals = (SkScalar*) sk_malloc_throw(count * sizeof(SkScalar));
1362         for (Json::ArrayIndex i = 0; i < count; i++) {
1363             intervals[i] = jsonIntervals[i].asFloat();
1364         }
1365         SkScalar phase = dash[SKDEBUGCANVAS_ATTRIBUTE_PHASE].asFloat();
1366         target->setPathEffect(SkDashPathEffect::Create(intervals, count, phase));
1367         sk_free(intervals);
1368     }
1369 }
1370 
extract_json_paint_textalign(Json::Value & jsonPaint,SkPaint * target)1371 static void extract_json_paint_textalign(Json::Value& jsonPaint, SkPaint* target) {
1372     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN)) {
1373         SkPaint::Align textAlign;
1374         const char* jsonAlign = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTALIGN].asCString();
1375         if (!strcmp(jsonAlign, SKDEBUGCANVAS_ALIGN_LEFT)) {
1376             textAlign = SkPaint::kLeft_Align;
1377         }
1378         else if (!strcmp(jsonAlign, SKDEBUGCANVAS_ALIGN_CENTER)) {
1379             textAlign = SkPaint::kCenter_Align;
1380         }
1381         else if (!strcmp(jsonAlign, SKDEBUGCANVAS_ALIGN_RIGHT)) {
1382             textAlign = SkPaint::kRight_Align;
1383         }
1384         else {
1385             SkASSERT(false);
1386             textAlign = SkPaint::kLeft_Align;
1387         }
1388         target->setTextAlign(textAlign);
1389     }
1390 }
1391 
extract_json_paint_textsize(Json::Value & jsonPaint,SkPaint * target)1392 static void extract_json_paint_textsize(Json::Value& jsonPaint, SkPaint* target) {
1393     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE)) {
1394         float textSize = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTSIZE].asFloat();
1395         target->setTextSize(textSize);
1396     }
1397 }
1398 
extract_json_paint_textscalex(Json::Value & jsonPaint,SkPaint * target)1399 static void extract_json_paint_textscalex(Json::Value& jsonPaint, SkPaint* target) {
1400     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX)) {
1401         float textScaleX = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTSCALEX].asFloat();
1402         target->setTextScaleX(textScaleX);
1403     }
1404 }
1405 
extract_json_paint_textskewx(Json::Value & jsonPaint,SkPaint * target)1406 static void extract_json_paint_textskewx(Json::Value& jsonPaint, SkPaint* target) {
1407     if (jsonPaint.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX)) {
1408         float textSkewX = jsonPaint[SKDEBUGCANVAS_ATTRIBUTE_TEXTSKEWX].asFloat();
1409         target->setTextSkewX(textSkewX);
1410     }
1411 }
1412 
extract_json_paint(Json::Value & paint,UrlDataManager & urlDataManager,SkPaint * result)1413 static void extract_json_paint(Json::Value& paint, UrlDataManager& urlDataManager,
1414                                SkPaint* result) {
1415     extract_json_paint_color(paint, result);
1416     extract_json_paint_shader(paint, urlDataManager, result);
1417     extract_json_paint_patheffect(paint, urlDataManager, result);
1418     extract_json_paint_maskfilter(paint, urlDataManager, result);
1419     extract_json_paint_colorfilter(paint, urlDataManager, result);
1420     extract_json_paint_xfermode(paint, urlDataManager, result);
1421     extract_json_paint_looper(paint, urlDataManager, result);
1422     extract_json_paint_imagefilter(paint, urlDataManager, result);
1423     extract_json_paint_typeface(paint, urlDataManager, result);
1424     extract_json_paint_style(paint, result);
1425     extract_json_paint_strokewidth(paint, result);
1426     extract_json_paint_strokemiter(paint, result);
1427     extract_json_paint_strokejoin(paint, result);
1428     extract_json_paint_cap(paint, result);
1429     extract_json_paint_filterquality(paint, result);
1430     extract_json_paint_antialias(paint, result);
1431     extract_json_paint_dither(paint, result);
1432     extract_json_paint_blur(paint, result);
1433     extract_json_paint_dashing(paint, result);
1434     extract_json_paint_textalign(paint, result);
1435     extract_json_paint_textsize(paint, result);
1436     extract_json_paint_textscalex(paint, result);
1437     extract_json_paint_textskewx(paint, result);
1438 }
1439 
extract_json_rect(Json::Value & rect,SkRect * result)1440 static void extract_json_rect(Json::Value& rect, SkRect* result) {
1441     result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3].asFloat());
1442 }
1443 
extract_json_irect(Json::Value & rect,SkIRect * result)1444 static void extract_json_irect(Json::Value& rect, SkIRect* result) {
1445     result->set(rect[0].asInt(), rect[1].asInt(), rect[2].asInt(), rect[3].asInt());
1446 }
1447 
extract_json_rrect(Json::Value & rrect,SkRRect * result)1448 static void extract_json_rrect(Json::Value& rrect, SkRRect* result) {
1449     SkVector radii[4] = {
1450                             { rrect[1][0].asFloat(), rrect[1][1].asFloat() },
1451                             { rrect[2][0].asFloat(), rrect[2][1].asFloat() },
1452                             { rrect[3][0].asFloat(), rrect[3][1].asFloat() },
1453                             { rrect[4][0].asFloat(), rrect[4][1].asFloat() }
1454                         };
1455     result->setRectRadii(SkRect::MakeLTRB(rrect[0][0].asFloat(), rrect[0][1].asFloat(),
1456                                           rrect[0][2].asFloat(), rrect[0][3].asFloat()),
1457                                           radii);
1458 }
1459 
extract_json_matrix(Json::Value & matrix,SkMatrix * result)1460 static void extract_json_matrix(Json::Value& matrix, SkMatrix* result) {
1461     SkScalar values[] = {
1462         matrix[0][0].asFloat(), matrix[0][1].asFloat(), matrix[0][2].asFloat(),
1463         matrix[1][0].asFloat(), matrix[1][1].asFloat(), matrix[1][2].asFloat(),
1464         matrix[2][0].asFloat(), matrix[2][1].asFloat(), matrix[2][2].asFloat()
1465     };
1466     result->set9(values);
1467 }
1468 
extract_json_path(Json::Value & path,SkPath * result)1469 static void extract_json_path(Json::Value& path, SkPath* result) {
1470     const char* fillType = path[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE].asCString();
1471     if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_WINDING)) {
1472         result->setFillType(SkPath::kWinding_FillType);
1473     }
1474     else if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_EVENODD)) {
1475         result->setFillType(SkPath::kEvenOdd_FillType);
1476     }
1477     else if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_INVERSEWINDING)) {
1478         result->setFillType(SkPath::kInverseWinding_FillType);
1479     }
1480     else if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_INVERSEEVENODD)) {
1481         result->setFillType(SkPath::kInverseEvenOdd_FillType);
1482     }
1483     Json::Value verbs = path[SKDEBUGCANVAS_ATTRIBUTE_VERBS];
1484     for (Json::ArrayIndex i = 0; i < verbs.size(); i++) {
1485         Json::Value verb = verbs[i];
1486         if (verb.isString()) {
1487             SkASSERT(!strcmp(verb.asCString(), SKDEBUGCANVAS_VERB_CLOSE));
1488             result->close();
1489         }
1490         else {
1491             if (verb.isMember(SKDEBUGCANVAS_VERB_MOVE)) {
1492                 Json::Value move = verb[SKDEBUGCANVAS_VERB_MOVE];
1493                 result->moveTo(move[0].asFloat(), move[1].asFloat());
1494             }
1495             else if (verb.isMember(SKDEBUGCANVAS_VERB_LINE)) {
1496                 Json::Value line = verb[SKDEBUGCANVAS_VERB_LINE];
1497                 result->lineTo(line[0].asFloat(), line[1].asFloat());
1498             }
1499             else if (verb.isMember(SKDEBUGCANVAS_VERB_QUAD)) {
1500                 Json::Value quad = verb[SKDEBUGCANVAS_VERB_QUAD];
1501                 result->quadTo(quad[0][0].asFloat(), quad[0][1].asFloat(),
1502                                quad[1][0].asFloat(), quad[1][1].asFloat());
1503             }
1504             else if (verb.isMember(SKDEBUGCANVAS_VERB_CUBIC)) {
1505                 Json::Value cubic = verb[SKDEBUGCANVAS_VERB_CUBIC];
1506                 result->cubicTo(cubic[0][0].asFloat(), cubic[0][1].asFloat(),
1507                                 cubic[1][0].asFloat(), cubic[1][1].asFloat(),
1508                                 cubic[2][0].asFloat(), cubic[2][1].asFloat());
1509             }
1510             else if (verb.isMember(SKDEBUGCANVAS_VERB_CONIC)) {
1511                 Json::Value conic = verb[SKDEBUGCANVAS_VERB_CONIC];
1512                 result->conicTo(conic[0][0].asFloat(), conic[0][1].asFloat(),
1513                                 conic[1][0].asFloat(), conic[1][1].asFloat(),
1514                                 conic[2].asFloat());
1515             }
1516             else {
1517                 SkASSERT(false);
1518             }
1519         }
1520     }
1521 }
1522 
get_json_regionop(Json::Value & jsonOp)1523 SkRegion::Op get_json_regionop(Json::Value& jsonOp) {
1524     const char* op = jsonOp.asCString();
1525     if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_DIFFERENCE)) {
1526         return SkRegion::kDifference_Op;
1527     }
1528     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_INTERSECT)) {
1529         return SkRegion::kIntersect_Op;
1530     }
1531     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_UNION)) {
1532         return SkRegion::kUnion_Op;
1533     }
1534     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_XOR)) {
1535         return SkRegion::kXOR_Op;
1536     }
1537     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_REVERSE_DIFFERENCE)) {
1538         return SkRegion::kReverseDifference_Op;
1539     }
1540     else if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_REPLACE)) {
1541         return SkRegion::kReplace_Op;
1542     }
1543     SkASSERT(false);
1544     return SkRegion::kIntersect_Op;
1545 }
1546 
SkClearCommand(SkColor color)1547 SkClearCommand::SkClearCommand(SkColor color) : INHERITED(kDrawClear_OpType) {
1548     fColor = color;
1549     fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
1550 }
1551 
execute(SkCanvas * canvas) const1552 void SkClearCommand::execute(SkCanvas* canvas) const {
1553     canvas->clear(fColor);
1554 }
1555 
toJSON(UrlDataManager & urlDataManager) const1556 Json::Value SkClearCommand::toJSON(UrlDataManager& urlDataManager) const {
1557     Json::Value result = INHERITED::toJSON(urlDataManager);
1558     result[SKDEBUGCANVAS_ATTRIBUTE_COLOR] = make_json_color(fColor);
1559     return result;
1560 }
1561 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1562  SkClearCommand* SkClearCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
1563     Json::Value color = command[SKDEBUGCANVAS_ATTRIBUTE_COLOR];
1564     return new SkClearCommand(get_json_color(color));
1565 }
1566 
SkClipPathCommand(const SkPath & path,SkRegion::Op op,bool doAA)1567 SkClipPathCommand::SkClipPathCommand(const SkPath& path, SkRegion::Op op, bool doAA)
1568     : INHERITED(kClipPath_OpType) {
1569     fPath = path;
1570     fOp = op;
1571     fDoAA = doAA;
1572 
1573     fInfo.push(SkObjectParser::PathToString(path));
1574     fInfo.push(SkObjectParser::RegionOpToString(op));
1575     fInfo.push(SkObjectParser::BoolToString(doAA));
1576 }
1577 
execute(SkCanvas * canvas) const1578 void SkClipPathCommand::execute(SkCanvas* canvas) const {
1579     canvas->clipPath(fPath, fOp, fDoAA);
1580 }
1581 
render(SkCanvas * canvas) const1582 bool SkClipPathCommand::render(SkCanvas* canvas) const {
1583     render_path(canvas, fPath);
1584     return true;
1585 }
1586 
toJSON(UrlDataManager & urlDataManager) const1587 Json::Value SkClipPathCommand::toJSON(UrlDataManager& urlDataManager) const {
1588     Json::Value result = INHERITED::toJSON(urlDataManager);
1589     result[SKDEBUGCANVAS_ATTRIBUTE_PATH] = make_json_path(fPath);
1590     result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
1591     result[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS] = fDoAA;
1592     return result;
1593 }
1594 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1595 SkClipPathCommand* SkClipPathCommand::fromJSON(Json::Value& command,
1596                                                UrlDataManager& urlDataManager) {
1597     SkPath path;
1598     extract_json_path(command[SKDEBUGCANVAS_ATTRIBUTE_PATH], &path);
1599     return new SkClipPathCommand(path, get_json_regionop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]),
1600                                  command[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
1601 }
1602 
SkClipRegionCommand(const SkRegion & region,SkRegion::Op op)1603 SkClipRegionCommand::SkClipRegionCommand(const SkRegion& region, SkRegion::Op op)
1604     : INHERITED(kClipRegion_OpType) {
1605     fRegion = region;
1606     fOp = op;
1607 
1608     fInfo.push(SkObjectParser::RegionToString(region));
1609     fInfo.push(SkObjectParser::RegionOpToString(op));
1610 }
1611 
execute(SkCanvas * canvas) const1612 void SkClipRegionCommand::execute(SkCanvas* canvas) const {
1613     canvas->clipRegion(fRegion, fOp);
1614 }
1615 
toJSON(UrlDataManager & urlDataManager) const1616 Json::Value SkClipRegionCommand::toJSON(UrlDataManager& urlDataManager) const {
1617     Json::Value result = INHERITED::toJSON(urlDataManager);
1618     result[SKDEBUGCANVAS_ATTRIBUTE_REGION] = make_json_region(fRegion);
1619     result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
1620     return result;
1621 }
1622 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1623 SkClipRegionCommand* SkClipRegionCommand::fromJSON(Json::Value& command,
1624                                                    UrlDataManager& urlDataManager) {
1625     SkASSERT(false);
1626     return nullptr;
1627 }
1628 
SkClipRectCommand(const SkRect & rect,SkRegion::Op op,bool doAA)1629 SkClipRectCommand::SkClipRectCommand(const SkRect& rect, SkRegion::Op op, bool doAA)
1630     : INHERITED(kClipRect_OpType) {
1631     fRect = rect;
1632     fOp = op;
1633     fDoAA = doAA;
1634 
1635     fInfo.push(SkObjectParser::RectToString(rect));
1636     fInfo.push(SkObjectParser::RegionOpToString(op));
1637     fInfo.push(SkObjectParser::BoolToString(doAA));
1638 }
1639 
execute(SkCanvas * canvas) const1640 void SkClipRectCommand::execute(SkCanvas* canvas) const {
1641     canvas->clipRect(fRect, fOp, fDoAA);
1642 }
1643 
toJSON(UrlDataManager & urlDataManager) const1644 Json::Value SkClipRectCommand::toJSON(UrlDataManager& urlDataManager) const {
1645     Json::Value result = INHERITED::toJSON(urlDataManager);
1646     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rect(fRect);
1647     result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
1648     result[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS] = Json::Value(fDoAA);
1649     return result;
1650 }
1651 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1652 SkClipRectCommand* SkClipRectCommand::fromJSON(Json::Value& command,
1653                                                UrlDataManager& urlDataManager) {
1654     SkRect rect;
1655     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &rect);
1656     return new SkClipRectCommand(rect, get_json_regionop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]),
1657                                  command[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
1658 }
1659 
SkClipRRectCommand(const SkRRect & rrect,SkRegion::Op op,bool doAA)1660 SkClipRRectCommand::SkClipRRectCommand(const SkRRect& rrect, SkRegion::Op op, bool doAA)
1661     : INHERITED(kClipRRect_OpType) {
1662     fRRect = rrect;
1663     fOp = op;
1664     fDoAA = doAA;
1665 
1666     fInfo.push(SkObjectParser::RRectToString(rrect));
1667     fInfo.push(SkObjectParser::RegionOpToString(op));
1668     fInfo.push(SkObjectParser::BoolToString(doAA));
1669 }
1670 
execute(SkCanvas * canvas) const1671 void SkClipRRectCommand::execute(SkCanvas* canvas) const {
1672     canvas->clipRRect(fRRect, fOp, fDoAA);
1673 }
1674 
render(SkCanvas * canvas) const1675 bool SkClipRRectCommand::render(SkCanvas* canvas) const {
1676     render_rrect(canvas, fRRect);
1677     return true;
1678 }
1679 
toJSON(UrlDataManager & urlDataManager) const1680 Json::Value SkClipRRectCommand::toJSON(UrlDataManager& urlDataManager) const {
1681     Json::Value result = INHERITED::toJSON(urlDataManager);
1682     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rrect(fRRect);
1683     result[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP] = make_json_regionop(fOp);
1684     result[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS] = Json::Value(fDoAA);
1685     return result;
1686 }
1687 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1688 SkClipRRectCommand* SkClipRRectCommand::fromJSON(Json::Value& command,
1689                                                  UrlDataManager& urlDataManager) {
1690     SkRRect rrect;
1691     extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &rrect);
1692     return new SkClipRRectCommand(rrect,
1693                                   get_json_regionop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]),
1694                                   command[SKDEBUGCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
1695 }
1696 
SkConcatCommand(const SkMatrix & matrix)1697 SkConcatCommand::SkConcatCommand(const SkMatrix& matrix)
1698     : INHERITED(kConcat_OpType) {
1699     fMatrix = matrix;
1700 
1701     fInfo.push(SkObjectParser::MatrixToString(matrix));
1702 }
1703 
execute(SkCanvas * canvas) const1704 void SkConcatCommand::execute(SkCanvas* canvas) const {
1705     canvas->concat(fMatrix);
1706 }
1707 
toJSON(UrlDataManager & urlDataManager) const1708 Json::Value SkConcatCommand::toJSON(UrlDataManager& urlDataManager) const {
1709     Json::Value result = INHERITED::toJSON(urlDataManager);
1710     result[SKDEBUGCANVAS_ATTRIBUTE_MATRIX] = make_json_matrix(fMatrix);
1711     return result;
1712 }
1713 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1714 SkConcatCommand* SkConcatCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
1715     SkMatrix matrix;
1716     extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
1717     return new SkConcatCommand(matrix);
1718 }
1719 
SkDrawBitmapCommand(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)1720 SkDrawBitmapCommand::SkDrawBitmapCommand(const SkBitmap& bitmap, SkScalar left, SkScalar top,
1721                                          const SkPaint* paint)
1722     : INHERITED(kDrawBitmap_OpType) {
1723     fBitmap = bitmap;
1724     fLeft = left;
1725     fTop = top;
1726     if (paint) {
1727         fPaint = *paint;
1728         fPaintPtr = &fPaint;
1729     } else {
1730         fPaintPtr = nullptr;
1731     }
1732 
1733     fInfo.push(SkObjectParser::BitmapToString(bitmap));
1734     fInfo.push(SkObjectParser::ScalarToString(left, "SkScalar left: "));
1735     fInfo.push(SkObjectParser::ScalarToString(top, "SkScalar top: "));
1736     if (paint) {
1737         fInfo.push(SkObjectParser::PaintToString(*paint));
1738     }
1739 }
1740 
execute(SkCanvas * canvas) const1741 void SkDrawBitmapCommand::execute(SkCanvas* canvas) const {
1742     canvas->drawBitmap(fBitmap, fLeft, fTop, fPaintPtr);
1743 }
1744 
render(SkCanvas * canvas) const1745 bool SkDrawBitmapCommand::render(SkCanvas* canvas) const {
1746     render_bitmap(canvas, fBitmap);
1747     return true;
1748 }
1749 
toJSON(UrlDataManager & urlDataManager) const1750 Json::Value SkDrawBitmapCommand::toJSON(UrlDataManager& urlDataManager) const {
1751     Json::Value result = INHERITED::toJSON(urlDataManager);
1752     Json::Value encoded;
1753     if (flatten(fBitmap, &encoded, urlDataManager)) {
1754         Json::Value command(Json::objectValue);
1755         result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
1756         result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_point(fLeft, fTop);
1757         if (fPaintPtr != nullptr) {
1758             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaintPtr, urlDataManager);
1759         }
1760     }
1761     return result;
1762 }
1763 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1764 SkDrawBitmapCommand* SkDrawBitmapCommand::fromJSON(Json::Value& command,
1765                                                    UrlDataManager& urlDataManager) {
1766     SkBitmap* bitmap = load_bitmap(command[SKDEBUGCANVAS_ATTRIBUTE_BITMAP], urlDataManager);
1767     if (bitmap == nullptr) {
1768         return nullptr;
1769     }
1770     Json::Value point = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
1771     SkPaint* paintPtr;
1772     SkPaint paint;
1773     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
1774         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
1775         paintPtr = &paint;
1776     }
1777     else {
1778         paintPtr = nullptr;
1779     }
1780     SkDrawBitmapCommand* result = new SkDrawBitmapCommand(*bitmap, point[0].asFloat(),
1781                                                           point[1].asFloat(), paintPtr);
1782     delete bitmap;
1783     return result;
1784 }
1785 
SkDrawBitmapNineCommand(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1786 SkDrawBitmapNineCommand::SkDrawBitmapNineCommand(const SkBitmap& bitmap, const SkIRect& center,
1787                                                  const SkRect& dst, const SkPaint* paint)
1788     : INHERITED(kDrawBitmapNine_OpType) {
1789     fBitmap = bitmap;
1790     fCenter = center;
1791     fDst = dst;
1792     if (paint) {
1793         fPaint = *paint;
1794         fPaintPtr = &fPaint;
1795     } else {
1796         fPaintPtr = nullptr;
1797     }
1798 
1799     fInfo.push(SkObjectParser::BitmapToString(bitmap));
1800     fInfo.push(SkObjectParser::IRectToString(center));
1801     fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
1802     if (paint) {
1803         fInfo.push(SkObjectParser::PaintToString(*paint));
1804     }
1805 }
1806 
execute(SkCanvas * canvas) const1807 void SkDrawBitmapNineCommand::execute(SkCanvas* canvas) const {
1808     canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaintPtr);
1809 }
1810 
render(SkCanvas * canvas) const1811 bool SkDrawBitmapNineCommand::render(SkCanvas* canvas) const {
1812     SkRect tmp = SkRect::Make(fCenter);
1813     render_bitmap(canvas, fBitmap, &tmp);
1814     return true;
1815 }
1816 
toJSON(UrlDataManager & urlDataManager) const1817 Json::Value SkDrawBitmapNineCommand::toJSON(UrlDataManager& urlDataManager) const {
1818     Json::Value result = INHERITED::toJSON(urlDataManager);
1819     Json::Value encoded;
1820     if (flatten(fBitmap, &encoded, urlDataManager)) {
1821         result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
1822         result[SKDEBUGCANVAS_ATTRIBUTE_CENTER] = make_json_irect(fCenter);
1823         result[SKDEBUGCANVAS_ATTRIBUTE_DST] = make_json_rect(fDst);
1824         if (fPaintPtr != nullptr) {
1825             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaintPtr, urlDataManager);
1826         }
1827     }
1828     return result;
1829 }
1830 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1831 SkDrawBitmapNineCommand* SkDrawBitmapNineCommand::fromJSON(Json::Value& command,
1832                                                            UrlDataManager& urlDataManager) {
1833     SkBitmap* bitmap = load_bitmap(command[SKDEBUGCANVAS_ATTRIBUTE_BITMAP], urlDataManager);
1834     if (bitmap == nullptr) {
1835         return nullptr;
1836     }
1837     SkIRect center;
1838     extract_json_irect(command[SKDEBUGCANVAS_ATTRIBUTE_CENTER], &center);
1839     SkRect dst;
1840     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
1841     SkPaint* paintPtr;
1842     SkPaint paint;
1843     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
1844         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
1845         paintPtr = &paint;
1846     }
1847     else {
1848         paintPtr = nullptr;
1849     }
1850     SkDrawBitmapNineCommand* result = new SkDrawBitmapNineCommand(*bitmap, center, dst, paintPtr);
1851     delete bitmap;
1852     return result;
1853 }
1854 
SkDrawBitmapRectCommand(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)1855 SkDrawBitmapRectCommand::SkDrawBitmapRectCommand(const SkBitmap& bitmap, const SkRect* src,
1856                                                  const SkRect& dst, const SkPaint* paint,
1857                                                  SkCanvas::SrcRectConstraint constraint)
1858     : INHERITED(kDrawBitmapRect_OpType) {
1859     fBitmap = bitmap;
1860     if (src) {
1861         fSrc = *src;
1862     } else {
1863         fSrc.setEmpty();
1864     }
1865     fDst = dst;
1866 
1867     if (paint) {
1868         fPaint = *paint;
1869         fPaintPtr = &fPaint;
1870     } else {
1871         fPaintPtr = nullptr;
1872     }
1873     fConstraint = constraint;
1874 
1875     fInfo.push(SkObjectParser::BitmapToString(bitmap));
1876     if (src) {
1877         fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
1878     }
1879     fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
1880     if (paint) {
1881         fInfo.push(SkObjectParser::PaintToString(*paint));
1882     }
1883     fInfo.push(SkObjectParser::IntToString(fConstraint, "Constraint: "));
1884 }
1885 
execute(SkCanvas * canvas) const1886 void SkDrawBitmapRectCommand::execute(SkCanvas* canvas) const {
1887     canvas->legacy_drawBitmapRect(fBitmap, this->srcRect(), fDst, fPaintPtr, fConstraint);
1888 }
1889 
render(SkCanvas * canvas) const1890 bool SkDrawBitmapRectCommand::render(SkCanvas* canvas) const {
1891     render_bitmap(canvas, fBitmap, this->srcRect());
1892     return true;
1893 }
1894 
toJSON(UrlDataManager & urlDataManager) const1895 Json::Value SkDrawBitmapRectCommand::toJSON(UrlDataManager& urlDataManager) const {
1896     Json::Value result = INHERITED::toJSON(urlDataManager);
1897     Json::Value encoded;
1898     if (flatten(fBitmap, &encoded, urlDataManager)) {
1899         result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
1900         if (!fSrc.isEmpty()) {
1901             result[SKDEBUGCANVAS_ATTRIBUTE_SRC] = make_json_rect(fSrc);
1902         }
1903         result[SKDEBUGCANVAS_ATTRIBUTE_DST] = make_json_rect(fDst);
1904         if (fPaintPtr != nullptr) {
1905             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaintPtr, urlDataManager);
1906         }
1907         if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
1908             result[SKDEBUGCANVAS_ATTRIBUTE_STRICT] = Json::Value(true);
1909         }
1910     }
1911     return result;
1912 }
1913 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1914 SkDrawBitmapRectCommand* SkDrawBitmapRectCommand::fromJSON(Json::Value& command,
1915                                                            UrlDataManager& urlDataManager) {
1916     SkBitmap* bitmap = load_bitmap(command[SKDEBUGCANVAS_ATTRIBUTE_BITMAP], urlDataManager);
1917     if (bitmap == nullptr) {
1918         return nullptr;
1919     }
1920     SkRect dst;
1921     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
1922     SkPaint* paintPtr;
1923     SkPaint paint;
1924     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
1925         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
1926         paintPtr = &paint;
1927     }
1928     else {
1929         paintPtr = nullptr;
1930     }
1931     SkCanvas::SrcRectConstraint constraint;
1932     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_STRICT) &&
1933         command[SKDEBUGCANVAS_ATTRIBUTE_STRICT].asBool()) {
1934         constraint = SkCanvas::kStrict_SrcRectConstraint;
1935     }
1936     else {
1937         constraint = SkCanvas::kFast_SrcRectConstraint;
1938     }
1939     SkRect* srcPtr;
1940     SkRect src;
1941     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_SRC)) {
1942         extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_SRC], &src);
1943         srcPtr = &src;
1944     }
1945     else {
1946         srcPtr = nullptr;
1947     }
1948     SkDrawBitmapRectCommand* result = new SkDrawBitmapRectCommand(*bitmap, srcPtr, dst, paintPtr,
1949                                                                   constraint);
1950     delete bitmap;
1951     return result;
1952 }
1953 
SkDrawImageCommand(const SkImage * image,SkScalar left,SkScalar top,const SkPaint * paint)1954 SkDrawImageCommand::SkDrawImageCommand(const SkImage* image, SkScalar left, SkScalar top,
1955                                        const SkPaint* paint)
1956     : INHERITED(kDrawImage_OpType)
1957     , fImage(SkRef(image))
1958     , fLeft(left)
1959     , fTop(top) {
1960 
1961     fInfo.push(SkObjectParser::ImageToString(image));
1962     fInfo.push(SkObjectParser::ScalarToString(left, "Left: "));
1963     fInfo.push(SkObjectParser::ScalarToString(top, "Top: "));
1964 
1965     if (paint) {
1966         fPaint.set(*paint);
1967         fInfo.push(SkObjectParser::PaintToString(*paint));
1968     }
1969 }
1970 
execute(SkCanvas * canvas) const1971 void SkDrawImageCommand::execute(SkCanvas* canvas) const {
1972     canvas->drawImage(fImage, fLeft, fTop, fPaint.getMaybeNull());
1973 }
1974 
render(SkCanvas * canvas) const1975 bool SkDrawImageCommand::render(SkCanvas* canvas) const {
1976     SkAutoCanvasRestore acr(canvas, true);
1977     canvas->clear(0xFFFFFFFF);
1978 
1979     xlate_and_scale_to_bounds(canvas, SkRect::MakeXYWH(fLeft, fTop,
1980                                                        SkIntToScalar(fImage->width()),
1981                                                        SkIntToScalar(fImage->height())));
1982     this->execute(canvas);
1983     return true;
1984 }
1985 
toJSON(UrlDataManager & urlDataManager) const1986 Json::Value SkDrawImageCommand::toJSON(UrlDataManager& urlDataManager) const {
1987     Json::Value result = INHERITED::toJSON(urlDataManager);
1988     Json::Value encoded;
1989     if (flatten(*fImage, &encoded, urlDataManager)) {
1990         result[SKDEBUGCANVAS_ATTRIBUTE_IMAGE] = encoded;
1991         result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_point(fLeft, fTop);
1992         if (fPaint.isValid()) {
1993             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaint.get(), urlDataManager);
1994         }
1995     }
1996     return result;
1997 }
1998 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)1999 SkDrawImageCommand* SkDrawImageCommand::fromJSON(Json::Value& command,
2000                                                  UrlDataManager& urlDataManager) {
2001     SkImage* image = load_image(command[SKDEBUGCANVAS_ATTRIBUTE_IMAGE], urlDataManager);
2002     if (image == nullptr) {
2003         return nullptr;
2004     }
2005     Json::Value point = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
2006     SkPaint* paintPtr;
2007     SkPaint paint;
2008     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
2009         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2010         paintPtr = &paint;
2011     }
2012     else {
2013         paintPtr = nullptr;
2014     }
2015     SkDrawImageCommand* result = new SkDrawImageCommand(image, point[0].asFloat(),
2016                                                         point[1].asFloat(), paintPtr);
2017     image->unref();
2018     return result;
2019 }
2020 
SkDrawImageRectCommand(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)2021 SkDrawImageRectCommand::SkDrawImageRectCommand(const SkImage* image, const SkRect* src,
2022                                                const SkRect& dst, const SkPaint* paint,
2023                                                SkCanvas::SrcRectConstraint constraint)
2024     : INHERITED(kDrawImageRect_OpType)
2025     , fImage(SkRef(image))
2026     , fDst(dst)
2027     , fConstraint(constraint) {
2028 
2029     if (src) {
2030         fSrc.set(*src);
2031     }
2032 
2033     if (paint) {
2034         fPaint.set(*paint);
2035     }
2036 
2037     fInfo.push(SkObjectParser::ImageToString(image));
2038     if (src) {
2039         fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
2040     }
2041     fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
2042     if (paint) {
2043         fInfo.push(SkObjectParser::PaintToString(*paint));
2044     }
2045     fInfo.push(SkObjectParser::IntToString(fConstraint, "Constraint: "));
2046 }
2047 
execute(SkCanvas * canvas) const2048 void SkDrawImageRectCommand::execute(SkCanvas* canvas) const {
2049     canvas->legacy_drawImageRect(fImage, fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(),
2050                                  fConstraint);
2051 }
2052 
render(SkCanvas * canvas) const2053 bool SkDrawImageRectCommand::render(SkCanvas* canvas) const {
2054     SkAutoCanvasRestore acr(canvas, true);
2055     canvas->clear(0xFFFFFFFF);
2056 
2057     xlate_and_scale_to_bounds(canvas, fDst);
2058 
2059     this->execute(canvas);
2060     return true;
2061 }
2062 
toJSON(UrlDataManager & urlDataManager) const2063 Json::Value SkDrawImageRectCommand::toJSON(UrlDataManager& urlDataManager) const {
2064     Json::Value result = INHERITED::toJSON(urlDataManager);
2065     Json::Value encoded;
2066     if (flatten(*fImage.get(), &encoded, urlDataManager)) {
2067         result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
2068         if (fSrc.isValid()) {
2069             result[SKDEBUGCANVAS_ATTRIBUTE_SRC] = make_json_rect(*fSrc.get());
2070         }
2071         result[SKDEBUGCANVAS_ATTRIBUTE_DST] = make_json_rect(fDst);
2072         if (fPaint.isValid()) {
2073             result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaint.get(), urlDataManager);
2074         }
2075         if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) {
2076             result[SKDEBUGCANVAS_ATTRIBUTE_STRICT] = Json::Value(true);
2077         }
2078     }
2079     return result;
2080 }
2081 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2082 SkDrawImageRectCommand* SkDrawImageRectCommand::fromJSON(Json::Value& command,
2083                                                          UrlDataManager& urlDataManager) {
2084     SkImage* image = load_image(command[SKDEBUGCANVAS_ATTRIBUTE_IMAGE], urlDataManager);
2085     if (image == nullptr) {
2086         return nullptr;
2087     }
2088     SkRect dst;
2089     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
2090     SkPaint* paintPtr;
2091     SkPaint paint;
2092     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
2093         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2094         paintPtr = &paint;
2095     }
2096     else {
2097         paintPtr = nullptr;
2098     }
2099     SkCanvas::SrcRectConstraint constraint;
2100     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_STRICT) &&
2101         command[SKDEBUGCANVAS_ATTRIBUTE_STRICT].asBool()) {
2102         constraint = SkCanvas::kStrict_SrcRectConstraint;
2103     }
2104     else {
2105         constraint = SkCanvas::kFast_SrcRectConstraint;
2106     }
2107     SkRect* srcPtr;
2108     SkRect src;
2109     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_SRC)) {
2110         extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_SRC], &src);
2111         srcPtr = &src;
2112     }
2113     else {
2114         srcPtr = nullptr;
2115     }
2116     SkDrawImageRectCommand* result = new SkDrawImageRectCommand(image, srcPtr, dst, paintPtr,
2117                                                                 constraint);
2118     image->unref();
2119     return result;
2120 }
2121 
SkDrawOvalCommand(const SkRect & oval,const SkPaint & paint)2122 SkDrawOvalCommand::SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint)
2123     : INHERITED(kDrawOval_OpType) {
2124     fOval = oval;
2125     fPaint = paint;
2126 
2127     fInfo.push(SkObjectParser::RectToString(oval));
2128     fInfo.push(SkObjectParser::PaintToString(paint));
2129 }
2130 
execute(SkCanvas * canvas) const2131 void SkDrawOvalCommand::execute(SkCanvas* canvas) const {
2132     canvas->drawOval(fOval, fPaint);
2133 }
2134 
render(SkCanvas * canvas) const2135 bool SkDrawOvalCommand::render(SkCanvas* canvas) const {
2136     canvas->clear(0xFFFFFFFF);
2137     canvas->save();
2138 
2139     xlate_and_scale_to_bounds(canvas, fOval);
2140 
2141     SkPaint p;
2142     p.setColor(SK_ColorBLACK);
2143     p.setStyle(SkPaint::kStroke_Style);
2144 
2145     canvas->drawOval(fOval, p);
2146     canvas->restore();
2147 
2148     return true;
2149 }
2150 
toJSON(UrlDataManager & urlDataManager) const2151 Json::Value SkDrawOvalCommand::toJSON(UrlDataManager& urlDataManager) const {
2152     Json::Value result = INHERITED::toJSON(urlDataManager);
2153     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rect(fOval);
2154     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2155     return result;
2156 }
2157 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2158 SkDrawOvalCommand* SkDrawOvalCommand::fromJSON(Json::Value& command,
2159                                                UrlDataManager& urlDataManager) {
2160     SkRect coords;
2161     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
2162     SkPaint paint;
2163     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2164     return new SkDrawOvalCommand(coords, paint);
2165 }
2166 
SkDrawPaintCommand(const SkPaint & paint)2167 SkDrawPaintCommand::SkDrawPaintCommand(const SkPaint& paint)
2168     : INHERITED(kDrawPaint_OpType) {
2169     fPaint = paint;
2170 
2171     fInfo.push(SkObjectParser::PaintToString(paint));
2172 }
2173 
execute(SkCanvas * canvas) const2174 void SkDrawPaintCommand::execute(SkCanvas* canvas) const {
2175     canvas->drawPaint(fPaint);
2176 }
2177 
render(SkCanvas * canvas) const2178 bool SkDrawPaintCommand::render(SkCanvas* canvas) const {
2179     canvas->clear(0xFFFFFFFF);
2180     canvas->drawPaint(fPaint);
2181     return true;
2182 }
2183 
toJSON(UrlDataManager & urlDataManager) const2184 Json::Value SkDrawPaintCommand::toJSON(UrlDataManager& urlDataManager) const {
2185     Json::Value result = INHERITED::toJSON(urlDataManager);
2186     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2187     return result;
2188 }
2189 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2190 SkDrawPaintCommand* SkDrawPaintCommand::fromJSON(Json::Value& command,
2191                                                  UrlDataManager& urlDataManager) {
2192     SkPaint paint;
2193     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2194     return new SkDrawPaintCommand(paint);
2195 }
2196 
SkDrawPathCommand(const SkPath & path,const SkPaint & paint)2197 SkDrawPathCommand::SkDrawPathCommand(const SkPath& path, const SkPaint& paint)
2198     : INHERITED(kDrawPath_OpType) {
2199     fPath = path;
2200     fPaint = paint;
2201 
2202     fInfo.push(SkObjectParser::PathToString(path));
2203     fInfo.push(SkObjectParser::PaintToString(paint));
2204 }
2205 
execute(SkCanvas * canvas) const2206 void SkDrawPathCommand::execute(SkCanvas* canvas) const {
2207     canvas->drawPath(fPath, fPaint);
2208 }
2209 
render(SkCanvas * canvas) const2210 bool SkDrawPathCommand::render(SkCanvas* canvas) const {
2211     render_path(canvas, fPath);
2212     return true;
2213 }
2214 
toJSON(UrlDataManager & urlDataManager) const2215 Json::Value SkDrawPathCommand::toJSON(UrlDataManager& urlDataManager) const {
2216     Json::Value result = INHERITED::toJSON(urlDataManager);
2217     result[SKDEBUGCANVAS_ATTRIBUTE_PATH] = make_json_path(fPath);
2218     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2219     return result;
2220 }
2221 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2222 SkDrawPathCommand* SkDrawPathCommand::fromJSON(Json::Value& command,
2223                                                UrlDataManager& urlDataManager) {
2224     SkPath path;
2225     extract_json_path(command[SKDEBUGCANVAS_ATTRIBUTE_PATH], &path);
2226     SkPaint paint;
2227     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2228     return new SkDrawPathCommand(path, paint);
2229 }
2230 
SkBeginDrawPictureCommand(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)2231 SkBeginDrawPictureCommand::SkBeginDrawPictureCommand(const SkPicture* picture,
2232                                                      const SkMatrix* matrix,
2233                                                      const SkPaint* paint)
2234     : INHERITED(kBeginDrawPicture_OpType)
2235     , fPicture(SkRef(picture)) {
2236 
2237     SkString* str = new SkString;
2238     str->appendf("SkPicture: L: %f T: %f R: %f B: %f",
2239                  picture->cullRect().fLeft, picture->cullRect().fTop,
2240                  picture->cullRect().fRight, picture->cullRect().fBottom);
2241     fInfo.push(str);
2242 
2243     if (matrix) {
2244         fMatrix.set(*matrix);
2245         fInfo.push(SkObjectParser::MatrixToString(*matrix));
2246     }
2247 
2248     if (paint) {
2249         fPaint.set(*paint);
2250         fInfo.push(SkObjectParser::PaintToString(*paint));
2251     }
2252 
2253 }
2254 
execute(SkCanvas * canvas) const2255 void SkBeginDrawPictureCommand::execute(SkCanvas* canvas) const {
2256     if (fPaint.isValid()) {
2257         SkRect bounds = fPicture->cullRect();
2258         if (fMatrix.isValid()) {
2259             fMatrix.get()->mapRect(&bounds);
2260         }
2261         canvas->saveLayer(&bounds, fPaint.get());
2262     }
2263 
2264     if (fMatrix.isValid()) {
2265         if (!fPaint.isValid()) {
2266             canvas->save();
2267         }
2268         canvas->concat(*fMatrix.get());
2269     }
2270 }
2271 
render(SkCanvas * canvas) const2272 bool SkBeginDrawPictureCommand::render(SkCanvas* canvas) const {
2273     canvas->clear(0xFFFFFFFF);
2274     canvas->save();
2275 
2276     xlate_and_scale_to_bounds(canvas, fPicture->cullRect());
2277 
2278     canvas->drawPicture(fPicture.get());
2279 
2280     canvas->restore();
2281 
2282     return true;
2283 }
2284 
SkEndDrawPictureCommand(bool restore)2285 SkEndDrawPictureCommand::SkEndDrawPictureCommand(bool restore)
2286     : INHERITED(kEndDrawPicture_OpType) , fRestore(restore) { }
2287 
execute(SkCanvas * canvas) const2288 void SkEndDrawPictureCommand::execute(SkCanvas* canvas) const {
2289     if (fRestore) {
2290         canvas->restore();
2291     }
2292 }
2293 
SkDrawPointsCommand(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)2294 SkDrawPointsCommand::SkDrawPointsCommand(SkCanvas::PointMode mode, size_t count,
2295                                          const SkPoint pts[], const SkPaint& paint)
2296     : INHERITED(kDrawPoints_OpType) {
2297     fMode = mode;
2298     fCount = count;
2299     fPts = new SkPoint[count];
2300     memcpy(fPts, pts, count * sizeof(SkPoint));
2301     fPaint = paint;
2302 
2303     fInfo.push(SkObjectParser::PointsToString(pts, count));
2304     fInfo.push(SkObjectParser::ScalarToString(SkIntToScalar((unsigned int)count),
2305                                               "Points: "));
2306     fInfo.push(SkObjectParser::PointModeToString(mode));
2307     fInfo.push(SkObjectParser::PaintToString(paint));
2308 }
2309 
execute(SkCanvas * canvas) const2310 void SkDrawPointsCommand::execute(SkCanvas* canvas) const {
2311     canvas->drawPoints(fMode, fCount, fPts, fPaint);
2312 }
2313 
render(SkCanvas * canvas) const2314 bool SkDrawPointsCommand::render(SkCanvas* canvas) const {
2315     canvas->clear(0xFFFFFFFF);
2316     canvas->save();
2317 
2318     SkRect bounds;
2319 
2320     bounds.setEmpty();
2321     for (unsigned int i = 0; i < fCount; ++i) {
2322         bounds.growToInclude(fPts[i].fX, fPts[i].fY);
2323     }
2324 
2325     xlate_and_scale_to_bounds(canvas, bounds);
2326 
2327     SkPaint p;
2328     p.setColor(SK_ColorBLACK);
2329     p.setStyle(SkPaint::kStroke_Style);
2330 
2331     canvas->drawPoints(fMode, fCount, fPts, p);
2332     canvas->restore();
2333 
2334     return true;
2335 }
2336 
toJSON(UrlDataManager & urlDataManager) const2337 Json::Value SkDrawPointsCommand::toJSON(UrlDataManager& urlDataManager) const {
2338     Json::Value result = INHERITED::toJSON(urlDataManager);
2339     result[SKDEBUGCANVAS_ATTRIBUTE_MODE] = make_json_pointmode(fMode);
2340     Json::Value points(Json::arrayValue);
2341     for (size_t i = 0; i < fCount; i++) {
2342         points.append(make_json_point(fPts[i]));
2343     }
2344     result[SKDEBUGCANVAS_ATTRIBUTE_POINTS] = points;
2345     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2346     return result;
2347 }
2348 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2349 SkDrawPointsCommand* SkDrawPointsCommand::fromJSON(Json::Value& command,
2350                                                    UrlDataManager& urlDataManager) {
2351     SkCanvas::PointMode mode;
2352     const char* jsonMode = command[SKDEBUGCANVAS_ATTRIBUTE_MODE].asCString();
2353     if (!strcmp(jsonMode, SKDEBUGCANVAS_POINTMODE_POINTS)) {
2354         mode = SkCanvas::kPoints_PointMode;
2355     }
2356     else if (!strcmp(jsonMode, SKDEBUGCANVAS_POINTMODE_LINES)) {
2357         mode = SkCanvas::kLines_PointMode;
2358     }
2359     else if (!strcmp(jsonMode, SKDEBUGCANVAS_POINTMODE_POLYGON)) {
2360         mode = SkCanvas::kPolygon_PointMode;
2361     }
2362     else {
2363         SkASSERT(false);
2364         return nullptr;
2365     }
2366     Json::Value jsonPoints = command[SKDEBUGCANVAS_ATTRIBUTE_POINTS];
2367     int count = (int) jsonPoints.size();
2368     SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
2369     for (int i = 0; i < count; i++) {
2370         points[i] = SkPoint::Make(jsonPoints[i][0].asFloat(), jsonPoints[i][1].asFloat());
2371     }
2372     SkPaint paint;
2373     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2374     SkDrawPointsCommand* result = new SkDrawPointsCommand(mode, count, points, paint);
2375     sk_free(points);
2376     return result;
2377 }
2378 
SkDrawPosTextCommand(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)2379 SkDrawPosTextCommand::SkDrawPosTextCommand(const void* text, size_t byteLength,
2380                                            const SkPoint pos[], const SkPaint& paint)
2381     : INHERITED(kDrawPosText_OpType) {
2382     size_t numPts = paint.countText(text, byteLength);
2383 
2384     fText = new char[byteLength];
2385     memcpy(fText, text, byteLength);
2386     fByteLength = byteLength;
2387 
2388     fPos = new SkPoint[numPts];
2389     memcpy(fPos, pos, numPts * sizeof(SkPoint));
2390 
2391     fPaint = paint;
2392 
2393     fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
2394     // TODO(chudy): Test that this works.
2395     fInfo.push(SkObjectParser::PointsToString(pos, 1));
2396     fInfo.push(SkObjectParser::PaintToString(paint));
2397 }
2398 
execute(SkCanvas * canvas) const2399 void SkDrawPosTextCommand::execute(SkCanvas* canvas) const {
2400     canvas->drawPosText(fText, fByteLength, fPos, fPaint);
2401 }
2402 
toJSON(UrlDataManager & urlDataManager) const2403 Json::Value SkDrawPosTextCommand::toJSON(UrlDataManager& urlDataManager) const {
2404     Json::Value result = INHERITED::toJSON(urlDataManager);
2405     result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
2406                                                        ((const char*) fText) + fByteLength);
2407     Json::Value coords(Json::arrayValue);
2408     for (size_t i = 0; i < fByteLength; i++) {
2409         coords.append(make_json_point(fPos[i]));
2410     }
2411     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = coords;
2412     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2413     return result;
2414 }
2415 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2416 SkDrawPosTextCommand* SkDrawPosTextCommand::fromJSON(Json::Value& command,
2417                                                      UrlDataManager& urlDataManager) {
2418     const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
2419     SkPaint paint;
2420     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2421     Json::Value coords = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
2422     int count = (int) coords.size();
2423     SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
2424     for (int i = 0; i < count; i++) {
2425         points[i] = SkPoint::Make(coords[i][0].asFloat(), coords[i][1].asFloat());
2426     }
2427     return new SkDrawPosTextCommand(text, strlen(text), points, paint);
2428 }
2429 
SkDrawPosTextHCommand(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)2430 SkDrawPosTextHCommand::SkDrawPosTextHCommand(const void* text, size_t byteLength,
2431                                              const SkScalar xpos[], SkScalar constY,
2432                                              const SkPaint& paint)
2433     : INHERITED(kDrawPosTextH_OpType) {
2434     size_t numPts = paint.countText(text, byteLength);
2435 
2436     fText = new char[byteLength];
2437     memcpy(fText, text, byteLength);
2438     fByteLength = byteLength;
2439 
2440     fXpos = new SkScalar[numPts];
2441     memcpy(fXpos, xpos, numPts * sizeof(SkScalar));
2442 
2443     fConstY = constY;
2444     fPaint = paint;
2445 
2446     fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
2447     fInfo.push(SkObjectParser::ScalarToString(xpos[0], "XPOS: "));
2448     fInfo.push(SkObjectParser::ScalarToString(constY, "SkScalar constY: "));
2449     fInfo.push(SkObjectParser::PaintToString(paint));
2450 }
2451 
execute(SkCanvas * canvas) const2452 void SkDrawPosTextHCommand::execute(SkCanvas* canvas) const {
2453     canvas->drawPosTextH(fText, fByteLength, fXpos, fConstY, fPaint);
2454 }
2455 
2456 static const char* gPositioningLabels[] = {
2457     "kDefault_Positioning",
2458     "kHorizontal_Positioning",
2459     "kFull_Positioning",
2460 };
2461 
SkDrawTextBlobCommand(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)2462 SkDrawTextBlobCommand::SkDrawTextBlobCommand(const SkTextBlob* blob, SkScalar x, SkScalar y,
2463                                              const SkPaint& paint)
2464     : INHERITED(kDrawTextBlob_OpType)
2465     , fBlob(SkRef(blob))
2466     , fXPos(x)
2467     , fYPos(y)
2468     , fPaint(paint) {
2469 
2470     SkAutoTDelete<SkString> runsStr(new SkString);
2471     fInfo.push(SkObjectParser::ScalarToString(x, "XPOS: "));
2472     fInfo.push(SkObjectParser::ScalarToString(y, "YPOS: "));
2473     fInfo.push(SkObjectParser::RectToString(fBlob->bounds(), "Bounds: "));
2474     fInfo.push(runsStr);
2475     fInfo.push(SkObjectParser::PaintToString(paint));
2476 
2477     unsigned runs = 0;
2478     SkPaint runPaint(paint);
2479     SkTextBlobRunIterator iter(blob);
2480     while (!iter.done()) {
2481         SkAutoTDelete<SkString> tmpStr(new SkString);
2482         tmpStr->printf("==== Run [%d] ====", runs++);
2483         fInfo.push(tmpStr.release());
2484 
2485         fInfo.push(SkObjectParser::IntToString(iter.glyphCount(), "GlyphCount: "));
2486         tmpStr.reset(new SkString("GlyphPositioning: "));
2487         tmpStr->append(gPositioningLabels[iter.positioning()]);
2488         fInfo.push(tmpStr.release());
2489 
2490         iter.applyFontToPaint(&runPaint);
2491         fInfo.push(SkObjectParser::PaintToString(runPaint));
2492 
2493         iter.next();
2494     }
2495 
2496     runsStr->printf("Runs: %d", runs);
2497     // runStr is owned by fInfo at this point.
2498     runsStr.release();
2499 }
2500 
execute(SkCanvas * canvas) const2501 void SkDrawTextBlobCommand::execute(SkCanvas* canvas) const {
2502     canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
2503 }
2504 
render(SkCanvas * canvas) const2505 bool SkDrawTextBlobCommand::render(SkCanvas* canvas) const {
2506     canvas->clear(SK_ColorWHITE);
2507     canvas->save();
2508 
2509     SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
2510     xlate_and_scale_to_bounds(canvas, bounds);
2511 
2512     canvas->drawTextBlob(fBlob.get(), fXPos, fYPos, fPaint);
2513 
2514     canvas->restore();
2515 
2516     return true;
2517 }
2518 
toJSON(UrlDataManager & urlDataManager) const2519 Json::Value SkDrawTextBlobCommand::toJSON(UrlDataManager& urlDataManager) const {
2520     Json::Value result = INHERITED::toJSON(urlDataManager);
2521     Json::Value runs(Json::arrayValue);
2522     SkTextBlobRunIterator iter(fBlob.get());
2523     while (!iter.done()) {
2524         Json::Value run(Json::objectValue);
2525         Json::Value jsonPositions(Json::arrayValue);
2526         Json::Value jsonGlyphs(Json::arrayValue);
2527         const SkScalar* iterPositions = iter.pos();
2528         const uint16_t* iterGlyphs = iter.glyphs();
2529         for (uint32_t i = 0; i < iter.glyphCount(); i++) {
2530             switch (iter.positioning()) {
2531                 case SkTextBlob::kFull_Positioning:
2532                     jsonPositions.append(make_json_point(iterPositions[i * 2],
2533                                                          iterPositions[i * 2 + 1]));
2534                     break;
2535                 case SkTextBlob::kHorizontal_Positioning:
2536                     jsonPositions.append(Json::Value(iterPositions[i]));
2537                     break;
2538                 case SkTextBlob::kDefault_Positioning:
2539                     break;
2540             }
2541             jsonGlyphs.append(Json::Value(iterGlyphs[i]));
2542         }
2543         if (iter.positioning() != SkTextBlob::kDefault_Positioning) {
2544             run[SKDEBUGCANVAS_ATTRIBUTE_POSITIONS] = jsonPositions;
2545         }
2546         run[SKDEBUGCANVAS_ATTRIBUTE_GLYPHS] = jsonGlyphs;
2547         SkPaint fontPaint;
2548         iter.applyFontToPaint(&fontPaint);
2549         run[SKDEBUGCANVAS_ATTRIBUTE_FONT] = make_json_paint(fontPaint, urlDataManager);
2550         run[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_point(iter.offset());
2551         runs.append(run);
2552         iter.next();
2553     }
2554     result[SKDEBUGCANVAS_ATTRIBUTE_RUNS] = runs;
2555     result[SKDEBUGCANVAS_ATTRIBUTE_X] = Json::Value(fXPos);
2556     result[SKDEBUGCANVAS_ATTRIBUTE_Y] = Json::Value(fYPos);
2557     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2558     return result;
2559 }
2560 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2561 SkDrawTextBlobCommand* SkDrawTextBlobCommand::fromJSON(Json::Value& command,
2562                                                        UrlDataManager& urlDataManager) {
2563     SkTextBlobBuilder builder;
2564     Json::Value runs = command[SKDEBUGCANVAS_ATTRIBUTE_RUNS];
2565     for (Json::ArrayIndex i = 0 ; i < runs.size(); i++) {
2566         Json::Value run = runs[i];
2567         SkPaint font;
2568         font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
2569         extract_json_paint(run[SKDEBUGCANVAS_ATTRIBUTE_FONT], urlDataManager, &font);
2570         Json::Value glyphs = run[SKDEBUGCANVAS_ATTRIBUTE_GLYPHS];
2571         int count = glyphs.size();
2572         Json::Value coords = run[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
2573         SkScalar x = coords[0].asFloat();
2574         SkScalar y = coords[1].asFloat();
2575         if (run.isMember(SKDEBUGCANVAS_ATTRIBUTE_POSITIONS)) {
2576             Json::Value positions = run[SKDEBUGCANVAS_ATTRIBUTE_POSITIONS];
2577             if (positions.size() > 0 && positions[0].isNumeric()) {
2578                 SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPosH(font, count, y);
2579                 for (int j = 0; j < count; j++) {
2580                     buffer.glyphs[j] = glyphs[j].asUInt();
2581                     buffer.pos[j] = positions[j].asFloat();
2582                 }
2583             }
2584             else {
2585                 SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPos(font, count);
2586                 for (int j = 0; j < count; j++) {
2587                     buffer.glyphs[j] = glyphs[j].asUInt();
2588                     buffer.pos[j * 2] = positions[j][0].asFloat();
2589                     buffer.pos[j * 2 + 1] = positions[j][1].asFloat();
2590                 }
2591             }
2592         }
2593         else {
2594             SkTextBlobBuilder::RunBuffer buffer = builder.allocRun(font, count, x, y);
2595             for (int j = 0; j < count; j++) {
2596                 buffer.glyphs[j] = glyphs[j].asUInt();
2597             }
2598         }
2599     }
2600     SkScalar x = command[SKDEBUGCANVAS_ATTRIBUTE_X].asFloat();
2601     SkScalar y = command[SKDEBUGCANVAS_ATTRIBUTE_Y].asFloat();
2602     SkPaint paint;
2603     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2604     return new SkDrawTextBlobCommand(builder.build(), x, y, paint);
2605 }
2606 
SkDrawPatchCommand(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xfermode,const SkPaint & paint)2607 SkDrawPatchCommand::SkDrawPatchCommand(const SkPoint cubics[12], const SkColor colors[4],
2608                                        const SkPoint texCoords[4], SkXfermode* xfermode,
2609                                        const SkPaint& paint)
2610     : INHERITED(kDrawPatch_OpType) {
2611     memcpy(fCubics, cubics, sizeof(fCubics));
2612     if (colors != nullptr) {
2613         memcpy(fColors, colors, sizeof(fColors));
2614         fColorsPtr = fColors;
2615     } else {
2616         fColorsPtr = nullptr;
2617     }
2618     if (texCoords != nullptr) {
2619         memcpy(fTexCoords, texCoords, sizeof(fTexCoords));
2620         fTexCoordsPtr = fTexCoords;
2621     } else {
2622         fTexCoordsPtr = nullptr;
2623     }
2624     if (xfermode != nullptr) {
2625         fXfermode.reset(SkRef(xfermode));
2626     }
2627     fPaint = paint;
2628 
2629     fInfo.push(SkObjectParser::PaintToString(paint));
2630 }
2631 
execute(SkCanvas * canvas) const2632 void SkDrawPatchCommand::execute(SkCanvas* canvas) const {
2633     canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fXfermode, fPaint);
2634 }
2635 
toJSON(UrlDataManager & urlDataManager) const2636 Json::Value SkDrawPatchCommand::toJSON(UrlDataManager& urlDataManager) const {
2637     Json::Value result = INHERITED::toJSON(urlDataManager);
2638     Json::Value cubics = Json::Value(Json::arrayValue);
2639     for (int i = 0; i < 12; i++) {
2640         cubics.append(make_json_point(fCubics[i]));
2641     }
2642     result[SKDEBUGCANVAS_ATTRIBUTE_CUBICS] = cubics;
2643     if (fColorsPtr != nullptr) {
2644         Json::Value colors = Json::Value(Json::arrayValue);
2645         for (int i = 0; i < 4; i++) {
2646             colors.append(make_json_color(fColorsPtr[i]));
2647         }
2648         result[SKDEBUGCANVAS_ATTRIBUTE_COLORS] = colors;
2649     }
2650     if (fTexCoordsPtr != nullptr) {
2651         Json::Value texCoords = Json::Value(Json::arrayValue);
2652         for (int i = 0; i < 4; i++) {
2653             texCoords.append(make_json_point(fTexCoords[i]));
2654         }
2655         result[SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS] = texCoords;
2656     }
2657     if (fXfermode.get() != nullptr) {
2658         Json::Value jsonXfermode;
2659         flatten(fXfermode, &jsonXfermode, urlDataManager);
2660         result[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE] = jsonXfermode;
2661     }
2662     return result;
2663 }
2664 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2665 SkDrawPatchCommand* SkDrawPatchCommand::fromJSON(Json::Value& command,
2666                                                  UrlDataManager& urlDataManager) {
2667     Json::Value jsonCubics = command[SKDEBUGCANVAS_ATTRIBUTE_CUBICS];
2668     SkPoint cubics[12];
2669     for (int i = 0; i < 12; i++) {
2670         cubics[i] = get_json_point(jsonCubics[i]);
2671     }
2672     SkColor* colorsPtr;
2673     SkColor colors[4];
2674     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_COLORS)) {
2675         Json::Value jsonColors = command[SKDEBUGCANVAS_ATTRIBUTE_COLORS];
2676         for (int i = 0; i < 4; i++) {
2677             colors[i] = get_json_color(jsonColors[i]);
2678         }
2679         colorsPtr = colors;
2680     }
2681     else {
2682         colorsPtr = nullptr;
2683     }
2684     SkPoint* texCoordsPtr;
2685     SkPoint texCoords[4];
2686     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS)) {
2687         Json::Value jsonTexCoords = command[SKDEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS];
2688         for (int i = 0; i < 4; i++) {
2689             texCoords[i] = get_json_point(jsonTexCoords[i]);
2690         }
2691         texCoordsPtr = texCoords;
2692     }
2693     else {
2694         texCoordsPtr = nullptr;
2695     }
2696     SkAutoTUnref<SkXfermode> xfermode;
2697     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_XFERMODE)) {
2698         Json::Value jsonXfermode = command[SKDEBUGCANVAS_ATTRIBUTE_XFERMODE];
2699         xfermode.reset((SkXfermode*) load_flattenable(jsonXfermode, urlDataManager));
2700     }
2701     SkPaint paint;
2702     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2703     return new SkDrawPatchCommand(cubics, colorsPtr, texCoordsPtr, xfermode, paint);
2704 }
2705 
SkDrawRectCommand(const SkRect & rect,const SkPaint & paint)2706 SkDrawRectCommand::SkDrawRectCommand(const SkRect& rect, const SkPaint& paint)
2707     : INHERITED(kDrawRect_OpType) {
2708     fRect = rect;
2709     fPaint = paint;
2710 
2711     fInfo.push(SkObjectParser::RectToString(rect));
2712     fInfo.push(SkObjectParser::PaintToString(paint));
2713 }
2714 
execute(SkCanvas * canvas) const2715 void SkDrawRectCommand::execute(SkCanvas* canvas) const {
2716     canvas->drawRect(fRect, fPaint);
2717 }
2718 
toJSON(UrlDataManager & urlDataManager) const2719 Json::Value SkDrawRectCommand::toJSON(UrlDataManager& urlDataManager) const {
2720     Json::Value result = INHERITED::toJSON(urlDataManager);
2721     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rect(fRect);
2722     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2723     return result;
2724 }
2725 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2726 SkDrawRectCommand* SkDrawRectCommand::fromJSON(Json::Value& command,
2727                                                UrlDataManager& urlDataManager) {
2728     SkRect coords;
2729     extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
2730     SkPaint paint;
2731     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2732     return new SkDrawRectCommand(coords, paint);
2733 }
2734 
SkDrawRRectCommand(const SkRRect & rrect,const SkPaint & paint)2735 SkDrawRRectCommand::SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
2736     : INHERITED(kDrawRRect_OpType) {
2737     fRRect = rrect;
2738     fPaint = paint;
2739 
2740     fInfo.push(SkObjectParser::RRectToString(rrect));
2741     fInfo.push(SkObjectParser::PaintToString(paint));
2742 }
2743 
execute(SkCanvas * canvas) const2744 void SkDrawRRectCommand::execute(SkCanvas* canvas) const {
2745     canvas->drawRRect(fRRect, fPaint);
2746 }
2747 
render(SkCanvas * canvas) const2748 bool SkDrawRRectCommand::render(SkCanvas* canvas) const {
2749     render_rrect(canvas, fRRect);
2750     return true;
2751 }
2752 
toJSON(UrlDataManager & urlDataManager) const2753 Json::Value SkDrawRRectCommand::toJSON(UrlDataManager& urlDataManager) const {
2754     Json::Value result = INHERITED::toJSON(urlDataManager);
2755     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_rrect(fRRect);
2756     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2757     return result;
2758 }
2759 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2760 SkDrawRRectCommand* SkDrawRRectCommand::fromJSON(Json::Value& command,
2761                                                  UrlDataManager& urlDataManager) {
2762     SkRRect coords;
2763     extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_COORDS], &coords);
2764     SkPaint paint;
2765     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2766     return new SkDrawRRectCommand(coords, paint);
2767 }
2768 
SkDrawDRRectCommand(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)2769 SkDrawDRRectCommand::SkDrawDRRectCommand(const SkRRect& outer,
2770                                          const SkRRect& inner,
2771                                          const SkPaint& paint)
2772     : INHERITED(kDrawDRRect_OpType) {
2773     fOuter = outer;
2774     fInner = inner;
2775     fPaint = paint;
2776 
2777     fInfo.push(SkObjectParser::RRectToString(outer));
2778     fInfo.push(SkObjectParser::RRectToString(inner));
2779     fInfo.push(SkObjectParser::PaintToString(paint));
2780 }
2781 
execute(SkCanvas * canvas) const2782 void SkDrawDRRectCommand::execute(SkCanvas* canvas) const {
2783     canvas->drawDRRect(fOuter, fInner, fPaint);
2784 }
2785 
render(SkCanvas * canvas) const2786 bool SkDrawDRRectCommand::render(SkCanvas* canvas) const {
2787     render_drrect(canvas, fOuter, fInner);
2788     return true;
2789 }
2790 
toJSON(UrlDataManager & urlDataManager) const2791 Json::Value SkDrawDRRectCommand::toJSON(UrlDataManager& urlDataManager) const {
2792     Json::Value result = INHERITED::toJSON(urlDataManager);
2793     result[SKDEBUGCANVAS_ATTRIBUTE_OUTER] = make_json_rrect(fOuter);
2794     result[SKDEBUGCANVAS_ATTRIBUTE_INNER] = make_json_rrect(fInner);
2795     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2796     return result;
2797 }
2798 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2799 SkDrawDRRectCommand* SkDrawDRRectCommand::fromJSON(Json::Value& command,
2800                                                    UrlDataManager& urlDataManager) {
2801     SkRRect outer;
2802     extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_INNER], &outer);
2803     SkRRect inner;
2804     extract_json_rrect(command[SKDEBUGCANVAS_ATTRIBUTE_INNER], &inner);
2805     SkPaint paint;
2806     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2807     return new SkDrawDRRectCommand(outer, inner, paint);
2808 }
2809 
SkDrawTextCommand(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)2810 SkDrawTextCommand::SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2811                                      const SkPaint& paint)
2812     : INHERITED(kDrawText_OpType) {
2813     fText = new char[byteLength];
2814     memcpy(fText, text, byteLength);
2815     fByteLength = byteLength;
2816     fX = x;
2817     fY = y;
2818     fPaint = paint;
2819 
2820     fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
2821     fInfo.push(SkObjectParser::ScalarToString(x, "SkScalar x: "));
2822     fInfo.push(SkObjectParser::ScalarToString(y, "SkScalar y: "));
2823     fInfo.push(SkObjectParser::PaintToString(paint));
2824 }
2825 
execute(SkCanvas * canvas) const2826 void SkDrawTextCommand::execute(SkCanvas* canvas) const {
2827     canvas->drawText(fText, fByteLength, fX, fY, fPaint);
2828 }
2829 
toJSON(UrlDataManager & urlDataManager) const2830 Json::Value SkDrawTextCommand::toJSON(UrlDataManager& urlDataManager) const {
2831     Json::Value result = INHERITED::toJSON(urlDataManager);
2832     result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
2833                                                        ((const char*) fText) + fByteLength);
2834     Json::Value coords(Json::arrayValue);
2835     result[SKDEBUGCANVAS_ATTRIBUTE_COORDS] = make_json_point(fX, fY);
2836     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2837     return result;
2838 }
2839 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2840 SkDrawTextCommand* SkDrawTextCommand::fromJSON(Json::Value& command,
2841                                                UrlDataManager& urlDataManager) {
2842     const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
2843     SkPaint paint;
2844     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2845     Json::Value coords = command[SKDEBUGCANVAS_ATTRIBUTE_COORDS];
2846     return new SkDrawTextCommand(text, strlen(text), coords[0].asFloat(), coords[1].asFloat(),
2847                                  paint);
2848 }
2849 
SkDrawTextOnPathCommand(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)2850 SkDrawTextOnPathCommand::SkDrawTextOnPathCommand(const void* text, size_t byteLength,
2851                                                  const SkPath& path, const SkMatrix* matrix,
2852                                                  const SkPaint& paint)
2853     : INHERITED(kDrawTextOnPath_OpType) {
2854     fText = new char[byteLength];
2855     memcpy(fText, text, byteLength);
2856     fByteLength = byteLength;
2857     fPath = path;
2858     if (matrix) {
2859         fMatrix = *matrix;
2860     } else {
2861         fMatrix.setIdentity();
2862     }
2863     fPaint = paint;
2864 
2865     fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
2866     fInfo.push(SkObjectParser::PathToString(path));
2867     if (matrix) {
2868         fInfo.push(SkObjectParser::MatrixToString(*matrix));
2869     }
2870     fInfo.push(SkObjectParser::PaintToString(paint));
2871 }
2872 
execute(SkCanvas * canvas) const2873 void SkDrawTextOnPathCommand::execute(SkCanvas* canvas) const {
2874     canvas->drawTextOnPath(fText, fByteLength, fPath,
2875                            fMatrix.isIdentity() ? nullptr : &fMatrix,
2876                            fPaint);
2877 }
2878 
toJSON(UrlDataManager & urlDataManager) const2879 Json::Value SkDrawTextOnPathCommand::toJSON(UrlDataManager& urlDataManager) const {
2880     Json::Value result = INHERITED::toJSON(urlDataManager);
2881     result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
2882                                                        ((const char*) fText) + fByteLength);
2883     Json::Value coords(Json::arrayValue);
2884     result[SKDEBUGCANVAS_ATTRIBUTE_PATH] = make_json_path(fPath);
2885     if (!fMatrix.isIdentity()) {
2886         result[SKDEBUGCANVAS_ATTRIBUTE_MATRIX] = make_json_matrix(fMatrix);
2887     }
2888     result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(fPaint, urlDataManager);
2889     return result;
2890 }
2891 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2892 SkDrawTextOnPathCommand* SkDrawTextOnPathCommand::fromJSON(Json::Value& command,
2893                                                            UrlDataManager& urlDataManager) {
2894     const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
2895     SkPaint paint;
2896     extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
2897     SkPath path;
2898     extract_json_path(command[SKDEBUGCANVAS_ATTRIBUTE_PATH], &path);
2899     SkMatrix* matrixPtr;
2900     SkMatrix matrix;
2901     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_MATRIX)) {
2902         extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
2903         matrixPtr = &matrix;
2904     }
2905     else {
2906         matrixPtr = nullptr;
2907     }
2908     return new SkDrawTextOnPathCommand(text, strlen(text), path, matrixPtr, paint);
2909 }
2910 
SkDrawVerticesCommand(SkCanvas::VertexMode vmode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode * xfermode,const uint16_t indices[],int indexCount,const SkPaint & paint)2911 SkDrawVerticesCommand::SkDrawVerticesCommand(SkCanvas::VertexMode vmode, int vertexCount,
2912                                              const SkPoint vertices[], const SkPoint texs[],
2913                                              const SkColor colors[], SkXfermode* xfermode,
2914                                              const uint16_t indices[], int indexCount,
2915                                              const SkPaint& paint)
2916     : INHERITED(kDrawVertices_OpType) {
2917     fVmode = vmode;
2918 
2919     fVertexCount = vertexCount;
2920 
2921     fVertices = new SkPoint[vertexCount];
2922     memcpy(fVertices, vertices, vertexCount * sizeof(SkPoint));
2923 
2924     if (texs) {
2925         fTexs = new SkPoint[vertexCount];
2926         memcpy(fTexs, texs, vertexCount * sizeof(SkPoint));
2927     } else {
2928         fTexs = nullptr;
2929     }
2930 
2931     if (colors) {
2932         fColors = new SkColor[vertexCount];
2933         memcpy(fColors, colors, vertexCount * sizeof(SkColor));
2934     } else {
2935         fColors = nullptr;
2936     }
2937 
2938     fXfermode = xfermode;
2939     if (fXfermode) {
2940         fXfermode->ref();
2941     }
2942 
2943     if (indexCount > 0) {
2944         fIndices = new uint16_t[indexCount];
2945         memcpy(fIndices, indices, indexCount * sizeof(uint16_t));
2946     } else {
2947         fIndices = nullptr;
2948     }
2949 
2950     fIndexCount = indexCount;
2951     fPaint = paint;
2952 
2953     // TODO(chudy)
2954     fInfo.push(SkObjectParser::CustomTextToString("To be implemented."));
2955     fInfo.push(SkObjectParser::PaintToString(paint));
2956 }
2957 
~SkDrawVerticesCommand()2958 SkDrawVerticesCommand::~SkDrawVerticesCommand() {
2959     delete [] fVertices;
2960     delete [] fTexs;
2961     delete [] fColors;
2962     SkSafeUnref(fXfermode);
2963     delete [] fIndices;
2964 }
2965 
execute(SkCanvas * canvas) const2966 void SkDrawVerticesCommand::execute(SkCanvas* canvas) const {
2967     canvas->drawVertices(fVmode, fVertexCount, fVertices,
2968                          fTexs, fColors, fXfermode, fIndices,
2969                          fIndexCount, fPaint);
2970 }
2971 
SkRestoreCommand()2972 SkRestoreCommand::SkRestoreCommand()
2973     : INHERITED(kRestore_OpType) {
2974     fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
2975 }
2976 
execute(SkCanvas * canvas) const2977 void SkRestoreCommand::execute(SkCanvas* canvas) const {
2978     canvas->restore();
2979 }
2980 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2981 SkRestoreCommand* SkRestoreCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
2982     return new SkRestoreCommand();
2983 }
2984 
SkSaveCommand()2985 SkSaveCommand::SkSaveCommand()
2986     : INHERITED(kSave_OpType) {
2987 }
2988 
execute(SkCanvas * canvas) const2989 void SkSaveCommand::execute(SkCanvas* canvas) const {
2990     canvas->save();
2991 }
2992 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)2993 SkSaveCommand* SkSaveCommand::fromJSON(Json::Value& command, UrlDataManager& urlDataManager) {
2994     return new SkSaveCommand();
2995 }
2996 
SkSaveLayerCommand(const SkCanvas::SaveLayerRec & rec)2997 SkSaveLayerCommand::SkSaveLayerCommand(const SkCanvas::SaveLayerRec& rec)
2998     : INHERITED(kSaveLayer_OpType) {
2999     if (rec.fBounds) {
3000         fBounds = *rec.fBounds;
3001     } else {
3002         fBounds.setEmpty();
3003     }
3004 
3005     if (rec.fPaint) {
3006         fPaint = *rec.fPaint;
3007         fPaintPtr = &fPaint;
3008     } else {
3009         fPaintPtr = nullptr;
3010     }
3011     fSaveLayerFlags = rec.fSaveLayerFlags;
3012 
3013     if (rec.fBackdrop) {
3014         fBackdrop = rec.fBackdrop;
3015         fBackdrop->ref();
3016     } else {
3017         fBackdrop = nullptr;
3018     }
3019 
3020     if (rec.fBounds) {
3021         fInfo.push(SkObjectParser::RectToString(*rec.fBounds, "Bounds: "));
3022     }
3023     if (rec.fPaint) {
3024         fInfo.push(SkObjectParser::PaintToString(*rec.fPaint));
3025     }
3026     fInfo.push(SkObjectParser::SaveLayerFlagsToString(fSaveLayerFlags));
3027 }
3028 
~SkSaveLayerCommand()3029 SkSaveLayerCommand::~SkSaveLayerCommand() {
3030     if (fBackdrop != nullptr) {
3031         fBackdrop->unref();
3032     }
3033 }
3034 
execute(SkCanvas * canvas) const3035 void SkSaveLayerCommand::execute(SkCanvas* canvas) const {
3036     canvas->saveLayer(SkCanvas::SaveLayerRec(fBounds.isEmpty() ? nullptr : &fBounds,
3037                                              fPaintPtr,
3038                                              fSaveLayerFlags));
3039 }
3040 
vizExecute(SkCanvas * canvas) const3041 void SkSaveLayerCommand::vizExecute(SkCanvas* canvas) const {
3042     canvas->save();
3043 }
3044 
toJSON(UrlDataManager & urlDataManager) const3045 Json::Value SkSaveLayerCommand::toJSON(UrlDataManager& urlDataManager) const {
3046     Json::Value result = INHERITED::toJSON(urlDataManager);
3047     if (!fBounds.isEmpty()) {
3048         result[SKDEBUGCANVAS_ATTRIBUTE_BOUNDS] = make_json_rect(fBounds);
3049     }
3050     if (fPaintPtr != nullptr) {
3051         result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = make_json_paint(*fPaintPtr,
3052                                                                 urlDataManager);
3053     }
3054     if (fBackdrop != nullptr) {
3055         Json::Value jsonBackdrop;
3056         flatten(fBackdrop, &jsonBackdrop, urlDataManager);
3057         result[SKDEBUGCANVAS_ATTRIBUTE_BACKDROP] = jsonBackdrop;
3058     }
3059     if (fSaveLayerFlags != 0) {
3060         SkDebugf("unsupported: saveLayer flags\n");
3061         SkASSERT(false);
3062     }
3063     return result;
3064 }
3065 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)3066 SkSaveLayerCommand* SkSaveLayerCommand::fromJSON(Json::Value& command,
3067                                                  UrlDataManager& urlDataManager) {
3068     SkCanvas::SaveLayerRec rec;
3069     SkRect bounds;
3070     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_BOUNDS)) {
3071         extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_BOUNDS], &bounds);
3072         rec.fBounds = &bounds;
3073     }
3074     SkPaint paint;
3075     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
3076         extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
3077         rec.fPaint = &paint;
3078     }
3079     if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_BACKDROP)) {
3080         Json::Value backdrop = command[SKDEBUGCANVAS_ATTRIBUTE_BACKDROP];
3081         rec.fBackdrop = (SkImageFilter*) load_flattenable(backdrop, urlDataManager);
3082     }
3083     SkSaveLayerCommand* result = new SkSaveLayerCommand(rec);
3084     if (rec.fBackdrop != nullptr) {
3085         rec.fBackdrop->unref();
3086     }
3087     return result;
3088 }
3089 
SkSetMatrixCommand(const SkMatrix & matrix)3090 SkSetMatrixCommand::SkSetMatrixCommand(const SkMatrix& matrix)
3091     : INHERITED(kSetMatrix_OpType) {
3092     fUserMatrix.reset();
3093     fMatrix = matrix;
3094     fInfo.push(SkObjectParser::MatrixToString(matrix));
3095 }
3096 
setUserMatrix(const SkMatrix & userMatrix)3097 void SkSetMatrixCommand::setUserMatrix(const SkMatrix& userMatrix) {
3098     fUserMatrix = userMatrix;
3099 }
3100 
execute(SkCanvas * canvas) const3101 void SkSetMatrixCommand::execute(SkCanvas* canvas) const {
3102     SkMatrix temp = SkMatrix::Concat(fUserMatrix, fMatrix);
3103     canvas->setMatrix(temp);
3104 }
3105 
toJSON(UrlDataManager & urlDataManager) const3106 Json::Value SkSetMatrixCommand::toJSON(UrlDataManager& urlDataManager) const {
3107     Json::Value result = INHERITED::toJSON(urlDataManager);
3108     result[SKDEBUGCANVAS_ATTRIBUTE_MATRIX] = make_json_matrix(fMatrix);
3109     return result;
3110 }
3111 
fromJSON(Json::Value & command,UrlDataManager & urlDataManager)3112 SkSetMatrixCommand* SkSetMatrixCommand::fromJSON(Json::Value& command,
3113                                                  UrlDataManager& urlDataManager) {
3114     SkMatrix matrix;
3115     extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
3116     return new SkSetMatrixCommand(matrix);
3117 }
3118