blob: 6c018b70dee845714d26609eaabc3aa23dfb4375 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SampleCode.h"
reed@android.comcb608442009-12-04 21:32:27 +00002#include "SkDumpCanvas.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00003#include "SkView.h"
4#include "SkCanvas.h"
5#include "Sk64.h"
6#include "SkGradientShader.h"
7#include "SkGraphics.h"
8#include "SkImageDecoder.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00009#include "SkPath.h"
10#include "SkPicture.h"
11#include "SkRandom.h"
12#include "SkRegion.h"
13#include "SkShader.h"
14#include "SkUtils.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015#include "SkColorPriv.h"
16#include "SkColorFilter.h"
reed@android.com7d970c72010-04-22 16:07:49 +000017#include "SkShape.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000018#include "SkTime.h"
19#include "SkTypeface.h"
20#include "SkXfermode.h"
21
22#include "SkStream.h"
23#include "SkXMLParser.h"
24
reed@android.com7d970c72010-04-22 16:07:49 +000025class SignalShape : public SkShape {
26public:
27 SignalShape() : fSignal(0) {}
28
29 SkShape* setSignal(int n) {
30 fSignal = n;
31 return this;
32 }
33
34protected:
35 virtual void onDraw(SkCanvas* canvas) {
36 SkDebugf("---- sc %d\n", canvas->getSaveCount() - 1);
37 }
38
39private:
40 int fSignal;
41};
42
43static SkPMColor SignalProc(SkPMColor src, SkPMColor dst) {
44 return dst;
45}
46
47/* Picture playback will skip blocks of draw calls that follow a clip() call
48 that returns empty, and jump down to the corresponding restore() call.
49
50 This is a great preformance win for drawing very large/tall pictures with
51 a small visible window (think scrolling a long document). These tests make
52 sure that (a) we are performing the culling, and (b) we don't get confused
53 by nested save() calls, nor by calls to restoreToCount().
54 */
55static void test_saveRestoreCulling() {
56 SkPaint signalPaint;
57 SignalShape signalShape;
58
59 SkPicture pic;
60 SkRect r = SkRect::MakeWH(0, 0);
61 int n;
62 SkCanvas* canvas = pic.beginRecording(100, 100);
63 int startN = canvas->getSaveCount();
64 SkDebugf("---- start sc %d\n", startN);
65 canvas->drawShape(signalShape.setSignal(1));
66 canvas->save();
67 canvas->drawShape(signalShape.setSignal(2));
68 n = canvas->save();
69 canvas->drawShape(signalShape.setSignal(3));
70 canvas->save();
71 canvas->clipRect(r);
72 canvas->drawShape(signalShape.setSignal(4));
73 canvas->restoreToCount(n);
74 canvas->drawShape(signalShape.setSignal(5));
75 canvas->restore();
76 canvas->drawShape(signalShape.setSignal(6));
77 SkASSERT(canvas->getSaveCount() == startN);
78
79 SkBitmap bm;
80 bm.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
81 bm.allocPixels();
82 SkCanvas c(bm);
83 c.drawPicture(pic);
84}
85
86///////////////////////////////////////////////////////////////////////////////
87
reed@android.comc6ddc112009-11-10 15:54:55 +000088#include "SkImageRef_GlobalPool.h"
89
90static SkBitmap load_bitmap() {
91 SkStream* stream = new SkFILEStream("/skimages/sesame_street_ensemble-hp.jpg");
92 SkAutoUnref aur(stream);
93
94 SkBitmap bm;
95 if (SkImageDecoder::DecodeStream(stream, &bm, SkBitmap::kNo_Config,
96 SkImageDecoder::kDecodeBounds_Mode)) {
97 SkPixelRef* pr = new SkImageRef_GlobalPool(stream, bm.config(), 1);
98 bm.setPixelRef(pr)->unref();
99 }
100 return bm;
101}
102
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103static void drawCircle(SkCanvas* canvas, int r, SkColor color) {
104 SkPaint paint;
105 paint.setAntiAlias(true);
106 paint.setColor(color);
107
108 canvas->drawCircle(SkIntToScalar(r), SkIntToScalar(r), SkIntToScalar(r),
109 paint);
110}
111
112class PictureView : public SkView {
reed@android.comc6ddc112009-11-10 15:54:55 +0000113 SkBitmap fBitmap;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114public:
115 PictureView() {
reed@android.comc6ddc112009-11-10 15:54:55 +0000116 SkImageRef_GlobalPool::SetRAMBudget(16 * 1024);
117
118 fBitmap = load_bitmap();
119
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120 fPicture = new SkPicture;
121 SkCanvas* canvas = fPicture->beginRecording(100, 100);
122 SkPaint paint;
123 paint.setAntiAlias(true);
124
reed@android.comc6ddc112009-11-10 15:54:55 +0000125 canvas->drawBitmap(fBitmap, 0, 0, NULL);
126
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 drawCircle(canvas, 50, SK_ColorBLACK);
128 fSubPicture = new SkPicture;
129 canvas->drawPicture(*fSubPicture);
130 canvas->translate(SkIntToScalar(50), 0);
131 canvas->drawPicture(*fSubPicture);
132 canvas->translate(0, SkIntToScalar(50));
133 canvas->drawPicture(*fSubPicture);
134 canvas->translate(SkIntToScalar(-50), 0);
135 canvas->drawPicture(*fSubPicture);
136 // fPicture now has (4) references to us. We can release ours, and just
137 // unref fPicture in our destructor, and it will in turn take care of
138 // the other references to fSubPicture
139 fSubPicture->unref();
reed@android.com7d970c72010-04-22 16:07:49 +0000140
141 test_saveRestoreCulling();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000142 }
143
144 virtual ~PictureView() {
145 fPicture->unref();
146 }
147
148protected:
149 // overrides from SkEventSink
150 virtual bool onQuery(SkEvent* evt) {
151 if (SampleCode::TitleQ(*evt)) {
152 SampleCode::TitleR(evt, "Picture");
153 return true;
154 }
155 return this->INHERITED::onQuery(evt);
156 }
157
158 void drawBG(SkCanvas* canvas) {
159// canvas->drawColor(0xFFDDDDDD);
160 canvas->drawColor(SK_ColorWHITE);
161 // canvas->drawColor(SK_ColorBLACK);
162 }
163
164 void drawSomething(SkCanvas* canvas) {
165 SkPaint paint;
reed@android.comc6ddc112009-11-10 15:54:55 +0000166
167 canvas->save();
168 canvas->scale(0.5f, 0.5f);
169 canvas->drawBitmap(fBitmap, 0, 0, NULL);
170 canvas->restore();
171
reed@android.comcb608442009-12-04 21:32:27 +0000172 const char beforeStr[] = "before circle";
173 const char afterStr[] = "after circle";
174
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175 paint.setAntiAlias(true);
176
177 paint.setColor(SK_ColorRED);
reed@android.comcb608442009-12-04 21:32:27 +0000178 canvas->drawData(beforeStr, sizeof(beforeStr));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179 canvas->drawCircle(SkIntToScalar(50), SkIntToScalar(50),
180 SkIntToScalar(40), paint);
reed@android.comcb608442009-12-04 21:32:27 +0000181 canvas->drawData(afterStr, sizeof(afterStr));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000182 paint.setColor(SK_ColorBLACK);
183 paint.setTextSize(SkIntToScalar(40));
184 canvas->drawText("Picture", 7, SkIntToScalar(50), SkIntToScalar(62),
185 paint);
reed@android.comcb608442009-12-04 21:32:27 +0000186
reed@android.com8a1c16f2008-12-17 15:59:43 +0000187 }
188
189 virtual void onDraw(SkCanvas* canvas) {
190 this->drawBG(canvas);
191
192 drawSomething(canvas);
reed@android.com149e2f62009-05-22 14:39:03 +0000193
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194 SkPicture* pict = new SkPicture;
195 SkAutoUnref aur(pict);
196
197 drawSomething(pict->beginRecording(100, 100));
198 pict->endRecording();
reed@android.com149e2f62009-05-22 14:39:03 +0000199
reed@android.com8a1c16f2008-12-17 15:59:43 +0000200 canvas->save();
201 canvas->translate(SkIntToScalar(300), SkIntToScalar(50));
202 canvas->scale(-SK_Scalar1, -SK_Scalar1);
203 canvas->translate(-SkIntToScalar(100), -SkIntToScalar(50));
204 canvas->drawPicture(*pict);
205 canvas->restore();
206
207 canvas->save();
208 canvas->translate(SkIntToScalar(200), SkIntToScalar(150));
209 canvas->scale(SK_Scalar1, -SK_Scalar1);
210 canvas->translate(0, -SkIntToScalar(50));
211 canvas->drawPicture(*pict);
212 canvas->restore();
213
214 canvas->save();
215 canvas->translate(SkIntToScalar(100), SkIntToScalar(100));
216 canvas->scale(-SK_Scalar1, SK_Scalar1);
217 canvas->translate(-SkIntToScalar(100), 0);
218 canvas->drawPicture(*pict);
219 canvas->restore();
reed@android.comcb608442009-12-04 21:32:27 +0000220
221 if (false) {
222 SkDebugfDumper dumper;
223 SkDumpCanvas dumpCanvas(&dumper);
224 dumpCanvas.drawPicture(*pict);
225 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226
227 // test that we can re-record a subpicture, and see the results
228
reed@android.com44177402009-11-23 21:07:51 +0000229 SkRandom rand(SampleCode::GetAnimTime());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000230 canvas->translate(SkIntToScalar(10), SkIntToScalar(250));
231 drawCircle(fSubPicture->beginRecording(50, 50), 25,
reed@android.com44177402009-11-23 21:07:51 +0000232 rand.nextU() | 0xFF000000);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000233 canvas->drawPicture(*fPicture);
234 delayInval(500);
235 }
236
237private:
238 #define INVAL_ALL_TYPE "inval-all"
239
240 void delayInval(SkMSec delay) {
241 (new SkEvent(INVAL_ALL_TYPE))->post(this->getSinkID(), delay);
242 }
243
244 virtual bool onEvent(const SkEvent& evt) {
245 if (evt.isType(INVAL_ALL_TYPE)) {
246 this->inval(NULL);
247 return true;
248 }
249 return this->INHERITED::onEvent(evt);
250 }
251
252 SkPicture* fPicture;
253 SkPicture* fSubPicture;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000254
255 typedef SkView INHERITED;
256};
257
258//////////////////////////////////////////////////////////////////////////////
259
260static SkView* MyFactory() { return new PictureView; }
261static SkViewRegister reg(MyFactory);
262