1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 #include "SampleApp.h"
8
9 #include "SkData.h"
10 #include "SkCanvas.h"
11 #include "SkDevice.h"
12 #include "SkGpuDevice.h"
13 #include "SkGraphics.h"
14 #include "SkImageEncoder.h"
15 #include "SkPaint.h"
16 #include "SkPicture.h"
17 #include "SkStream.h"
18 #include "SkTime.h"
19 #include "SkWindow.h"
20
21 #include "SampleCode.h"
22 #include "GrContext.h"
23 #include "SkTypeface.h"
24
25 #include "gl/GrGLInterface.h"
26 #include "GrRenderTarget.h"
27
28 #include "SkPDFDevice.h"
29 #include "SkPDFDocument.h"
30 #include "SkStream.h"
31
32 #define TEST_GPIPE
33
34 #ifdef TEST_GPIPE
35 #define PIPE_FILEx
36 #ifdef PIPE_FILE
37 #define FILE_PATH "/path/to/drawing.data"
38 #endif
39
40 #define PIPE_NETx
41 #ifdef PIPE_NET
42 #include "SkSockets.h"
43 SkTCPServer gServer;
44 #endif
45
46 #define DEBUGGERx
47 #ifdef DEBUGGER
48 extern SkView* create_debugger(const char* data, size_t size);
49 extern bool is_debugger(SkView* view);
50 SkTDArray<char> gTempDataStore;
51 #endif
52
53 #endif
54
55 #define USE_ARROWS_FOR_ZOOM true
56 //#define DEFAULT_TO_GPU
57
58 extern SkView* create_overview(int, const SkViewFactory*[]);
59 extern bool is_overview(SkView* view);
60 //extern SkView* create_transition(SkView*, SkView*, int);
61 //extern bool is_transition(SkView* view);
62
63
64 #define ANIMATING_EVENTTYPE "nextSample"
65 #define ANIMATING_DELAY 750
66
67 #ifdef SK_DEBUG
68 #define FPS_REPEAT_MULTIPLIER 1
69 #else
70 #define FPS_REPEAT_MULTIPLIER 10
71 #endif
72 #define FPS_REPEAT_COUNT (10 * FPS_REPEAT_MULTIPLIER)
73
74 static SampleWindow* gSampleWindow;
75
postEventToSink(SkEvent * evt,SkEventSink * sink)76 static void postEventToSink(SkEvent* evt, SkEventSink* sink) {
77 evt->setTargetID(sink->getSinkID())->post();
78 }
79
80 ///////////////////////////////////////////////////////////////////////////////
81
skip_until(const char * str,const char * skip)82 static const char* skip_until(const char* str, const char* skip) {
83 if (!str) {
84 return NULL;
85 }
86 return strstr(str, skip);
87 }
88
skip_past(const char * str,const char * skip)89 static const char* skip_past(const char* str, const char* skip) {
90 const char* found = skip_until(str, skip);
91 if (!found) {
92 return NULL;
93 }
94 return found + strlen(skip);
95 }
96
97 static const char* gPrefFileName = "sampleapp_prefs.txt";
98
readTitleFromPrefs(SkString * title)99 static bool readTitleFromPrefs(SkString* title) {
100 SkFILEStream stream(gPrefFileName);
101 if (!stream.isValid()) {
102 return false;
103 }
104
105 int len = stream.getLength();
106 SkString data(len);
107 stream.read(data.writable_str(), len);
108 const char* s = data.c_str();
109
110 s = skip_past(s, "curr-slide-title");
111 s = skip_past(s, "=");
112 s = skip_past(s, "\"");
113 const char* stop = skip_until(s, "\"");
114 if (stop > s) {
115 title->set(s, stop - s);
116 return true;
117 }
118 return false;
119 }
120
writeTitleToPrefs(const char * title)121 static void writeTitleToPrefs(const char* title) {
122 SkFILEWStream stream(gPrefFileName);
123 SkString data;
124 data.printf("curr-slide-title = \"%s\"\n", title);
125 stream.write(data.c_str(), data.size());
126 }
127
128 ///////////////////////////////////////////////////////////////////////////////
129
130 class SampleWindow::DefaultDeviceManager : public SampleWindow::DeviceManager {
131 public:
132
DefaultDeviceManager()133 DefaultDeviceManager() {
134 fGrRenderTarget = NULL;
135 fGrContext = NULL;
136 fGL = NULL;
137 fNullGrContext = NULL;
138 fNullGrRenderTarget = NULL;
139 }
140
~DefaultDeviceManager()141 virtual ~DefaultDeviceManager() {
142 SkSafeUnref(fGrRenderTarget);
143 SkSafeUnref(fGrContext);
144 SkSafeUnref(fGL);
145 SkSafeUnref(fNullGrContext);
146 SkSafeUnref(fNullGrRenderTarget);
147 }
148
init(SampleWindow * win)149 virtual void init(SampleWindow* win) {
150 if (!win->attachGL()) {
151 SkDebugf("Failed to initialize GL");
152 }
153 if (NULL == fGL) {
154 fGL = GrGLCreateNativeInterface();
155 GrAssert(NULL == fGrContext);
156 fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
157 (GrPlatform3DContext) fGL);
158 }
159 if (NULL == fGrContext || NULL == fGL) {
160 SkSafeUnref(fGrContext);
161 SkSafeUnref(fGL);
162 SkDebugf("Failed to setup 3D");
163 win->detachGL();
164 }
165 if (NULL == fNullGrContext) {
166 const GrGLInterface* nullGL = GrGLCreateNullInterface();
167 fNullGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
168 (GrPlatform3DContext) nullGL);
169 nullGL->unref();
170 }
171 }
172
supportsDeviceType(SampleWindow::DeviceType dType)173 virtual bool supportsDeviceType(SampleWindow::DeviceType dType) {
174 switch (dType) {
175 case kRaster_DeviceType:
176 case kPicture_DeviceType: // fallthru
177 return true;
178 case kGPU_DeviceType:
179 return NULL != fGrContext && NULL != fGrRenderTarget;
180 case kNullGPU_DeviceType:
181 return NULL != fNullGrContext && NULL != fNullGrRenderTarget;
182 default:
183 return false;
184 }
185 }
186
prepareCanvas(SampleWindow::DeviceType dType,SkCanvas * canvas,SampleWindow * win)187 virtual bool prepareCanvas(SampleWindow::DeviceType dType,
188 SkCanvas* canvas,
189 SampleWindow* win) {
190 switch (dType) {
191 case kGPU_DeviceType:
192 if (fGrContext) {
193 canvas->setDevice(new SkGpuDevice(fGrContext,
194 fGrRenderTarget))->unref();
195 } else {
196 return false;
197 }
198 break;
199 case kNullGPU_DeviceType:
200 if (fNullGrContext) {
201 canvas->setDevice(new SkGpuDevice(fNullGrContext,
202 fNullGrRenderTarget))->unref();
203 } else {
204 return false;
205 }
206 break;
207 case kRaster_DeviceType:
208 case kPicture_DeviceType:
209 break;
210 }
211 return true;
212 }
213
publishCanvas(SampleWindow::DeviceType dType,SkCanvas * canvas,SampleWindow * win)214 virtual void publishCanvas(SampleWindow::DeviceType dType,
215 SkCanvas* canvas,
216 SampleWindow* win) {
217 if (fGrContext) {
218 // in case we have queued drawing calls
219 fGrContext->flush();
220 if (NULL != fNullGrContext) {
221 fNullGrContext->flush();
222 }
223 if (dType != kGPU_DeviceType &&
224 dType != kNullGPU_DeviceType) {
225 // need to send the raster bits to the (gpu) window
226 fGrContext->setRenderTarget(fGrRenderTarget);
227 const SkBitmap& bm = win->getBitmap();
228 fGrRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
229 kSkia8888_PM_GrPixelConfig,
230 bm.getPixels(),
231 bm.rowBytes());
232 }
233 }
234 win->presentGL();
235 }
236
windowSizeChanged(SampleWindow * win)237 virtual void windowSizeChanged(SampleWindow* win) {
238 if (fGrContext) {
239 win->attachGL();
240
241 GrPlatformRenderTargetDesc desc;
242 desc.fWidth = SkScalarRound(win->width());
243 desc.fHeight = SkScalarRound(win->height());
244 desc.fConfig = kSkia8888_PM_GrPixelConfig;
245 GR_GL_GetIntegerv(fGL, GR_GL_SAMPLES, &desc.fSampleCnt);
246 GR_GL_GetIntegerv(fGL, GR_GL_STENCIL_BITS, &desc.fStencilBits);
247 GrGLint buffer;
248 GR_GL_GetIntegerv(fGL, GR_GL_FRAMEBUFFER_BINDING, &buffer);
249 desc.fRenderTargetHandle = buffer;
250
251 SkSafeUnref(fGrRenderTarget);
252 fGrRenderTarget = fGrContext->createPlatformRenderTarget(desc);
253 }
254 if (NULL != fNullGrContext) {
255 GrPlatformRenderTargetDesc desc;
256 desc.fWidth = SkScalarRound(win->width());
257 desc.fHeight = SkScalarRound(win->height());
258 desc.fConfig = kSkia8888_PM_GrPixelConfig;
259 desc.fStencilBits = 8;
260 desc.fSampleCnt = 0;
261 desc.fRenderTargetHandle = 0;
262 fNullGrRenderTarget = fNullGrContext->createPlatformRenderTarget(desc);
263 }
264 }
265
getGrContext(SampleWindow::DeviceType dType)266 virtual GrContext* getGrContext(SampleWindow::DeviceType dType) {
267 if (kNullGPU_DeviceType == dType) {
268 return fNullGrContext;
269 } else {
270 return fGrContext;
271 }
272 }
273 private:
274 GrContext* fGrContext;
275 const GrGLInterface* fGL;
276 GrRenderTarget* fGrRenderTarget;
277 GrContext* fNullGrContext;
278 GrRenderTarget* fNullGrRenderTarget;
279 };
280
281 ///////////////
282 static const char view_inval_msg[] = "view-inval-msg";
283
postInvalDelay()284 void SampleWindow::postInvalDelay() {
285 (new SkEvent(view_inval_msg, this->getSinkID()))->postDelay(1);
286 }
287
isInvalEvent(const SkEvent & evt)288 static bool isInvalEvent(const SkEvent& evt) {
289 return evt.isType(view_inval_msg);
290 }
291 //////////////////
292
SkFuncViewFactory(SkViewCreateFunc func)293 SkFuncViewFactory::SkFuncViewFactory(SkViewCreateFunc func)
294 : fCreateFunc(func) {
295 }
296
operator ()() const297 SkView* SkFuncViewFactory::operator() () const {
298 return (*fCreateFunc)();
299 }
300
301 #include "GMSampleView.h"
302
SkGMSampleViewFactory(GMFactoryFunc func)303 SkGMSampleViewFactory::SkGMSampleViewFactory(GMFactoryFunc func)
304 : fFunc(func) {
305 }
306
operator ()() const307 SkView* SkGMSampleViewFactory::operator() () const {
308 return new GMSampleView(fFunc(NULL));
309 }
310
311 SkViewRegister* SkViewRegister::gHead;
SkViewRegister(SkViewFactory * fact)312 SkViewRegister::SkViewRegister(SkViewFactory* fact) : fFact(fact) {
313 fFact->ref();
314 fChain = gHead;
315 gHead = this;
316 }
317
SkViewRegister(SkViewCreateFunc func)318 SkViewRegister::SkViewRegister(SkViewCreateFunc func) {
319 fFact = new SkFuncViewFactory(func);
320 fChain = gHead;
321 gHead = this;
322 }
323
SkViewRegister(GMFactoryFunc func)324 SkViewRegister::SkViewRegister(GMFactoryFunc func) {
325 fFact = new SkGMSampleViewFactory(func);
326 fChain = gHead;
327 gHead = this;
328 }
329
330 class AutoUnrefArray {
331 public:
AutoUnrefArray()332 AutoUnrefArray() {}
~AutoUnrefArray()333 ~AutoUnrefArray() {
334 int count = fObjs.count();
335 for (int i = 0; i < count; ++i) {
336 fObjs[i]->unref();
337 }
338 }
push_back()339 SkRefCnt*& push_back() { return *fObjs.append(); }
340
341 private:
342 SkTDArray<SkRefCnt*> fObjs;
343 };
344
345 // registers GMs as Samples
346 // This can't be performed during static initialization because it could be
347 // run before GMRegistry has been fully built.
SkGMRegistyToSampleRegistry()348 void SkGMRegistyToSampleRegistry() {
349 static bool gOnce;
350 static AutoUnrefArray fRegisters;
351
352 if (!gOnce) {
353 const skiagm::GMRegistry* gmreg = skiagm::GMRegistry::Head();
354 while (gmreg) {
355 fRegisters.push_back() = new SkViewRegister(gmreg->factory());
356 gmreg = gmreg->next();
357 }
358 gOnce = true;
359 }
360 }
361
362 #if 0
363 #include <CoreFoundation/CoreFoundation.h>
364 #include <CoreFoundation/CFURLAccess.h>
365
366 static void testpdf() {
367 CFStringRef path = CFStringCreateWithCString(NULL, "/test.pdf",
368 kCFStringEncodingUTF8);
369 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path,
370 kCFURLPOSIXPathStyle,
371 false);
372 CFRelease(path);
373 CGRect box = CGRectMake(0, 0, 8*72, 10*72);
374 CGContextRef cg = CGPDFContextCreateWithURL(url, &box, NULL);
375 CFRelease(url);
376
377 CGContextBeginPage(cg, &box);
378 CGRect r = CGRectMake(10, 10, 40 + 0.5, 50 + 0.5);
379 CGContextFillEllipseInRect(cg, r);
380 CGContextEndPage(cg);
381 CGContextRelease(cg);
382
383 if (false) {
384 SkBitmap bm;
385 bm.setConfig(SkBitmap::kA8_Config, 64, 64);
386 bm.allocPixels();
387 bm.eraseColor(0);
388
389 SkCanvas canvas(bm);
390
391 }
392 }
393 #endif
394
395 //////////////////////////////////////////////////////////////////////////////
396
397 enum FlipAxisEnum {
398 kFlipAxis_X = (1 << 0),
399 kFlipAxis_Y = (1 << 1)
400 };
401
402 #include "SkDrawFilter.h"
403
404 class FlagsDrawFilter : public SkDrawFilter {
405 public:
FlagsDrawFilter(SkOSMenu::TriState lcd,SkOSMenu::TriState aa,SkOSMenu::TriState filter,SkOSMenu::TriState hinting)406 FlagsDrawFilter(SkOSMenu::TriState lcd, SkOSMenu::TriState aa, SkOSMenu::TriState filter,
407 SkOSMenu::TriState hinting) :
408 fLCDState(lcd), fAAState(aa), fFilterState(filter), fHintingState(hinting) {}
409
filter(SkPaint * paint,Type t)410 virtual void filter(SkPaint* paint, Type t) {
411 if (kText_Type == t && SkOSMenu::kMixedState != fLCDState) {
412 paint->setLCDRenderText(SkOSMenu::kOnState == fLCDState);
413 }
414 if (SkOSMenu::kMixedState != fAAState) {
415 paint->setAntiAlias(SkOSMenu::kOnState == fAAState);
416 }
417 if (SkOSMenu::kMixedState != fFilterState) {
418 paint->setFilterBitmap(SkOSMenu::kOnState == fFilterState);
419 }
420 if (SkOSMenu::kMixedState != fHintingState) {
421 paint->setHinting(SkOSMenu::kOnState == fHintingState ?
422 SkPaint::kNormal_Hinting :
423 SkPaint::kSlight_Hinting);
424 }
425 }
426
427 private:
428 SkOSMenu::TriState fLCDState;
429 SkOSMenu::TriState fAAState;
430 SkOSMenu::TriState fFilterState;
431 SkOSMenu::TriState fHintingState;
432 };
433
434 //////////////////////////////////////////////////////////////////////////////
435
436 #define MAX_ZOOM_LEVEL 8
437 #define MIN_ZOOM_LEVEL -8
438
439 static const char gCharEvtName[] = "SampleCode_Char_Event";
440 static const char gKeyEvtName[] = "SampleCode_Key_Event";
441 static const char gTitleEvtName[] = "SampleCode_Title_Event";
442 static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
443 static const char gFastTextEvtName[] = "SampleCode_FastText_Event";
444 static const char gUpdateWindowTitleEvtName[] = "SampleCode_UpdateWindowTitle";
445
CharQ(const SkEvent & evt,SkUnichar * outUni)446 bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) {
447 if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) {
448 if (outUni) {
449 *outUni = evt.getFast32();
450 }
451 return true;
452 }
453 return false;
454 }
455
KeyQ(const SkEvent & evt,SkKey * outKey)456 bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) {
457 if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) {
458 if (outKey) {
459 *outKey = (SkKey)evt.getFast32();
460 }
461 return true;
462 }
463 return false;
464 }
465
TitleQ(const SkEvent & evt)466 bool SampleCode::TitleQ(const SkEvent& evt) {
467 return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
468 }
469
TitleR(SkEvent * evt,const char title[])470 void SampleCode::TitleR(SkEvent* evt, const char title[]) {
471 SkASSERT(evt && TitleQ(*evt));
472 evt->setString(gTitleEvtName, title);
473 }
474
RequestTitle(SkView * view,SkString * title)475 bool SampleCode::RequestTitle(SkView* view, SkString* title) {
476 SkEvent evt(gTitleEvtName);
477 if (view->doQuery(&evt)) {
478 title->set(evt.findString(gTitleEvtName));
479 return true;
480 }
481 return false;
482 }
483
PrefSizeQ(const SkEvent & evt)484 bool SampleCode::PrefSizeQ(const SkEvent& evt) {
485 return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1);
486 }
487
PrefSizeR(SkEvent * evt,SkScalar width,SkScalar height)488 void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) {
489 SkASSERT(evt && PrefSizeQ(*evt));
490 SkScalar size[2];
491 size[0] = width;
492 size[1] = height;
493 evt->setScalars(gPrefSizeEvtName, 2, size);
494 }
495
FastTextQ(const SkEvent & evt)496 bool SampleCode::FastTextQ(const SkEvent& evt) {
497 return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1);
498 }
499
500 ///////////////////////////////////////////////////////////////////////////////
501
502 static SkMSec gAnimTime;
503 static SkMSec gAnimTimePrev;
504
GetAnimTime()505 SkMSec SampleCode::GetAnimTime() { return gAnimTime; }
GetAnimTimeDelta()506 SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; }
GetAnimSecondsDelta()507 SkScalar SampleCode::GetAnimSecondsDelta() {
508 return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0);
509 }
510
GetAnimScalar(SkScalar speed,SkScalar period)511 SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) {
512 // since gAnimTime can be up to 32 bits, we can't convert it to a float
513 // or we'll lose the low bits. Hence we use doubles for the intermediate
514 // calculations
515 double seconds = (double)gAnimTime / 1000.0;
516 double value = SkScalarToDouble(speed) * seconds;
517 if (period) {
518 value = ::fmod(value, SkScalarToDouble(period));
519 }
520 return SkDoubleToScalar(value);
521 }
522
GetGr()523 GrContext* SampleCode::GetGr() {
524 return gSampleWindow ? gSampleWindow->getGrContext() : NULL;
525 }
526
527 // some GMs rely on having a skiagm::GetGr function defined
528 namespace skiagm {
GetGr()529 GrContext* GetGr() { return SampleCode::GetGr(); }
530 }
531
532 //////////////////////////////////////////////////////////////////////////////
533
curr_view(SkWindow * wind)534 static SkView* curr_view(SkWindow* wind) {
535 SkView::F2BIter iter(wind);
536 return iter.next();
537 }
538
curr_title(SkWindow * wind,SkString * title)539 static bool curr_title(SkWindow* wind, SkString* title) {
540 SkView* view = curr_view(wind);
541 if (view) {
542 SkEvent evt(gTitleEvtName);
543 if (view->doQuery(&evt)) {
544 title->set(evt.findString(gTitleEvtName));
545 return true;
546 }
547 }
548 return false;
549 }
550
setZoomCenter(float x,float y)551 void SampleWindow::setZoomCenter(float x, float y)
552 {
553 fZoomCenterX = SkFloatToScalar(x);
554 fZoomCenterY = SkFloatToScalar(y);
555 }
556
zoomIn()557 bool SampleWindow::zoomIn()
558 {
559 // Arbitrarily decided
560 if (fFatBitsScale == 25) return false;
561 fFatBitsScale++;
562 this->inval(NULL);
563 return true;
564 }
565
zoomOut()566 bool SampleWindow::zoomOut()
567 {
568 if (fFatBitsScale == 1) return false;
569 fFatBitsScale--;
570 this->inval(NULL);
571 return true;
572 }
573
updatePointer(int x,int y)574 void SampleWindow::updatePointer(int x, int y)
575 {
576 fMouseX = x;
577 fMouseY = y;
578 if (fShowZoomer) {
579 this->inval(NULL);
580 }
581 }
582
cycle_devicetype(SampleWindow::DeviceType ct)583 static inline SampleWindow::DeviceType cycle_devicetype(SampleWindow::DeviceType ct) {
584 static const SampleWindow::DeviceType gCT[] = {
585 SampleWindow::kPicture_DeviceType,
586 SampleWindow::kGPU_DeviceType,
587 SampleWindow::kRaster_DeviceType, // skip the null gpu device in normal cycling
588 SampleWindow::kRaster_DeviceType
589 };
590 return gCT[ct];
591 }
592
SampleWindow(void * hwnd,int argc,char ** argv,DeviceManager * devManager)593 SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* devManager) : INHERITED(hwnd) {
594 gSampleWindow = this;
595
596 #ifdef PIPE_FILE
597 //Clear existing file or create file if it doesn't exist
598 FILE* f = fopen(FILE_PATH, "wb");
599 fclose(f);
600 #endif
601
602 fPicture = NULL;
603
604 #ifdef DEFAULT_TO_GPU
605 fDeviceType = kGPU_DeviceType;
606 #else
607 fDeviceType = kRaster_DeviceType;
608 #endif
609 fUseClip = false;
610 fNClip = false;
611 fAnimating = false;
612 fRotate = false;
613 fPerspAnim = false;
614 fPerspAnimTime = 0;
615 fScale = false;
616 fRequestGrabImage = false;
617 fUsePipe = false;
618 fMeasureFPS = false;
619 fLCDState = SkOSMenu::kMixedState;
620 fAAState = SkOSMenu::kMixedState;
621 fFilterState = SkOSMenu::kMixedState;
622 fHintingState = SkOSMenu::kMixedState;
623 fFlipAxis = 0;
624 fScrollTestX = fScrollTestY = 0;
625
626 fMouseX = fMouseY = 0;
627 fFatBitsScale = 8;
628 fTypeface = SkTypeface::CreateFromTypeface(NULL, SkTypeface::kBold);
629 fShowZoomer = false;
630
631 fZoomLevel = 0;
632 fZoomScale = SK_Scalar1;
633
634 fMagnify = false;
635 fDebugger = false;
636
637 fSaveToPdf = false;
638 fPdfCanvas = NULL;
639
640 fTransitionNext = 6;
641 fTransitionPrev = 2;
642
643 int sinkID = this->getSinkID();
644 fAppMenu.setTitle("Global Settings");
645 int itemID;
646
647 itemID =fAppMenu.appendList("Device Type", "Device Type", sinkID, 0,
648 "Raster", "Picture", "OpenGL", NULL);
649 fAppMenu.assignKeyEquivalentToItem(itemID, 'd');
650 itemID = fAppMenu.appendTriState("AA", "AA", sinkID, fAAState);
651 fAppMenu.assignKeyEquivalentToItem(itemID, 'b');
652 itemID = fAppMenu.appendTriState("LCD", "LCD", sinkID, fLCDState);
653 fAppMenu.assignKeyEquivalentToItem(itemID, 'l');
654 itemID = fAppMenu.appendTriState("Filter", "Filter", sinkID, fFilterState);
655 fAppMenu.assignKeyEquivalentToItem(itemID, 'n');
656 itemID = fAppMenu.appendTriState("Hinting", "Hinting", sinkID, fHintingState);
657 fAppMenu.assignKeyEquivalentToItem(itemID, 'h');
658 fUsePipeMenuItemID = fAppMenu.appendSwitch("Pipe", "Pipe" , sinkID, fUsePipe);
659 fAppMenu.assignKeyEquivalentToItem(fUsePipeMenuItemID, 'p');
660 #ifdef DEBUGGER
661 itemID = fAppMenu.appendSwitch("Debugger", "Debugger", sinkID, fDebugger);
662 fAppMenu.assignKeyEquivalentToItem(itemID, 'q');
663 #endif
664 itemID = fAppMenu.appendSwitch("Slide Show", "Slide Show" , sinkID, false);
665 fAppMenu.assignKeyEquivalentToItem(itemID, 'a');
666 itemID = fAppMenu.appendSwitch("Clip", "Clip" , sinkID, fUseClip);
667 fAppMenu.assignKeyEquivalentToItem(itemID, 'c');
668 itemID = fAppMenu.appendSwitch("Flip X", "Flip X" , sinkID, false);
669 fAppMenu.assignKeyEquivalentToItem(itemID, 'x');
670 itemID = fAppMenu.appendSwitch("Flip Y", "Flip Y" , sinkID, false);
671 fAppMenu.assignKeyEquivalentToItem(itemID, 'y');
672 itemID = fAppMenu.appendSwitch("Zoomer", "Zoomer" , sinkID, fShowZoomer);
673 fAppMenu.assignKeyEquivalentToItem(itemID, 'z');
674 itemID = fAppMenu.appendSwitch("Magnify", "Magnify" , sinkID, fMagnify);
675 fAppMenu.assignKeyEquivalentToItem(itemID, 'm');
676 itemID =fAppMenu.appendList("Transition-Next", "Transition-Next", sinkID,
677 fTransitionNext, "Up", "Up and Right", "Right",
678 "Down and Right", "Down", "Down and Left",
679 "Left", "Up and Left", NULL);
680 fAppMenu.assignKeyEquivalentToItem(itemID, 'j');
681 itemID =fAppMenu.appendList("Transition-Prev", "Transition-Prev", sinkID,
682 fTransitionPrev, "Up", "Up and Right", "Right",
683 "Down and Right", "Down", "Down and Left",
684 "Left", "Up and Left", NULL);
685 fAppMenu.assignKeyEquivalentToItem(itemID, 'k');
686 itemID = fAppMenu.appendAction("Save to PDF", sinkID);
687 fAppMenu.assignKeyEquivalentToItem(itemID, 'e');
688
689 this->addMenu(&fAppMenu);
690 this->addMenu(&fSlideMenu);
691
692 // this->setConfig(SkBitmap::kRGB_565_Config);
693 this->setConfig(SkBitmap::kARGB_8888_Config);
694 this->setVisibleP(true);
695 this->setClipToBounds(false);
696
697 SkGMRegistyToSampleRegistry();
698 {
699 const SkViewRegister* reg = SkViewRegister::Head();
700 while (reg) {
701 *fSamples.append() = reg->factory();
702 reg = reg->next();
703 }
704 }
705 fCurrIndex = 0;
706 if (argc > 1) {
707 fCurrIndex = findByTitle(argv[1]);
708 if (fCurrIndex < 0) {
709 fprintf(stderr, "Unknown sample \"%s\"\n", argv[1]);
710 }
711 } else {
712 SkString title;
713 if (readTitleFromPrefs(&title)) {
714 fCurrIndex = findByTitle(title.c_str());
715 }
716 }
717
718 if (fCurrIndex < 0) {
719 fCurrIndex = 0;
720 }
721 this->loadView((*fSamples[fCurrIndex])());
722
723 fPDFData = NULL;
724
725 if (NULL == devManager) {
726 fDevManager = new DefaultDeviceManager();
727 } else {
728 devManager->ref();
729 fDevManager = devManager;
730 }
731 fDevManager->init(this);
732
733 // If another constructor set our dimensions, ensure that our
734 // onSizeChange gets called.
735 if (this->height() && this->width()) {
736 this->onSizeChange();
737 }
738
739 // can't call this synchronously, since it may require a subclass to
740 // to implement, or the caller may need us to have returned from the
741 // constructor first. Hence we post an event to ourselves.
742 // this->updateTitle();
743 postEventToSink(new SkEvent(gUpdateWindowTitleEvtName), this);
744 }
745
~SampleWindow()746 SampleWindow::~SampleWindow() {
747 delete fPicture;
748 delete fPdfCanvas;
749 fTypeface->unref();
750
751 SkSafeUnref(fDevManager);
752 }
753
findByTitle(const char title[])754 int SampleWindow::findByTitle(const char title[]) {
755 int i, count = fSamples.count();
756 for (i = 0; i < count; i++) {
757 if (getSampleTitle(i).equals(title)) {
758 return i;
759 }
760 }
761 return -1;
762 }
763
capture_bitmap(SkCanvas * canvas)764 static SkBitmap capture_bitmap(SkCanvas* canvas) {
765 SkBitmap bm;
766 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
767 src.copyTo(&bm, src.config());
768 return bm;
769 }
770
bitmap_diff(SkCanvas * canvas,const SkBitmap & orig,SkBitmap * diff)771 static bool bitmap_diff(SkCanvas* canvas, const SkBitmap& orig,
772 SkBitmap* diff) {
773 const SkBitmap& src = canvas->getDevice()->accessBitmap(false);
774
775 SkAutoLockPixels alp0(src);
776 SkAutoLockPixels alp1(orig);
777 for (int y = 0; y < src.height(); y++) {
778 const void* srcP = src.getAddr(0, y);
779 const void* origP = orig.getAddr(0, y);
780 size_t bytes = src.width() * src.bytesPerPixel();
781 if (memcmp(srcP, origP, bytes)) {
782 SkDebugf("---------- difference on line %d\n", y);
783 return true;
784 }
785 }
786 return false;
787 }
788
drawText(SkCanvas * canvas,SkString string,SkScalar left,SkScalar top,SkPaint & paint)789 static void drawText(SkCanvas* canvas, SkString string, SkScalar left, SkScalar top, SkPaint& paint)
790 {
791 SkColor desiredColor = paint.getColor();
792 paint.setColor(SK_ColorWHITE);
793 const char* c_str = string.c_str();
794 size_t size = string.size();
795 SkRect bounds;
796 paint.measureText(c_str, size, &bounds);
797 bounds.offset(left, top);
798 SkScalar inset = SkIntToScalar(-2);
799 bounds.inset(inset, inset);
800 canvas->drawRect(bounds, paint);
801 if (desiredColor != SK_ColorBLACK) {
802 paint.setColor(SK_ColorBLACK);
803 canvas->drawText(c_str, size, left + SK_Scalar1, top + SK_Scalar1, paint);
804 }
805 paint.setColor(desiredColor);
806 canvas->drawText(c_str, size, left, top, paint);
807 }
808
809 #define XCLIP_N 8
810 #define YCLIP_N 8
811
draw(SkCanvas * canvas)812 void SampleWindow::draw(SkCanvas* canvas) {
813 if (!fDevManager->prepareCanvas(fDeviceType, canvas, this)) {
814 return;
815 }
816 // update the animation time
817 if (!gAnimTimePrev && !gAnimTime) {
818 // first time make delta be 0
819 gAnimTime = SkTime::GetMSecs();
820 gAnimTimePrev = gAnimTime;
821 } else {
822 gAnimTimePrev = gAnimTime;
823 gAnimTime = SkTime::GetMSecs();
824 }
825
826 const SkMatrix& localM = fGesture.localM();
827 if (localM.getType() & SkMatrix::kScale_Mask) {
828 canvas->setExternalMatrix(&localM);
829 }
830 if (fGesture.isActive()) {
831 this->updateMatrix();
832 }
833
834 if (fNClip) {
835 this->INHERITED::draw(canvas);
836 SkBitmap orig = capture_bitmap(canvas);
837
838 const SkScalar w = this->width();
839 const SkScalar h = this->height();
840 const SkScalar cw = w / XCLIP_N;
841 const SkScalar ch = h / YCLIP_N;
842 for (int y = 0; y < YCLIP_N; y++) {
843 SkRect r;
844 r.fTop = y * ch;
845 r.fBottom = (y + 1) * ch;
846 if (y == YCLIP_N - 1) {
847 r.fBottom = h;
848 }
849 for (int x = 0; x < XCLIP_N; x++) {
850 SkAutoCanvasRestore acr(canvas, true);
851 r.fLeft = x * cw;
852 r.fRight = (x + 1) * cw;
853 if (x == XCLIP_N - 1) {
854 r.fRight = w;
855 }
856 canvas->clipRect(r);
857 this->INHERITED::draw(canvas);
858 }
859 }
860
861 SkBitmap diff;
862 if (bitmap_diff(canvas, orig, &diff)) {
863 }
864 } else {
865 this->INHERITED::draw(canvas);
866 }
867 if (fShowZoomer && !fSaveToPdf) {
868 showZoomer(canvas);
869 }
870 if (fMagnify && !fSaveToPdf) {
871 magnify(canvas);
872 }
873
874 // do this last
875 fDevManager->publishCanvas(fDeviceType, canvas, this);
876 }
877
878 static float clipW = 200;
879 static float clipH = 200;
magnify(SkCanvas * canvas)880 void SampleWindow::magnify(SkCanvas* canvas) {
881 SkRect r;
882 int count = canvas->save();
883
884 SkMatrix m = canvas->getTotalMatrix();
885 m.invert(&m);
886 SkPoint offset, center;
887 SkScalar mouseX = fMouseX * SK_Scalar1;
888 SkScalar mouseY = fMouseY * SK_Scalar1;
889 m.mapXY(mouseX - clipW/2, mouseY - clipH/2, &offset);
890 m.mapXY(mouseX, mouseY, ¢er);
891
892 r.set(0, 0, clipW * m.getScaleX(), clipH * m.getScaleX());
893 r.offset(offset.fX, offset.fY);
894
895 SkPaint paint;
896 paint.setColor(0xFF66AAEE);
897 paint.setStyle(SkPaint::kStroke_Style);
898 paint.setStrokeWidth(10.f * m.getScaleX());
899 //lense offset
900 //canvas->translate(0, -250);
901 canvas->drawRect(r, paint);
902 canvas->clipRect(r);
903
904 m = canvas->getTotalMatrix();
905 m.setTranslate(-center.fX, -center.fY);
906 m.postScale(0.5f * fFatBitsScale, 0.5f * fFatBitsScale);
907 m.postTranslate(center.fX, center.fY);
908 canvas->concat(m);
909
910 this->INHERITED::draw(canvas);
911
912 canvas->restoreToCount(count);
913 }
914
showZoomer(SkCanvas * canvas)915 void SampleWindow::showZoomer(SkCanvas* canvas) {
916 int count = canvas->save();
917 canvas->resetMatrix();
918 // Ensure the mouse position is on screen.
919 int width = SkScalarRound(this->width());
920 int height = SkScalarRound(this->height());
921 if (fMouseX >= width) fMouseX = width - 1;
922 else if (fMouseX < 0) fMouseX = 0;
923 if (fMouseY >= height) fMouseY = height - 1;
924 else if (fMouseY < 0) fMouseY = 0;
925
926 SkBitmap bitmap = capture_bitmap(canvas);
927 bitmap.lockPixels();
928
929 // Find the size of the zoomed in view, forced to be odd, so the examined pixel is in the middle.
930 int zoomedWidth = (width >> 1) | 1;
931 int zoomedHeight = (height >> 1) | 1;
932 SkIRect src;
933 src.set(0, 0, zoomedWidth / fFatBitsScale, zoomedHeight / fFatBitsScale);
934 src.offset(fMouseX - (src.width()>>1), fMouseY - (src.height()>>1));
935 SkRect dest;
936 dest.set(0, 0, SkIntToScalar(zoomedWidth), SkIntToScalar(zoomedHeight));
937 dest.offset(SkIntToScalar(width - zoomedWidth), SkIntToScalar(height - zoomedHeight));
938 SkPaint paint;
939 // Clear the background behind our zoomed in view
940 paint.setColor(SK_ColorWHITE);
941 canvas->drawRect(dest, paint);
942 canvas->drawBitmapRect(bitmap, &src, dest);
943 paint.setColor(SK_ColorBLACK);
944 paint.setStyle(SkPaint::kStroke_Style);
945 // Draw a border around the pixel in the middle
946 SkRect originalPixel;
947 originalPixel.set(SkIntToScalar(fMouseX), SkIntToScalar(fMouseY), SkIntToScalar(fMouseX + 1), SkIntToScalar(fMouseY + 1));
948 SkMatrix matrix;
949 SkRect scalarSrc;
950 scalarSrc.set(src);
951 SkColor color = bitmap.getColor(fMouseX, fMouseY);
952 if (matrix.setRectToRect(scalarSrc, dest, SkMatrix::kFill_ScaleToFit)) {
953 SkRect pixel;
954 matrix.mapRect(&pixel, originalPixel);
955 // TODO Perhaps measure the values and make the outline white if it's "dark"
956 if (color == SK_ColorBLACK) {
957 paint.setColor(SK_ColorWHITE);
958 }
959 canvas->drawRect(pixel, paint);
960 }
961 paint.setColor(SK_ColorBLACK);
962 // Draw a border around the destination rectangle
963 canvas->drawRect(dest, paint);
964 paint.setStyle(SkPaint::kStrokeAndFill_Style);
965 // Identify the pixel and its color on screen
966 paint.setTypeface(fTypeface);
967 paint.setAntiAlias(true);
968 SkScalar lineHeight = paint.getFontMetrics(NULL);
969 SkString string;
970 string.appendf("(%i, %i)", fMouseX, fMouseY);
971 SkScalar left = dest.fLeft + SkIntToScalar(3);
972 SkScalar i = SK_Scalar1;
973 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
974 // Alpha
975 i += SK_Scalar1;
976 string.reset();
977 string.appendf("A: %X", SkColorGetA(color));
978 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
979 // Red
980 i += SK_Scalar1;
981 string.reset();
982 string.appendf("R: %X", SkColorGetR(color));
983 paint.setColor(SK_ColorRED);
984 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
985 // Green
986 i += SK_Scalar1;
987 string.reset();
988 string.appendf("G: %X", SkColorGetG(color));
989 paint.setColor(SK_ColorGREEN);
990 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
991 // Blue
992 i += SK_Scalar1;
993 string.reset();
994 string.appendf("B: %X", SkColorGetB(color));
995 paint.setColor(SK_ColorBLUE);
996 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint);
997 canvas->restoreToCount(count);
998 }
999
onDraw(SkCanvas * canvas)1000 void SampleWindow::onDraw(SkCanvas* canvas) {
1001 }
1002
1003 #include "SkColorPriv.h"
1004
reverseRedAndBlue(const SkBitmap & bm)1005 static void reverseRedAndBlue(const SkBitmap& bm) {
1006 SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config);
1007 uint8_t* p = (uint8_t*)bm.getPixels();
1008 uint8_t* stop = p + bm.getSize();
1009 while (p < stop) {
1010 // swap red/blue (to go from ARGB(int) to RGBA(memory) and premultiply
1011 unsigned scale = SkAlpha255To256(p[3]);
1012 unsigned r = p[2];
1013 unsigned b = p[0];
1014 p[0] = SkAlphaMul(r, scale);
1015 p[1] = SkAlphaMul(p[1], scale);
1016 p[2] = SkAlphaMul(b, scale);
1017 p += 4;
1018 }
1019 }
1020
saveToPdf()1021 void SampleWindow::saveToPdf()
1022 {
1023 fSaveToPdf = true;
1024 this->inval(NULL);
1025 }
1026
beforeChildren(SkCanvas * canvas)1027 SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
1028 if (fSaveToPdf) {
1029 const SkBitmap& bmp = canvas->getDevice()->accessBitmap(false);
1030 SkISize size = SkISize::Make(bmp.width(), bmp.height());
1031 SkPDFDevice* pdfDevice = new SkPDFDevice(size, size,
1032 canvas->getTotalMatrix());
1033 fPdfCanvas = new SkCanvas(pdfDevice);
1034 pdfDevice->unref();
1035 canvas = fPdfCanvas;
1036 } else {
1037 switch (fDeviceType) {
1038 case kRaster_DeviceType:
1039 case kGPU_DeviceType:
1040 canvas = this->INHERITED::beforeChildren(canvas);
1041 break;
1042 case kPicture_DeviceType:
1043 fPicture = new SkPicture;
1044 canvas = fPicture->beginRecording(9999, 9999);
1045 break;
1046 case kNullGPU_DeviceType:
1047 break;
1048 }
1049 }
1050
1051 if (fUseClip) {
1052 canvas->drawColor(0xFFFF88FF);
1053 canvas->clipPath(fClipPath, SkRegion::kIntersect_Op, true);
1054 }
1055
1056 return canvas;
1057 }
1058
paint_rgn(const SkBitmap & bm,const SkIRect & r,const SkRegion & rgn)1059 static void paint_rgn(const SkBitmap& bm, const SkIRect& r,
1060 const SkRegion& rgn) {
1061 SkCanvas canvas(bm);
1062 SkRegion inval(rgn);
1063
1064 inval.translate(r.fLeft, r.fTop);
1065 canvas.clipRegion(inval);
1066 canvas.drawColor(0xFFFF8080);
1067 }
1068 #include "SkData.h"
afterChildren(SkCanvas * orig)1069 void SampleWindow::afterChildren(SkCanvas* orig) {
1070 if (fSaveToPdf) {
1071 fSaveToPdf = false;
1072 if (fShowZoomer) {
1073 showZoomer(fPdfCanvas);
1074 }
1075 SkString name;
1076 name.printf("%s.pdf", this->getTitle());
1077 SkPDFDocument doc;
1078 SkPDFDevice* device = static_cast<SkPDFDevice*>(fPdfCanvas->getDevice());
1079 doc.appendPage(device);
1080 #ifdef SK_BUILD_FOR_ANDROID
1081 name.prepend("/sdcard/");
1082 #endif
1083
1084 #ifdef SK_BUILD_FOR_IOS
1085 SkDynamicMemoryWStream mstream;
1086 doc.emitPDF(&mstream);
1087 fPDFData = mstream.copyToData();
1088 #endif
1089 SkFILEWStream stream(name.c_str());
1090 if (stream.isValid()) {
1091 doc.emitPDF(&stream);
1092 const char* desc = "File saved from Skia SampleApp";
1093 this->onPDFSaved(this->getTitle(), desc, name.c_str());
1094 }
1095
1096 delete fPdfCanvas;
1097 fPdfCanvas = NULL;
1098
1099 // We took over the draw calls in order to create the PDF, so we need
1100 // to redraw.
1101 this->inval(NULL);
1102 return;
1103 }
1104
1105 if (fRequestGrabImage) {
1106 fRequestGrabImage = false;
1107
1108 SkDevice* device = orig->getDevice();
1109 SkBitmap bmp;
1110 if (device->accessBitmap(false).copyTo(&bmp, SkBitmap::kARGB_8888_Config)) {
1111 static int gSampleGrabCounter;
1112 SkString name;
1113 name.printf("sample_grab_%d", gSampleGrabCounter++);
1114 SkImageEncoder::EncodeFile(name.c_str(), bmp,
1115 SkImageEncoder::kPNG_Type, 100);
1116 }
1117 }
1118
1119 if (kPicture_DeviceType == fDeviceType) {
1120 if (true) {
1121 SkPicture* pict = new SkPicture(*fPicture);
1122 fPicture->unref();
1123 this->installDrawFilter(orig);
1124 orig->drawPicture(*pict);
1125 pict->unref();
1126 } else if (true) {
1127 SkDynamicMemoryWStream ostream;
1128 fPicture->serialize(&ostream);
1129 fPicture->unref();
1130
1131 SkAutoDataUnref data(ostream.copyToData());
1132 SkMemoryStream istream(data.data(), data.size());
1133 SkPicture pict(&istream);
1134 orig->drawPicture(pict);
1135 } else {
1136 fPicture->draw(orig);
1137 fPicture->unref();
1138 }
1139 fPicture = NULL;
1140 }
1141
1142 // Do this after presentGL and other finishing, rather than in afterChild
1143 if (fMeasureFPS && fMeasureFPS_Time) {
1144 fMeasureFPS_Time = SkTime::GetMSecs() - fMeasureFPS_Time;
1145 this->updateTitle();
1146 this->postInvalDelay();
1147 }
1148
1149 // if ((fScrollTestX | fScrollTestY) != 0)
1150 if (false) {
1151 const SkBitmap& bm = orig->getDevice()->accessBitmap(true);
1152 int dx = fScrollTestX * 7;
1153 int dy = fScrollTestY * 7;
1154 SkIRect r;
1155 SkRegion inval;
1156
1157 r.set(50, 50, 50+100, 50+100);
1158 bm.scrollRect(&r, dx, dy, &inval);
1159 paint_rgn(bm, r, inval);
1160 }
1161 #ifdef DEBUGGER
1162 SkView* curr = curr_view(this);
1163 if (fDebugger && !is_debugger(curr) && !is_transition(curr) && !is_overview(curr)) {
1164 //Stop Pipe when fDebugger is active
1165 fUsePipe = false;
1166 (void)SampleView::SetUsePipe(curr, false);
1167 fAppMenu.getItemByID(fUsePipeMenuItemID)->setBool(fUsePipe);
1168 this->onUpdateMenu(&fAppMenu);
1169
1170 //Reset any transformations
1171 fGesture.stop();
1172 fGesture.reset();
1173
1174 this->loadView(create_debugger(gTempDataStore.begin(),
1175 gTempDataStore.count()));
1176 }
1177 #endif
1178 }
1179
beforeChild(SkView * child,SkCanvas * canvas)1180 void SampleWindow::beforeChild(SkView* child, SkCanvas* canvas) {
1181 if (fScale) {
1182 SkScalar scale = SK_Scalar1 * 7 / 10;
1183 SkScalar cx = this->width() / 2;
1184 SkScalar cy = this->height() / 2;
1185 canvas->translate(cx, cy);
1186 canvas->scale(scale, scale);
1187 canvas->translate(-cx, -cy);
1188 }
1189 if (fRotate) {
1190 SkScalar cx = this->width() / 2;
1191 SkScalar cy = this->height() / 2;
1192 canvas->translate(cx, cy);
1193 canvas->rotate(SkIntToScalar(30));
1194 canvas->translate(-cx, -cy);
1195 }
1196 if (fPerspAnim) {
1197 fPerspAnimTime += SampleCode::GetAnimSecondsDelta();
1198
1199 static const SkScalar gAnimPeriod = 10 * SK_Scalar1;
1200 static const SkScalar gAnimMag = SK_Scalar1 / 1000;
1201 SkScalar t = SkScalarMod(fPerspAnimTime, gAnimPeriod);
1202 if (SkScalarFloorToInt(SkScalarDiv(fPerspAnimTime, gAnimPeriod)) & 0x1) {
1203 t = gAnimPeriod - t;
1204 }
1205 t = 2 * t - gAnimPeriod;
1206 t = SkScalarMul(SkScalarDiv(t, gAnimPeriod), gAnimMag);
1207 SkMatrix m;
1208 m.reset();
1209 m.setPerspY(t);
1210 canvas->concat(m);
1211 }
1212
1213 this->installDrawFilter(canvas);
1214
1215 if (fMeasureFPS) {
1216 fMeasureFPS_Time = 0; // 0 means the child is not aware of repeat-draw
1217 if (SampleView::SetRepeatDraw(child, FPS_REPEAT_COUNT)) {
1218 fMeasureFPS_Time = SkTime::GetMSecs();
1219 }
1220 } else {
1221 (void)SampleView::SetRepeatDraw(child, 1);
1222 }
1223 if (fPerspAnim) {
1224 this->inval(NULL);
1225 }
1226 //(void)SampleView::SetUsePipe(child, fUsePipe);
1227 }
1228
afterChild(SkView * child,SkCanvas * canvas)1229 void SampleWindow::afterChild(SkView* child, SkCanvas* canvas) {
1230 canvas->setDrawFilter(NULL);
1231 }
1232
1233 static SkBitmap::Config gConfigCycle[] = {
1234 SkBitmap::kNo_Config, // none -> none
1235 SkBitmap::kNo_Config, // a1 -> none
1236 SkBitmap::kNo_Config, // a8 -> none
1237 SkBitmap::kNo_Config, // index8 -> none
1238 SkBitmap::kARGB_4444_Config, // 565 -> 4444
1239 SkBitmap::kARGB_8888_Config, // 4444 -> 8888
1240 SkBitmap::kRGB_565_Config // 8888 -> 565
1241 };
1242
cycle_configs(SkBitmap::Config c)1243 static SkBitmap::Config cycle_configs(SkBitmap::Config c) {
1244 return gConfigCycle[c];
1245 }
1246
changeZoomLevel(float delta)1247 void SampleWindow::changeZoomLevel(float delta) {
1248 fZoomLevel += SkFloatToScalar(delta);
1249 if (fZoomLevel > 0) {
1250 fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL);
1251 fZoomScale = fZoomLevel + SK_Scalar1;
1252 } else if (fZoomLevel < 0) {
1253 fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL);
1254 fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel);
1255 } else {
1256 fZoomScale = SK_Scalar1;
1257 }
1258 this->updateMatrix();
1259 }
1260
updateMatrix()1261 void SampleWindow::updateMatrix(){
1262 SkMatrix m;
1263 m.reset();
1264 if (fZoomLevel) {
1265 SkPoint center;
1266 //m = this->getLocalMatrix();//.invert(&m);
1267 m.mapXY(fZoomCenterX, fZoomCenterY, ¢er);
1268 SkScalar cx = center.fX;
1269 SkScalar cy = center.fY;
1270
1271 m.setTranslate(-cx, -cy);
1272 m.postScale(fZoomScale, fZoomScale);
1273 m.postTranslate(cx, cy);
1274 }
1275
1276 if (fFlipAxis) {
1277 m.preTranslate(fZoomCenterX, fZoomCenterY);
1278 if (fFlipAxis & kFlipAxis_X) {
1279 m.preScale(-SK_Scalar1, SK_Scalar1);
1280 }
1281 if (fFlipAxis & kFlipAxis_Y) {
1282 m.preScale(SK_Scalar1, -SK_Scalar1);
1283 }
1284 m.preTranslate(-fZoomCenterX, -fZoomCenterY);
1285 //canvas->concat(m);
1286 }
1287 // Apply any gesture matrix
1288 m.preConcat(fGesture.localM());
1289 m.preConcat(fGesture.globalM());
1290
1291 this->setLocalMatrix(m);
1292
1293 this->updateTitle();
1294 this->inval(NULL);
1295 }
previousSample()1296 bool SampleWindow::previousSample() {
1297 fCurrIndex = (fCurrIndex - 1 + fSamples.count()) % fSamples.count();
1298 SkView* view = (*fSamples[fCurrIndex])();
1299 this->loadView(view);
1300 // this->loadView(create_transition(curr_view(this), (*fSamples[fCurrIndex])(),
1301 // fTransitionPrev));
1302 return true;
1303 }
1304
nextSample()1305 bool SampleWindow::nextSample() {
1306 fCurrIndex = (fCurrIndex + 1) % fSamples.count();
1307 SkView* view = (*fSamples[fCurrIndex])();
1308 this->loadView(view);
1309 // this->loadView(create_transition(curr_view(this), (*fSamples[fCurrIndex])(),
1310 // fTransitionNext));
1311 return true;
1312 }
1313
goToSample(int i)1314 bool SampleWindow::goToSample(int i) {
1315 fCurrIndex = (i) % fSamples.count();
1316 SkView* view = (*fSamples[fCurrIndex])();
1317 this->loadView(view);
1318 // this->loadView(create_transition(curr_view(this),(*fSamples[fCurrIndex])(), 6));
1319 return true;
1320 }
1321
getSampleTitle(int i)1322 SkString SampleWindow::getSampleTitle(int i) {
1323 SkView* view = (*fSamples[i])();
1324 SkString title;
1325 SampleCode::RequestTitle(view, &title);
1326 view->unref();
1327 return title;
1328 }
1329
sampleCount()1330 int SampleWindow::sampleCount() {
1331 return fSamples.count();
1332 }
1333
showOverview()1334 void SampleWindow::showOverview() {
1335 this->loadView(create_overview(fSamples.count(), fSamples.begin()));
1336 // this->loadView(create_transition(curr_view(this),
1337 // create_overview(fSamples.count(), fSamples.begin()),
1338 // 4));
1339 }
1340
installDrawFilter(SkCanvas * canvas)1341 void SampleWindow::installDrawFilter(SkCanvas* canvas) {
1342 canvas->setDrawFilter(new FlagsDrawFilter(fLCDState, fAAState,
1343 fFilterState, fHintingState))->unref();
1344 }
1345
postAnimatingEvent()1346 void SampleWindow::postAnimatingEvent() {
1347 if (fAnimating) {
1348 (new SkEvent(ANIMATING_EVENTTYPE, this->getSinkID()))->postDelay(ANIMATING_DELAY);
1349 }
1350 }
1351
onEvent(const SkEvent & evt)1352 bool SampleWindow::onEvent(const SkEvent& evt) {
1353 if (evt.isType(gUpdateWindowTitleEvtName)) {
1354 this->updateTitle();
1355 return true;
1356 }
1357 if (evt.isType(ANIMATING_EVENTTYPE)) {
1358 if (fAnimating) {
1359 this->nextSample();
1360 this->postAnimatingEvent();
1361 }
1362 return true;
1363 }
1364 if (evt.isType("replace-transition-view")) {
1365 this->loadView((SkView*)SkEventSink::FindSink(evt.getFast32()));
1366 return true;
1367 }
1368 if (evt.isType("set-curr-index")) {
1369 this->goToSample(evt.getFast32());
1370 return true;
1371 }
1372 if (isInvalEvent(evt)) {
1373 this->inval(NULL);
1374 return true;
1375 }
1376 int selected = -1;
1377 if (SkOSMenu::FindListIndex(evt, "Device Type", &selected)) {
1378 this->setDeviceType((DeviceType)selected);
1379 return true;
1380 }
1381 if (SkOSMenu::FindSwitchState(evt, "Pipe", &fUsePipe)) {
1382 #ifdef PIPE_NET
1383 if (!fUsePipe)
1384 gServer.disconnectAll();
1385 #endif
1386 (void)SampleView::SetUsePipe(curr_view(this), fUsePipe);
1387 this->updateTitle();
1388 this->inval(NULL);
1389 return true;
1390 }
1391 if (SkOSMenu::FindSwitchState(evt, "Slide Show", NULL)) {
1392 this->toggleSlideshow();
1393 return true;
1394 }
1395 if (SkOSMenu::FindTriState(evt, "AA", &fAAState) ||
1396 SkOSMenu::FindTriState(evt, "LCD", &fLCDState) ||
1397 SkOSMenu::FindTriState(evt, "Filter", &fFilterState) ||
1398 SkOSMenu::FindTriState(evt, "Hinting", &fHintingState) ||
1399 SkOSMenu::FindSwitchState(evt, "Clip", &fUseClip) ||
1400 SkOSMenu::FindSwitchState(evt, "Zoomer", &fShowZoomer) ||
1401 SkOSMenu::FindSwitchState(evt, "Magnify", &fMagnify) ||
1402 SkOSMenu::FindListIndex(evt, "Transition-Next", &fTransitionNext) ||
1403 SkOSMenu::FindListIndex(evt, "Transition-Prev", &fTransitionPrev)) {
1404 this->inval(NULL);
1405 this->updateTitle();
1406 return true;
1407 }
1408 if (SkOSMenu::FindSwitchState(evt, "Flip X", NULL)) {
1409 fFlipAxis ^= kFlipAxis_X;
1410 this->updateMatrix();
1411 return true;
1412 }
1413 if (SkOSMenu::FindSwitchState(evt, "Flip Y", NULL)) {
1414 fFlipAxis ^= kFlipAxis_Y;
1415 this->updateMatrix();
1416 return true;
1417 }
1418 if (SkOSMenu::FindAction(evt,"Save to PDF")) {
1419 this->saveToPdf();
1420 return true;
1421 }
1422 #ifdef DEBUGGER
1423 if (SkOSMenu::FindSwitchState(evt, "Debugger", &fDebugger)) {
1424 if (fDebugger) {
1425 fUsePipe = true;
1426 (void)SampleView::SetUsePipe(curr_view(this), true);
1427 } else {
1428 this->loadView(fSamples[fCurrIndex]());
1429 }
1430 this->inval(NULL);
1431 return true;
1432 }
1433 #endif
1434 return this->INHERITED::onEvent(evt);
1435 }
1436
onQuery(SkEvent * query)1437 bool SampleWindow::onQuery(SkEvent* query) {
1438 if (query->isType("get-slide-count")) {
1439 query->setFast32(fSamples.count());
1440 return true;
1441 }
1442 if (query->isType("get-slide-title")) {
1443 SkView* view = (*fSamples[query->getFast32()])();
1444 SkEvent evt(gTitleEvtName);
1445 if (view->doQuery(&evt)) {
1446 query->setString("title", evt.findString(gTitleEvtName));
1447 }
1448 SkSafeUnref(view);
1449 return true;
1450 }
1451 if (query->isType("use-fast-text")) {
1452 SkEvent evt(gFastTextEvtName);
1453 return curr_view(this)->doQuery(&evt);
1454 }
1455 if (query->isType("ignore-window-bitmap")) {
1456 query->setFast32(this->getGrContext() != NULL);
1457 return true;
1458 }
1459 return this->INHERITED::onQuery(query);
1460 }
1461
cleanup_for_filename(SkString * name)1462 static void cleanup_for_filename(SkString* name) {
1463 char* str = name->writable_str();
1464 for (size_t i = 0; i < name->size(); i++) {
1465 switch (str[i]) {
1466 case ':': str[i] = '-'; break;
1467 case '/': str[i] = '-'; break;
1468 case ' ': str[i] = '_'; break;
1469 default: break;
1470 }
1471 }
1472 }
1473
onHandleChar(SkUnichar uni)1474 bool SampleWindow::onHandleChar(SkUnichar uni) {
1475 {
1476 SkView* view = curr_view(this);
1477 if (view) {
1478 SkEvent evt(gCharEvtName);
1479 evt.setFast32(uni);
1480 if (view->doQuery(&evt)) {
1481 return true;
1482 }
1483 }
1484 }
1485
1486 int dx = 0xFF;
1487 int dy = 0xFF;
1488
1489 switch (uni) {
1490 case '5': dx = 0; dy = 0; break;
1491 case '8': dx = 0; dy = -1; break;
1492 case '6': dx = 1; dy = 0; break;
1493 case '2': dx = 0; dy = 1; break;
1494 case '4': dx = -1; dy = 0; break;
1495 case '7': dx = -1; dy = -1; break;
1496 case '9': dx = 1; dy = -1; break;
1497 case '3': dx = 1; dy = 1; break;
1498 case '1': dx = -1; dy = 1; break;
1499
1500 default:
1501 break;
1502 }
1503
1504 if (0xFF != dx && 0xFF != dy) {
1505 if ((dx | dy) == 0) {
1506 fScrollTestX = fScrollTestY = 0;
1507 } else {
1508 fScrollTestX += dx;
1509 fScrollTestY += dy;
1510 }
1511 this->inval(NULL);
1512 return true;
1513 }
1514
1515 switch (uni) {
1516 case 'f':
1517 // only
1518 toggleFPS();
1519 break;
1520 case 'g':
1521 fRequestGrabImage = true;
1522 this->inval(NULL);
1523 break;
1524 case 'i':
1525 this->zoomIn();
1526 break;
1527 case 'o':
1528 this->zoomOut();
1529 break;
1530 case 'r':
1531 fRotate = !fRotate;
1532 this->inval(NULL);
1533 this->updateTitle();
1534 return true;
1535 case 'k':
1536 fPerspAnim = !fPerspAnim;
1537 this->inval(NULL);
1538 this->updateTitle();
1539 return true;
1540 case '\\':
1541 if (fDevManager->supportsDeviceType(kNullGPU_DeviceType)) {
1542 fDeviceType= kNullGPU_DeviceType;
1543 this->inval(NULL);
1544 this->updateTitle();
1545 }
1546 return true;
1547 case 'p':
1548 {
1549 GrContext* grContext = this->getGrContext();
1550 if (grContext) {
1551 size_t cacheBytes = grContext->getGpuTextureCacheBytes();
1552 grContext->freeGpuResources();
1553 SkDebugf("Purged %d bytes from the GPU resource cache.\n",
1554 cacheBytes);
1555 }
1556 }
1557 return true;
1558 case 's':
1559 fScale = !fScale;
1560 this->inval(NULL);
1561 this->updateTitle();
1562 return true;
1563 default:
1564 break;
1565 }
1566
1567 if (fAppMenu.handleKeyEquivalent(uni)|| fSlideMenu.handleKeyEquivalent(uni)) {
1568 this->onUpdateMenu(&fAppMenu);
1569 this->onUpdateMenu(&fSlideMenu);
1570 return true;
1571 }
1572 return this->INHERITED::onHandleChar(uni);
1573 }
1574
setDeviceType(DeviceType type)1575 void SampleWindow::setDeviceType(DeviceType type) {
1576 if (type != fDeviceType && fDevManager->supportsDeviceType(fDeviceType))
1577 fDeviceType = type;
1578 this->updateTitle();
1579 this->inval(NULL);
1580 }
1581
toggleSlideshow()1582 void SampleWindow::toggleSlideshow() {
1583 fAnimating = !fAnimating;
1584 this->postAnimatingEvent();
1585 this->updateTitle();
1586 }
1587
toggleRendering()1588 void SampleWindow::toggleRendering() {
1589 DeviceType origDevType = fDeviceType;
1590 do {
1591 fDeviceType = cycle_devicetype(fDeviceType);
1592 } while (origDevType != fDeviceType &&
1593 !fDevManager->supportsDeviceType(fDeviceType));
1594 this->updateTitle();
1595 this->inval(NULL);
1596 }
1597
toggleFPS()1598 void SampleWindow::toggleFPS() {
1599 fMeasureFPS = !fMeasureFPS;
1600 this->updateTitle();
1601 this->inval(NULL);
1602 }
1603
1604 #include "SkDumpCanvas.h"
1605
onHandleKey(SkKey key)1606 bool SampleWindow::onHandleKey(SkKey key) {
1607 {
1608 SkView* view = curr_view(this);
1609 if (view) {
1610 SkEvent evt(gKeyEvtName);
1611 evt.setFast32(key);
1612 if (view->doQuery(&evt)) {
1613 return true;
1614 }
1615 }
1616 }
1617 switch (key) {
1618 case kRight_SkKey:
1619 if (this->nextSample()) {
1620 return true;
1621 }
1622 break;
1623 case kLeft_SkKey:
1624 toggleRendering();
1625 return true;
1626 case kUp_SkKey:
1627 if (USE_ARROWS_FOR_ZOOM) {
1628 this->changeZoomLevel(1.f);
1629 } else {
1630 fNClip = !fNClip;
1631 this->inval(NULL);
1632 this->updateTitle();
1633 }
1634 return true;
1635 case kDown_SkKey:
1636 if (USE_ARROWS_FOR_ZOOM) {
1637 this->changeZoomLevel(-1.f);
1638 } else {
1639 this->setConfig(cycle_configs(this->getBitmap().config()));
1640 this->updateTitle();
1641 }
1642 return true;
1643 case kOK_SkKey: {
1644 SkString title;
1645 if (curr_title(this, &title)) {
1646 writeTitleToPrefs(title.c_str());
1647 }
1648 return true;
1649 }
1650 case kBack_SkKey:
1651 this->showOverview();
1652 return true;
1653 default:
1654 break;
1655 }
1656 return this->INHERITED::onHandleKey(key);
1657 }
1658
1659 ///////////////////////////////////////////////////////////////////////////////
1660
1661 static const char gGestureClickType[] = "GestureClickType";
1662
onDispatchClick(int x,int y,Click::State state,void * owner)1663 bool SampleWindow::onDispatchClick(int x, int y, Click::State state,
1664 void* owner) {
1665 if (Click::kMoved_State == state) {
1666 updatePointer(x, y);
1667 }
1668 int w = SkScalarRound(this->width());
1669 int h = SkScalarRound(this->height());
1670
1671 // check for the resize-box
1672 if (w - x < 16 && h - y < 16) {
1673 return false; // let the OS handle the click
1674 }
1675 else if (fMagnify) {
1676 //it's only necessary to update the drawing if there's a click
1677 this->inval(NULL);
1678 return false; //prevent dragging while magnify is enabled
1679 }
1680 else {
1681 return this->INHERITED::onDispatchClick(x, y, state, owner);
1682 }
1683 }
1684
1685 class GestureClick : public SkView::Click {
1686 public:
GestureClick(SkView * target)1687 GestureClick(SkView* target) : SkView::Click(target) {
1688 this->setType(gGestureClickType);
1689 }
1690
IsGesture(Click * click)1691 static bool IsGesture(Click* click) {
1692 return click->isType(gGestureClickType);
1693 }
1694 };
1695
onFindClickHandler(SkScalar x,SkScalar y)1696 SkView::Click* SampleWindow::onFindClickHandler(SkScalar x, SkScalar y) {
1697 return new GestureClick(this);
1698 }
1699
onClick(Click * click)1700 bool SampleWindow::onClick(Click* click) {
1701 if (GestureClick::IsGesture(click)) {
1702 float x = static_cast<float>(click->fICurr.fX);
1703 float y = static_cast<float>(click->fICurr.fY);
1704
1705 switch (click->fState) {
1706 case SkView::Click::kDown_State:
1707 fGesture.touchBegin(click->fOwner, x, y);
1708 break;
1709 case SkView::Click::kMoved_State:
1710 fGesture.touchMoved(click->fOwner, x, y);
1711 this->updateMatrix();
1712 break;
1713 case SkView::Click::kUp_State:
1714 fGesture.touchEnd(click->fOwner);
1715 this->updateMatrix();
1716 break;
1717 }
1718 return true;
1719 }
1720 return false;
1721 }
1722
1723 ///////////////////////////////////////////////////////////////////////////////
1724
loadView(SkView * view)1725 void SampleWindow::loadView(SkView* view) {
1726 SkView::F2BIter iter(this);
1727 SkView* prev = iter.next();
1728 if (prev) {
1729 prev->detachFromParent();
1730 }
1731
1732 view->setVisibleP(true);
1733 view->setClipToBounds(false);
1734 this->attachChildToFront(view)->unref();
1735 view->setSize(this->width(), this->height());
1736
1737 //repopulate the slide menu when a view is loaded
1738 fSlideMenu.reset();
1739 #ifdef DEBUGGER
1740 if (!is_debugger(view) && !is_overview(view) && !is_transition(view) && fDebugger) {
1741 //Force Pipe to be on if using debugger
1742 fUsePipe = true;
1743 }
1744 #endif
1745 (void)SampleView::SetUsePipe(view, fUsePipe);
1746 if (SampleView::IsSampleView(view))
1747 ((SampleView*)view)->requestMenu(&fSlideMenu);
1748 this->onUpdateMenu(&fSlideMenu);
1749 this->updateTitle();
1750 }
1751
1752 static const char* gConfigNames[] = {
1753 "unknown config",
1754 "A1",
1755 "A8",
1756 "Index8",
1757 "565",
1758 "4444",
1759 "8888"
1760 };
1761
configToString(SkBitmap::Config c)1762 static const char* configToString(SkBitmap::Config c) {
1763 return gConfigNames[c];
1764 }
1765
1766 static const char* gDeviceTypePrefix[] = {
1767 "raster: ",
1768 "picture: ",
1769 "opengl: ",
1770 "null-gl: "
1771 };
1772
trystate_str(SkOSMenu::TriState state,const char trueStr[],const char falseStr[])1773 static const char* trystate_str(SkOSMenu::TriState state,
1774 const char trueStr[], const char falseStr[]) {
1775 if (SkOSMenu::kOnState == state) {
1776 return trueStr;
1777 } else if (SkOSMenu::kOffState == state) {
1778 return falseStr;
1779 }
1780 return NULL;
1781 }
1782
updateTitle()1783 void SampleWindow::updateTitle() {
1784 SkView* view = curr_view(this);
1785
1786 SkString title;
1787 if (!curr_title(this, &title)) {
1788 title.set("<unknown>");
1789 }
1790
1791 title.prepend(gDeviceTypePrefix[fDeviceType]);
1792
1793 title.prepend(" ");
1794 title.prepend(configToString(this->getBitmap().config()));
1795
1796 if (fAnimating) {
1797 title.prepend("<A> ");
1798 }
1799 if (fScale) {
1800 title.prepend("<S> ");
1801 }
1802 if (fRotate) {
1803 title.prepend("<R> ");
1804 }
1805 if (fNClip) {
1806 title.prepend("<C> ");
1807 }
1808 if (fPerspAnim) {
1809 title.prepend("<K> ");
1810 }
1811
1812 title.prepend(trystate_str(fLCDState, "LCD ", "lcd "));
1813 title.prepend(trystate_str(fAAState, "AA ", "aa "));
1814 title.prepend(trystate_str(fFilterState, "H ", "h "));
1815 title.prepend(fFlipAxis & kFlipAxis_X ? "X " : NULL);
1816 title.prepend(fFlipAxis & kFlipAxis_Y ? "Y " : NULL);
1817
1818 if (fZoomLevel) {
1819 title.prependf("{%.2f} ", SkScalarToFloat(fZoomLevel));
1820 }
1821
1822 if (fMeasureFPS) {
1823 title.appendf(" %6.1f ms", fMeasureFPS_Time / (float)FPS_REPEAT_MULTIPLIER);
1824 }
1825 if (fUsePipe && SampleView::IsSampleView(view)) {
1826 title.prepend("<P> ");
1827 }
1828 if (SampleView::IsSampleView(view)) {
1829 title.prepend("! ");
1830 }
1831
1832 this->setTitle(title.c_str());
1833 }
1834
onSizeChange()1835 void SampleWindow::onSizeChange() {
1836 this->INHERITED::onSizeChange();
1837
1838 SkView::F2BIter iter(this);
1839 SkView* view = iter.next();
1840 view->setSize(this->width(), this->height());
1841
1842 // rebuild our clippath
1843 {
1844 const SkScalar W = this->width();
1845 const SkScalar H = this->height();
1846
1847 fClipPath.reset();
1848 #if 0
1849 for (SkScalar y = SK_Scalar1; y < H; y += SkIntToScalar(32)) {
1850 SkRect r;
1851 r.set(SK_Scalar1, y, SkIntToScalar(30), y + SkIntToScalar(30));
1852 for (; r.fLeft < W; r.offset(SkIntToScalar(32), 0))
1853 fClipPath.addRect(r);
1854 }
1855 #else
1856 SkRect r;
1857 r.set(0, 0, W, H);
1858 fClipPath.addRect(r, SkPath::kCCW_Direction);
1859 r.set(W/4, H/4, W*3/4, H*3/4);
1860 fClipPath.addRect(r, SkPath::kCW_Direction);
1861 #endif
1862 }
1863
1864 fZoomCenterX = SkScalarHalf(this->width());
1865 fZoomCenterY = SkScalarHalf(this->height());
1866
1867 #ifdef SK_BUILD_FOR_ANDROID
1868 // FIXME: The first draw after a size change does not work on Android, so
1869 // we post an invalidate.
1870 this->postInvalDelay();
1871 #endif
1872 this->updateTitle(); // to refresh our config
1873 fDevManager->windowSizeChanged(this);
1874 }
1875
1876 ///////////////////////////////////////////////////////////////////////////////
1877
1878 static const char is_sample_view_tag[] = "sample-is-sample-view";
1879 static const char repeat_count_tag[] = "sample-set-repeat-count";
1880 static const char set_use_pipe_tag[] = "sample-set-use-pipe";
1881
IsSampleView(SkView * view)1882 bool SampleView::IsSampleView(SkView* view) {
1883 SkEvent evt(is_sample_view_tag);
1884 return view->doQuery(&evt);
1885 }
1886
SetRepeatDraw(SkView * view,int count)1887 bool SampleView::SetRepeatDraw(SkView* view, int count) {
1888 SkEvent evt(repeat_count_tag);
1889 evt.setFast32(count);
1890 return view->doEvent(evt);
1891 }
1892
SetUsePipe(SkView * view,bool pred)1893 bool SampleView::SetUsePipe(SkView* view, bool pred) {
1894 SkEvent evt(set_use_pipe_tag);
1895 evt.setFast32(pred);
1896 return view->doEvent(evt);
1897 }
1898
onEvent(const SkEvent & evt)1899 bool SampleView::onEvent(const SkEvent& evt) {
1900 if (evt.isType(repeat_count_tag)) {
1901 fRepeatCount = evt.getFast32();
1902 return true;
1903 }
1904 if (evt.isType(set_use_pipe_tag)) {
1905 fUsePipe = !!evt.getFast32();
1906 return true;
1907 }
1908 return this->INHERITED::onEvent(evt);
1909 }
1910
onQuery(SkEvent * evt)1911 bool SampleView::onQuery(SkEvent* evt) {
1912 if (evt->isType(is_sample_view_tag)) {
1913 return true;
1914 }
1915 return this->INHERITED::onQuery(evt);
1916 }
1917
1918 #ifdef TEST_GPIPE
1919 #include "SkGPipe.h"
1920
1921 class SimplePC : public SkGPipeController {
1922 public:
1923 SimplePC(SkCanvas* target);
1924 ~SimplePC();
1925
1926 /**
1927 * User this method to halt/restart pipe
1928 */
setWriteToPipe(bool writeToPipe)1929 void setWriteToPipe(bool writeToPipe) { fWriteToPipe = writeToPipe; }
1930 virtual void* requestBlock(size_t minRequest, size_t* actual);
1931 virtual void notifyWritten(size_t bytes);
1932
1933 private:
1934 SkGPipeReader fReader;
1935 void* fBlock;
1936 size_t fBlockSize;
1937 size_t fBytesWritten;
1938 int fAtomsWritten;
1939 SkGPipeReader::Status fStatus;
1940 bool fWriteToPipe;
1941
1942 size_t fTotalWritten;
1943 };
1944
SimplePC(SkCanvas * target)1945 SimplePC::SimplePC(SkCanvas* target) : fReader(target) {
1946 fBlock = NULL;
1947 fBlockSize = fBytesWritten = 0;
1948 fStatus = SkGPipeReader::kDone_Status;
1949 fTotalWritten = 0;
1950 fAtomsWritten = 0;
1951 fWriteToPipe = true;
1952 }
1953
~SimplePC()1954 SimplePC::~SimplePC() {
1955 // SkASSERT(SkGPipeReader::kDone_Status == fStatus);
1956 if (fTotalWritten) {
1957 if (fWriteToPipe) {
1958 SkDebugf("--- %d bytes %d atoms, status %d\n", fTotalWritten,
1959 fAtomsWritten, fStatus);
1960 #ifdef PIPE_FILE
1961 //File is open in append mode
1962 FILE* f = fopen(FILE_PATH, "ab");
1963 SkASSERT(f != NULL);
1964 fwrite((const char*)fBlock + fBytesWritten, 1, bytes, f);
1965 fclose(f);
1966 #endif
1967 #ifdef PIPE_NET
1968 if (fAtomsWritten > 1 && fTotalWritten > 4) { //ignore done
1969 gServer.acceptConnections();
1970 gServer.writePacket(fBlock, fTotalWritten);
1971 }
1972 #endif
1973 #ifdef DEBUGGER
1974 gTempDataStore.reset();
1975 gTempDataStore.append(fTotalWritten, (const char*)fBlock);
1976 #endif
1977 }
1978 }
1979 sk_free(fBlock);
1980 }
1981
requestBlock(size_t minRequest,size_t * actual)1982 void* SimplePC::requestBlock(size_t minRequest, size_t* actual) {
1983 sk_free(fBlock);
1984
1985 fBlockSize = minRequest * 4;
1986 fBlock = sk_malloc_throw(fBlockSize);
1987 fBytesWritten = 0;
1988 *actual = fBlockSize;
1989 return fBlock;
1990 }
1991
notifyWritten(size_t bytes)1992 void SimplePC::notifyWritten(size_t bytes) {
1993 SkASSERT(fBytesWritten + bytes <= fBlockSize);
1994 fStatus = fReader.playback((const char*)fBlock + fBytesWritten, bytes);
1995 SkASSERT(SkGPipeReader::kError_Status != fStatus);
1996 fBytesWritten += bytes;
1997 fTotalWritten += bytes;
1998
1999 fAtomsWritten += 1;
2000 }
2001
2002 #endif
2003
draw(SkCanvas * canvas)2004 void SampleView::draw(SkCanvas* canvas) {
2005 #ifdef TEST_GPIPE
2006 if (fUsePipe) {
2007 SkGPipeWriter writer;
2008 SimplePC controller(canvas);
2009 uint32_t flags = SkGPipeWriter::kCrossProcess_Flag;
2010 canvas = writer.startRecording(&controller, flags);
2011 //Must draw before controller goes out of scope and sends data
2012 this->INHERITED::draw(canvas);
2013 //explicitly end recording to ensure writer is flushed before the memory
2014 //is freed in the deconstructor of the controller
2015 writer.endRecording();
2016 controller.setWriteToPipe(fUsePipe);
2017 }
2018 else
2019 this->INHERITED::draw(canvas);
2020 #else
2021 this->INHERITED::draw(canvas);
2022 #endif
2023 }
onDraw(SkCanvas * canvas)2024 void SampleView::onDraw(SkCanvas* canvas) {
2025 this->onDrawBackground(canvas);
2026
2027 for (int i = 0; i < fRepeatCount; i++) {
2028 SkAutoCanvasRestore acr(canvas, true);
2029 this->onDrawContent(canvas);
2030 }
2031 }
2032
onDrawBackground(SkCanvas * canvas)2033 void SampleView::onDrawBackground(SkCanvas* canvas) {
2034 canvas->drawColor(fBGColor);
2035 }
2036
2037 ///////////////////////////////////////////////////////////////////////////////
2038
SkTBSort(T array[],int count)2039 template <typename T> void SkTBSort(T array[], int count) {
2040 for (int i = 1; i < count - 1; i++) {
2041 bool didSwap = false;
2042 for (int j = count - 1; j > i; --j) {
2043 if (array[j] < array[j-1]) {
2044 T tmp(array[j-1]);
2045 array[j-1] = array[j];
2046 array[j] = tmp;
2047 didSwap = true;
2048 }
2049 }
2050 if (!didSwap) {
2051 break;
2052 }
2053 }
2054
2055 for (int k = 0; k < count - 1; k++) {
2056 SkASSERT(!(array[k+1] < array[k]));
2057 }
2058 }
2059
2060 #include "SkRandom.h"
2061
rand_rect(SkIRect * rect,SkRandom & rand)2062 static void rand_rect(SkIRect* rect, SkRandom& rand) {
2063 int bits = 8;
2064 int shift = 32 - bits;
2065 rect->set(rand.nextU() >> shift, rand.nextU() >> shift,
2066 rand.nextU() >> shift, rand.nextU() >> shift);
2067 rect->sort();
2068 }
2069
dumpRect(const SkIRect & r)2070 static void dumpRect(const SkIRect& r) {
2071 SkDebugf(" { %d, %d, %d, %d },\n",
2072 r.fLeft, r.fTop,
2073 r.fRight, r.fBottom);
2074 }
2075
test_rects(const SkIRect rect[],int count)2076 static void test_rects(const SkIRect rect[], int count) {
2077 SkRegion rgn0, rgn1;
2078
2079 for (int i = 0; i < count; i++) {
2080 rgn0.op(rect[i], SkRegion::kUnion_Op);
2081 // dumpRect(rect[i]);
2082 }
2083 rgn1.setRects(rect, count);
2084
2085 if (rgn0 != rgn1) {
2086 SkDebugf("\n");
2087 for (int i = 0; i < count; i++) {
2088 dumpRect(rect[i]);
2089 }
2090 SkDebugf("\n");
2091 }
2092 }
2093
test()2094 static void test() {
2095 size_t i;
2096
2097 const SkIRect r0[] = {
2098 { 0, 0, 1, 1 },
2099 { 2, 2, 3, 3 },
2100 };
2101 const SkIRect r1[] = {
2102 { 0, 0, 1, 3 },
2103 { 1, 1, 2, 2 },
2104 { 2, 0, 3, 3 },
2105 };
2106 const SkIRect r2[] = {
2107 { 0, 0, 1, 2 },
2108 { 2, 1, 3, 3 },
2109 { 4, 0, 5, 1 },
2110 { 6, 0, 7, 4 },
2111 };
2112
2113 static const struct {
2114 const SkIRect* fRects;
2115 int fCount;
2116 } gRecs[] = {
2117 { r0, SK_ARRAY_COUNT(r0) },
2118 { r1, SK_ARRAY_COUNT(r1) },
2119 { r2, SK_ARRAY_COUNT(r2) },
2120 };
2121
2122 for (i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
2123 test_rects(gRecs[i].fRects, gRecs[i].fCount);
2124 }
2125
2126 SkRandom rand;
2127 for (i = 0; i < 10000; i++) {
2128 SkRegion rgn0, rgn1;
2129
2130 const int N = 8;
2131 SkIRect rect[N];
2132 for (int j = 0; j < N; j++) {
2133 rand_rect(&rect[j], rand);
2134 }
2135 test_rects(rect, N);
2136 }
2137 }
2138
create_sk_window(void * hwnd,int argc,char ** argv)2139 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
2140 // test();
2141 return new SampleWindow(hwnd, argc, argv, NULL);
2142 }
2143
get_preferred_size(int * x,int * y,int * width,int * height)2144 void get_preferred_size(int* x, int* y, int* width, int* height) {
2145 *x = 10;
2146 *y = 50;
2147 *width = 640;
2148 *height = 480;
2149 }
2150
application_init()2151 void application_init() {
2152 // setenv("ANDROID_ROOT", "../../../data", 0);
2153 #ifdef SK_BUILD_FOR_MAC
2154 setenv("ANDROID_ROOT", "/android/device/data", 0);
2155 #endif
2156 SkGraphics::Init();
2157 SkEvent::Init();
2158 }
2159
application_term()2160 void application_term() {
2161 SkEvent::Term();
2162 SkGraphics::Term();
2163 }
2164