• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SampleCode.h"
2 #include "SkDumpCanvas.h"
3 #include "SkView.h"
4 #include "SkCanvas.h"
5 #include "Sk64.h"
6 #include "SkGradientShader.h"
7 #include "SkGraphics.h"
8 #include "SkImageDecoder.h"
9 #include "SkPath.h"
10 #include "SkPicture.h"
11 #include "SkRandom.h"
12 #include "SkRegion.h"
13 #include "SkShader.h"
14 #include "SkUtils.h"
15 #include "SkColorPriv.h"
16 #include "SkColorFilter.h"
17 #include "SkShape.h"
18 #include "SkTime.h"
19 #include "SkTypeface.h"
20 #include "SkXfermode.h"
21 
22 #include "SkStream.h"
23 #include "SkXMLParser.h"
24 
25 class SignalShape : public SkShape {
26 public:
SignalShape()27     SignalShape() : fSignal(0) {}
28 
setSignal(int n)29     SkShape* setSignal(int n) {
30         fSignal = n;
31         return this;
32     }
33 
34 protected:
onDraw(SkCanvas * canvas)35     virtual void onDraw(SkCanvas* canvas) {
36     //    SkDebugf("---- sc %d\n", canvas->getSaveCount() - 1);
37     }
38 
39 private:
40     int fSignal;
41 };
42 
SignalProc(SkPMColor src,SkPMColor dst)43 static 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  */
test_saveRestoreCulling()55 static 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 
88 #include "SkImageRef_GlobalPool.h"
89 
load_bitmap()90 static 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 
drawCircle(SkCanvas * canvas,int r,SkColor color)103 static 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 
112 class PictureView : public SampleView {
113     SkBitmap fBitmap;
114 public:
PictureView()115 	PictureView() {
116         SkImageRef_GlobalPool::SetRAMBudget(16 * 1024);
117 
118         fBitmap = load_bitmap();
119 
120         fPicture = new SkPicture;
121         SkCanvas* canvas = fPicture->beginRecording(100, 100);
122         SkPaint paint;
123         paint.setAntiAlias(true);
124 
125         canvas->drawBitmap(fBitmap, 0, 0, NULL);
126 
127         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();
140 
141         test_saveRestoreCulling();
142     }
143 
~PictureView()144     virtual ~PictureView() {
145         fPicture->unref();
146     }
147 
148 protected:
149     // overrides from SkEventSink
onQuery(SkEvent * evt)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 
drawSomething(SkCanvas * canvas)158     void drawSomething(SkCanvas* canvas) {
159         SkPaint paint;
160 
161         canvas->save();
162         canvas->scale(0.5f, 0.5f);
163         canvas->drawBitmap(fBitmap, 0, 0, NULL);
164         canvas->restore();
165 
166         const char beforeStr[] = "before circle";
167         const char afterStr[] = "after circle";
168 
169         paint.setAntiAlias(true);
170 
171         paint.setColor(SK_ColorRED);
172         canvas->drawData(beforeStr, sizeof(beforeStr));
173         canvas->drawCircle(SkIntToScalar(50), SkIntToScalar(50),
174                            SkIntToScalar(40), paint);
175         canvas->drawData(afterStr, sizeof(afterStr));
176         paint.setColor(SK_ColorBLACK);
177         paint.setTextSize(SkIntToScalar(40));
178         canvas->drawText("Picture", 7, SkIntToScalar(50), SkIntToScalar(62),
179                          paint);
180 
181     }
182 
onDrawContent(SkCanvas * canvas)183     virtual void onDrawContent(SkCanvas* canvas) {
184         drawSomething(canvas);
185 
186         SkPicture* pict = new SkPicture;
187         SkAutoUnref aur(pict);
188 
189         drawSomething(pict->beginRecording(100, 100));
190         pict->endRecording();
191 
192         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();
212 
213         if (false) {
214             SkDebugfDumper dumper;
215             SkDumpCanvas dumpCanvas(&dumper);
216             dumpCanvas.drawPicture(*pict);
217         }
218 
219         // test that we can re-record a subpicture, and see the results
220 
221         SkRandom rand(SampleCode::GetAnimTime());
222         canvas->translate(SkIntToScalar(10), SkIntToScalar(250));
223         drawCircle(fSubPicture->beginRecording(50, 50), 25,
224                    rand.nextU() | 0xFF000000);
225         canvas->drawPicture(*fPicture);
226         delayInval(500);
227     }
228 
229 private:
230     #define INVAL_ALL_TYPE  "inval-all"
231 
delayInval(SkMSec delay)232     void delayInval(SkMSec delay) {
233         (new SkEvent(INVAL_ALL_TYPE))->post(this->getSinkID(), delay);
234     }
235 
onEvent(const SkEvent & evt)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;
246 
247     typedef SampleView INHERITED;
248 };
249 
250 //////////////////////////////////////////////////////////////////////////////
251 
MyFactory()252 static SkView* MyFactory() { return new PictureView; }
253 static SkViewRegister reg(MyFactory);
254 
255