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