blob: 3a7a1a6330db167fdcd1a95208a50c91a8893361 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkCanvas.h"
2#include "SkDevice.h"
reed@google.comac10a2d2010-12-22 21:39:39 +00003#include "SkGpuCanvas.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00004#include "SkGraphics.h"
reed@android.comb08eb2b2009-01-06 20:16:26 +00005#include "SkImageEncoder.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00006#include "SkPaint.h"
7#include "SkPicture.h"
8#include "SkStream.h"
reed@android.com44177402009-11-23 21:07:51 +00009#include "SkTime.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#include "SkWindow.h"
11
12#include "SampleCode.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000013#include "GrContext.h"
reed@google.com52f57e12011-03-16 12:10:02 +000014#include "SkTouchGesture.h"
reed@android.comf2b98d62010-12-20 18:26:13 +000015
16//#define DEFAULT_TO_GPU
17
reed@android.come191b162009-12-18 21:33:39 +000018extern SkView* create_overview(int, const SkViewFactory[]);
reed@android.com34245c72009-11-03 04:00:48 +000019
reed@android.comcb342352010-07-22 18:27:53 +000020#define SK_SUPPORT_GL
reed@android.com8a1c16f2008-12-17 15:59:43 +000021
22#define ANIMATING_EVENTTYPE "nextSample"
23#define ANIMATING_DELAY 750
24
reed@google.comac10a2d2010-12-22 21:39:39 +000025#ifdef SK_SUPPORT_GL
26 #include "GrGLConfig.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000027#endif
28
reed@android.com8a1c16f2008-12-17 15:59:43 +000029SkViewRegister* SkViewRegister::gHead;
30SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
31 static bool gOnce;
32 if (!gOnce) {
33 gHead = NULL;
34 gOnce = true;
35 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +000036
reed@android.com8a1c16f2008-12-17 15:59:43 +000037 fChain = gHead;
38 gHead = this;
39}
40
reed@android.comf2b98d62010-12-20 18:26:13 +000041#if defined(SK_SUPPORT_GL)
42 #define SK_USE_SHADERS
43#endif
44
twiz@google.com06c3b6b2011-03-14 16:58:39 +000045#ifdef SK_BUILD_FOR_MAC
reed@google.comf0b5f682011-03-11 20:08:25 +000046#include <CoreFoundation/CoreFoundation.h>
47#include <CoreFoundation/CFURLAccess.h>
48
49static void testpdf() {
50 CFStringRef path = CFStringCreateWithCString(NULL, "/test.pdf",
51 kCFStringEncodingUTF8);
52 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path,
53 kCFURLPOSIXPathStyle,
54 false);
55 CFRelease(path);
56 CGRect box = CGRectMake(0, 0, 8*72, 10*72);
57 CGContextRef cg = CGPDFContextCreateWithURL(url, &box, NULL);
58 CFRelease(url);
59
60 CGContextBeginPage(cg, &box);
61 CGRect r = CGRectMake(10, 10, 40 + 0.5, 50 + 0.5);
62 CGContextFillEllipseInRect(cg, r);
63 CGContextEndPage(cg);
64 CGContextRelease(cg);
65
66 if (false) {
67 SkBitmap bm;
68 bm.setConfig(SkBitmap::kA8_Config, 64, 64);
69 bm.allocPixels();
70 bm.eraseColor(0);
71
72 SkCanvas canvas(bm);
73
74 }
75}
76#endif
77
78//////////////////////////////////////////////////////////////////////////////
79
80#include "SkDrawFilter.h"
81
82class LCDTextDrawFilter : public SkDrawFilter {
83public:
84 enum Mode {
85 kNeutral_Mode,
86 kForceOn_Mode,
87 kForceOff_Mode
88 };
89
90 LCDTextDrawFilter(Mode mode) : fMode(mode) {}
91
92 virtual bool filter(SkCanvas*, SkPaint* paint, Type t) {
93 if (kText_Type == t && kNeutral_Mode != fMode) {
94 fPrevLCD = paint->isLCDRenderText();
95 paint->setLCDRenderText(kForceOn_Mode == fMode);
96 }
97 return true;
98 }
99
100 /** If filter() returned true, then restore() will be called to restore the
101 canvas/paint to their previous states
102 */
103 virtual void restore(SkCanvas*, SkPaint* paint, Type t) {
104 if (kText_Type == t && kNeutral_Mode != fMode) {
105 paint->setLCDRenderText(fPrevLCD);
106 }
107 }
108
109private:
110 Mode fMode;
111 bool fPrevLCD;
112};
113
114LCDTextDrawFilter::Mode cycle_lcdmode(LCDTextDrawFilter::Mode mode) {
115 static const LCDTextDrawFilter::Mode gCycle[] = {
116 /* kNeutral_Mode -> */ LCDTextDrawFilter::kForceOn_Mode,
117 /* kForceOn_Mode -> */ LCDTextDrawFilter::kForceOff_Mode,
118 /* kForceOff_Mode -> */ LCDTextDrawFilter::kNeutral_Mode
119 };
120 return gCycle[mode];
121}
122
reed@android.com8a1c16f2008-12-17 15:59:43 +0000123//////////////////////////////////////////////////////////////////////////////
124
reed@android.comf2b98d62010-12-20 18:26:13 +0000125static const char gCharEvtName[] = "SampleCode_Char_Event";
126static const char gKeyEvtName[] = "SampleCode_Key_Event";
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127static const char gTitleEvtName[] = "SampleCode_Title_Event";
128static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
reed@android.comf2b98d62010-12-20 18:26:13 +0000129static const char gFastTextEvtName[] = "SampleCode_FastText_Event";
130
131bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) {
132 if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) {
133 if (outUni) {
134 *outUni = evt.getFast32();
135 }
136 return true;
137 }
138 return false;
139}
140
141bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) {
142 if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) {
143 if (outKey) {
144 *outKey = (SkKey)evt.getFast32();
145 }
146 return true;
147 }
148 return false;
149}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150
151bool SampleCode::TitleQ(const SkEvent& evt) {
152 return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
153}
154
155void SampleCode::TitleR(SkEvent* evt, const char title[]) {
156 SkASSERT(evt && TitleQ(*evt));
157 evt->setString(gTitleEvtName, title);
158}
159
160bool SampleCode::PrefSizeQ(const SkEvent& evt) {
161 return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1);
162}
163
164void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) {
165 SkASSERT(evt && PrefSizeQ(*evt));
166 SkScalar size[2];
167 size[0] = width;
168 size[1] = height;
169 evt->setScalars(gPrefSizeEvtName, 2, size);
170}
171
reed@android.comf2b98d62010-12-20 18:26:13 +0000172bool SampleCode::FastTextQ(const SkEvent& evt) {
173 return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1);
174}
175
176///////////////////////////////////////////////////////////////////////////////
177
reed@android.com44177402009-11-23 21:07:51 +0000178static SkMSec gAnimTime;
reed@android.comf2b98d62010-12-20 18:26:13 +0000179static SkMSec gAnimTimePrev;
180
reed@android.com44177402009-11-23 21:07:51 +0000181SkMSec SampleCode::GetAnimTime() { return gAnimTime; }
reed@android.comf2b98d62010-12-20 18:26:13 +0000182SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; }
183SkScalar SampleCode::GetAnimSecondsDelta() {
184 return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0);
185}
reed@android.com44177402009-11-23 21:07:51 +0000186
187SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000188 // since gAnimTime can be up to 32 bits, we can't convert it to a float
189 // or we'll lose the low bits. Hence we use doubles for the intermediate
190 // calculations
191 double seconds = (double)gAnimTime / 1000.0;
192 double value = SkScalarToDouble(speed) * seconds;
reed@android.com44177402009-11-23 21:07:51 +0000193 if (period) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000194 value = ::fmod(value, SkScalarToDouble(period));
reed@android.com44177402009-11-23 21:07:51 +0000195 }
reed@android.comf2b98d62010-12-20 18:26:13 +0000196 return SkDoubleToScalar(value);
reed@android.com44177402009-11-23 21:07:51 +0000197}
198
reed@android.com8a1c16f2008-12-17 15:59:43 +0000199//////////////////////////////////////////////////////////////////////////////
200
reed@android.comf2b98d62010-12-20 18:26:13 +0000201static SkView* curr_view(SkWindow* wind) {
202 SkView::F2BIter iter(wind);
203 return iter.next();
204}
205
reed@android.com8a1c16f2008-12-17 15:59:43 +0000206class SampleWindow : public SkOSWindow {
reed@android.com34245c72009-11-03 04:00:48 +0000207 SkTDArray<SkViewFactory> fSamples;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208public:
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000209 SampleWindow(void* hwnd);
210 virtual ~SampleWindow();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000211
reed@android.come522ca52009-11-23 20:10:41 +0000212 virtual void draw(SkCanvas* canvas);
213
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214protected:
215 virtual void onDraw(SkCanvas* canvas);
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000216 virtual bool onHandleKey(SkKey key);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000217 virtual bool onHandleChar(SkUnichar);
218 virtual void onSizeChange();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000219
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220 virtual SkCanvas* beforeChildren(SkCanvas*);
221 virtual void afterChildren(SkCanvas*);
reed@android.com6c5f6f22009-08-14 16:08:38 +0000222 virtual void beforeChild(SkView* child, SkCanvas* canvas);
223 virtual void afterChild(SkView* child, SkCanvas* canvas);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000224
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000225 virtual bool onEvent(const SkEvent& evt);
reed@android.comf2b98d62010-12-20 18:26:13 +0000226 virtual bool onQuery(SkEvent* evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000227
reed@google.com52f57e12011-03-16 12:10:02 +0000228 virtual bool onClick(Click* click);
229 virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
230
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231#if 0
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000232 virtual bool handleChar(SkUnichar uni);
233 virtual bool handleEvent(const SkEvent& evt);
234 virtual bool handleKey(SkKey key);
235 virtual bool handleKeyUp(SkKey key);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000236
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000237 virtual bool onClick(Click* click);
238 virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000239 virtual bool onHandleKeyUp(SkKey key);
240#endif
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000241
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242private:
reed@android.com34245c72009-11-03 04:00:48 +0000243 int fCurrIndex;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000244
reed@android.com8a1c16f2008-12-17 15:59:43 +0000245 SkPicture* fPicture;
reed@android.comf2b98d62010-12-20 18:26:13 +0000246 SkGpuCanvas* fGpuCanvas;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000247 GrContext* fGrContext;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248 SkPath fClipPath;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000249
reed@google.com52f57e12011-03-16 12:10:02 +0000250 SkTouchGesture fGesture;
251
reed@android.com8a1c16f2008-12-17 15:59:43 +0000252 enum CanvasType {
253 kRaster_CanvasType,
254 kPicture_CanvasType,
reed@android.comf2b98d62010-12-20 18:26:13 +0000255 kGPU_CanvasType
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256 };
257 CanvasType fCanvasType;
258
259 bool fUseClip;
reed@android.come522ca52009-11-23 20:10:41 +0000260 bool fNClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000261 bool fRepeatDrawing;
262 bool fAnimating;
reed@android.com6c5f6f22009-08-14 16:08:38 +0000263 bool fRotate;
264 bool fScale;
reed@android.comf2b98d62010-12-20 18:26:13 +0000265 bool fRequestGrabImage;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000266
reed@google.comf0b5f682011-03-11 20:08:25 +0000267 LCDTextDrawFilter::Mode fLCDMode;
268
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269 int fScrollTestX, fScrollTestY;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000270
271 bool make3DReady();
272
reed@android.com8a1c16f2008-12-17 15:59:43 +0000273 void loadView(SkView*);
274 void updateTitle();
275 bool nextSample();
276
277 void postAnimatingEvent() {
278 if (fAnimating) {
279 SkEvent* evt = new SkEvent(ANIMATING_EVENTTYPE);
280 evt->post(this->getSinkID(), ANIMATING_DELAY);
281 }
282 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000283
284
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285 static CanvasType cycle_canvastype(CanvasType);
286
287 typedef SkOSWindow INHERITED;
288};
289
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000290bool SampleWindow::make3DReady() {
291
292#if defined(SK_SUPPORT_GL)
bsalomon@google.com498a6232011-03-10 18:24:15 +0000293 if (attachGL()) {
294 if (NULL == fGrContext) {
295 #if defined(SK_USE_SHADERS)
296 fGrContext = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
297 #else
298 fGrContext = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, NULL);
299 #endif
300 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000301
bsalomon@google.com498a6232011-03-10 18:24:15 +0000302 if (NULL != fGrContext) {
303 return true;
304 } else {
305 detachGL();
306 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000307 }
308#endif
309 SkDebugf("Failed to setup 3D");
310 return false;
311}
312
reed@android.com8a1c16f2008-12-17 15:59:43 +0000313SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) {
314 static const CanvasType gCT[] = {
315 kPicture_CanvasType,
reed@android.comf2b98d62010-12-20 18:26:13 +0000316 kGPU_CanvasType,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000317 kRaster_CanvasType
318 };
319 return gCT[ct];
320}
321
322SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000323 fPicture = NULL;
reed@android.comf2b98d62010-12-20 18:26:13 +0000324 fGpuCanvas = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000325
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000326 fGrContext = NULL;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000327
reed@android.comf2b98d62010-12-20 18:26:13 +0000328#ifdef DEFAULT_TO_GPU
329 fCanvasType = kGPU_CanvasType;
330#else
reed@android.com8a1c16f2008-12-17 15:59:43 +0000331 fCanvasType = kRaster_CanvasType;
reed@android.comf2b98d62010-12-20 18:26:13 +0000332#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000333 fUseClip = false;
reed@android.come522ca52009-11-23 20:10:41 +0000334 fNClip = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335 fRepeatDrawing = false;
336 fAnimating = false;
reed@android.com6c5f6f22009-08-14 16:08:38 +0000337 fRotate = false;
338 fScale = false;
reed@android.comf2b98d62010-12-20 18:26:13 +0000339 fRequestGrabImage = false;
reed@google.comf0b5f682011-03-11 20:08:25 +0000340 fLCDMode = LCDTextDrawFilter::kNeutral_Mode;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000341 fScrollTestX = fScrollTestY = 0;
342
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000343// this->setConfig(SkBitmap::kRGB_565_Config);
344 this->setConfig(SkBitmap::kARGB_8888_Config);
345 this->setVisibleP(true);
reed@android.comf2b98d62010-12-20 18:26:13 +0000346 this->setClipToBounds(false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000347
reed@android.com34245c72009-11-03 04:00:48 +0000348 {
349 const SkViewRegister* reg = SkViewRegister::Head();
350 while (reg) {
351 *fSamples.append() = reg->factory();
352 reg = reg->next();
353 }
354 }
355 fCurrIndex = 0;
reed@android.come0f13ee2009-11-04 19:40:25 +0000356 this->loadView(fSamples[fCurrIndex]());
reed@google.comf0b5f682011-03-11 20:08:25 +0000357
twiz@google.com06c3b6b2011-03-14 16:58:39 +0000358#ifdef SK_BUILD_FOR_MAC
reed@google.comf0b5f682011-03-11 20:08:25 +0000359 testpdf();
twiz@google.com06c3b6b2011-03-14 16:58:39 +0000360#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000361}
362
363SampleWindow::~SampleWindow() {
364 delete fPicture;
reed@android.comf2b98d62010-12-20 18:26:13 +0000365 delete fGpuCanvas;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000366 if (NULL != fGrContext) {
367 fGrContext->unref();
368 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000369}
370
reed@android.com55e76b22009-11-23 21:46:47 +0000371static SkBitmap capture_bitmap(SkCanvas* canvas) {
372 SkBitmap bm;
373 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
374 src.copyTo(&bm, src.config());
375 return bm;
376}
377
378static bool bitmap_diff(SkCanvas* canvas, const SkBitmap& orig,
379 SkBitmap* diff) {
380 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000381
reed@android.com55e76b22009-11-23 21:46:47 +0000382 SkAutoLockPixels alp0(src);
383 SkAutoLockPixels alp1(orig);
384 for (int y = 0; y < src.height(); y++) {
385 const void* srcP = src.getAddr(0, y);
386 const void* origP = orig.getAddr(0, y);
387 size_t bytes = src.width() * src.bytesPerPixel();
388 if (memcmp(srcP, origP, bytes)) {
389 SkDebugf("---------- difference on line %d\n", y);
390 return true;
391 }
392 }
393 return false;
394}
395
reed@android.com44177402009-11-23 21:07:51 +0000396#define XCLIP_N 8
397#define YCLIP_N 8
reed@android.come522ca52009-11-23 20:10:41 +0000398
399void SampleWindow::draw(SkCanvas* canvas) {
reed@android.com44177402009-11-23 21:07:51 +0000400 // update the animation time
reed@android.comf2b98d62010-12-20 18:26:13 +0000401 gAnimTimePrev = gAnimTime;
reed@android.com44177402009-11-23 21:07:51 +0000402 gAnimTime = SkTime::GetMSecs();
403
reed@google.com52f57e12011-03-16 12:10:02 +0000404 // Apply any gesture matrix
405 if (true) {
406 const SkMatrix& localM = fGesture.localM();
407 if (localM.getType() & SkMatrix::kScale_Mask) {
408 canvas->setExternalMatrix(&localM);
409 }
410 canvas->concat(localM);
411 canvas->concat(fGesture.globalM());
412
413 if (fGesture.isActive()) {
414 this->inval(NULL);
415 }
416 }
417
reed@android.come522ca52009-11-23 20:10:41 +0000418 if (fNClip) {
reed@android.com55e76b22009-11-23 21:46:47 +0000419 this->INHERITED::draw(canvas);
420 SkBitmap orig = capture_bitmap(canvas);
reed@android.come522ca52009-11-23 20:10:41 +0000421
422 const SkScalar w = this->width();
423 const SkScalar h = this->height();
424 const SkScalar cw = w / XCLIP_N;
425 const SkScalar ch = h / YCLIP_N;
426 for (int y = 0; y < YCLIP_N; y++) {
reed@android.com55e76b22009-11-23 21:46:47 +0000427 SkRect r;
428 r.fTop = y * ch;
429 r.fBottom = (y + 1) * ch;
430 if (y == YCLIP_N - 1) {
431 r.fBottom = h;
432 }
reed@android.come522ca52009-11-23 20:10:41 +0000433 for (int x = 0; x < XCLIP_N; x++) {
434 SkAutoCanvasRestore acr(canvas, true);
reed@android.com55e76b22009-11-23 21:46:47 +0000435 r.fLeft = x * cw;
436 r.fRight = (x + 1) * cw;
437 if (x == XCLIP_N - 1) {
438 r.fRight = w;
439 }
reed@android.come522ca52009-11-23 20:10:41 +0000440 canvas->clipRect(r);
441 this->INHERITED::draw(canvas);
442 }
443 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000444
reed@android.com55e76b22009-11-23 21:46:47 +0000445 SkBitmap diff;
446 if (bitmap_diff(canvas, orig, &diff)) {
447 }
reed@android.come522ca52009-11-23 20:10:41 +0000448 } else {
449 this->INHERITED::draw(canvas);
450 }
451}
452
reed@android.com8a1c16f2008-12-17 15:59:43 +0000453void SampleWindow::onDraw(SkCanvas* canvas) {
454 if (fRepeatDrawing) {
455 this->inval(NULL);
456 }
457}
458
459#include "SkColorPriv.h"
460
461static void reverseRedAndBlue(const SkBitmap& bm) {
462 SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config);
463 uint8_t* p = (uint8_t*)bm.getPixels();
464 uint8_t* stop = p + bm.getSize();
465 while (p < stop) {
466 // swap red/blue (to go from ARGB(int) to RGBA(memory) and premultiply
467 unsigned scale = SkAlpha255To256(p[3]);
468 unsigned r = p[2];
469 unsigned b = p[0];
470 p[0] = SkAlphaMul(r, scale);
471 p[1] = SkAlphaMul(p[1], scale);
472 p[2] = SkAlphaMul(b, scale);
473 p += 4;
474 }
475}
476
477SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000478 SkIPoint viewport;
479 bool alreadyGPU = canvas->getViewport(&viewport);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000480
reed@android.comf2b98d62010-12-20 18:26:13 +0000481 if (kGPU_CanvasType != fCanvasType) {
reed@android.com6efdc472008-12-19 18:24:35 +0000482#ifdef SK_SUPPORT_GL
reed@android.comf2b98d62010-12-20 18:26:13 +0000483 detachGL();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000484#endif
reed@android.comf2b98d62010-12-20 18:26:13 +0000485 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000486
reed@android.com8a1c16f2008-12-17 15:59:43 +0000487 switch (fCanvasType) {
488 case kRaster_CanvasType:
489 canvas = this->INHERITED::beforeChildren(canvas);
490 break;
491 case kPicture_CanvasType:
492 fPicture = new SkPicture;
493 canvas = fPicture->beginRecording(9999, 9999);
494 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000495 case kGPU_CanvasType: {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000496 if (!alreadyGPU && make3DReady()) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000497 SkDevice* device = canvas->getDevice();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000498 const SkBitmap& bitmap = device->accessBitmap(true);
499
bsalomon@google.com5782d712011-01-21 21:03:59 +0000500 GrRenderTarget* renderTarget;
501 renderTarget = fGrContext->createRenderTargetFrom3DApiState();
502 fGpuCanvas = new SkGpuCanvas(fGrContext, renderTarget);
503 renderTarget->unref();
504
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000505 device = fGpuCanvas->createDevice(SkBitmap::kARGB_8888_Config,
506 bitmap.width(), bitmap.height(),
507 false, false);
reed@google.comac10a2d2010-12-22 21:39:39 +0000508 fGpuCanvas->setDevice(device)->unref();
reed@android.comf2b98d62010-12-20 18:26:13 +0000509 canvas = fGpuCanvas;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000510
reed@android.comf2b98d62010-12-20 18:26:13 +0000511 } else {
512 canvas = this->INHERITED::beforeChildren(canvas);
513 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000514 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000515 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000516 }
517
518 if (fUseClip) {
519 canvas->drawColor(0xFFFF88FF);
520 canvas->clipPath(fClipPath);
521 }
522
523 return canvas;
524}
525
526static void paint_rgn(const SkBitmap& bm, const SkIRect& r,
527 const SkRegion& rgn) {
528 SkCanvas canvas(bm);
529 SkRegion inval(rgn);
530
531 inval.translate(r.fLeft, r.fTop);
532 canvas.clipRegion(inval);
533 canvas.drawColor(0xFFFF8080);
534}
535
536void SampleWindow::afterChildren(SkCanvas* orig) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000537 if (fRequestGrabImage) {
538 fRequestGrabImage = false;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000539
reed@android.comf2b98d62010-12-20 18:26:13 +0000540 SkCanvas* canvas = fGpuCanvas ? fGpuCanvas : orig;
541 SkDevice* device = canvas->getDevice();
542 SkBitmap bitmap;
reed@google.com5ba2d5b2011-03-10 19:40:34 +0000543 SkIRect bounds = {
544 0, 0,
545 SkScalarRound(this->width()),
546 SkScalarRound(this->height())
547 };
reed@android.comf2b98d62010-12-20 18:26:13 +0000548 if (device->readPixels(bounds, &bitmap)) {
549 static int gSampleGrabCounter;
550 SkString name;
551 name.printf("sample_grab_%d", gSampleGrabCounter++);
552 SkImageEncoder::EncodeFile(name.c_str(), bitmap,
553 SkImageEncoder::kPNG_Type, 100);
554 }
555 }
556
reed@android.com8a1c16f2008-12-17 15:59:43 +0000557 switch (fCanvasType) {
558 case kRaster_CanvasType:
559 break;
560 case kPicture_CanvasType:
reed@android.comaefd2bc2009-03-30 21:02:14 +0000561 if (true) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000562 SkPicture* pict = new SkPicture(*fPicture);
563 fPicture->unref();
564 orig->drawPicture(*pict);
565 pict->unref();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000566 } else if (true) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000567 SkDynamicMemoryWStream ostream;
568 fPicture->serialize(&ostream);
569 fPicture->unref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000570
reed@android.com8a1c16f2008-12-17 15:59:43 +0000571 SkMemoryStream istream(ostream.getStream(), ostream.getOffset());
572 SkPicture pict(&istream);
573 orig->drawPicture(pict);
574 } else {
575 fPicture->draw(orig);
576 fPicture->unref();
577 }
578 fPicture = NULL;
579 break;
reed@android.com6efdc472008-12-19 18:24:35 +0000580#ifdef SK_SUPPORT_GL
reed@android.comf2b98d62010-12-20 18:26:13 +0000581 case kGPU_CanvasType:
582 delete fGpuCanvas;
583 fGpuCanvas = NULL;
584 presentGL();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000585 break;
reed@android.com6efdc472008-12-19 18:24:35 +0000586#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000587 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000588
reed@android.com8a1c16f2008-12-17 15:59:43 +0000589// if ((fScrollTestX | fScrollTestY) != 0)
reed@android.comf2b98d62010-12-20 18:26:13 +0000590 if (false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000591 const SkBitmap& bm = orig->getDevice()->accessBitmap(true);
592 int dx = fScrollTestX * 7;
593 int dy = fScrollTestY * 7;
594 SkIRect r;
595 SkRegion inval;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000596
reed@android.com8a1c16f2008-12-17 15:59:43 +0000597 r.set(50, 50, 50+100, 50+100);
598 bm.scrollRect(&r, dx, dy, &inval);
599 paint_rgn(bm, r, inval);
600 }
601}
602
reed@android.com6c5f6f22009-08-14 16:08:38 +0000603void SampleWindow::beforeChild(SkView* child, SkCanvas* canvas) {
604 if (fScale) {
605 SkScalar scale = SK_Scalar1 * 7 / 10;
606 SkScalar cx = this->width() / 2;
607 SkScalar cy = this->height() / 2;
608 canvas->translate(cx, cy);
609 canvas->scale(scale, scale);
610 canvas->translate(-cx, -cy);
611 }
612 if (fRotate) {
613 SkScalar cx = this->width() / 2;
614 SkScalar cy = this->height() / 2;
615 canvas->translate(cx, cy);
616 canvas->rotate(SkIntToScalar(30));
617 canvas->translate(-cx, -cy);
618 }
reed@google.comf0b5f682011-03-11 20:08:25 +0000619
620 if (LCDTextDrawFilter::kNeutral_Mode != fLCDMode) {
621 canvas->setDrawFilter(new LCDTextDrawFilter(fLCDMode))->unref();
622 }
reed@android.com6c5f6f22009-08-14 16:08:38 +0000623}
624
625void SampleWindow::afterChild(SkView* child, SkCanvas* canvas) {
reed@google.comf0b5f682011-03-11 20:08:25 +0000626 canvas->setDrawFilter(NULL);
reed@android.com6c5f6f22009-08-14 16:08:38 +0000627}
628
reed@android.com8a1c16f2008-12-17 15:59:43 +0000629static SkBitmap::Config gConfigCycle[] = {
630 SkBitmap::kNo_Config, // none -> none
631 SkBitmap::kNo_Config, // a1 -> none
632 SkBitmap::kNo_Config, // a8 -> none
633 SkBitmap::kNo_Config, // index8 -> none
634 SkBitmap::kARGB_4444_Config, // 565 -> 4444
635 SkBitmap::kARGB_8888_Config, // 4444 -> 8888
636 SkBitmap::kRGB_565_Config // 8888 -> 565
637};
638
639static SkBitmap::Config cycle_configs(SkBitmap::Config c) {
640 return gConfigCycle[c];
641}
642
643bool SampleWindow::nextSample() {
reed@android.com34245c72009-11-03 04:00:48 +0000644 fCurrIndex = (fCurrIndex + 1) % fSamples.count();
645 this->loadView(fSamples[fCurrIndex]());
646 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000647}
648
649bool SampleWindow::onEvent(const SkEvent& evt) {
650 if (evt.isType(ANIMATING_EVENTTYPE)) {
651 if (fAnimating) {
652 this->nextSample();
653 this->postAnimatingEvent();
654 }
655 return true;
656 }
reed@android.com34245c72009-11-03 04:00:48 +0000657 if (evt.isType("set-curr-index")) {
658 fCurrIndex = evt.getFast32() % fSamples.count();
659 this->loadView(fSamples[fCurrIndex]());
660 return true;
661 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000662 return this->INHERITED::onEvent(evt);
663}
664
reed@android.comf2b98d62010-12-20 18:26:13 +0000665bool SampleWindow::onQuery(SkEvent* query) {
666 if (query->isType("get-slide-count")) {
667 query->setFast32(fSamples.count());
668 return true;
669 }
670 if (query->isType("get-slide-title")) {
671 SkView* view = fSamples[query->getFast32()]();
672 SkEvent evt(gTitleEvtName);
673 if (view->doQuery(&evt)) {
674 query->setString("title", evt.findString(gTitleEvtName));
675 }
676 SkSafeUnref(view);
677 return true;
678 }
679 if (query->isType("use-fast-text")) {
680 SkEvent evt(gFastTextEvtName);
681 return curr_view(this)->doQuery(&evt);
682 }
683 return this->INHERITED::onQuery(query);
684}
685
reed@android.com0ae6b242008-12-23 16:49:54 +0000686static void cleanup_for_filename(SkString* name) {
687 char* str = name->writable_str();
reed@android.come191b162009-12-18 21:33:39 +0000688 for (size_t i = 0; i < name->size(); i++) {
reed@android.com0ae6b242008-12-23 16:49:54 +0000689 switch (str[i]) {
690 case ':': str[i] = '-'; break;
691 case '/': str[i] = '-'; break;
692 case ' ': str[i] = '_'; break;
693 default: break;
694 }
695 }
696}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000697
698bool SampleWindow::onHandleChar(SkUnichar uni) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000699 {
700 SkView* view = curr_view(this);
701 if (view) {
702 SkEvent evt(gCharEvtName);
703 evt.setFast32(uni);
704 if (view->doQuery(&evt)) {
705 return true;
706 }
707 }
708 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000709
reed@android.com8a1c16f2008-12-17 15:59:43 +0000710 int dx = 0xFF;
711 int dy = 0xFF;
712
713 switch (uni) {
714 case '5': dx = 0; dy = 0; break;
715 case '8': dx = 0; dy = -1; break;
716 case '6': dx = 1; dy = 0; break;
717 case '2': dx = 0; dy = 1; break;
718 case '4': dx = -1; dy = 0; break;
719 case '7': dx = -1; dy = -1; break;
720 case '9': dx = 1; dy = -1; break;
721 case '3': dx = 1; dy = 1; break;
722 case '1': dx = -1; dy = 1; break;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000723
reed@android.com8a1c16f2008-12-17 15:59:43 +0000724 default:
725 break;
726 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000727
reed@android.com8a1c16f2008-12-17 15:59:43 +0000728 if (0xFF != dx && 0xFF != dy) {
729 if ((dx | dy) == 0) {
730 fScrollTestX = fScrollTestY = 0;
731 } else {
732 fScrollTestX += dx;
733 fScrollTestY += dy;
734 }
735 this->inval(NULL);
736 return true;
737 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000738
reed@android.com0ae6b242008-12-23 16:49:54 +0000739 switch (uni) {
740 case 'a':
741 fAnimating = !fAnimating;
742 this->postAnimatingEvent();
743 this->updateTitle();
744 return true;
745 case 'f': {
746 const char* title = this->getTitle();
747 if (title[0] == 0) {
748 title = "sampleapp";
749 }
750 SkString name(title);
751 cleanup_for_filename(&name);
752 name.append(".png");
753 if (SkImageEncoder::EncodeFile(name.c_str(), this->getBitmap(),
reed@android.comb08eb2b2009-01-06 20:16:26 +0000754 SkImageEncoder::kPNG_Type, 100)) {
reed@android.com0ae6b242008-12-23 16:49:54 +0000755 SkDebugf("Created %s\n", name.c_str());
756 }
757 return true;
758 }
reed@android.com6c5f6f22009-08-14 16:08:38 +0000759 case 'r':
760 fRotate = !fRotate;
761 this->inval(NULL);
762 this->updateTitle();
763 return true;
764 case 's':
765 fScale = !fScale;
766 this->inval(NULL);
767 this->updateTitle();
768 return true;
reed@google.comfb56a9e2011-02-10 18:47:24 +0000769 case 'c':
770 fUseClip = !fUseClip;
771 this->inval(NULL);
772 this->updateTitle();
773 return true;
reed@android.comf2b98d62010-12-20 18:26:13 +0000774 case 'd':
775 SkGraphics::SetFontCacheUsed(0);
776 return true;
777 case 'g':
778 fRequestGrabImage = true;
779 this->inval(NULL);
780 break;
reed@google.comf0b5f682011-03-11 20:08:25 +0000781 case 'l':
782 fLCDMode = cycle_lcdmode(fLCDMode);
783 this->updateTitle();
784 this->inval(NULL);
785 break;
reed@android.com0ae6b242008-12-23 16:49:54 +0000786 default:
787 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000788 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000789
reed@android.com8a1c16f2008-12-17 15:59:43 +0000790 return this->INHERITED::onHandleChar(uni);
791}
792
793#include "SkDumpCanvas.h"
794
795bool SampleWindow::onHandleKey(SkKey key) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000796 {
797 SkView* view = curr_view(this);
798 if (view) {
799 SkEvent evt(gKeyEvtName);
800 evt.setFast32(key);
801 if (view->doQuery(&evt)) {
802 return true;
803 }
804 }
805 }
806
reed@android.com8a1c16f2008-12-17 15:59:43 +0000807 switch (key) {
808 case kRight_SkKey:
809 if (this->nextSample()) {
810 return true;
811 }
812 break;
813 case kLeft_SkKey:
814 fCanvasType = cycle_canvastype(fCanvasType);
815 this->updateTitle();
816 this->inval(NULL);
817 return true;
818 case kUp_SkKey:
reed@android.come522ca52009-11-23 20:10:41 +0000819 fNClip = !fNClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000820 this->updateTitle();
821 this->inval(NULL);
822 return true;
823 case kDown_SkKey:
824 this->setConfig(cycle_configs(this->getBitmap().config()));
825 this->updateTitle();
826 return true;
827 case kOK_SkKey:
reed@android.comf2b98d62010-12-20 18:26:13 +0000828 if (false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000829 SkDebugfDumper dumper;
830 SkDumpCanvas dc(&dumper);
831 this->draw(&dc);
832 } else {
833 fRepeatDrawing = !fRepeatDrawing;
834 if (fRepeatDrawing) {
835 this->inval(NULL);
836 }
837 }
838 return true;
reed@android.com34245c72009-11-03 04:00:48 +0000839 case kBack_SkKey:
840 this->loadView(NULL);
841 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000842 default:
843 break;
844 }
845 return this->INHERITED::onHandleKey(key);
846}
847
reed@google.com52f57e12011-03-16 12:10:02 +0000848///////////////////////////////////////////////////////////////////////////////
849
850static const char gGestureClickType[] = "GestureClickType";
851
852class GestureClick : public SkView::Click {
853public:
854 GestureClick(SkView* target) : SkView::Click(target) {
855 this->setType(gGestureClickType);
856 }
857
858 static bool IsGesture(Click* click) {
859 return click->isType(gGestureClickType);
860 }
861};
862
863SkView::Click* SampleWindow::onFindClickHandler(SkScalar x, SkScalar y) {
864 return new GestureClick(this);
865}
866
867bool SampleWindow::onClick(Click* click) {
868 if (GestureClick::IsGesture(click)) {
869 float x = SkScalarToFloat(click->fCurr.fX);
870 float y = SkScalarToFloat(click->fCurr.fY);
871 switch (click->fState) {
872 case SkView::Click::kDown_State:
873 fGesture.touchBegin(click, x, y);
874 break;
875 case SkView::Click::kMoved_State:
876 fGesture.touchMoved(click, x, y);
877 this->inval(NULL);
878 break;
879 case SkView::Click::kUp_State:
880 fGesture.touchEnd(click);
881 this->inval(NULL);
882 break;
883 }
884 return true;
885 }
886 return false;
887}
888
889///////////////////////////////////////////////////////////////////////////////
890
reed@android.com8a1c16f2008-12-17 15:59:43 +0000891void SampleWindow::loadView(SkView* view) {
892 SkView::F2BIter iter(this);
893 SkView* prev = iter.next();
894 if (prev) {
895 prev->detachFromParent();
896 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000897
reed@android.com34245c72009-11-03 04:00:48 +0000898 if (NULL == view) {
899 view = create_overview(fSamples.count(), fSamples.begin());
900 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000901 view->setVisibleP(true);
reed@android.comf2b98d62010-12-20 18:26:13 +0000902 view->setClipToBounds(false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000903 this->attachChildToFront(view)->unref();
904 view->setSize(this->width(), this->height());
905
906 this->updateTitle();
907}
908
909static const char* gConfigNames[] = {
910 "unknown config",
911 "A1",
912 "A8",
913 "Index8",
914 "565",
915 "4444",
916 "8888"
917};
918
919static const char* configToString(SkBitmap::Config c) {
920 return gConfigNames[c];
921}
922
923static const char* gCanvasTypePrefix[] = {
924 "raster: ",
925 "picture: ",
926 "opengl: "
927};
928
929void SampleWindow::updateTitle() {
930 SkString title;
931
932 SkView::F2BIter iter(this);
933 SkView* view = iter.next();
934 SkEvent evt(gTitleEvtName);
935 if (view->doQuery(&evt)) {
936 title.set(evt.findString(gTitleEvtName));
937 }
938 if (title.size() == 0) {
939 title.set("<unknown>");
940 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000941
reed@android.com8a1c16f2008-12-17 15:59:43 +0000942 title.prepend(gCanvasTypePrefix[fCanvasType]);
943
944 title.prepend(" ");
945 title.prepend(configToString(this->getBitmap().config()));
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000946
reed@android.com8a1c16f2008-12-17 15:59:43 +0000947 if (fAnimating) {
948 title.prepend("<A> ");
949 }
reed@android.com6c5f6f22009-08-14 16:08:38 +0000950 if (fScale) {
951 title.prepend("<S> ");
952 }
953 if (fRotate) {
954 title.prepend("<R> ");
955 }
reed@android.come522ca52009-11-23 20:10:41 +0000956 if (fNClip) {
957 title.prepend("<C> ");
958 }
reed@google.comf0b5f682011-03-11 20:08:25 +0000959 if (LCDTextDrawFilter::kForceOn_Mode == fLCDMode) {
960 title.prepend("LCD ");
961 } else if (LCDTextDrawFilter::kForceOff_Mode == fLCDMode) {
962 title.prepend("lcd ");
963 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000964 this->setTitle(title.c_str());
965}
966
967void SampleWindow::onSizeChange() {
968 this->INHERITED::onSizeChange();
969
970 SkView::F2BIter iter(this);
971 SkView* view = iter.next();
972 view->setSize(this->width(), this->height());
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000973
reed@android.com8a1c16f2008-12-17 15:59:43 +0000974 // rebuild our clippath
975 {
976 const SkScalar W = this->width();
977 const SkScalar H = this->height();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000978
reed@android.com8a1c16f2008-12-17 15:59:43 +0000979 fClipPath.reset();
980#if 0
981 for (SkScalar y = SK_Scalar1; y < H; y += SkIntToScalar(32)) {
982 SkRect r;
983 r.set(SK_Scalar1, y, SkIntToScalar(30), y + SkIntToScalar(30));
984 for (; r.fLeft < W; r.offset(SkIntToScalar(32), 0))
985 fClipPath.addRect(r);
986 }
987#else
988 SkRect r;
989 r.set(0, 0, W, H);
990 fClipPath.addRect(r, SkPath::kCCW_Direction);
991 r.set(W/4, H/4, W*3/4, H*3/4);
992 fClipPath.addRect(r, SkPath::kCW_Direction);
993#endif
994 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000995
reed@android.com8a1c16f2008-12-17 15:59:43 +0000996 this->updateTitle(); // to refresh our config
997}
998
999///////////////////////////////////////////////////////////////////////////////
1000
reed@android.comf2b98d62010-12-20 18:26:13 +00001001template <typename T> void SkTBSort(T array[], int count) {
1002 for (int i = 1; i < count - 1; i++) {
1003 bool didSwap = false;
1004 for (int j = count - 1; j > i; --j) {
1005 if (array[j] < array[j-1]) {
1006 T tmp(array[j-1]);
1007 array[j-1] = array[j];
1008 array[j] = tmp;
1009 didSwap = true;
1010 }
1011 }
1012 if (!didSwap) {
1013 break;
1014 }
1015 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001016
reed@android.comf2b98d62010-12-20 18:26:13 +00001017 for (int k = 0; k < count - 1; k++) {
1018 SkASSERT(!(array[k+1] < array[k]));
1019 }
1020}
1021
1022#include "SkRandom.h"
1023
1024static void rand_rect(SkIRect* rect, SkRandom& rand) {
1025 int bits = 8;
1026 int shift = 32 - bits;
1027 rect->set(rand.nextU() >> shift, rand.nextU() >> shift,
1028 rand.nextU() >> shift, rand.nextU() >> shift);
1029 rect->sort();
1030}
1031
1032static void dumpRect(const SkIRect& r) {
1033 SkDebugf(" { %d, %d, %d, %d },\n",
1034 r.fLeft, r.fTop,
1035 r.fRight, r.fBottom);
1036}
1037
1038static void test_rects(const SkIRect rect[], int count) {
1039 SkRegion rgn0, rgn1;
1040
1041 for (int i = 0; i < count; i++) {
1042 rgn0.op(rect[i], SkRegion::kUnion_Op);
1043 // dumpRect(rect[i]);
1044 }
1045 rgn1.setRects(rect, count);
1046
1047 if (rgn0 != rgn1) {
1048 SkDebugf("\n");
1049 for (int i = 0; i < count; i++) {
1050 dumpRect(rect[i]);
1051 }
1052 SkDebugf("\n");
1053 }
1054}
1055
1056static void test() {
1057 size_t i;
1058
1059 const SkIRect r0[] = {
1060 { 0, 0, 1, 1 },
1061 { 2, 2, 3, 3 },
1062 };
1063 const SkIRect r1[] = {
1064 { 0, 0, 1, 3 },
1065 { 1, 1, 2, 2 },
1066 { 2, 0, 3, 3 },
1067 };
1068 const SkIRect r2[] = {
1069 { 0, 0, 1, 2 },
1070 { 2, 1, 3, 3 },
1071 { 4, 0, 5, 1 },
1072 { 6, 0, 7, 4 },
1073 };
1074
1075 static const struct {
1076 const SkIRect* fRects;
1077 int fCount;
1078 } gRecs[] = {
1079 { r0, SK_ARRAY_COUNT(r0) },
1080 { r1, SK_ARRAY_COUNT(r1) },
1081 { r2, SK_ARRAY_COUNT(r2) },
1082 };
1083
1084 for (i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
1085 test_rects(gRecs[i].fRects, gRecs[i].fCount);
1086 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001087
reed@android.comf2b98d62010-12-20 18:26:13 +00001088 SkRandom rand;
1089 for (i = 0; i < 10000; i++) {
1090 SkRegion rgn0, rgn1;
1091
1092 const int N = 8;
1093 SkIRect rect[N];
1094 for (int j = 0; j < N; j++) {
1095 rand_rect(&rect[j], rand);
1096 }
1097 test_rects(rect, N);
1098 }
1099}
1100
reed@android.com8a1c16f2008-12-17 15:59:43 +00001101SkOSWindow* create_sk_window(void* hwnd) {
reed@android.comf2b98d62010-12-20 18:26:13 +00001102// test();
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001103 return new SampleWindow(hwnd);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001104}
1105
1106void get_preferred_size(int* x, int* y, int* width, int* height) {
1107 *x = 10;
1108 *y = 50;
1109 *width = 640;
1110 *height = 480;
1111}
1112
1113void application_init() {
1114// setenv("ANDROID_ROOT", "../../../data", 0);
reed@android.come191b162009-12-18 21:33:39 +00001115#ifdef SK_BUILD_FOR_MAC
reed@android.com8a1c16f2008-12-17 15:59:43 +00001116 setenv("ANDROID_ROOT", "/android/device/data", 0);
reed@android.come191b162009-12-18 21:33:39 +00001117#endif
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001118 SkGraphics::Init();
1119 SkEvent::Init();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001120}
1121
1122void application_term() {
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001123 SkEvent::Term();
1124 SkGraphics::Term();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001125}