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 void SkWindow::setMatrix(const SkMatrix& matrix) { 70 if (fMatrix != matrix) { 71 fMatrix = matrix; 72 this->inval(NULL); 73 } 74 } 75 76 void SkWindow::preConcat(const SkMatrix& matrix) { 77 SkMatrix m; 78 m.setConcat(fMatrix, matrix); 79 this->setMatrix(m); 80 } 81 82 void SkWindow::postConcat(const SkMatrix& matrix) { 83 SkMatrix m; 84 m.setConcat(matrix, fMatrix); 85 this->setMatrix(m); 86 } 87 88 void SkWindow::setConfig(SkBitmap::Config config) 89 { 90 this->resize(fBitmap.width(), fBitmap.height(), config); 91 } 92 93 void SkWindow::resize(int width, int height, SkBitmap::Config config) 94 { 95 if (config == SkBitmap::kNo_Config) 96 config = fConfig; 97 98 if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig) 99 { 100 fConfig = config; 101 fBitmap.setConfig(config, width, height); 102 fBitmap.allocPixels(); 103 fBitmap.setIsOpaque(true); 104 105 this->setSize(SkIntToScalar(width), SkIntToScalar(height)); 106 this->inval(NULL); 107 } 108 } 109 110 void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) 111 { 112 fBitmap.eraseARGB(a, r, g, b); 113 } 114 115 void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b) 116 { 117 fBitmap.eraseRGB(r, g, b); 118 } 119 120 bool SkWindow::handleInval(const SkRect* localR) 121 { 122 SkIRect ir; 123 124 if (localR) { 125 SkRect devR; 126 SkMatrix inverse; 127 if (!fMatrix.invert(&inverse)) { 128 return false; 129 } 130 fMatrix.mapRect(&devR, *localR); 131 devR.round(&ir); 132 } else { 133 ir.set(0, 0, 134 SkScalarRound(this->width()), 135 SkScalarRound(this->height())); 136 } 137 fDirtyRgn.op(ir, SkRegion::kUnion_Op); 138 139 this->onHandleInval(ir); 140 return true; 141 } 142 143 void SkWindow::forceInvalAll() { 144 fDirtyRgn.setRect(0, 0, 145 SkScalarCeil(this->width()), 146 SkScalarCeil(this->height())); 147 } 148 149 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 150 #include <windows.h> 151 #include <gx.h> 152 extern GXDisplayProperties gDisplayProps; 153 #endif 154 155 #ifdef SK_SIMULATE_FAILED_MALLOC 156 extern bool gEnableControlledThrow; 157 #endif 158 159 bool SkWindow::update(SkIRect* updateArea, SkCanvas* canvas) 160 { 161 if (!fDirtyRgn.isEmpty()) 162 { 163 SkBitmap bm = this->getBitmap(); 164 165 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 166 char* buffer = (char*)GXBeginDraw(); 167 SkASSERT(buffer); 168 169 RECT rect; 170 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect); 171 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch; 172 173 bm.setPixels(buffer); 174 #endif 175 176 SkCanvas rasterCanvas; 177 178 if (NULL == canvas) { 179 canvas = &rasterCanvas; 180 } 181 canvas->setBitmapDevice(bm); 182 183 canvas->clipRegion(fDirtyRgn); 184 if (updateArea) 185 *updateArea = fDirtyRgn.getBounds(); 186 187 SkAutoCanvasRestore acr(canvas, true); 188 canvas->concat(fMatrix); 189 190 // empty this now, so we can correctly record any inval calls that 191 // might be made during the draw call. 192 fDirtyRgn.setEmpty(); 193 194 #ifdef TEST_BOUNDER 195 test_bounder b(bm); 196 canvas->setBounder(&b); 197 #endif 198 #ifdef SK_SIMULATE_FAILED_MALLOC 199 gEnableControlledThrow = true; 200 #endif 201 #ifdef SK_BUILD_FOR_WIN32 202 //try { 203 this->draw(canvas); 204 //} 205 //catch (...) { 206 //} 207 #else 208 this->draw(canvas); 209 #endif 210 #ifdef SK_SIMULATE_FAILED_MALLOC 211 gEnableControlledThrow = false; 212 #endif 213 #ifdef TEST_BOUNDER 214 canvas->setBounder(NULL); 215 #endif 216 217 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 218 GXEndDraw(); 219 #endif 220 221 return true; 222 } 223 return false; 224 } 225 226 bool SkWindow::handleChar(SkUnichar uni) 227 { 228 if (this->onHandleChar(uni)) 229 return true; 230 231 SkView* focus = this->getFocusView(); 232 if (focus == NULL) 233 focus = this; 234 235 SkEvent evt(SK_EventType_Unichar); 236 evt.setFast32(uni); 237 return focus->doEvent(evt); 238 } 239 240 bool SkWindow::handleKey(SkKey key) 241 { 242 if (key == kNONE_SkKey) 243 return false; 244 245 if (this->onHandleKey(key)) 246 return true; 247 248 // send an event to the focus-view 249 { 250 SkView* focus = this->getFocusView(); 251 if (focus == NULL) 252 focus = this; 253 254 SkEvent evt(SK_EventType_Key); 255 evt.setFast32(key); 256 if (focus->doEvent(evt)) 257 return true; 258 } 259 260 if (key == kUp_SkKey || key == kDown_SkKey) 261 { 262 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL) 263 this->onSetFocusView(NULL); 264 return true; 265 } 266 return false; 267 } 268 269 bool SkWindow::handleKeyUp(SkKey key) 270 { 271 if (key == kNONE_SkKey) 272 return false; 273 274 if (this->onHandleKeyUp(key)) 275 return true; 276 277 //send an event to the focus-view 278 { 279 SkView* focus = this->getFocusView(); 280 if (focus == NULL) 281 focus = this; 282 283 //should this one be the same? 284 SkEvent evt(SK_EventType_KeyUp); 285 evt.setFast32(key); 286 if (focus->doEvent(evt)) 287 return true; 288 } 289 return false; 290 } 291 292 void SkWindow::addMenu(SkOSMenu* menu) { 293 *fMenus.append() = menu; 294 this->onAddMenu(menu); 295 } 296 297 void SkWindow::setTitle(const char title[]) { 298 if (NULL == title) { 299 title = ""; 300 } 301 fTitle.set(title); 302 this->onSetTitle(title); 303 } 304 305 ////////////////////////////////////////////////////////////////////// 306 307 bool SkWindow::onEvent(const SkEvent& evt) 308 { 309 if (evt.isType(SK_EventDelayInval)) 310 { 311 SkRegion::Iterator iter(fDirtyRgn); 312 313 for (; !iter.done(); iter.next()) 314 this->onHandleInval(iter.rect()); 315 fWaitingOnInval = false; 316 return true; 317 } 318 return this->INHERITED::onEvent(evt); 319 } 320 321 bool SkWindow::onGetFocusView(SkView** focus) const 322 { 323 if (focus) 324 *focus = fFocusView; 325 return true; 326 } 327 328 bool SkWindow::onSetFocusView(SkView* focus) 329 { 330 if (fFocusView != focus) 331 { 332 if (fFocusView) 333 fFocusView->onFocusChange(false); 334 fFocusView = focus; 335 if (focus) 336 focus->onFocusChange(true); 337 } 338 return true; 339 } 340 341 ////////////////////////////////////////////////////////////////////// 342 343 void SkWindow::onHandleInval(const SkIRect&) 344 { 345 } 346 347 bool SkWindow::onHandleChar(SkUnichar) 348 { 349 return false; 350 } 351 352 bool SkWindow::onHandleKey(SkKey key) 353 { 354 return false; 355 } 356 357 bool SkWindow::onHandleKeyUp(SkKey key) 358 { 359 return false; 360 } 361 362 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner) { 363 return this->onDispatchClick(x, y, state, owner); 364 } 365 366 bool SkWindow::onDispatchClick(int x, int y, Click::State state, 367 void* owner) { 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)); 387 388 if (click) { 389 click->fOwner = owner; 390 *fClicks.append() = click; 391 SkView::DoClickDown(click, x, y); 392 handled = true; 393 } 394 break; 395 } 396 case Click::kMoved_State: 397 if (index != -1) { 398 SkView::DoClickMoved(fClicks[index], x, y); 399 handled = true; 400 } 401 break; 402 case Click::kUp_State: 403 if (index != -1) { 404 SkView::DoClickUp(fClicks[index], x, y); 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 417