Merge branch 'skia'

This commit is contained in:
David Capello 2015-05-26 17:24:59 -03:00
commit 26b170e67f
22 changed files with 761 additions and 202 deletions

View File

@ -55,10 +55,10 @@ std::string show_file_selector(const std::string& title,
dlg->addFilter("*." + tok, tok + " files (*." + tok + ")");
dlg->addFilter("*.*", "All files (*.*)");
if (dlg->show(she::instance()->defaultDisplay()->nativeHandle())) {
if (dlg->show(she::instance()->defaultDisplay()->nativeHandle()))
res = dlg->getFileName();
dlg->dispose();
}
dlg->dispose();
return res;
}
}

View File

@ -19,9 +19,19 @@ if(USE_ALLEG4_BACKEND)
endif()
if(USE_SKIA_BACKEND)
set(SKIA_BUILD_DIR "" CACHE PATH "Skia build directory")
set(SKIA_DIR "" CACHE PATH "Skia source code directory")
add_definitions(
-DSK_INTERNAL
-DSK_GAMMA_SRGB
-DSK_GAMMA_APPLY_TO_A8
-DSK_SCALAR_TO_FLOAT_EXCLUDED
-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1
-DSK_SUPPORT_GPU=1
-DSK_SUPPORT_OPENCL=0
-DSK_FORCE_DISTANCE_FIELD_TEXT=0
-DGR_GL_FUNCTION_TYPE=__stdcall)
add_definitions(-DSK_INTERNAL -DSK_GAMMA_SRGB -DSK_GAMMA_APPLY_TO_A8 -DSK_SCALAR_TO_FLOAT_EXCLUDED -DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1 -DSK_SUPPORT_GPU=1 -DSK_SUPPORT_OPENCL=0 -DSK_FORCE_DISTANCE_FIELD_TEXT=0 -DGR_GL_FUNCTION_TYPE=__stdcall)
if(WIN32)
add_definitions(-DSK_BUILD_FOR_WIN32)
elseif(APPLE)
@ -29,10 +39,10 @@ if(USE_SKIA_BACKEND)
endif()
if(CMAKE_BUILD_TYPE STREQUAL Debug)
set(SKIA_BUILD_OUT_DIR "${SKIA_BUILD_DIR}/out/Debug")
set(SKIA_BUILD_OUT_DIR "${SKIA_DIR}/out/Debug")
add_definitions(-DSK_DEVELOPER=1)
else()
set(SKIA_BUILD_OUT_DIR "${SKIA_BUILD_DIR}/out/Release")
set(SKIA_BUILD_OUT_DIR "${SKIA_DIR}/out/Release")
endif()
find_library(SKIA_CORE_LIBRARY skia_core PATH "${SKIA_BUILD_OUT_DIR}")
@ -46,34 +56,46 @@ if(USE_SKIA_BACKEND)
find_library(SKIA_GPU_LIBRARY skia_skgpu PATH "${SKIA_BUILD_OUT_DIR}")
find_library(SKIA_UTILS_LIBRARY skia_utils PATH "${SKIA_BUILD_OUT_DIR}")
set(SKIA_LIBEGL_LIBRARY "")
if(WIN32)
find_library(ETC1_LIBRARY libetc1 PATH "${SKIA_BUILD_OUT_DIR}/obj/gyp")
find_library(LIBSKKTX_LIBRARY libSkKTX PATH "${SKIA_BUILD_OUT_DIR}/obj/gyp")
find_library(OPENGL32_LIBRARY opengl32)
find_library(SKIA_ETC1_LIBRARY libetc1 PATH "${SKIA_BUILD_OUT_DIR}/obj/gyp")
find_library(SKIA_LIBSKKTX_LIBRARY libSkKTX PATH "${SKIA_BUILD_OUT_DIR}/obj/gyp")
find_library(SKIA_OPENGL32_LIBRARY opengl32)
find_library(SKIA_LIBEGL_LIBRARY libEGL.dll.lib PATH "${SKIA_BUILD_OUT_DIR}")
if(SKIA_LIBEGL_LIBRARY)
add_definitions(-DSK_ANGLE=1)
endif()
else()
set(ETC1_LIBRARY)
set(LIBSKKTX_LIBRARY)
# find_library(OPENGL32_LIBRARY glapi)
set(OPENGL32_LIBRARY)
set(SKIA_ETC1_LIBRARY)
set(SKIA_LIBSKKTX_LIBRARY)
# find_library(SKIA_OPENGL32_LIBRARY glapi)
set(SKIA_OPENGL32_LIBRARY)
endif()
find_path(SKIA_CONFIG_INCLUDE_DIR SkUserConfig.h HINTS "${SKIA_BUILD_DIR}/include/config")
find_path(SKIA_CORE_INCLUDE_DIR SkCanvas.h HINTS "${SKIA_BUILD_DIR}/include/core")
find_path(SKIA_EFFECTS_INCLUDE_DIR SkBitmapSource.h HINTS "${SKIA_BUILD_DIR}/include/effects")
find_path(SKIA_GPU_INCLUDE_DIR SkGr.h HINTS "${SKIA_BUILD_DIR}/include/gpu")
find_path(SKIA_UTILS_INCLUDE_DIR SkRandom.h HINTS "${SKIA_BUILD_DIR}/include/utils")
find_path(SKIA_CONFIG_INCLUDE_DIR SkUserConfig.h HINTS "${SKIA_DIR}/include/config")
find_path(SKIA_CORE_INCLUDE_DIR SkCanvas.h HINTS "${SKIA_DIR}/include/core")
find_path(SKIA_EFFECTS_INCLUDE_DIR SkBitmapSource.h HINTS "${SKIA_DIR}/include/effects")
find_path(SKIA_GPU_INCLUDE_DIR SkGr.h HINTS "${SKIA_DIR}/include/gpu")
find_path(SKIA_UTILS_INCLUDE_DIR SkRandom.h HINTS "${SKIA_DIR}/include/utils")
set(SKIA_ANGLE_INCLUDE_DIR "")
if(WIN32)
find_path(SKIA_ANGLE_INCLUDE_DIR angle_gl.h HINTS "${SKIA_DIR}/third_party/externals/angle2/include")
endif()
include_directories(
${SKIA_CONFIG_INCLUDE_DIR}
${SKIA_CORE_INCLUDE_DIR}
${SKIA_GPU_INCLUDE_DIR}
${SKIA_PORTS_INCLUDE_DIR}
${SKIA_UTILS_INCLUDE_DIR})
${SKIA_UTILS_INCLUDE_DIR}
${SKIA_ANGLE_INCLUDE_DIR})
set(SKIA_LIBRARIES
${ETC1_LIBRARY}
${LIBSKKTX_LIBRARY}
${OPENGL32_LIBRARY}
${SKIA_ETC1_LIBRARY}
${SKIA_LIBSKKTX_LIBRARY}
${SKIA_OPENGL32_LIBRARY}
${SKIA_LIBEGL_LIBRARY}
${SKIA_CORE_LIBRARY}
${SKIA_EFFECTS_LIBRARY}
${SKIA_GPU_LIBRARY}
@ -87,11 +109,11 @@ if(USE_SKIA_BACKEND)
list(APPEND SHE_SOURCES
skia/skia_display.cpp
skia/skia_window.cpp
skia/she.cpp)
if(WIN32)
list(APPEND SHE_SOURCES
skia/skia_window_win.cpp
win/vk.cpp)
endif()
endif()

View File

@ -135,7 +135,7 @@ public:
event.setType(Event::None);
}
void queueEvent(const Event& event) {
void queueEvent(const Event& event) override {
m_events.push(event);
}

View File

@ -349,6 +349,13 @@ namespace she {
width, height);
}
void scrollTo(const gfx::Rect& rc, int dx, int dy) override {
blit(m_bmp, m_bmp,
rc.x, rc.y,
rc.x+dx, rc.y+dy,
rc.w, rc.h);
}
void drawSurface(const LockedSurface* src, int dstx, int dsty) override {
draw_sprite(m_bmp, static_cast<const Alleg4Surface*>(src)->m_bmp, dstx, dsty);
}

View File

@ -14,6 +14,8 @@
#include "she/scoped_surface_lock.h"
#include "she/surface.h"
#include <vector>
namespace she {
class CommonFont : public Font {

View File

@ -16,6 +16,7 @@ namespace she {
public:
virtual ~EventQueue() { }
virtual void getEvent(Event& ev, bool canWait) = 0;
virtual void queueEvent(const Event& ev) = 0;
};
} // namespace she

View File

@ -44,6 +44,7 @@ namespace she {
virtual void fillRect(gfx::Color color, const gfx::Rect& rc) = 0;
virtual void blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const = 0;
virtual void scrollTo(const gfx::Rect& rc, int dx, int dy) = 0;
virtual void drawSurface(const LockedSurface* src, int dstx, int dsty) = 0;
virtual void drawRgbaSurface(const LockedSurface* src, int dstx, int dsty) = 0;
virtual void drawColoredRgbaSurface(const LockedSurface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clip) = 0;

View File

@ -0,0 +1,111 @@
// 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.
#include <windows.h>
#include "GL/gl.h"
#include "gl/SkGLContext.h"
namespace she {
class GLContextWGL : public SkGLContext {
public:
GLContextWGL(HWND hwnd, GrGLStandard forcedGpuAPI)
: m_hwnd(hwnd)
, m_glrc(nullptr) {
HDC hdc = GetDC(m_hwnd);
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL, // support OpenGL
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
8, // 8-bit alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
0, // no z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
int pixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, pixelFormat, &pfd);
m_glrc = wglCreateContext(hdc);
if (!m_glrc) {
ReleaseDC(m_hwnd, hdc);
return;
}
wglMakeCurrent(hdc, m_glrc);
fGL.reset(GrGLCreateNativeInterface());
if (!fGL) {
ReleaseDC(m_hwnd, hdc);
destroy();
return;
}
if (!fGL->validate()) {
ReleaseDC(m_hwnd, hdc);
destroy();
return;
}
ReleaseDC(m_hwnd, hdc);
}
~GLContextWGL() {
destroy();
}
void makeCurrent() const override {
HDC hdc = GetDC(m_hwnd);
wglMakeCurrent(hdc, m_glrc);
ReleaseDC(m_hwnd, hdc);
}
void swapBuffers() const override {
HDC hdc = GetDC(m_hwnd);
SwapBuffers(hdc);
ReleaseDC(m_hwnd, hdc);
}
int getStencilBits() {
HDC hdc = GetDC(m_hwnd);
int pixelFormat = GetPixelFormat(hdc);
PIXELFORMATDESCRIPTOR pfd;
DescribePixelFormat(hdc, pixelFormat, sizeof(pfd), &pfd);
ReleaseDC(m_hwnd, hdc);
return pfd.cStencilBits;
}
int getSampleCount() {
return 0; // TODO
}
private:
void destroy() {
fGL.reset(nullptr);
if (m_glrc) {
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(m_glrc);
m_glrc = nullptr;
}
}
HWND m_hwnd;
HGLRC m_glrc;
};
} // namespace she

View File

@ -12,9 +12,11 @@
namespace she {
SkiaDisplay::SkiaDisplay(int width, int height, int scale)
: m_window(&m_queue, this)
SkiaDisplay::SkiaDisplay(EventQueue* queue, int width, int height, int scale)
: m_queue(queue)
, m_window(m_queue, this)
, m_surface(new SkiaSurface)
, m_customSurface(false)
{
m_surface->create(width, height);
m_window.setScale(scale);
@ -22,8 +24,18 @@ SkiaDisplay::SkiaDisplay(int width, int height, int scale)
m_recreated = false;
}
void SkiaDisplay::setSkiaSurface(SkiaSurface* surface)
{
m_surface->dispose();
m_surface = surface;
m_customSurface = true;
}
void SkiaDisplay::resize(const gfx::Size& size)
{
if (m_customSurface)
return;
m_surface->dispose();
m_surface = new SkiaSurface;
m_surface->create(size.w, size.h);
@ -80,7 +92,7 @@ bool SkiaDisplay::flip()
return false;
}
m_window.invalidate();
m_window.updateWindow();
return true;
}
@ -101,16 +113,18 @@ void SkiaDisplay::setTitleBar(const std::string& title)
EventQueue* SkiaDisplay::getEventQueue()
{
return &m_queue;
return m_queue;
}
bool SkiaDisplay::setNativeMouseCursor(NativeCursor cursor)
{
m_window.setNativeMouseCursor(cursor);
return true;
}
void SkiaDisplay::setMousePosition(const gfx::Point& position)
{
m_window.setMousePosition(position);
}
void SkiaDisplay::captureMouse()

View File

@ -9,8 +9,12 @@
#pragma once
#include "she/display.h"
#include "she/skia/skia_event_queue.h"
#include "she/skia/skia_window.h"
#ifdef _WIN32
#include "she/skia/skia_window_win.h"
#else
#error There is no SkiaWindow implementation for your platform
#endif
namespace she {
@ -18,7 +22,9 @@ class SkiaSurface;
class SkiaDisplay : public Display {
public:
SkiaDisplay(int width, int height, int scale);
SkiaDisplay(EventQueue* queue, int width, int height, int scale);
void setSkiaSurface(SkiaSurface* surface);
void resize(const gfx::Size& size);
void dispose() override;
@ -55,10 +61,11 @@ public:
DisplayHandle nativeHandle() override;
private:
SkiaEventQueue m_queue;
EventQueue* m_queue;
SkiaWindow m_window;
SkiaSurface* m_surface;
bool m_recreated;
bool m_customSurface;
};
} // namespace she

View File

@ -8,15 +8,18 @@
#define SHE_SKIA_SKIA_SURFACE_INCLUDED
#pragma once
#include "she/common/locked_surface.h"
#include "base/unique_ptr.h"
#include "gfx/clip.h"
#include "she/common/font.h"
#include "she/locked_surface.h"
#include "she/scoped_surface_lock.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkImageInfo.h"
#include "SkRegion.h"
#include "SkSurface.h"
namespace she {
@ -29,25 +32,49 @@ inline SkRect to_skia(const gfx::Rect& rc) {
}
class SkiaSurface : public NonDisposableSurface
, public CommonLockedSurface {
, public LockedSurface {
public:
SkiaSurface() {
SkiaSurface() : m_surface(nullptr)
, m_canvas(nullptr) {
}
SkiaSurface(SkSurface* surface)
: m_surface(surface)
, m_canvas(m_surface->getCanvas())
, m_clip(0, 0, width(), height())
{
}
~SkiaSurface() {
if (!m_surface)
delete m_canvas;
}
void create(int width, int height) {
ASSERT(!m_surface);
m_bitmap.tryAllocPixels(
SkImageInfo::MakeN32Premul(width, height));
m_bitmap.eraseColor(SK_ColorTRANSPARENT);
rebuild();
}
void createRgba(int width, int height) {
ASSERT(!m_surface);
m_bitmap.tryAllocPixels(
SkImageInfo::MakeN32Premul(width, height));
m_bitmap.eraseColor(SK_ColorTRANSPARENT);
rebuild();
}
void flush() {
if (m_canvas)
m_canvas->flush();
}
// Surface impl
void dispose() override {
@ -55,11 +82,17 @@ public:
}
int width() const override {
return m_bitmap.width();
if (m_surface)
return m_surface->width();
else
return m_bitmap.width();
}
int height() const override {
return m_bitmap.height();
if (m_surface)
return m_surface->height();
else
return m_bitmap.height();
}
bool isDirectToScreen() const override {
@ -91,14 +124,19 @@ public:
}
void applyScale(int scaleFactor) override {
ASSERT(!m_surface);
SkBitmap result;
result.tryAllocPixels(
SkImageInfo::MakeN32Premul(width()*scaleFactor, height()*scaleFactor));
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
SkCanvas canvas(result);
SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(0, 0, m_bitmap.width(), m_bitmap.height()));
SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(0, 0, width(), height()));
SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(0, 0, result.width(), result.height()));
canvas.drawBitmapRectToRect(m_bitmap, &srcRect, dstRect);
canvas.drawBitmapRectToRect(m_bitmap, &srcRect, dstRect, &paint);
swapBitmap(result);
}
@ -110,11 +148,11 @@ public:
// LockedSurface impl
int lockedWidth() const override {
return m_bitmap.width();
return width();
}
int lockedHeight() const override {
return m_bitmap.height();
return height();
}
void unlock() override {
@ -122,6 +160,7 @@ public:
}
void clear() override {
// TODO
}
uint8_t* getData(int x, int y) const override {
@ -188,7 +227,19 @@ public:
}
gfx::Color getPixel(int x, int y) const override {
SkColor c = m_bitmap.getColor(x, y);
SkColor c = 0;
if (m_surface) {
// m_canvas->flush();
SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(1, 1);
uint32_t dstPixels;
if (m_canvas->readPixels(dstInfo, &dstPixels, 4, x, y))
c = dstPixels;
}
else
c = m_bitmap.getColor(x, y);
return gfx::rgba(
SkColorGetR(c),
SkColorGetG(c),
@ -207,7 +258,7 @@ public:
paint.setColor(to_skia(color));
m_canvas->drawLine(
SkIntToScalar(x), SkIntToScalar(y),
SkIntToScalar(x+w-1), SkIntToScalar(y), paint);
SkIntToScalar(x+w), SkIntToScalar(y), paint);
}
void drawVLine(gfx::Color color, int x, int y, int h) override {
@ -215,7 +266,7 @@ public:
paint.setColor(to_skia(color));
m_canvas->drawLine(
SkIntToScalar(x), SkIntToScalar(y),
SkIntToScalar(x), SkIntToScalar(y+h-1), paint);
SkIntToScalar(x), SkIntToScalar(y+h), paint);
}
void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b) override {
@ -237,24 +288,73 @@ public:
SkPaint paint;
paint.setColor(to_skia(color));
paint.setStyle(SkPaint::kFill_Style);
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
m_canvas->drawRect(to_skia(rc), paint);
}
void blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const override {
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
if (m_surface) {
// m_canvas->flush();
SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(srcx, srcy, width, height));
SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(dstx, dsty, width, height));
((SkiaSurface*)dest)->m_canvas->drawBitmapRectToRect(m_bitmap, &srcRect, dstRect, &paint);
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
std::vector<uint32_t> pixels(width * height * 4);
m_canvas->readPixels(info, (void*)&pixels[0], 4*width, srcx, srcy);
((SkiaSurface*)dest)->m_canvas->writePixels(info, (void*)&pixels[0], 4*width, dstx, dsty);
}
else {
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(srcx, srcy, width, height));
SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(dstx, dsty, width, height));
((SkiaSurface*)dest)->m_canvas->drawBitmapRectToRect(m_bitmap, &srcRect, dstRect, &paint);
}
}
void scrollTo(const gfx::Rect& rc, int dx, int dy) override {
int w = width();
int h = height();
gfx::Clip clip(rc.x+dx, rc.y+dy, rc);
if (!clip.clip(w, h, w, h))
return;
if (m_surface) {
blitTo(this, clip.src.x, clip.src.y, clip.dst.x, clip.dst.y, clip.size.w, clip.size.h);
return;
}
int bytesPerPixel = m_bitmap.bytesPerPixel();
int rowBytes = (int)m_bitmap.rowBytes();
int rowDelta;
if (dy > 0) {
clip.src.y += clip.size.h-1;
clip.dst.y += clip.size.h-1;
rowDelta = -rowBytes;
}
else
rowDelta = rowBytes;
char* dst = (char*)m_bitmap.getPixels();
const char* src = dst;
dst += rowBytes*clip.dst.y + bytesPerPixel*clip.dst.x;
src += rowBytes*clip.src.y + bytesPerPixel*clip.src.x;
w = bytesPerPixel*clip.size.w;
h = clip.size.h;
while (--h >= 0) {
memmove(dst, src, w);
dst += rowDelta;
src += rowDelta;
}
}
void drawSurface(const LockedSurface* src, int dstx, int dsty) override {
gfx::Clip clip(dstx, dsty, 0, 0,
((SkiaSurface*)src)->m_bitmap.width(),
((SkiaSurface*)src)->m_bitmap.height());
((SkiaSurface*)src)->width(),
((SkiaSurface*)src)->height());
if (!clip.clip(m_bitmap.width(), m_bitmap.height(), clip.size.w, clip.size.h))
if (!clip.clip(width(), height(), clip.size.w, clip.size.h))
return;
SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(clip.src.x, clip.src.y, clip.size.w, clip.size.h));
@ -269,39 +369,91 @@ public:
void drawRgbaSurface(const LockedSurface* src, int dstx, int dsty) override {
gfx::Clip clip(dstx, dsty, 0, 0,
((SkiaSurface*)src)->m_bitmap.width(),
((SkiaSurface*)src)->m_bitmap.height());
((SkiaSurface*)src)->width(),
((SkiaSurface*)src)->height());
if (!clip.clip(m_bitmap.width(), m_bitmap.height(), clip.size.w, clip.size.h))
if (!clip.clip(width(), height(), clip.size.w, clip.size.h))
return;
SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(clip.src.x, clip.src.y, clip.size.w, clip.size.h));
SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(clip.dst.x, clip.dst.y, clip.size.w, clip.size.h));
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrcATop_Mode);
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
m_canvas->drawBitmapRectToRect(
((SkiaSurface*)src)->m_bitmap, &srcRect, dstRect, &paint);
}
void drawColoredRgbaSurface(const LockedSurface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clipbase) override {
gfx::Clip clip(clipbase);
if (!clip.clip(lockedWidth(), lockedHeight(), src->lockedWidth(), src->lockedHeight()))
return;
SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(clip.src.x, clip.src.y, clip.size.w, clip.size.h));
SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(clip.dst.x, clip.dst.y, clip.size.w, clip.size.h));
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
if (gfx::geta(bg) > 0) {
SkPaint paint;
paint.setColor(to_skia(bg));
paint.setStyle(SkPaint::kFill_Style);
m_canvas->drawRect(dstRect, paint);
}
SkAutoTUnref<SkColorFilter> colorFilter(
SkColorFilter::CreateModeFilter(to_skia(fg), SkXfermode::kSrcIn_Mode));
paint.setColorFilter(colorFilter);
m_canvas->drawBitmapRectToRect(
((SkiaSurface*)src)->m_bitmap,
&srcRect, dstRect, &paint);
}
void drawChar(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, int chr) override {
CommonFont* commonFont = static_cast<CommonFont*>(font);
gfx::Rect charBounds = commonFont->getCharBounds(chr);
if (!charBounds.isEmpty()) {
ScopedSurfaceLock lock(commonFont->getSurfaceSheet());
drawColoredRgbaSurface(lock, fg, bg, gfx::Clip(x, y, charBounds));
}
}
void drawString(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, const std::string& str) override {
base::utf8_const_iterator it(str.begin()), end(str.end());
while (it != end) {
drawChar(font, fg, bg, x, y, *it);
x += font->charWidth(*it);
++it;
}
}
SkBitmap& bitmap() {
return m_bitmap;
}
void swapBitmap(SkBitmap& other) {
ASSERT(!m_surface);
m_bitmap.swap(other);
rebuild();
}
private:
void rebuild() {
m_canvas.reset(new SkCanvas(m_bitmap));
ASSERT(!m_surface);
delete m_canvas;
m_canvas = new SkCanvas(m_bitmap);
m_clip = gfx::Rect(0, 0, width(), height());
}
SkBitmap m_bitmap;
base::UniquePtr<SkCanvas> m_canvas;
SkSurface* m_surface;
SkCanvas* m_canvas;
gfx::Rect m_clip;
};

View File

@ -17,6 +17,12 @@
#include "she/skia/skia_display.h"
#include "she/skia/skia_surface.h"
#ifdef _WIN32
#include "she/win/event_queue.h"
#else
#error There is no EventQueue implementation for your platform
#endif
namespace she {
class SkiaSystem : public CommonSystem {
@ -44,7 +50,7 @@ public:
}
Display* createDisplay(int width, int height, int scale) override {
SkiaDisplay* display = new SkiaDisplay(width, height, scale);
SkiaDisplay* display = new SkiaDisplay(&m_queue, width, height, scale);
if (!m_defaultDisplay)
m_defaultDisplay = display;
return display;
@ -67,8 +73,6 @@ public:
SkAutoTDelete<SkStreamAsset> stream(SkNEW_ARGS(SkFILEStream, (fp.get(), SkFILEStream::kCallerRetains_Ownership)));
SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
// decoder->setRequireUnpremultipliedColors(true);
if (decoder) {
stream->rewind();
SkBitmap bm;
@ -92,6 +96,7 @@ public:
private:
SkiaDisplay* m_defaultDisplay;
EventQueueImpl m_queue;
};
} // namespace she

View File

@ -1,62 +0,0 @@
// 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

@ -1,38 +0,0 @@
// 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.
#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, SkiaDisplay* display);
void queueEventImpl(Event& ev);
void paintImpl(HDC hdc);
void resizeImpl(const gfx::Size& size);
private:
SkiaEventQueue* m_queue;
SkiaDisplay* m_display;
};
} // namespace she
#endif

View File

@ -0,0 +1,213 @@
// 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_win.h"
#include "she/event_queue.h"
#include "she/skia/skia_display.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "she/skia/gl_context_wgl.h"
#endif
namespace she {
SkiaWindow::SkiaWindow(EventQueue* queue, SkiaDisplay* display)
: m_queue(queue)
, m_display(display)
, m_backend(Backend::NONE)
#if SK_SUPPORT_GPU
, m_sampleCount(0)
, m_stencilBits(0)
#endif
{
}
SkiaWindow::~SkiaWindow()
{
switch (m_backend) {
case Backend::NONE:
// Do nothing
break;
#if SK_SUPPORT_GPU
case Backend::GL:
case Backend::ANGLE:
detachGL();
break;
#endif // SK_SUPPORT_GPU
}
}
void SkiaWindow::queueEventImpl(Event& ev)
{
ev.setDisplay(m_display);
m_queue->queueEvent(ev);
}
void SkiaWindow::paintImpl(HDC hdc)
{
switch (m_backend) {
case Backend::NONE:
paintHDC(hdc);
break;
#if SK_SUPPORT_GPU
case Backend::GL:
case Backend::ANGLE:
// Flush operations to the SkCanvas
{
SkiaSurface* surface = static_cast<SkiaSurface*>(m_display->getSurface());
surface->flush();
}
// Flush GL context
m_grInterface->fFunctions.fFlush();
// We don't use double-buffer
//ASSERT(m_glCtx);
//if (m_glCtx)
// m_glCtx->swapBuffers();
break;
#endif // SK_SUPPORT_GPU
}
}
void SkiaWindow::paintHDC(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();
}
#if SK_SUPPORT_GPU
bool SkiaWindow::attachGL()
{
if (!m_glCtx) {
GLContextWGL* wglCtx = SkNEW_ARGS(GLContextWGL, (handle(), kGLES_GrGLStandard));
m_stencilBits = wglCtx->getStencilBits();
m_sampleCount = wglCtx->getSampleCount();
m_glCtx.reset(wglCtx);
ASSERT(m_glCtx->isValid());
if (!m_glCtx->isValid()) {
detachGL();
return false;
}
m_grInterface.reset(SkRef(m_glCtx->gl()));
m_grInterface.reset(GrGLInterfaceRemoveNVPR(m_grInterface));
m_grCtx.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)m_grInterface.get()));
}
if (m_glCtx) {
m_glCtx->makeCurrent();
return true;
}
else
return false;
}
#if SK_ANGLE
bool SkiaWindow::attachANGLE()
{
return false; // TODO
}
#endif // SK_ANGLE
void SkiaWindow::detachGL()
{
m_grCtx.reset(nullptr);
m_grInterface.reset(nullptr);
m_glCtx.reset(nullptr);
}
void SkiaWindow::createRenderTarget(const gfx::Size& size)
{
GrBackendRenderTargetDesc desc;
desc.fWidth = size.w / m_display->scale();
desc.fHeight = size.h / m_display->scale();
desc.fConfig = kSkia8888_GrPixelConfig;
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
desc.fSampleCnt = m_sampleCount;
desc.fStencilBits = m_stencilBits;
GrGLint buffer;
m_grInterface->fFunctions.fGetIntegerv(0x8CA6, &buffer); // GL_FRAMEBUFFER_BINDING = 0x8CA6
desc.fRenderTargetHandle = buffer;
m_grRenderTarget.reset(m_grCtx->textureProvider()->wrapBackendRenderTarget(desc));
m_skSurface.reset(SkSurface::NewRenderTargetDirect(m_grRenderTarget));
m_display->setSkiaSurface(new SkiaSurface(m_skSurface));
}
#endif // SK_SUPPORT_GPU
void SkiaWindow::resizeImpl(const gfx::Size& size)
{
#if SK_SUPPORT_GPU
#if SK_ANGLE
if (attachANGLE()) {
m_backend = Backend::ANGLE;
}
else
#endif // SK_ANGLE
if (attachGL()) {
m_backend = Backend::GL;
}
else
#endif // SK_SUPPORT_GPU
{
#if SK_SUPPORT_GPU
detachGL();
#endif
m_backend = Backend::NONE;
}
if (m_glCtx)
createRenderTarget(size);
m_display->resize(size);
}
} // namespace she

View File

@ -0,0 +1,65 @@
// 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.
#ifndef SHE_SKIA_SKIA_WINDOW_WIN_INCLUDED
#define SHE_SKIA_SKIA_WINDOW_WIN_INCLUDED
#pragma once
#include "base/disable_copying.h"
#include "she/skia/skia_surface.h"
#include "she/win/window.h"
#if SK_SUPPORT_GPU
#include "gl/SkGLContext.h"
#endif
namespace she {
class EventQueue;
class SkiaDisplay;
class SkiaWindow : public Window<SkiaWindow> {
public:
enum class Backend { NONE, GL, ANGLE };
SkiaWindow(EventQueue* queue, SkiaDisplay* display);
~SkiaWindow();
void queueEventImpl(Event& ev);
void paintImpl(HDC hdc);
void resizeImpl(const gfx::Size& size);
private:
void paintHDC(HDC dc);
#if SK_SUPPORT_GPU
bool attachGL();
#if SK_ANGLE
bool attachANGLE();
#endif // SK_ANGLE
void detachGL();
void createRenderTarget(const gfx::Size& size);
#endif // SK_SUPPORT_GPU
EventQueue* m_queue;
SkiaDisplay* m_display;
Backend m_backend;
#if SK_SUPPORT_GPU
SkAutoTUnref<SkGLContext> m_glCtx;
SkAutoTUnref<const GrGLInterface> m_grInterface;
SkAutoTUnref<GrContext> m_grCtx;
SkAutoTUnref<GrRenderTarget> m_grRenderTarget;
SkAutoTDelete<SkSurface> m_skSurface;
int m_sampleCount;
int m_stencilBits;
#endif // SK_SUPPORT_GPU
DISABLE_COPYING(SkiaWindow);
};
} // namespace she
#endif

View File

@ -4,8 +4,8 @@
// 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
#ifndef SHE_WIN_EVENT_QUEUE_INCLUDED
#define SHE_WIN_EVENT_QUEUE_INCLUDED
#pragma once
#include <queue>
@ -17,18 +17,16 @@
namespace she {
class SkiaEventQueue : public EventQueue {
class EventQueueImpl : public EventQueue {
public:
SkiaEventQueue() : m_stop(false) {
}
void getEvent(Event& ev, bool canWait) override {
MSG msg;
while (!m_stop && m_events.empty()) {
while (m_events.empty()) {
BOOL res;
if (canWait) {
ASSERT(false); // Not yet supported
res = GetMessage(&msg, nullptr, 0, 0);
}
else {
@ -52,16 +50,12 @@ public:
}
}
void queueEvent(Event& ev) {
if (ev.type() == Event::CloseDisplay)
m_stop = true;
void queueEvent(const Event& ev) override {
m_events.push(ev);
}
private:
std::queue<Event> m_events;
bool m_stop;
};
} // namespace she

View File

@ -11,10 +11,12 @@
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <shellapi.h>
#include "gfx/size.h"
#include "she/event.h"
#include "she/keys.h"
#include "she/native_cursor.h"
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
@ -32,6 +34,7 @@ namespace she {
Window() {
registerClass();
m_hwnd = createHwnd(this);
m_hcursor = NULL;
m_hasMouse = false;
m_captureMouse = false;
m_scale = 1;
@ -87,8 +90,68 @@ namespace she {
m_captureMouse = false;
}
void invalidate() {
void setMousePosition(const gfx::Point& position) {
POINT pos = { position.x * m_scale,
position.y * m_scale };
ClientToScreen(m_hwnd, &pos);
SetCursorPos(pos.x, pos.y);
}
void setNativeMouseCursor(NativeCursor cursor) {
HCURSOR hcursor = NULL;
switch (cursor) {
case kNoCursor:
// Do nothing, just set to null
break;
case kArrowCursor:
hcursor = LoadCursor(NULL, IDC_ARROW);
break;
case kIBeamCursor:
hcursor = LoadCursor(NULL, IDC_IBEAM);
break;
case kWaitCursor:
hcursor = LoadCursor(NULL, IDC_WAIT);
break;
case kLinkCursor:
hcursor = LoadCursor(NULL, IDC_HAND);
break;
case kHelpCursor:
hcursor = LoadCursor(NULL, IDC_HELP);
break;
case kForbiddenCursor:
hcursor = LoadCursor(NULL, IDC_NO);
break;
case kMoveCursor:
hcursor = LoadCursor(NULL, IDC_SIZEALL);
break;
case kSizeNCursor:
case kSizeNSCursor:
case kSizeSCursor:
hcursor = LoadCursor(NULL, IDC_SIZENS);
break;
case kSizeECursor:
case kSizeWCursor:
case kSizeWECursor:
hcursor = LoadCursor(NULL, IDC_SIZEWE);
break;
case kSizeNWCursor:
case kSizeSECursor:
hcursor = LoadCursor(NULL, IDC_SIZENWSE);
break;
case kSizeNECursor:
case kSizeSWCursor:
hcursor = LoadCursor(NULL, IDC_SIZENESW);
break;
}
SetCursor(hcursor);
m_hcursor = hcursor;
}
void updateWindow() {
InvalidateRect(m_hwnd, NULL, FALSE);
UpdateWindow(m_hwnd);
}
HWND handle() {
@ -99,6 +162,13 @@ namespace she {
LRESULT wndProc(UINT msg, WPARAM wparam, LPARAM lparam) {
switch (msg) {
case WM_SETCURSOR:
if (LOWORD(lparam) == HTCLIENT) {
SetCursor(m_hcursor);
return TRUE;
}
break;
case WM_CLOSE: {
Event ev;
ev.setType(Event::CloseDisplay);
@ -236,15 +306,13 @@ namespace she {
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL: {
RECT rc;
::GetWindowRect(m_hwnd, &rc);
POINT pos = { GET_X_LPARAM(lparam),
GET_Y_LPARAM(lparam) };
ScreenToClient(m_hwnd, &pos);
Event ev;
ev.setType(Event::MouseWheel);
ev.setPosition((gfx::Point(
GET_X_LPARAM(lparam),
GET_Y_LPARAM(lparam)) - gfx::Point(rc.left, rc.top))
/ m_scale);
ev.setPosition(gfx::Point(pos.x, pos.y) / m_scale);
int z = ((short)HIWORD(wparam)) / WHEEL_DELTA;
gfx::Point delta(
@ -260,16 +328,13 @@ namespace she {
case WM_HSCROLL:
case WM_VSCROLL: {
RECT rc;
::GetWindowRect(m_hwnd, &rc);
POINT pos;
::GetCursorPos(&pos);
GetCursorPos(&pos);
ScreenToClient(m_hwnd, &pos);
Event ev;
ev.setType(Event::MouseWheel);
ev.setPosition((gfx::Point(pos.x, pos.y) - gfx::Point(rc.left, rc.top))
/ m_scale);
ev.setPosition(gfx::Point(pos.x, pos.y) / m_scale);
int bar = (msg == WM_HSCROLL ? SB_HORZ: SB_VERT);
int z = GetScrollPos(m_hwnd, bar);
@ -309,6 +374,7 @@ namespace she {
break;
}
case WM_SYSKEYDOWN:
case WM_KEYDOWN: {
int vk = wparam;
int scancode = (lparam >> 16) & 0xff;
@ -392,13 +458,13 @@ namespace she {
return; // Already registered
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = &Window::staticWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = instance;
wcex.hIcon = nullptr;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hCursor = NULL;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = nullptr;
wcex.lpszClassName = SHE_WND_CLASS_NAME;
@ -442,6 +508,7 @@ namespace she {
}
mutable HWND m_hwnd;
HCURSOR m_hcursor;
gfx::Size m_clientSize;
gfx::Size m_restoredSize;
int m_scale;

View File

@ -22,12 +22,8 @@ namespace ui {
using namespace gfx;
void move_region(const Region& region, int dx, int dy)
void move_region(Manager* manager, const Region& region, int dx, int dy)
{
ASSERT(Manager::getDefault());
if (!Manager::getDefault())
return;
she::System* system = she::instance();
she::Display* display = Manager::getDefault()->getDisplay();
ASSERT(display);
@ -40,7 +36,7 @@ void move_region(const Region& region, int dx, int dy)
// Blit directly screen to screen.
if (nrects == 1) {
Rect rc = region[0];
lock->blitTo(lock, rc.x, rc.y, rc.x+dx, rc.y+dy, rc.w, rc.h);
lock->scrollTo(rc, dx, dy);
}
// Blit saving areas and copy them.
else if (nrects > 1) {

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2014 David Capello
// Copyright (C) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -10,9 +10,11 @@
#include "gfx/region.h"
namespace ui { // TODO all these functions are deprecated and must be replaced by Graphics methods.
namespace ui {
void move_region(const gfx::Region& region, int dx, int dy);
class Manager;
void move_region(Manager* manager, const gfx::Region& region, int dx, int dy);
} // namespace ui

View File

@ -1068,7 +1068,7 @@ void Widget::scrollRegion(const Region& region, const Point& delta)
reg2.offset(-delta);
// Move screen pixels
ui::move_region(reg2, delta.x, delta.y);
ui::move_region(getManager(), reg2, delta.x, delta.y);
reg2.offset(delta);

View File

@ -577,7 +577,7 @@ void Window::moveWindow(const gfx::Rect& rect, bool use_blit)
{
IntersectClip clip(&g, man_pos);
if (clip) {
ui::move_region(moveableRegion, dx, dy);
ui::move_region(manager, moveableRegion, dx, dy);
}
}
show_mouse_cursor();