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 16sk_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 37BisectSlide::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 43bool 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 99void 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