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