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