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