From 8c67909e0443d0419edbb3743fed57df063850f6 Mon Sep 17 00:00:00 2001 From: csmartdalton Date: Mon, 27 Mar 2017 12:32:29 -0600 Subject: Add a simple tool for isolating a path from an SKP BUG=skia: Change-Id: I5ca9bbd43919e3f65ea940847c68f85cc78dfeda Reviewed-on: https://skia-review.googlesource.com/10130 Commit-Queue: Chris Dalton Reviewed-by: Jim Van Verth --- samplecode/SamplePathFinder.cpp | 158 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 samplecode/SamplePathFinder.cpp (limited to 'samplecode/SamplePathFinder.cpp') diff --git a/samplecode/SamplePathFinder.cpp b/samplecode/SamplePathFinder.cpp new file mode 100644 index 0000000000..2cbfdc3ba2 --- /dev/null +++ b/samplecode/SamplePathFinder.cpp @@ -0,0 +1,158 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SampleCode.h" +#include "SkCanvas.h" +#include "SkCommandLineFlags.h" +#include "SkOSPath.h" +#include "SkPath.h" +#include "SkPicture.h" +#include "SkStream.h" +#include + +DEFINE_string(pathfinderTrail, "", "List of keystrokes to execute upon loading a pathfinder."); + +/** + * This is a simple utility designed to extract the paths from an SKP file and then isolate a single + * one of them. Use the 'x' and 'X' keys to guide a binary search: + * + * 'x': Throw out half the paths. + * 'X': Toggle which half gets tossed and which half is kept. + * 'Z': Back up one level. + * 'D': Dump the path. + */ +class PathFinderView : public SampleView, public SkCanvas { +public: + PathFinderView(const char name[] = nullptr) + : SkCanvas(4096, 4096, nullptr) + , fFilename(name) { + SkFILEStream stream(fFilename.c_str()); + if (!stream.isValid()) { + SkDebugf("couldn't load picture at \"%s\"\n", fFilename.c_str()); + return; + } + sk_sp pic = SkPicture::MakeFromStream(&stream); + if (!pic) { + SkDebugf("couldn't load picture at \"%s\"\n", fFilename.c_str()); + return; + } + pic->playback(this); + for (int i = 0; i < FLAGS_pathfinderTrail.count(); ++i) { + const char* key = FLAGS_pathfinderTrail[i]; + while (*key) { + this->handleKeystroke(*key++); + } + } + } + + ~PathFinderView() override {} + +private: + // Called through SkPicture::playback during construction. + void onDrawPath(const SkPath& path, const SkPaint& paint) override { + fPaths.push_back() = {path, paint, this->getTotalMatrix()}; + } + + // overrides from SkEventSink + bool onQuery(SkEvent* evt) override { + if (SampleCode::TitleQ(*evt)) { + SkString name("PATHFINDER:"); + const char* basename = strrchr(fFilename.c_str(), SkOSPath::SEPARATOR); + name.append(basename ? basename+1: fFilename.c_str()); + SampleCode::TitleR(evt, name.c_str()); + return true; + } + SkUnichar key; + if (SampleCode::CharQ(*evt, &key)) { + if (this->handleKeystroke(key)) { + return true; + } + } + return this->INHERITED::onQuery(evt); + } + + bool handleKeystroke(SkUnichar key) { + switch (key) { + case 'X': + if (!fTossedPaths.empty()) { + SkTSwap(fPaths, fTossedPaths); + if ('X' == fTrail.back()) { + fTrail.pop_back(); + } else { + fTrail.push_back('X'); + } + this->inval(nullptr); + } + return true; + case 'x': + if (fPaths.count() > 1) { + int midpt = (fPaths.count() + 1) / 2; + fPathHistory.emplace(fPaths, fTossedPaths); + fTossedPaths.reset(fPaths.begin() + midpt, fPaths.count() - midpt); + fPaths.resize_back(midpt); + fTrail.push_back('x'); + this->inval(nullptr); + } + return true; + case 'Z': { + if (!fPathHistory.empty()) { + fPaths = fPathHistory.top().first; + fTossedPaths = fPathHistory.top().second; + fPathHistory.pop(); + char ch; + do { + ch = fTrail.back(); + fTrail.pop_back(); + } while (ch != 'x'); + this->inval(nullptr); + } + return true; + } + case 'D': + SkDebugf("SampleApp --pathfinder %s", fFilename.c_str()); + if (!fTrail.empty()) { + SkDebugf(" --pathfinderTrail ", fFilename.c_str()); + for (char ch : fTrail) { + SkDebugf("%c", ch); + } + } + SkDebugf("\n"); + for (const FoundPath& foundPath : fPaths) { + foundPath.fPath.dump(); + } + return true; + } + return false; + } + + void onDrawContent(SkCanvas* canvas) override { + for (const FoundPath& path : fPaths) { + SkAutoCanvasRestore acr(canvas, true); + canvas->concat(path.fViewMatrix); + canvas->drawPath(path.fPath, path.fPaint); + } + } + + struct FoundPath { + SkPath fPath; + SkPaint fPaint; + SkMatrix fViewMatrix; + }; + + SkString fFilename; + SkTArray fPaths; + SkTArray fTossedPaths; + SkTArray fTrail; + + std::stack, SkTArray>> fPathHistory; + + typedef SampleView INHERITED; +}; + +SampleView* CreateSamplePathFinderView(const char filename[]) { + return new PathFinderView(filename); +} -- cgit v1.2.3