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