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