blob: d7b6b229f4cb939fec3e0ed86681ef0ec637faf9 [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) {
reed@google.com2f3dc9d2011-05-02 17:33:45 +000036 // SkDebugf("---- sc %d\n", canvas->getSaveCount() - 1);
reed@android.com7d970c72010-04-22 16:07:49 +000037 }
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
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000112class PictureView : public SampleView {
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
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158 void drawSomething(SkCanvas* canvas) {
159 SkPaint paint;
reed@android.comc6ddc112009-11-10 15:54:55 +0000160
161 canvas->save();
162 canvas->scale(0.5f, 0.5f);
163 canvas->drawBitmap(fBitmap, 0, 0, NULL);
164 canvas->restore();
165
reed@android.comcb608442009-12-04 21:32:27 +0000166 const char beforeStr[] = "before circle";
167 const char afterStr[] = "after circle";
168
reed@android.com8a1c16f2008-12-17 15:59:43 +0000169 paint.setAntiAlias(true);
170
171 paint.setColor(SK_ColorRED);
reed@android.comcb608442009-12-04 21:32:27 +0000172 canvas->drawData(beforeStr, sizeof(beforeStr));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000173 canvas->drawCircle(SkIntToScalar(50), SkIntToScalar(50),
174 SkIntToScalar(40), paint);
reed@android.comcb608442009-12-04 21:32:27 +0000175 canvas->drawData(afterStr, sizeof(afterStr));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000176 paint.setColor(SK_ColorBLACK);
177 paint.setTextSize(SkIntToScalar(40));
178 canvas->drawText("Picture", 7, SkIntToScalar(50), SkIntToScalar(62),
179 paint);
reed@android.comcb608442009-12-04 21:32:27 +0000180
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181 }
182
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000183 virtual void onDrawContent(SkCanvas* canvas) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184 drawSomething(canvas);
reed@android.com149e2f62009-05-22 14:39:03 +0000185
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186 SkPicture* pict = new SkPicture;
187 SkAutoUnref aur(pict);
188
189 drawSomething(pict->beginRecording(100, 100));
190 pict->endRecording();
reed@android.com149e2f62009-05-22 14:39:03 +0000191
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192 canvas->save();
193 canvas->translate(SkIntToScalar(300), SkIntToScalar(50));
194 canvas->scale(-SK_Scalar1, -SK_Scalar1);
195 canvas->translate(-SkIntToScalar(100), -SkIntToScalar(50));
196 canvas->drawPicture(*pict);
197 canvas->restore();
198
199 canvas->save();
200 canvas->translate(SkIntToScalar(200), SkIntToScalar(150));
201 canvas->scale(SK_Scalar1, -SK_Scalar1);
202 canvas->translate(0, -SkIntToScalar(50));
203 canvas->drawPicture(*pict);
204 canvas->restore();
205
206 canvas->save();
207 canvas->translate(SkIntToScalar(100), SkIntToScalar(100));
208 canvas->scale(-SK_Scalar1, SK_Scalar1);
209 canvas->translate(-SkIntToScalar(100), 0);
210 canvas->drawPicture(*pict);
211 canvas->restore();
reed@android.comcb608442009-12-04 21:32:27 +0000212
213 if (false) {
214 SkDebugfDumper dumper;
215 SkDumpCanvas dumpCanvas(&dumper);
216 dumpCanvas.drawPicture(*pict);
217 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218
219 // test that we can re-record a subpicture, and see the results
220
reed@android.com44177402009-11-23 21:07:51 +0000221 SkRandom rand(SampleCode::GetAnimTime());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 canvas->translate(SkIntToScalar(10), SkIntToScalar(250));
223 drawCircle(fSubPicture->beginRecording(50, 50), 25,
reed@android.com44177402009-11-23 21:07:51 +0000224 rand.nextU() | 0xFF000000);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000225 canvas->drawPicture(*fPicture);
226 delayInval(500);
227 }
228
229private:
230 #define INVAL_ALL_TYPE "inval-all"
231
232 void delayInval(SkMSec delay) {
233 (new SkEvent(INVAL_ALL_TYPE))->post(this->getSinkID(), delay);
234 }
235
236 virtual bool onEvent(const SkEvent& evt) {
237 if (evt.isType(INVAL_ALL_TYPE)) {
238 this->inval(NULL);
239 return true;
240 }
241 return this->INHERITED::onEvent(evt);
242 }
243
244 SkPicture* fPicture;
245 SkPicture* fSubPicture;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000246
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000247 typedef SampleView INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248};
249
250//////////////////////////////////////////////////////////////////////////////
251
252static SkView* MyFactory() { return new PictureView; }
253static SkViewRegister reg(MyFactory);
254