/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "DecodeFile.h" #include "SampleCode.h" #include "SkDumpCanvas.h" #include "SkView.h" #include "SkCanvas.h" #include "SkGradientShader.h" #include "SkGraphics.h" #include "SkOSFile.h" #include "SkOSPath.h" #include "SkPath.h" #include "SkPicture.h" #include "SkPictureRecorder.h" #include "SkRandom.h" #include "SkRegion.h" #include "SkShader.h" #include "SkUtils.h" #include "SkColorPriv.h" #include "SkColorFilter.h" #include "SkTime.h" #include "SkTypeface.h" #include "SkStream.h" #include "SkSurface.h" #include "SkGlyphCache.h" #include "SkDrawFilter.h" class SkCounterDrawFilter : public SkDrawFilter { public: SkCounterDrawFilter(int count) : fCount(count) {} bool filter(SkPaint*, Type t) override { return --fCount >= 0; } int fCount; }; class PictFileView : public SampleView { public: PictFileView(const char name[] = nullptr) : fFilename(name) , fBBox(kNo_BBoxType) , fTileSize(SkSize::Make(0, 0)) { for (int i = 0; i < kBBoxTypeCount; ++i) { fPictures[i] = nullptr; } fCount = 0; } ~PictFileView() override { this->freePictures(); } void freePictures() { for (int i = 0; i < kBBoxTypeCount; ++i) { SkSafeUnref(fPictures[i]); fPictures[i] = nullptr; } } void onTileSizeChanged(const SkSize &tileSize) override { if (tileSize != fTileSize) { fTileSize = tileSize; } } protected: // overrides from SkEventSink bool onQuery(SkEvent* evt) override { if (SampleCode::TitleQ(*evt)) { SkString name("P:"); const char* basename = strrchr(fFilename.c_str(), SkOSPath::SEPARATOR); name.append(basename ? basename+1: fFilename.c_str()); switch (fBBox) { case kNo_BBoxType: // No name appended break; case kRTree_BBoxType: name.append(" "); break; default: SkASSERT(false); break; } SampleCode::TitleR(evt, name.c_str()); return true; } SkUnichar uni; if (SampleCode::CharQ(*evt, &uni)) { switch (uni) { case 'n': fCount += 1; this->inval(nullptr); return true; case 'p': fCount -= 1; this->inval(nullptr); return true; case 's': fCount = 0; this->inval(nullptr); return true; case 'F': fFilterQuality = (kNone_SkFilterQuality == fFilterQuality) ? kHigh_SkFilterQuality : kNone_SkFilterQuality; this->freePictures(); this->inval(nullptr); return true; default: break; } } return this->INHERITED::onQuery(evt); } bool onEvent(const SkEvent& evt) override { if (evt.isType("PictFileView::toggleBBox")) { fBBox = (BBoxType)((fBBox + 1) % kBBoxTypeCount); return true; } return this->INHERITED::onEvent(evt); } void onDrawContent(SkCanvas* canvas) override { SkASSERT(static_cast(fBBox) < kBBoxTypeCount); SkPicture** picture = fPictures + fBBox; #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS SkGraphics::PurgeFontCache(); #endif if (!*picture) { *picture = LoadPicture(fFilename.c_str(), fBBox).release(); } if (*picture) { SkCounterDrawFilter filter(fCount); if (fCount > 0) { canvas->setDrawFilter(&filter); } canvas->drawPicture(*picture); canvas->setDrawFilter(nullptr); } #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS SkGlyphCache::Dump(); SkDebugf("\n"); #endif } private: enum BBoxType { kNo_BBoxType, kRTree_BBoxType, kLast_BBoxType = kRTree_BBoxType, }; static const int kBBoxTypeCount = kLast_BBoxType + 1; SkString fFilename; SkPicture* fPictures[kBBoxTypeCount]; BBoxType fBBox; SkSize fTileSize; int fCount; SkFilterQuality fFilterQuality = kNone_SkFilterQuality; sk_sp LoadPicture(const char path[], BBoxType bbox) { sk_sp pic; if (sk_sp img = decode_file(path)) { SkPictureRecorder recorder; SkCanvas* can = recorder.beginRecording(SkIntToScalar(img->width()), SkIntToScalar(img->height()), nullptr, 0); SkPaint paint; paint.setFilterQuality(fFilterQuality); can->drawImage(img, 0, 0, &paint); pic = recorder.finishRecordingAsPicture(); } else { SkFILEStream stream(path); if (stream.isValid()) { pic = SkPicture::MakeFromStream(&stream); } else { SkDebugf("coun't load picture at \"path\"\n", path); } if (false) { // re-record SkPictureRecorder recorder; pic->playback(recorder.beginRecording(pic->cullRect().width(), pic->cullRect().height(), nullptr, 0)); sk_sp p2(recorder.finishRecordingAsPicture()); SkString path2(path); path2.append(".new.skp"); SkFILEWStream writer(path2.c_str()); p2->serialize(&writer); } } if (nullptr == pic) { return nullptr; } std::unique_ptr factory; switch (bbox) { case kNo_BBoxType: // no bbox playback necessary return pic; case kRTree_BBoxType: factory.reset(new SkRTreeFactory); break; default: SkASSERT(false); } SkPictureRecorder recorder; pic->playback(recorder.beginRecording(pic->cullRect().width(), pic->cullRect().height(), factory.get(), 0)); return recorder.finishRecordingAsPicture(); } typedef SampleView INHERITED; }; SampleView* CreateSamplePictFileView(const char filename[]); SampleView* CreateSamplePictFileView(const char filename[]) { return new PictFileView(filename); } ////////////////////////////////////////////////////////////////////////////// #if 0 static SkView* MyFactory() { return new PictFileView; } static SkViewRegister reg(MyFactory); #endif