• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(nullptr)
20 {
21     fClicks.reset();
22     fWaitingOnInval = false;
23     fMatrix.reset();
24 
25     fBitmap.allocN32Pixels(0, 0);
26 }
27 
~SkWindow()28 SkWindow::~SkWindow() {
29     fClicks.deleteAll();
30     fMenus.deleteAll();
31 }
32 
makeSurface()33 sk_sp<SkSurface> SkWindow::makeSurface() {
34     const SkBitmap& bm = this->getBitmap();
35     return SkSurface::MakeRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes(), &fSurfaceProps);
36 }
37 
setMatrix(const SkMatrix & matrix)38 void SkWindow::setMatrix(const SkMatrix& matrix) {
39     if (fMatrix != matrix) {
40         fMatrix = matrix;
41         this->inval(nullptr);
42     }
43 }
44 
preConcat(const SkMatrix & matrix)45 void SkWindow::preConcat(const SkMatrix& matrix) {
46     SkMatrix m;
47     m.setConcat(fMatrix, matrix);
48     this->setMatrix(m);
49 }
50 
postConcat(const SkMatrix & matrix)51 void SkWindow::postConcat(const SkMatrix& matrix) {
52     SkMatrix m;
53     m.setConcat(matrix, fMatrix);
54     this->setMatrix(m);
55 }
56 
resize(const SkImageInfo & info)57 void SkWindow::resize(const SkImageInfo& info) {
58     if (fBitmap.info() != info) {
59         fBitmap.allocPixels(info);
60         this->inval(nullptr);
61     }
62     this->setSize(SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height()));
63 }
64 
resize(int width,int height)65 void SkWindow::resize(int width, int height) {
66     this->resize(fBitmap.info().makeWH(width, height));
67 }
68 
setColorType(SkColorType ct,sk_sp<SkColorSpace> cs)69 void SkWindow::setColorType(SkColorType ct, sk_sp<SkColorSpace> cs) {
70     const SkImageInfo& info = fBitmap.info();
71     this->resize(SkImageInfo::Make(info.width(), info.height(), ct, kPremul_SkAlphaType, cs));
72 }
73 
handleInval(const SkRect * localR)74 bool SkWindow::handleInval(const SkRect* localR) {
75     SkIRect ir;
76 
77     if (localR) {
78         SkRect devR;
79         SkMatrix inverse;
80         if (!fMatrix.invert(&inverse)) {
81             return false;
82         }
83         fMatrix.mapRect(&devR, *localR);
84         devR.round(&ir);
85     } else {
86         ir.set(0, 0,
87                SkScalarRoundToInt(this->width()),
88                SkScalarRoundToInt(this->height()));
89     }
90     fDirtyRgn.op(ir, SkRegion::kUnion_Op);
91 
92     this->onHandleInval(ir);
93     return true;
94 }
95 
forceInvalAll()96 void SkWindow::forceInvalAll() {
97     fDirtyRgn.setRect(0, 0,
98                       SkScalarCeilToInt(this->width()),
99                       SkScalarCeilToInt(this->height()));
100 }
101 
102 #ifdef SK_SIMULATE_FAILED_MALLOC
103 extern bool gEnableControlledThrow;
104 #endif
105 
update(SkIRect * updateArea)106 bool SkWindow::update(SkIRect* updateArea) {
107     if (!fDirtyRgn.isEmpty()) {
108         sk_sp<SkSurface> surface(this->makeSurface());
109         SkCanvas* canvas = surface->getCanvas();
110 
111         canvas->clipRegion(fDirtyRgn);
112         if (updateArea) {
113             *updateArea = fDirtyRgn.getBounds();
114         }
115 
116         SkAutoCanvasRestore acr(canvas, true);
117         canvas->concat(fMatrix);
118 
119         // empty this now, so we can correctly record any inval calls that
120         // might be made during the draw call.
121         fDirtyRgn.setEmpty();
122 
123 #ifdef SK_SIMULATE_FAILED_MALLOC
124         gEnableControlledThrow = true;
125 #endif
126 #ifdef SK_BUILD_FOR_WIN32
127         //try {
128             this->draw(canvas);
129         //}
130         //catch (...) {
131         //}
132 #else
133         this->draw(canvas);
134 #endif
135 #ifdef SK_SIMULATE_FAILED_MALLOC
136         gEnableControlledThrow = false;
137 #endif
138 
139         return true;
140     }
141     return false;
142 }
143 
handleChar(SkUnichar uni)144 bool SkWindow::handleChar(SkUnichar uni) {
145     if (this->onHandleChar(uni))
146         return true;
147 
148     SkView* focus = this->getFocusView();
149     if (focus == nullptr)
150         focus = this;
151 
152     SkEvent evt(SK_EventType_Unichar);
153     evt.setFast32(uni);
154     return focus->doEvent(evt);
155 }
156 
handleKey(SkKey key)157 bool SkWindow::handleKey(SkKey key) {
158     if (key == kNONE_SkKey)
159         return false;
160 
161     if (this->onHandleKey(key))
162         return true;
163 
164     // send an event to the focus-view
165     {
166         SkView* focus = this->getFocusView();
167         if (focus == nullptr)
168             focus = this;
169 
170         SkEvent evt(SK_EventType_Key);
171         evt.setFast32(key);
172         if (focus->doEvent(evt))
173             return true;
174     }
175 
176     if (key == kUp_SkKey || key == kDown_SkKey) {
177         if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == nullptr)
178             this->onSetFocusView(nullptr);
179         return true;
180     }
181     return false;
182 }
183 
handleKeyUp(SkKey key)184 bool SkWindow::handleKeyUp(SkKey key) {
185     if (key == kNONE_SkKey)
186         return false;
187 
188     if (this->onHandleKeyUp(key))
189         return true;
190 
191     //send an event to the focus-view
192     {
193         SkView* focus = this->getFocusView();
194         if (focus == nullptr)
195             focus = this;
196 
197         //should this one be the same?
198         SkEvent evt(SK_EventType_KeyUp);
199         evt.setFast32(key);
200         if (focus->doEvent(evt))
201             return true;
202     }
203     return false;
204 }
205 
addMenu(SkOSMenu * menu)206 void SkWindow::addMenu(SkOSMenu* menu) {
207     *fMenus.append() = menu;
208     this->onAddMenu(menu);
209 }
210 
setTitle(const char title[])211 void SkWindow::setTitle(const char title[]) {
212     if (nullptr == title) {
213         title = "";
214     }
215     fTitle.set(title);
216     this->onSetTitle(title);
217 }
218 
onEvent(const SkEvent & evt)219 bool SkWindow::onEvent(const SkEvent& evt) {
220     if (evt.isType(SK_EventDelayInval)) {
221         for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
222             this->onHandleInval(iter.rect());
223         fWaitingOnInval = false;
224         return true;
225     }
226     return this->INHERITED::onEvent(evt);
227 }
228 
onGetFocusView(SkView ** focus) const229 bool SkWindow::onGetFocusView(SkView** focus) const {
230     if (focus)
231         *focus = fFocusView;
232     return true;
233 }
234 
onSetFocusView(SkView * focus)235 bool SkWindow::onSetFocusView(SkView* focus) {
236     if (fFocusView != focus) {
237         if (fFocusView)
238             fFocusView->onFocusChange(false);
239         fFocusView = focus;
240         if (focus)
241             focus->onFocusChange(true);
242     }
243     return true;
244 }
245 
onHandleInval(const SkIRect &)246 void SkWindow::onHandleInval(const SkIRect&) {
247 }
248 
onHandleChar(SkUnichar)249 bool SkWindow::onHandleChar(SkUnichar) {
250     return false;
251 }
252 
onHandleKey(SkKey)253 bool SkWindow::onHandleKey(SkKey) {
254     return false;
255 }
256 
onHandleKeyUp(SkKey)257 bool SkWindow::onHandleKeyUp(SkKey) {
258     return false;
259 }
260 
handleClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)261 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
262                            unsigned modifierKeys) {
263     return this->onDispatchClick(x, y, state, owner, modifierKeys);
264 }
265 
onDispatchClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)266 bool SkWindow::onDispatchClick(int x, int y, Click::State state,
267                                void* owner, unsigned modifierKeys) {
268     bool handled = false;
269 
270     // First, attempt to find an existing click with this owner.
271     int index = -1;
272     for (int i = 0; i < fClicks.count(); i++) {
273         if (owner == fClicks[i]->fOwner) {
274             index = i;
275             break;
276         }
277     }
278 
279     switch (state) {
280         case Click::kDown_State: {
281             if (index != -1) {
282                 delete fClicks[index];
283                 fClicks.remove(index);
284             }
285             Click* click = this->findClickHandler(SkIntToScalar(x),
286                                                   SkIntToScalar(y), modifierKeys);
287 
288             if (click) {
289                 click->fOwner = owner;
290                 *fClicks.append() = click;
291                 SkView::DoClickDown(click, x, y, modifierKeys);
292                 handled = true;
293             }
294             break;
295         }
296         case Click::kMoved_State:
297             if (index != -1) {
298                 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
299                 handled = true;
300             }
301             break;
302         case Click::kUp_State:
303             if (index != -1) {
304                 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
305                 delete fClicks[index];
306                 fClicks.remove(index);
307                 handled = true;
308             }
309             break;
310         default:
311             // Do nothing
312             break;
313     }
314     return handled;
315 }
316 
317 #if SK_SUPPORT_GPU
318 
319 #include "GrBackendSurface.h"
320 #include "GrContext.h"
321 #include "gl/GrGLInterface.h"
322 #include "gl/GrGLUtil.h"
323 #include "SkGr.h"
324 
makeGpuBackedSurface(const AttachmentInfo & attachmentInfo,const GrGLInterface * interface,GrContext * grContext)325 sk_sp<SkSurface> SkWindow::makeGpuBackedSurface(const AttachmentInfo& attachmentInfo,
326                                                 const GrGLInterface* interface,
327                                                 GrContext* grContext) {
328     int width = SkScalarRoundToInt(this->width());
329     int height = SkScalarRoundToInt(this->height());
330     if (0 == width || 0 == height) {
331         return nullptr;
332     }
333 
334     // TODO: Query the actual framebuffer for sRGB capable. However, to
335     // preserve old (fake-linear) behavior, we don't do this. Instead, rely
336     // on the flag (currently driven via 'C' mode in SampleApp).
337     //
338     // Also, we may not have real sRGB support (ANGLE, in particular), so check for
339     // that, and fall back to L32:
340     //
341     // ... and, if we're using a 10-bit/channel FB0, it doesn't do sRGB conversion on write,
342     // so pretend that it's non-sRGB 8888:
343     GrPixelConfig config = grContext->caps()->srgbSupport() &&
344                            info().colorSpace() &&
345                            (attachmentInfo.fColorBits != 30)
346                            ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
347     GrGLFramebufferInfo fbInfo;
348     GrGLint buffer;
349     GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
350     fbInfo.fFBOID = buffer;
351 
352     GrBackendRenderTarget backendRT(width,
353                                     height,
354                                     attachmentInfo.fSampleCount,
355                                     attachmentInfo.fStencilBits,
356                                     config,
357                                     fbInfo);
358 
359 
360     sk_sp<SkColorSpace> colorSpace =
361         grContext->caps()->srgbSupport() && info().colorSpace()
362         ? SkColorSpace::MakeSRGB() : nullptr;
363     return SkSurface::MakeFromBackendRenderTarget(grContext, backendRT, kBottomLeft_GrSurfaceOrigin,
364                                                   colorSpace, &fSurfaceProps);
365 }
366 
367 #endif
368