Recreate SkiaSurface when the window is resized

This commit is contained in:
David Capello 2015-04-16 20:32:15 -03:00
parent d36883e61e
commit 4bb7c87af5
10 changed files with 278 additions and 121 deletions

View File

@ -86,6 +86,8 @@ if(USE_SKIA_BACKEND)
CACHE INTERNAL "Skia libraries")
list(APPEND SHE_SOURCES
skia/skia_display.cpp
skia/skia_window.cpp
skia/she.cpp)
if(WIN32)

View File

@ -10,6 +10,9 @@
#include "base/string.h"
#include "she/font.h"
#include "she/locked_surface.h"
#include "she/scoped_surface_lock.h"
#include "she/surface.h"
namespace she {

View File

@ -14,18 +14,6 @@
#include "she/common/system.h"
#ifdef _WIN32
#include <windows.h>
#include "she/win/window.h"
#else
#error There is no Window implementation
#endif
#include "she/skia/skia_surface.h"
#include "she/skia/skia_event_queue.h"
#include "she/skia/skia_window.h"
#include "she/skia/skia_display.h"
#include "she/skia/skia_system.h"
namespace she {

View File

@ -0,0 +1,131 @@
// SHE library
// Copyright (C) 2012-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "she/skia/skia_display.h"
namespace she {
SkiaDisplay::SkiaDisplay(int width, int height, int scale)
: m_window(&m_queue, this)
, m_surface(new SkiaSurface)
{
m_surface->create(width, height);
m_window.setScale(scale);
m_window.setVisible(true);
m_recreated = false;
}
void SkiaDisplay::resize(const gfx::Size& size)
{
m_surface->dispose();
m_surface = new SkiaSurface;
m_surface->create(size.w, size.h);
m_recreated = true;
}
void SkiaDisplay::dispose()
{
delete this;
}
int SkiaDisplay::width() const
{
return m_window.clientSize().w;
}
int SkiaDisplay::height() const
{
return m_window.clientSize().h;
}
int SkiaDisplay::originalWidth() const
{
return m_window.restoredSize().w;
}
int SkiaDisplay::originalHeight() const
{
return m_window.restoredSize().h;
}
void SkiaDisplay::setScale(int scale)
{
m_window.setScale(scale);
}
int SkiaDisplay::scale() const
{
return m_window.scale();
}
NonDisposableSurface* SkiaDisplay::getSurface()
{
return static_cast<NonDisposableSurface*>(m_surface);
}
// Flips all graphics in the surface to the real display. Returns
// false if the flip couldn't be done because the display was
// resized.
bool SkiaDisplay::flip()
{
if (m_recreated) {
m_recreated = false;
return false;
}
m_window.invalidate();
return true;
}
void SkiaDisplay::maximize()
{
m_window.maximize();
}
bool SkiaDisplay::isMaximized() const
{
return m_window.isMaximized();
}
void SkiaDisplay::setTitleBar(const std::string& title)
{
m_window.setText(title);
}
EventQueue* SkiaDisplay::getEventQueue()
{
return &m_queue;
}
bool SkiaDisplay::setNativeMouseCursor(NativeCursor cursor)
{
return true;
}
void SkiaDisplay::setMousePosition(const gfx::Point& position)
{
}
void SkiaDisplay::captureMouse()
{
m_window.captureMouse();
}
void SkiaDisplay::releaseMouse()
{
m_window.releaseMouse();
}
DisplayHandle SkiaDisplay::nativeHandle()
{
return (DisplayHandle)m_window.handle();
}
} // namespace she

View File

@ -4,101 +4,63 @@
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef SHE_SKIA_SKIA_DISPLAY_INCLUDED
#define SHE_SKIA_SKIA_DISPLAY_INCLUDED
#pragma once
#include "she/display.h"
#include "she/skia/skia_event_queue.h"
#include "she/skia/skia_window.h"
namespace she {
class SkiaSurface;
class SkiaDisplay : public Display {
public:
SkiaDisplay(int width, int height, int scale)
: m_window(&m_queue, this) {
m_surface.create(width, height);
m_window.setScale(scale);
m_window.setVisible(true);
}
SkiaDisplay(int width, int height, int scale);
void dispose() override {
delete this;
}
void resize(const gfx::Size& size);
void dispose() override;
// Returns the real and current display's size (without scale applied).
int width() const override {
return m_window.clientSize().w;
}
int height() const override {
return m_window.clientSize().h;
}
int width() const override;
int height() const override;
// Returns the display when it was not maximized.
int originalWidth() const override {
return m_window.restoredSize().w;
}
int originalWidth() const override;
int originalHeight() const override;
int originalHeight() const override {
return m_window.restoredSize().h;
}
void setScale(int scale) override {
m_window.setScale(scale);
}
int scale() const override {
return m_window.scale();
}
void setScale(int scale) override;
int scale() const override;
// Returns the main surface to draw into this display.
// You must not dispose this surface.
NonDisposableSurface* getSurface() override {
return static_cast<NonDisposableSurface*>(&m_surface);
}
NonDisposableSurface* getSurface() override;
// Flips all graphics in the surface to the real display. Returns
// false if the flip couldn't be done because the display was
// resized.
bool flip() override {
m_window.invalidate();
return true;
}
void maximize() override {
m_window.maximize();
}
bool isMaximized() const override {
return m_window.isMaximized();
}
void setTitleBar(const std::string& title) override {
m_window.setText(title);
}
EventQueue* getEventQueue() override {
return &m_queue;
}
bool setNativeMouseCursor(NativeCursor cursor) override {
return true;
}
void setMousePosition(const gfx::Point& position) override {
}
void captureMouse() override {
m_window.captureMouse();
}
void releaseMouse() override {
m_window.releaseMouse();
}
bool flip() override;
void maximize() override;
bool isMaximized() const override;
void setTitleBar(const std::string& title) override;
EventQueue* getEventQueue() override;
bool setNativeMouseCursor(NativeCursor cursor) override;
void setMousePosition(const gfx::Point& position) override;
void captureMouse() override;
void releaseMouse() override;
// Returns the HWND on Windows.
DisplayHandle nativeHandle() override {
return (DisplayHandle)m_window.handle();
}
DisplayHandle nativeHandle() override;
private:
SkiaEventQueue m_queue;
SkiaWindow m_window;
SkiaSurface m_surface;
SkiaSurface* m_surface;
bool m_recreated;
};
} // namespace she
#endif

View File

@ -4,8 +4,17 @@
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef SHE_SKIA_SKIA_EVENT_QUEUE_INCLUDED
#define SHE_SKIA_SKIA_EVENT_QUEUE_INCLUDED
#pragma once
#include <queue>
#include <windows.h>
#include "she/event.h"
#include "she/event_queue.h"
namespace she {
class SkiaEventQueue : public EventQueue {
@ -56,3 +65,5 @@ private:
};
} // namespace she
#endif

View File

@ -4,12 +4,19 @@
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef SHE_SKIA_SKIA_SYSTEM_INCLUDED
#define SHE_SKIA_SKIA_SYSTEM_INCLUDED
#pragma once
#include "base/file_handle.h"
#include "SkImageDecoder.h"
#include "SkPixelRef.h"
#include "SkStream.h"
#include "she/skia/skia_display.h"
#include "she/skia/skia_surface.h"
namespace she {
class SkiaSystem : public CommonSystem {
@ -88,3 +95,5 @@ private:
};
} // namespace she
#endif

View File

@ -0,0 +1,62 @@
// SHE library
// Copyright (C) 2012-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "she/skia/skia_window.h"
#include "she/skia/skia_display.h"
namespace she {
SkiaWindow::SkiaWindow(SkiaEventQueue* queue, SkiaDisplay* display)
: m_queue(queue)
, m_display(display)
{
}
void SkiaWindow::queueEventImpl(Event& ev)
{
ev.setDisplay(m_display);
m_queue->queueEvent(ev);
}
void SkiaWindow::paintImpl(HDC hdc)
{
SkiaSurface* surface = static_cast<SkiaSurface*>(m_display->getSurface());
const SkBitmap& bitmap = surface->bitmap();
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = bitmap.width();
bmi.bmiHeader.biHeight = -bitmap.height();
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
ASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
bitmap.lockPixels();
int ret = StretchDIBits(hdc,
0, 0, bitmap.width()*scale(), bitmap.height()*scale(),
0, 0, bitmap.width(), bitmap.height(),
bitmap.getPixels(),
&bmi, DIB_RGB_COLORS, SRCCOPY);
(void)ret;
bitmap.unlockPixels();
}
void SkiaWindow::resizeImpl(const gfx::Size& size)
{
m_display->resize(size);
}
} // namespace she

View File

@ -4,50 +4,35 @@
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef SHE_SKIA_SKIA_WINDOW_INCLUDED
#define SHE_SKIA_SKIA_WINDOW_INCLUDED
#pragma once
#ifdef _WIN32
#include "she/win/window.h"
#else
#error There is no Window implementation
#endif
#include "she/skia/skia_event_queue.h"
#include "she/skia/skia_surface.h"
namespace she {
class SkiaDisplay;
class SkiaWindow : public Window<SkiaWindow> {
public:
SkiaWindow(SkiaEventQueue* queue, Display* display)
: m_queue(queue)
, m_display(display) {
}
void queueEventImpl(Event& ev) {
ev.setDisplay(m_display);
m_queue->queueEvent(ev);
}
void paintImpl(HDC hdc) {
SkiaSurface* surface = static_cast<SkiaSurface*>(m_display->getSurface());
const SkBitmap& bitmap = surface->bitmap();
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = bitmap.width();
bmi.bmiHeader.biHeight = -bitmap.height();
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
ASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
bitmap.lockPixels();
int ret = StretchDIBits(hdc,
0, 0, bitmap.width()*scale(), bitmap.height()*scale(),
0, 0, bitmap.width(), bitmap.height(),
bitmap.getPixels(),
&bmi, DIB_RGB_COLORS, SRCCOPY);
(void)ret;
bitmap.unlockPixels();
}
SkiaWindow(SkiaEventQueue* queue, SkiaDisplay* display);
void queueEventImpl(Event& ev);
void paintImpl(HDC hdc);
void resizeImpl(const gfx::Size& size);
private:
SkiaEventQueue* m_queue;
Display* m_display;
SkiaDisplay* m_display;
};
} // namespace she
#endif

View File

@ -12,6 +12,8 @@
#include <windowsx.h>
#include <commctrl.h>
#include "gfx/size.h"
#include "she/event.h"
#include "she/keys.h"
#ifndef WM_MOUSEHWHEEL
@ -118,6 +120,8 @@ namespace she {
case SIZE_RESTORED:
m_clientSize.w = GET_X_LPARAM(lparam);
m_clientSize.h = GET_Y_LPARAM(lparam);
static_cast<T*>(this)->resizeImpl(m_clientSize);
break;
}