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:
SkCounterDrawFilter(int count)38 SkCounterDrawFilter(int count) : fCount(count) {}
39
filter(SkPaint *,Type t)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:
PictFileView(const char name[]=nullptr)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
~PictFileView()59 virtual ~PictFileView() {
60 for (int i = 0; i < kBBoxTypeCount; ++i) {
61 SkSafeUnref(fPictures[i]);
62 }
63 }
64
onTileSizeChanged(const SkSize & tileSize)65 void onTileSizeChanged(const SkSize &tileSize) override {
66 if (tileSize != fTileSize) {
67 fTileSize = tileSize;
68 }
69 }
70
71 protected:
72 // overrides from SkEventSink
onQuery(SkEvent * evt)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
onEvent(const SkEvent & evt)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
onDrawContent(SkCanvas * canvas)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
LoadPicture(const char path[],BBoxType bbox)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[]);
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