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