• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkPicture.h"
11 #include "include/core/SkStream.h"
12 #include "src/utils/SkOSPath.h"
13 
14 #include <utility>
15 
16 #ifdef SK_XML
17 #include "experimental/svg/model/SkSVGDOM.h"
18 #include "src/xml/SkDOM.h"
19 #endif
20 
Create(const char filepath[])21 sk_sp<BisectSlide> BisectSlide::Create(const char filepath[]) {
22     SkFILEStream stream(filepath);
23     if (!stream.isValid()) {
24         SkDebugf("BISECT: invalid input file at \"%s\"\n", filepath);
25         return nullptr;
26     }
27 
28     sk_sp<BisectSlide> bisect(new BisectSlide(filepath));
29     if (bisect->fFilePath.endsWith(".svg")) {
30 #ifdef SK_XML
31         SkDOM xml;
32         if (!xml.build(stream)) {
33             SkDebugf("BISECT: XML parsing failed: \"%s\"\n", filepath);
34             return nullptr;
35         }
36         sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromDOM(xml);
37         if (!svg) {
38             SkDebugf("BISECT: couldn't load svg at \"%s\"\n", filepath);
39             return nullptr;
40         }
41         svg->setContainerSize(SkSize::Make(bisect->getDimensions()));
42         svg->render(bisect.get());
43 #else
44         return nullptr;
45 #endif
46     } else {
47         sk_sp<SkPicture> skp = SkPicture::MakeFromStream(&stream);
48         if (!skp) {
49             SkDebugf("BISECT: couldn't load skp at \"%s\"\n", filepath);
50             return nullptr;
51         }
52         skp->playback(bisect.get());
53     }
54 
55     return bisect;
56 }
57 
BisectSlide(const char filepath[])58 BisectSlide::BisectSlide(const char filepath[])
59         : SkCanvas(4096, 4096, nullptr)
60         , fFilePath(filepath) {
61     const char* basename = strrchr(fFilePath.c_str(), SkOSPath::SEPARATOR);
62     fName.printf("BISECT_%s", basename ? basename + 1 : fFilePath.c_str());
63 }
64 
65 // Called through SkPicture::playback only during creation.
onDrawPath(const SkPath & path,const SkPaint & paint)66 void BisectSlide::onDrawPath(const SkPath& path, const SkPaint& paint) {
67     SkRect bounds;
68     SkIRect ibounds;
69     this->getTotalMatrix().mapRect(&bounds, path.getBounds());
70     bounds.roundOut(&ibounds);
71     fDrawBounds.join(ibounds);
72     fFoundPaths.push_back() = {path, paint, this->getTotalMatrix()};
73 }
74 
onChar(SkUnichar c)75 bool BisectSlide::onChar(SkUnichar c) {
76     switch (c) {
77         case 'X':
78             if (!fTossedPaths.empty()) {
79                 using std::swap;
80                 swap(fFoundPaths, fTossedPaths);
81                 if ('X' == fTrail.back()) {
82                     fTrail.pop_back();
83                 } else {
84                     fTrail.push_back('X');
85                 }
86             }
87             return true;
88 
89         case 'x':
90             if (fFoundPaths.count() > 1) {
91                 int midpt = (fFoundPaths.count() + 1) / 2;
92                 fPathHistory.emplace(fFoundPaths, fTossedPaths);
93                 fTossedPaths.reset(fFoundPaths.begin() + midpt, fFoundPaths.count() - midpt);
94                 fFoundPaths.resize_back(midpt);
95                 fTrail.push_back('x');
96             }
97             return true;
98 
99         case 'Z': {
100             if (!fPathHistory.empty()) {
101                 fFoundPaths = fPathHistory.top().first;
102                 fTossedPaths = fPathHistory.top().second;
103                 fPathHistory.pop();
104                 char ch;
105                 do {
106                     ch = fTrail.back();
107                     fTrail.pop_back();
108                 } while (ch != 'x');
109             }
110             return true;
111         }
112 
113         case 'D':
114             SkDebugf("viewer --bisect %s", fFilePath.c_str());
115             if (!fTrail.empty()) {
116                 SkDebugf(" ");
117                 for (char ch : fTrail) {
118                     SkDebugf("%c", ch);
119                 }
120             }
121             SkDebugf("\n");
122             for (const FoundPath& foundPath : fFoundPaths) {
123                 foundPath.fPath.dump();
124             }
125             return true;
126     }
127 
128     return false;
129 }
130 
draw(SkCanvas * canvas)131 void BisectSlide::draw(SkCanvas* canvas) {
132     SkAutoCanvasRestore acr(canvas, true);
133     canvas->translate(-fDrawBounds.left(), -fDrawBounds.top());
134 
135     for (const FoundPath& path : fFoundPaths) {
136         SkAutoCanvasRestore acr(canvas, true);
137         canvas->concat(path.fViewMatrix);
138         canvas->drawPath(path.fPath, path.fPaint);
139     }
140 }
141