blob: 5291b7edaac22b1f0070d5da78c690ca9fffc0d1 [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"
Scroggo0f185c22011-03-24 18:35:50 +000015#include "SkTypeface.h"
reed@android.comf2b98d62010-12-20 18:26:13 +000016
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000017#define USE_ARROWS_FOR_ZOOM true
reed@android.comf2b98d62010-12-20 18:26:13 +000018//#define DEFAULT_TO_GPU
19
reed@android.come191b162009-12-18 21:33:39 +000020extern SkView* create_overview(int, const SkViewFactory[]);
reed@android.com34245c72009-11-03 04:00:48 +000021
reed@android.comcb342352010-07-22 18:27:53 +000022#define SK_SUPPORT_GL
reed@android.com8a1c16f2008-12-17 15:59:43 +000023
24#define ANIMATING_EVENTTYPE "nextSample"
25#define ANIMATING_DELAY 750
26
reed@google.comac10a2d2010-12-22 21:39:39 +000027#ifdef SK_SUPPORT_GL
28 #include "GrGLConfig.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000029#endif
30
reed@android.com8a1c16f2008-12-17 15:59:43 +000031SkViewRegister* SkViewRegister::gHead;
32SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
33 static bool gOnce;
34 if (!gOnce) {
35 gHead = NULL;
36 gOnce = true;
37 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +000038
reed@android.com8a1c16f2008-12-17 15:59:43 +000039 fChain = gHead;
40 gHead = this;
41}
42
reed@android.comf2b98d62010-12-20 18:26:13 +000043#if defined(SK_SUPPORT_GL)
44 #define SK_USE_SHADERS
45#endif
46
twiz@google.com06c3b6b2011-03-14 16:58:39 +000047#ifdef SK_BUILD_FOR_MAC
reed@google.comf0b5f682011-03-11 20:08:25 +000048#include <CoreFoundation/CoreFoundation.h>
49#include <CoreFoundation/CFURLAccess.h>
50
51static void testpdf() {
52 CFStringRef path = CFStringCreateWithCString(NULL, "/test.pdf",
53 kCFStringEncodingUTF8);
54 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path,
55 kCFURLPOSIXPathStyle,
56 false);
57 CFRelease(path);
58 CGRect box = CGRectMake(0, 0, 8*72, 10*72);
59 CGContextRef cg = CGPDFContextCreateWithURL(url, &box, NULL);
60 CFRelease(url);
61
62 CGContextBeginPage(cg, &box);
63 CGRect r = CGRectMake(10, 10, 40 + 0.5, 50 + 0.5);
64 CGContextFillEllipseInRect(cg, r);
65 CGContextEndPage(cg);
66 CGContextRelease(cg);
67
68 if (false) {
69 SkBitmap bm;
70 bm.setConfig(SkBitmap::kA8_Config, 64, 64);
71 bm.allocPixels();
72 bm.eraseColor(0);
73
74 SkCanvas canvas(bm);
75
76 }
77}
78#endif
79
80//////////////////////////////////////////////////////////////////////////////
81
reed@google.com569e0432011-04-05 13:07:03 +000082enum FlipAxisEnum {
83 kFlipAxis_X = (1 << 0),
84 kFlipAxis_Y = (1 << 1)
85};
86
87enum SkTriState {
88 kFalse_SkTriState,
89 kTrue_SkTriState,
90 kUnknown_SkTriState,
91};
92
93static SkTriState cycle_tristate(SkTriState state) {
94 static const SkTriState gCycle[] = {
95 /* kFalse_SkTriState -> */ kUnknown_SkTriState,
96 /* kTrue_SkTriState -> */ kFalse_SkTriState,
97 /* kUnknown_SkTriState -> */ kTrue_SkTriState,
98 };
99 return gCycle[state];
100}
101
reed@google.comf0b5f682011-03-11 20:08:25 +0000102#include "SkDrawFilter.h"
103
reed@google.com569e0432011-04-05 13:07:03 +0000104class FlagsDrawFilter : public SkDrawFilter {
reed@google.comf0b5f682011-03-11 20:08:25 +0000105public:
reed@google.com569e0432011-04-05 13:07:03 +0000106 FlagsDrawFilter(SkTriState lcd, SkTriState aa) : fLCDState(lcd), fAAState(aa) {}
reed@google.comf0b5f682011-03-11 20:08:25 +0000107
mike@reedtribe.org3ce59dc2011-04-08 00:38:05 +0000108 virtual void filter(SkPaint* paint, Type t) {
reed@google.com569e0432011-04-05 13:07:03 +0000109 if (kText_Type == t && kUnknown_SkTriState != fLCDState) {
reed@google.com569e0432011-04-05 13:07:03 +0000110 paint->setLCDRenderText(kTrue_SkTriState == fLCDState);
111 }
112 if (kUnknown_SkTriState != fAAState) {
reed@google.com569e0432011-04-05 13:07:03 +0000113 paint->setAntiAlias(kTrue_SkTriState == fAAState);
reed@google.comf0b5f682011-03-11 20:08:25 +0000114 }
reed@google.comf0b5f682011-03-11 20:08:25 +0000115 }
116
117private:
reed@google.com569e0432011-04-05 13:07:03 +0000118 SkTriState fLCDState;
reed@google.com569e0432011-04-05 13:07:03 +0000119 SkTriState fAAState;
reed@google.comf0b5f682011-03-11 20:08:25 +0000120};
121
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122//////////////////////////////////////////////////////////////////////////////
123
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000124#define MAX_ZOOM_LEVEL 8
125#define MIN_ZOOM_LEVEL -8
126
reed@android.comf2b98d62010-12-20 18:26:13 +0000127static const char gCharEvtName[] = "SampleCode_Char_Event";
128static const char gKeyEvtName[] = "SampleCode_Key_Event";
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129static const char gTitleEvtName[] = "SampleCode_Title_Event";
130static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
reed@android.comf2b98d62010-12-20 18:26:13 +0000131static const char gFastTextEvtName[] = "SampleCode_FastText_Event";
132
133bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) {
134 if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) {
135 if (outUni) {
136 *outUni = evt.getFast32();
137 }
138 return true;
139 }
140 return false;
141}
142
143bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) {
144 if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) {
145 if (outKey) {
146 *outKey = (SkKey)evt.getFast32();
147 }
148 return true;
149 }
150 return false;
151}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152
153bool SampleCode::TitleQ(const SkEvent& evt) {
154 return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
155}
156
157void SampleCode::TitleR(SkEvent* evt, const char title[]) {
158 SkASSERT(evt && TitleQ(*evt));
159 evt->setString(gTitleEvtName, title);
160}
161
162bool SampleCode::PrefSizeQ(const SkEvent& evt) {
163 return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1);
164}
165
166void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) {
167 SkASSERT(evt && PrefSizeQ(*evt));
168 SkScalar size[2];
169 size[0] = width;
170 size[1] = height;
171 evt->setScalars(gPrefSizeEvtName, 2, size);
172}
173
reed@android.comf2b98d62010-12-20 18:26:13 +0000174bool SampleCode::FastTextQ(const SkEvent& evt) {
175 return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1);
176}
177
178///////////////////////////////////////////////////////////////////////////////
179
reed@android.com44177402009-11-23 21:07:51 +0000180static SkMSec gAnimTime;
reed@android.comf2b98d62010-12-20 18:26:13 +0000181static SkMSec gAnimTimePrev;
182
reed@android.com44177402009-11-23 21:07:51 +0000183SkMSec SampleCode::GetAnimTime() { return gAnimTime; }
reed@android.comf2b98d62010-12-20 18:26:13 +0000184SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; }
185SkScalar SampleCode::GetAnimSecondsDelta() {
186 return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0);
187}
reed@android.com44177402009-11-23 21:07:51 +0000188
189SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000190 // since gAnimTime can be up to 32 bits, we can't convert it to a float
191 // or we'll lose the low bits. Hence we use doubles for the intermediate
192 // calculations
193 double seconds = (double)gAnimTime / 1000.0;
194 double value = SkScalarToDouble(speed) * seconds;
reed@android.com44177402009-11-23 21:07:51 +0000195 if (period) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000196 value = ::fmod(value, SkScalarToDouble(period));
reed@android.com44177402009-11-23 21:07:51 +0000197 }
reed@android.comf2b98d62010-12-20 18:26:13 +0000198 return SkDoubleToScalar(value);
reed@android.com44177402009-11-23 21:07:51 +0000199}
200
reed@android.com8a1c16f2008-12-17 15:59:43 +0000201//////////////////////////////////////////////////////////////////////////////
202
reed@android.comf2b98d62010-12-20 18:26:13 +0000203static SkView* curr_view(SkWindow* wind) {
204 SkView::F2BIter iter(wind);
205 return iter.next();
206}
207
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208class SampleWindow : public SkOSWindow {
reed@android.com34245c72009-11-03 04:00:48 +0000209 SkTDArray<SkViewFactory> fSamples;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210public:
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000211 SampleWindow(void* hwnd);
212 virtual ~SampleWindow();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000213
reed@android.come522ca52009-11-23 20:10:41 +0000214 virtual void draw(SkCanvas* canvas);
215
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216protected:
217 virtual void onDraw(SkCanvas* canvas);
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000218 virtual bool onHandleKey(SkKey key);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000219 virtual bool onHandleChar(SkUnichar);
220 virtual void onSizeChange();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000221
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 virtual SkCanvas* beforeChildren(SkCanvas*);
223 virtual void afterChildren(SkCanvas*);
reed@android.com6c5f6f22009-08-14 16:08:38 +0000224 virtual void beforeChild(SkView* child, SkCanvas* canvas);
225 virtual void afterChild(SkView* child, SkCanvas* canvas);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000226
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000227 virtual bool onEvent(const SkEvent& evt);
reed@android.comf2b98d62010-12-20 18:26:13 +0000228 virtual bool onQuery(SkEvent* evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000229
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000230 virtual bool onDispatchClick(int x, int y, Click::State);
reed@google.com52f57e12011-03-16 12:10:02 +0000231 virtual bool onClick(Click* click);
232 virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
233
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234#if 0
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000235 virtual bool handleChar(SkUnichar uni);
236 virtual bool handleEvent(const SkEvent& evt);
237 virtual bool handleKey(SkKey key);
238 virtual bool handleKeyUp(SkKey key);
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;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000251 int fZoomLevel;
252 SkScalar fZoomScale;
reed@google.com52f57e12011-03-16 12:10:02 +0000253
reed@android.com8a1c16f2008-12-17 15:59:43 +0000254 enum CanvasType {
255 kRaster_CanvasType,
256 kPicture_CanvasType,
reed@android.comf2b98d62010-12-20 18:26:13 +0000257 kGPU_CanvasType
reed@android.com8a1c16f2008-12-17 15:59:43 +0000258 };
259 CanvasType fCanvasType;
260
261 bool fUseClip;
reed@android.come522ca52009-11-23 20:10:41 +0000262 bool fNClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263 bool fRepeatDrawing;
264 bool fAnimating;
reed@android.com6c5f6f22009-08-14 16:08:38 +0000265 bool fRotate;
266 bool fScale;
reed@android.comf2b98d62010-12-20 18:26:13 +0000267 bool fRequestGrabImage;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000268
Scroggo0f185c22011-03-24 18:35:50 +0000269 // The following are for the 'fatbits' drawing
270 // Latest position of the mouse.
271 int fMouseX, fMouseY;
272 int fFatBitsScale;
273 // Used by the text showing position and color values.
274 SkTypeface* fTypeface;
275 bool fShowZoomer;
276
reed@google.com569e0432011-04-05 13:07:03 +0000277 SkTriState fLCDState;
278 SkTriState fAAState;
279 unsigned fFlipAxis;
reed@google.comf0b5f682011-03-11 20:08:25 +0000280
reed@android.com8a1c16f2008-12-17 15:59:43 +0000281 int fScrollTestX, fScrollTestY;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000282
283 bool make3DReady();
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000284 void changeZoomLevel(int delta);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000285
reed@android.com8a1c16f2008-12-17 15:59:43 +0000286 void loadView(SkView*);
287 void updateTitle();
288 bool nextSample();
289
Scroggo0f185c22011-03-24 18:35:50 +0000290 void toggleZoomer();
291 bool zoomIn();
292 bool zoomOut();
293 void updatePointer(int x, int y);
294
reed@android.com8a1c16f2008-12-17 15:59:43 +0000295 void postAnimatingEvent() {
296 if (fAnimating) {
297 SkEvent* evt = new SkEvent(ANIMATING_EVENTTYPE);
298 evt->post(this->getSinkID(), ANIMATING_DELAY);
299 }
300 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000301
302
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303 static CanvasType cycle_canvastype(CanvasType);
304
305 typedef SkOSWindow INHERITED;
306};
307
Scroggo0f185c22011-03-24 18:35:50 +0000308bool SampleWindow::zoomIn()
309{
310 // Arbitrarily decided
311 if (fFatBitsScale == 25) return false;
312 fFatBitsScale++;
313 this->inval(NULL);
314 return true;
315}
316
317bool SampleWindow::zoomOut()
318{
319 if (fFatBitsScale == 1) return false;
320 fFatBitsScale--;
321 this->inval(NULL);
322 return true;
323}
324
325void SampleWindow::toggleZoomer()
326{
327 fShowZoomer = !fShowZoomer;
328 this->inval(NULL);
329}
330
331void SampleWindow::updatePointer(int x, int y)
332{
333 fMouseX = x;
334 fMouseY = y;
335 if (fShowZoomer) {
336 this->inval(NULL);
337 }
338}
339
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000340bool SampleWindow::make3DReady() {
341
342#if defined(SK_SUPPORT_GL)
bsalomon@google.com498a6232011-03-10 18:24:15 +0000343 if (attachGL()) {
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000344 if (NULL != fGrContext) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000345 // various gr lifecycle tests
346 #if 0
347 fGrContext->freeGpuResources();
348 #elif 0
349 // this will leak resources.
350 fGrContext->contextLost();
351 #elif 0
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000352 GrAssert(1 == fGrContext->refcnt());
353 fGrContext->unref();
354 fGrContext = NULL;
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000355 #endif
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000356 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000357
bsalomon@google.com498a6232011-03-10 18:24:15 +0000358 if (NULL == fGrContext) {
359 #if defined(SK_USE_SHADERS)
360 fGrContext = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
361 #else
362 fGrContext = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, NULL);
363 #endif
reed@google.com569e0432011-04-05 13:07:03 +0000364 SkDebugf("---- constructor\n");
bsalomon@google.com498a6232011-03-10 18:24:15 +0000365 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000366
bsalomon@google.com498a6232011-03-10 18:24:15 +0000367 if (NULL != fGrContext) {
368 return true;
369 } else {
370 detachGL();
371 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000372 }
373#endif
374 SkDebugf("Failed to setup 3D");
375 return false;
376}
377
reed@android.com8a1c16f2008-12-17 15:59:43 +0000378SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) {
379 static const CanvasType gCT[] = {
380 kPicture_CanvasType,
reed@android.comf2b98d62010-12-20 18:26:13 +0000381 kGPU_CanvasType,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000382 kRaster_CanvasType
383 };
384 return gCT[ct];
385}
386
387SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000388 fPicture = NULL;
reed@android.comf2b98d62010-12-20 18:26:13 +0000389 fGpuCanvas = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000390
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000391 fGrContext = NULL;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000392
reed@android.comf2b98d62010-12-20 18:26:13 +0000393#ifdef DEFAULT_TO_GPU
394 fCanvasType = kGPU_CanvasType;
395#else
reed@android.com8a1c16f2008-12-17 15:59:43 +0000396 fCanvasType = kRaster_CanvasType;
reed@android.comf2b98d62010-12-20 18:26:13 +0000397#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000398 fUseClip = false;
reed@android.come522ca52009-11-23 20:10:41 +0000399 fNClip = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000400 fRepeatDrawing = false;
401 fAnimating = false;
reed@android.com6c5f6f22009-08-14 16:08:38 +0000402 fRotate = false;
403 fScale = false;
reed@android.comf2b98d62010-12-20 18:26:13 +0000404 fRequestGrabImage = false;
reed@google.com569e0432011-04-05 13:07:03 +0000405 fLCDState = kUnknown_SkTriState;
406 fAAState = kUnknown_SkTriState;
407 fFlipAxis = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000408 fScrollTestX = fScrollTestY = 0;
409
Scroggo0f185c22011-03-24 18:35:50 +0000410 fMouseX = fMouseY = 0;
mike@reedtribe.org3ce59dc2011-04-08 00:38:05 +0000411 fFatBitsScale = 8;
Scroggo0f185c22011-03-24 18:35:50 +0000412 fTypeface = SkTypeface::CreateFromTypeface(NULL, SkTypeface::kBold);
413 fShowZoomer = false;
414
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000415 fZoomLevel = 0;
416 fZoomScale = SK_Scalar1;
417
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000418// this->setConfig(SkBitmap::kRGB_565_Config);
419 this->setConfig(SkBitmap::kARGB_8888_Config);
420 this->setVisibleP(true);
reed@android.comf2b98d62010-12-20 18:26:13 +0000421 this->setClipToBounds(false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000422
reed@android.com34245c72009-11-03 04:00:48 +0000423 {
424 const SkViewRegister* reg = SkViewRegister::Head();
425 while (reg) {
426 *fSamples.append() = reg->factory();
427 reg = reg->next();
428 }
429 }
430 fCurrIndex = 0;
reed@android.come0f13ee2009-11-04 19:40:25 +0000431 this->loadView(fSamples[fCurrIndex]());
reed@google.comf0b5f682011-03-11 20:08:25 +0000432
twiz@google.com06c3b6b2011-03-14 16:58:39 +0000433#ifdef SK_BUILD_FOR_MAC
reed@google.comf0b5f682011-03-11 20:08:25 +0000434 testpdf();
twiz@google.com06c3b6b2011-03-14 16:58:39 +0000435#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000436}
437
438SampleWindow::~SampleWindow() {
439 delete fPicture;
reed@android.comf2b98d62010-12-20 18:26:13 +0000440 delete fGpuCanvas;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000441 if (NULL != fGrContext) {
442 fGrContext->unref();
443 }
Scroggo0f185c22011-03-24 18:35:50 +0000444 fTypeface->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000445}
446
reed@android.com55e76b22009-11-23 21:46:47 +0000447static SkBitmap capture_bitmap(SkCanvas* canvas) {
448 SkBitmap bm;
449 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
450 src.copyTo(&bm, src.config());
451 return bm;
452}
453
454static bool bitmap_diff(SkCanvas* canvas, const SkBitmap& orig,
455 SkBitmap* diff) {
456 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000457
reed@android.com55e76b22009-11-23 21:46:47 +0000458 SkAutoLockPixels alp0(src);
459 SkAutoLockPixels alp1(orig);
460 for (int y = 0; y < src.height(); y++) {
461 const void* srcP = src.getAddr(0, y);
462 const void* origP = orig.getAddr(0, y);
463 size_t bytes = src.width() * src.bytesPerPixel();
464 if (memcmp(srcP, origP, bytes)) {
465 SkDebugf("---------- difference on line %d\n", y);
466 return true;
467 }
468 }
469 return false;
470}
471
Scroggo0f185c22011-03-24 18:35:50 +0000472static void drawText(SkCanvas* canvas, SkString string, SkScalar left, SkScalar top, SkPaint& paint)
473{
474 SkColor desiredColor = paint.getColor();
475 paint.setColor(SK_ColorWHITE);
476 const char* c_str = string.c_str();
477 size_t size = string.size();
478 SkRect bounds;
479 paint.measureText(c_str, size, &bounds);
480 bounds.offset(left, top);
481 SkScalar inset = SkIntToScalar(-2);
482 bounds.inset(inset, inset);
483 canvas->drawRect(bounds, paint);
484 if (desiredColor != SK_ColorBLACK) {
485 paint.setColor(SK_ColorBLACK);
486 canvas->drawText(c_str, size, left + SK_Scalar1, top + SK_Scalar1, paint);
487 }
488 paint.setColor(desiredColor);
489 canvas->drawText(c_str, size, left, top, paint);
490}
491
reed@android.com44177402009-11-23 21:07:51 +0000492#define XCLIP_N 8
493#define YCLIP_N 8
reed@android.come522ca52009-11-23 20:10:41 +0000494
495void SampleWindow::draw(SkCanvas* canvas) {
reed@android.com44177402009-11-23 21:07:51 +0000496 // update the animation time
reed@android.comf2b98d62010-12-20 18:26:13 +0000497 gAnimTimePrev = gAnimTime;
reed@android.com44177402009-11-23 21:07:51 +0000498 gAnimTime = SkTime::GetMSecs();
499
reed@google.com569e0432011-04-05 13:07:03 +0000500 SkScalar cx = SkScalarHalf(this->width());
501 SkScalar cy = SkScalarHalf(this->height());
502
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000503 if (fZoomLevel) {
504 SkMatrix m;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000505 SkPoint center;
506 m = canvas->getTotalMatrix();//.invert(&m);
507 m.mapXY(cx, cy, &center);
508 cx = center.fX;
509 cy = center.fY;
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000510
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000511 m.setTranslate(-cx, -cy);
512 m.postScale(fZoomScale, fZoomScale);
513 m.postTranslate(cx, cy);
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000514
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000515 canvas->concat(m);
516 }
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000517
reed@google.com569e0432011-04-05 13:07:03 +0000518 if (fFlipAxis) {
519 SkMatrix m;
520 m.setTranslate(cx, cy);
521 if (fFlipAxis & kFlipAxis_X) {
522 m.preScale(-SK_Scalar1, SK_Scalar1);
523 }
524 if (fFlipAxis & kFlipAxis_Y) {
525 m.preScale(SK_Scalar1, -SK_Scalar1);
526 }
527 m.preTranslate(-cx, -cy);
528 canvas->concat(m);
529 }
530
reed@google.com52f57e12011-03-16 12:10:02 +0000531 // Apply any gesture matrix
532 if (true) {
533 const SkMatrix& localM = fGesture.localM();
534 if (localM.getType() & SkMatrix::kScale_Mask) {
535 canvas->setExternalMatrix(&localM);
536 }
537 canvas->concat(localM);
538 canvas->concat(fGesture.globalM());
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000539
reed@google.com52f57e12011-03-16 12:10:02 +0000540 if (fGesture.isActive()) {
541 this->inval(NULL);
542 }
543 }
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000544
reed@android.come522ca52009-11-23 20:10:41 +0000545 if (fNClip) {
reed@android.com55e76b22009-11-23 21:46:47 +0000546 this->INHERITED::draw(canvas);
547 SkBitmap orig = capture_bitmap(canvas);
reed@android.come522ca52009-11-23 20:10:41 +0000548
549 const SkScalar w = this->width();
550 const SkScalar h = this->height();
551 const SkScalar cw = w / XCLIP_N;
552 const SkScalar ch = h / YCLIP_N;
553 for (int y = 0; y < YCLIP_N; y++) {
reed@android.com55e76b22009-11-23 21:46:47 +0000554 SkRect r;
555 r.fTop = y * ch;
556 r.fBottom = (y + 1) * ch;
557 if (y == YCLIP_N - 1) {
558 r.fBottom = h;
559 }
reed@android.come522ca52009-11-23 20:10:41 +0000560 for (int x = 0; x < XCLIP_N; x++) {
561 SkAutoCanvasRestore acr(canvas, true);
reed@android.com55e76b22009-11-23 21:46:47 +0000562 r.fLeft = x * cw;
563 r.fRight = (x + 1) * cw;
564 if (x == XCLIP_N - 1) {
565 r.fRight = w;
566 }
reed@android.come522ca52009-11-23 20:10:41 +0000567 canvas->clipRect(r);
568 this->INHERITED::draw(canvas);
569 }
570 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000571
reed@android.com55e76b22009-11-23 21:46:47 +0000572 SkBitmap diff;
573 if (bitmap_diff(canvas, orig, &diff)) {
574 }
reed@android.come522ca52009-11-23 20:10:41 +0000575 } else {
576 this->INHERITED::draw(canvas);
577 }
Scroggo0f185c22011-03-24 18:35:50 +0000578 if (fShowZoomer) {
579 int count = canvas->save();
580 canvas->resetMatrix();
581 // Ensure the mouse position is on screen.
582 int width = this->width();
583 int height = this->height();
584 if (fMouseX >= width) fMouseX = width - 1;
585 else if (fMouseX < 0) fMouseX = 0;
586 if (fMouseY >= height) fMouseY = height - 1;
587 else if (fMouseY < 0) fMouseY = 0;
588 SkBitmap bitmap = capture_bitmap(canvas);
589 // Find the size of the zoomed in view, forced to be odd, so the examined pixel is in the middle.
mike@reedtribe.org3ce59dc2011-04-08 00:38:05 +0000590 int zoomedWidth = (width >> 1) | 1;
591 int zoomedHeight = (height >> 1) | 1;
Scroggo0f185c22011-03-24 18:35:50 +0000592 SkIRect src;
593 src.set(0, 0, zoomedWidth / fFatBitsScale, zoomedHeight / fFatBitsScale);
594 src.offset(fMouseX - (src.width()>>1), fMouseY - (src.height()>>1));
595 SkRect dest;
596 dest.set(0, 0, SkIntToScalar(zoomedWidth), SkIntToScalar(zoomedHeight));
597 dest.offset(SkIntToScalar(width - zoomedWidth), SkIntToScalar(height - zoomedHeight));
598 SkPaint paint;
599 // Clear the background behind our zoomed in view
600 paint.setColor(SK_ColorWHITE);
601 canvas->drawRect(dest, paint);
602 canvas->drawBitmapRect(bitmap, &src, dest);
603 paint.setColor(SK_ColorBLACK);
604 paint.setStyle(SkPaint::kStroke_Style);
605 // Draw a border around the pixel in the middle
606 SkRect originalPixel;
607 originalPixel.set(SkIntToScalar(fMouseX), SkIntToScalar(fMouseY), SkIntToScalar(fMouseX + 1), SkIntToScalar(fMouseY + 1));
608 SkMatrix matrix;
609 SkRect scalarSrc;
610 scalarSrc.set(src);
611 SkColor color = bitmap.getColor(fMouseX, fMouseY);
612 if (matrix.setRectToRect(scalarSrc, dest, SkMatrix::kFill_ScaleToFit)) {
613 SkRect pixel;
614 matrix.mapRect(&pixel, originalPixel);
615 // TODO Perhaps measure the values and make the outline white if it's "dark"
616 if (color == SK_ColorBLACK) {
617 paint.setColor(SK_ColorWHITE);
618 }
619 canvas->drawRect(pixel, paint);
620 }
621 paint.setColor(SK_ColorBLACK);
622 // Draw a border around the destination rectangle
623 canvas->drawRect(dest, paint);
624 paint.setStyle(SkPaint::kStrokeAndFill_Style);
625 // Identify the pixel and its color on screen
626 paint.setTypeface(fTypeface);
627 paint.setAntiAlias(true);
628 SkScalar lineHeight = paint.getFontMetrics(NULL);
629 SkString string;
630 string.appendf("(%i, %i)", fMouseX, fMouseY);
631 SkScalar left = dest.fLeft + SkIntToScalar(3);
632 SkScalar i = SK_Scalar1;
633 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
634 // Alpha
635 i += SK_Scalar1;
636 string.reset();
637 string.appendf("A: %X", SkColorGetA(color));
638 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
639 // Red
640 i += SK_Scalar1;
641 string.reset();
642 string.appendf("R: %X", SkColorGetR(color));
643 paint.setColor(SK_ColorRED);
644 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
645 // Green
646 i += SK_Scalar1;
647 string.reset();
648 string.appendf("G: %X", SkColorGetG(color));
649 paint.setColor(SK_ColorGREEN);
650 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
651 // Blue
652 i += SK_Scalar1;
653 string.reset();
654 string.appendf("B: %X", SkColorGetB(color));
655 paint.setColor(SK_ColorBLUE);
656 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
657 canvas->restoreToCount(count);
658 }
reed@android.come522ca52009-11-23 20:10:41 +0000659}
660
reed@android.com8a1c16f2008-12-17 15:59:43 +0000661void SampleWindow::onDraw(SkCanvas* canvas) {
662 if (fRepeatDrawing) {
663 this->inval(NULL);
664 }
665}
666
667#include "SkColorPriv.h"
668
669static void reverseRedAndBlue(const SkBitmap& bm) {
670 SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config);
671 uint8_t* p = (uint8_t*)bm.getPixels();
672 uint8_t* stop = p + bm.getSize();
673 while (p < stop) {
674 // swap red/blue (to go from ARGB(int) to RGBA(memory) and premultiply
675 unsigned scale = SkAlpha255To256(p[3]);
676 unsigned r = p[2];
677 unsigned b = p[0];
678 p[0] = SkAlphaMul(r, scale);
679 p[1] = SkAlphaMul(p[1], scale);
680 p[2] = SkAlphaMul(b, scale);
681 p += 4;
682 }
683}
684
685SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000686 SkIPoint viewport;
687 bool alreadyGPU = canvas->getViewport(&viewport);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000688
reed@android.comf2b98d62010-12-20 18:26:13 +0000689 if (kGPU_CanvasType != fCanvasType) {
reed@android.com6efdc472008-12-19 18:24:35 +0000690#ifdef SK_SUPPORT_GL
reed@android.comf2b98d62010-12-20 18:26:13 +0000691 detachGL();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000692#endif
reed@android.comf2b98d62010-12-20 18:26:13 +0000693 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000694
reed@android.com8a1c16f2008-12-17 15:59:43 +0000695 switch (fCanvasType) {
696 case kRaster_CanvasType:
697 canvas = this->INHERITED::beforeChildren(canvas);
698 break;
699 case kPicture_CanvasType:
700 fPicture = new SkPicture;
701 canvas = fPicture->beginRecording(9999, 9999);
702 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000703 case kGPU_CanvasType: {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000704 if (!alreadyGPU && make3DReady()) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000705 SkDevice* device = canvas->getDevice();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000706 const SkBitmap& bitmap = device->accessBitmap(true);
707
bsalomon@google.com5782d712011-01-21 21:03:59 +0000708 GrRenderTarget* renderTarget;
709 renderTarget = fGrContext->createRenderTargetFrom3DApiState();
710 fGpuCanvas = new SkGpuCanvas(fGrContext, renderTarget);
711 renderTarget->unref();
712
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000713 device = fGpuCanvas->createDevice(SkBitmap::kARGB_8888_Config,
714 bitmap.width(), bitmap.height(),
715 false, false);
reed@google.comac10a2d2010-12-22 21:39:39 +0000716 fGpuCanvas->setDevice(device)->unref();
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000717
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000718 fGpuCanvas->concat(canvas->getTotalMatrix());
reed@android.comf2b98d62010-12-20 18:26:13 +0000719 canvas = fGpuCanvas;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000720
reed@android.comf2b98d62010-12-20 18:26:13 +0000721 } else {
722 canvas = this->INHERITED::beforeChildren(canvas);
723 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000724 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000725 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000726 }
727
728 if (fUseClip) {
729 canvas->drawColor(0xFFFF88FF);
730 canvas->clipPath(fClipPath);
731 }
732
733 return canvas;
734}
735
736static void paint_rgn(const SkBitmap& bm, const SkIRect& r,
737 const SkRegion& rgn) {
738 SkCanvas canvas(bm);
739 SkRegion inval(rgn);
740
741 inval.translate(r.fLeft, r.fTop);
742 canvas.clipRegion(inval);
743 canvas.drawColor(0xFFFF8080);
744}
745
746void SampleWindow::afterChildren(SkCanvas* orig) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000747 if (fRequestGrabImage) {
748 fRequestGrabImage = false;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000749
reed@android.comf2b98d62010-12-20 18:26:13 +0000750 SkCanvas* canvas = fGpuCanvas ? fGpuCanvas : orig;
751 SkDevice* device = canvas->getDevice();
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000752 SkBitmap bmp;
753 if (device->accessBitmap(false).copyTo(&bmp, SkBitmap::kARGB_8888_Config)) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000754 static int gSampleGrabCounter;
755 SkString name;
756 name.printf("sample_grab_%d", gSampleGrabCounter++);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000757 SkImageEncoder::EncodeFile(name.c_str(), bmp,
reed@android.comf2b98d62010-12-20 18:26:13 +0000758 SkImageEncoder::kPNG_Type, 100);
759 }
760 }
761
reed@android.com8a1c16f2008-12-17 15:59:43 +0000762 switch (fCanvasType) {
763 case kRaster_CanvasType:
764 break;
765 case kPicture_CanvasType:
reed@android.comaefd2bc2009-03-30 21:02:14 +0000766 if (true) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000767 SkPicture* pict = new SkPicture(*fPicture);
768 fPicture->unref();
769 orig->drawPicture(*pict);
770 pict->unref();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000771 } else if (true) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000772 SkDynamicMemoryWStream ostream;
773 fPicture->serialize(&ostream);
774 fPicture->unref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000775
reed@android.com8a1c16f2008-12-17 15:59:43 +0000776 SkMemoryStream istream(ostream.getStream(), ostream.getOffset());
777 SkPicture pict(&istream);
778 orig->drawPicture(pict);
779 } else {
780 fPicture->draw(orig);
781 fPicture->unref();
782 }
783 fPicture = NULL;
784 break;
reed@android.com6efdc472008-12-19 18:24:35 +0000785#ifdef SK_SUPPORT_GL
reed@android.comf2b98d62010-12-20 18:26:13 +0000786 case kGPU_CanvasType:
787 delete fGpuCanvas;
788 fGpuCanvas = NULL;
789 presentGL();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000790 break;
reed@android.com6efdc472008-12-19 18:24:35 +0000791#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000792 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000793
reed@android.com8a1c16f2008-12-17 15:59:43 +0000794// if ((fScrollTestX | fScrollTestY) != 0)
reed@android.comf2b98d62010-12-20 18:26:13 +0000795 if (false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000796 const SkBitmap& bm = orig->getDevice()->accessBitmap(true);
797 int dx = fScrollTestX * 7;
798 int dy = fScrollTestY * 7;
799 SkIRect r;
800 SkRegion inval;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000801
reed@android.com8a1c16f2008-12-17 15:59:43 +0000802 r.set(50, 50, 50+100, 50+100);
803 bm.scrollRect(&r, dx, dy, &inval);
804 paint_rgn(bm, r, inval);
805 }
806}
807
reed@android.com6c5f6f22009-08-14 16:08:38 +0000808void SampleWindow::beforeChild(SkView* child, SkCanvas* canvas) {
809 if (fScale) {
810 SkScalar scale = SK_Scalar1 * 7 / 10;
811 SkScalar cx = this->width() / 2;
812 SkScalar cy = this->height() / 2;
813 canvas->translate(cx, cy);
814 canvas->scale(scale, scale);
815 canvas->translate(-cx, -cy);
816 }
817 if (fRotate) {
818 SkScalar cx = this->width() / 2;
819 SkScalar cy = this->height() / 2;
820 canvas->translate(cx, cy);
821 canvas->rotate(SkIntToScalar(30));
822 canvas->translate(-cx, -cy);
823 }
reed@google.comf0b5f682011-03-11 20:08:25 +0000824
reed@google.com569e0432011-04-05 13:07:03 +0000825 if (kUnknown_SkTriState != fLCDState ||
826 kUnknown_SkTriState != fAAState) {
827 canvas->setDrawFilter(new FlagsDrawFilter(fLCDState, fAAState))->unref();
reed@google.comf0b5f682011-03-11 20:08:25 +0000828 }
reed@android.com6c5f6f22009-08-14 16:08:38 +0000829}
830
831void SampleWindow::afterChild(SkView* child, SkCanvas* canvas) {
reed@google.comf0b5f682011-03-11 20:08:25 +0000832 canvas->setDrawFilter(NULL);
reed@android.com6c5f6f22009-08-14 16:08:38 +0000833}
834
reed@android.com8a1c16f2008-12-17 15:59:43 +0000835static SkBitmap::Config gConfigCycle[] = {
836 SkBitmap::kNo_Config, // none -> none
837 SkBitmap::kNo_Config, // a1 -> none
838 SkBitmap::kNo_Config, // a8 -> none
839 SkBitmap::kNo_Config, // index8 -> none
840 SkBitmap::kARGB_4444_Config, // 565 -> 4444
841 SkBitmap::kARGB_8888_Config, // 4444 -> 8888
842 SkBitmap::kRGB_565_Config // 8888 -> 565
843};
844
845static SkBitmap::Config cycle_configs(SkBitmap::Config c) {
846 return gConfigCycle[c];
847}
848
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000849void SampleWindow::changeZoomLevel(int delta) {
850 fZoomLevel += delta;
851 if (fZoomLevel > 0) {
852 fZoomLevel = SkMin32(fZoomLevel, MAX_ZOOM_LEVEL);
853 fZoomScale = SkIntToScalar(fZoomLevel + 1);
854 } else if (fZoomLevel < 0) {
855 fZoomLevel = SkMax32(fZoomLevel, MIN_ZOOM_LEVEL);
856 fZoomScale = SK_Scalar1 / (1 - fZoomLevel);
857 } else {
858 fZoomScale = SK_Scalar1;
859 }
860
861 this->inval(NULL);
862}
863
reed@android.com8a1c16f2008-12-17 15:59:43 +0000864bool SampleWindow::nextSample() {
reed@android.com34245c72009-11-03 04:00:48 +0000865 fCurrIndex = (fCurrIndex + 1) % fSamples.count();
866 this->loadView(fSamples[fCurrIndex]());
867 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000868}
869
870bool SampleWindow::onEvent(const SkEvent& evt) {
871 if (evt.isType(ANIMATING_EVENTTYPE)) {
872 if (fAnimating) {
873 this->nextSample();
874 this->postAnimatingEvent();
875 }
876 return true;
877 }
reed@android.com34245c72009-11-03 04:00:48 +0000878 if (evt.isType("set-curr-index")) {
879 fCurrIndex = evt.getFast32() % fSamples.count();
880 this->loadView(fSamples[fCurrIndex]());
881 return true;
882 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000883 return this->INHERITED::onEvent(evt);
884}
885
reed@android.comf2b98d62010-12-20 18:26:13 +0000886bool SampleWindow::onQuery(SkEvent* query) {
887 if (query->isType("get-slide-count")) {
888 query->setFast32(fSamples.count());
889 return true;
890 }
891 if (query->isType("get-slide-title")) {
892 SkView* view = fSamples[query->getFast32()]();
893 SkEvent evt(gTitleEvtName);
894 if (view->doQuery(&evt)) {
895 query->setString("title", evt.findString(gTitleEvtName));
896 }
897 SkSafeUnref(view);
898 return true;
899 }
900 if (query->isType("use-fast-text")) {
901 SkEvent evt(gFastTextEvtName);
902 return curr_view(this)->doQuery(&evt);
903 }
904 return this->INHERITED::onQuery(query);
905}
906
reed@android.com0ae6b242008-12-23 16:49:54 +0000907static void cleanup_for_filename(SkString* name) {
908 char* str = name->writable_str();
reed@android.come191b162009-12-18 21:33:39 +0000909 for (size_t i = 0; i < name->size(); i++) {
reed@android.com0ae6b242008-12-23 16:49:54 +0000910 switch (str[i]) {
911 case ':': str[i] = '-'; break;
912 case '/': str[i] = '-'; break;
913 case ' ': str[i] = '_'; break;
914 default: break;
915 }
916 }
917}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000918
919bool SampleWindow::onHandleChar(SkUnichar uni) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000920 {
921 SkView* view = curr_view(this);
922 if (view) {
923 SkEvent evt(gCharEvtName);
924 evt.setFast32(uni);
925 if (view->doQuery(&evt)) {
926 return true;
927 }
928 }
929 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000930
reed@android.com8a1c16f2008-12-17 15:59:43 +0000931 int dx = 0xFF;
932 int dy = 0xFF;
933
934 switch (uni) {
935 case '5': dx = 0; dy = 0; break;
936 case '8': dx = 0; dy = -1; break;
937 case '6': dx = 1; dy = 0; break;
938 case '2': dx = 0; dy = 1; break;
939 case '4': dx = -1; dy = 0; break;
940 case '7': dx = -1; dy = -1; break;
941 case '9': dx = 1; dy = -1; break;
942 case '3': dx = 1; dy = 1; break;
943 case '1': dx = -1; dy = 1; break;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000944
reed@android.com8a1c16f2008-12-17 15:59:43 +0000945 default:
946 break;
947 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000948
reed@android.com8a1c16f2008-12-17 15:59:43 +0000949 if (0xFF != dx && 0xFF != dy) {
950 if ((dx | dy) == 0) {
951 fScrollTestX = fScrollTestY = 0;
952 } else {
953 fScrollTestX += dx;
954 fScrollTestY += dy;
955 }
956 this->inval(NULL);
957 return true;
958 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000959
reed@android.com0ae6b242008-12-23 16:49:54 +0000960 switch (uni) {
961 case 'a':
962 fAnimating = !fAnimating;
963 this->postAnimatingEvent();
964 this->updateTitle();
965 return true;
966 case 'f': {
967 const char* title = this->getTitle();
968 if (title[0] == 0) {
969 title = "sampleapp";
970 }
971 SkString name(title);
972 cleanup_for_filename(&name);
973 name.append(".png");
974 if (SkImageEncoder::EncodeFile(name.c_str(), this->getBitmap(),
reed@android.comb08eb2b2009-01-06 20:16:26 +0000975 SkImageEncoder::kPNG_Type, 100)) {
reed@android.com0ae6b242008-12-23 16:49:54 +0000976 SkDebugf("Created %s\n", name.c_str());
977 }
978 return true;
979 }
reed@android.com6c5f6f22009-08-14 16:08:38 +0000980 case 'r':
981 fRotate = !fRotate;
982 this->inval(NULL);
983 this->updateTitle();
984 return true;
985 case 's':
986 fScale = !fScale;
987 this->inval(NULL);
988 this->updateTitle();
989 return true;
reed@google.comfb56a9e2011-02-10 18:47:24 +0000990 case 'c':
991 fUseClip = !fUseClip;
992 this->inval(NULL);
993 this->updateTitle();
994 return true;
reed@android.comf2b98d62010-12-20 18:26:13 +0000995 case 'd':
996 SkGraphics::SetFontCacheUsed(0);
997 return true;
998 case 'g':
999 fRequestGrabImage = true;
1000 this->inval(NULL);
1001 break;
reed@google.comf0b5f682011-03-11 20:08:25 +00001002 case 'l':
reed@google.com569e0432011-04-05 13:07:03 +00001003 fLCDState = cycle_tristate(fLCDState);
1004 this->updateTitle();
1005 this->inval(NULL);
1006 break;
1007 case 'b':
1008 fAAState = cycle_tristate(fAAState);
reed@google.comf0b5f682011-03-11 20:08:25 +00001009 this->updateTitle();
1010 this->inval(NULL);
1011 break;
scroggo08526c02011-03-22 14:03:21 +00001012 case 'i':
1013 this->zoomIn();
1014 break;
1015 case 'o':
1016 this->zoomOut();
1017 break;
reed@google.com569e0432011-04-05 13:07:03 +00001018 case 'x':
1019 fFlipAxis ^= kFlipAxis_X;
1020 this->updateTitle();
1021 this->inval(NULL);
1022 break;
1023 case 'y':
1024 fFlipAxis ^= kFlipAxis_Y;
1025 this->updateTitle();
1026 this->inval(NULL);
1027 break;
scroggo08526c02011-03-22 14:03:21 +00001028 case 'z':
1029 this->toggleZoomer();
1030 break;
reed@android.com0ae6b242008-12-23 16:49:54 +00001031 default:
1032 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001033 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001034
reed@android.com8a1c16f2008-12-17 15:59:43 +00001035 return this->INHERITED::onHandleChar(uni);
1036}
1037
1038#include "SkDumpCanvas.h"
1039
1040bool SampleWindow::onHandleKey(SkKey key) {
reed@android.comf2b98d62010-12-20 18:26:13 +00001041 {
1042 SkView* view = curr_view(this);
1043 if (view) {
1044 SkEvent evt(gKeyEvtName);
1045 evt.setFast32(key);
1046 if (view->doQuery(&evt)) {
1047 return true;
1048 }
1049 }
1050 }
1051
reed@android.com8a1c16f2008-12-17 15:59:43 +00001052 switch (key) {
1053 case kRight_SkKey:
1054 if (this->nextSample()) {
1055 return true;
1056 }
1057 break;
1058 case kLeft_SkKey:
1059 fCanvasType = cycle_canvastype(fCanvasType);
1060 this->updateTitle();
1061 this->inval(NULL);
1062 return true;
1063 case kUp_SkKey:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001064 if (USE_ARROWS_FOR_ZOOM) {
1065 this->changeZoomLevel(1);
1066 } else {
1067 fNClip = !fNClip;
1068 this->inval(NULL);
1069 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001070 this->updateTitle();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001071 return true;
1072 case kDown_SkKey:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001073 if (USE_ARROWS_FOR_ZOOM) {
1074 this->changeZoomLevel(-1);
1075 } else {
1076 this->setConfig(cycle_configs(this->getBitmap().config()));
1077 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001078 this->updateTitle();
1079 return true;
1080 case kOK_SkKey:
reed@android.comf2b98d62010-12-20 18:26:13 +00001081 if (false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001082 SkDebugfDumper dumper;
1083 SkDumpCanvas dc(&dumper);
1084 this->draw(&dc);
1085 } else {
1086 fRepeatDrawing = !fRepeatDrawing;
1087 if (fRepeatDrawing) {
1088 this->inval(NULL);
1089 }
1090 }
1091 return true;
reed@android.com34245c72009-11-03 04:00:48 +00001092 case kBack_SkKey:
1093 this->loadView(NULL);
1094 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001095 default:
1096 break;
1097 }
1098 return this->INHERITED::onHandleKey(key);
1099}
1100
reed@google.com52f57e12011-03-16 12:10:02 +00001101///////////////////////////////////////////////////////////////////////////////
1102
1103static const char gGestureClickType[] = "GestureClickType";
1104
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001105bool SampleWindow::onDispatchClick(int x, int y, Click::State state) {
Scroggo0f185c22011-03-24 18:35:50 +00001106 if (Click::kMoved_State == state) {
1107 updatePointer(x, y);
1108 }
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001109 int w = SkScalarRound(this->width());
1110 int h = SkScalarRound(this->height());
1111
1112 // check for the resize-box
1113 if (w - x < 16 && h - y < 16) {
1114 return false; // let the OS handle the click
1115 } else {
1116 return this->INHERITED::onDispatchClick(x, y, state);
1117 }
1118}
1119
reed@google.com52f57e12011-03-16 12:10:02 +00001120class GestureClick : public SkView::Click {
1121public:
1122 GestureClick(SkView* target) : SkView::Click(target) {
1123 this->setType(gGestureClickType);
1124 }
1125
1126 static bool IsGesture(Click* click) {
1127 return click->isType(gGestureClickType);
1128 }
1129};
1130
1131SkView::Click* SampleWindow::onFindClickHandler(SkScalar x, SkScalar y) {
1132 return new GestureClick(this);
1133}
1134
1135bool SampleWindow::onClick(Click* click) {
1136 if (GestureClick::IsGesture(click)) {
1137 float x = SkScalarToFloat(click->fCurr.fX);
1138 float y = SkScalarToFloat(click->fCurr.fY);
1139 switch (click->fState) {
1140 case SkView::Click::kDown_State:
1141 fGesture.touchBegin(click, x, y);
1142 break;
1143 case SkView::Click::kMoved_State:
1144 fGesture.touchMoved(click, x, y);
1145 this->inval(NULL);
1146 break;
1147 case SkView::Click::kUp_State:
1148 fGesture.touchEnd(click);
1149 this->inval(NULL);
1150 break;
1151 }
1152 return true;
1153 }
1154 return false;
1155}
1156
1157///////////////////////////////////////////////////////////////////////////////
1158
reed@android.com8a1c16f2008-12-17 15:59:43 +00001159void SampleWindow::loadView(SkView* view) {
1160 SkView::F2BIter iter(this);
1161 SkView* prev = iter.next();
1162 if (prev) {
1163 prev->detachFromParent();
1164 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001165
reed@android.com34245c72009-11-03 04:00:48 +00001166 if (NULL == view) {
1167 view = create_overview(fSamples.count(), fSamples.begin());
1168 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001169 view->setVisibleP(true);
reed@android.comf2b98d62010-12-20 18:26:13 +00001170 view->setClipToBounds(false);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001171 this->attachChildToFront(view)->unref();
1172 view->setSize(this->width(), this->height());
1173
1174 this->updateTitle();
1175}
1176
1177static const char* gConfigNames[] = {
1178 "unknown config",
1179 "A1",
1180 "A8",
1181 "Index8",
1182 "565",
1183 "4444",
1184 "8888"
1185};
1186
1187static const char* configToString(SkBitmap::Config c) {
1188 return gConfigNames[c];
1189}
1190
1191static const char* gCanvasTypePrefix[] = {
1192 "raster: ",
1193 "picture: ",
1194 "opengl: "
1195};
1196
reed@google.com569e0432011-04-05 13:07:03 +00001197static const char* trystate_str(SkTriState state,
1198 const char trueStr[], const char falseStr[]) {
1199 if (kTrue_SkTriState == state) {
1200 return trueStr;
1201 } else if (kFalse_SkTriState == state) {
1202 return falseStr;
1203 }
1204 return NULL;
1205}
1206
reed@android.com8a1c16f2008-12-17 15:59:43 +00001207void SampleWindow::updateTitle() {
1208 SkString title;
1209
1210 SkView::F2BIter iter(this);
1211 SkView* view = iter.next();
1212 SkEvent evt(gTitleEvtName);
1213 if (view->doQuery(&evt)) {
1214 title.set(evt.findString(gTitleEvtName));
1215 }
1216 if (title.size() == 0) {
1217 title.set("<unknown>");
1218 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001219
reed@android.com8a1c16f2008-12-17 15:59:43 +00001220 title.prepend(gCanvasTypePrefix[fCanvasType]);
1221
1222 title.prepend(" ");
1223 title.prepend(configToString(this->getBitmap().config()));
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001224
reed@android.com8a1c16f2008-12-17 15:59:43 +00001225 if (fAnimating) {
1226 title.prepend("<A> ");
1227 }
reed@android.com6c5f6f22009-08-14 16:08:38 +00001228 if (fScale) {
1229 title.prepend("<S> ");
1230 }
1231 if (fRotate) {
1232 title.prepend("<R> ");
1233 }
reed@android.come522ca52009-11-23 20:10:41 +00001234 if (fNClip) {
1235 title.prepend("<C> ");
1236 }
reed@google.com569e0432011-04-05 13:07:03 +00001237
1238 title.prepend(trystate_str(fLCDState, "LCD ", "lcd "));
1239 title.prepend(trystate_str(fAAState, "AA ", "aa "));
1240 title.prepend(fFlipAxis & kFlipAxis_X ? "X " : NULL);
1241 title.prepend(fFlipAxis & kFlipAxis_Y ? "Y " : NULL);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001242
1243 if (fZoomLevel) {
1244 title.prependf("{%d} ", fZoomLevel);
1245 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001246 this->setTitle(title.c_str());
1247}
1248
1249void SampleWindow::onSizeChange() {
1250 this->INHERITED::onSizeChange();
1251
1252 SkView::F2BIter iter(this);
1253 SkView* view = iter.next();
1254 view->setSize(this->width(), this->height());
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001255
reed@android.com8a1c16f2008-12-17 15:59:43 +00001256 // rebuild our clippath
1257 {
1258 const SkScalar W = this->width();
1259 const SkScalar H = this->height();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001260
reed@android.com8a1c16f2008-12-17 15:59:43 +00001261 fClipPath.reset();
1262#if 0
1263 for (SkScalar y = SK_Scalar1; y < H; y += SkIntToScalar(32)) {
1264 SkRect r;
1265 r.set(SK_Scalar1, y, SkIntToScalar(30), y + SkIntToScalar(30));
1266 for (; r.fLeft < W; r.offset(SkIntToScalar(32), 0))
1267 fClipPath.addRect(r);
1268 }
1269#else
1270 SkRect r;
1271 r.set(0, 0, W, H);
1272 fClipPath.addRect(r, SkPath::kCCW_Direction);
1273 r.set(W/4, H/4, W*3/4, H*3/4);
1274 fClipPath.addRect(r, SkPath::kCW_Direction);
1275#endif
1276 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001277
reed@android.com8a1c16f2008-12-17 15:59:43 +00001278 this->updateTitle(); // to refresh our config
1279}
1280
1281///////////////////////////////////////////////////////////////////////////////
1282
reed@android.comf2b98d62010-12-20 18:26:13 +00001283template <typename T> void SkTBSort(T array[], int count) {
1284 for (int i = 1; i < count - 1; i++) {
1285 bool didSwap = false;
1286 for (int j = count - 1; j > i; --j) {
1287 if (array[j] < array[j-1]) {
1288 T tmp(array[j-1]);
1289 array[j-1] = array[j];
1290 array[j] = tmp;
1291 didSwap = true;
1292 }
1293 }
1294 if (!didSwap) {
1295 break;
1296 }
1297 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001298
reed@android.comf2b98d62010-12-20 18:26:13 +00001299 for (int k = 0; k < count - 1; k++) {
1300 SkASSERT(!(array[k+1] < array[k]));
1301 }
1302}
1303
1304#include "SkRandom.h"
1305
1306static void rand_rect(SkIRect* rect, SkRandom& rand) {
1307 int bits = 8;
1308 int shift = 32 - bits;
1309 rect->set(rand.nextU() >> shift, rand.nextU() >> shift,
1310 rand.nextU() >> shift, rand.nextU() >> shift);
1311 rect->sort();
1312}
1313
1314static void dumpRect(const SkIRect& r) {
1315 SkDebugf(" { %d, %d, %d, %d },\n",
1316 r.fLeft, r.fTop,
1317 r.fRight, r.fBottom);
1318}
1319
1320static void test_rects(const SkIRect rect[], int count) {
1321 SkRegion rgn0, rgn1;
1322
1323 for (int i = 0; i < count; i++) {
1324 rgn0.op(rect[i], SkRegion::kUnion_Op);
1325 // dumpRect(rect[i]);
1326 }
1327 rgn1.setRects(rect, count);
1328
1329 if (rgn0 != rgn1) {
1330 SkDebugf("\n");
1331 for (int i = 0; i < count; i++) {
1332 dumpRect(rect[i]);
1333 }
1334 SkDebugf("\n");
1335 }
1336}
1337
1338static void test() {
1339 size_t i;
1340
1341 const SkIRect r0[] = {
1342 { 0, 0, 1, 1 },
1343 { 2, 2, 3, 3 },
1344 };
1345 const SkIRect r1[] = {
1346 { 0, 0, 1, 3 },
1347 { 1, 1, 2, 2 },
1348 { 2, 0, 3, 3 },
1349 };
1350 const SkIRect r2[] = {
1351 { 0, 0, 1, 2 },
1352 { 2, 1, 3, 3 },
1353 { 4, 0, 5, 1 },
1354 { 6, 0, 7, 4 },
1355 };
1356
1357 static const struct {
1358 const SkIRect* fRects;
1359 int fCount;
1360 } gRecs[] = {
1361 { r0, SK_ARRAY_COUNT(r0) },
1362 { r1, SK_ARRAY_COUNT(r1) },
1363 { r2, SK_ARRAY_COUNT(r2) },
1364 };
1365
1366 for (i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
1367 test_rects(gRecs[i].fRects, gRecs[i].fCount);
1368 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001369
reed@android.comf2b98d62010-12-20 18:26:13 +00001370 SkRandom rand;
1371 for (i = 0; i < 10000; i++) {
1372 SkRegion rgn0, rgn1;
1373
1374 const int N = 8;
1375 SkIRect rect[N];
1376 for (int j = 0; j < N; j++) {
1377 rand_rect(&rect[j], rand);
1378 }
1379 test_rects(rect, N);
1380 }
1381}
1382
reed@android.com8a1c16f2008-12-17 15:59:43 +00001383SkOSWindow* create_sk_window(void* hwnd) {
reed@android.comf2b98d62010-12-20 18:26:13 +00001384// test();
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001385 return new SampleWindow(hwnd);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001386}
1387
1388void get_preferred_size(int* x, int* y, int* width, int* height) {
1389 *x = 10;
1390 *y = 50;
1391 *width = 640;
1392 *height = 480;
1393}
1394
1395void application_init() {
1396// setenv("ANDROID_ROOT", "../../../data", 0);
reed@android.come191b162009-12-18 21:33:39 +00001397#ifdef SK_BUILD_FOR_MAC
reed@android.com8a1c16f2008-12-17 15:59:43 +00001398 setenv("ANDROID_ROOT", "/android/device/data", 0);
reed@android.come191b162009-12-18 21:33:39 +00001399#endif
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001400 SkGraphics::Init();
1401 SkEvent::Init();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001402}
1403
1404void application_term() {
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001405 SkEvent::Term();
1406 SkGraphics::Term();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001407}