1 /*
2 * Copyright 2018 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/viewer/BisectSlide.h"
9
10 #include "include/core/SkStream.h"
11 #include "src/utils/SkOSPath.h"
12 #include "tools/ToolUtils.h"
13
14 #include <utility>
15
Create(const char filepath[])16 sk_sp<BisectSlide> BisectSlide::Create(const char filepath[]) {
17 SkFILEStream stream(filepath);
18 if (!stream.isValid()) {
19 SkDebugf("BISECT: invalid input file at \"%s\"\n", filepath);
20 return nullptr;
21 }
22
23 sk_sp<BisectSlide> bisect(new BisectSlide(filepath));
24 ToolUtils::sniff_paths(filepath, [&](const SkMatrix& matrix,
25 const SkPath& path,
26 const SkPaint& paint) {
27 SkRect bounds;
28 SkIRect ibounds;
29 matrix.mapRect(&bounds, path.getBounds());
30 bounds.roundOut(&ibounds);
31 bisect->fDrawBounds.join(ibounds);
32 bisect->fFoundPaths.push_back() = {path, paint, matrix};
33 });
34 return bisect;
35 }
36
BisectSlide(const char filepath[])37 BisectSlide::BisectSlide(const char filepath[])
38 : fFilePath(filepath) {
39 const char* basename = strrchr(fFilePath.c_str(), SkOSPath::SEPARATOR);
40 fName.printf("BISECT_%s", basename ? basename + 1 : fFilePath.c_str());
41 }
42
onChar(SkUnichar c)43 bool BisectSlide::onChar(SkUnichar c) {
44 switch (c) {
45 case 'X':
46 if (!fTossedPaths.empty()) {
47 using std::swap;
48 swap(fFoundPaths, fTossedPaths);
49 if ('X' == fTrail.back()) {
50 fTrail.pop_back();
51 } else {
52 fTrail.push_back('X');
53 }
54 }
55 return true;
56
57 case 'x':
58 if (fFoundPaths.count() > 1) {
59 int midpt = (fFoundPaths.count() + 1) / 2;
60 fPathHistory.emplace(fFoundPaths, fTossedPaths);
61 fTossedPaths.reset(fFoundPaths.begin() + midpt, fFoundPaths.count() - midpt);
62 fFoundPaths.resize_back(midpt);
63 fTrail.push_back('x');
64 }
65 return true;
66
67 case 'Z': {
68 if (!fPathHistory.empty()) {
69 fFoundPaths = fPathHistory.top().first;
70 fTossedPaths = fPathHistory.top().second;
71 fPathHistory.pop();
72 char ch;
73 do {
74 ch = fTrail.back();
75 fTrail.pop_back();
76 } while (ch != 'x');
77 }
78 return true;
79 }
80
81 case 'D':
82 SkDebugf("viewer --bisect %s", fFilePath.c_str());
83 if (!fTrail.empty()) {
84 SkDebugf(" ");
85 for (char ch : fTrail) {
86 SkDebugf("%c", ch);
87 }
88 }
89 SkDebugf("\n");
90 for (const FoundPath& foundPath : fFoundPaths) {
91 foundPath.fPath.dump();
92 }
93 return true;
94 }
95
96 return false;
97 }
98
draw(SkCanvas * canvas)99 void BisectSlide::draw(SkCanvas* canvas) {
100 SkAutoCanvasRestore acr(canvas, true);
101 canvas->translate(-fDrawBounds.left(), -fDrawBounds.top());
102
103 for (const FoundPath& path : fFoundPaths) {
104 SkAutoCanvasRestore acr2(canvas, true);
105 canvas->concat(path.fViewMatrix);
106 canvas->drawPath(path.fPath, path.fPaint);
107 }
108 }
109