/* * 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 "SkOSWindow_SDL.h" #include "SkCanvas.h" #include "SkColorPriv.h" #include "SkGLCanvas.h" #include "SkOSMenu.h" #include "SkTime.h" static void post_SkEvent_event() { SDL_Event evt; evt.type = SDL_USEREVENT; evt.user.type = SDL_USEREVENT; evt.user.code = 0; evt.user.data1 = NULL; evt.user.data2 = NULL; SDL_PushEvent(&evt); } static bool skia_setBitmapFromSurface(SkBitmap* dst, SDL_Surface* src) { SkBitmap::Config config; switch (src->format->BytesPerPixel) { case 2: config = SkBitmap::kRGB_565_Config; break; case 4: config = SkBitmap::kARGB_8888_Config; break; default: return false; } dst->setConfig(config, src->w, src->h, src->pitch); dst->setPixels(src->pixels); return true; } SkOSWindow::SkOSWindow(void* screen) { fScreen = reinterpret_cast(screen); this->resize(fScreen->w, fScreen->h); uint32_t rmask = SK_R32_MASK << SK_R32_SHIFT; uint32_t gmask = SK_G32_MASK << SK_G32_SHIFT; uint32_t bmask = SK_B32_MASK << SK_B32_SHIFT; uint32_t amask = SK_A32_MASK << SK_A32_SHIFT; if (fScreen->flags & SDL_OPENGL) { fSurface = NULL; fGLCanvas = new SkGLCanvas; fGLCanvas->setViewport(fScreen->w, fScreen->h); } else { fGLCanvas = NULL; fSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, fScreen->w, fScreen->h, 32, rmask, gmask, bmask, amask); } } SkOSWindow::~SkOSWindow() { delete fGLCanvas; if (fSurface) { SDL_FreeSurface(fSurface); } } #include void SkOSWindow::doDraw() { if (fGLCanvas) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); glEnable(GL_TEXTURE_2D); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); int count = fGLCanvas->save(); this->draw(fGLCanvas); fGLCanvas->restoreToCount(count); SDL_GL_SwapBuffers( ); } else { if ( SDL_MUSTLOCK(fSurface) ) { if ( SDL_LockSurface(fSurface) < 0 ) { return; } } SkBitmap bitmap; if (skia_setBitmapFromSurface(&bitmap, fSurface)) { SkCanvas canvas(bitmap); this->draw(&canvas); } if ( SDL_MUSTLOCK(fSurface) ) { SDL_UnlockSurface(fSurface); } int result = SDL_BlitSurface(fSurface, NULL, fScreen, NULL); if (result) { SkDebugf("------- SDL_BlitSurface returned %d\n", result); } SDL_UpdateRect(fScreen, 0, 0, fScreen->w, fScreen->h); } } static SkKey find_skkey(SDLKey src) { // this array must match the enum order in SkKey.h static const SDLKey gKeys[] = { SDLK_UNKNOWN, SDLK_UNKNOWN, // left softkey SDLK_UNKNOWN, // right softkey SDLK_UNKNOWN, // home SDLK_UNKNOWN, // back SDLK_UNKNOWN, // send SDLK_UNKNOWN, // end SDLK_0, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDLK_ASTERISK, SDLK_HASH, SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, SDLK_RETURN, // OK SDLK_UNKNOWN, // volume up SDLK_UNKNOWN, // volume down SDLK_UNKNOWN, // power SDLK_UNKNOWN, // camera }; const SDLKey* array = gKeys; for (size_t i = 0; i < SK_ARRAY_COUNT(gKeys); i++) { if (array[i] == src) { return static_cast(i); } } return kNONE_SkKey; } void SkOSWindow::handleSDLEvent(const SDL_Event& event) { switch (event.type) { case SDL_VIDEORESIZE: this->resize(event.resize.w, event.resize.h); break; case SDL_VIDEOEXPOSE: this->doDraw(); break; case SDL_MOUSEMOTION: if (event.motion.state == SDL_PRESSED) { this->handleClick(event.motion.x, event.motion.y, SkView::Click::kMoved_State); } break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: this->handleClick(event.button.x, event.button.y, event.button.state == SDL_PRESSED ? SkView::Click::kDown_State : SkView::Click::kUp_State); break; case SDL_KEYDOWN: { SkKey sk = find_skkey(event.key.keysym.sym); if (kNONE_SkKey != sk) { if (event.key.state == SDL_PRESSED) { this->handleKey(sk); } else { this->handleKeyUp(sk); } } break; } case SDL_USEREVENT: if (SkEvent::ProcessEvent()) { post_SkEvent_event(); } break; } } void SkOSWindow::onHandleInval(const SkIRect& r) { SDL_Event evt; evt.type = SDL_VIDEOEXPOSE; evt.expose.type = SDL_VIDEOEXPOSE; SDL_PushEvent(&evt); } void SkOSWindow::onSetTitle(const char title[]) { SDL_WM_SetCaption(title, NULL); } void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) {} /////////////////////////////////////////////////////////////////////////////////////// void SkEvent::SignalNonEmptyQueue() { SkDebugf("-------- signal nonempty\n"); post_SkEvent_event(); } static Uint32 timer_callback(Uint32 interval) { // SkDebugf("-------- timercallback %d\n", interval); SkEvent::ServiceQueueTimer(); return 0; } void SkEvent::SignalQueueTimer(SkMSec delay) { SDL_SetTimer(0, NULL); if (delay) { SDL_SetTimer(delay, timer_callback); } }