SampleApp.cpp revision e32b5837c3f35b80502759f3de3e8cadf6625f4e
1#include "SkCanvas.h" 2#include "SkDevice.h" 3#include "SkGpuCanvas.h" 4#include "SkGraphics.h" 5#include "SkImageEncoder.h" 6#include "SkPaint.h" 7#include "SkPicture.h" 8#include "SkStream.h" 9#include "SkTime.h" 10#include "SkWindow.h" 11 12#include "SampleCode.h" 13#include "GrContext.h" 14#include "SkTouchGesture.h" 15#include "SkTypeface.h" 16 17#define TEST_GPIPEx 18 19#ifdef TEST_GPIPE 20#define PIPE_FILE 21#define FILE_PATH "/path/to/drawing.data" 22#endif 23 24#define USE_ARROWS_FOR_ZOOM true 25//#define DEFAULT_TO_GPU 26 27extern SkView* create_overview(int, const SkViewFactory[]); 28 29#define SK_SUPPORT_GL 30 31#define ANIMATING_EVENTTYPE "nextSample" 32#define ANIMATING_DELAY 750 33 34#ifdef SK_DEBUG 35 #define FPS_REPEAT_MULTIPLIER 1 36#else 37 #define FPS_REPEAT_MULTIPLIER 10 38#endif 39#define FPS_REPEAT_COUNT (10 * FPS_REPEAT_MULTIPLIER) 40 41#ifdef SK_SUPPORT_GL 42 #include "GrGLConfig.h" 43#endif 44 45/////////////// 46static const char view_inval_msg[] = "view-inval-msg"; 47 48static void postInvalDelay(SkEventSinkID sinkID) { 49 SkEvent* evt = new SkEvent(view_inval_msg); 50 evt->post(sinkID, 1); 51} 52 53static bool isInvalEvent(const SkEvent& evt) { 54 return evt.isType(view_inval_msg); 55} 56////////////////// 57 58SkViewRegister* SkViewRegister::gHead; 59SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) { 60 static bool gOnce; 61 if (!gOnce) { 62 gHead = NULL; 63 gOnce = true; 64 } 65 66 fChain = gHead; 67 gHead = this; 68} 69 70#if defined(SK_SUPPORT_GL) 71 #define SK_USE_SHADERS 72#endif 73 74#ifdef SK_BUILD_FOR_MAC 75#include <CoreFoundation/CoreFoundation.h> 76#include <CoreFoundation/CFURLAccess.h> 77 78static void testpdf() { 79 CFStringRef path = CFStringCreateWithCString(NULL, "/test.pdf", 80 kCFStringEncodingUTF8); 81 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, 82 kCFURLPOSIXPathStyle, 83 false); 84 CFRelease(path); 85 CGRect box = CGRectMake(0, 0, 8*72, 10*72); 86 CGContextRef cg = CGPDFContextCreateWithURL(url, &box, NULL); 87 CFRelease(url); 88 89 CGContextBeginPage(cg, &box); 90 CGRect r = CGRectMake(10, 10, 40 + 0.5, 50 + 0.5); 91 CGContextFillEllipseInRect(cg, r); 92 CGContextEndPage(cg); 93 CGContextRelease(cg); 94 95 if (false) { 96 SkBitmap bm; 97 bm.setConfig(SkBitmap::kA8_Config, 64, 64); 98 bm.allocPixels(); 99 bm.eraseColor(0); 100 101 SkCanvas canvas(bm); 102 103 } 104} 105#endif 106 107////////////////////////////////////////////////////////////////////////////// 108 109enum FlipAxisEnum { 110 kFlipAxis_X = (1 << 0), 111 kFlipAxis_Y = (1 << 1) 112}; 113 114enum SkTriState { 115 kFalse_SkTriState, 116 kTrue_SkTriState, 117 kUnknown_SkTriState, 118}; 119 120static SkTriState cycle_tristate(SkTriState state) { 121 static const SkTriState gCycle[] = { 122 /* kFalse_SkTriState -> */ kUnknown_SkTriState, 123 /* kTrue_SkTriState -> */ kFalse_SkTriState, 124 /* kUnknown_SkTriState -> */ kTrue_SkTriState, 125 }; 126 return gCycle[state]; 127} 128 129#include "SkDrawFilter.h" 130 131class FlagsDrawFilter : public SkDrawFilter { 132public: 133 FlagsDrawFilter(SkTriState lcd, SkTriState aa, SkTriState filter, 134 SkTriState hinting) : 135 fLCDState(lcd), fAAState(aa), fFilterState(filter), fHintingState(hinting) {} 136 137 virtual void filter(SkPaint* paint, Type t) { 138 if (kText_Type == t && kUnknown_SkTriState != fLCDState) { 139 paint->setLCDRenderText(kTrue_SkTriState == fLCDState); 140 } 141 if (kUnknown_SkTriState != fAAState) { 142 paint->setAntiAlias(kTrue_SkTriState == fAAState); 143 } 144 if (kUnknown_SkTriState != fFilterState) { 145 paint->setFilterBitmap(kTrue_SkTriState == fFilterState); 146 } 147 if (kUnknown_SkTriState != fHintingState) { 148 paint->setHinting(kTrue_SkTriState == fHintingState ? 149 SkPaint::kNormal_Hinting : 150 SkPaint::kSlight_Hinting); 151 } 152 } 153 154private: 155 SkTriState fLCDState; 156 SkTriState fAAState; 157 SkTriState fFilterState; 158 SkTriState fHintingState; 159}; 160 161////////////////////////////////////////////////////////////////////////////// 162 163#define MAX_ZOOM_LEVEL 8 164#define MIN_ZOOM_LEVEL -8 165 166static const char gCharEvtName[] = "SampleCode_Char_Event"; 167static const char gKeyEvtName[] = "SampleCode_Key_Event"; 168static const char gTitleEvtName[] = "SampleCode_Title_Event"; 169static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event"; 170static const char gFastTextEvtName[] = "SampleCode_FastText_Event"; 171 172bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) { 173 if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) { 174 if (outUni) { 175 *outUni = evt.getFast32(); 176 } 177 return true; 178 } 179 return false; 180} 181 182bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) { 183 if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) { 184 if (outKey) { 185 *outKey = (SkKey)evt.getFast32(); 186 } 187 return true; 188 } 189 return false; 190} 191 192bool SampleCode::TitleQ(const SkEvent& evt) { 193 return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1); 194} 195 196void SampleCode::TitleR(SkEvent* evt, const char title[]) { 197 SkASSERT(evt && TitleQ(*evt)); 198 evt->setString(gTitleEvtName, title); 199} 200 201bool SampleCode::PrefSizeQ(const SkEvent& evt) { 202 return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1); 203} 204 205void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) { 206 SkASSERT(evt && PrefSizeQ(*evt)); 207 SkScalar size[2]; 208 size[0] = width; 209 size[1] = height; 210 evt->setScalars(gPrefSizeEvtName, 2, size); 211} 212 213bool SampleCode::FastTextQ(const SkEvent& evt) { 214 return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1); 215} 216 217/////////////////////////////////////////////////////////////////////////////// 218 219static SkMSec gAnimTime; 220static SkMSec gAnimTimePrev; 221 222SkMSec SampleCode::GetAnimTime() { return gAnimTime; } 223SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; } 224SkScalar SampleCode::GetAnimSecondsDelta() { 225 return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0); 226} 227 228SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) { 229 // since gAnimTime can be up to 32 bits, we can't convert it to a float 230 // or we'll lose the low bits. Hence we use doubles for the intermediate 231 // calculations 232 double seconds = (double)gAnimTime / 1000.0; 233 double value = SkScalarToDouble(speed) * seconds; 234 if (period) { 235 value = ::fmod(value, SkScalarToDouble(period)); 236 } 237 return SkDoubleToScalar(value); 238} 239 240////////////////////////////////////////////////////////////////////////////// 241 242static SkView* curr_view(SkWindow* wind) { 243 SkView::F2BIter iter(wind); 244 return iter.next(); 245} 246 247class SampleWindow : public SkOSWindow { 248 SkTDArray<SkViewFactory> fSamples; 249public: 250 SampleWindow(void* hwnd); 251 virtual ~SampleWindow(); 252 253 virtual void draw(SkCanvas* canvas); 254#ifdef ANDROID 255 virtual bool drawsToHardware() { return fCanvasType == kGPU_CanvasType; } 256 virtual bool setGrContext(GrContext*); 257 virtual GrContext* getGrContext(); 258#endif 259 260protected: 261 virtual void onDraw(SkCanvas* canvas); 262 virtual bool onHandleKey(SkKey key); 263 virtual bool onHandleChar(SkUnichar); 264 virtual void onSizeChange(); 265 266 virtual SkCanvas* beforeChildren(SkCanvas*); 267 virtual void afterChildren(SkCanvas*); 268 virtual void beforeChild(SkView* child, SkCanvas* canvas); 269 virtual void afterChild(SkView* child, SkCanvas* canvas); 270 271 virtual bool onEvent(const SkEvent& evt); 272 virtual bool onQuery(SkEvent* evt); 273 274 virtual bool onDispatchClick(int x, int y, Click::State); 275 virtual bool onClick(Click* click); 276 virtual Click* onFindClickHandler(SkScalar x, SkScalar y); 277 278#if 0 279 virtual bool handleChar(SkUnichar uni); 280 virtual bool handleEvent(const SkEvent& evt); 281 virtual bool handleKey(SkKey key); 282 virtual bool handleKeyUp(SkKey key); 283 virtual bool onHandleKeyUp(SkKey key); 284#endif 285 286private: 287 int fCurrIndex; 288 289 SkPicture* fPicture; 290 SkGpuCanvas* fGpuCanvas; 291 GrContext* fGrContext; 292 SkPath fClipPath; 293 294 SkTouchGesture fGesture; 295 SkScalar fZoomLevel; 296 SkScalar fZoomScale; 297 298 enum CanvasType { 299 kRaster_CanvasType, 300 kPicture_CanvasType, 301 kGPU_CanvasType 302 }; 303 CanvasType fCanvasType; 304 305 bool fUseClip; 306 bool fNClip; 307 bool fRepeatDrawing; 308 bool fAnimating; 309 bool fRotate; 310 bool fScale; 311 bool fRequestGrabImage; 312 bool fUsePipe; 313 bool fMeasureFPS; 314 SkMSec fMeasureFPS_Time; 315 316 // The following are for the 'fatbits' drawing 317 // Latest position of the mouse. 318 int fMouseX, fMouseY; 319 int fFatBitsScale; 320 // Used by the text showing position and color values. 321 SkTypeface* fTypeface; 322 bool fShowZoomer; 323 324 SkTriState fLCDState; 325 SkTriState fAAState; 326 SkTriState fFilterState; 327 SkTriState fHintingState; 328 unsigned fFlipAxis; 329 330 int fScrollTestX, fScrollTestY; 331 332 bool make3DReady(); 333#ifdef ANDROID 334 virtual 335#endif 336 void changeZoomLevel(float delta); 337 338 void loadView(SkView*); 339 void updateTitle(); 340 bool nextSample(); 341 342 void toggleZoomer(); 343 bool zoomIn(); 344 bool zoomOut(); 345 void updatePointer(int x, int y); 346 void showZoomer(SkCanvas* canvas); 347 348 void postAnimatingEvent() { 349 if (fAnimating) { 350 SkEvent* evt = new SkEvent(ANIMATING_EVENTTYPE); 351 evt->post(this->getSinkID(), ANIMATING_DELAY); 352 } 353 } 354 355 356 static CanvasType cycle_canvastype(CanvasType); 357 358 typedef SkOSWindow INHERITED; 359}; 360 361#ifdef ANDROID 362bool SampleWindow::setGrContext(GrContext* context) 363{ 364 if (fGrContext) { 365 fGrContext->unref(); 366 } 367 fGrContext = context; 368 fGrContext->ref(); 369 return true; 370} 371 372GrContext* SampleWindow::getGrContext() 373{ 374 return fGrContext; 375} 376#endif 377 378bool SampleWindow::zoomIn() 379{ 380 // Arbitrarily decided 381 if (fFatBitsScale == 25) return false; 382 fFatBitsScale++; 383 this->inval(NULL); 384 return true; 385} 386 387bool SampleWindow::zoomOut() 388{ 389 if (fFatBitsScale == 1) return false; 390 fFatBitsScale--; 391 this->inval(NULL); 392 return true; 393} 394 395void SampleWindow::toggleZoomer() 396{ 397 fShowZoomer = !fShowZoomer; 398 this->inval(NULL); 399} 400 401void SampleWindow::updatePointer(int x, int y) 402{ 403 fMouseX = x; 404 fMouseY = y; 405 if (fShowZoomer) { 406 this->inval(NULL); 407 } 408} 409 410bool SampleWindow::make3DReady() { 411 412#if defined(SK_SUPPORT_GL) 413 if (attachGL()) { 414 if (NULL != fGrContext) { 415 // various gr lifecycle tests 416 #if 0 417 fGrContext->freeGpuResources(); 418 #elif 0 419 // this will leak resources. 420 fGrContext->contextLost(); 421 #elif 0 422 GrAssert(1 == fGrContext->refcnt()); 423 fGrContext->unref(); 424 fGrContext = NULL; 425 #endif 426 } 427 428 if (NULL == fGrContext) { 429 #if defined(SK_USE_SHADERS) 430 fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL); 431 #else 432 fGrContext = GrContext::Create(kOpenGL_Fixed_GrEngine, NULL); 433 #endif 434 SkDebugf("---- constructor\n"); 435 } 436 437 if (NULL != fGrContext) { 438 return true; 439 } else { 440 detachGL(); 441 } 442 } 443#endif 444 SkDebugf("Failed to setup 3D"); 445 return false; 446} 447 448SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) { 449 static const CanvasType gCT[] = { 450 kPicture_CanvasType, 451 kGPU_CanvasType, 452 kRaster_CanvasType 453 }; 454 return gCT[ct]; 455} 456 457SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) { 458#ifdef PIPE_FILE 459 //Clear existing file or create file if it doesn't exist 460 FILE* f = fopen(FILE_PATH, "wb"); 461 fclose(f); 462#endif 463 464 fPicture = NULL; 465 fGpuCanvas = NULL; 466 467 fGrContext = NULL; 468 469#ifdef DEFAULT_TO_GPU 470 fCanvasType = kGPU_CanvasType; 471#else 472 fCanvasType = kRaster_CanvasType; 473#endif 474 fUseClip = false; 475 fNClip = false; 476 fRepeatDrawing = false; 477 fAnimating = false; 478 fRotate = false; 479 fScale = false; 480 fRequestGrabImage = false; 481 fUsePipe = false; 482 fMeasureFPS = false; 483 fLCDState = kUnknown_SkTriState; 484 fAAState = kUnknown_SkTriState; 485 fFilterState = kUnknown_SkTriState; 486 fHintingState = kUnknown_SkTriState; 487 fFlipAxis = 0; 488 fScrollTestX = fScrollTestY = 0; 489 490 fMouseX = fMouseY = 0; 491 fFatBitsScale = 8; 492 fTypeface = SkTypeface::CreateFromTypeface(NULL, SkTypeface::kBold); 493 fShowZoomer = false; 494 495 fZoomLevel = 0; 496 fZoomScale = SK_Scalar1; 497 498// this->setConfig(SkBitmap::kRGB_565_Config); 499 this->setConfig(SkBitmap::kARGB_8888_Config); 500 this->setVisibleP(true); 501 this->setClipToBounds(false); 502 503 { 504 const SkViewRegister* reg = SkViewRegister::Head(); 505 while (reg) { 506 *fSamples.append() = reg->factory(); 507 reg = reg->next(); 508 } 509 } 510 fCurrIndex = 0; 511 this->loadView(fSamples[fCurrIndex]()); 512 513#ifdef SK_BUILD_FOR_MAC 514 testpdf(); 515#endif 516} 517 518SampleWindow::~SampleWindow() { 519 delete fPicture; 520 delete fGpuCanvas; 521 if (NULL != fGrContext) { 522 fGrContext->unref(); 523 } 524 fTypeface->unref(); 525} 526 527static SkBitmap capture_bitmap(SkCanvas* canvas) { 528 SkBitmap bm; 529 const SkBitmap& src = canvas->getDevice()->accessBitmap(false); 530 src.copyTo(&bm, src.config()); 531 return bm; 532} 533 534static bool bitmap_diff(SkCanvas* canvas, const SkBitmap& orig, 535 SkBitmap* diff) { 536 const SkBitmap& src = canvas->getDevice()->accessBitmap(false); 537 538 SkAutoLockPixels alp0(src); 539 SkAutoLockPixels alp1(orig); 540 for (int y = 0; y < src.height(); y++) { 541 const void* srcP = src.getAddr(0, y); 542 const void* origP = orig.getAddr(0, y); 543 size_t bytes = src.width() * src.bytesPerPixel(); 544 if (memcmp(srcP, origP, bytes)) { 545 SkDebugf("---------- difference on line %d\n", y); 546 return true; 547 } 548 } 549 return false; 550} 551 552static void drawText(SkCanvas* canvas, SkString string, SkScalar left, SkScalar top, SkPaint& paint) 553{ 554 SkColor desiredColor = paint.getColor(); 555 paint.setColor(SK_ColorWHITE); 556 const char* c_str = string.c_str(); 557 size_t size = string.size(); 558 SkRect bounds; 559 paint.measureText(c_str, size, &bounds); 560 bounds.offset(left, top); 561 SkScalar inset = SkIntToScalar(-2); 562 bounds.inset(inset, inset); 563 canvas->drawRect(bounds, paint); 564 if (desiredColor != SK_ColorBLACK) { 565 paint.setColor(SK_ColorBLACK); 566 canvas->drawText(c_str, size, left + SK_Scalar1, top + SK_Scalar1, paint); 567 } 568 paint.setColor(desiredColor); 569 canvas->drawText(c_str, size, left, top, paint); 570} 571 572#define XCLIP_N 8 573#define YCLIP_N 8 574 575void SampleWindow::draw(SkCanvas* canvas) { 576 // update the animation time 577 gAnimTimePrev = gAnimTime; 578 gAnimTime = SkTime::GetMSecs(); 579 580 SkScalar cx = SkScalarHalf(this->width()); 581 SkScalar cy = SkScalarHalf(this->height()); 582 583 if (fZoomLevel) { 584 SkMatrix m; 585 SkPoint center; 586 m = canvas->getTotalMatrix();//.invert(&m); 587 m.mapXY(cx, cy, ¢er); 588 cx = center.fX; 589 cy = center.fY; 590 591 m.setTranslate(-cx, -cy); 592 m.postScale(fZoomScale, fZoomScale); 593 m.postTranslate(cx, cy); 594 595 canvas->concat(m); 596 } 597 598 if (fFlipAxis) { 599 SkMatrix m; 600 m.setTranslate(cx, cy); 601 if (fFlipAxis & kFlipAxis_X) { 602 m.preScale(-SK_Scalar1, SK_Scalar1); 603 } 604 if (fFlipAxis & kFlipAxis_Y) { 605 m.preScale(SK_Scalar1, -SK_Scalar1); 606 } 607 m.preTranslate(-cx, -cy); 608 canvas->concat(m); 609 } 610 611 // Apply any gesture matrix 612 if (true) { 613 const SkMatrix& localM = fGesture.localM(); 614 if (localM.getType() & SkMatrix::kScale_Mask) { 615 canvas->setExternalMatrix(&localM); 616 } 617 canvas->concat(localM); 618 canvas->concat(fGesture.globalM()); 619 620 if (fGesture.isActive()) { 621 this->inval(NULL); 622 } 623 } 624 625 if (fNClip) { 626 this->INHERITED::draw(canvas); 627 SkBitmap orig = capture_bitmap(canvas); 628 629 const SkScalar w = this->width(); 630 const SkScalar h = this->height(); 631 const SkScalar cw = w / XCLIP_N; 632 const SkScalar ch = h / YCLIP_N; 633 for (int y = 0; y < YCLIP_N; y++) { 634 SkRect r; 635 r.fTop = y * ch; 636 r.fBottom = (y + 1) * ch; 637 if (y == YCLIP_N - 1) { 638 r.fBottom = h; 639 } 640 for (int x = 0; x < XCLIP_N; x++) { 641 SkAutoCanvasRestore acr(canvas, true); 642 r.fLeft = x * cw; 643 r.fRight = (x + 1) * cw; 644 if (x == XCLIP_N - 1) { 645 r.fRight = w; 646 } 647 canvas->clipRect(r); 648 this->INHERITED::draw(canvas); 649 } 650 } 651 652 SkBitmap diff; 653 if (bitmap_diff(canvas, orig, &diff)) { 654 } 655 } else { 656 this->INHERITED::draw(canvas); 657 } 658 if (fShowZoomer && fCanvasType != kGPU_CanvasType) { 659 // In the GPU case, INHERITED::draw calls beforeChildren, which 660 // creates an SkGpuCanvas. All further draw calls are directed 661 // at that canvas, which is deleted in afterChildren (which is 662 // also called by draw), so we cannot show the zoomer here. 663 // Instead, we call it inside afterChildren. 664 showZoomer(canvas); 665 } 666} 667 668void SampleWindow::showZoomer(SkCanvas* canvas) { 669 int count = canvas->save(); 670 canvas->resetMatrix(); 671 // Ensure the mouse position is on screen. 672 int width = SkScalarRound(this->width()); 673 int height = SkScalarRound(this->height()); 674 if (fMouseX >= width) fMouseX = width - 1; 675 else if (fMouseX < 0) fMouseX = 0; 676 if (fMouseY >= height) fMouseY = height - 1; 677 else if (fMouseY < 0) fMouseY = 0; 678 679 SkBitmap bitmap = capture_bitmap(canvas); 680 bitmap.lockPixels(); 681 682 // Find the size of the zoomed in view, forced to be odd, so the examined pixel is in the middle. 683 int zoomedWidth = (width >> 1) | 1; 684 int zoomedHeight = (height >> 1) | 1; 685 SkIRect src; 686 src.set(0, 0, zoomedWidth / fFatBitsScale, zoomedHeight / fFatBitsScale); 687 src.offset(fMouseX - (src.width()>>1), fMouseY - (src.height()>>1)); 688 SkRect dest; 689 dest.set(0, 0, SkIntToScalar(zoomedWidth), SkIntToScalar(zoomedHeight)); 690 dest.offset(SkIntToScalar(width - zoomedWidth), SkIntToScalar(height - zoomedHeight)); 691 SkPaint paint; 692 // Clear the background behind our zoomed in view 693 paint.setColor(SK_ColorWHITE); 694 canvas->drawRect(dest, paint); 695 canvas->drawBitmapRect(bitmap, &src, dest); 696 paint.setColor(SK_ColorBLACK); 697 paint.setStyle(SkPaint::kStroke_Style); 698 // Draw a border around the pixel in the middle 699 SkRect originalPixel; 700 originalPixel.set(SkIntToScalar(fMouseX), SkIntToScalar(fMouseY), SkIntToScalar(fMouseX + 1), SkIntToScalar(fMouseY + 1)); 701 SkMatrix matrix; 702 SkRect scalarSrc; 703 scalarSrc.set(src); 704 SkColor color = bitmap.getColor(fMouseX, fMouseY); 705 if (matrix.setRectToRect(scalarSrc, dest, SkMatrix::kFill_ScaleToFit)) { 706 SkRect pixel; 707 matrix.mapRect(&pixel, originalPixel); 708 // TODO Perhaps measure the values and make the outline white if it's "dark" 709 if (color == SK_ColorBLACK) { 710 paint.setColor(SK_ColorWHITE); 711 } 712 canvas->drawRect(pixel, paint); 713 } 714 paint.setColor(SK_ColorBLACK); 715 // Draw a border around the destination rectangle 716 canvas->drawRect(dest, paint); 717 paint.setStyle(SkPaint::kStrokeAndFill_Style); 718 // Identify the pixel and its color on screen 719 paint.setTypeface(fTypeface); 720 paint.setAntiAlias(true); 721 SkScalar lineHeight = paint.getFontMetrics(NULL); 722 SkString string; 723 string.appendf("(%i, %i)", fMouseX, fMouseY); 724 SkScalar left = dest.fLeft + SkIntToScalar(3); 725 SkScalar i = SK_Scalar1; 726 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint); 727 // Alpha 728 i += SK_Scalar1; 729 string.reset(); 730 string.appendf("A: %X", SkColorGetA(color)); 731 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint); 732 // Red 733 i += SK_Scalar1; 734 string.reset(); 735 string.appendf("R: %X", SkColorGetR(color)); 736 paint.setColor(SK_ColorRED); 737 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint); 738 // Green 739 i += SK_Scalar1; 740 string.reset(); 741 string.appendf("G: %X", SkColorGetG(color)); 742 paint.setColor(SK_ColorGREEN); 743 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint); 744 // Blue 745 i += SK_Scalar1; 746 string.reset(); 747 string.appendf("B: %X", SkColorGetB(color)); 748 paint.setColor(SK_ColorBLUE); 749 drawText(canvas, string, left, SkScalarMulAdd(lineHeight, i, dest.fTop), paint); 750 canvas->restoreToCount(count); 751} 752 753void SampleWindow::onDraw(SkCanvas* canvas) { 754 if (fRepeatDrawing) { 755 this->inval(NULL); 756 } 757} 758 759#include "SkColorPriv.h" 760 761static void reverseRedAndBlue(const SkBitmap& bm) { 762 SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config); 763 uint8_t* p = (uint8_t*)bm.getPixels(); 764 uint8_t* stop = p + bm.getSize(); 765 while (p < stop) { 766 // swap red/blue (to go from ARGB(int) to RGBA(memory) and premultiply 767 unsigned scale = SkAlpha255To256(p[3]); 768 unsigned r = p[2]; 769 unsigned b = p[0]; 770 p[0] = SkAlphaMul(r, scale); 771 p[1] = SkAlphaMul(p[1], scale); 772 p[2] = SkAlphaMul(b, scale); 773 p += 4; 774 } 775} 776 777SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) { 778 if (kGPU_CanvasType != fCanvasType) { 779#ifdef SK_SUPPORT_GL 780 detachGL(); 781#endif 782 } 783 784 switch (fCanvasType) { 785 case kRaster_CanvasType: 786 canvas = this->INHERITED::beforeChildren(canvas); 787 break; 788 case kPicture_CanvasType: 789 fPicture = new SkPicture; 790 canvas = fPicture->beginRecording(9999, 9999); 791 break; 792 case kGPU_CanvasType: { 793 if (make3DReady()) { 794 SkDevice* device = canvas->getDevice(); 795 const SkBitmap& bitmap = device->accessBitmap(true); 796 797 GrRenderTarget* renderTarget; 798 renderTarget = fGrContext->createRenderTargetFrom3DApiState(); 799 fGpuCanvas = new SkGpuCanvas(fGrContext, renderTarget); 800 renderTarget->unref(); 801 802 device = fGpuCanvas->createDevice(SkBitmap::kARGB_8888_Config, 803 bitmap.width(), bitmap.height(), 804 false, false); 805 fGpuCanvas->setDevice(device)->unref(); 806 807 fGpuCanvas->concat(canvas->getTotalMatrix()); 808 canvas = fGpuCanvas; 809 810 } else { 811 canvas = this->INHERITED::beforeChildren(canvas); 812 } 813 break; 814 } 815 } 816 817 if (fUseClip) { 818 canvas->drawColor(0xFFFF88FF); 819 canvas->clipPath(fClipPath); 820 } 821 822 return canvas; 823} 824 825static void paint_rgn(const SkBitmap& bm, const SkIRect& r, 826 const SkRegion& rgn) { 827 SkCanvas canvas(bm); 828 SkRegion inval(rgn); 829 830 inval.translate(r.fLeft, r.fTop); 831 canvas.clipRegion(inval); 832 canvas.drawColor(0xFFFF8080); 833} 834 835void SampleWindow::afterChildren(SkCanvas* orig) { 836 if (fRequestGrabImage) { 837 fRequestGrabImage = false; 838 839 SkCanvas* canvas = fGpuCanvas ? fGpuCanvas : orig; 840 SkDevice* device = canvas->getDevice(); 841 SkBitmap bmp; 842 if (device->accessBitmap(false).copyTo(&bmp, SkBitmap::kARGB_8888_Config)) { 843 static int gSampleGrabCounter; 844 SkString name; 845 name.printf("sample_grab_%d", gSampleGrabCounter++); 846 SkImageEncoder::EncodeFile(name.c_str(), bmp, 847 SkImageEncoder::kPNG_Type, 100); 848 } 849 } 850 851 switch (fCanvasType) { 852 case kRaster_CanvasType: 853 break; 854 case kPicture_CanvasType: 855 if (true) { 856 SkPicture* pict = new SkPicture(*fPicture); 857 fPicture->unref(); 858 orig->drawPicture(*pict); 859 pict->unref(); 860 } else if (true) { 861 SkDynamicMemoryWStream ostream; 862 fPicture->serialize(&ostream); 863 fPicture->unref(); 864 865 SkMemoryStream istream(ostream.getStream(), ostream.getOffset()); 866 SkPicture pict(&istream); 867 orig->drawPicture(pict); 868 } else { 869 fPicture->draw(orig); 870 fPicture->unref(); 871 } 872 fPicture = NULL; 873 break; 874#ifdef SK_SUPPORT_GL 875 case kGPU_CanvasType: 876 if (fShowZoomer && fGpuCanvas) { 877 this->showZoomer(fGpuCanvas); 878 } 879 delete fGpuCanvas; 880 fGpuCanvas = NULL; 881 presentGL(); 882 break; 883#endif 884 } 885 886 // Do this after presentGL and other finishing, rather than in afterChild 887 if (fMeasureFPS && fMeasureFPS_Time) { 888 fMeasureFPS_Time = SkTime::GetMSecs() - fMeasureFPS_Time; 889 this->updateTitle(); 890 postInvalDelay(this->getSinkID()); 891 } 892 893 // if ((fScrollTestX | fScrollTestY) != 0) 894 if (false) { 895 const SkBitmap& bm = orig->getDevice()->accessBitmap(true); 896 int dx = fScrollTestX * 7; 897 int dy = fScrollTestY * 7; 898 SkIRect r; 899 SkRegion inval; 900 901 r.set(50, 50, 50+100, 50+100); 902 bm.scrollRect(&r, dx, dy, &inval); 903 paint_rgn(bm, r, inval); 904 } 905} 906 907void SampleWindow::beforeChild(SkView* child, SkCanvas* canvas) { 908 if (fScale) { 909 SkScalar scale = SK_Scalar1 * 7 / 10; 910 SkScalar cx = this->width() / 2; 911 SkScalar cy = this->height() / 2; 912 canvas->translate(cx, cy); 913 canvas->scale(scale, scale); 914 canvas->translate(-cx, -cy); 915 } 916 if (fRotate) { 917 SkScalar cx = this->width() / 2; 918 SkScalar cy = this->height() / 2; 919 canvas->translate(cx, cy); 920 canvas->rotate(SkIntToScalar(30)); 921 canvas->translate(-cx, -cy); 922 } 923 924 canvas->setDrawFilter(new FlagsDrawFilter(fLCDState, fAAState, 925 fFilterState, fHintingState))->unref(); 926 927 if (fMeasureFPS) { 928 fMeasureFPS_Time = 0; // 0 means the child is not aware of repeat-draw 929 if (SampleView::SetRepeatDraw(child, FPS_REPEAT_COUNT)) { 930 fMeasureFPS_Time = SkTime::GetMSecs(); 931 } 932 } else { 933 (void)SampleView::SetRepeatDraw(child, 1); 934 } 935 (void)SampleView::SetUsePipe(child, fUsePipe); 936} 937 938void SampleWindow::afterChild(SkView* child, SkCanvas* canvas) { 939 canvas->setDrawFilter(NULL); 940} 941 942static SkBitmap::Config gConfigCycle[] = { 943 SkBitmap::kNo_Config, // none -> none 944 SkBitmap::kNo_Config, // a1 -> none 945 SkBitmap::kNo_Config, // a8 -> none 946 SkBitmap::kNo_Config, // index8 -> none 947 SkBitmap::kARGB_4444_Config, // 565 -> 4444 948 SkBitmap::kARGB_8888_Config, // 4444 -> 8888 949 SkBitmap::kRGB_565_Config // 8888 -> 565 950}; 951 952static SkBitmap::Config cycle_configs(SkBitmap::Config c) { 953 return gConfigCycle[c]; 954} 955 956void SampleWindow::changeZoomLevel(float delta) { 957 fZoomLevel += SkFloatToScalar(delta); 958 if (fZoomLevel > 0) { 959 fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL); 960 fZoomScale = fZoomLevel + SK_Scalar1; 961 } else if (fZoomLevel < 0) { 962 fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL); 963 fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel); 964 } else { 965 fZoomScale = SK_Scalar1; 966 } 967 968 this->updateTitle(); 969 970 this->inval(NULL); 971} 972 973bool SampleWindow::nextSample() { 974 fCurrIndex = (fCurrIndex + 1) % fSamples.count(); 975 this->loadView(fSamples[fCurrIndex]()); 976 return true; 977} 978 979bool SampleWindow::onEvent(const SkEvent& evt) { 980 if (evt.isType(ANIMATING_EVENTTYPE)) { 981 if (fAnimating) { 982 this->nextSample(); 983 this->postAnimatingEvent(); 984 } 985 return true; 986 } 987 if (evt.isType("set-curr-index")) { 988 fCurrIndex = evt.getFast32() % fSamples.count(); 989 this->loadView(fSamples[fCurrIndex]()); 990 return true; 991 } 992 if (isInvalEvent(evt)) { 993 this->inval(NULL); 994 return true; 995 } 996 return this->INHERITED::onEvent(evt); 997} 998 999bool SampleWindow::onQuery(SkEvent* query) { 1000 if (query->isType("get-slide-count")) { 1001 query->setFast32(fSamples.count()); 1002 return true; 1003 } 1004 if (query->isType("get-slide-title")) { 1005 SkView* view = fSamples[query->getFast32()](); 1006 SkEvent evt(gTitleEvtName); 1007 if (view->doQuery(&evt)) { 1008 query->setString("title", evt.findString(gTitleEvtName)); 1009 } 1010 SkSafeUnref(view); 1011 return true; 1012 } 1013 if (query->isType("use-fast-text")) { 1014 SkEvent evt(gFastTextEvtName); 1015 return curr_view(this)->doQuery(&evt); 1016 } 1017 return this->INHERITED::onQuery(query); 1018} 1019 1020static void cleanup_for_filename(SkString* name) { 1021 char* str = name->writable_str(); 1022 for (size_t i = 0; i < name->size(); i++) { 1023 switch (str[i]) { 1024 case ':': str[i] = '-'; break; 1025 case '/': str[i] = '-'; break; 1026 case ' ': str[i] = '_'; break; 1027 default: break; 1028 } 1029 } 1030} 1031 1032bool SampleWindow::onHandleChar(SkUnichar uni) { 1033 { 1034 SkView* view = curr_view(this); 1035 if (view) { 1036 SkEvent evt(gCharEvtName); 1037 evt.setFast32(uni); 1038 if (view->doQuery(&evt)) { 1039 return true; 1040 } 1041 } 1042 } 1043 1044 int dx = 0xFF; 1045 int dy = 0xFF; 1046 1047 switch (uni) { 1048 case '5': dx = 0; dy = 0; break; 1049 case '8': dx = 0; dy = -1; break; 1050 case '6': dx = 1; dy = 0; break; 1051 case '2': dx = 0; dy = 1; break; 1052 case '4': dx = -1; dy = 0; break; 1053 case '7': dx = -1; dy = -1; break; 1054 case '9': dx = 1; dy = -1; break; 1055 case '3': dx = 1; dy = 1; break; 1056 case '1': dx = -1; dy = 1; break; 1057 1058 default: 1059 break; 1060 } 1061 1062 if (0xFF != dx && 0xFF != dy) { 1063 if ((dx | dy) == 0) { 1064 fScrollTestX = fScrollTestY = 0; 1065 } else { 1066 fScrollTestX += dx; 1067 fScrollTestY += dy; 1068 } 1069 this->inval(NULL); 1070 return true; 1071 } 1072 1073 switch (uni) { 1074 case 'a': 1075 fAnimating = !fAnimating; 1076 this->postAnimatingEvent(); 1077 this->updateTitle(); 1078 return true; 1079 case 'b': 1080 fAAState = cycle_tristate(fAAState); 1081 this->updateTitle(); 1082 this->inval(NULL); 1083 break; 1084 case 'c': 1085 fUseClip = !fUseClip; 1086 this->inval(NULL); 1087 this->updateTitle(); 1088 return true; 1089 case 'd': 1090 SkGraphics::SetFontCacheUsed(0); 1091 return true; 1092 case 'f': 1093 fMeasureFPS = !fMeasureFPS; 1094 this->inval(NULL); 1095 break; 1096 case 'g': 1097 fRequestGrabImage = true; 1098 this->inval(NULL); 1099 break; 1100 case 'h': 1101 fHintingState = cycle_tristate(fHintingState); 1102 this->updateTitle(); 1103 this->inval(NULL); 1104 break; 1105 case 'i': 1106 this->zoomIn(); 1107 break; 1108 case 'l': 1109 fLCDState = cycle_tristate(fLCDState); 1110 this->updateTitle(); 1111 this->inval(NULL); 1112 break; 1113 case 'n': 1114 fFilterState = cycle_tristate(fFilterState); 1115 this->updateTitle(); 1116 this->inval(NULL); 1117 break; 1118 case 'o': 1119 this->zoomOut(); 1120 break; 1121 case 'p': 1122 fUsePipe = !fUsePipe; 1123 this->updateTitle(); 1124 this->inval(NULL); 1125 break; 1126 case 'r': 1127 fRotate = !fRotate; 1128 this->inval(NULL); 1129 this->updateTitle(); 1130 return true; 1131 case 's': 1132 fScale = !fScale; 1133 this->inval(NULL); 1134 this->updateTitle(); 1135 return true; 1136 case 'x': 1137 fFlipAxis ^= kFlipAxis_X; 1138 this->updateTitle(); 1139 this->inval(NULL); 1140 break; 1141 case 'y': 1142 fFlipAxis ^= kFlipAxis_Y; 1143 this->updateTitle(); 1144 this->inval(NULL); 1145 break; 1146 case 'z': 1147 this->toggleZoomer(); 1148 break; 1149 default: 1150 break; 1151 } 1152 1153 return this->INHERITED::onHandleChar(uni); 1154} 1155 1156#include "SkDumpCanvas.h" 1157 1158bool SampleWindow::onHandleKey(SkKey key) { 1159 { 1160 SkView* view = curr_view(this); 1161 if (view) { 1162 SkEvent evt(gKeyEvtName); 1163 evt.setFast32(key); 1164 if (view->doQuery(&evt)) { 1165 return true; 1166 } 1167 } 1168 } 1169 1170 switch (key) { 1171 case kRight_SkKey: 1172 if (this->nextSample()) { 1173 return true; 1174 } 1175 break; 1176 case kLeft_SkKey: 1177 fCanvasType = cycle_canvastype(fCanvasType); 1178 this->updateTitle(); 1179 this->inval(NULL); 1180 return true; 1181 case kUp_SkKey: 1182 if (USE_ARROWS_FOR_ZOOM) { 1183 this->changeZoomLevel(1.f); 1184 } else { 1185 fNClip = !fNClip; 1186 this->inval(NULL); 1187 this->updateTitle(); 1188 } 1189 return true; 1190 case kDown_SkKey: 1191 if (USE_ARROWS_FOR_ZOOM) { 1192 this->changeZoomLevel(-1.f); 1193 } else { 1194 this->setConfig(cycle_configs(this->getBitmap().config())); 1195 this->updateTitle(); 1196 } 1197 return true; 1198 case kOK_SkKey: 1199 if (false) { 1200 SkDebugfDumper dumper; 1201 SkDumpCanvas dc(&dumper); 1202 this->draw(&dc); 1203 } else { 1204 fRepeatDrawing = !fRepeatDrawing; 1205 if (fRepeatDrawing) { 1206 this->inval(NULL); 1207 } 1208 } 1209 return true; 1210 case kBack_SkKey: 1211 this->loadView(NULL); 1212 return true; 1213 default: 1214 break; 1215 } 1216 return this->INHERITED::onHandleKey(key); 1217} 1218 1219/////////////////////////////////////////////////////////////////////////////// 1220 1221static const char gGestureClickType[] = "GestureClickType"; 1222 1223bool SampleWindow::onDispatchClick(int x, int y, Click::State state) { 1224 if (Click::kMoved_State == state) { 1225 updatePointer(x, y); 1226 } 1227 int w = SkScalarRound(this->width()); 1228 int h = SkScalarRound(this->height()); 1229 1230 // check for the resize-box 1231 if (w - x < 16 && h - y < 16) { 1232 return false; // let the OS handle the click 1233 } else { 1234 return this->INHERITED::onDispatchClick(x, y, state); 1235 } 1236} 1237 1238class GestureClick : public SkView::Click { 1239public: 1240 GestureClick(SkView* target) : SkView::Click(target) { 1241 this->setType(gGestureClickType); 1242 } 1243 1244 static bool IsGesture(Click* click) { 1245 return click->isType(gGestureClickType); 1246 } 1247}; 1248 1249SkView::Click* SampleWindow::onFindClickHandler(SkScalar x, SkScalar y) { 1250 return new GestureClick(this); 1251} 1252 1253bool SampleWindow::onClick(Click* click) { 1254 if (GestureClick::IsGesture(click)) { 1255 float x = SkScalarToFloat(click->fCurr.fX); 1256 float y = SkScalarToFloat(click->fCurr.fY); 1257 switch (click->fState) { 1258 case SkView::Click::kDown_State: 1259 fGesture.touchBegin(click, x, y); 1260 break; 1261 case SkView::Click::kMoved_State: 1262 fGesture.touchMoved(click, x, y); 1263 this->inval(NULL); 1264 break; 1265 case SkView::Click::kUp_State: 1266 fGesture.touchEnd(click); 1267 this->inval(NULL); 1268 break; 1269 } 1270 return true; 1271 } 1272 return false; 1273} 1274 1275/////////////////////////////////////////////////////////////////////////////// 1276 1277void SampleWindow::loadView(SkView* view) { 1278 SkView::F2BIter iter(this); 1279 SkView* prev = iter.next(); 1280 if (prev) { 1281 prev->detachFromParent(); 1282 } 1283 1284 if (NULL == view) { 1285 view = create_overview(fSamples.count(), fSamples.begin()); 1286 } 1287 view->setVisibleP(true); 1288 view->setClipToBounds(false); 1289 this->attachChildToFront(view)->unref(); 1290 view->setSize(this->width(), this->height()); 1291 1292 this->updateTitle(); 1293} 1294 1295static const char* gConfigNames[] = { 1296 "unknown config", 1297 "A1", 1298 "A8", 1299 "Index8", 1300 "565", 1301 "4444", 1302 "8888" 1303}; 1304 1305static const char* configToString(SkBitmap::Config c) { 1306 return gConfigNames[c]; 1307} 1308 1309static const char* gCanvasTypePrefix[] = { 1310 "raster: ", 1311 "picture: ", 1312 "opengl: " 1313}; 1314 1315static const char* trystate_str(SkTriState state, 1316 const char trueStr[], const char falseStr[]) { 1317 if (kTrue_SkTriState == state) { 1318 return trueStr; 1319 } else if (kFalse_SkTriState == state) { 1320 return falseStr; 1321 } 1322 return NULL; 1323} 1324 1325void SampleWindow::updateTitle() { 1326 SkString title; 1327 1328 SkView::F2BIter iter(this); 1329 SkView* view = iter.next(); 1330 SkEvent evt(gTitleEvtName); 1331 if (view->doQuery(&evt)) { 1332 title.set(evt.findString(gTitleEvtName)); 1333 } 1334 if (title.size() == 0) { 1335 title.set("<unknown>"); 1336 } 1337 1338 title.prepend(gCanvasTypePrefix[fCanvasType]); 1339 1340 title.prepend(" "); 1341 title.prepend(configToString(this->getBitmap().config())); 1342 1343 if (fAnimating) { 1344 title.prepend("<A> "); 1345 } 1346 if (fScale) { 1347 title.prepend("<S> "); 1348 } 1349 if (fRotate) { 1350 title.prepend("<R> "); 1351 } 1352 if (fNClip) { 1353 title.prepend("<C> "); 1354 } 1355 1356 title.prepend(trystate_str(fLCDState, "LCD ", "lcd ")); 1357 title.prepend(trystate_str(fAAState, "AA ", "aa ")); 1358 title.prepend(trystate_str(fFilterState, "H ", "h ")); 1359 title.prepend(fFlipAxis & kFlipAxis_X ? "X " : NULL); 1360 title.prepend(fFlipAxis & kFlipAxis_Y ? "Y " : NULL); 1361 1362 if (fZoomLevel) { 1363 title.prependf("{%.2f} ", SkScalarToFloat(fZoomLevel)); 1364 } 1365 1366 if (fMeasureFPS) { 1367 title.appendf(" %6.1f ms", fMeasureFPS_Time / (float)FPS_REPEAT_MULTIPLIER); 1368 } 1369 if (fUsePipe && SampleView::IsSampleView(view)) { 1370 title.prepend("<P> "); 1371 } 1372 if (SampleView::IsSampleView(view)) { 1373 title.prepend("! "); 1374 } 1375 1376 this->setTitle(title.c_str()); 1377} 1378 1379void SampleWindow::onSizeChange() { 1380 this->INHERITED::onSizeChange(); 1381 1382 SkView::F2BIter iter(this); 1383 SkView* view = iter.next(); 1384 view->setSize(this->width(), this->height()); 1385 1386 // rebuild our clippath 1387 { 1388 const SkScalar W = this->width(); 1389 const SkScalar H = this->height(); 1390 1391 fClipPath.reset(); 1392#if 0 1393 for (SkScalar y = SK_Scalar1; y < H; y += SkIntToScalar(32)) { 1394 SkRect r; 1395 r.set(SK_Scalar1, y, SkIntToScalar(30), y + SkIntToScalar(30)); 1396 for (; r.fLeft < W; r.offset(SkIntToScalar(32), 0)) 1397 fClipPath.addRect(r); 1398 } 1399#else 1400 SkRect r; 1401 r.set(0, 0, W, H); 1402 fClipPath.addRect(r, SkPath::kCCW_Direction); 1403 r.set(W/4, H/4, W*3/4, H*3/4); 1404 fClipPath.addRect(r, SkPath::kCW_Direction); 1405#endif 1406 } 1407 1408 this->updateTitle(); // to refresh our config 1409} 1410 1411/////////////////////////////////////////////////////////////////////////////// 1412 1413static const char is_sample_view_tag[] = "sample-is-sample-view"; 1414static const char repeat_count_tag[] = "sample-set-repeat-count"; 1415static const char set_use_pipe_tag[] = "sample-set-use-pipe"; 1416 1417bool SampleView::IsSampleView(SkView* view) { 1418 SkEvent evt(is_sample_view_tag); 1419 return view->doQuery(&evt); 1420} 1421 1422bool SampleView::SetRepeatDraw(SkView* view, int count) { 1423 SkEvent evt(repeat_count_tag); 1424 evt.setFast32(count); 1425 return view->doEvent(evt); 1426} 1427 1428bool SampleView::SetUsePipe(SkView* view, bool pred) { 1429 SkEvent evt(set_use_pipe_tag); 1430 evt.setFast32(pred); 1431 return view->doEvent(evt); 1432} 1433 1434bool SampleView::onEvent(const SkEvent& evt) { 1435 if (evt.isType(repeat_count_tag)) { 1436 fRepeatCount = evt.getFast32(); 1437 return true; 1438 } 1439 if (evt.isType(set_use_pipe_tag)) { 1440 fUsePipe = !!evt.getFast32(); 1441 return true; 1442 } 1443 return this->INHERITED::onEvent(evt); 1444} 1445 1446bool SampleView::onQuery(SkEvent* evt) { 1447 if (evt->isType(is_sample_view_tag)) { 1448 return true; 1449 } 1450 return this->INHERITED::onQuery(evt); 1451} 1452 1453#ifdef TEST_GPIPE 1454 #include "SkGPipe.h" 1455 1456class SimplePC : public SkGPipeController { 1457public: 1458 SimplePC(SkCanvas* target); 1459 ~SimplePC(); 1460 1461 virtual void* requestBlock(size_t minRequest, size_t* actual); 1462 virtual void notifyWritten(size_t bytes); 1463 1464private: 1465 SkGPipeReader fReader; 1466 void* fBlock; 1467 size_t fBlockSize; 1468 size_t fBytesWritten; 1469 int fAtomsWritten; 1470 SkGPipeReader::Status fStatus; 1471 1472 size_t fTotalWritten; 1473}; 1474 1475SimplePC::SimplePC(SkCanvas* target) : fReader(target) { 1476 fBlock = NULL; 1477 fBlockSize = fBytesWritten = 0; 1478 fStatus = SkGPipeReader::kDone_Status; 1479 fTotalWritten = 0; 1480 fAtomsWritten = 0; 1481} 1482 1483SimplePC::~SimplePC() { 1484// SkASSERT(SkGPipeReader::kDone_Status == fStatus); 1485 sk_free(fBlock); 1486 1487 if (fTotalWritten) { 1488 SkDebugf("--- %d bytes %d atoms, status %d\n", fTotalWritten, 1489 fAtomsWritten, fStatus); 1490 } 1491} 1492 1493void* SimplePC::requestBlock(size_t minRequest, size_t* actual) { 1494 sk_free(fBlock); 1495 1496 fBlockSize = minRequest * 4; 1497 fBlock = sk_malloc_throw(fBlockSize); 1498 fBytesWritten = 0; 1499 *actual = fBlockSize; 1500 return fBlock; 1501} 1502 1503void SimplePC::notifyWritten(size_t bytes) { 1504 SkASSERT(fBytesWritten + bytes <= fBlockSize); 1505 1506#ifdef PIPE_FILE 1507 //File is open in append mode 1508 FILE* f = fopen(FILE_PATH, "ab"); 1509 SkASSERT(f != NULL); 1510 fwrite((const char*)fBlock + fBytesWritten, 1, bytes, f); 1511 fclose(f); 1512#endif 1513 1514 fStatus = fReader.playback((const char*)fBlock + fBytesWritten, bytes); 1515 SkASSERT(SkGPipeReader::kError_Status != fStatus); 1516 fBytesWritten += bytes; 1517 fTotalWritten += bytes; 1518 1519 fAtomsWritten += 1; 1520} 1521 1522#endif 1523 1524 1525void SampleView::onDraw(SkCanvas* canvas) { 1526#ifdef TEST_GPIPE 1527 SimplePC controller(canvas); 1528 SkGPipeWriter writer; 1529 if (fUsePipe) { 1530 uint32_t flags = SkGPipeWriter::kCrossProcess_Flag; 1531// flags = 0; 1532 canvas = writer.startRecording(&controller, flags); 1533 } 1534#endif 1535 1536 this->onDrawBackground(canvas); 1537 1538 for (int i = 0; i < fRepeatCount; i++) { 1539 SkAutoCanvasRestore acr(canvas, true); 1540 this->onDrawContent(canvas); 1541 } 1542} 1543 1544void SampleView::onDrawBackground(SkCanvas* canvas) { 1545 canvas->drawColor(fBGColor); 1546} 1547 1548/////////////////////////////////////////////////////////////////////////////// 1549 1550template <typename T> void SkTBSort(T array[], int count) { 1551 for (int i = 1; i < count - 1; i++) { 1552 bool didSwap = false; 1553 for (int j = count - 1; j > i; --j) { 1554 if (array[j] < array[j-1]) { 1555 T tmp(array[j-1]); 1556 array[j-1] = array[j]; 1557 array[j] = tmp; 1558 didSwap = true; 1559 } 1560 } 1561 if (!didSwap) { 1562 break; 1563 } 1564 } 1565 1566 for (int k = 0; k < count - 1; k++) { 1567 SkASSERT(!(array[k+1] < array[k])); 1568 } 1569} 1570 1571#include "SkRandom.h" 1572 1573static void rand_rect(SkIRect* rect, SkRandom& rand) { 1574 int bits = 8; 1575 int shift = 32 - bits; 1576 rect->set(rand.nextU() >> shift, rand.nextU() >> shift, 1577 rand.nextU() >> shift, rand.nextU() >> shift); 1578 rect->sort(); 1579} 1580 1581static void dumpRect(const SkIRect& r) { 1582 SkDebugf(" { %d, %d, %d, %d },\n", 1583 r.fLeft, r.fTop, 1584 r.fRight, r.fBottom); 1585} 1586 1587static void test_rects(const SkIRect rect[], int count) { 1588 SkRegion rgn0, rgn1; 1589 1590 for (int i = 0; i < count; i++) { 1591 rgn0.op(rect[i], SkRegion::kUnion_Op); 1592 // dumpRect(rect[i]); 1593 } 1594 rgn1.setRects(rect, count); 1595 1596 if (rgn0 != rgn1) { 1597 SkDebugf("\n"); 1598 for (int i = 0; i < count; i++) { 1599 dumpRect(rect[i]); 1600 } 1601 SkDebugf("\n"); 1602 } 1603} 1604 1605static void test() { 1606 size_t i; 1607 1608 const SkIRect r0[] = { 1609 { 0, 0, 1, 1 }, 1610 { 2, 2, 3, 3 }, 1611 }; 1612 const SkIRect r1[] = { 1613 { 0, 0, 1, 3 }, 1614 { 1, 1, 2, 2 }, 1615 { 2, 0, 3, 3 }, 1616 }; 1617 const SkIRect r2[] = { 1618 { 0, 0, 1, 2 }, 1619 { 2, 1, 3, 3 }, 1620 { 4, 0, 5, 1 }, 1621 { 6, 0, 7, 4 }, 1622 }; 1623 1624 static const struct { 1625 const SkIRect* fRects; 1626 int fCount; 1627 } gRecs[] = { 1628 { r0, SK_ARRAY_COUNT(r0) }, 1629 { r1, SK_ARRAY_COUNT(r1) }, 1630 { r2, SK_ARRAY_COUNT(r2) }, 1631 }; 1632 1633 for (i = 0; i < SK_ARRAY_COUNT(gRecs); i++) { 1634 test_rects(gRecs[i].fRects, gRecs[i].fCount); 1635 } 1636 1637 SkRandom rand; 1638 for (i = 0; i < 10000; i++) { 1639 SkRegion rgn0, rgn1; 1640 1641 const int N = 8; 1642 SkIRect rect[N]; 1643 for (int j = 0; j < N; j++) { 1644 rand_rect(&rect[j], rand); 1645 } 1646 test_rects(rect, N); 1647 } 1648} 1649 1650SkOSWindow* create_sk_window(void* hwnd) { 1651// test(); 1652 return new SampleWindow(hwnd); 1653} 1654 1655void get_preferred_size(int* x, int* y, int* width, int* height) { 1656 *x = 10; 1657 *y = 50; 1658 *width = 640; 1659 *height = 480; 1660} 1661 1662void application_init() { 1663// setenv("ANDROID_ROOT", "../../../data", 0); 1664#ifdef SK_BUILD_FOR_MAC 1665 setenv("ANDROID_ROOT", "/android/device/data", 0); 1666#endif 1667 SkGraphics::Init(); 1668 SkEvent::Init(); 1669} 1670 1671void application_term() { 1672 SkEvent::Term(); 1673 SkGraphics::Term(); 1674} 1675