diff options
Diffstat (limited to 'gfx/skia/skia/src/views/SkWindow.cpp')
-rw-r--r-- | gfx/skia/skia/src/views/SkWindow.cpp | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/views/SkWindow.cpp b/gfx/skia/skia/src/views/SkWindow.cpp new file mode 100644 index 000000000..6e1ebf7a7 --- /dev/null +++ b/gfx/skia/skia/src/views/SkWindow.cpp @@ -0,0 +1,361 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkWindow.h" +#include "SkCanvas.h" +#include "SkOSMenu.h" +#include "SkSurface.h" +#include "SkSystemEventTypes.h" +#include "SkTime.h" + +#define SK_EventDelayInval "\xd" "n" "\xa" "l" + +SkWindow::SkWindow() + : fSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType) + , fFocusView(nullptr) +{ + fClicks.reset(); + fWaitingOnInval = false; + fMatrix.reset(); + + fBitmap.allocN32Pixels(0, 0); +} + +SkWindow::~SkWindow() { + fClicks.deleteAll(); + fMenus.deleteAll(); +} + +sk_sp<SkSurface> SkWindow::makeSurface() { + const SkBitmap& bm = this->getBitmap(); + return SkSurface::MakeRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes(), &fSurfaceProps); +} + +void SkWindow::setMatrix(const SkMatrix& matrix) { + if (fMatrix != matrix) { + fMatrix = matrix; + this->inval(nullptr); + } +} + +void SkWindow::preConcat(const SkMatrix& matrix) { + SkMatrix m; + m.setConcat(fMatrix, matrix); + this->setMatrix(m); +} + +void SkWindow::postConcat(const SkMatrix& matrix) { + SkMatrix m; + m.setConcat(matrix, fMatrix); + this->setMatrix(m); +} + +void SkWindow::resize(const SkImageInfo& info) { + if (fBitmap.info() != info) { + fBitmap.allocPixels(info); + this->inval(nullptr); + } + this->setSize(SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height())); +} + +void SkWindow::resize(int width, int height) { + this->resize(fBitmap.info().makeWH(width, height)); +} + +void SkWindow::setColorType(SkColorType ct, sk_sp<SkColorSpace> cs) { + const SkImageInfo& info = fBitmap.info(); + this->resize(SkImageInfo::Make(info.width(), info.height(), ct, kPremul_SkAlphaType, cs)); +} + +bool SkWindow::handleInval(const SkRect* localR) { + SkIRect ir; + + if (localR) { + SkRect devR; + SkMatrix inverse; + if (!fMatrix.invert(&inverse)) { + return false; + } + fMatrix.mapRect(&devR, *localR); + devR.round(&ir); + } else { + ir.set(0, 0, + SkScalarRoundToInt(this->width()), + SkScalarRoundToInt(this->height())); + } + fDirtyRgn.op(ir, SkRegion::kUnion_Op); + + this->onHandleInval(ir); + return true; +} + +void SkWindow::forceInvalAll() { + fDirtyRgn.setRect(0, 0, + SkScalarCeilToInt(this->width()), + SkScalarCeilToInt(this->height())); +} + +#ifdef SK_SIMULATE_FAILED_MALLOC +extern bool gEnableControlledThrow; +#endif + +bool SkWindow::update(SkIRect* updateArea) { + if (!fDirtyRgn.isEmpty()) { + sk_sp<SkSurface> surface(this->makeSurface()); + SkCanvas* canvas = surface->getCanvas(); + + canvas->clipRegion(fDirtyRgn); + if (updateArea) { + *updateArea = fDirtyRgn.getBounds(); + } + + SkAutoCanvasRestore acr(canvas, true); + canvas->concat(fMatrix); + + // empty this now, so we can correctly record any inval calls that + // might be made during the draw call. + fDirtyRgn.setEmpty(); + +#ifdef SK_SIMULATE_FAILED_MALLOC + gEnableControlledThrow = true; +#endif +#ifdef SK_BUILD_FOR_WIN32 + //try { + this->draw(canvas); + //} + //catch (...) { + //} +#else + this->draw(canvas); +#endif +#ifdef SK_SIMULATE_FAILED_MALLOC + gEnableControlledThrow = false; +#endif + + return true; + } + return false; +} + +bool SkWindow::handleChar(SkUnichar uni) { + if (this->onHandleChar(uni)) + return true; + + SkView* focus = this->getFocusView(); + if (focus == nullptr) + focus = this; + + SkEvent evt(SK_EventType_Unichar); + evt.setFast32(uni); + return focus->doEvent(evt); +} + +bool SkWindow::handleKey(SkKey key) { + if (key == kNONE_SkKey) + return false; + + if (this->onHandleKey(key)) + return true; + + // send an event to the focus-view + { + SkView* focus = this->getFocusView(); + if (focus == nullptr) + focus = this; + + SkEvent evt(SK_EventType_Key); + evt.setFast32(key); + if (focus->doEvent(evt)) + return true; + } + + if (key == kUp_SkKey || key == kDown_SkKey) { + if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == nullptr) + this->onSetFocusView(nullptr); + return true; + } + return false; +} + +bool SkWindow::handleKeyUp(SkKey key) { + if (key == kNONE_SkKey) + return false; + + if (this->onHandleKeyUp(key)) + return true; + + //send an event to the focus-view + { + SkView* focus = this->getFocusView(); + if (focus == nullptr) + focus = this; + + //should this one be the same? + SkEvent evt(SK_EventType_KeyUp); + evt.setFast32(key); + if (focus->doEvent(evt)) + return true; + } + return false; +} + +void SkWindow::addMenu(SkOSMenu* menu) { + *fMenus.append() = menu; + this->onAddMenu(menu); +} + +void SkWindow::setTitle(const char title[]) { + if (nullptr == title) { + title = ""; + } + fTitle.set(title); + this->onSetTitle(title); +} + +bool SkWindow::onEvent(const SkEvent& evt) { + if (evt.isType(SK_EventDelayInval)) { + for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next()) + this->onHandleInval(iter.rect()); + fWaitingOnInval = false; + return true; + } + return this->INHERITED::onEvent(evt); +} + +bool SkWindow::onGetFocusView(SkView** focus) const { + if (focus) + *focus = fFocusView; + return true; +} + +bool SkWindow::onSetFocusView(SkView* focus) { + if (fFocusView != focus) { + if (fFocusView) + fFocusView->onFocusChange(false); + fFocusView = focus; + if (focus) + focus->onFocusChange(true); + } + return true; +} + +void SkWindow::onHandleInval(const SkIRect&) { +} + +bool SkWindow::onHandleChar(SkUnichar) { + return false; +} + +bool SkWindow::onHandleKey(SkKey) { + return false; +} + +bool SkWindow::onHandleKeyUp(SkKey) { + return false; +} + +bool SkWindow::handleClick(int x, int y, Click::State state, void *owner, + unsigned modifierKeys) { + return this->onDispatchClick(x, y, state, owner, modifierKeys); +} + +bool SkWindow::onDispatchClick(int x, int y, Click::State state, + void* owner, unsigned modifierKeys) { + bool handled = false; + + // First, attempt to find an existing click with this owner. + int index = -1; + for (int i = 0; i < fClicks.count(); i++) { + if (owner == fClicks[i]->fOwner) { + index = i; + break; + } + } + + switch (state) { + case Click::kDown_State: { + if (index != -1) { + delete fClicks[index]; + fClicks.remove(index); + } + Click* click = this->findClickHandler(SkIntToScalar(x), + SkIntToScalar(y), modifierKeys); + + if (click) { + click->fOwner = owner; + *fClicks.append() = click; + SkView::DoClickDown(click, x, y, modifierKeys); + handled = true; + } + break; + } + case Click::kMoved_State: + if (index != -1) { + SkView::DoClickMoved(fClicks[index], x, y, modifierKeys); + handled = true; + } + break; + case Click::kUp_State: + if (index != -1) { + SkView::DoClickUp(fClicks[index], x, y, modifierKeys); + delete fClicks[index]; + fClicks.remove(index); + handled = true; + } + break; + default: + // Do nothing + break; + } + return handled; +} + +#if SK_SUPPORT_GPU + +#include "GrContext.h" +#include "gl/GrGLInterface.h" +#include "gl/GrGLUtil.h" +#include "SkGr.h" + +sk_sp<SkSurface> SkWindow::makeGpuBackedSurface(const AttachmentInfo& attachmentInfo, + const GrGLInterface* interface, + GrContext* grContext) { + GrBackendRenderTargetDesc desc; + desc.fWidth = SkScalarRoundToInt(this->width()); + desc.fHeight = SkScalarRoundToInt(this->height()); + if (0 == desc.fWidth || 0 == desc.fHeight) { + return nullptr; + } + + // TODO: Query the actual framebuffer for sRGB capable. However, to + // preserve old (fake-linear) behavior, we don't do this. Instead, rely + // on the flag (currently driven via 'C' mode in SampleApp). + // + // Also, we may not have real sRGB support (ANGLE, in particular), so check for + // that, and fall back to L32: + // + // ... and, if we're using a 10-bit/channel FB0, it doesn't do sRGB conversion on write, + // so pretend that it's non-sRGB 8888: + desc.fConfig = + grContext->caps()->srgbSupport() && + SkImageInfoIsGammaCorrect(info()) && + (attachmentInfo.fColorBits != 30) + ? kSkiaGamma8888_GrPixelConfig : kSkia8888_GrPixelConfig; + desc.fOrigin = kBottomLeft_GrSurfaceOrigin; + desc.fSampleCnt = attachmentInfo.fSampleCount; + desc.fStencilBits = attachmentInfo.fStencilBits; + GrGLint buffer; + GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer); + desc.fRenderTargetHandle = buffer; + + sk_sp<SkColorSpace> colorSpace = + grContext->caps()->srgbSupport() && SkImageInfoIsGammaCorrect(info()) + ? SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named) : nullptr; + return SkSurface::MakeFromBackendRenderTarget(grContext, desc, colorSpace, &fSurfaceProps); +} + +#endif |