diff options
author | csmartdalton <csmartdalton@google.com> | 2017-03-27 12:32:29 -0600 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-03-27 19:19:19 +0000 |
commit | 8c67909e0443d0419edbb3743fed57df063850f6 (patch) | |
tree | cb184d9cbe07503590132f85787b227feb0febfb | |
parent | b338484d23d6fa4d6726361440962e75ec5855e0 (diff) |
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 <csmartdalton@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
-rw-r--r-- | BUILD.gn | 1 | ||||
-rw-r--r-- | gn/samples.gni | 1 | ||||
-rw-r--r-- | samplecode/SampleApp.cpp | 17 | ||||
-rw-r--r-- | samplecode/SamplePathFinder.cpp | 158 |
4 files changed, 177 insertions, 0 deletions
@@ -1113,6 +1113,7 @@ if (skia_enable_tools) { ] deps = [ ":experimental_svg_model", + ":flags", ":gm", ":tool_utils", ":views", diff --git a/gn/samples.gni b/gn/samples.gni index 7f8f3b990a..13a762cf19 100644 --- a/gn/samples.gni +++ b/gn/samples.gni @@ -70,6 +70,7 @@ samples_sources = [ "$_samplecode/SamplePathText.cpp", "$_samplecode/SamplePathClip.cpp", "$_samplecode/SamplePathEffects.cpp", + "$_samplecode/SamplePathFinder.cpp", "$_samplecode/SamplePathFuzz.cpp", "$_samplecode/SamplePathOverstroke.cpp", "$_samplecode/SamplePdfFileViewer.cpp", diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index 6b9a888651..bd7d567575 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -91,6 +91,17 @@ public: } }; +extern SampleView* CreateSamplePathFinderView(const char filename[]); + +class PathFinderFactory : public SkViewFactory { + SkString fFilename; +public: + PathFinderFactory(const SkString& filename) : fFilename(filename) {} + SkView* operator() () const override { + return CreateSamplePathFinderView(fFilename.c_str()); + } +}; + extern SampleView* CreateSampleSVGFileView(const SkString& filename); class SVGFileFactory : public SkViewFactory { @@ -726,6 +737,7 @@ static void restrict_samples(SkTDArray<const SkViewFactory*>& factories, const S DEFINE_string(slide, "", "Start on this sample."); DEFINE_string(pictureDir, "", "Read pictures from here."); DEFINE_string(picture, "", "Path to single picture."); +DEFINE_string(pathfinder, "", "SKP file with a single path to isolate."); DEFINE_string(svg, "", "Path to single SVG file."); DEFINE_string(svgDir, "", "Read SVGs from here."); DEFINE_string(sequence, "", "Path to file containing the desired samples/gms to show."); @@ -765,6 +777,11 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev fCurrIndex = fSamples.count(); *fSamples.append() = new PictFileFactory(path); } + if (!FLAGS_pathfinder.isEmpty()) { + SkString path(FLAGS_pathfinder[0]); + fCurrIndex = fSamples.count(); + *fSamples.append() = new PathFinderFactory(path); + } if (!FLAGS_svg.isEmpty()) { SkString path(FLAGS_svg[0]); fCurrIndex = fSamples.count(); 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 <stack> + +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<SkPicture> 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<FoundPath> fPaths; + SkTArray<FoundPath> fTossedPaths; + SkTArray<char> fTrail; + + std::stack<std::pair<SkTArray<FoundPath>, SkTArray<FoundPath>>> fPathHistory; + + typedef SampleView INHERITED; +}; + +SampleView* CreateSamplePathFinderView(const char filename[]) { + return new PathFinderView(filename); +} |