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