1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "SkWindow.h" 9 #include "SkCanvas.h" 10 #include "SkDevice.h" 11 #include "SkOSMenu.h" 12 #include "SkSystemEventTypes.h" 13 #include "SkTime.h" 14 15 #define SK_EventDelayInval "\xd" "n" "\xa" "l" 16 17 #define TEST_BOUNDERx 18 19 #include "SkBounder.h" 20 class test_bounder : public SkBounder { 21 public: 22 test_bounder(const SkBitmap& bm) : fCanvas(bm) {} 23 protected: 24 virtual bool onIRect(const SkIRect& r) 25 { 26 SkRect rr; 27 28 rr.set(SkIntToScalar(r.fLeft), SkIntToScalar(r.fTop), 29 SkIntToScalar(r.fRight), SkIntToScalar(r.fBottom)); 30 31 SkPaint p; 32 33 p.setStyle(SkPaint::kStroke_Style); 34 p.setColor(SK_ColorYELLOW); 35 36 #if 0 37 rr.inset(SK_ScalarHalf, SK_ScalarHalf); 38 #else 39 rr.inset(-SK_ScalarHalf, -SK_ScalarHalf); 40 #endif 41 42 fCanvas.drawRect(rr, p); 43 return true; 44 } 45 private: 46 SkCanvas fCanvas; 47 }; 48 49 SkWindow::SkWindow() : fFocusView(NULL) 50 { 51 fClicks.reset(); 52 fWaitingOnInval = false; 53 54 #ifdef SK_BUILD_FOR_WINCE 55 fConfig = SkBitmap::kRGB_565_Config; 56 #else 57 fConfig = SkBitmap::kARGB_8888_Config; 58 #endif 59 60 fMatrix.reset(); 61 } 62 63 SkWindow::~SkWindow() 64 { 65 fClicks.deleteAll(); 66 fMenus.deleteAll(); 67 } 68 69 SkCanvas* SkWindow::createCanvas() { 70 return new SkCanvas(this->getBitmap()); 71 } 72 73 void SkWindow::setMatrix(const SkMatrix& matrix) { 74 if (fMatrix != matrix) { 75 fMatrix = matrix; 76 this->inval(NULL); 77 } 78 } 79 80 void SkWindow::preConcat(const SkMatrix& matrix) { 81 SkMatrix m; 82 m.setConcat(fMatrix, matrix); 83 this->setMatrix(m); 84 } 85 86 void SkWindow::postConcat(const SkMatrix& matrix) { 87 SkMatrix m; 88 m.setConcat(matrix, fMatrix); 89 this->setMatrix(m); 90 } 91 92 void SkWindow::setConfig(SkBitmap::Config config) 93 { 94 this->resize(fBitmap.width(), fBitmap.height(), config); 95 } 96 97 void SkWindow::resize(int width, int height, SkBitmap::Config config) 98 { 99 if (config == SkBitmap::kNo_Config) 100 config = fConfig; 101 102 if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig) 103 { 104 fConfig = config; 105 fBitmap.setConfig(config, width, height); 106 fBitmap.allocPixels(); 107 fBitmap.setIsOpaque(true); 108 109 this->setSize(SkIntToScalar(width), SkIntToScalar(height)); 110 this->inval(NULL); 111 } 112 } 113 114 void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) 115 { 116 fBitmap.eraseARGB(a, r, g, b); 117 } 118 119 void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b) 120 { 121 fBitmap.eraseRGB(r, g, b); 122 } 123 124 bool SkWindow::handleInval(const SkRect* localR) 125 { 126 SkIRect ir; 127 128 if (localR) { 129 SkRect devR; 130 SkMatrix inverse; 131 if (!fMatrix.invert(&inverse)) { 132 return false; 133 } 134 fMatrix.mapRect(&devR, *localR); 135 devR.round(&ir); 136 } else { 137 ir.set(0, 0, 138 SkScalarRound(this->width()), 139 SkScalarRound(this->height())); 140 } 141 fDirtyRgn.op(ir, SkRegion::kUnion_Op); 142 143 this->onHandleInval(ir); 144 return true; 145 } 146 147 void SkWindow::forceInvalAll() { 148 fDirtyRgn.setRect(0, 0, 149 SkScalarCeil(this->width()), 150 SkScalarCeil(this->height())); 151 } 152 153 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 154 #include <windows.h> 155 #include <gx.h> 156 extern GXDisplayProperties gDisplayProps; 157 #endif 158 159 #ifdef SK_SIMULATE_FAILED_MALLOC 160 extern bool gEnableControlledThrow; 161 #endif 162 163 bool SkWindow::update(SkIRect* updateArea) 164 { 165 if (!fDirtyRgn.isEmpty()) 166 { 167 SkBitmap bm = this->getBitmap(); 168 169 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 170 char* buffer = (char*)GXBeginDraw(); 171 SkASSERT(buffer); 172 173 RECT rect; 174 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect); 175 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch; 176 177 bm.setPixels(buffer); 178 #endif 179 180 SkAutoTUnref<SkCanvas> canvas(this->createCanvas()); 181 182 canvas->clipRegion(fDirtyRgn); 183 if (updateArea) 184 *updateArea = fDirtyRgn.getBounds(); 185 186 SkAutoCanvasRestore acr(canvas, true); 187 canvas->concat(fMatrix); 188 189 // empty this now, so we can correctly record any inval calls that 190 // might be made during the draw call. 191 fDirtyRgn.setEmpty(); 192 193 #ifdef TEST_BOUNDER 194 test_bounder b(bm); 195 canvas->setBounder(&b); 196 #endif 197 #ifdef SK_SIMULATE_FAILED_MALLOC 198 gEnableControlledThrow = true; 199 #endif 200 #ifdef SK_BUILD_FOR_WIN32 201 //try { 202 this->draw(canvas); 203 //} 204 //catch (...) { 205 //} 206 #else 207 this->draw(canvas); 208 #endif 209 #ifdef SK_SIMULATE_FAILED_MALLOC 210 gEnableControlledThrow = false; 211 #endif 212 #ifdef TEST_BOUNDER 213 canvas->setBounder(NULL); 214 #endif 215 216 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 217 GXEndDraw(); 218 #endif 219 220 return true; 221 } 222 return false; 223 } 224 225 bool SkWindow::handleChar(SkUnichar uni) 226 { 227 if (this->onHandleChar(uni)) 228 return true; 229 230 SkView* focus = this->getFocusView(); 231 if (focus == NULL) 232 focus = this; 233 234 SkEvent evt(SK_EventType_Unichar); 235 evt.setFast32(uni); 236 return focus->doEvent(evt); 237 } 238 239 bool SkWindow::handleKey(SkKey key) 240 { 241 if (key == kNONE_SkKey) 242 return false; 243 244 if (this->onHandleKey(key)) 245 return true; 246 247 // send an event to the focus-view 248 { 249 SkView* focus = this->getFocusView(); 250 if (focus == NULL) 251 focus = this; 252 253 SkEvent evt(SK_EventType_Key); 254 evt.setFast32(key); 255 if (focus->doEvent(evt)) 256 return true; 257 } 258 259 if (key == kUp_SkKey || key == kDown_SkKey) 260 { 261 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL) 262 this->onSetFocusView(NULL); 263 return true; 264 } 265 return false; 266 } 267 268 bool SkWindow::handleKeyUp(SkKey key) 269 { 270 if (key == kNONE_SkKey) 271 return false; 272 273 if (this->onHandleKeyUp(key)) 274 return true; 275 276 //send an event to the focus-view 277 { 278 SkView* focus = this->getFocusView(); 279 if (focus == NULL) 280 focus = this; 281 282 //should this one be the same? 283 SkEvent evt(SK_EventType_KeyUp); 284 evt.setFast32(key); 285 if (focus->doEvent(evt)) 286 return true; 287 } 288 return false; 289 } 290 291 void SkWindow::addMenu(SkOSMenu* menu) { 292 *fMenus.append() = menu; 293 this->onAddMenu(menu); 294 } 295 296 void SkWindow::setTitle(const char title[]) { 297 if (NULL == title) { 298 title = ""; 299 } 300 fTitle.set(title); 301 this->onSetTitle(title); 302 } 303 304 ////////////////////////////////////////////////////////////////////// 305 306 bool SkWindow::onEvent(const SkEvent& evt) 307 { 308 if (evt.isType(SK_EventDelayInval)) 309 { 310 SkRegion::Iterator iter(fDirtyRgn); 311 312 for (; !iter.done(); iter.next()) 313 this->onHandleInval(iter.rect()); 314 fWaitingOnInval = false; 315 return true; 316 } 317 return this->INHERITED::onEvent(evt); 318 } 319 320 bool SkWindow::onGetFocusView(SkView** focus) const 321 { 322 if (focus) 323 *focus = fFocusView; 324 return true; 325 } 326 327 bool SkWindow::onSetFocusView(SkView* focus) 328 { 329 if (fFocusView != focus) 330 { 331 if (fFocusView) 332 fFocusView->onFocusChange(false); 333 fFocusView = focus; 334 if (focus) 335 focus->onFocusChange(true); 336 } 337 return true; 338 } 339 340 ////////////////////////////////////////////////////////////////////// 341 342 void SkWindow::onHandleInval(const SkIRect&) 343 { 344 } 345 346 bool SkWindow::onHandleChar(SkUnichar) 347 { 348 return false; 349 } 350 351 bool SkWindow::onHandleKey(SkKey) 352 { 353 return false; 354 } 355 356 bool SkWindow::onHandleKeyUp(SkKey) 357 { 358 return false; 359 } 360 361 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner, 362 unsigned modifierKeys) { 363 return this->onDispatchClick(x, y, state, owner, modifierKeys); 364 } 365 366 bool SkWindow::onDispatchClick(int x, int y, Click::State state, 367 void* owner, unsigned modifierKeys) { 368 bool handled = false; 369 370 // First, attempt to find an existing click with this owner. 371 int index = -1; 372 for (int i = 0; i < fClicks.count(); i++) { 373 if (owner == fClicks[i]->fOwner) { 374 index = i; 375 break; 376 } 377 } 378 379 switch (state) { 380 case Click::kDown_State: { 381 if (index != -1) { 382 delete fClicks[index]; 383 fClicks.remove(index); 384 } 385 Click* click = this->findClickHandler(SkIntToScalar(x), 386 SkIntToScalar(y), modifierKeys); 387 388 if (click) { 389 click->fOwner = owner; 390 *fClicks.append() = click; 391 SkView::DoClickDown(click, x, y, modifierKeys); 392 handled = true; 393 } 394 break; 395 } 396 case Click::kMoved_State: 397 if (index != -1) { 398 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys); 399 handled = true; 400 } 401 break; 402 case Click::kUp_State: 403 if (index != -1) { 404 SkView::DoClickUp(fClicks[index], x, y, modifierKeys); 405 delete fClicks[index]; 406 fClicks.remove(index); 407 handled = true; 408 } 409 break; 410 default: 411 // Do nothing 412 break; 413 } 414 return handled; 415 } 416