18c67909e0443d0419edbb3743fed57df063850f6csmartdalton/* 28c67909e0443d0419edbb3743fed57df063850f6csmartdalton * Copyright 2017 Google Inc. 38c67909e0443d0419edbb3743fed57df063850f6csmartdalton * 48c67909e0443d0419edbb3743fed57df063850f6csmartdalton * Use of this source code is governed by a BSD-style license that can be 58c67909e0443d0419edbb3743fed57df063850f6csmartdalton * found in the LICENSE file. 68c67909e0443d0419edbb3743fed57df063850f6csmartdalton */ 78c67909e0443d0419edbb3743fed57df063850f6csmartdalton 88c67909e0443d0419edbb3743fed57df063850f6csmartdalton#include "SampleCode.h" 98c67909e0443d0419edbb3743fed57df063850f6csmartdalton#include "SkCanvas.h" 108c67909e0443d0419edbb3743fed57df063850f6csmartdalton#include "SkCommandLineFlags.h" 118c67909e0443d0419edbb3743fed57df063850f6csmartdalton#include "SkOSPath.h" 128c67909e0443d0419edbb3743fed57df063850f6csmartdalton#include "SkPath.h" 138c67909e0443d0419edbb3743fed57df063850f6csmartdalton#include "SkPicture.h" 148c67909e0443d0419edbb3743fed57df063850f6csmartdalton#include "SkStream.h" 158c67909e0443d0419edbb3743fed57df063850f6csmartdalton#include <stack> 168c67909e0443d0419edbb3743fed57df063850f6csmartdalton 178c67909e0443d0419edbb3743fed57df063850f6csmartdaltonDEFINE_string(pathfinderTrail, "", "List of keystrokes to execute upon loading a pathfinder."); 188c67909e0443d0419edbb3743fed57df063850f6csmartdalton 198c67909e0443d0419edbb3743fed57df063850f6csmartdalton/** 208c67909e0443d0419edbb3743fed57df063850f6csmartdalton * This is a simple utility designed to extract the paths from an SKP file and then isolate a single 218c67909e0443d0419edbb3743fed57df063850f6csmartdalton * one of them. Use the 'x' and 'X' keys to guide a binary search: 228c67909e0443d0419edbb3743fed57df063850f6csmartdalton * 238c67909e0443d0419edbb3743fed57df063850f6csmartdalton * 'x': Throw out half the paths. 248c67909e0443d0419edbb3743fed57df063850f6csmartdalton * 'X': Toggle which half gets tossed and which half is kept. 258c67909e0443d0419edbb3743fed57df063850f6csmartdalton * 'Z': Back up one level. 268c67909e0443d0419edbb3743fed57df063850f6csmartdalton * 'D': Dump the path. 278c67909e0443d0419edbb3743fed57df063850f6csmartdalton */ 288c67909e0443d0419edbb3743fed57df063850f6csmartdaltonclass PathFinderView : public SampleView, public SkCanvas { 298c67909e0443d0419edbb3743fed57df063850f6csmartdaltonpublic: 308c67909e0443d0419edbb3743fed57df063850f6csmartdalton PathFinderView(const char name[] = nullptr) 318c67909e0443d0419edbb3743fed57df063850f6csmartdalton : SkCanvas(4096, 4096, nullptr) 328c67909e0443d0419edbb3743fed57df063850f6csmartdalton , fFilename(name) { 338c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkFILEStream stream(fFilename.c_str()); 348c67909e0443d0419edbb3743fed57df063850f6csmartdalton if (!stream.isValid()) { 358c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkDebugf("couldn't load picture at \"%s\"\n", fFilename.c_str()); 368c67909e0443d0419edbb3743fed57df063850f6csmartdalton return; 378c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 388c67909e0443d0419edbb3743fed57df063850f6csmartdalton sk_sp<SkPicture> pic = SkPicture::MakeFromStream(&stream); 398c67909e0443d0419edbb3743fed57df063850f6csmartdalton if (!pic) { 408c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkDebugf("couldn't load picture at \"%s\"\n", fFilename.c_str()); 418c67909e0443d0419edbb3743fed57df063850f6csmartdalton return; 428c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 438c67909e0443d0419edbb3743fed57df063850f6csmartdalton pic->playback(this); 448c67909e0443d0419edbb3743fed57df063850f6csmartdalton for (int i = 0; i < FLAGS_pathfinderTrail.count(); ++i) { 458c67909e0443d0419edbb3743fed57df063850f6csmartdalton const char* key = FLAGS_pathfinderTrail[i]; 468c67909e0443d0419edbb3743fed57df063850f6csmartdalton while (*key) { 478c67909e0443d0419edbb3743fed57df063850f6csmartdalton this->handleKeystroke(*key++); 488c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 498c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 508c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 518c67909e0443d0419edbb3743fed57df063850f6csmartdalton 528c67909e0443d0419edbb3743fed57df063850f6csmartdalton ~PathFinderView() override {} 538c67909e0443d0419edbb3743fed57df063850f6csmartdalton 548c67909e0443d0419edbb3743fed57df063850f6csmartdaltonprivate: 558c67909e0443d0419edbb3743fed57df063850f6csmartdalton // Called through SkPicture::playback during construction. 568c67909e0443d0419edbb3743fed57df063850f6csmartdalton void onDrawPath(const SkPath& path, const SkPaint& paint) override { 578c67909e0443d0419edbb3743fed57df063850f6csmartdalton fPaths.push_back() = {path, paint, this->getTotalMatrix()}; 588c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 598c67909e0443d0419edbb3743fed57df063850f6csmartdalton 608c67909e0443d0419edbb3743fed57df063850f6csmartdalton // overrides from SkEventSink 618c67909e0443d0419edbb3743fed57df063850f6csmartdalton bool onQuery(SkEvent* evt) override { 628c67909e0443d0419edbb3743fed57df063850f6csmartdalton if (SampleCode::TitleQ(*evt)) { 638c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkString name("PATHFINDER:"); 648c67909e0443d0419edbb3743fed57df063850f6csmartdalton const char* basename = strrchr(fFilename.c_str(), SkOSPath::SEPARATOR); 658c67909e0443d0419edbb3743fed57df063850f6csmartdalton name.append(basename ? basename+1: fFilename.c_str()); 668c67909e0443d0419edbb3743fed57df063850f6csmartdalton SampleCode::TitleR(evt, name.c_str()); 678c67909e0443d0419edbb3743fed57df063850f6csmartdalton return true; 688c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 698c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkUnichar key; 708c67909e0443d0419edbb3743fed57df063850f6csmartdalton if (SampleCode::CharQ(*evt, &key)) { 718c67909e0443d0419edbb3743fed57df063850f6csmartdalton if (this->handleKeystroke(key)) { 728c67909e0443d0419edbb3743fed57df063850f6csmartdalton return true; 738c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 748c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 758c67909e0443d0419edbb3743fed57df063850f6csmartdalton return this->INHERITED::onQuery(evt); 768c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 778c67909e0443d0419edbb3743fed57df063850f6csmartdalton 788c67909e0443d0419edbb3743fed57df063850f6csmartdalton bool handleKeystroke(SkUnichar key) { 798c67909e0443d0419edbb3743fed57df063850f6csmartdalton switch (key) { 808c67909e0443d0419edbb3743fed57df063850f6csmartdalton case 'X': 818c67909e0443d0419edbb3743fed57df063850f6csmartdalton if (!fTossedPaths.empty()) { 828c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkTSwap(fPaths, fTossedPaths); 838c67909e0443d0419edbb3743fed57df063850f6csmartdalton if ('X' == fTrail.back()) { 848c67909e0443d0419edbb3743fed57df063850f6csmartdalton fTrail.pop_back(); 858c67909e0443d0419edbb3743fed57df063850f6csmartdalton } else { 868c67909e0443d0419edbb3743fed57df063850f6csmartdalton fTrail.push_back('X'); 878c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 888c67909e0443d0419edbb3743fed57df063850f6csmartdalton this->inval(nullptr); 898c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 908c67909e0443d0419edbb3743fed57df063850f6csmartdalton return true; 918c67909e0443d0419edbb3743fed57df063850f6csmartdalton case 'x': 928c67909e0443d0419edbb3743fed57df063850f6csmartdalton if (fPaths.count() > 1) { 938c67909e0443d0419edbb3743fed57df063850f6csmartdalton int midpt = (fPaths.count() + 1) / 2; 948c67909e0443d0419edbb3743fed57df063850f6csmartdalton fPathHistory.emplace(fPaths, fTossedPaths); 958c67909e0443d0419edbb3743fed57df063850f6csmartdalton fTossedPaths.reset(fPaths.begin() + midpt, fPaths.count() - midpt); 968c67909e0443d0419edbb3743fed57df063850f6csmartdalton fPaths.resize_back(midpt); 978c67909e0443d0419edbb3743fed57df063850f6csmartdalton fTrail.push_back('x'); 988c67909e0443d0419edbb3743fed57df063850f6csmartdalton this->inval(nullptr); 998c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1008c67909e0443d0419edbb3743fed57df063850f6csmartdalton return true; 1018c67909e0443d0419edbb3743fed57df063850f6csmartdalton case 'Z': { 1028c67909e0443d0419edbb3743fed57df063850f6csmartdalton if (!fPathHistory.empty()) { 1038c67909e0443d0419edbb3743fed57df063850f6csmartdalton fPaths = fPathHistory.top().first; 1048c67909e0443d0419edbb3743fed57df063850f6csmartdalton fTossedPaths = fPathHistory.top().second; 1058c67909e0443d0419edbb3743fed57df063850f6csmartdalton fPathHistory.pop(); 1068c67909e0443d0419edbb3743fed57df063850f6csmartdalton char ch; 1078c67909e0443d0419edbb3743fed57df063850f6csmartdalton do { 1088c67909e0443d0419edbb3743fed57df063850f6csmartdalton ch = fTrail.back(); 1098c67909e0443d0419edbb3743fed57df063850f6csmartdalton fTrail.pop_back(); 1108c67909e0443d0419edbb3743fed57df063850f6csmartdalton } while (ch != 'x'); 1118c67909e0443d0419edbb3743fed57df063850f6csmartdalton this->inval(nullptr); 1128c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1138c67909e0443d0419edbb3743fed57df063850f6csmartdalton return true; 1148c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1158c67909e0443d0419edbb3743fed57df063850f6csmartdalton case 'D': 1168c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkDebugf("SampleApp --pathfinder %s", fFilename.c_str()); 1178c67909e0443d0419edbb3743fed57df063850f6csmartdalton if (!fTrail.empty()) { 1188c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkDebugf(" --pathfinderTrail ", fFilename.c_str()); 1198c67909e0443d0419edbb3743fed57df063850f6csmartdalton for (char ch : fTrail) { 1208c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkDebugf("%c", ch); 1218c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1228c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1238c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkDebugf("\n"); 1248c67909e0443d0419edbb3743fed57df063850f6csmartdalton for (const FoundPath& foundPath : fPaths) { 1258c67909e0443d0419edbb3743fed57df063850f6csmartdalton foundPath.fPath.dump(); 1268c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1278c67909e0443d0419edbb3743fed57df063850f6csmartdalton return true; 1288c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1298c67909e0443d0419edbb3743fed57df063850f6csmartdalton return false; 1308c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1318c67909e0443d0419edbb3743fed57df063850f6csmartdalton 1328c67909e0443d0419edbb3743fed57df063850f6csmartdalton void onDrawContent(SkCanvas* canvas) override { 1338c67909e0443d0419edbb3743fed57df063850f6csmartdalton for (const FoundPath& path : fPaths) { 1348c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkAutoCanvasRestore acr(canvas, true); 1358c67909e0443d0419edbb3743fed57df063850f6csmartdalton canvas->concat(path.fViewMatrix); 1368c67909e0443d0419edbb3743fed57df063850f6csmartdalton canvas->drawPath(path.fPath, path.fPaint); 1378c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1388c67909e0443d0419edbb3743fed57df063850f6csmartdalton } 1398c67909e0443d0419edbb3743fed57df063850f6csmartdalton 1408c67909e0443d0419edbb3743fed57df063850f6csmartdalton struct FoundPath { 1418c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkPath fPath; 1428c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkPaint fPaint; 1438c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkMatrix fViewMatrix; 1448c67909e0443d0419edbb3743fed57df063850f6csmartdalton }; 1458c67909e0443d0419edbb3743fed57df063850f6csmartdalton 1468c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkString fFilename; 1478c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkTArray<FoundPath> fPaths; 1488c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkTArray<FoundPath> fTossedPaths; 1498c67909e0443d0419edbb3743fed57df063850f6csmartdalton SkTArray<char> fTrail; 1508c67909e0443d0419edbb3743fed57df063850f6csmartdalton 1518c67909e0443d0419edbb3743fed57df063850f6csmartdalton std::stack<std::pair<SkTArray<FoundPath>, SkTArray<FoundPath>>> fPathHistory; 1528c67909e0443d0419edbb3743fed57df063850f6csmartdalton 1538c67909e0443d0419edbb3743fed57df063850f6csmartdalton typedef SampleView INHERITED; 1548c67909e0443d0419edbb3743fed57df063850f6csmartdalton}; 1558c67909e0443d0419edbb3743fed57df063850f6csmartdalton 1568c67909e0443d0419edbb3743fed57df063850f6csmartdaltonSampleView* CreateSamplePathFinderView(const char filename[]) { 1578c67909e0443d0419edbb3743fed57df063850f6csmartdalton return new PathFinderView(filename); 1588c67909e0443d0419edbb3743fed57df063850f6csmartdalton} 159