Coverage Report

Created: 2024-05-20 07:14

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