blob: bb55da36342f01633704626a4bae1659a735cbd9 [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
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000016#define USE_ARROWS_FOR_ZOOM true
reed@android.comf2b98d62010-12-20 18:26:13 +000017//#define DEFAULT_TO_GPU
18
reed@android.come191b162009-12-18 21:33:39 +000019extern SkView* create_overview(int, const SkViewFactory[]);
reed@android.com34245c72009-11-03 04:00:48 +000020
reed@android.comcb342352010-07-22 18:27:53 +000021#define SK_SUPPORT_GL
reed@android.com8a1c16f2008-12-17 15:59:43 +000022
23#define ANIMATING_EVENTTYPE "nextSample"
24#define ANIMATING_DELAY 750
25
reed@google.comac10a2d2010-12-22 21:39:39 +000026#ifdef SK_SUPPORT_GL
27 #include "GrGLConfig.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000028#endif
29
reed@android.com8a1c16f2008-12-17 15:59:43 +000030SkViewRegister* SkViewRegister::gHead;
31SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
32 static bool gOnce;
33 if (!gOnce) {
34 gHead = NULL;
35 gOnce = true;
36 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +000037
reed@android.com8a1c16f2008-12-17 15:59:43 +000038 fChain = gHead;
39 gHead = this;
40}
41
reed@android.comf2b98d62010-12-20 18:26:13 +000042#if defined(SK_SUPPORT_GL)
43 #define SK_USE_SHADERS
44#endif
45
twiz@google.com06c3b6b2011-03-14 16:58:39 +000046#ifdef SK_BUILD_FOR_MAC
reed@google.comf0b5f682011-03-11 20:08:25 +000047#include <CoreFoundation/CoreFoundation.h>
48#include <CoreFoundation/CFURLAccess.h>
49
50static void testpdf() {
51 CFStringRef path = CFStringCreateWithCString(NULL, "/test.pdf",
52 kCFStringEncodingUTF8);
53 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path,
54 kCFURLPOSIXPathStyle,
55 false);
56 CFRelease(path);
57 CGRect box = CGRectMake(0, 0, 8*72, 10*72);
58 CGContextRef cg = CGPDFContextCreateWithURL(url, &box, NULL);
59 CFRelease(url);
60
61 CGContextBeginPage(cg, &box);
62 CGRect r = CGRectMake(10, 10, 40 + 0.5, 50 + 0.5);
63 CGContextFillEllipseInRect(cg, r);
64 CGContextEndPage(cg);
65 CGContextRelease(cg);
66
67 if (false) {
68 SkBitmap bm;
69 bm.setConfig(SkBitmap::kA8_Config, 64, 64);
70 bm.allocPixels();
71 bm.eraseColor(0);
72
73 SkCanvas canvas(bm);
74
75 }
76}
77#endif
78
79//////////////////////////////////////////////////////////////////////////////
80
81#include "SkDrawFilter.h"
82
83class LCDTextDrawFilter : public SkDrawFilter {
84public:
85 enum Mode {
86 kNeutral_Mode,
87 kForceOn_Mode,
88 kForceOff_Mode
89 };
90
91 LCDTextDrawFilter(Mode mode) : fMode(mode) {}
92
93 virtual bool filter(SkCanvas*, SkPaint* paint, Type t) {
94 if (kText_Type == t && kNeutral_Mode != fMode) {
95 fPrevLCD = paint->isLCDRenderText();
96 paint->setLCDRenderText(kForceOn_Mode == fMode);
97 }
98 return true;
99 }
100
101 /** If filter() returned true, then restore() will be called to restore the
102 canvas/paint to their previous states
103 */
104 virtual void restore(SkCanvas*, SkPaint* paint, Type t) {
105 if (kText_Type == t && kNeutral_Mode != fMode) {
106 paint->setLCDRenderText(fPrevLCD);
107 }
108 }
109
110private:
111 Mode fMode;
112 bool fPrevLCD;
113};
114
115LCDTextDrawFilter::Mode cycle_lcdmode(LCDTextDrawFilter::Mode mode) {
116 static const LCDTextDrawFilter::Mode gCycle[] = {
117 /* kNeutral_Mode -> */ LCDTextDrawFilter::kForceOn_Mode,
118 /* kForceOn_Mode -> */ LCDTextDrawFilter::kForceOff_Mode,
119 /* kForceOff_Mode -> */ LCDTextDrawFilter::kNeutral_Mode
120 };
121 return gCycle[mode];
122}
123
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124//////////////////////////////////////////////////////////////////////////////
125
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000126#define MAX_ZOOM_LEVEL 8
127#define MIN_ZOOM_LEVEL -8
128
reed@android.comf2b98d62010-12-20 18:26:13 +0000129static const char gCharEvtName[] = "SampleCode_Char_Event";
130static const char gKeyEvtName[] = "SampleCode_Key_Event";
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131static const char gTitleEvtName[] = "SampleCode_Title_Event";
132static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
reed@android.comf2b98d62010-12-20 18:26:13 +0000133static const char gFastTextEvtName[] = "SampleCode_FastText_Event";
134
135bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) {
136 if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) {
137 if (outUni) {
138 *outUni = evt.getFast32();
139 }
140 return true;
141 }
142 return false;
143}
144
145bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) {
146 if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) {
147 if (outKey) {
148 *outKey = (SkKey)evt.getFast32();
149 }
150 return true;
151 }
152 return false;
153}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154
155bool SampleCode::TitleQ(const SkEvent& evt) {
156 return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
157}
158
159void SampleCode::TitleR(SkEvent* evt, const char title[]) {
160 SkASSERT(evt && TitleQ(*evt));
161 evt->setString(gTitleEvtName, title);
162}
163
164bool SampleCode::PrefSizeQ(const SkEvent& evt) {
165 return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1);
166}
167
168void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) {
169 SkASSERT(evt && PrefSizeQ(*evt));
170 SkScalar size[2];
171 size[0] = width;
172 size[1] = height;
173 evt->setScalars(gPrefSizeEvtName, 2, size);
174}
175
reed@android.comf2b98d62010-12-20 18:26:13 +0000176bool SampleCode::FastTextQ(const SkEvent& evt) {
177 return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1);
178}
179
180///////////////////////////////////////////////////////////////////////////////
181
reed@android.com44177402009-11-23 21:07:51 +0000182static SkMSec gAnimTime;
reed@android.comf2b98d62010-12-20 18:26:13 +0000183static SkMSec gAnimTimePrev;
184
reed@android.com44177402009-11-23 21:07:51 +0000185SkMSec SampleCode::GetAnimTime() { return gAnimTime; }
reed@android.comf2b98d62010-12-20 18:26:13 +0000186SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; }
187SkScalar SampleCode::GetAnimSecondsDelta() {
188 return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0);
189}
reed@android.com44177402009-11-23 21:07:51 +0000190
191SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000192 // since gAnimTime can be up to 32 bits, we can't convert it to a float
193 // or we'll lose the low bits. Hence we use doubles for the intermediate
194 // calculations
195 double seconds = (double)gAnimTime / 1000.0;
196 double value = SkScalarToDouble(speed) * seconds;
reed@android.com44177402009-11-23 21:07:51 +0000197 if (period) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000198 value = ::fmod(value, SkScalarToDouble(period));
reed@android.com44177402009-11-23 21:07:51 +0000199 }
reed@android.comf2b98d62010-12-20 18:26:13 +0000200 return SkDoubleToScalar(value);
reed@android.com44177402009-11-23 21:07:51 +0000201}
202
reed@android.com8a1c16f2008-12-17 15:59:43 +0000203//////////////////////////////////////////////////////////////////////////////
204
reed@android.comf2b98d62010-12-20 18:26:13 +0000205static SkView* curr_view(SkWindow* wind) {
206 SkView::F2BIter iter(wind);
207 return iter.next();
208}
209
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210class SampleWindow : public SkOSWindow {
reed@android.com34245c72009-11-03 04:00:48 +0000211 SkTDArray<SkViewFactory> fSamples;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212public:
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000213 SampleWindow(void* hwnd);
214 virtual ~SampleWindow();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215
reed@android.come522ca52009-11-23 20:10:41 +0000216 virtual void draw(SkCanvas* canvas);
217
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218protected:
219 virtual void onDraw(SkCanvas* canvas);
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000220 virtual bool onHandleKey(SkKey key);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000221 virtual bool onHandleChar(SkUnichar);
222 virtual void onSizeChange();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000223
reed@android.com8a1c16f2008-12-17 15:59:43 +0000224 virtual SkCanvas* beforeChildren(SkCanvas*);
225 virtual void afterChildren(SkCanvas*);
reed@android.com6c5f6f22009-08-14 16:08:38 +0000226 virtual void beforeChild(SkView* child, SkCanvas* canvas);
227 virtual void afterChild(SkView* child, SkCanvas* canvas);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000228
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000229 virtual bool onEvent(const SkEvent& evt);
reed@android.comf2b98d62010-12-20 18:26:13 +0000230 virtual bool onQuery(SkEvent* evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000232 virtual bool onDispatchClick(int x, int y, Click::State);
reed@google.com52f57e12011-03-16 12:10:02 +0000233 virtual bool onClick(Click* click);
234 virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
235
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236#if 0
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000237 virtual bool handleChar(SkUnichar uni);
238 virtual bool handleEvent(const SkEvent& evt);
239 virtual bool handleKey(SkKey key);
240 virtual bool handleKeyUp(SkKey key);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000241 virtual bool onHandleKeyUp(SkKey key);
242#endif
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000243
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244private:
reed@android.com34245c72009-11-03 04:00:48 +0000245 int fCurrIndex;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000246
reed@android.com8a1c16f2008-12-17 15:59:43 +0000247 SkPicture* fPicture;
reed@android.comf2b98d62010-12-20 18:26:13 +0000248 SkGpuCanvas* fGpuCanvas;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000249 GrContext* fGrContext;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250 SkPath fClipPath;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000251
reed@google.com52f57e12011-03-16 12:10:02 +0000252 SkTouchGesture fGesture;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000253 int fZoomLevel;
254 SkScalar fZoomScale;
reed@google.com52f57e12011-03-16 12:10:02 +0000255
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256 enum CanvasType {
257 kRaster_CanvasType,
258 kPicture_CanvasType,
reed@android.comf2b98d62010-12-20 18:26:13 +0000259 kGPU_CanvasType
reed@android.com8a1c16f2008-12-17 15:59:43 +0000260 };
261 CanvasType fCanvasType;
262
263 bool fUseClip;
reed@android.come522ca52009-11-23 20:10:41 +0000264 bool fNClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000265 bool fRepeatDrawing;
266 bool fAnimating;
reed@android.com6c5f6f22009-08-14 16:08:38 +0000267 bool fRotate;
268 bool fScale;
reed@android.comf2b98d62010-12-20 18:26:13 +0000269 bool fRequestGrabImage;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000270
reed@google.comf0b5f682011-03-11 20:08:25 +0000271 LCDTextDrawFilter::Mode fLCDMode;
272
reed@android.com8a1c16f2008-12-17 15:59:43 +0000273 int fScrollTestX, fScrollTestY;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000274
275 bool make3DReady();
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000276 void changeZoomLevel(int delta);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000277
reed@android.com8a1c16f2008-12-17 15:59:43 +0000278 void loadView(SkView*);
279 void updateTitle();
280 bool nextSample();
281
282 void postAnimatingEvent() {
283 if (fAnimating) {
284 SkEvent* evt = new SkEvent(ANIMATING_EVENTTYPE);
285 evt->post(this->getSinkID(), ANIMATING_DELAY);
286 }
287 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000288
289
reed@android.com8a1c16f2008-12-17 15:59:43 +0000290 static CanvasType cycle_canvastype(CanvasType);
291
292 typedef SkOSWindow INHERITED;
293};
294
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000295bool SampleWindow::make3DReady() {
296
297#if defined(SK_SUPPORT_GL)
bsalomon@google.com498a6232011-03-10 18:24:15 +0000298 if (attachGL()) {
299 if (NULL == fGrContext) {
300 #if defined(SK_USE_SHADERS)
301 fGrContext = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
302 #else
303 fGrContext = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, NULL);
304 #endif
305 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000306
bsalomon@google.com498a6232011-03-10 18:24:15 +0000307 if (NULL != fGrContext) {
308 return true;
309 } else {
310 detachGL();
311 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000312 }
313#endif
314 SkDebugf("Failed to setup 3D");
315 return false;
316}
317
reed@android.com8a1c16f2008-12-17 15:59:43 +0000318SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) {
319 static const CanvasType gCT[] = {
320 kPicture_CanvasType,
reed@android.comf2b98d62010-12-20 18:26:13 +0000321 kGPU_CanvasType,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322 kRaster_CanvasType
323 };
324 return gCT[ct];
325}
326
327SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000328 fPicture = NULL;
reed@android.comf2b98d62010-12-20 18:26:13 +0000329 fGpuCanvas = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000330
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000331 fGrContext = NULL;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000332
reed@android.comf2b98d62010-12-20 18:26:13 +0000333#ifdef DEFAULT_TO_GPU
334 fCanvasType = kGPU_CanvasType;
335#else
reed@android.com8a1c16f2008-12-17 15:59:43 +0000336 fCanvasType = kRaster_CanvasType;
reed@android.comf2b98d62010-12-20 18:26:13 +0000337#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000338 fUseClip = false;
reed@android.come522ca52009-11-23 20:10:41 +0000339 fNClip = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340 fRepeatDrawing = false;
341 fAnimating = false;
reed@android.com6c5f6f22009-08-14 16:08:38 +0000342 fRotate = false;
343 fScale = false;
reed@android.comf2b98d62010-12-20 18:26:13 +0000344 fRequestGrabImage = false;
reed@google.comf0b5f682011-03-11 20:08:25 +0000345 fLCDMode = LCDTextDrawFilter::kNeutral_Mode;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000346 fScrollTestX = fScrollTestY = 0;
347
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000348 fZoomLevel = 0;
349 fZoomScale = SK_Scalar1;
350
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000351// this->setConfig(SkBitmap::kRGB_565_Config);
352 this->setConfig(SkBitmap::kARGB_8888_Config);
353 this->setVisibleP(true);
reed@android.comf2b98d62010-12-20 18:26:13 +0000354 this->setClipToBounds(false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000355
reed@android.com34245c72009-11-03 04:00:48 +0000356 {
357 const SkViewRegister* reg = SkViewRegister::Head();
358 while (reg) {
359 *fSamples.append() = reg->factory();
360 reg = reg->next();
361 }
362 }
363 fCurrIndex = 0;
reed@android.come0f13ee2009-11-04 19:40:25 +0000364 this->loadView(fSamples[fCurrIndex]());
reed@google.comf0b5f682011-03-11 20:08:25 +0000365
twiz@google.com06c3b6b2011-03-14 16:58:39 +0000366#ifdef SK_BUILD_FOR_MAC
reed@google.comf0b5f682011-03-11 20:08:25 +0000367 testpdf();
twiz@google.com06c3b6b2011-03-14 16:58:39 +0000368#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000369}
370
371SampleWindow::~SampleWindow() {
372 delete fPicture;
reed@android.comf2b98d62010-12-20 18:26:13 +0000373 delete fGpuCanvas;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000374 if (NULL != fGrContext) {
375 fGrContext->unref();
376 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000377}
378
reed@android.com55e76b22009-11-23 21:46:47 +0000379static SkBitmap capture_bitmap(SkCanvas* canvas) {
380 SkBitmap bm;
381 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
382 src.copyTo(&bm, src.config());
383 return bm;
384}
385
386static bool bitmap_diff(SkCanvas* canvas, const SkBitmap& orig,
387 SkBitmap* diff) {
388 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000389
reed@android.com55e76b22009-11-23 21:46:47 +0000390 SkAutoLockPixels alp0(src);
391 SkAutoLockPixels alp1(orig);
392 for (int y = 0; y < src.height(); y++) {
393 const void* srcP = src.getAddr(0, y);
394 const void* origP = orig.getAddr(0, y);
395 size_t bytes = src.width() * src.bytesPerPixel();
396 if (memcmp(srcP, origP, bytes)) {
397 SkDebugf("---------- difference on line %d\n", y);
398 return true;
399 }
400 }
401 return false;
402}
403
reed@android.com44177402009-11-23 21:07:51 +0000404#define XCLIP_N 8
405#define YCLIP_N 8
reed@android.come522ca52009-11-23 20:10:41 +0000406
407void SampleWindow::draw(SkCanvas* canvas) {
reed@android.com44177402009-11-23 21:07:51 +0000408 // update the animation time
reed@android.comf2b98d62010-12-20 18:26:13 +0000409 gAnimTimePrev = gAnimTime;
reed@android.com44177402009-11-23 21:07:51 +0000410 gAnimTime = SkTime::GetMSecs();
411
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000412 if (fZoomLevel) {
413 SkMatrix m;
414 SkScalar cx = SkScalarHalf(this->width());
415 SkScalar cy = SkScalarHalf(this->height());
416 SkPoint center;
417 m = canvas->getTotalMatrix();//.invert(&m);
418 m.mapXY(cx, cy, &center);
419 cx = center.fX;
420 cy = center.fY;
421
422 m.setTranslate(-cx, -cy);
423 m.postScale(fZoomScale, fZoomScale);
424 m.postTranslate(cx, cy);
425
426 canvas->concat(m);
427 }
428
reed@google.com52f57e12011-03-16 12:10:02 +0000429 // Apply any gesture matrix
430 if (true) {
431 const SkMatrix& localM = fGesture.localM();
432 if (localM.getType() & SkMatrix::kScale_Mask) {
433 canvas->setExternalMatrix(&localM);
434 }
435 canvas->concat(localM);
436 canvas->concat(fGesture.globalM());
437
438 if (fGesture.isActive()) {
439 this->inval(NULL);
440 }
441 }
442
reed@android.come522ca52009-11-23 20:10:41 +0000443 if (fNClip) {
reed@android.com55e76b22009-11-23 21:46:47 +0000444 this->INHERITED::draw(canvas);
445 SkBitmap orig = capture_bitmap(canvas);
reed@android.come522ca52009-11-23 20:10:41 +0000446
447 const SkScalar w = this->width();
448 const SkScalar h = this->height();
449 const SkScalar cw = w / XCLIP_N;
450 const SkScalar ch = h / YCLIP_N;
451 for (int y = 0; y < YCLIP_N; y++) {
reed@android.com55e76b22009-11-23 21:46:47 +0000452 SkRect r;
453 r.fTop = y * ch;
454 r.fBottom = (y + 1) * ch;
455 if (y == YCLIP_N - 1) {
456 r.fBottom = h;
457 }
reed@android.come522ca52009-11-23 20:10:41 +0000458 for (int x = 0; x < XCLIP_N; x++) {
459 SkAutoCanvasRestore acr(canvas, true);
reed@android.com55e76b22009-11-23 21:46:47 +0000460 r.fLeft = x * cw;
461 r.fRight = (x + 1) * cw;
462 if (x == XCLIP_N - 1) {
463 r.fRight = w;
464 }
reed@android.come522ca52009-11-23 20:10:41 +0000465 canvas->clipRect(r);
466 this->INHERITED::draw(canvas);
467 }
468 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000469
reed@android.com55e76b22009-11-23 21:46:47 +0000470 SkBitmap diff;
471 if (bitmap_diff(canvas, orig, &diff)) {
472 }
reed@android.come522ca52009-11-23 20:10:41 +0000473 } else {
474 this->INHERITED::draw(canvas);
475 }
476}
477
reed@android.com8a1c16f2008-12-17 15:59:43 +0000478void SampleWindow::onDraw(SkCanvas* canvas) {
479 if (fRepeatDrawing) {
480 this->inval(NULL);
481 }
482}
483
484#include "SkColorPriv.h"
485
486static void reverseRedAndBlue(const SkBitmap& bm) {
487 SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config);
488 uint8_t* p = (uint8_t*)bm.getPixels();
489 uint8_t* stop = p + bm.getSize();
490 while (p < stop) {
491 // swap red/blue (to go from ARGB(int) to RGBA(memory) and premultiply
492 unsigned scale = SkAlpha255To256(p[3]);
493 unsigned r = p[2];
494 unsigned b = p[0];
495 p[0] = SkAlphaMul(r, scale);
496 p[1] = SkAlphaMul(p[1], scale);
497 p[2] = SkAlphaMul(b, scale);
498 p += 4;
499 }
500}
501
502SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000503 SkIPoint viewport;
504 bool alreadyGPU = canvas->getViewport(&viewport);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000505
reed@android.comf2b98d62010-12-20 18:26:13 +0000506 if (kGPU_CanvasType != fCanvasType) {
reed@android.com6efdc472008-12-19 18:24:35 +0000507#ifdef SK_SUPPORT_GL
reed@android.comf2b98d62010-12-20 18:26:13 +0000508 detachGL();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000509#endif
reed@android.comf2b98d62010-12-20 18:26:13 +0000510 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000511
reed@android.com8a1c16f2008-12-17 15:59:43 +0000512 switch (fCanvasType) {
513 case kRaster_CanvasType:
514 canvas = this->INHERITED::beforeChildren(canvas);
515 break;
516 case kPicture_CanvasType:
517 fPicture = new SkPicture;
518 canvas = fPicture->beginRecording(9999, 9999);
519 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000520 case kGPU_CanvasType: {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000521 if (!alreadyGPU && make3DReady()) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000522 SkDevice* device = canvas->getDevice();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000523 const SkBitmap& bitmap = device->accessBitmap(true);
524
bsalomon@google.com5782d712011-01-21 21:03:59 +0000525 GrRenderTarget* renderTarget;
526 renderTarget = fGrContext->createRenderTargetFrom3DApiState();
527 fGpuCanvas = new SkGpuCanvas(fGrContext, renderTarget);
528 renderTarget->unref();
529
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000530 device = fGpuCanvas->createDevice(SkBitmap::kARGB_8888_Config,
531 bitmap.width(), bitmap.height(),
532 false, false);
reed@google.comac10a2d2010-12-22 21:39:39 +0000533 fGpuCanvas->setDevice(device)->unref();
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000534
535 fGpuCanvas->concat(canvas->getTotalMatrix());
reed@android.comf2b98d62010-12-20 18:26:13 +0000536 canvas = fGpuCanvas;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000537
reed@android.comf2b98d62010-12-20 18:26:13 +0000538 } else {
539 canvas = this->INHERITED::beforeChildren(canvas);
540 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000541 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000542 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000543 }
544
545 if (fUseClip) {
546 canvas->drawColor(0xFFFF88FF);
547 canvas->clipPath(fClipPath);
548 }
549
550 return canvas;
551}
552
553static void paint_rgn(const SkBitmap& bm, const SkIRect& r,
554 const SkRegion& rgn) {
555 SkCanvas canvas(bm);
556 SkRegion inval(rgn);
557
558 inval.translate(r.fLeft, r.fTop);
559 canvas.clipRegion(inval);
560 canvas.drawColor(0xFFFF8080);
561}
562
563void SampleWindow::afterChildren(SkCanvas* orig) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000564 if (fRequestGrabImage) {
565 fRequestGrabImage = false;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000566
reed@android.comf2b98d62010-12-20 18:26:13 +0000567 SkCanvas* canvas = fGpuCanvas ? fGpuCanvas : orig;
568 SkDevice* device = canvas->getDevice();
569 SkBitmap bitmap;
reed@google.com5ba2d5b2011-03-10 19:40:34 +0000570 SkIRect bounds = {
571 0, 0,
572 SkScalarRound(this->width()),
573 SkScalarRound(this->height())
574 };
reed@android.comf2b98d62010-12-20 18:26:13 +0000575 if (device->readPixels(bounds, &bitmap)) {
576 static int gSampleGrabCounter;
577 SkString name;
578 name.printf("sample_grab_%d", gSampleGrabCounter++);
579 SkImageEncoder::EncodeFile(name.c_str(), bitmap,
580 SkImageEncoder::kPNG_Type, 100);
581 }
582 }
583
reed@android.com8a1c16f2008-12-17 15:59:43 +0000584 switch (fCanvasType) {
585 case kRaster_CanvasType:
586 break;
587 case kPicture_CanvasType:
reed@android.comaefd2bc2009-03-30 21:02:14 +0000588 if (true) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000589 SkPicture* pict = new SkPicture(*fPicture);
590 fPicture->unref();
591 orig->drawPicture(*pict);
592 pict->unref();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000593 } else if (true) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000594 SkDynamicMemoryWStream ostream;
595 fPicture->serialize(&ostream);
596 fPicture->unref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000597
reed@android.com8a1c16f2008-12-17 15:59:43 +0000598 SkMemoryStream istream(ostream.getStream(), ostream.getOffset());
599 SkPicture pict(&istream);
600 orig->drawPicture(pict);
601 } else {
602 fPicture->draw(orig);
603 fPicture->unref();
604 }
605 fPicture = NULL;
606 break;
reed@android.com6efdc472008-12-19 18:24:35 +0000607#ifdef SK_SUPPORT_GL
reed@android.comf2b98d62010-12-20 18:26:13 +0000608 case kGPU_CanvasType:
609 delete fGpuCanvas;
610 fGpuCanvas = NULL;
611 presentGL();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000612 break;
reed@android.com6efdc472008-12-19 18:24:35 +0000613#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000614 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000615
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616// if ((fScrollTestX | fScrollTestY) != 0)
reed@android.comf2b98d62010-12-20 18:26:13 +0000617 if (false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000618 const SkBitmap& bm = orig->getDevice()->accessBitmap(true);
619 int dx = fScrollTestX * 7;
620 int dy = fScrollTestY * 7;
621 SkIRect r;
622 SkRegion inval;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000623
reed@android.com8a1c16f2008-12-17 15:59:43 +0000624 r.set(50, 50, 50+100, 50+100);
625 bm.scrollRect(&r, dx, dy, &inval);
626 paint_rgn(bm, r, inval);
627 }
628}
629
reed@android.com6c5f6f22009-08-14 16:08:38 +0000630void SampleWindow::beforeChild(SkView* child, SkCanvas* canvas) {
631 if (fScale) {
632 SkScalar scale = SK_Scalar1 * 7 / 10;
633 SkScalar cx = this->width() / 2;
634 SkScalar cy = this->height() / 2;
635 canvas->translate(cx, cy);
636 canvas->scale(scale, scale);
637 canvas->translate(-cx, -cy);
638 }
639 if (fRotate) {
640 SkScalar cx = this->width() / 2;
641 SkScalar cy = this->height() / 2;
642 canvas->translate(cx, cy);
643 canvas->rotate(SkIntToScalar(30));
644 canvas->translate(-cx, -cy);
645 }
reed@google.comf0b5f682011-03-11 20:08:25 +0000646
647 if (LCDTextDrawFilter::kNeutral_Mode != fLCDMode) {
648 canvas->setDrawFilter(new LCDTextDrawFilter(fLCDMode))->unref();
649 }
reed@android.com6c5f6f22009-08-14 16:08:38 +0000650}
651
652void SampleWindow::afterChild(SkView* child, SkCanvas* canvas) {
reed@google.comf0b5f682011-03-11 20:08:25 +0000653 canvas->setDrawFilter(NULL);
reed@android.com6c5f6f22009-08-14 16:08:38 +0000654}
655
reed@android.com8a1c16f2008-12-17 15:59:43 +0000656static SkBitmap::Config gConfigCycle[] = {
657 SkBitmap::kNo_Config, // none -> none
658 SkBitmap::kNo_Config, // a1 -> none
659 SkBitmap::kNo_Config, // a8 -> none
660 SkBitmap::kNo_Config, // index8 -> none
661 SkBitmap::kARGB_4444_Config, // 565 -> 4444
662 SkBitmap::kARGB_8888_Config, // 4444 -> 8888
663 SkBitmap::kRGB_565_Config // 8888 -> 565
664};
665
666static SkBitmap::Config cycle_configs(SkBitmap::Config c) {
667 return gConfigCycle[c];
668}
669
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000670void SampleWindow::changeZoomLevel(int delta) {
671 fZoomLevel += delta;
672 if (fZoomLevel > 0) {
673 fZoomLevel = SkMin32(fZoomLevel, MAX_ZOOM_LEVEL);
674 fZoomScale = SkIntToScalar(fZoomLevel + 1);
675 } else if (fZoomLevel < 0) {
676 fZoomLevel = SkMax32(fZoomLevel, MIN_ZOOM_LEVEL);
677 fZoomScale = SK_Scalar1 / (1 - fZoomLevel);
678 } else {
679 fZoomScale = SK_Scalar1;
680 }
681
682 this->inval(NULL);
683}
684
reed@android.com8a1c16f2008-12-17 15:59:43 +0000685bool SampleWindow::nextSample() {
reed@android.com34245c72009-11-03 04:00:48 +0000686 fCurrIndex = (fCurrIndex + 1) % fSamples.count();
687 this->loadView(fSamples[fCurrIndex]());
688 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000689}
690
691bool SampleWindow::onEvent(const SkEvent& evt) {
692 if (evt.isType(ANIMATING_EVENTTYPE)) {
693 if (fAnimating) {
694 this->nextSample();
695 this->postAnimatingEvent();
696 }
697 return true;
698 }
reed@android.com34245c72009-11-03 04:00:48 +0000699 if (evt.isType("set-curr-index")) {
700 fCurrIndex = evt.getFast32() % fSamples.count();
701 this->loadView(fSamples[fCurrIndex]());
702 return true;
703 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000704 return this->INHERITED::onEvent(evt);
705}
706
reed@android.comf2b98d62010-12-20 18:26:13 +0000707bool SampleWindow::onQuery(SkEvent* query) {
708 if (query->isType("get-slide-count")) {
709 query->setFast32(fSamples.count());
710 return true;
711 }
712 if (query->isType("get-slide-title")) {
713 SkView* view = fSamples[query->getFast32()]();
714 SkEvent evt(gTitleEvtName);
715 if (view->doQuery(&evt)) {
716 query->setString("title", evt.findString(gTitleEvtName));
717 }
718 SkSafeUnref(view);
719 return true;
720 }
721 if (query->isType("use-fast-text")) {
722 SkEvent evt(gFastTextEvtName);
723 return curr_view(this)->doQuery(&evt);
724 }
725 return this->INHERITED::onQuery(query);
726}
727
reed@android.com0ae6b242008-12-23 16:49:54 +0000728static void cleanup_for_filename(SkString* name) {
729 char* str = name->writable_str();
reed@android.come191b162009-12-18 21:33:39 +0000730 for (size_t i = 0; i < name->size(); i++) {
reed@android.com0ae6b242008-12-23 16:49:54 +0000731 switch (str[i]) {
732 case ':': str[i] = '-'; break;
733 case '/': str[i] = '-'; break;
734 case ' ': str[i] = '_'; break;
735 default: break;
736 }
737 }
738}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000739
740bool SampleWindow::onHandleChar(SkUnichar uni) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000741 {
742 SkView* view = curr_view(this);
743 if (view) {
744 SkEvent evt(gCharEvtName);
745 evt.setFast32(uni);
746 if (view->doQuery(&evt)) {
747 return true;
748 }
749 }
750 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000751
reed@android.com8a1c16f2008-12-17 15:59:43 +0000752 int dx = 0xFF;
753 int dy = 0xFF;
754
755 switch (uni) {
756 case '5': dx = 0; dy = 0; break;
757 case '8': dx = 0; dy = -1; break;
758 case '6': dx = 1; dy = 0; break;
759 case '2': dx = 0; dy = 1; break;
760 case '4': dx = -1; dy = 0; break;
761 case '7': dx = -1; dy = -1; break;
762 case '9': dx = 1; dy = -1; break;
763 case '3': dx = 1; dy = 1; break;
764 case '1': dx = -1; dy = 1; break;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000765
reed@android.com8a1c16f2008-12-17 15:59:43 +0000766 default:
767 break;
768 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000769
reed@android.com8a1c16f2008-12-17 15:59:43 +0000770 if (0xFF != dx && 0xFF != dy) {
771 if ((dx | dy) == 0) {
772 fScrollTestX = fScrollTestY = 0;
773 } else {
774 fScrollTestX += dx;
775 fScrollTestY += dy;
776 }
777 this->inval(NULL);
778 return true;
779 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000780
reed@android.com0ae6b242008-12-23 16:49:54 +0000781 switch (uni) {
782 case 'a':
783 fAnimating = !fAnimating;
784 this->postAnimatingEvent();
785 this->updateTitle();
786 return true;
787 case 'f': {
788 const char* title = this->getTitle();
789 if (title[0] == 0) {
790 title = "sampleapp";
791 }
792 SkString name(title);
793 cleanup_for_filename(&name);
794 name.append(".png");
795 if (SkImageEncoder::EncodeFile(name.c_str(), this->getBitmap(),
reed@android.comb08eb2b2009-01-06 20:16:26 +0000796 SkImageEncoder::kPNG_Type, 100)) {
reed@android.com0ae6b242008-12-23 16:49:54 +0000797 SkDebugf("Created %s\n", name.c_str());
798 }
799 return true;
800 }
reed@android.com6c5f6f22009-08-14 16:08:38 +0000801 case 'r':
802 fRotate = !fRotate;
803 this->inval(NULL);
804 this->updateTitle();
805 return true;
806 case 's':
807 fScale = !fScale;
808 this->inval(NULL);
809 this->updateTitle();
810 return true;
reed@google.comfb56a9e2011-02-10 18:47:24 +0000811 case 'c':
812 fUseClip = !fUseClip;
813 this->inval(NULL);
814 this->updateTitle();
815 return true;
reed@android.comf2b98d62010-12-20 18:26:13 +0000816 case 'd':
817 SkGraphics::SetFontCacheUsed(0);
818 return true;
819 case 'g':
820 fRequestGrabImage = true;
821 this->inval(NULL);
822 break;
reed@google.comf0b5f682011-03-11 20:08:25 +0000823 case 'l':
824 fLCDMode = cycle_lcdmode(fLCDMode);
825 this->updateTitle();
826 this->inval(NULL);
827 break;
reed@android.com0ae6b242008-12-23 16:49:54 +0000828 default:
829 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000830 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000831
reed@android.com8a1c16f2008-12-17 15:59:43 +0000832 return this->INHERITED::onHandleChar(uni);
833}
834
835#include "SkDumpCanvas.h"
836
837bool SampleWindow::onHandleKey(SkKey key) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000838 {
839 SkView* view = curr_view(this);
840 if (view) {
841 SkEvent evt(gKeyEvtName);
842 evt.setFast32(key);
843 if (view->doQuery(&evt)) {
844 return true;
845 }
846 }
847 }
848
reed@android.com8a1c16f2008-12-17 15:59:43 +0000849 switch (key) {
850 case kRight_SkKey:
851 if (this->nextSample()) {
852 return true;
853 }
854 break;
855 case kLeft_SkKey:
856 fCanvasType = cycle_canvastype(fCanvasType);
857 this->updateTitle();
858 this->inval(NULL);
859 return true;
860 case kUp_SkKey:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000861 if (USE_ARROWS_FOR_ZOOM) {
862 this->changeZoomLevel(1);
863 } else {
864 fNClip = !fNClip;
865 this->inval(NULL);
866 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000867 this->updateTitle();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000868 return true;
869 case kDown_SkKey:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000870 if (USE_ARROWS_FOR_ZOOM) {
871 this->changeZoomLevel(-1);
872 } else {
873 this->setConfig(cycle_configs(this->getBitmap().config()));
874 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000875 this->updateTitle();
876 return true;
877 case kOK_SkKey:
reed@android.comf2b98d62010-12-20 18:26:13 +0000878 if (false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000879 SkDebugfDumper dumper;
880 SkDumpCanvas dc(&dumper);
881 this->draw(&dc);
882 } else {
883 fRepeatDrawing = !fRepeatDrawing;
884 if (fRepeatDrawing) {
885 this->inval(NULL);
886 }
887 }
888 return true;
reed@android.com34245c72009-11-03 04:00:48 +0000889 case kBack_SkKey:
890 this->loadView(NULL);
891 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000892 default:
893 break;
894 }
895 return this->INHERITED::onHandleKey(key);
896}
897
reed@google.com52f57e12011-03-16 12:10:02 +0000898///////////////////////////////////////////////////////////////////////////////
899
900static const char gGestureClickType[] = "GestureClickType";
901
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000902bool SampleWindow::onDispatchClick(int x, int y, Click::State state) {
903 int w = SkScalarRound(this->width());
904 int h = SkScalarRound(this->height());
905
906 // check for the resize-box
907 if (w - x < 16 && h - y < 16) {
908 return false; // let the OS handle the click
909 } else {
910 return this->INHERITED::onDispatchClick(x, y, state);
911 }
912}
913
reed@google.com52f57e12011-03-16 12:10:02 +0000914class GestureClick : public SkView::Click {
915public:
916 GestureClick(SkView* target) : SkView::Click(target) {
917 this->setType(gGestureClickType);
918 }
919
920 static bool IsGesture(Click* click) {
921 return click->isType(gGestureClickType);
922 }
923};
924
925SkView::Click* SampleWindow::onFindClickHandler(SkScalar x, SkScalar y) {
926 return new GestureClick(this);
927}
928
929bool SampleWindow::onClick(Click* click) {
930 if (GestureClick::IsGesture(click)) {
931 float x = SkScalarToFloat(click->fCurr.fX);
932 float y = SkScalarToFloat(click->fCurr.fY);
933 switch (click->fState) {
934 case SkView::Click::kDown_State:
935 fGesture.touchBegin(click, x, y);
936 break;
937 case SkView::Click::kMoved_State:
938 fGesture.touchMoved(click, x, y);
939 this->inval(NULL);
940 break;
941 case SkView::Click::kUp_State:
942 fGesture.touchEnd(click);
943 this->inval(NULL);
944 break;
945 }
946 return true;
947 }
948 return false;
949}
950
951///////////////////////////////////////////////////////////////////////////////
952
reed@android.com8a1c16f2008-12-17 15:59:43 +0000953void SampleWindow::loadView(SkView* view) {
954 SkView::F2BIter iter(this);
955 SkView* prev = iter.next();
956 if (prev) {
957 prev->detachFromParent();
958 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000959
reed@android.com34245c72009-11-03 04:00:48 +0000960 if (NULL == view) {
961 view = create_overview(fSamples.count(), fSamples.begin());
962 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000963 view->setVisibleP(true);
reed@android.comf2b98d62010-12-20 18:26:13 +0000964 view->setClipToBounds(false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000965 this->attachChildToFront(view)->unref();
966 view->setSize(this->width(), this->height());
967
968 this->updateTitle();
969}
970
971static const char* gConfigNames[] = {
972 "unknown config",
973 "A1",
974 "A8",
975 "Index8",
976 "565",
977 "4444",
978 "8888"
979};
980
981static const char* configToString(SkBitmap::Config c) {
982 return gConfigNames[c];
983}
984
985static const char* gCanvasTypePrefix[] = {
986 "raster: ",
987 "picture: ",
988 "opengl: "
989};
990
991void SampleWindow::updateTitle() {
992 SkString title;
993
994 SkView::F2BIter iter(this);
995 SkView* view = iter.next();
996 SkEvent evt(gTitleEvtName);
997 if (view->doQuery(&evt)) {
998 title.set(evt.findString(gTitleEvtName));
999 }
1000 if (title.size() == 0) {
1001 title.set("<unknown>");
1002 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001003
reed@android.com8a1c16f2008-12-17 15:59:43 +00001004 title.prepend(gCanvasTypePrefix[fCanvasType]);
1005
1006 title.prepend(" ");
1007 title.prepend(configToString(this->getBitmap().config()));
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001008
reed@android.com8a1c16f2008-12-17 15:59:43 +00001009 if (fAnimating) {
1010 title.prepend("<A> ");
1011 }
reed@android.com6c5f6f22009-08-14 16:08:38 +00001012 if (fScale) {
1013 title.prepend("<S> ");
1014 }
1015 if (fRotate) {
1016 title.prepend("<R> ");
1017 }
reed@android.come522ca52009-11-23 20:10:41 +00001018 if (fNClip) {
1019 title.prepend("<C> ");
1020 }
reed@google.comf0b5f682011-03-11 20:08:25 +00001021 if (LCDTextDrawFilter::kForceOn_Mode == fLCDMode) {
1022 title.prepend("LCD ");
1023 } else if (LCDTextDrawFilter::kForceOff_Mode == fLCDMode) {
1024 title.prepend("lcd ");
1025 }
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001026
1027 if (fZoomLevel) {
1028 title.prependf("{%d} ", fZoomLevel);
1029 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001030 this->setTitle(title.c_str());
1031}
1032
1033void SampleWindow::onSizeChange() {
1034 this->INHERITED::onSizeChange();
1035
1036 SkView::F2BIter iter(this);
1037 SkView* view = iter.next();
1038 view->setSize(this->width(), this->height());
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001039
reed@android.com8a1c16f2008-12-17 15:59:43 +00001040 // rebuild our clippath
1041 {
1042 const SkScalar W = this->width();
1043 const SkScalar H = this->height();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001044
reed@android.com8a1c16f2008-12-17 15:59:43 +00001045 fClipPath.reset();
1046#if 0
1047 for (SkScalar y = SK_Scalar1; y < H; y += SkIntToScalar(32)) {
1048 SkRect r;
1049 r.set(SK_Scalar1, y, SkIntToScalar(30), y + SkIntToScalar(30));
1050 for (; r.fLeft < W; r.offset(SkIntToScalar(32), 0))
1051 fClipPath.addRect(r);
1052 }
1053#else
1054 SkRect r;
1055 r.set(0, 0, W, H);
1056 fClipPath.addRect(r, SkPath::kCCW_Direction);
1057 r.set(W/4, H/4, W*3/4, H*3/4);
1058 fClipPath.addRect(r, SkPath::kCW_Direction);
1059#endif
1060 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001061
reed@android.com8a1c16f2008-12-17 15:59:43 +00001062 this->updateTitle(); // to refresh our config
1063}
1064
1065///////////////////////////////////////////////////////////////////////////////
1066
reed@android.comf2b98d62010-12-20 18:26:13 +00001067template <typename T> void SkTBSort(T array[], int count) {
1068 for (int i = 1; i < count - 1; i++) {
1069 bool didSwap = false;
1070 for (int j = count - 1; j > i; --j) {
1071 if (array[j] < array[j-1]) {
1072 T tmp(array[j-1]);
1073 array[j-1] = array[j];
1074 array[j] = tmp;
1075 didSwap = true;
1076 }
1077 }
1078 if (!didSwap) {
1079 break;
1080 }
1081 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001082
reed@android.comf2b98d62010-12-20 18:26:13 +00001083 for (int k = 0; k < count - 1; k++) {
1084 SkASSERT(!(array[k+1] < array[k]));
1085 }
1086}
1087
1088#include "SkRandom.h"
1089
1090static void rand_rect(SkIRect* rect, SkRandom& rand) {
1091 int bits = 8;
1092 int shift = 32 - bits;
1093 rect->set(rand.nextU() >> shift, rand.nextU() >> shift,
1094 rand.nextU() >> shift, rand.nextU() >> shift);
1095 rect->sort();
1096}
1097
1098static void dumpRect(const SkIRect& r) {
1099 SkDebugf(" { %d, %d, %d, %d },\n",
1100 r.fLeft, r.fTop,
1101 r.fRight, r.fBottom);
1102}
1103
1104static void test_rects(const SkIRect rect[], int count) {
1105 SkRegion rgn0, rgn1;
1106
1107 for (int i = 0; i < count; i++) {
1108 rgn0.op(rect[i], SkRegion::kUnion_Op);
1109 // dumpRect(rect[i]);
1110 }
1111 rgn1.setRects(rect, count);
1112
1113 if (rgn0 != rgn1) {
1114 SkDebugf("\n");
1115 for (int i = 0; i < count; i++) {
1116 dumpRect(rect[i]);
1117 }
1118 SkDebugf("\n");
1119 }
1120}
1121
1122static void test() {
1123 size_t i;
1124
1125 const SkIRect r0[] = {
1126 { 0, 0, 1, 1 },
1127 { 2, 2, 3, 3 },
1128 };
1129 const SkIRect r1[] = {
1130 { 0, 0, 1, 3 },
1131 { 1, 1, 2, 2 },
1132 { 2, 0, 3, 3 },
1133 };
1134 const SkIRect r2[] = {
1135 { 0, 0, 1, 2 },
1136 { 2, 1, 3, 3 },
1137 { 4, 0, 5, 1 },
1138 { 6, 0, 7, 4 },
1139 };
1140
1141 static const struct {
1142 const SkIRect* fRects;
1143 int fCount;
1144 } gRecs[] = {
1145 { r0, SK_ARRAY_COUNT(r0) },
1146 { r1, SK_ARRAY_COUNT(r1) },
1147 { r2, SK_ARRAY_COUNT(r2) },
1148 };
1149
1150 for (i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
1151 test_rects(gRecs[i].fRects, gRecs[i].fCount);
1152 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001153
reed@android.comf2b98d62010-12-20 18:26:13 +00001154 SkRandom rand;
1155 for (i = 0; i < 10000; i++) {
1156 SkRegion rgn0, rgn1;
1157
1158 const int N = 8;
1159 SkIRect rect[N];
1160 for (int j = 0; j < N; j++) {
1161 rand_rect(&rect[j], rand);
1162 }
1163 test_rects(rect, N);
1164 }
1165}
1166
reed@android.com8a1c16f2008-12-17 15:59:43 +00001167SkOSWindow* create_sk_window(void* hwnd) {
reed@android.comf2b98d62010-12-20 18:26:13 +00001168// test();
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001169 return new SampleWindow(hwnd);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001170}
1171
1172void get_preferred_size(int* x, int* y, int* width, int* height) {
1173 *x = 10;
1174 *y = 50;
1175 *width = 640;
1176 *height = 480;
1177}
1178
1179void application_init() {
1180// setenv("ANDROID_ROOT", "../../../data", 0);
reed@android.come191b162009-12-18 21:33:39 +00001181#ifdef SK_BUILD_FOR_MAC
reed@android.com8a1c16f2008-12-17 15:59:43 +00001182 setenv("ANDROID_ROOT", "/android/device/data", 0);
reed@android.come191b162009-12-18 21:33:39 +00001183#endif
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001184 SkGraphics::Init();
1185 SkEvent::Init();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001186}
1187
1188void application_term() {
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001189 SkEvent::Term();
1190 SkGraphics::Term();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001191}