Home | History | Annotate | Download | only in viewer
      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 "BisectSlide.h"
      9 
     10 #include "SkOSPath.h"
     11 #include "SkPicture.h"
     12 #include "SkStream.h"
     13 
     14 #include <utility>
     15 
     16 #ifdef SK_XML
     17 #include "SkDOM.h"
     18 #include "../experimental/svg/model/SkSVGDOM.h"
     19 #endif
     20 
     21 sk_sp<BisectSlide> BisectSlide::Create(const char filepath[]) {
     22     SkFILEStream stream(filepath);
     23     if (!stream.isValid()) {
     24         SkDebugf("BISECT: invalid input file at \"%s\"\n", filepath);
     25         return nullptr;
     26     }
     27 
     28     sk_sp<BisectSlide> bisect(new BisectSlide(filepath));
     29     if (bisect->fFilePath.endsWith(".svg")) {
     30 #ifdef SK_XML
     31         SkDOM xml;
     32         if (!xml.build(stream)) {
     33             SkDebugf("BISECT: XML parsing failed: \"%s\"\n", filepath);
     34             return nullptr;
     35         }
     36         sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromDOM(xml);
     37         if (!svg) {
     38             SkDebugf("BISECT: couldn't load svg at \"%s\"\n", filepath);
     39             return nullptr;
     40         }
     41         svg->setContainerSize(SkSize::Make(bisect->getDimensions()));
     42         svg->render(bisect.get());
     43 #else
     44         return nullptr;
     45 #endif
     46     } else {
     47         sk_sp<SkPicture> skp = SkPicture::MakeFromStream(&stream);
     48         if (!skp) {
     49             SkDebugf("BISECT: couldn't load skp at \"%s\"\n", filepath);
     50             return nullptr;
     51         }
     52         skp->playback(bisect.get());
     53     }
     54 
     55     return bisect;
     56 }
     57 
     58 BisectSlide::BisectSlide(const char filepath[])
     59         : SkCanvas(4096, 4096, nullptr)
     60         , fFilePath(filepath) {
     61     const char* basename = strrchr(fFilePath.c_str(), SkOSPath::SEPARATOR);
     62     fName.printf("BISECT_%s", basename ? basename + 1 : fFilePath.c_str());
     63 }
     64 
     65 // Called through SkPicture::playback only during creation.
     66 void BisectSlide::onDrawPath(const SkPath& path, const SkPaint& paint) {
     67     SkRect bounds;
     68     SkIRect ibounds;
     69     this->getTotalMatrix().mapRect(&bounds, path.getBounds());
     70     bounds.roundOut(&ibounds);
     71     fDrawBounds.join(ibounds);
     72     fFoundPaths.push_back() = {path, paint, this->getTotalMatrix()};
     73 }
     74 
     75 bool BisectSlide::onChar(SkUnichar c) {
     76     switch (c) {
     77         case 'X':
     78             if (!fTossedPaths.empty()) {
     79                 using std::swap;
     80                 swap(fFoundPaths, fTossedPaths);
     81                 if ('X' == fTrail.back()) {
     82                     fTrail.pop_back();
     83                 } else {
     84                     fTrail.push_back('X');
     85                 }
     86             }
     87             return true;
     88 
     89         case 'x':
     90             if (fFoundPaths.count() > 1) {
     91                 int midpt = (fFoundPaths.count() + 1) / 2;
     92                 fPathHistory.emplace(fFoundPaths, fTossedPaths);
     93                 fTossedPaths.reset(fFoundPaths.begin() + midpt, fFoundPaths.count() - midpt);
     94                 fFoundPaths.resize_back(midpt);
     95                 fTrail.push_back('x');
     96             }
     97             return true;
     98 
     99         case 'Z': {
    100             if (!fPathHistory.empty()) {
    101                 fFoundPaths = fPathHistory.top().first;
    102                 fTossedPaths = fPathHistory.top().second;
    103                 fPathHistory.pop();
    104                 char ch;
    105                 do {
    106                     ch = fTrail.back();
    107                     fTrail.pop_back();
    108                 } while (ch != 'x');
    109             }
    110             return true;
    111         }
    112 
    113         case 'D':
    114             SkDebugf("viewer --bisect %s", fFilePath.c_str());
    115             if (!fTrail.empty()) {
    116                 SkDebugf(" ");
    117                 for (char ch : fTrail) {
    118                     SkDebugf("%c", ch);
    119                 }
    120             }
    121             SkDebugf("\n");
    122             for (const FoundPath& foundPath : fFoundPaths) {
    123                 foundPath.fPath.dump();
    124             }
    125             return true;
    126     }
    127 
    128     return false;
    129 }
    130 
    131 void BisectSlide::draw(SkCanvas* canvas) {
    132     SkAutoCanvasRestore acr(canvas, true);
    133     canvas->translate(-fDrawBounds.left(), -fDrawBounds.top());
    134 
    135     for (const FoundPath& path : fFoundPaths) {
    136         SkAutoCanvasRestore acr(canvas, true);
    137         canvas->concat(path.fViewMatrix);
    138         canvas->drawPath(path.fPath, path.fPaint);
    139     }
    140 }
    141