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 "gm.h" 9 10 #include "Resources.h" 11 #include "SampleCode.h" 12 #include "SkCanvas.h" 13 #include "SkColorFilter.h" 14 #include "SkColorPriv.h" 15 #include "SkData.h" 16 #include "SkDecodingImageGenerator.h" 17 #include "SkDumpCanvas.h" 18 #include "SkGradientShader.h" 19 #include "SkGraphics.h" 20 #include "SkImageDecoder.h" 21 #include "SkOSFile.h" 22 #include "SkPath.h" 23 #include "SkPicture.h" 24 #include "SkPictureRecorder.h" 25 #include "SkRandom.h" 26 #include "SkRegion.h" 27 #include "SkShader.h" 28 #include "SkStream.h" 29 #include "SkTime.h" 30 #include "SkTypeface.h" 31 #include "SkUtils.h" 32 #include "SkView.h" 33 #include "SkXMLParser.h" 34 #include "SkXfermode.h" 35 36 /////////////////////////////////////////////////////////////////////////////// 37 38 static SkBitmap load_bitmap() { 39 SkBitmap bm; 40 SkString resourcePath = GetResourcePath(); 41 SkString path = SkOSPath::SkPathJoin(resourcePath.c_str(), "mandrill_512.png"); 42 SkAutoDataUnref data(SkData::NewFromFileName(path.c_str())); 43 if (data.get() != NULL) { 44 SkInstallDiscardablePixelRef(SkDecodingImageGenerator::Create( 45 data, SkDecodingImageGenerator::Options()), &bm); 46 } 47 return bm; 48 } 49 50 static void drawCircle(SkCanvas* canvas, int r, SkColor color) { 51 SkPaint paint; 52 paint.setAntiAlias(true); 53 paint.setColor(color); 54 55 canvas->drawCircle(SkIntToScalar(r), SkIntToScalar(r), SkIntToScalar(r), 56 paint); 57 } 58 59 class PictureView : public SampleView { 60 SkBitmap fBitmap; 61 public: 62 PictureView() { 63 64 fBitmap = load_bitmap(); 65 66 SkPictureRecorder recorder; 67 68 recorder.beginRecording(100, 100, NULL, 0); 69 fSubPicture = recorder.endRecording(); 70 71 SkCanvas* canvas = recorder.beginRecording(100, 100, NULL, 0); 72 SkPaint paint; 73 paint.setAntiAlias(true); 74 75 canvas->drawBitmap(fBitmap, 0, 0, NULL); 76 77 drawCircle(canvas, 50, SK_ColorBLACK); 78 canvas->drawPicture(fSubPicture); 79 canvas->translate(SkIntToScalar(50), 0); 80 canvas->drawPicture(fSubPicture); 81 canvas->translate(0, SkIntToScalar(50)); 82 canvas->drawPicture(fSubPicture); 83 canvas->translate(SkIntToScalar(-50), 0); 84 canvas->drawPicture(fSubPicture); 85 86 fPicture = recorder.endRecording(); 87 88 // fPicture now has (4) references to fSubPicture. We can release our ref, 89 // and just unref fPicture in our destructor, and it will in turn take care of 90 // the other references to fSubPicture 91 fSubPicture->unref(); 92 } 93 94 virtual ~PictureView() { 95 fPicture->unref(); 96 } 97 98 protected: 99 // overrides from SkEventSink 100 virtual bool onQuery(SkEvent* evt) { 101 if (SampleCode::TitleQ(*evt)) { 102 SampleCode::TitleR(evt, "Picture"); 103 return true; 104 } 105 return this->INHERITED::onQuery(evt); 106 } 107 108 void drawSomething(SkCanvas* canvas) { 109 SkPaint paint; 110 111 canvas->save(); 112 canvas->scale(0.5f, 0.5f); 113 canvas->drawBitmap(fBitmap, 0, 0, NULL); 114 canvas->restore(); 115 116 const char beforeStr[] = "before circle"; 117 const char afterStr[] = "after circle"; 118 119 paint.setAntiAlias(true); 120 121 paint.setColor(SK_ColorRED); 122 canvas->drawData(beforeStr, sizeof(beforeStr)); 123 canvas->drawCircle(SkIntToScalar(50), SkIntToScalar(50), 124 SkIntToScalar(40), paint); 125 canvas->drawData(afterStr, sizeof(afterStr)); 126 paint.setColor(SK_ColorBLACK); 127 paint.setTextSize(SkIntToScalar(40)); 128 canvas->drawText("Picture", 7, SkIntToScalar(50), SkIntToScalar(62), 129 paint); 130 131 } 132 133 virtual void onDrawContent(SkCanvas* canvas) { 134 this->drawSomething(canvas); 135 136 SkPictureRecorder recorder; 137 this->drawSomething(recorder.beginRecording(100, 100, NULL, 0)); 138 SkAutoTUnref<SkPicture> pict(recorder.endRecording()); 139 140 canvas->save(); 141 canvas->translate(SkIntToScalar(300), SkIntToScalar(50)); 142 canvas->scale(-SK_Scalar1, -SK_Scalar1); 143 canvas->translate(-SkIntToScalar(100), -SkIntToScalar(50)); 144 canvas->drawPicture(pict); 145 canvas->restore(); 146 147 canvas->save(); 148 canvas->translate(SkIntToScalar(200), SkIntToScalar(150)); 149 canvas->scale(SK_Scalar1, -SK_Scalar1); 150 canvas->translate(0, -SkIntToScalar(50)); 151 canvas->drawPicture(pict); 152 canvas->restore(); 153 154 canvas->save(); 155 canvas->translate(SkIntToScalar(100), SkIntToScalar(100)); 156 canvas->scale(-SK_Scalar1, SK_Scalar1); 157 canvas->translate(-SkIntToScalar(100), 0); 158 canvas->drawPicture(pict); 159 canvas->restore(); 160 161 #ifdef SK_DEVELOPER 162 if (false) { 163 SkDebugfDumper dumper; 164 SkDumpCanvas dumpCanvas(&dumper); 165 dumpCanvas.drawPicture(pict); 166 } 167 #endif 168 169 // This used to re-record the sub-picture and redraw the parent 170 // A capability that is now forbidden! 171 172 SkRandom rand(SampleCode::GetAnimTime()); 173 canvas->translate(SkIntToScalar(10), SkIntToScalar(250)); 174 canvas->drawPicture(fPicture); 175 delayInval(500); 176 } 177 178 private: 179 #define INVAL_ALL_TYPE "inval-all" 180 181 void delayInval(SkMSec delay) { 182 (new SkEvent(INVAL_ALL_TYPE, this->getSinkID()))->postDelay(delay); 183 } 184 185 virtual bool onEvent(const SkEvent& evt) { 186 if (evt.isType(INVAL_ALL_TYPE)) { 187 this->inval(NULL); 188 return true; 189 } 190 return this->INHERITED::onEvent(evt); 191 } 192 193 SkPicture* fPicture; 194 SkPicture* fSubPicture; 195 196 typedef SampleView INHERITED; 197 }; 198 199 ////////////////////////////////////////////////////////////////////////////// 200 201 static SkView* MyFactory() { return new PictureView; } 202 static SkViewRegister reg(MyFactory); 203