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