/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "tools/viewer/BisectSlide.h" #include "include/core/SkStream.h" #include "src/utils/SkOSPath.h" #include "tools/ToolUtils.h" #include sk_sp BisectSlide::Create(const char filepath[]) { SkFILEStream stream(filepath); if (!stream.isValid()) { SkDebugf("BISECT: invalid input file at \"%s\"\n", filepath); return nullptr; } sk_sp bisect(new BisectSlide(filepath)); ToolUtils::sniff_paths(filepath, [&](const SkMatrix& matrix, const SkPath& path, const SkPaint& paint) { SkRect bounds; SkIRect ibounds; matrix.mapRect(&bounds, path.getBounds()); bounds.roundOut(&ibounds); bisect->fDrawBounds.join(ibounds); bisect->fFoundPaths.push_back() = {path, paint, matrix}; }); return bisect; } BisectSlide::BisectSlide(const char filepath[]) : fFilePath(filepath) { const char* basename = strrchr(fFilePath.c_str(), SkOSPath::SEPARATOR); fName.printf("BISECT_%s", basename ? basename + 1 : fFilePath.c_str()); } bool BisectSlide::onChar(SkUnichar c) { switch (c) { case 'X': if (!fTossedPaths.empty()) { using std::swap; swap(fFoundPaths, fTossedPaths); if ('X' == fTrail.back()) { fTrail.pop_back(); } else { fTrail.push_back('X'); } } return true; case 'x': if (fFoundPaths.count() > 1) { int midpt = (fFoundPaths.count() + 1) / 2; fPathHistory.emplace(fFoundPaths, fTossedPaths); fTossedPaths.reset(fFoundPaths.begin() + midpt, fFoundPaths.count() - midpt); fFoundPaths.resize_back(midpt); fTrail.push_back('x'); } return true; case 'Z': { if (!fPathHistory.empty()) { fFoundPaths = fPathHistory.top().first; fTossedPaths = fPathHistory.top().second; fPathHistory.pop(); char ch; do { ch = fTrail.back(); fTrail.pop_back(); } while (ch != 'x'); } return true; } case 'D': SkDebugf("viewer --bisect %s", fFilePath.c_str()); if (!fTrail.empty()) { SkDebugf(" "); for (char ch : fTrail) { SkDebugf("%c", ch); } } SkDebugf("\n"); for (const FoundPath& foundPath : fFoundPaths) { foundPath.fPath.dump(); } return true; } return false; } void BisectSlide::draw(SkCanvas* canvas) { SkAutoCanvasRestore acr(canvas, true); canvas->translate(-fDrawBounds.left(), -fDrawBounds.top()); for (const FoundPath& path : fFoundPaths) { SkAutoCanvasRestore acr2(canvas, true); canvas->concat(path.fViewMatrix); canvas->drawPath(path.fPath, path.fPaint); } }