blob: 5251604dd906c7e7d30ab6cb447ad9b3b13274bc [file] [log] [blame]
Scroggo2c8208f2011-06-15 16:49:08 +00001#include "SampleApp.h"
2
reed@google.com8a85d0c2011-06-24 19:12:12 +00003#include "SkData.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00004#include "SkCanvas.h"
5#include "SkDevice.h"
reed@google.comaf951c92011-06-16 19:10:39 +00006#include "SkGpuDevice.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00007#include "SkGraphics.h"
reed@android.comb08eb2b2009-01-06 20:16:26 +00008#include "SkImageEncoder.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00009#include "SkPaint.h"
10#include "SkPicture.h"
11#include "SkStream.h"
reed@android.com44177402009-11-23 21:07:51 +000012#include "SkTime.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkWindow.h"
14
15#include "SampleCode.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016#include "GrContext.h"
Scroggo0f185c22011-03-24 18:35:50 +000017#include "SkTypeface.h"
reed@android.comf2b98d62010-12-20 18:26:13 +000018
Scroggo3e7ff9f2011-06-16 15:31:26 +000019#include "GrGLInterface.h"
Scroggo2c8208f2011-06-15 16:49:08 +000020
Scroggo8ac0d542011-06-21 14:44:57 +000021#include "SkPDFDevice.h"
22#include "SkPDFDocument.h"
23#include "SkStream.h"
24
yangsu@google.com1f394212011-06-01 18:03:34 +000025#define TEST_GPIPEx
26
27#ifdef TEST_GPIPE
28#define PIPE_FILE
29#define FILE_PATH "/path/to/drawing.data"
30#endif
31
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000032#define USE_ARROWS_FOR_ZOOM true
reed@android.comf2b98d62010-12-20 18:26:13 +000033//#define DEFAULT_TO_GPU
34
reed@android.come191b162009-12-18 21:33:39 +000035extern SkView* create_overview(int, const SkViewFactory[]);
reed@android.com34245c72009-11-03 04:00:48 +000036
reed@android.comcb342352010-07-22 18:27:53 +000037#define SK_SUPPORT_GL
reed@android.com8a1c16f2008-12-17 15:59:43 +000038
39#define ANIMATING_EVENTTYPE "nextSample"
40#define ANIMATING_DELAY 750
41
mike@reedtribe.org2eb59522011-04-22 01:59:09 +000042#ifdef SK_DEBUG
reed@google.combad8c872011-05-18 20:10:31 +000043 #define FPS_REPEAT_MULTIPLIER 1
mike@reedtribe.org2eb59522011-04-22 01:59:09 +000044#else
reed@google.combad8c872011-05-18 20:10:31 +000045 #define FPS_REPEAT_MULTIPLIER 10
mike@reedtribe.org2eb59522011-04-22 01:59:09 +000046#endif
reed@google.combad8c872011-05-18 20:10:31 +000047#define FPS_REPEAT_COUNT (10 * FPS_REPEAT_MULTIPLIER)
mike@reedtribe.org2eb59522011-04-22 01:59:09 +000048
reed@google.comac10a2d2010-12-22 21:39:39 +000049#ifdef SK_SUPPORT_GL
50 #include "GrGLConfig.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000051#endif
52
reed@google.com3cec4d72011-07-06 13:59:47 +000053static SampleWindow* gSampleWindow;
54
mike@reedtribe.org2eb59522011-04-22 01:59:09 +000055///////////////
bsalomon@google.com098e96d2011-07-14 14:30:46 +000056class SampleWindow::DefaultDeviceManager : public SampleWindow::DeviceManager {
57public:
58
59 DefaultDeviceManager() {
60 fGrRenderTarget = NULL;
61 fGrContext = NULL;
62 }
63
64 virtual ~DefaultDeviceManager() {
65 SkSafeUnref(fGrRenderTarget);
66 SkSafeUnref(fGrContext);
67 }
68
69 virtual void init(SampleWindow* win) {
70 win->attachGL();
71 if (NULL == fGrContext) {
72 fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL);
73 }
74 if (NULL == fGrContext) {
75 SkDebugf("Failed to setup 3D");
76 win->detachGL();
77 }
78 }
79
80 virtual bool supportsDeviceType(SampleWindow::DeviceType dType) {
81 switch (dType) {
82 case kRaster_DeviceType:
83 case kPicture_DeviceType: // fallthru
84 return true;
85 case kGPU_DeviceType:
86 return NULL != fGrContext && NULL != fGrRenderTarget;
87 default:
88 return false;
89 }
90 }
91
92 virtual bool prepareCanvas(SampleWindow::DeviceType dType,
93 SkCanvas* canvas,
94 SampleWindow* win) {
95 if (kGPU_DeviceType == dType) {
96 if (fGrContext) {
97 canvas->setDevice(new SkGpuDevice(fGrContext,
98 fGrRenderTarget))->unref();
99 } else {
100 return false;
101 }
102 }
103 return true;
104 }
105
106 virtual void publishCanvas(SampleWindow::DeviceType dType,
107 SkCanvas* canvas,
108 SampleWindow* win) {
109 if (fGrContext) {
110 // in case we have queued drawing calls
111 fGrContext->flush();
112 if (dType != kGPU_DeviceType) {
113 // need to send the raster bits to the (gpu) window
114 fGrContext->setRenderTarget(fGrRenderTarget);
115 const SkBitmap& bm = win->getBitmap();
116 fGrContext->writePixels(0, 0, bm.width(), bm.height(),
117 kRGBA_8888_GrPixelConfig, bm.getPixels(),
118 bm.rowBytes());
119 }
120 }
121 win->presentGL();
122 }
123
124 virtual void windowSizeChanged(SampleWindow* win) {
125 if (fGrContext) {
126 win->attachGL();
127
128 GrPlatformSurfaceDesc desc;
129 desc.reset();
130 desc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
131 desc.fWidth = SkScalarRound(win->width());
132 desc.fHeight = SkScalarRound(win->height());
133 desc.fConfig = kRGBA_8888_GrPixelConfig;
134 desc.fStencilBits = 8;
135 GrGLint buffer;
136 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer);
137 desc.fPlatformRenderTarget = buffer;
138
139 SkSafeUnref(fGrRenderTarget);
140 fGrRenderTarget = static_cast<GrRenderTarget*>(
141 fGrContext->createPlatformSurface(desc));
142 }
143 }
144
145 virtual GrContext* getGrContext() {
146 return fGrContext;
147 }
148private:
149 GrContext* fGrContext;
150 GrRenderTarget* fGrRenderTarget;
151};
152
153///////////////
mike@reedtribe.org2eb59522011-04-22 01:59:09 +0000154static const char view_inval_msg[] = "view-inval-msg";
155
Scroggo62b65b02011-06-21 16:01:26 +0000156void SampleWindow::postInvalDelay() {
mike@reedtribe.org2eb59522011-04-22 01:59:09 +0000157 SkEvent* evt = new SkEvent(view_inval_msg);
Scroggo62b65b02011-06-21 16:01:26 +0000158 evt->post(this->getSinkID(), 1);
mike@reedtribe.org2eb59522011-04-22 01:59:09 +0000159}
160
161static bool isInvalEvent(const SkEvent& evt) {
162 return evt.isType(view_inval_msg);
163}
164//////////////////
165
reed@android.com8a1c16f2008-12-17 15:59:43 +0000166SkViewRegister* SkViewRegister::gHead;
167SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
168 static bool gOnce;
169 if (!gOnce) {
170 gHead = NULL;
171 gOnce = true;
172 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000173
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174 fChain = gHead;
175 gHead = this;
176}
177
reed@android.comf2b98d62010-12-20 18:26:13 +0000178#if defined(SK_SUPPORT_GL)
179 #define SK_USE_SHADERS
180#endif
181
reed@google.com29038ed2011-07-06 17:56:47 +0000182#if 0
reed@google.comf0b5f682011-03-11 20:08:25 +0000183#include <CoreFoundation/CoreFoundation.h>
184#include <CoreFoundation/CFURLAccess.h>
185
186static void testpdf() {
187 CFStringRef path = CFStringCreateWithCString(NULL, "/test.pdf",
188 kCFStringEncodingUTF8);
189 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path,
190 kCFURLPOSIXPathStyle,
191 false);
192 CFRelease(path);
193 CGRect box = CGRectMake(0, 0, 8*72, 10*72);
194 CGContextRef cg = CGPDFContextCreateWithURL(url, &box, NULL);
195 CFRelease(url);
196
197 CGContextBeginPage(cg, &box);
198 CGRect r = CGRectMake(10, 10, 40 + 0.5, 50 + 0.5);
199 CGContextFillEllipseInRect(cg, r);
200 CGContextEndPage(cg);
201 CGContextRelease(cg);
202
203 if (false) {
204 SkBitmap bm;
205 bm.setConfig(SkBitmap::kA8_Config, 64, 64);
206 bm.allocPixels();
207 bm.eraseColor(0);
208
209 SkCanvas canvas(bm);
210
211 }
212}
213#endif
214
215//////////////////////////////////////////////////////////////////////////////
216
reed@google.com569e0432011-04-05 13:07:03 +0000217enum FlipAxisEnum {
218 kFlipAxis_X = (1 << 0),
219 kFlipAxis_Y = (1 << 1)
220};
221
reed@google.com569e0432011-04-05 13:07:03 +0000222static SkTriState cycle_tristate(SkTriState state) {
223 static const SkTriState gCycle[] = {
224 /* kFalse_SkTriState -> */ kUnknown_SkTriState,
225 /* kTrue_SkTriState -> */ kFalse_SkTriState,
226 /* kUnknown_SkTriState -> */ kTrue_SkTriState,
227 };
228 return gCycle[state];
229}
230
reed@google.comf0b5f682011-03-11 20:08:25 +0000231#include "SkDrawFilter.h"
232
reed@google.com569e0432011-04-05 13:07:03 +0000233class FlagsDrawFilter : public SkDrawFilter {
reed@google.comf0b5f682011-03-11 20:08:25 +0000234public:
reed@google.com09e3baa2011-05-18 12:04:31 +0000235 FlagsDrawFilter(SkTriState lcd, SkTriState aa, SkTriState filter,
236 SkTriState hinting) :
237 fLCDState(lcd), fAAState(aa), fFilterState(filter), fHintingState(hinting) {}
reed@google.comf0b5f682011-03-11 20:08:25 +0000238
mike@reedtribe.org3ce59dc2011-04-08 00:38:05 +0000239 virtual void filter(SkPaint* paint, Type t) {
reed@google.com569e0432011-04-05 13:07:03 +0000240 if (kText_Type == t && kUnknown_SkTriState != fLCDState) {
reed@google.com569e0432011-04-05 13:07:03 +0000241 paint->setLCDRenderText(kTrue_SkTriState == fLCDState);
242 }
243 if (kUnknown_SkTriState != fAAState) {
reed@google.com569e0432011-04-05 13:07:03 +0000244 paint->setAntiAlias(kTrue_SkTriState == fAAState);
reed@google.comf0b5f682011-03-11 20:08:25 +0000245 }
reed@google.com176753a2011-05-17 15:32:04 +0000246 if (kUnknown_SkTriState != fFilterState) {
247 paint->setFilterBitmap(kTrue_SkTriState == fFilterState);
248 }
reed@google.com09e3baa2011-05-18 12:04:31 +0000249 if (kUnknown_SkTriState != fHintingState) {
250 paint->setHinting(kTrue_SkTriState == fHintingState ?
251 SkPaint::kNormal_Hinting :
252 SkPaint::kSlight_Hinting);
253 }
reed@google.comf0b5f682011-03-11 20:08:25 +0000254 }
255
256private:
reed@google.com569e0432011-04-05 13:07:03 +0000257 SkTriState fLCDState;
reed@google.com569e0432011-04-05 13:07:03 +0000258 SkTriState fAAState;
reed@google.com176753a2011-05-17 15:32:04 +0000259 SkTriState fFilterState;
reed@google.com09e3baa2011-05-18 12:04:31 +0000260 SkTriState fHintingState;
reed@google.comf0b5f682011-03-11 20:08:25 +0000261};
262
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263//////////////////////////////////////////////////////////////////////////////
264
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000265#define MAX_ZOOM_LEVEL 8
266#define MIN_ZOOM_LEVEL -8
267
reed@android.comf2b98d62010-12-20 18:26:13 +0000268static const char gCharEvtName[] = "SampleCode_Char_Event";
269static const char gKeyEvtName[] = "SampleCode_Key_Event";
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270static const char gTitleEvtName[] = "SampleCode_Title_Event";
271static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
reed@android.comf2b98d62010-12-20 18:26:13 +0000272static const char gFastTextEvtName[] = "SampleCode_FastText_Event";
273
274bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) {
275 if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) {
276 if (outUni) {
277 *outUni = evt.getFast32();
278 }
279 return true;
280 }
281 return false;
282}
283
284bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) {
285 if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) {
286 if (outKey) {
287 *outKey = (SkKey)evt.getFast32();
288 }
289 return true;
290 }
291 return false;
292}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000293
294bool SampleCode::TitleQ(const SkEvent& evt) {
295 return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
296}
297
298void SampleCode::TitleR(SkEvent* evt, const char title[]) {
299 SkASSERT(evt && TitleQ(*evt));
300 evt->setString(gTitleEvtName, title);
301}
302
303bool SampleCode::PrefSizeQ(const SkEvent& evt) {
304 return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1);
305}
306
307void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) {
308 SkASSERT(evt && PrefSizeQ(*evt));
309 SkScalar size[2];
310 size[0] = width;
311 size[1] = height;
312 evt->setScalars(gPrefSizeEvtName, 2, size);
313}
314
reed@android.comf2b98d62010-12-20 18:26:13 +0000315bool SampleCode::FastTextQ(const SkEvent& evt) {
316 return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1);
317}
318
319///////////////////////////////////////////////////////////////////////////////
320
reed@android.com44177402009-11-23 21:07:51 +0000321static SkMSec gAnimTime;
reed@android.comf2b98d62010-12-20 18:26:13 +0000322static SkMSec gAnimTimePrev;
323
reed@android.com44177402009-11-23 21:07:51 +0000324SkMSec SampleCode::GetAnimTime() { return gAnimTime; }
reed@android.comf2b98d62010-12-20 18:26:13 +0000325SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; }
326SkScalar SampleCode::GetAnimSecondsDelta() {
327 return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0);
328}
reed@android.com44177402009-11-23 21:07:51 +0000329
330SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000331 // since gAnimTime can be up to 32 bits, we can't convert it to a float
332 // or we'll lose the low bits. Hence we use doubles for the intermediate
333 // calculations
334 double seconds = (double)gAnimTime / 1000.0;
335 double value = SkScalarToDouble(speed) * seconds;
reed@android.com44177402009-11-23 21:07:51 +0000336 if (period) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000337 value = ::fmod(value, SkScalarToDouble(period));
reed@android.com44177402009-11-23 21:07:51 +0000338 }
reed@android.comf2b98d62010-12-20 18:26:13 +0000339 return SkDoubleToScalar(value);
reed@android.com44177402009-11-23 21:07:51 +0000340}
341
reed@google.com3cec4d72011-07-06 13:59:47 +0000342GrContext* SampleCode::GetGr() {
343 return gSampleWindow ? gSampleWindow->getGrContext() : NULL;
344}
345
reed@android.com8a1c16f2008-12-17 15:59:43 +0000346//////////////////////////////////////////////////////////////////////////////
347
reed@android.comf2b98d62010-12-20 18:26:13 +0000348static SkView* curr_view(SkWindow* wind) {
349 SkView::F2BIter iter(wind);
350 return iter.next();
351}
352
Scroggo2c8208f2011-06-15 16:49:08 +0000353void SampleWindow::setZoomCenter(float x, float y)
354{
355 fZoomCenterX = SkFloatToScalar(x);
356 fZoomCenterY = SkFloatToScalar(y);
357}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358
Scroggo0f185c22011-03-24 18:35:50 +0000359bool SampleWindow::zoomIn()
360{
361 // Arbitrarily decided
362 if (fFatBitsScale == 25) return false;
363 fFatBitsScale++;
364 this->inval(NULL);
365 return true;
366}
367
368bool SampleWindow::zoomOut()
369{
370 if (fFatBitsScale == 1) return false;
371 fFatBitsScale--;
372 this->inval(NULL);
373 return true;
374}
375
376void SampleWindow::toggleZoomer()
377{
378 fShowZoomer = !fShowZoomer;
379 this->inval(NULL);
380}
381
382void SampleWindow::updatePointer(int x, int y)
383{
384 fMouseX = x;
385 fMouseY = y;
386 if (fShowZoomer) {
387 this->inval(NULL);
388 }
389}
390
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000391static inline SampleWindow::DeviceType cycle_devicetype(SampleWindow::DeviceType ct) {
392 static const SampleWindow::DeviceType gCT[] = {
393 SampleWindow::kPicture_DeviceType,
394 SampleWindow::kGPU_DeviceType,
395 SampleWindow::kRaster_DeviceType
reed@android.com8a1c16f2008-12-17 15:59:43 +0000396 };
397 return gCT[ct];
398}
399
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000400SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* devManager) : INHERITED(hwnd) {
reed@google.com3cec4d72011-07-06 13:59:47 +0000401 gSampleWindow = this;
402
yangsu@google.com1f394212011-06-01 18:03:34 +0000403#ifdef PIPE_FILE
404 //Clear existing file or create file if it doesn't exist
405 FILE* f = fopen(FILE_PATH, "wb");
406 fclose(f);
407#endif
408
reed@android.com8a1c16f2008-12-17 15:59:43 +0000409 fPicture = NULL;
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000410
reed@android.comf2b98d62010-12-20 18:26:13 +0000411#ifdef DEFAULT_TO_GPU
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000412 fDeviceType = kGPU_DeviceType;
reed@android.comf2b98d62010-12-20 18:26:13 +0000413#else
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000414 fDeviceType = kRaster_DeviceType;
reed@android.comf2b98d62010-12-20 18:26:13 +0000415#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000416 fUseClip = false;
reed@android.come522ca52009-11-23 20:10:41 +0000417 fNClip = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 fRepeatDrawing = false;
419 fAnimating = false;
reed@android.com6c5f6f22009-08-14 16:08:38 +0000420 fRotate = false;
421 fScale = false;
reed@android.comf2b98d62010-12-20 18:26:13 +0000422 fRequestGrabImage = false;
reed@google.com0faac1e2011-05-11 05:58:58 +0000423 fUsePipe = false;
mike@reedtribe.org2eb59522011-04-22 01:59:09 +0000424 fMeasureFPS = false;
reed@google.com569e0432011-04-05 13:07:03 +0000425 fLCDState = kUnknown_SkTriState;
426 fAAState = kUnknown_SkTriState;
reed@google.com66f22fd2011-05-17 15:33:45 +0000427 fFilterState = kUnknown_SkTriState;
reed@google.com09e3baa2011-05-18 12:04:31 +0000428 fHintingState = kUnknown_SkTriState;
reed@google.com569e0432011-04-05 13:07:03 +0000429 fFlipAxis = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000430 fScrollTestX = fScrollTestY = 0;
431
Scroggo0f185c22011-03-24 18:35:50 +0000432 fMouseX = fMouseY = 0;
mike@reedtribe.org3ce59dc2011-04-08 00:38:05 +0000433 fFatBitsScale = 8;
Scroggo0f185c22011-03-24 18:35:50 +0000434 fTypeface = SkTypeface::CreateFromTypeface(NULL, SkTypeface::kBold);
435 fShowZoomer = false;
436
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000437 fZoomLevel = 0;
438 fZoomScale = SK_Scalar1;
439
Scroggo8ac0d542011-06-21 14:44:57 +0000440 fSaveToPdf = false;
441 fPdfCanvas = NULL;
442
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000443// this->setConfig(SkBitmap::kRGB_565_Config);
444 this->setConfig(SkBitmap::kARGB_8888_Config);
445 this->setVisibleP(true);
reed@android.comf2b98d62010-12-20 18:26:13 +0000446 this->setClipToBounds(false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000447
reed@android.com34245c72009-11-03 04:00:48 +0000448 {
449 const SkViewRegister* reg = SkViewRegister::Head();
450 while (reg) {
451 *fSamples.append() = reg->factory();
452 reg = reg->next();
453 }
454 }
455 fCurrIndex = 0;
senorblanco@chromium.org78b82532011-06-28 19:44:03 +0000456 if (argc > 1) {
457 int i, count = fSamples.count();
458 for (i = 0; i < count; i++) {
459 SkString title = getSampleTitle(i);
460 if (title.equals(argv[1])) {
461 fCurrIndex = i;
462 break;
463 }
464 }
465 if (i == count) {
466 fprintf(stderr, "Unknown sample \"%s\"\n", argv[1]);
467 }
468 }
reed@android.come0f13ee2009-11-04 19:40:25 +0000469 this->loadView(fSamples[fCurrIndex]());
bsalomon@google.com840e9f32011-07-06 21:59:09 +0000470
471 fPDFData = NULL;
reed@google.comf0b5f682011-03-11 20:08:25 +0000472
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000473 if (NULL == devManager) {
474 fDevManager = new DefaultDeviceManager();
475 } else {
476 devManager->ref();
477 fDevManager = devManager;
478 }
479 fDevManager->init(this);
480
Scroggob4490c72011-06-17 13:53:05 +0000481 // If another constructor set our dimensions, ensure that our
482 // onSizeChange gets called.
483 if (this->height() && this->width()) {
484 this->onSizeChange();
485 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000486}
487
488SampleWindow::~SampleWindow() {
489 delete fPicture;
Scroggo8ac0d542011-06-21 14:44:57 +0000490 delete fPdfCanvas;
Scroggo0f185c22011-03-24 18:35:50 +0000491 fTypeface->unref();
reed@google.com29038ed2011-07-06 17:56:47 +0000492
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000493 SkSafeUnref(fDevManager);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000494}
495
reed@android.com55e76b22009-11-23 21:46:47 +0000496static SkBitmap capture_bitmap(SkCanvas* canvas) {
497 SkBitmap bm;
498 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
499 src.copyTo(&bm, src.config());
500 return bm;
501}
502
503static bool bitmap_diff(SkCanvas* canvas, const SkBitmap& orig,
504 SkBitmap* diff) {
505 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000506
reed@android.com55e76b22009-11-23 21:46:47 +0000507 SkAutoLockPixels alp0(src);
508 SkAutoLockPixels alp1(orig);
509 for (int y = 0; y < src.height(); y++) {
510 const void* srcP = src.getAddr(0, y);
511 const void* origP = orig.getAddr(0, y);
512 size_t bytes = src.width() * src.bytesPerPixel();
513 if (memcmp(srcP, origP, bytes)) {
514 SkDebugf("---------- difference on line %d\n", y);
515 return true;
516 }
517 }
518 return false;
519}
520
Scroggo0f185c22011-03-24 18:35:50 +0000521static void drawText(SkCanvas* canvas, SkString string, SkScalar left, SkScalar top, SkPaint& paint)
522{
523 SkColor desiredColor = paint.getColor();
524 paint.setColor(SK_ColorWHITE);
525 const char* c_str = string.c_str();
526 size_t size = string.size();
527 SkRect bounds;
528 paint.measureText(c_str, size, &bounds);
529 bounds.offset(left, top);
530 SkScalar inset = SkIntToScalar(-2);
531 bounds.inset(inset, inset);
532 canvas->drawRect(bounds, paint);
533 if (desiredColor != SK_ColorBLACK) {
534 paint.setColor(SK_ColorBLACK);
535 canvas->drawText(c_str, size, left + SK_Scalar1, top + SK_Scalar1, paint);
536 }
537 paint.setColor(desiredColor);
538 canvas->drawText(c_str, size, left, top, paint);
539}
540
reed@android.com44177402009-11-23 21:07:51 +0000541#define XCLIP_N 8
542#define YCLIP_N 8
reed@android.come522ca52009-11-23 20:10:41 +0000543
544void SampleWindow::draw(SkCanvas* canvas) {
reed@google.com29038ed2011-07-06 17:56:47 +0000545
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000546 if (!fDevManager->prepareCanvas(fDeviceType, canvas, this)) {
547 return;
548 }
reed@android.com44177402009-11-23 21:07:51 +0000549 // update the animation time
reed@android.comf2b98d62010-12-20 18:26:13 +0000550 gAnimTimePrev = gAnimTime;
reed@android.com44177402009-11-23 21:07:51 +0000551 gAnimTime = SkTime::GetMSecs();
552
Scroggo2c8208f2011-06-15 16:49:08 +0000553 SkScalar cx = fZoomCenterX;
554 SkScalar cy = fZoomCenterY;
reed@google.com569e0432011-04-05 13:07:03 +0000555
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000556 if (fZoomLevel) {
557 SkMatrix m;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000558 SkPoint center;
559 m = canvas->getTotalMatrix();//.invert(&m);
560 m.mapXY(cx, cy, &center);
561 cx = center.fX;
562 cy = center.fY;
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000563
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000564 m.setTranslate(-cx, -cy);
565 m.postScale(fZoomScale, fZoomScale);
566 m.postTranslate(cx, cy);
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000567
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000568 canvas->concat(m);
569 }
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000570
reed@google.com569e0432011-04-05 13:07:03 +0000571 if (fFlipAxis) {
572 SkMatrix m;
573 m.setTranslate(cx, cy);
574 if (fFlipAxis & kFlipAxis_X) {
575 m.preScale(-SK_Scalar1, SK_Scalar1);
576 }
577 if (fFlipAxis & kFlipAxis_Y) {
578 m.preScale(SK_Scalar1, -SK_Scalar1);
579 }
580 m.preTranslate(-cx, -cy);
581 canvas->concat(m);
582 }
583
reed@google.com52f57e12011-03-16 12:10:02 +0000584 // Apply any gesture matrix
585 if (true) {
586 const SkMatrix& localM = fGesture.localM();
587 if (localM.getType() & SkMatrix::kScale_Mask) {
588 canvas->setExternalMatrix(&localM);
589 }
590 canvas->concat(localM);
591 canvas->concat(fGesture.globalM());
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000592
reed@google.com52f57e12011-03-16 12:10:02 +0000593 if (fGesture.isActive()) {
594 this->inval(NULL);
595 }
596 }
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000597
reed@android.come522ca52009-11-23 20:10:41 +0000598 if (fNClip) {
reed@android.com55e76b22009-11-23 21:46:47 +0000599 this->INHERITED::draw(canvas);
600 SkBitmap orig = capture_bitmap(canvas);
reed@android.come522ca52009-11-23 20:10:41 +0000601
602 const SkScalar w = this->width();
603 const SkScalar h = this->height();
604 const SkScalar cw = w / XCLIP_N;
605 const SkScalar ch = h / YCLIP_N;
606 for (int y = 0; y < YCLIP_N; y++) {
reed@android.com55e76b22009-11-23 21:46:47 +0000607 SkRect r;
608 r.fTop = y * ch;
609 r.fBottom = (y + 1) * ch;
610 if (y == YCLIP_N - 1) {
611 r.fBottom = h;
612 }
reed@android.come522ca52009-11-23 20:10:41 +0000613 for (int x = 0; x < XCLIP_N; x++) {
614 SkAutoCanvasRestore acr(canvas, true);
reed@android.com55e76b22009-11-23 21:46:47 +0000615 r.fLeft = x * cw;
616 r.fRight = (x + 1) * cw;
617 if (x == XCLIP_N - 1) {
618 r.fRight = w;
619 }
reed@android.come522ca52009-11-23 20:10:41 +0000620 canvas->clipRect(r);
621 this->INHERITED::draw(canvas);
622 }
623 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000624
reed@android.com55e76b22009-11-23 21:46:47 +0000625 SkBitmap diff;
626 if (bitmap_diff(canvas, orig, &diff)) {
627 }
reed@android.come522ca52009-11-23 20:10:41 +0000628 } else {
629 this->INHERITED::draw(canvas);
630 }
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000631 if (fShowZoomer && !fSaveToPdf) {
Scroggo3272ba82011-05-25 20:50:42 +0000632 showZoomer(canvas);
633 }
reed@google.com29038ed2011-07-06 17:56:47 +0000634
635 // do this last
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000636 fDevManager->publishCanvas(fDeviceType, canvas, this);
Scroggo3272ba82011-05-25 20:50:42 +0000637}
638
639void SampleWindow::showZoomer(SkCanvas* canvas) {
Scroggo0f185c22011-03-24 18:35:50 +0000640 int count = canvas->save();
641 canvas->resetMatrix();
642 // Ensure the mouse position is on screen.
reed@google.com261b8e22011-04-14 17:53:24 +0000643 int width = SkScalarRound(this->width());
644 int height = SkScalarRound(this->height());
Scroggo0f185c22011-03-24 18:35:50 +0000645 if (fMouseX >= width) fMouseX = width - 1;
646 else if (fMouseX < 0) fMouseX = 0;
647 if (fMouseY >= height) fMouseY = height - 1;
648 else if (fMouseY < 0) fMouseY = 0;
reed@google.comb36334d2011-05-18 15:07:20 +0000649
Scroggo0f185c22011-03-24 18:35:50 +0000650 SkBitmap bitmap = capture_bitmap(canvas);
reed@google.comb36334d2011-05-18 15:07:20 +0000651 bitmap.lockPixels();
652
Scroggo0f185c22011-03-24 18:35:50 +0000653 // 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 +0000654 int zoomedWidth = (width >> 1) | 1;
655 int zoomedHeight = (height >> 1) | 1;
Scroggo0f185c22011-03-24 18:35:50 +0000656 SkIRect src;
657 src.set(0, 0, zoomedWidth / fFatBitsScale, zoomedHeight / fFatBitsScale);
658 src.offset(fMouseX - (src.width()>>1), fMouseY - (src.height()>>1));
659 SkRect dest;
660 dest.set(0, 0, SkIntToScalar(zoomedWidth), SkIntToScalar(zoomedHeight));
661 dest.offset(SkIntToScalar(width - zoomedWidth), SkIntToScalar(height - zoomedHeight));
662 SkPaint paint;
663 // Clear the background behind our zoomed in view
664 paint.setColor(SK_ColorWHITE);
665 canvas->drawRect(dest, paint);
666 canvas->drawBitmapRect(bitmap, &src, dest);
667 paint.setColor(SK_ColorBLACK);
668 paint.setStyle(SkPaint::kStroke_Style);
669 // Draw a border around the pixel in the middle
670 SkRect originalPixel;
671 originalPixel.set(SkIntToScalar(fMouseX), SkIntToScalar(fMouseY), SkIntToScalar(fMouseX + 1), SkIntToScalar(fMouseY + 1));
672 SkMatrix matrix;
673 SkRect scalarSrc;
674 scalarSrc.set(src);
675 SkColor color = bitmap.getColor(fMouseX, fMouseY);
676 if (matrix.setRectToRect(scalarSrc, dest, SkMatrix::kFill_ScaleToFit)) {
677 SkRect pixel;
678 matrix.mapRect(&pixel, originalPixel);
679 // TODO Perhaps measure the values and make the outline white if it's "dark"
680 if (color == SK_ColorBLACK) {
681 paint.setColor(SK_ColorWHITE);
682 }
683 canvas->drawRect(pixel, paint);
684 }
685 paint.setColor(SK_ColorBLACK);
686 // Draw a border around the destination rectangle
687 canvas->drawRect(dest, paint);
688 paint.setStyle(SkPaint::kStrokeAndFill_Style);
689 // Identify the pixel and its color on screen
690 paint.setTypeface(fTypeface);
691 paint.setAntiAlias(true);
692 SkScalar lineHeight = paint.getFontMetrics(NULL);
693 SkString string;
694 string.appendf("(%i, %i)", fMouseX, fMouseY);
695 SkScalar left = dest.fLeft + SkIntToScalar(3);
696 SkScalar i = SK_Scalar1;
697 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
698 // Alpha
699 i += SK_Scalar1;
700 string.reset();
701 string.appendf("A: %X", SkColorGetA(color));
702 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
703 // Red
704 i += SK_Scalar1;
705 string.reset();
706 string.appendf("R: %X", SkColorGetR(color));
707 paint.setColor(SK_ColorRED);
708 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
709 // Green
710 i += SK_Scalar1;
711 string.reset();
712 string.appendf("G: %X", SkColorGetG(color));
713 paint.setColor(SK_ColorGREEN);
714 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
715 // Blue
716 i += SK_Scalar1;
717 string.reset();
718 string.appendf("B: %X", SkColorGetB(color));
719 paint.setColor(SK_ColorBLUE);
720 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
721 canvas->restoreToCount(count);
reed@android.come522ca52009-11-23 20:10:41 +0000722}
723
reed@android.com8a1c16f2008-12-17 15:59:43 +0000724void SampleWindow::onDraw(SkCanvas* canvas) {
725 if (fRepeatDrawing) {
726 this->inval(NULL);
727 }
728}
729
730#include "SkColorPriv.h"
731
732static void reverseRedAndBlue(const SkBitmap& bm) {
733 SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config);
734 uint8_t* p = (uint8_t*)bm.getPixels();
735 uint8_t* stop = p + bm.getSize();
736 while (p < stop) {
737 // swap red/blue (to go from ARGB(int) to RGBA(memory) and premultiply
738 unsigned scale = SkAlpha255To256(p[3]);
739 unsigned r = p[2];
740 unsigned b = p[0];
741 p[0] = SkAlphaMul(r, scale);
742 p[1] = SkAlphaMul(p[1], scale);
743 p[2] = SkAlphaMul(b, scale);
744 p += 4;
745 }
746}
747
Scroggo8ac0d542011-06-21 14:44:57 +0000748void SampleWindow::saveToPdf()
749{
750 fSaveToPdf = true;
751 this->inval(NULL);
752}
753
reed@android.com8a1c16f2008-12-17 15:59:43 +0000754SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
Scroggo8ac0d542011-06-21 14:44:57 +0000755 if (fSaveToPdf) {
756 const SkBitmap& bmp = canvas->getDevice()->accessBitmap(false);
757 SkISize size = SkISize::Make(bmp.width(), bmp.height());
758 SkPDFDevice* pdfDevice = new SkPDFDevice(size, size,
759 canvas->getTotalMatrix());
760 fPdfCanvas = new SkCanvas(pdfDevice);
761 pdfDevice->unref();
762 canvas = fPdfCanvas;
763 } else {
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000764 switch (fDeviceType) {
765 case kRaster_DeviceType:
766 case kGPU_DeviceType:
reed@android.comf2b98d62010-12-20 18:26:13 +0000767 canvas = this->INHERITED::beforeChildren(canvas);
Scroggo8ac0d542011-06-21 14:44:57 +0000768 break;
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000769 case kPicture_DeviceType:
Scroggo8ac0d542011-06-21 14:44:57 +0000770 fPicture = new SkPicture;
771 canvas = fPicture->beginRecording(9999, 9999);
772 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000773 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000774 }
775
776 if (fUseClip) {
777 canvas->drawColor(0xFFFF88FF);
778 canvas->clipPath(fClipPath);
779 }
780
781 return canvas;
782}
783
784static void paint_rgn(const SkBitmap& bm, const SkIRect& r,
785 const SkRegion& rgn) {
786 SkCanvas canvas(bm);
787 SkRegion inval(rgn);
788
789 inval.translate(r.fLeft, r.fTop);
790 canvas.clipRegion(inval);
791 canvas.drawColor(0xFFFF8080);
792}
yangsu@google.com501775e2011-06-24 16:04:50 +0000793#include "SkData.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +0000794void SampleWindow::afterChildren(SkCanvas* orig) {
Scroggo8ac0d542011-06-21 14:44:57 +0000795 if (fSaveToPdf) {
796 fSaveToPdf = false;
797 if (fShowZoomer) {
798 showZoomer(fPdfCanvas);
799 }
800 SkString name;
801 name.printf("%s.pdf", this->getTitle());
802 SkPDFDocument doc;
803 SkPDFDevice* device = static_cast<SkPDFDevice*>(fPdfCanvas->getDevice());
804 doc.appendPage(device);
805#ifdef ANDROID
806 name.prepend("/sdcard/");
807#endif
yangsu@google.com501775e2011-06-24 16:04:50 +0000808
809#ifdef SK_BUILD_FOR_IOS
810 SkDynamicMemoryWStream mstream;
811 doc.emitPDF(&mstream);
yangsu@google.comae8a2e52011-06-24 21:09:39 +0000812 fPDFData = mstream.copyToData();
yangsu@google.com501775e2011-06-24 16:04:50 +0000813#endif
Scroggo8ac0d542011-06-21 14:44:57 +0000814 SkFILEWStream stream(name.c_str());
815 if (stream.isValid()) {
816 doc.emitPDF(&stream);
817 const char* desc = "File saved from Skia SampleApp";
818 this->onPDFSaved(this->getTitle(), desc, name.c_str());
819 }
yangsu@google.com501775e2011-06-24 16:04:50 +0000820
Scroggo8ac0d542011-06-21 14:44:57 +0000821 delete fPdfCanvas;
822 fPdfCanvas = NULL;
823
824 // We took over the draw calls in order to create the PDF, so we need
825 // to redraw.
826 this->inval(NULL);
827 return;
828 }
829
reed@android.comf2b98d62010-12-20 18:26:13 +0000830 if (fRequestGrabImage) {
831 fRequestGrabImage = false;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000832
reed@google.com29038ed2011-07-06 17:56:47 +0000833 SkDevice* device = orig->getDevice();
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000834 SkBitmap bmp;
835 if (device->accessBitmap(false).copyTo(&bmp, SkBitmap::kARGB_8888_Config)) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000836 static int gSampleGrabCounter;
837 SkString name;
838 name.printf("sample_grab_%d", gSampleGrabCounter++);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000839 SkImageEncoder::EncodeFile(name.c_str(), bmp,
reed@android.comf2b98d62010-12-20 18:26:13 +0000840 SkImageEncoder::kPNG_Type, 100);
841 }
842 }
843
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000844 if (kPicture_DeviceType == fDeviceType) {
845 if (true) {
846 SkPicture* pict = new SkPicture(*fPicture);
847 fPicture->unref();
848 orig->drawPicture(*pict);
849 pict->unref();
850 } else if (true) {
851 SkDynamicMemoryWStream ostream;
852 fPicture->serialize(&ostream);
853 fPicture->unref();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000854
bsalomon@google.com098e96d2011-07-14 14:30:46 +0000855 SkAutoDataUnref data(ostream.copyToData());
856 SkMemoryStream istream(data.data(), data.size());
857 SkPicture pict(&istream);
858 orig->drawPicture(pict);
859 } else {
860 fPicture->draw(orig);
861 fPicture->unref();
862 }
863 fPicture = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000864 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000865
reed@google.com17d7aec2011-04-25 14:31:44 +0000866 // Do this after presentGL and other finishing, rather than in afterChild
867 if (fMeasureFPS && fMeasureFPS_Time) {
868 fMeasureFPS_Time = SkTime::GetMSecs() - fMeasureFPS_Time;
869 this->updateTitle();
Scroggo62b65b02011-06-21 16:01:26 +0000870 this->postInvalDelay();
reed@google.com17d7aec2011-04-25 14:31:44 +0000871 }
872
873 // if ((fScrollTestX | fScrollTestY) != 0)
reed@android.comf2b98d62010-12-20 18:26:13 +0000874 if (false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000875 const SkBitmap& bm = orig->getDevice()->accessBitmap(true);
876 int dx = fScrollTestX * 7;
877 int dy = fScrollTestY * 7;
878 SkIRect r;
879 SkRegion inval;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000880
reed@android.com8a1c16f2008-12-17 15:59:43 +0000881 r.set(50, 50, 50+100, 50+100);
882 bm.scrollRect(&r, dx, dy, &inval);
883 paint_rgn(bm, r, inval);
mike@reedtribe.org2eb59522011-04-22 01:59:09 +0000884 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000885}
886
reed@android.com6c5f6f22009-08-14 16:08:38 +0000887void SampleWindow::beforeChild(SkView* child, SkCanvas* canvas) {
888 if (fScale) {
889 SkScalar scale = SK_Scalar1 * 7 / 10;
890 SkScalar cx = this->width() / 2;
891 SkScalar cy = this->height() / 2;
892 canvas->translate(cx, cy);
893 canvas->scale(scale, scale);
894 canvas->translate(-cx, -cy);
895 }
896 if (fRotate) {
897 SkScalar cx = this->width() / 2;
898 SkScalar cy = this->height() / 2;
899 canvas->translate(cx, cy);
900 canvas->rotate(SkIntToScalar(30));
901 canvas->translate(-cx, -cy);
902 }
reed@google.comf0b5f682011-03-11 20:08:25 +0000903
reed@google.com09e3baa2011-05-18 12:04:31 +0000904 canvas->setDrawFilter(new FlagsDrawFilter(fLCDState, fAAState,
905 fFilterState, fHintingState))->unref();
mike@reedtribe.org2eb59522011-04-22 01:59:09 +0000906
mike@reedtribe.org2eb59522011-04-22 01:59:09 +0000907 if (fMeasureFPS) {
reed@google.comf2183392011-04-22 14:10:48 +0000908 fMeasureFPS_Time = 0; // 0 means the child is not aware of repeat-draw
909 if (SampleView::SetRepeatDraw(child, FPS_REPEAT_COUNT)) {
910 fMeasureFPS_Time = SkTime::GetMSecs();
911 }
912 } else {
913 (void)SampleView::SetRepeatDraw(child, 1);
mike@reedtribe.org2eb59522011-04-22 01:59:09 +0000914 }
reed@google.com0faac1e2011-05-11 05:58:58 +0000915 (void)SampleView::SetUsePipe(child, fUsePipe);
reed@android.com6c5f6f22009-08-14 16:08:38 +0000916}
917
918void SampleWindow::afterChild(SkView* child, SkCanvas* canvas) {
reed@google.comf0b5f682011-03-11 20:08:25 +0000919 canvas->setDrawFilter(NULL);
reed@android.com6c5f6f22009-08-14 16:08:38 +0000920}
921
reed@android.com8a1c16f2008-12-17 15:59:43 +0000922static SkBitmap::Config gConfigCycle[] = {
923 SkBitmap::kNo_Config, // none -> none
924 SkBitmap::kNo_Config, // a1 -> none
925 SkBitmap::kNo_Config, // a8 -> none
926 SkBitmap::kNo_Config, // index8 -> none
927 SkBitmap::kARGB_4444_Config, // 565 -> 4444
928 SkBitmap::kARGB_8888_Config, // 4444 -> 8888
929 SkBitmap::kRGB_565_Config // 8888 -> 565
930};
931
932static SkBitmap::Config cycle_configs(SkBitmap::Config c) {
933 return gConfigCycle[c];
934}
935
djsollen@google.come32b5832011-06-13 16:58:40 +0000936void SampleWindow::changeZoomLevel(float delta) {
937 fZoomLevel += SkFloatToScalar(delta);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000938 if (fZoomLevel > 0) {
djsollen@google.come32b5832011-06-13 16:58:40 +0000939 fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL);
940 fZoomScale = fZoomLevel + SK_Scalar1;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000941 } else if (fZoomLevel < 0) {
djsollen@google.come32b5832011-06-13 16:58:40 +0000942 fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL);
943 fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000944 } else {
945 fZoomScale = SK_Scalar1;
946 }
947
djsollen@google.come32b5832011-06-13 16:58:40 +0000948 this->updateTitle();
949
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000950 this->inval(NULL);
951}
952
Scroggo2c8208f2011-06-15 16:49:08 +0000953bool SampleWindow::previousSample() {
Scroggo62b65b02011-06-21 16:01:26 +0000954 fCurrIndex = (fCurrIndex - 1 + fSamples.count()) % fSamples.count();
Scroggo2c8208f2011-06-15 16:49:08 +0000955 this->loadView(fSamples[fCurrIndex]());
956 return true;
957}
958
reed@android.com8a1c16f2008-12-17 15:59:43 +0000959bool SampleWindow::nextSample() {
reed@android.com34245c72009-11-03 04:00:48 +0000960 fCurrIndex = (fCurrIndex + 1) % fSamples.count();
961 this->loadView(fSamples[fCurrIndex]());
962 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000963}
964
yangsu@google.com501775e2011-06-24 16:04:50 +0000965bool SampleWindow::goToSample(int i) {
966 fCurrIndex = (i) % fSamples.count();
967 this->loadView(fSamples[fCurrIndex]());
968 return true;
969}
970
971SkString SampleWindow::getSampleTitle(int i) {
972 SkView* view = fSamples[i]();
973 SkString title;
974 SkEvent evt(gTitleEvtName);
975 if (view->doQuery(&evt)) {
976 title.set(evt.findString(gTitleEvtName));
977 }
978 view->unref();
979 return title;
980}
981
982int SampleWindow::sampleCount() {
983 return fSamples.count();
984}
985
Scroggo2c8208f2011-06-15 16:49:08 +0000986void SampleWindow::postAnimatingEvent() {
987 if (fAnimating) {
988 SkEvent* evt = new SkEvent(ANIMATING_EVENTTYPE);
989 evt->post(this->getSinkID(), ANIMATING_DELAY);
990 }
991}
992
reed@android.com8a1c16f2008-12-17 15:59:43 +0000993bool SampleWindow::onEvent(const SkEvent& evt) {
994 if (evt.isType(ANIMATING_EVENTTYPE)) {
995 if (fAnimating) {
996 this->nextSample();
997 this->postAnimatingEvent();
998 }
999 return true;
1000 }
reed@android.com34245c72009-11-03 04:00:48 +00001001 if (evt.isType("set-curr-index")) {
1002 fCurrIndex = evt.getFast32() % fSamples.count();
1003 this->loadView(fSamples[fCurrIndex]());
1004 return true;
1005 }
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001006 if (isInvalEvent(evt)) {
1007 this->inval(NULL);
1008 return true;
1009 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001010 return this->INHERITED::onEvent(evt);
1011}
1012
reed@android.comf2b98d62010-12-20 18:26:13 +00001013bool SampleWindow::onQuery(SkEvent* query) {
1014 if (query->isType("get-slide-count")) {
1015 query->setFast32(fSamples.count());
1016 return true;
1017 }
1018 if (query->isType("get-slide-title")) {
1019 SkView* view = fSamples[query->getFast32()]();
1020 SkEvent evt(gTitleEvtName);
1021 if (view->doQuery(&evt)) {
1022 query->setString("title", evt.findString(gTitleEvtName));
1023 }
1024 SkSafeUnref(view);
1025 return true;
1026 }
1027 if (query->isType("use-fast-text")) {
1028 SkEvent evt(gFastTextEvtName);
1029 return curr_view(this)->doQuery(&evt);
1030 }
reed@google.com29038ed2011-07-06 17:56:47 +00001031 if (query->isType("ignore-window-bitmap")) {
1032 query->setFast32(this->getGrContext() != NULL);
1033 return true;
1034 }
reed@android.comf2b98d62010-12-20 18:26:13 +00001035 return this->INHERITED::onQuery(query);
1036}
1037
reed@android.com0ae6b242008-12-23 16:49:54 +00001038static void cleanup_for_filename(SkString* name) {
1039 char* str = name->writable_str();
reed@android.come191b162009-12-18 21:33:39 +00001040 for (size_t i = 0; i < name->size(); i++) {
reed@android.com0ae6b242008-12-23 16:49:54 +00001041 switch (str[i]) {
1042 case ':': str[i] = '-'; break;
1043 case '/': str[i] = '-'; break;
1044 case ' ': str[i] = '_'; break;
1045 default: break;
1046 }
1047 }
1048}
reed@android.com8a1c16f2008-12-17 15:59:43 +00001049
1050bool SampleWindow::onHandleChar(SkUnichar uni) {
reed@android.comf2b98d62010-12-20 18:26:13 +00001051 {
1052 SkView* view = curr_view(this);
1053 if (view) {
1054 SkEvent evt(gCharEvtName);
1055 evt.setFast32(uni);
1056 if (view->doQuery(&evt)) {
1057 return true;
1058 }
1059 }
1060 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001061
reed@android.com8a1c16f2008-12-17 15:59:43 +00001062 int dx = 0xFF;
1063 int dy = 0xFF;
1064
1065 switch (uni) {
1066 case '5': dx = 0; dy = 0; break;
1067 case '8': dx = 0; dy = -1; break;
1068 case '6': dx = 1; dy = 0; break;
1069 case '2': dx = 0; dy = 1; break;
1070 case '4': dx = -1; dy = 0; break;
1071 case '7': dx = -1; dy = -1; break;
1072 case '9': dx = 1; dy = -1; break;
1073 case '3': dx = 1; dy = 1; break;
1074 case '1': dx = -1; dy = 1; break;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001075
reed@android.com8a1c16f2008-12-17 15:59:43 +00001076 default:
1077 break;
1078 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001079
reed@android.com8a1c16f2008-12-17 15:59:43 +00001080 if (0xFF != dx && 0xFF != dy) {
1081 if ((dx | dy) == 0) {
1082 fScrollTestX = fScrollTestY = 0;
1083 } else {
1084 fScrollTestX += dx;
1085 fScrollTestY += dy;
1086 }
1087 this->inval(NULL);
1088 return true;
1089 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001090
reed@android.com0ae6b242008-12-23 16:49:54 +00001091 switch (uni) {
1092 case 'a':
Scroggo2c8208f2011-06-15 16:49:08 +00001093 this->toggleSlideshow();
reed@android.com0ae6b242008-12-23 16:49:54 +00001094 return true;
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001095 case 'b':
1096 fAAState = cycle_tristate(fAAState);
1097 this->updateTitle();
1098 this->inval(NULL);
1099 break;
1100 case 'c':
1101 fUseClip = !fUseClip;
1102 this->inval(NULL);
1103 this->updateTitle();
reed@android.com0ae6b242008-12-23 16:49:54 +00001104 return true;
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001105 case 'd':
1106 SkGraphics::SetFontCacheUsed(0);
1107 return true;
Scroggo8ac0d542011-06-21 14:44:57 +00001108 case 'e':
1109 this->saveToPdf();
1110 break;
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001111 case 'f':
Scroggo2c8208f2011-06-15 16:49:08 +00001112 this->toggleFPS();
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001113 break;
1114 case 'g':
1115 fRequestGrabImage = true;
1116 this->inval(NULL);
1117 break;
reed@google.com09e3baa2011-05-18 12:04:31 +00001118 case 'h':
1119 fHintingState = cycle_tristate(fHintingState);
1120 this->updateTitle();
1121 this->inval(NULL);
1122 break;
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001123 case 'i':
1124 this->zoomIn();
1125 break;
1126 case 'l':
1127 fLCDState = cycle_tristate(fLCDState);
1128 this->updateTitle();
1129 this->inval(NULL);
1130 break;
reed@google.com176753a2011-05-17 15:32:04 +00001131 case 'n':
1132 fFilterState = cycle_tristate(fFilterState);
1133 this->updateTitle();
1134 this->inval(NULL);
1135 break;
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001136 case 'o':
1137 this->zoomOut();
1138 break;
reed@google.com0faac1e2011-05-11 05:58:58 +00001139 case 'p':
1140 fUsePipe = !fUsePipe;
reed@google.coma6ff4dc2011-05-12 22:08:24 +00001141 this->updateTitle();
reed@google.com0faac1e2011-05-11 05:58:58 +00001142 this->inval(NULL);
1143 break;
reed@android.com6c5f6f22009-08-14 16:08:38 +00001144 case 'r':
1145 fRotate = !fRotate;
1146 this->inval(NULL);
1147 this->updateTitle();
1148 return true;
1149 case 's':
1150 fScale = !fScale;
1151 this->inval(NULL);
1152 this->updateTitle();
1153 return true;
reed@google.com569e0432011-04-05 13:07:03 +00001154 case 'x':
1155 fFlipAxis ^= kFlipAxis_X;
1156 this->updateTitle();
1157 this->inval(NULL);
1158 break;
1159 case 'y':
1160 fFlipAxis ^= kFlipAxis_Y;
1161 this->updateTitle();
1162 this->inval(NULL);
1163 break;
scroggo08526c02011-03-22 14:03:21 +00001164 case 'z':
1165 this->toggleZoomer();
1166 break;
reed@android.com0ae6b242008-12-23 16:49:54 +00001167 default:
1168 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001169 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001170
reed@android.com8a1c16f2008-12-17 15:59:43 +00001171 return this->INHERITED::onHandleChar(uni);
1172}
1173
Scroggo2c8208f2011-06-15 16:49:08 +00001174void SampleWindow::toggleFPS() {
1175 fMeasureFPS = !fMeasureFPS;
1176 this->inval(NULL);
1177 this->updateTitle();
1178}
1179
1180void SampleWindow::toggleSlideshow() {
1181 fAnimating = !fAnimating;
1182 this->postAnimatingEvent();
1183 this->updateTitle();
1184}
1185
1186void SampleWindow::toggleRendering() {
bsalomon@google.com098e96d2011-07-14 14:30:46 +00001187 DeviceType origDevType = fDeviceType;
1188 do {
1189 fDeviceType = cycle_devicetype(fDeviceType);
1190 } while (origDevType != fDeviceType &&
1191 !fDevManager->supportsDeviceType(fDeviceType));
Scroggo2c8208f2011-06-15 16:49:08 +00001192 this->updateTitle();
1193 this->inval(NULL);
1194}
1195
reed@android.com8a1c16f2008-12-17 15:59:43 +00001196#include "SkDumpCanvas.h"
1197
1198bool SampleWindow::onHandleKey(SkKey key) {
reed@android.comf2b98d62010-12-20 18:26:13 +00001199 {
1200 SkView* view = curr_view(this);
1201 if (view) {
1202 SkEvent evt(gKeyEvtName);
1203 evt.setFast32(key);
1204 if (view->doQuery(&evt)) {
1205 return true;
1206 }
1207 }
1208 }
1209
reed@android.com8a1c16f2008-12-17 15:59:43 +00001210 switch (key) {
1211 case kRight_SkKey:
1212 if (this->nextSample()) {
1213 return true;
1214 }
1215 break;
1216 case kLeft_SkKey:
Scroggo2c8208f2011-06-15 16:49:08 +00001217 toggleRendering();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001218 return true;
1219 case kUp_SkKey:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001220 if (USE_ARROWS_FOR_ZOOM) {
djsollen@google.come32b5832011-06-13 16:58:40 +00001221 this->changeZoomLevel(1.f);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001222 } else {
1223 fNClip = !fNClip;
1224 this->inval(NULL);
djsollen@google.come32b5832011-06-13 16:58:40 +00001225 this->updateTitle();
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001226 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001227 return true;
1228 case kDown_SkKey:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001229 if (USE_ARROWS_FOR_ZOOM) {
djsollen@google.come32b5832011-06-13 16:58:40 +00001230 this->changeZoomLevel(-1.f);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001231 } else {
1232 this->setConfig(cycle_configs(this->getBitmap().config()));
djsollen@google.come32b5832011-06-13 16:58:40 +00001233 this->updateTitle();
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001234 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001235 return true;
1236 case kOK_SkKey:
reed@android.comf2b98d62010-12-20 18:26:13 +00001237 if (false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001238 SkDebugfDumper dumper;
1239 SkDumpCanvas dc(&dumper);
1240 this->draw(&dc);
1241 } else {
1242 fRepeatDrawing = !fRepeatDrawing;
1243 if (fRepeatDrawing) {
1244 this->inval(NULL);
1245 }
1246 }
1247 return true;
reed@android.com34245c72009-11-03 04:00:48 +00001248 case kBack_SkKey:
1249 this->loadView(NULL);
1250 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001251 default:
1252 break;
1253 }
1254 return this->INHERITED::onHandleKey(key);
1255}
1256
reed@google.com52f57e12011-03-16 12:10:02 +00001257///////////////////////////////////////////////////////////////////////////////
1258
1259static const char gGestureClickType[] = "GestureClickType";
1260
Scroggod3aed392011-06-22 13:26:56 +00001261bool SampleWindow::onDispatchClick(int x, int y, Click::State state,
1262 void* owner) {
Scroggo0f185c22011-03-24 18:35:50 +00001263 if (Click::kMoved_State == state) {
1264 updatePointer(x, y);
1265 }
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001266 int w = SkScalarRound(this->width());
1267 int h = SkScalarRound(this->height());
1268
1269 // check for the resize-box
1270 if (w - x < 16 && h - y < 16) {
1271 return false; // let the OS handle the click
1272 } else {
Scroggod3aed392011-06-22 13:26:56 +00001273 return this->INHERITED::onDispatchClick(x, y, state, owner);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001274 }
1275}
1276
reed@google.com52f57e12011-03-16 12:10:02 +00001277class GestureClick : public SkView::Click {
1278public:
1279 GestureClick(SkView* target) : SkView::Click(target) {
1280 this->setType(gGestureClickType);
1281 }
1282
1283 static bool IsGesture(Click* click) {
1284 return click->isType(gGestureClickType);
1285 }
1286};
1287
1288SkView::Click* SampleWindow::onFindClickHandler(SkScalar x, SkScalar y) {
1289 return new GestureClick(this);
1290}
1291
1292bool SampleWindow::onClick(Click* click) {
1293 if (GestureClick::IsGesture(click)) {
1294 float x = SkScalarToFloat(click->fCurr.fX);
1295 float y = SkScalarToFloat(click->fCurr.fY);
1296 switch (click->fState) {
1297 case SkView::Click::kDown_State:
Scroggod3aed392011-06-22 13:26:56 +00001298 fGesture.touchBegin(click->fOwner, x, y);
reed@google.com52f57e12011-03-16 12:10:02 +00001299 break;
1300 case SkView::Click::kMoved_State:
Scroggod3aed392011-06-22 13:26:56 +00001301 fGesture.touchMoved(click->fOwner, x, y);
reed@google.com52f57e12011-03-16 12:10:02 +00001302 this->inval(NULL);
1303 break;
1304 case SkView::Click::kUp_State:
Scroggod3aed392011-06-22 13:26:56 +00001305 fGesture.touchEnd(click->fOwner);
reed@google.com52f57e12011-03-16 12:10:02 +00001306 this->inval(NULL);
1307 break;
1308 }
1309 return true;
1310 }
1311 return false;
1312}
1313
1314///////////////////////////////////////////////////////////////////////////////
1315
reed@android.com8a1c16f2008-12-17 15:59:43 +00001316void SampleWindow::loadView(SkView* view) {
1317 SkView::F2BIter iter(this);
1318 SkView* prev = iter.next();
1319 if (prev) {
1320 prev->detachFromParent();
1321 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001322
reed@android.com34245c72009-11-03 04:00:48 +00001323 if (NULL == view) {
1324 view = create_overview(fSamples.count(), fSamples.begin());
1325 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001326 view->setVisibleP(true);
reed@android.comf2b98d62010-12-20 18:26:13 +00001327 view->setClipToBounds(false);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001328 this->attachChildToFront(view)->unref();
1329 view->setSize(this->width(), this->height());
1330
1331 this->updateTitle();
1332}
1333
1334static const char* gConfigNames[] = {
1335 "unknown config",
1336 "A1",
1337 "A8",
1338 "Index8",
1339 "565",
1340 "4444",
1341 "8888"
1342};
1343
1344static const char* configToString(SkBitmap::Config c) {
1345 return gConfigNames[c];
1346}
1347
bsalomon@google.com098e96d2011-07-14 14:30:46 +00001348static const char* gDeviceTypePrefix[] = {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001349 "raster: ",
1350 "picture: ",
1351 "opengl: "
1352};
1353
reed@google.com569e0432011-04-05 13:07:03 +00001354static const char* trystate_str(SkTriState state,
1355 const char trueStr[], const char falseStr[]) {
1356 if (kTrue_SkTriState == state) {
1357 return trueStr;
1358 } else if (kFalse_SkTriState == state) {
1359 return falseStr;
1360 }
1361 return NULL;
1362}
1363
reed@android.com8a1c16f2008-12-17 15:59:43 +00001364void SampleWindow::updateTitle() {
1365 SkString title;
1366
1367 SkView::F2BIter iter(this);
1368 SkView* view = iter.next();
1369 SkEvent evt(gTitleEvtName);
1370 if (view->doQuery(&evt)) {
1371 title.set(evt.findString(gTitleEvtName));
1372 }
1373 if (title.size() == 0) {
1374 title.set("<unknown>");
1375 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001376
bsalomon@google.com098e96d2011-07-14 14:30:46 +00001377 title.prepend(gDeviceTypePrefix[fDeviceType]);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001378
1379 title.prepend(" ");
1380 title.prepend(configToString(this->getBitmap().config()));
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001381
reed@android.com8a1c16f2008-12-17 15:59:43 +00001382 if (fAnimating) {
1383 title.prepend("<A> ");
1384 }
reed@android.com6c5f6f22009-08-14 16:08:38 +00001385 if (fScale) {
1386 title.prepend("<S> ");
1387 }
1388 if (fRotate) {
1389 title.prepend("<R> ");
1390 }
reed@android.come522ca52009-11-23 20:10:41 +00001391 if (fNClip) {
1392 title.prepend("<C> ");
1393 }
reed@google.com569e0432011-04-05 13:07:03 +00001394
1395 title.prepend(trystate_str(fLCDState, "LCD ", "lcd "));
1396 title.prepend(trystate_str(fAAState, "AA ", "aa "));
reed@google.com09e3baa2011-05-18 12:04:31 +00001397 title.prepend(trystate_str(fFilterState, "H ", "h "));
reed@google.com569e0432011-04-05 13:07:03 +00001398 title.prepend(fFlipAxis & kFlipAxis_X ? "X " : NULL);
1399 title.prepend(fFlipAxis & kFlipAxis_Y ? "Y " : NULL);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001400
1401 if (fZoomLevel) {
djsollen@google.come32b5832011-06-13 16:58:40 +00001402 title.prependf("{%.2f} ", SkScalarToFloat(fZoomLevel));
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +00001403 }
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001404
1405 if (fMeasureFPS) {
reed@google.combad8c872011-05-18 20:10:31 +00001406 title.appendf(" %6.1f ms", fMeasureFPS_Time / (float)FPS_REPEAT_MULTIPLIER);
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001407 }
reed@google.coma6ff4dc2011-05-12 22:08:24 +00001408 if (fUsePipe && SampleView::IsSampleView(view)) {
1409 title.prepend("<P> ");
1410 }
1411 if (SampleView::IsSampleView(view)) {
1412 title.prepend("! ");
1413 }
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001414
reed@android.com8a1c16f2008-12-17 15:59:43 +00001415 this->setTitle(title.c_str());
1416}
1417
1418void SampleWindow::onSizeChange() {
1419 this->INHERITED::onSizeChange();
reed@google.com29038ed2011-07-06 17:56:47 +00001420
reed@android.com8a1c16f2008-12-17 15:59:43 +00001421 SkView::F2BIter iter(this);
1422 SkView* view = iter.next();
1423 view->setSize(this->width(), this->height());
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001424
reed@android.com8a1c16f2008-12-17 15:59:43 +00001425 // rebuild our clippath
1426 {
1427 const SkScalar W = this->width();
1428 const SkScalar H = this->height();
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001429
reed@android.com8a1c16f2008-12-17 15:59:43 +00001430 fClipPath.reset();
1431#if 0
1432 for (SkScalar y = SK_Scalar1; y < H; y += SkIntToScalar(32)) {
1433 SkRect r;
1434 r.set(SK_Scalar1, y, SkIntToScalar(30), y + SkIntToScalar(30));
1435 for (; r.fLeft < W; r.offset(SkIntToScalar(32), 0))
1436 fClipPath.addRect(r);
1437 }
1438#else
1439 SkRect r;
1440 r.set(0, 0, W, H);
1441 fClipPath.addRect(r, SkPath::kCCW_Direction);
1442 r.set(W/4, H/4, W*3/4, H*3/4);
1443 fClipPath.addRect(r, SkPath::kCW_Direction);
1444#endif
1445 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001446
Scroggo2c8208f2011-06-15 16:49:08 +00001447 fZoomCenterX = SkScalarHalf(this->width());
1448 fZoomCenterY = SkScalarHalf(this->height());
1449
Scroggo3e7ff9f2011-06-16 15:31:26 +00001450#ifdef ANDROID
Scroggob4490c72011-06-17 13:53:05 +00001451 // FIXME: The first draw after a size change does not work on Android, so
1452 // we post an invalidate.
Scroggo62b65b02011-06-21 16:01:26 +00001453 this->postInvalDelay();
Scroggo716a0382011-06-16 14:00:15 +00001454#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +00001455 this->updateTitle(); // to refresh our config
bsalomon@google.com098e96d2011-07-14 14:30:46 +00001456 fDevManager->windowSizeChanged(this);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001457}
1458
1459///////////////////////////////////////////////////////////////////////////////
1460
reed@google.coma6ff4dc2011-05-12 22:08:24 +00001461static const char is_sample_view_tag[] = "sample-is-sample-view";
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001462static const char repeat_count_tag[] = "sample-set-repeat-count";
reed@google.com0faac1e2011-05-11 05:58:58 +00001463static const char set_use_pipe_tag[] = "sample-set-use-pipe";
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001464
reed@google.coma6ff4dc2011-05-12 22:08:24 +00001465bool SampleView::IsSampleView(SkView* view) {
1466 SkEvent evt(is_sample_view_tag);
1467 return view->doQuery(&evt);
1468}
1469
reed@google.comf2183392011-04-22 14:10:48 +00001470bool SampleView::SetRepeatDraw(SkView* view, int count) {
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001471 SkEvent evt(repeat_count_tag);
1472 evt.setFast32(count);
reed@google.comf2183392011-04-22 14:10:48 +00001473 return view->doEvent(evt);
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001474}
1475
reed@google.com0faac1e2011-05-11 05:58:58 +00001476bool SampleView::SetUsePipe(SkView* view, bool pred) {
1477 SkEvent evt(set_use_pipe_tag);
1478 evt.setFast32(pred);
1479 return view->doEvent(evt);
1480}
1481
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001482bool SampleView::onEvent(const SkEvent& evt) {
1483 if (evt.isType(repeat_count_tag)) {
1484 fRepeatCount = evt.getFast32();
1485 return true;
1486 }
reed@google.com0faac1e2011-05-11 05:58:58 +00001487 if (evt.isType(set_use_pipe_tag)) {
1488 fUsePipe = !!evt.getFast32();
1489 return true;
1490 }
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001491 return this->INHERITED::onEvent(evt);
1492}
1493
1494bool SampleView::onQuery(SkEvent* evt) {
reed@google.coma6ff4dc2011-05-12 22:08:24 +00001495 if (evt->isType(is_sample_view_tag)) {
1496 return true;
1497 }
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001498 return this->INHERITED::onQuery(evt);
1499}
1500
reed@google.com68f456d2011-05-02 18:55:39 +00001501#ifdef TEST_GPIPE
1502 #include "SkGPipe.h"
reed@google.com64e3eb22011-05-04 14:32:04 +00001503
1504class SimplePC : public SkGPipeController {
1505public:
1506 SimplePC(SkCanvas* target);
1507 ~SimplePC();
1508
1509 virtual void* requestBlock(size_t minRequest, size_t* actual);
1510 virtual void notifyWritten(size_t bytes);
1511
1512private:
reed@google.com961ddb02011-05-05 14:03:48 +00001513 SkGPipeReader fReader;
1514 void* fBlock;
1515 size_t fBlockSize;
1516 size_t fBytesWritten;
1517 int fAtomsWritten;
reed@google.com64e3eb22011-05-04 14:32:04 +00001518 SkGPipeReader::Status fStatus;
1519
1520 size_t fTotalWritten;
1521};
1522
1523SimplePC::SimplePC(SkCanvas* target) : fReader(target) {
1524 fBlock = NULL;
1525 fBlockSize = fBytesWritten = 0;
1526 fStatus = SkGPipeReader::kDone_Status;
1527 fTotalWritten = 0;
reed@google.com961ddb02011-05-05 14:03:48 +00001528 fAtomsWritten = 0;
reed@google.com64e3eb22011-05-04 14:32:04 +00001529}
1530
1531SimplePC::~SimplePC() {
1532// SkASSERT(SkGPipeReader::kDone_Status == fStatus);
1533 sk_free(fBlock);
1534
reed@google.com0faac1e2011-05-11 05:58:58 +00001535 if (fTotalWritten) {
1536 SkDebugf("--- %d bytes %d atoms, status %d\n", fTotalWritten,
1537 fAtomsWritten, fStatus);
1538 }
reed@google.com64e3eb22011-05-04 14:32:04 +00001539}
1540
1541void* SimplePC::requestBlock(size_t minRequest, size_t* actual) {
1542 sk_free(fBlock);
1543
1544 fBlockSize = minRequest * 4;
1545 fBlock = sk_malloc_throw(fBlockSize);
1546 fBytesWritten = 0;
1547 *actual = fBlockSize;
1548 return fBlock;
1549}
1550
1551void SimplePC::notifyWritten(size_t bytes) {
1552 SkASSERT(fBytesWritten + bytes <= fBlockSize);
yangsu@google.com1f394212011-06-01 18:03:34 +00001553
1554#ifdef PIPE_FILE
1555 //File is open in append mode
1556 FILE* f = fopen(FILE_PATH, "ab");
1557 SkASSERT(f != NULL);
1558 fwrite((const char*)fBlock + fBytesWritten, 1, bytes, f);
1559 fclose(f);
1560#endif
1561
reed@google.com64e3eb22011-05-04 14:32:04 +00001562 fStatus = fReader.playback((const char*)fBlock + fBytesWritten, bytes);
1563 SkASSERT(SkGPipeReader::kError_Status != fStatus);
1564 fBytesWritten += bytes;
1565 fTotalWritten += bytes;
reed@google.com961ddb02011-05-05 14:03:48 +00001566
1567 fAtomsWritten += 1;
reed@google.com64e3eb22011-05-04 14:32:04 +00001568}
1569
reed@google.com68f456d2011-05-02 18:55:39 +00001570#endif
reed@google.com2f3dc9d2011-05-02 17:33:45 +00001571
reed@google.com64e3eb22011-05-04 14:32:04 +00001572
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001573void SampleView::onDraw(SkCanvas* canvas) {
reed@google.com2f3dc9d2011-05-02 17:33:45 +00001574#ifdef TEST_GPIPE
reed@google.com64e3eb22011-05-04 14:32:04 +00001575 SimplePC controller(canvas);
reed@google.com2f3dc9d2011-05-02 17:33:45 +00001576 SkGPipeWriter writer;
reed@google.com0faac1e2011-05-11 05:58:58 +00001577 if (fUsePipe) {
reed@google.comdde09562011-05-23 12:21:05 +00001578 uint32_t flags = SkGPipeWriter::kCrossProcess_Flag;
1579// flags = 0;
1580 canvas = writer.startRecording(&controller, flags);
reed@google.com0faac1e2011-05-11 05:58:58 +00001581 }
reed@google.com2f3dc9d2011-05-02 17:33:45 +00001582#endif
1583
reed@google.com81e3d7f2011-06-01 12:42:36 +00001584 this->onDrawBackground(canvas);
1585
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001586 for (int i = 0; i < fRepeatCount; i++) {
1587 SkAutoCanvasRestore acr(canvas, true);
1588 this->onDrawContent(canvas);
1589 }
1590}
1591
1592void SampleView::onDrawBackground(SkCanvas* canvas) {
reed@google.comf2183392011-04-22 14:10:48 +00001593 canvas->drawColor(fBGColor);
mike@reedtribe.org2eb59522011-04-22 01:59:09 +00001594}
1595
1596///////////////////////////////////////////////////////////////////////////////
1597
reed@android.comf2b98d62010-12-20 18:26:13 +00001598template <typename T> void SkTBSort(T array[], int count) {
1599 for (int i = 1; i < count - 1; i++) {
1600 bool didSwap = false;
1601 for (int j = count - 1; j > i; --j) {
1602 if (array[j] < array[j-1]) {
1603 T tmp(array[j-1]);
1604 array[j-1] = array[j];
1605 array[j] = tmp;
1606 didSwap = true;
1607 }
1608 }
1609 if (!didSwap) {
1610 break;
1611 }
1612 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001613
reed@android.comf2b98d62010-12-20 18:26:13 +00001614 for (int k = 0; k < count - 1; k++) {
1615 SkASSERT(!(array[k+1] < array[k]));
1616 }
1617}
1618
1619#include "SkRandom.h"
1620
1621static void rand_rect(SkIRect* rect, SkRandom& rand) {
1622 int bits = 8;
1623 int shift = 32 - bits;
1624 rect->set(rand.nextU() >> shift, rand.nextU() >> shift,
1625 rand.nextU() >> shift, rand.nextU() >> shift);
1626 rect->sort();
1627}
1628
1629static void dumpRect(const SkIRect& r) {
1630 SkDebugf(" { %d, %d, %d, %d },\n",
1631 r.fLeft, r.fTop,
1632 r.fRight, r.fBottom);
1633}
1634
1635static void test_rects(const SkIRect rect[], int count) {
1636 SkRegion rgn0, rgn1;
1637
1638 for (int i = 0; i < count; i++) {
1639 rgn0.op(rect[i], SkRegion::kUnion_Op);
1640 // dumpRect(rect[i]);
1641 }
1642 rgn1.setRects(rect, count);
1643
1644 if (rgn0 != rgn1) {
1645 SkDebugf("\n");
1646 for (int i = 0; i < count; i++) {
1647 dumpRect(rect[i]);
1648 }
1649 SkDebugf("\n");
1650 }
1651}
1652
1653static void test() {
1654 size_t i;
1655
1656 const SkIRect r0[] = {
1657 { 0, 0, 1, 1 },
1658 { 2, 2, 3, 3 },
1659 };
1660 const SkIRect r1[] = {
1661 { 0, 0, 1, 3 },
1662 { 1, 1, 2, 2 },
1663 { 2, 0, 3, 3 },
1664 };
1665 const SkIRect r2[] = {
1666 { 0, 0, 1, 2 },
1667 { 2, 1, 3, 3 },
1668 { 4, 0, 5, 1 },
1669 { 6, 0, 7, 4 },
1670 };
1671
1672 static const struct {
1673 const SkIRect* fRects;
1674 int fCount;
1675 } gRecs[] = {
1676 { r0, SK_ARRAY_COUNT(r0) },
1677 { r1, SK_ARRAY_COUNT(r1) },
1678 { r2, SK_ARRAY_COUNT(r2) },
1679 };
1680
1681 for (i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
1682 test_rects(gRecs[i].fRects, gRecs[i].fCount);
1683 }
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001684
reed@android.comf2b98d62010-12-20 18:26:13 +00001685 SkRandom rand;
1686 for (i = 0; i < 10000; i++) {
1687 SkRegion rgn0, rgn1;
1688
1689 const int N = 8;
1690 SkIRect rect[N];
1691 for (int j = 0; j < N; j++) {
1692 rand_rect(&rect[j], rand);
1693 }
1694 test_rects(rect, N);
1695 }
1696}
1697
senorblanco@chromium.org78b82532011-06-28 19:44:03 +00001698SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
reed@android.comf2b98d62010-12-20 18:26:13 +00001699// test();
bsalomon@google.com098e96d2011-07-14 14:30:46 +00001700 return new SampleWindow(hwnd, argc, argv, NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001701}
1702
1703void get_preferred_size(int* x, int* y, int* width, int* height) {
1704 *x = 10;
1705 *y = 50;
1706 *width = 640;
1707 *height = 480;
1708}
1709
1710void application_init() {
1711// setenv("ANDROID_ROOT", "../../../data", 0);
reed@android.come191b162009-12-18 21:33:39 +00001712#ifdef SK_BUILD_FOR_MAC
reed@android.com8a1c16f2008-12-17 15:59:43 +00001713 setenv("ANDROID_ROOT", "/android/device/data", 0);
reed@android.come191b162009-12-18 21:33:39 +00001714#endif
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001715 SkGraphics::Init();
1716 SkEvent::Init();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001717}
1718
1719void application_term() {
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001720 SkEvent::Term();
1721 SkGraphics::Term();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001722}