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