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