xref: /aosp_15_r20/external/skia/tools/viewer/BisectSlide.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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