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 33class PictFileView : public SampleView { 34public: 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 44 virtual ~PictFileView() { 45 for (int i = 0; i < kBBoxTypeCount; ++i) { 46 SkSafeUnref(fPictures[i]); 47 } 48 } 49 50 virtual void onTileSizeChanged(const SkSize &tileSize) SK_OVERRIDE { 51 if (tileSize != fTileSize) { 52 fTileSize = tileSize; 53 SkSafeSetNull(fPictures[kTileGrid_BBoxType]); 54 } 55 } 56 57protected: 58 // overrides from SkEventSink 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 kQuadTree_BBoxType: 72 name.append(" <bbox: Q>"); 73 break; 74 case kTileGrid_BBoxType: 75 name.append(" <bbox: T>"); 76 break; 77 default: 78 SkASSERT(false); 79 break; 80 } 81 SampleCode::TitleR(evt, name.c_str()); 82 return true; 83 } 84 return this->INHERITED::onQuery(evt); 85 } 86 87 virtual bool onEvent(const SkEvent& evt) SK_OVERRIDE { 88 if (evt.isType("PictFileView::toggleBBox")) { 89 fBBox = (BBoxType)((fBBox + 1) % kBBoxTypeCount); 90 return true; 91 } 92 return this->INHERITED::onEvent(evt); 93 } 94 95 virtual void onDrawContent(SkCanvas* canvas) SK_OVERRIDE { 96 SkASSERT(static_cast<int>(fBBox) < kBBoxTypeCount); 97 SkPicture** picture = fPictures + fBBox; 98 99 if (!*picture) { 100 *picture = LoadPicture(fFilename.c_str(), fBBox); 101 } 102 if (*picture) { 103 canvas->drawPicture(*picture); 104 } 105 } 106 107private: 108 enum BBoxType { 109 kNo_BBoxType, 110 kQuadTree_BBoxType, 111 kRTree_BBoxType, 112 kTileGrid_BBoxType, 113 114 kLast_BBoxType = kTileGrid_BBoxType 115 }; 116 static const int kBBoxTypeCount = kLast_BBoxType + 1; 117 118 SkString fFilename; 119 SkPicture* fPictures[kBBoxTypeCount]; 120 BBoxType fBBox; 121 SkSize fTileSize; 122 123 SkPicture* LoadPicture(const char path[], BBoxType bbox) { 124 SkAutoTUnref<SkPicture> pic; 125 126 SkBitmap bm; 127 if (SkImageDecoder::DecodeFile(path, &bm)) { 128 bm.setImmutable(); 129 SkPictureRecorder recorder; 130 SkCanvas* can = recorder.beginRecording(bm.width(), bm.height(), NULL, 0); 131 can->drawBitmap(bm, 0, 0, NULL); 132 pic.reset(recorder.endRecording()); 133 } else { 134 SkFILEStream stream(path); 135 if (stream.isValid()) { 136 pic.reset(SkPicture::CreateFromStream(&stream)); 137 } else { 138 SkDebugf("coun't load picture at \"path\"\n", path); 139 } 140 141 if (false) { 142 SkSurface* surf = SkSurface::NewRasterPMColor(pic->width(), pic->height()); 143 surf->getCanvas()->drawPicture(pic); 144 surf->unref(); 145 } 146 if (false) { // re-record 147 SkPictureRecorder recorder; 148 pic->draw(recorder.beginRecording(pic->width(), pic->height(), NULL, 0)); 149 SkAutoTUnref<SkPicture> p2(recorder.endRecording()); 150 151 SkString path2(path); 152 path2.append(".new.skp"); 153 SkFILEWStream writer(path2.c_str()); 154 p2->serialize(&writer); 155 } 156 } 157 158 if (NULL == pic) { 159 return NULL; 160 } 161 162 SkAutoTDelete<SkBBHFactory> factory; 163 switch (bbox) { 164 case kNo_BBoxType: 165 // no bbox playback necessary 166 return pic.detach(); 167 case kRTree_BBoxType: 168 factory.reset(SkNEW(SkRTreeFactory)); 169 break; 170 case kQuadTree_BBoxType: 171 factory.reset(SkNEW(SkQuadTreeFactory)); 172 break; 173 case kTileGrid_BBoxType: { 174 SkASSERT(!fTileSize.isEmpty()); 175 SkTileGridFactory::TileGridInfo gridInfo; 176 gridInfo.fMargin = SkISize::Make(0, 0); 177 gridInfo.fOffset = SkIPoint::Make(0, 0); 178 gridInfo.fTileInterval = fTileSize.toRound(); 179 factory.reset(SkNEW_ARGS(SkTileGridFactory, (gridInfo))); 180 break; 181 } 182 default: 183 SkASSERT(false); 184 } 185 186 SkPictureRecorder recorder; 187 pic->draw(recorder.beginRecording(pic->width(), pic->height(), factory.get(), 0)); 188 return recorder.endRecording(); 189 } 190 191 typedef SampleView INHERITED; 192}; 193 194SampleView* CreateSamplePictFileView(const char filename[]); 195SampleView* CreateSamplePictFileView(const char filename[]) { 196 return new PictFileView(filename); 197} 198 199////////////////////////////////////////////////////////////////////////////// 200 201#if 0 202static SkView* MyFactory() { return new PictFileView; } 203static SkViewRegister reg(MyFactory); 204#endif 205