1 /* 2 * Copyright 2011 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 "SampleCode.h" 9 #include "SkDumpCanvas.h" 10 #include "SkView.h" 11 #include "SkCanvas.h" 12 #include "SkGradientShader.h" 13 #include "SkGraphics.h" 14 #include "SkImageDecoder.h" 15 #include "SkOSFile.h" 16 #include "SkPath.h" 17 #include "SkPicture.h" 18 #include "SkPictureRecorder.h" 19 #include "SkRandom.h" 20 #include "SkRegion.h" 21 #include "SkShader.h" 22 #include "SkUtils.h" 23 #include "SkColorPriv.h" 24 #include "SkColorFilter.h" 25 #include "SkTime.h" 26 #include "SkTypeface.h" 27 #include "SkXfermode.h" 28 29 #include "SkStream.h" 30 #include "SkSurface.h" 31 #include "SkXMLParser.h" 32 33 #include "SkGlyphCache.h" 34 35 #include "SkDrawFilter.h" 36 class SkCounterDrawFilter : public SkDrawFilter { 37 public: 38 SkCounterDrawFilter(int count) : fCount(count) {} 39 40 bool filter(SkPaint*, Type t) override { 41 return --fCount >= 0; 42 } 43 44 int fCount; 45 }; 46 47 class PictFileView : public SampleView { 48 public: 49 PictFileView(const char name[] = nullptr) 50 : fFilename(name) 51 , fBBox(kNo_BBoxType) 52 , fTileSize(SkSize::Make(0, 0)) { 53 for (int i = 0; i < kBBoxTypeCount; ++i) { 54 fPictures[i] = nullptr; 55 } 56 fCount = 0; 57 } 58 59 virtual ~PictFileView() { 60 for (int i = 0; i < kBBoxTypeCount; ++i) { 61 SkSafeUnref(fPictures[i]); 62 } 63 } 64 65 void onTileSizeChanged(const SkSize &tileSize) override { 66 if (tileSize != fTileSize) { 67 fTileSize = tileSize; 68 } 69 } 70 71 protected: 72 // overrides from SkEventSink 73 bool onQuery(SkEvent* evt) override { 74 if (SampleCode::TitleQ(*evt)) { 75 SkString name("P:"); 76 const char* basename = strrchr(fFilename.c_str(), SkPATH_SEPARATOR); 77 name.append(basename ? basename+1: fFilename.c_str()); 78 switch (fBBox) { 79 case kNo_BBoxType: 80 // No name appended 81 break; 82 case kRTree_BBoxType: 83 name.append(" <bbox: R>"); 84 break; 85 default: 86 SkASSERT(false); 87 break; 88 } 89 SampleCode::TitleR(evt, name.c_str()); 90 return true; 91 } 92 SkUnichar uni; 93 if (SampleCode::CharQ(*evt, &uni)) { 94 switch (uni) { 95 case 'n': fCount += 1; this->inval(nullptr); return true; 96 case 'p': fCount -= 1; this->inval(nullptr); return true; 97 case 's': fCount = 0; this->inval(nullptr); return true; 98 default: break; 99 } 100 } 101 return this->INHERITED::onQuery(evt); 102 } 103 104 bool onEvent(const SkEvent& evt) override { 105 if (evt.isType("PictFileView::toggleBBox")) { 106 fBBox = (BBoxType)((fBBox + 1) % kBBoxTypeCount); 107 return true; 108 } 109 return this->INHERITED::onEvent(evt); 110 } 111 112 void onDrawContent(SkCanvas* canvas) override { 113 SkASSERT(static_cast<int>(fBBox) < kBBoxTypeCount); 114 SkPicture** picture = fPictures + fBBox; 115 116 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 117 SkGraphics::PurgeFontCache(); 118 #endif 119 120 if (!*picture) { 121 *picture = LoadPicture(fFilename.c_str(), fBBox); 122 } 123 if (*picture) { 124 SkCounterDrawFilter filter(fCount); 125 if (fCount > 0) { 126 canvas->setDrawFilter(&filter); 127 } 128 canvas->drawPicture(*picture); 129 canvas->setDrawFilter(nullptr); 130 } 131 132 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 133 SkGlyphCache::Dump(); 134 SkDebugf("\n"); 135 #endif 136 } 137 138 private: 139 enum BBoxType { 140 kNo_BBoxType, 141 kRTree_BBoxType, 142 143 kLast_BBoxType = kRTree_BBoxType, 144 }; 145 static const int kBBoxTypeCount = kLast_BBoxType + 1; 146 147 SkString fFilename; 148 SkPicture* fPictures[kBBoxTypeCount]; 149 BBoxType fBBox; 150 SkSize fTileSize; 151 int fCount; 152 153 SkPicture* LoadPicture(const char path[], BBoxType bbox) { 154 SkAutoTUnref<SkPicture> pic; 155 156 SkBitmap bm; 157 if (SkImageDecoder::DecodeFile(path, &bm)) { 158 bm.setImmutable(); 159 SkPictureRecorder recorder; 160 SkCanvas* can = recorder.beginRecording(SkIntToScalar(bm.width()), 161 SkIntToScalar(bm.height()), 162 nullptr, 0); 163 can->drawBitmap(bm, 0, 0, nullptr); 164 pic.reset(recorder.endRecording()); 165 } else { 166 SkFILEStream stream(path); 167 if (stream.isValid()) { 168 pic.reset(SkPicture::CreateFromStream(&stream)); 169 } else { 170 SkDebugf("coun't load picture at \"path\"\n", path); 171 } 172 173 if (false) { // re-record 174 SkPictureRecorder recorder; 175 pic->playback(recorder.beginRecording(pic->cullRect().width(), 176 pic->cullRect().height(), 177 nullptr, 0)); 178 SkAutoTUnref<SkPicture> p2(recorder.endRecording()); 179 180 SkString path2(path); 181 path2.append(".new.skp"); 182 SkFILEWStream writer(path2.c_str()); 183 p2->serialize(&writer); 184 } 185 } 186 187 if (nullptr == pic) { 188 return nullptr; 189 } 190 191 SkAutoTDelete<SkBBHFactory> factory; 192 switch (bbox) { 193 case kNo_BBoxType: 194 // no bbox playback necessary 195 return pic.detach(); 196 case kRTree_BBoxType: 197 factory.reset(new SkRTreeFactory); 198 break; 199 default: 200 SkASSERT(false); 201 } 202 203 SkPictureRecorder recorder; 204 pic->playback(recorder.beginRecording(pic->cullRect().width(), 205 pic->cullRect().height(), 206 factory.get(), 0)); 207 return recorder.endRecording(); 208 } 209 210 typedef SampleView INHERITED; 211 }; 212 213 SampleView* CreateSamplePictFileView(const char filename[]); 214 SampleView* CreateSamplePictFileView(const char filename[]) { 215 return new PictFileView(filename); 216 } 217 218 ////////////////////////////////////////////////////////////////////////////// 219 220 #if 0 221 static SkView* MyFactory() { return new PictFileView; } 222 static SkViewRegister reg(MyFactory); 223 #endif 224