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 class PictFileView : public SampleView {
34 public:
PictFileView(const char name[]=NULL)35 PictFileView(const char name[] = NULL)
36 : fFilename(name)
37 , fBBox(kNo_BBoxType)
38 , fTileSize(SkSize::Make(0, 0)) {
39 for (int i = 0; i < kBBoxTypeCount; ++i) {
40 fPictures[i] = NULL;
41 }
42 }
43
~PictFileView()44 virtual ~PictFileView() {
45 for (int i = 0; i < kBBoxTypeCount; ++i) {
46 SkSafeUnref(fPictures[i]);
47 }
48 }
49
onTileSizeChanged(const SkSize & tileSize)50 virtual void onTileSizeChanged(const SkSize &tileSize) SK_OVERRIDE {
51 if (tileSize != fTileSize) {
52 fTileSize = tileSize;
53 SkSafeSetNull(fPictures[kTileGrid_BBoxType]);
54 }
55 }
56
57 protected:
58 // overrides from SkEventSink
onQuery(SkEvent * evt)59 virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
60 if (SampleCode::TitleQ(*evt)) {
61 SkString name("P:");
62 const char* basename = strrchr(fFilename.c_str(), SkPATH_SEPARATOR);
63 name.append(basename ? basename+1: fFilename.c_str());
64 switch (fBBox) {
65 case kNo_BBoxType:
66 // No name appended
67 break;
68 case kRTree_BBoxType:
69 name.append(" <bbox: R>");
70 break;
71 case kTileGrid_BBoxType:
72 name.append(" <bbox: T>");
73 break;
74 default:
75 SkASSERT(false);
76 break;
77 }
78 SampleCode::TitleR(evt, name.c_str());
79 return true;
80 }
81 return this->INHERITED::onQuery(evt);
82 }
83
onEvent(const SkEvent & evt)84 virtual bool onEvent(const SkEvent& evt) SK_OVERRIDE {
85 if (evt.isType("PictFileView::toggleBBox")) {
86 fBBox = (BBoxType)((fBBox + 1) % kBBoxTypeCount);
87 return true;
88 }
89 return this->INHERITED::onEvent(evt);
90 }
91
onDrawContent(SkCanvas * canvas)92 virtual void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
93 SkASSERT(static_cast<int>(fBBox) < kBBoxTypeCount);
94 SkPicture** picture = fPictures + fBBox;
95
96 if (!*picture) {
97 *picture = LoadPicture(fFilename.c_str(), fBBox);
98 }
99 if (*picture) {
100 canvas->drawPicture(*picture);
101 }
102 }
103
104 private:
105 enum BBoxType {
106 kNo_BBoxType,
107 kRTree_BBoxType,
108 kTileGrid_BBoxType,
109
110 kLast_BBoxType = kTileGrid_BBoxType
111 };
112 static const int kBBoxTypeCount = kLast_BBoxType + 1;
113
114 SkString fFilename;
115 SkPicture* fPictures[kBBoxTypeCount];
116 BBoxType fBBox;
117 SkSize fTileSize;
118
LoadPicture(const char path[],BBoxType bbox)119 SkPicture* LoadPicture(const char path[], BBoxType bbox) {
120 SkAutoTUnref<SkPicture> pic;
121
122 SkBitmap bm;
123 if (SkImageDecoder::DecodeFile(path, &bm)) {
124 bm.setImmutable();
125 SkPictureRecorder recorder;
126 SkCanvas* can = recorder.beginRecording(SkIntToScalar(bm.width()),
127 SkIntToScalar(bm.height()),
128 NULL, 0);
129 can->drawBitmap(bm, 0, 0, NULL);
130 pic.reset(recorder.endRecording());
131 } else {
132 SkFILEStream stream(path);
133 if (stream.isValid()) {
134 pic.reset(SkPicture::CreateFromStream(&stream));
135 } else {
136 SkDebugf("coun't load picture at \"path\"\n", path);
137 }
138
139 if (false) {
140 SkSurface* surf = SkSurface::NewRasterPMColor(SkScalarCeilToInt(pic->cullRect().width()),
141 SkScalarCeilToInt(pic->cullRect().height()));
142 surf->getCanvas()->drawPicture(pic);
143 surf->unref();
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 case kTileGrid_BBoxType: {
172 SkASSERT(!fTileSize.isEmpty());
173 SkTileGridFactory::TileGridInfo gridInfo;
174 gridInfo.fMargin = SkISize::Make(0, 0);
175 gridInfo.fOffset = SkIPoint::Make(0, 0);
176 gridInfo.fTileInterval = fTileSize.toRound();
177 factory.reset(SkNEW_ARGS(SkTileGridFactory, (gridInfo)));
178 break;
179 }
180 default:
181 SkASSERT(false);
182 }
183
184 SkPictureRecorder recorder;
185 pic->playback(recorder.beginRecording(pic->cullRect().width(),
186 pic->cullRect().height(),
187 factory.get(), 0));
188 return recorder.endRecording();
189 }
190
191 typedef SampleView INHERITED;
192 };
193
194 SampleView* CreateSamplePictFileView(const char filename[]);
CreateSamplePictFileView(const char filename[])195 SampleView* CreateSamplePictFileView(const char filename[]) {
196 return new PictFileView(filename);
197 }
198
199 //////////////////////////////////////////////////////////////////////////////
200
201 #if 0
202 static SkView* MyFactory() { return new PictFileView; }
203 static SkViewRegister reg(MyFactory);
204 #endif
205